pax_global_header00006660000000000000000000000064115317720130014512gustar00rootroot0000000000000052 comment=7392a50f1b49e5eb0623dc19f222c1b556596070 voxbo-1.8.5~svn1246/000077500000000000000000000000001153177201300141245ustar00rootroot00000000000000voxbo-1.8.5~svn1246/.gitattributes000066400000000000000000000000261153177201300170150ustar00rootroot00000000000000/debian export-ignore voxbo-1.8.5~svn1246/.gitignore000066400000000000000000000000041153177201300161060ustar00rootroot00000000000000.pc voxbo-1.8.5~svn1246/COPYING000077500000000000000000001045141153177201300151670ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . voxbo-1.8.5~svn1246/INSTALL000066400000000000000000000004401153177201300151530ustar00rootroot00000000000000 You could try just: make make install If you have slightly more complicated needs, preface that with: ./configure.py and then run it again with whatever arguments you need. For more detailed build notes and other documentation, visit the web site at: http://www.voxbo.org/ voxbo-1.8.5~svn1246/Makefile000066400000000000000000000027611153177201300155720ustar00rootroot00000000000000 # This is the master makefile for VoxBo and the database project -include make_vars.txt include make_stuff.txt # Here are our targets COMMANDLINEDIRS=fileformats munge stats crunch stand_alone utils resample gdscript\ scheduler scripts ifeq ($(VB_TARGET),spm) GUIDIRS= qtglm vbview DBDIRS= else ifeq ($(VB_TARGET),db) COMMANDLINEDIRS= GUIDIRS= DBDIRS=client server dbutil else GUIDIRS=qtglm vbview vbsequence qtvlsm DBDIRS=client server dbutil endif VOXBODIRS = $(COMMANDLINEDIRS) $(GUIDIRS) INSTALLDIRS = $(COMMANDLINEDIRS) $(GUIDIRS) MAKEDIRS = $(VOXBODIRS) $(DBDIRS) CLEANDIRS = lib vbwidgets $(MAKEDIRS) OUT=getput qa brainBrowser db_import # PHONY declaration makes life easier .PHONY: clean install lib vbwidgets subdirs db nogui voxbo showconfig $(VOXBODIRS) $(DBDIRS) subdirs: lib $(VOXBODIRS) $(DBDIRS) nogui: $(COMMANDLINEDIRS) db: $(DBDIRS) voxbo: $(VOXBODIRS) # all targets $(MAKEDIRS): lib +make -C $@ # extra dependencies for specific targets qtglm: lib vbwidgets utils vbview: lib vbwidgets client: lib vbwidgets vbview vbsequence: lib vbwidgets lib: +make -C $@ vbwidgets: +make -C $@ install: mkdir -p $(VB_BINDIR) +for dir in $(INSTALLDIRS) ; do make -C $$dir install ; done distclean: clean rm -f make_vars.txt showconfig: @echo "VB_PREFIX="$(VB_PREFIX) @echo "VB_BINDIR="$(VB_BINDIR) @echo "VB_LIBDIR="$(VB_LIBDIR) @echo "VB_FFDIR="$(VB_FFDIR) @echo "VB_TARGET="$(VB_TARGET) clean: +for dir in $(CLEANDIRS) ; do make -C $$dir clean ; done voxbo-1.8.5~svn1246/README000077500000000000000000000010051153177201300150030ustar00rootroot00000000000000 Welcome to the VoxBo source distribiton. For documentation, binaries, or other VoxBo-related information, visit the web site at: http://voxbo.org/ For information on building and installing VoxBo from source, see the file "INSTALL" in this directory. For information on the licensing of this software, see the file "COPYING". All other documentation has been moved to the web site. Support is provided via the VoxBo mailing lists, see this page for details: http://voxbo.org/mailman/listinfo/voxbo-general voxbo-1.8.5~svn1246/brainBrowser/000077500000000000000000000000001153177201300165635ustar00rootroot00000000000000voxbo-1.8.5~svn1246/brainBrowser/Makefile000066400000000000000000000021451153177201300202250ustar00rootroot00000000000000 # makefile for brainbrowser -include ../make_vars.txt include ../make_stuff.txt VBLIBS=$(VBLIBS2) CXXFLAGS += -DQT3_SUPPORT $(QTLIBDIRS) $(QTINCDIRS) OBJECTS=br_util.o main.o myDB.o HEADERS=br_util.h main.h myDB.h region.h region_relation.h searchBrain.h synonym.h LIBS =$(LDFLAGS) $(LIBDIRS) $(QTLIBDIRS) $(QTLIBS) -lvbprefs -lvbglm -lvbio -lvbutil -lz $(DLLIB) -lgsl -lgslcblas ALLBINS=brainBrowser BINS=brainBrowser ifdef VB_NOX BINS= endif all: $(BINS) install: ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) # executables brainBrowser: main.moc.h $(OBJECTS) $(CXX) -o brainBrowser $(OBJECTS) $(LIBS) main.moc.h : $(HEADERS) $(MOC) main.h -o main.moc.h br_util.o: $(HEADERS) br_util.cpp $(CXX) -c $(CXXFLAGS) -o br_util.o br_util.cpp myDB.o: $(HEADERS) myDB.cpp $(CXX) -c $(CXXFLAGS) -o myDB.o myDB.cpp searchBrain: searchBrain.o myDB.o br_util.o $(CXX) --whole-archive -o searchBrain searchBrain.o myDB.o br_util.o -ldb_cxx searchBrain.o: searchBrain.cpp searchBrain.h $(CXX) -c -Wall -W -O3 -o searchBrain.o searchBrain.cpp voxbo-1.8.5~svn1246/brainBrowser/bbdialog.cpp000066400000000000000000000045371153177201300210430ustar00rootroot00000000000000 // bbdialog.cpp // dialogs for structure browser // Copyright (c) 2010 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg, based on a design by // Dongbo Hu. #include "bbdialog.moc.h" BBdialog::BBdialog(QWidget *parent) : QDialog(parent) { // main layout QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); this->setLayout(layout); // form layout QFormLayout *myform=new QFormLayout(); layout->addLayout(myform); // stuff in form layout w_name=new QLineEdit(); w_namespace=new QComboBox(); w_parent=new QListWidget(); w_child=new QListWidget(); w_synonyms=new QListWidget(); w_source=new QLineEdit(); w_link=new QLineEdit(); w_relationship=new QListWidget(); myform->addRow("Region Name:",w_name); myform->addRow("Located in:",w_namespace); myform->addRow("Parent Structure:",w_parent); myform->addRow("Child Structure(s):",w_child); myform->addRow("Synonyms:",w_synonyms); myform->addRow("Source:",w_source); myform->addRow("Link:",w_link); myform->addRow("Relationship:",w_relationship); hb=new QHBox(); layout->addWidget(hb); button=new QPushButton("Reset"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Close"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); // setMinimumSize(320,1); setWindowTitle("VoxBo Brain Structure Name Browser"); } voxbo-1.8.5~svn1246/brainBrowser/bbdialog.h000066400000000000000000000027521153177201300205050ustar00rootroot00000000000000 // bbdialog.h // dialogs for structure browser // Copyright (c) 2010 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg, based on a design by // Dongbo Hu. #include #include #include #include "bbdialogs.moc.h" #include "myboxes.h" using namespace std; class BBdialog : public QDialog { Q_OBJECT public: BBdialog(QWidget *parent); public slots: private: QLineEdit *w_name; QComboBox *w_namespace; QListWidget *w_parent; QListWidget *w_child; QListWidget *w_synonyms; QLineEdit *w_source; QLineEdit *w_link; QListWidget *w_relationship; signals: }; voxbo-1.8.5~svn1246/brainBrowser/br_util.cpp000066400000000000000000000727161153177201300207440ustar00rootroot00000000000000 // br_util.cpp // Copyright (c) 2010 by Daniel Y. Kimberg // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* This file includes some generic functions to read/write records * in the following three brain region database tables: * region_name.db * synonym.db * region_relation.db */ using namespace std; #include "br_util.h" /* This function checks whether a certain name exists in a certain namespace * of region name db. * Returns -1 or -2 for exceptions; * returns 0 if it does not exist; * returns 1 if it does exist; */ int chkRegionName(string dbHome, string rDbName, string rName, string name_space) { mydb rDB(dbHome, rDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { rDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); if (rData.getName() == rName && rData.getNameSpace() == name_space) { foo = 1; break; } } } catch(DbException &e) { rDB.getDb().err(e.get_errno(), "Error in chkRegionName()"); foo = -1; } catch(exception &e) { rDB.getDb().errx("Error in chkRegionName(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function checks whether a certain synonym string exists in a certain namespace * of synonym db. * Returns -1 or -2 for exceptions; * returns 0 if it does not exist; * returns 1 if it does exist; */ int chkSynonymStr(string dbHome, string sDbName, string sName, string name_space) { mydb sDB(dbHome, sDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { sDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { synonymRec sData(data.get_data()); if (sData.getName() == sName && sData.getNameSpace() == name_space) { foo = 1; break; } } } catch(DbException &e) { sDB.getDb().err(e.get_errno(), "Error in chkSynonymStr()"); foo = -1; } catch(exception &e) { sDB.getDb().errx("Error in chkSynonymStr(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function assigns all region names and namespaces from region_name.db * to the last two arguments. * Returns 0 if database read process is correct. * Returns negative values if db read exception shows up. */ int getAllRegions(string dbHome, string rName, vector &nameList, vector &spaceList) { mydb regionDB(dbHome, rName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); nameList.push_back(rData.getName()); spaceList.push_back(rData.getNameSpace()); } } catch(DbException &e) { regionDB.getDb().err(e.get_errno(), "Error in getAllRegions()"); foo = -1; } catch(exception &e) { regionDB.getDb().errx("Error in getAllRegions(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function assigns all region names in a certain namespace in region_name.db * to the last argument. * Returns 0 if database read process is correct. * Returns -1 or -2 for db exceptions. */ int getRegions(string dbHome, string rName, string name_space_in, vector &nameList) { mydb regionDB(dbHome, rName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); if (rData.getNameSpace() == name_space_in) nameList.push_back(rData.getName()); } } catch(DbException &e) { regionDB.getDb().err(e.get_errno(), "Error in getRegions()"); foo = -1; } catch(exception &e) { regionDB.getDb().errx("Error in getRegions(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function assigns all synonyms and namespaces in synonym.db to * the last two arguments. * Returns 0 if database read process is correct. * Returns negative values if db read exception shows up. */ int getAllSynonyms(string dbHome, string sName, vector &nameList, vector &spaceList) { mydb synonymDB(dbHome, sName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { synonymDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { synonymRec sData(data.get_data()); nameList.push_back(sData.getName()); spaceList.push_back(sData.getNameSpace()); } } catch(DbException &e) { synonymDB.getDb().err(e.get_errno(), "Error in getAllSynonyms()"); foo = -1; } catch(exception &e) { synonymDB.getDb().errx("Error in getAllSynonyms(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function assigns all synonyms and namespaces in synonym.db to * the last two arguments. * Returns 0 if database read process is correct. * Returns negative values if db read exception shows up. */ int getSynonyms(string dbHome, string sName, string name_space_in, vector &nameList) { mydb synonymDB(dbHome, sName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { synonymDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { synonymRec sData(data.get_data()); if (name_space_in == sData.getNameSpace()) nameList.push_back(sData.getName()); } } catch(DbException &e) { synonymDB.getDb().err(e.get_errno(), "Error in getSynonyms()"); foo = -1; } catch(exception &e) { synonymDB.getDb().errx("Error in getSynonyms(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects a certain region's details from region_name.db * and put in regionRec object. * Returns -1 or -2 if db read exception is met. * Returns 0 if input region name is not found; * Returns 1 if input region is found. */ int getRegionRec(string dbHome, string rDbName, string inputName, string name_space, regionRec &outputRec) { mydb regionDB(dbHome, rDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int stat = 0; try { regionDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); if (rData.getName() == inputName && rData.getNameSpace() == name_space) { outputRec.setData(data.get_data()); stat = 1; break; } } } catch(DbException &e) { regionDB.getDb().err(e.get_errno(), "Error in getRegionRec()"); stat = -1; } catch(exception &e) { regionDB.getDb().errx("Error in getRegionRec(): %s", e.what()); stat = -2; } cursorp->close(); return stat; } /* This function searches region name db according to relation ID * and put the region name and namespace strings into the last twqo arguments. * at the end of region name in parenthesis. BY default it is false. * Returns -1 or -2 for exceptions; * returns 0 if record is not found; * returns -3 for any other errors; * returns 1 if record is found and variables are assisgned successfully. */ int getRegionName(string dbHome, string rDbName, long rID_in, string & rName_out, string & space_out) { mydb rDB(dbHome, rDbName, DB_RDONLY); Dbc *cursorp; Dbt key(&rID_in, sizeof(rID_in)); Dbt data; long foo = -3; try { rDB.getDb().cursor(NULL, &cursorp, 0); int ret = cursorp->get(&key, &data, DB_SET); if (!ret) { regionRec rData(data.get_data()); rName_out = rData.getName(); space_out = rData.getNameSpace(); foo = 1; } else if (ret == DB_NOTFOUND) foo = 0; } catch(DbException &e) { rDB.getDb().err(e.get_errno(), "Error in getRegionName()"); foo = -1; } catch(exception &e) { rDB.getDb().errx("Error in getRegionName(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function searches region name db according to relation name and namespace * and returns the region ID. * Returns -1 or -2 for exceptions; * returns 0 if it is not found; */ long getRegionID(string dbHome, string rDbName, string rName, string name_space) { mydb rDB(dbHome, rDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; long foo = 0; try { rDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); if (rData.getName() == rName && rData.getNameSpace() == name_space) { foo = rData.getID(); break; } } } catch(DbException &e) { rDB.getDb().err(e.get_errno(), "Error in getRegionID()"); foo = -1; } catch(exception &e) { rDB.getDb().errx("Error in getRegionID(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* Seach a synonym name in synonym db file and put primary structure name in pName. * Returns -1 or -2 if exceptions are met; * returns 0 if parent name is not found; * returns 1 if parent name is found. */ int getPrimary(string dbHome, string sDbName, string sName_in, string name_space_in, string &pName) { mydb symDB(dbHome, sDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int stat = 0; int ret; try { symDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { synonymRec sData(data.get_data()); if (sData.getName() == sName_in && sData.getNameSpace() == name_space_in) { pName = sData.getPrimary(); stat = 1; break; } } } catch(DbException &e) { symDB.getDb().err(e.get_errno(), "Error in getPname()"); stat = -1; } catch(exception &e) { symDB.getDb().errx("Error in getPname(): %s", e.what()); stat = -2; } cursorp->close(); return stat; } /* This function collects parent and child region ID information and put in pID and cList. * Returns -1 or -2 if exception is met; * returns 0 if db file is read without error. */ int getParentChild(string dbHome, string rrDbName, long rID_in, long * pID, vector &cList) { mydb regionRelationDB(dbHome, rrDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionRelationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { regionRelationRec rrData(data.get_data()); if (rrData.getRegion1() == rID_in && rrData.getRelationship() == "child") { if (*pID) printf("Multiple parent regions found for %ld: %ld and %ld\n", rID_in, *pID, rrData.getRegion2()); else *pID = rrData.getRegion2(); } else if (rrData.getRegion2() == rID_in && rrData.getRelationship() == "child") { long cID = rrData.getRegion1(); cList.push_back(cID); } } } catch(DbException &e) { regionRelationDB.getDb().err(e.get_errno(), "Error in getParentChild()"); foo = -1; } catch(exception &e) { regionRelationDB.getDb().errx("Error in getParentChild(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects parent region name information and put in pID. * Returns -1 or -2 if exception is met; * returns 0 if db file is read successfully. */ int getParent(string dbHome, string rrDbName, long rID_in, long * pID) { mydb regionRelationDB(dbHome, rrDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionRelationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { regionRelationRec rrData(data.get_data()); if (rrData.getRegion1() == rID_in && rrData.getRelationship() == "child") { *pID = rrData.getRegion2(); break; } } } catch(DbException &e) { regionRelationDB.getDb().err(e.get_errno(), "Error in getParent()"); foo = -1; } catch(exception &e) { regionRelationDB.getDb().errx("Error in getParent(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects child region ID information and put in cList array. * Returns -1 or -2 if exception is met; * returns 0 if db file is read without error. */ int getChild(string dbHome, string rrDbName, long rID_in, vector &cList) { mydb regionRelationDB(dbHome, rrDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionRelationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { regionRelationRec rrData(data.get_data()); // skip the region that is same as its parent ("BRAIN") if (rrData.getRegion2() == rID_in && rrData.getRegion1() != rID_in && rrData.getRelationship() == "child") { long cID = rrData.getRegion1(); cList.push_back(cID); } } } catch(DbException &e) { regionRelationDB.getDb().err(e.get_errno(), "Error in getChild()"); foo = -1; } catch(exception &e) { regionRelationDB.getDb().errx("Error in getChild(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects a input region's synonyms and put in a string list argument. * Returns -1 or -2 if exceptions are met; * returns 0 if db file is read in w/0 error. */ int getSynonym(string dbHome, string sDbName, string rName_in, string name_space_in, vector &sList) { mydb synonymDB(dbHome, sDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { synonymDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { synonymRec sData(data.get_data()); if (sData.getPrimary() == rName_in && sData.getNameSpace() == name_space_in) sList.push_back(sData.getName()); } } catch(DbException &e) { synonymDB.getDb().err(e.get_errno(), "Error in getSynonym()"); foo = -1; } catch(exception &e) { synonymDB.getDb().errx("Error in getSynonym(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function searches relationship table according to the input r1 ID, r2 ID * and relationship string. * returns -1 or -2 for exceptions; * returns 0 if record is not found; * returns the relationship ID otherwise. */ long getRelationID(string dbHome, string rrDbName, long r1, long r2, string relStr) { mydb relationDB(dbHome, rrDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; long foo = 0; try { relationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRelationRec rrData(data.get_data()); if ((r1 == rrData.getRegion1() && r2 == rrData.getRegion2() && relStr == rrData.getRelationship()) || (relStr == "overlap" && r1 == rrData.getRegion2() && r2 == rrData.getRegion1() && relStr == rrData.getRelationship())) foo = rrData.getID(); } } catch(DbException &e) { relationDB.getDb().err(e.get_errno(), "Error in getRelation_ui()"); foo = -1; } catch(exception &e) { relationDB.getDb().errx("Error in getRelation_ui(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects all non-parent/child relationship records that involves rName_in. * It is written to show relationships on "search region" interface, so parent/child are ignored. * Return -1 or -2 when exceptions are met; * Return 0 if reading w/o error. */ int getRel_ui(string dbHome, string rrDbName, long rID_in, vector &r2List, vector &relList) { mydb relationDB(dbHome, rrDbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { relationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRelationRec rrData(data.get_data()); long r1 = rrData.getRegion1(); long r2 = rrData.getRegion2(); string tmpRel = rrData.getRelationship(); if (r1 == rID_in && tmpRel != "child") { r2List.push_back(r2); relList.push_back(trRel_db2ui(tmpRel, true)); } else if(r2 == rID_in && tmpRel != "child") { r2List.push_back(r1); relList.push_back(trRel_db2ui(tmpRel, false)); } } } catch(DbException &e) { relationDB.getDb().err(e.get_errno(), "Error in getRelation_ui()"); foo = -1; } catch(exception &e) { relationDB.getDb().errx("Error in getRelation_ui(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects relationship records that are * not parent/child between r1 and r2 in relationship db. * Return -1 or -2 when exceptions are met; * Return 0 if everything is ok. */ int getRel_noChild(string dbHome, string rrDbName, long excludeID, long r1, long r2, vector &relList) { mydb relationDB(dbHome, rrDbName, DB_RDONLY); string relStr; Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { relationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { regionRelationRec rrData(data.get_data()); if (rrData.getID() == excludeID || rrData.getRelationship() == "child") continue; if (rrData.getRegion1() == r1 && rrData.getRegion2() == r2) { relStr = trRel_db2ui(rrData.getRelationship(), true); relList.push_back(relStr); } else if (rrData.getRegion1() == r2 && rrData.getRegion2() == r1) { relStr = trRel_db2ui(rrData.getRelationship(), false); relList.push_back(relStr); } } } catch(DbException &e) { relationDB.getDb().err(e.get_errno(), "Error in getRelation_all()"); foo = -1; } catch(exception &e) { relationDB.getDb().errx("Error in getRelation_all(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects relationship records that are not * "child" or "part-of" between r1 and r2 in relationship db. * Return -1 or -2 when exceptions are met; * Return 0 if everything is ok. */ int getRel_noChildPart(string dbHome, string rrDbName, long r1, long r2, vector &relList) { mydb relationDB(dbHome, rrDbName, DB_RDONLY); string relStr; Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { relationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { regionRelationRec rrData(data.get_data()); if (rrData.getRelationship() == "child" || rrData.getRelationship() == "part-of") continue; if (rrData.getRegion1() == r1 && rrData.getRegion2() == r2) { relStr = trRel_db2ui(rrData.getRelationship(), true); relList.push_back(relStr); } else if (rrData.getRegion1() == r2 && rrData.getRegion2() == r1) { relStr = trRel_db2ui(rrData.getRelationship(), false); relList.push_back(relStr); } } } catch(DbException &e) { relationDB.getDb().err(e.get_errno(), "Error in getRelation_all()"); foo = -1; } catch(exception &e) { relationDB.getDb().errx("Error in getRelation_all(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function collects all relationship records between rName1 and rName2 * in relationship db. Note the difference between this function and previous one. * Return -1 or -2 when exceptions are met; * Return 0 if reading w/o error. */ int getRel_all(string dbHome, string rrDbName, long r1, long r2, vector &relList) { mydb relationDB(dbHome, rrDbName, DB_RDONLY); string relStr; Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { relationDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRelationRec rrData(data.get_data()); if (rrData.getRegion1() == r1 && rrData.getRegion2() == r2) { relStr = trRel_db2ui(rrData.getRelationship(), true); relList.push_back(relStr); } else if (rrData.getRegion1() == r2 && rrData.getRegion2() == r1) { relStr = trRel_db2ui(rrData.getRelationship(), false); relList.push_back(relStr); } } } catch(DbException &e) { relationDB.getDb().err(e.get_errno(), "Error in getRelation_all()"); foo = -1; } catch(exception &e) { relationDB.getDb().errx("Error in getRelation_all(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function "translates" the relationship string in DB file * to description string that will be shown on QT interface. * The inputFlag specifies whether the relationship should be keep * in orginal order or reversed (i.e. "child" to "parent", "part of" to "include". */ string trRel_db2ui(string inputStr, bool keepOrder) { string newRel; if (inputStr == "child") { if (keepOrder) newRel = "is child of"; else newRel = "is parent of"; } else if (inputStr == "part-of") { if (keepOrder) newRel = "is part of"; else newRel = "includes"; } else if (inputStr == "overlap") newRel = "overlaps with"; else if (inputStr == "equiv") newRel = "is equiv to"; return newRel; } /* This function is written specially for command line search. * It searches the region name db using an input string. * If the region name contains that string, the region name and its namespace * will be put into the string vector. * Returns 0 if everything is ok, non-zero otherwise. */ int findRegionNames(string dbHome, string dbName, string key_in, bool ik_flag, vector &outputList) { string keyStr = key_in; if (ik_flag) keyStr = toLowerCase(key_in); mydb regionDB(dbHome, dbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); string rName = rData.getName(); if (ik_flag) rName = toLowerCase(rData.getName()); string rNS = rData.getNameSpace(); if (rName.find(keyStr) != string::npos) outputList.push_back(rData); } } catch(DbException &e) { regionDB.getDb().err(e.get_errno(), "Error in findRegionNames()"); foo = -1; } catch(exception &e) { regionDB.getDb().errx("Error in findRegionNames(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function is written specially for command line search. * It searches the region name db using keyStr and nsStr. * If the region name contains keyStr and nsStr EQUALS nsStr, * the region name will be put into the string vector. * Returns 0 if everything is ok, non-zero otherwise. */ int findRegionNames(string dbHome, string dbName, string key_in, bool ik_flag, string ns_in, bool ins_flag, vector &outputList) { string keyStr = key_in; if (ik_flag) keyStr = toLowerCase(key_in); string nsStr = ns_in; if (ins_flag) keyStr = toLowerCase(ns_in); mydb regionDB(dbHome, dbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); string rName = rData.getName(); if (ik_flag) rName = toLowerCase(rData.getName()); string nsName = rData.getNameSpace(); if (ins_flag) nsName = toLowerCase(rData.getNameSpace()); if (rName.find(keyStr) != string::npos && nsStr == nsName) outputList.push_back(rData); } } catch(DbException &e) { regionDB.getDb().err(e.get_errno(), "Error in findRegionNames()"); foo = -1; } catch(exception &e) { regionDB.getDb().errx("Error in findRegionNames(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function is written specially for command line search. * It searches the region names that belong to a certain namespace. * If the region name contains that string, the region name and its namespace * will be put into the string vector. * Returns 0 if everything is ok, non-zero otherwise. */ int findRegionNS(string dbHome, string dbName, string ns_in, bool ins_flag, vector &outputList) { string nsStr = ns_in; if (ins_flag) nsStr = toLowerCase(ns_in); mydb regionDB(dbHome, dbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { regionDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); string nsName = rData.getNameSpace(); if (ins_flag) nsName = toLowerCase(rData.getNameSpace()); if (nsName == nsStr) outputList.push_back(rData); } } catch(DbException &e) { regionDB.getDb().err(e.get_errno(), "Error in findRegionNames()"); foo = -1; } catch(exception &e) { regionDB.getDb().errx("Error in findRegionNames(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function is written specially for command line search. * It searches the synonym db using an input string. * If the synonym contains that string, the synonym, region name * and its namespace will be put into the string vector. * Returns 0 if everything is ok, non-zero otherwise. */ int findSynonyms(string dbHome, string dbName, string key_in, bool ik_flag, vector &outputList) { string keyStr = key_in; if (ik_flag) keyStr = toLowerCase(key_in); mydb synonymDB(dbHome, dbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { synonymDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { synonymRec sData(data.get_data()); string sName = sData.getName(); if (ik_flag) sName = toLowerCase(sData.getName()); if (sName.find(keyStr) != string::npos) outputList.push_back(sData); } } catch(DbException &e) { synonymDB.getDb().err(e.get_errno(), "Error in getAllSynonyms()"); foo = -1; } catch(exception &e) { synonymDB.getDb().errx("Error in getAllSynonyms(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function is written specially for command line search. * It searches the synonym db using keyStr and nsStr. * If the region name contains keyStr and nsStr EQUALS nsStr, * the region name will be put into the string vector. * Returns 0 if everything is ok, non-zero otherwise. */ int findSynonyms(string dbHome, string dbName, string key_in, bool ik_flag, string ns_in, bool ins_flag, vector &outputList) { string keyStr = key_in; if (ik_flag) keyStr = toLowerCase(key_in); string nsStr = ns_in; if (ins_flag) nsStr = toLowerCase(ns_in); mydb synonymDB(dbHome, dbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { synonymDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { synonymRec sData(data.get_data()); string sName = sData.getName(); if (ik_flag) sName = toLowerCase(sData.getName()); string nsName = sData.getNameSpace(); if (ins_flag) nsName = toLowerCase(sData.getNameSpace()); if (sName.find(keyStr) != string::npos && nsStr == nsName) outputList.push_back(sData); } } catch(DbException &e) { synonymDB.getDb().err(e.get_errno(), "Error in getAllSynonyms()"); foo = -1; } catch(exception &e) { synonymDB.getDb().errx("Error in getAllSynonyms(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function is written specially for command line search. * It searches synonym records that belong to a certain namespace and * put them into the string vector. * Returns 0 if everything is ok, non-zero otherwise. */ int findSynmNS(string dbHome, string dbName, string ns_in, bool ins_flag, vector &outputList) { string nsStr = ns_in; if (ins_flag) nsStr = toLowerCase(ns_in); mydb synonymDB(dbHome, dbName, DB_RDONLY); Dbc *cursorp; Dbt key, data; int ret; int foo = 0; try { synonymDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0 ) { synonymRec sData(data.get_data()); string nsName = sData.getNameSpace(); if (ins_flag) nsName = toLowerCase(sData.getNameSpace()); if (nsStr == nsName) outputList.push_back(sData); } } catch(DbException &e) { synonymDB.getDb().err(e.get_errno(), "Error in getAllSynonyms()"); foo = -1; } catch(exception &e) { synonymDB.getDb().errx("Error in getAllSynonyms(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function converts each letter in an input string into lower case and returns the new string. */ string toLowerCase(string inputStr) { string newStr = inputStr; for (uint i = 0; i< inputStr.size(); i++) newStr[i] = tolower(inputStr[i]); return newStr; } voxbo-1.8.5~svn1246/brainBrowser/br_util.h000066400000000000000000000057661153177201300204120ustar00rootroot00000000000000 // br_util.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* This header file includes some generic functions to read/write records * in the following three brain region database tables: * region_name.db * synonym.db * region_relation.db */ #ifndef BR_UTIL_H #define BR_UTIL_H #include "mydb.h" #include "region.h" #include "region_relation.h" #include "synonym.h" #include int chkRegionName(string, string, string, string); int chkSynonymStr(string, string, string, string); int getAllRegions(string, string, vector &, vector &); int getRegions(string, string, string, vector &); int getAllSynonyms(string, string, vector &, vector &); int getSynonyms(string, string, string, vector &); int getRegionRec(string, string, string, string, regionRec &); long getRegionID(string, string, string, string); int getRegionName(string, string, long, string &, string &); int getPrimary(string, string, string, string, string &); int getParentChild(string, string, long, long *, vector &); int getParent(string, string, long, long *); int getChild(string, string, long, vector &); int getSynonym(string, string, string, string, vector &); long getRelationID(string, string, long, long, string); int getRel_ui(string, string, long, vector &, vector &); int getRel_noChild(string, string, long, long, long, vector &); int getRel_noChildPart(string, string, long, long, vector &); int getRel_all(string, string, long, long, vector &); string trRel_db2ui(string, bool); // Function written specially for command line search int findRegionNames(string, string, string, bool, vector &); int findRegionNames(string, string, string, bool, string, bool, vector &); int findRegionNS(string, string, string, bool, vector &); int findSynonyms(string, string, string, bool, vector &); int findSynonyms(string, string, string, bool, string, bool, vector &); int findSynmNS(string, string, string, bool, vector &); string toLowerCase(string); #endif voxbo-1.8.5~svn1246/brainBrowser/brainBrowser.pro000066400000000000000000000006401153177201300217440ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (2.01a) Mon Mar 24 11:01:14 2008 ###################################################################### TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . # Input HEADERS += br_util.h main.h myDB.h region.h region_relation.h synonym.h FORMS += browseRegion.ui SOURCES += br_util.cpp main.cpp myDB.cpp voxbo-1.8.5~svn1246/brainBrowser/browseRegion.ui000066400000000000000000000270151153177201300215740ustar00rootroot00000000000000 brainBrowser 0 0 620 604 Brain Region Browser 60 346 0 17 Added on: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 80 454 101 20 PreferAntialias Relationship: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 39 186 141 20 PreferAntialias Child Structure(s): Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 360 530 91 28 PreferAntialias Close 90 286 91 20 PreferAntialias Synonyms: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 10 57 171 20 Helvetica PreferAntialias Search Region Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 190 246 381 91 50 120 131 20 PreferAntialias Parent Structure: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 130 383 51 20 PreferAntialias Link: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 190 380 381 27 PreferAntialias true 190 415 381 101 PreferAntialias 190 116 381 25 PreferAntialias QFrame::StyledPanel QFrame::Sunken 1 190 345 381 27 PreferAntialias true 110 350 71 20 PreferAntialias Source: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 190 50 381 29 PreferAntialias 100 90 81 20 PreferAntialias Located in: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 210 10 221 21 12 75 true PreferAntialias <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Helvetica'; font-size:12pt; font-weight:600; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><span style=" font-size:13pt;">Brain Region Browser</span></p></body></html> Qt::AlignCenter 190 147 381 91 PreferAntialias 190 83 141 28 PreferAntialias All namespaces NN2002 AAL Brodmann true 190 77 381 6 PreferAntialias 220 530 91 28 PreferAntialias Reset 0 0 620 23 &Help &About PreferAntialias nameEdit searchList name_space parent child synList srcEdit linkEdit relationList closeButt voxbo-1.8.5~svn1246/brainBrowser/main.cpp000066400000000000000000000467201153177201300202240ustar00rootroot00000000000000 // main.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* Possible bug: * when adding new relationship on "add new structure" interface, * the new relationship's compatibility is not checked completely * with other relationships. * For example, suppose the new structure is A, B and C already exists * and B is part of (or child of) C, user is allowed to added: * A is part of B; * A includes C; * although they should be incompatible. */ #include "main.h" #include "main.moc.h" #include #include #include #include #include int main(int argc, char *argv[]) { string dbHome; string rDbName = "region_name.db"; string rrDbName = "region_relation.db"; string sDbName = "synonym.db"; if (!setFiles(rDbName, rrDbName, sDbName, dbHome)) { printf("Database files not found in the following directories:\n"); printf(" /usr/share/brainregions/\n"); printf(" /usr/local/brainregions/\n"); printf(" $HOME/brainregions/\n"); printf(" ./\n"); printf("Application aborted.\n"); exit(0); } QApplication app(argc, argv); browser *myWindow = new browser(dbHome, rDbName, rrDbName, sDbName); myWindow->show(); return app.exec(); } /* Set location of bdb files. */ bool setFiles(string rDbName, string rrDbName, string sDbName, string &dbHome) { QStringList dbDirs; dbDirs << "/usr/share/brainregions/" << "/usr/local/brainregions/"; char *homedir = getenv("HOME"); if (homedir) dbDirs.append(QString(homedir) + "/brainregions/"); dbDirs.append("./"); int i; for (i = 0; i < dbDirs.count(); i++) { QFileInfo fi1 = dbDirs[i] + QString::fromStdString(rDbName); QFileInfo fi2 = dbDirs[i] + QString::fromStdString(rrDbName); QFileInfo fi3 = dbDirs[i] + QString::fromStdString(sDbName); if (fi1.isReadable() && fi2.isReadable() && fi3.isReadable()) { dbHome = dbDirs[i].toStdString(); break; } } if (i < dbDirs.count()) return true; return false; } /* Simple constructor */ browser::browser(string home_in, string rdb_in, string rrdb_in, string sdb_in, QWidget *parent) : QMainWindow(parent) { dbHome = home_in; rDbName = rdb_in; rrDbName = rrdb_in; sDbName = sdb_in; regionName = ""; buildUI(); } /* build the main interface */ void browser::buildUI() { ui_browser.setupUi(this); ui_browser.searchList->hide(); buildList(); ui_browser.nameEdit->setFocus(); connect(ui_browser.nameEdit, SIGNAL(textEdited(const QString &)), this, SLOT(popupList())); connect(ui_browser.searchList, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(selectName(QListWidgetItem *))); connect(ui_browser.name_space, SIGNAL(currentIndexChanged(int)), this, SLOT(changeNS())); connect(ui_browser.parent, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(toParent(QListWidgetItem *))); connect(ui_browser.child, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(toChild(QListWidgetItem *))); connect(ui_browser.relationList, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(toRelated(QListWidgetItem *))); connect(ui_browser.aboutAct, SIGNAL(triggered()), this, SLOT(about())); connect(ui_browser.resetButt, SIGNAL(clicked()), this, SLOT(resetUI())); connect(ui_browser.closeButt, SIGNAL(clicked()), this, SLOT(close())); setWindowTitle("Browse Database in " + QString::fromStdString(dbHome)); } /* Add structure names into wordList */ void browser::buildList() { nameList.clear(); spaceList.clear(); string currentSpace = ui_browser.name_space->currentText().toStdString(); int foo; if (currentSpace == "All namespaces") foo = getAllRegions(dbHome, rDbName, nameList, spaceList); else foo = getRegions(dbHome, rDbName, currentSpace, nameList); if (foo) { QMessageBox::critical(0, "Error", "Region name db exception."); return; } if (currentSpace == "All namespaces") foo = getAllSynonyms(dbHome, sDbName, nameList, spaceList); else foo = getSynonyms(dbHome, sDbName, currentSpace, nameList); if (foo) { QMessageBox::critical(0, "Error", "Synonym db exception."); return; } } /* This slot replies to the name_space change signal. * It rebuilds search list and start a new search. */ void browser::changeNS() { buildList(); clearUI(); popupList(); } /* This slot pops up the completion list */ void browser::popupList() { ui_browser.searchList->clear(); QString searchStr = ui_browser.nameEdit->text().simplified(); if (!searchStr.length()) { clearUI(); ui_browser.searchList->hide(); return; } for (uint i = 0; i < nameList.size(); i++) { QString itemStr = nameList[i].c_str(); if (itemStr.contains(QRegExp(searchStr, Qt::CaseInsensitive))) { if (ui_browser.name_space->currentIndex() == 0) itemStr = itemStr + " (" + spaceList[i].c_str() + ")"; ui_browser.searchList->addItem(itemStr); } } if (!ui_browser.searchList->count()) { ui_browser.searchList->hide(); return; } ui_browser.searchList->setMinimumHeight(165); ui_browser.searchList->sortItems(Qt::AscendingOrder); ui_browser.searchList->show(); } /* This slot selects one of the names from list box and show relevant infomation on interface */ void browser::selectName(QListWidgetItem *mySel) { //ui_browser.main_title->setText("Brain Region Browser"); //ui_browser.name_title->setText("Search Region Name:"); QString comboStr = mySel->text(); QString nameStr, spaceStr; bool withNS = true; if (ui_browser.name_space->currentIndex()) withNS = false; int foo = parseRegionName(comboStr, withNS, nameStr, spaceStr); if (foo == 1) { QMessageBox::critical(0, "Error", "Invalid selection string: " + comboStr); ui_browser.searchList->hide(); return; } if (foo == 2) { QMessageBox::critical(0, "Error", "Invalid name space: " + spaceStr); ui_browser.searchList->hide(); return; } ui_browser.nameEdit->setText(nameStr); ui_browser.searchList->hide(); searchRegion(nameStr.toStdString(), spaceStr.toStdString()); if (regionName.length()) return; searchSynonym(nameStr.toStdString(), spaceStr.toStdString()); ui_browser.nameEdit->setFocus(); } /* This function reads the first argument and divides it into two parts: * region name and namespace. * Returns 0 if everything is ok; * returns 1 if input string can't be divided successfully. * returns 2 if namespace is unknown; */ int browser::parseRegionName(QString inputStr, bool withNS, QString & nameStr, QString & spaceStr) { if (!withNS) { nameStr = inputStr; spaceStr = ui_browser.name_space->currentText(); return 0; } int strLen = inputStr.length(); int foo = inputStr.lastIndexOf("("); int bar = inputStr.lastIndexOf(")"); if (foo == -1 || foo < 2 || bar == -1 || foo >= bar || bar != strLen - 1) return 1; nameStr = inputStr.left(foo - 1); spaceStr = inputStr.mid(foo + 1, bar - foo - 1); if (!chkNameSpace(spaceStr)) return 2; return 0; } /* This function checks whether the input string is a valid namespace. If it is, * set the namespace combo box on the interface to correct value and returns true; * returns false otherwise. */ bool browser::chkNameSpace(QString inputStr) { if (inputStr == "NN2002") return true; if (inputStr == "AAL") return true; if (inputStr == "Brodmann") return true; if (inputStr == "Marianna") return true; if (inputStr == "QT_UI") return true; return false; } /* This function checks whether the input string is a valid namespace. If it is, * set the namespace combo box on the interface to correct value and returns true; * returns false otherwise. */ void browser::setNameSpace(string inputStr) { int nsIndex; if (inputStr == "NN2002") nsIndex = 1; else if (inputStr == "AAL") nsIndex = 2; else if (inputStr == "Brodmann") nsIndex = 3; else { QMessageBox::critical(0, "Error", "Unknown namespace: " + QString(inputStr.c_str())); return; } disconnect(ui_browser.name_space, SIGNAL(currentIndexChanged(int)), this, SLOT(changeNS())); ui_browser.name_space->setCurrentIndex(nsIndex); name_space = inputStr; buildList(); connect(ui_browser.name_space, SIGNAL(currentIndexChanged(int)), this, SLOT(changeNS())); } /* seach a structure name in region_name.db and show its information on the interface */ void browser::searchRegion(string rName, string inputSpace) { clearUI(); regionRec rData; int foo = getRegionRec(dbHome, rDbName, rName, inputSpace, rData); // quit if db file exception is met if (foo < 0) { QMessageBox::critical(0, "Error", "Region name db exception"); return; } // quit if the name is not found in region name db file if (foo == 0) return; regionID = rData.getID(); regionName = rName; //long add_time = rData.getAddDate(); //if(add_time) // ui_browser.addDate->setText(ctime(&add_time)); //long mod_time = rData.getModDate(); //if (mod_time) // ui_browser.modDate->setText(ctime(&mod_time)); ui_browser.nameEdit->setText(rName.c_str()); setNameSpace(inputSpace); ui_browser.srcEdit->setText(rData.getSource().c_str()); ui_browser.linkEdit->setText(rData.getLink().c_str()); showParentChild(); showSynonym(); showRelation(); //setWindowTitle("Brain Region Info: " + ui_browser.nameEdit->text()); } /* seach a synonym name and show relevant information on the interface */ void browser::searchSynonym(string sName, string inputSpace) { string pName; int foo = getPrimary(dbHome, sDbName, sName, inputSpace, pName); if (foo < 0) { QMessageBox::critical(0, "Error", "Synonym db exception."); return; } // quit if the name is not found in synonym db file if (foo == 0) { QMessageBox::critical(0, "Error", "Name not found in region name and synonym db files: " + ui_browser.nameEdit->text()); return; } searchRegion(pName, inputSpace); } /* This functions clears all information on the interface */ void browser::clearUI() { regionID = 0; regionName = name_space = ""; ui_browser.parent->clear(); ui_browser.child->clear(); ui_browser.synList->clear(); //ui_browser.addDate->clear(); //ui_browser.modDate->clear(); ui_browser.srcEdit->clear(); ui_browser.linkEdit->clear(); ui_browser.relationList->clear(); } /* This slot responds to "reset button click. */ void browser::resetUI() { ui_browser.nameEdit->clear(); clearUI(); } /* Show parent and child information on the interface */ void browser::showParentChild() { long parentID = 0; vector cList; int foo = getParentChild(dbHome, rrDbName, regionID, &parentID, cList); if (foo < 0) { QMessageBox::critical(0, "Error", "Relationship db exception."); return; } // If parent exists, get its name and show on interface if (parentID) { string parentStr, spaceStr; foo = getRegionName(dbHome, rDbName, parentID, parentStr, spaceStr); if (foo == 1) ui_browser.parent->addItem(parentStr.c_str()); else QMessageBox::critical(0, "Error", "Fails to get parent region name from ID " + QString::number(parentID) + " in region db."); } for (unsigned i = 0; i < cList.size(); i++) { long cID = cList[i]; string cName, spaceStr; foo = getRegionName(dbHome, rDbName, cID, cName, spaceStr); if (foo == 1) ui_browser.child->addItem(cName.c_str()); else QMessageBox::critical(0, "Error", "Fails to get child region name from ID " + QString::number(cID) + " in region name db."); } if (ui_browser.child->count()) ui_browser.child->sortItems(Qt::AscendingOrder); } /* This function updates the current parent region name. */ void browser::showParent() { ui_browser.parent->clear(); long pID = 0; int foo = getParent(dbHome, rrDbName, regionID, &pID); if (foo < 0) { QMessageBox::critical(0, "Error", "Relationship db exception."); return; } if (!pID) return; string parentStr, spaceStr; foo = getRegionName(dbHome, rDbName, pID, parentStr, spaceStr); if (foo != 1) { QMessageBox::critical(0, "Error", "Fails to get parent region name from ID " + QString::number(pID) + " in region db."); return; } ui_browser.parent->addItem(parentStr.c_str()); } /* Show parent and child information on the interface */ void browser::showChild() { ui_browser.child->clear(); vector cList; int foo = getChild(dbHome, rrDbName, regionID, cList); if (foo < 0) { QMessageBox::critical(0, "Error", "Relationship db exception."); return; } for (unsigned i = 0; i < cList.size(); i++) { long cID = cList[i]; string cName, spaceStr; foo = getRegionName(dbHome, rDbName, cID, cName, spaceStr); if (foo == 1) ui_browser.child->addItem(cName.c_str()); else QMessageBox::critical(0, "Error", "Fails to get child region name from ID " + QString::number(cID) + " in region name db."); } if (ui_browser.child->count()) ui_browser.child->sortItems(Qt::AscendingOrder); } /* This function shows synonym(s) on the interface */ void browser::showSynonym() { ui_browser.synList->clear(); vector symList; int foo = getSynonym(dbHome, sDbName, regionName, name_space, symList); if (foo < 0) { QMessageBox::critical(0, "Error", "Synonym db exception."); return; } for (unsigned i = 0; i < symList.size(); i++) ui_browser.synList->addItem(symList[i].c_str()); } /* This function collects input region's relationship information and show on the interface. * Note that child/parent relationships are excluded because they are already shown. */ void browser::showRelation() { ui_browser.relationList->clear(); vector r2List; vector relList; int foo = getRel_ui(dbHome, rrDbName, regionID, r2List, relList); if (foo < 0) { QMessageBox::critical(0, "Error", "Relationship db exception."); return; } for (unsigned i = 0; i < relList.size(); i++) { string r2_name, r2_space; foo = getRegionName(dbHome, rDbName, r2List[i], r2_name, r2_space); if (foo == 1) { string tmpStr = relList[i] + ": " + r2_name + " (" + r2_space + ")"; ui_browser.relationList->addItem(tmpStr.c_str()); } else QMessageBox::critical(0, "Error", "Fails to get region name from ID " + QString::number(r2List[i]) + " in region name db."); } } /* This function collects parent structure info and show on the interface */ void browser::toParent(QListWidgetItem *pItem) { QString pStr = pItem->text(); // Return 0 if parent name is same as the structure name ("BRAIN") if (regionName == pStr.toStdString()) return; ui_browser.nameEdit->setText(pStr); searchRegion(pStr.toStdString(), name_space); } /* This is the slot when item in child name list is double clicked */ void browser::toChild(QListWidgetItem *selItem) { QString selName = selItem->text(); ui_browser.nameEdit->setText(selName); searchRegion(selName.toStdString(), name_space); } /* This slot takes care of double click signal in relationship box. */ void browser::toRelated(QListWidgetItem *selItem) { QString relStr = selItem->text(); int colon_post = relStr.indexOf(": "); int ns_post = relStr.lastIndexOf(" ("); if (colon_post == -1 || ns_post == -1) { QMessageBox::critical(0, "Error", "Relationship not understood: " + relStr); return; } QString newRegion = relStr.mid(colon_post + 2, ns_post - colon_post - 2); QString newNS = relStr.mid(ns_post + 2, relStr.length() - ns_post - 3); ui_browser.nameEdit->setText(newRegion); searchRegion(newRegion.toStdString(), newNS.toStdString()); } /* Show acknowledgement information. */ void browser::about() { string helptext= "This initial release of the VoxBo Brain Structure Browser was written by Dongbo Hu (code) and " "Daniel Kimberg (sage advice). It is distributed along with structure " "information derived from the NeuroNames project (Bowden and Dubach, " "2002) as well as the AAL atlas (Automatic Anatomical Labeling, " "Tzourio-Mazoyer et al., 2002).

" "References:

" "Tzourio-Mazoyer N, Landeau B, Papathanassiou D, Crivello F, Etard O, " "Delcroix N, Mazoyer B, Joliot M (2002). \"Automated Anatomical " "Labeling of activations in SPM using a Macroscopic Anatomical " "Parcellation of the MNI MRI single-subject brain.\" NeuroImage 15 (1), " "273-89.

" "Bowden D and Dubach M (2003). NeuroNames 2002. Neuroinformatics, 1, " "43-59."; QMessageBox::about(this, tr("About Application"), tr(helptext.c_str())); } /* This overloaded function takes care of some key press events */ void browser::keyPressEvent(QKeyEvent * kEvent) { if (ui_browser.nameEdit->hasFocus() || ui_browser.searchList->hasFocus()) { if (ui_browser.searchList->isVisible() && kEvent->key() == Qt::Key_Escape) { ui_browser.searchList->setFocus(); ui_browser.searchList->hide(); ui_browser.nameEdit->setFocus(); } } if (ui_browser.nameEdit->hasFocus() && ui_browser.searchList->count() && ui_browser.searchList->isVisible()) { if (kEvent->key() == Qt::Key_Down) { ui_browser.searchList->setFocus(); ui_browser.searchList->setCurrentRow(0); } else if (kEvent->key() == Qt::Key_Up) { ui_browser.searchList->setFocus(); ui_browser.searchList->setCurrentRow(ui_browser.searchList->count() - 1); } else ui_browser.searchList->show(); } else if (ui_browser.searchList->hasFocus() && ui_browser.searchList->currentRow() == ui_browser.searchList->count() - 1 && kEvent->key() == Qt::Key_Down) ui_browser.searchList->setCurrentRow(0); else if (ui_browser.searchList->hasFocus() && ui_browser.searchList->currentRow() == 0 && kEvent->key() == Qt::Key_Up) ui_browser.searchList->setCurrentRow(ui_browser.searchList->count() - 1); else if (ui_browser.searchList->hasFocus() && kEvent->key() == Qt::Key_Backspace) { ui_browser.nameEdit->setFocus(); ui_browser.nameEdit->backspace(); } else if (ui_browser.searchList->hasFocus() && kEvent->key() == Qt::Key_Delete) { ui_browser.nameEdit->setFocus(); ui_browser.nameEdit->del(); } else if (ui_browser.searchList->hasFocus() && kEvent->key() != Qt::Key_Up && kEvent->key() != Qt::Key_Down && kEvent->key() != Qt::Key_Return && kEvent->key() != Qt::Key_Enter && kEvent->key() != Qt::Key_PageUp && kEvent->key() != Qt::Key_PageDown) { ui_browser.nameEdit->setFocus(); QString orgStr = ui_browser.nameEdit->text(); QString newStr = kEvent->text(); if (newStr.length()) { ui_browser.nameEdit->setText(orgStr + newStr); popupList(); } } else if (!ui_browser.nameEdit->hasFocus() && !ui_browser.searchList->hasFocus()) ui_browser.searchList->hide(); //kEvent->accept(); QMainWindow::keyPressEvent(kEvent); } voxbo-1.8.5~svn1246/brainBrowser/main.h000066400000000000000000000041431153177201300176620ustar00rootroot00000000000000 // main.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* This interface allows user to browse/search brain region database. */ #include "br_util.h" #include "ui_browseRegion.h" #include bool setFiles(string, string, string, string &); class browser : public QMainWindow { Q_OBJECT public: browser(string, string, string, string, QWidget *parent = 0); private: void buildUI(); void buildList(); int parseRegionName(QString, bool, QString &, QString &); bool chkNameSpace(QString); void setNameSpace(string); void searchRegion(string, string); void searchSynonym(string, string); void clearUI(); void showParentChild(); void showParent(); void showChild(); void showSynonym(); bool chkName(string); void showRelation(); void keyPressEvent(QKeyEvent *); string dbHome, rDbName, rrDbName, sDbName; Ui_brainBrowser ui_browser; vector nameList; vector spaceList; long regionID; string regionName, name_space; private slots: void popupList(); void selectName(QListWidgetItem *); void changeNS(); void toParent(QListWidgetItem *); void toChild(QListWidgetItem *); void toRelated(QListWidgetItem *); void resetUI(); void about(); }; voxbo-1.8.5~svn1246/brainBrowser/myDB.cpp000066400000000000000000000071341153177201300201270ustar00rootroot00000000000000 // myDB.cpp // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* Simple database class, more like a wraaper of Berkeley DB's db_ */ using namespace std; #include "myDB.h" /* Class constructor. Requires a path to the location * where the database is located, and a database name. */ myDB::myDB(std::string &path, std::string &dbName, u_int32_t openFlag, bool idCompare, bool allowDup, DBTYPE inputType) : db_(NULL, 0), // Instantiate Db object dbFileName_(path + dbName) // Database file name { try { // Redirect debugging information to std::cerr db_.set_error_stream(&std::cerr); // Set encrypt db_.set_encrypt("fyeo2006", DB_ENCRYPT_AES); // If this is a secondary database, support sorted duplicates if (allowDup) db_.set_flags(DB_DUPSORT); else if (idCompare && inputType == DB_BTREE) db_.set_bt_compare(compare_int); // Open the database db_.open(NULL, dbFileName_.c_str(), NULL, inputType, openFlag, 0); } // DbException is not a subclass of std::exception, so we need to catch them both. catch(DbException &e) { std::cerr << "Error opening database: " << dbFileName_ << "\n"; std::cerr << e.what() << std::endl; } catch(std::exception &e) { std::cerr << "Error opening database: " << dbFileName_ << "\n"; std::cerr << e.what() << std::endl; } } /* Private member used to close a database. Called from the class destructor. */ void myDB::close() { // Close the db try { db_.close(0); //std::cout << "Database " << dbFileName_ << " is closed." << std::endl; } catch(DbException &e) { std::cerr << "Error closing database: " << dbFileName_ << "\n"; std::cerr << e.what() << std::endl; } catch(std::exception &e) { std::cerr << "Error closing database: " << dbFileName_ << "\n"; std::cerr << e.what() << std::endl; } } /* This function returns the number of records in database, * used to generate keys automatically. */ long myDB::countRec() { long length = 0; // Get a cursor to the patient db Dbc *cursorp; try { getDb().cursor(NULL, &cursorp, 0); Dbt key, data; while (cursorp->get(&key, &data, DB_NEXT) == 0) length++; } catch(DbException &e) { getDb().err(e.get_errno(), "Error in reading records"); cursorp->close(); throw e; } catch(exception &e) { cursorp->close(); throw e; } cursorp->close(); return length; } /* This function compares keys arithmetically instead of lexically. * It is called when the db key is a long integer and we want to * rank the records according to the key value. */ int compare_int(DB *dbp, const DBT *dbt1, const DBT *dbt2) { long l = *(long *) dbt1->data; long r = *(long *) dbt2->data; return l - r; } voxbo-1.8.5~svn1246/brainBrowser/myDB.h000066400000000000000000000034141153177201300175710ustar00rootroot00000000000000 // myDB.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* myDB.h: simple wrapper of the basic _db class */ #ifndef MYDB_H #define MYDB_H #include #include class myDB { public: // Constructor requires a path to the database and a database name. myDB(std::string &path, std::string &dbName, u_int32_t openFlag = DB_CREATE, bool idCompare = true, bool allowDup = false, DBTYPE dbtype = DB_BTREE); // Destructor just calls private close method. ~myDB() { close(); } inline Db &getDb() { return db_; } long countRec(); private: Db db_; std::string dbFileName_; u_int32_t cFlags_; // Make sure the default constructor is private myDB() : db_(NULL, 0) { } // put our database close activity here. Called from our destructor. Could be public void close(); }; int compare_int(DB *dbp, const DBT *dbt1, const DBT *dbt2); #endif voxbo-1.8.5~svn1246/brainBrowser/region.h000066400000000000000000000135031153177201300202210ustar00rootroot00000000000000 // region.h // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /******************************************************************************* * regionRec class definition: hold each region's information *******************************************************************************/ using namespace std; #include #include #include class regionRec { public: regionRec() { clear(); } regionRec(void *buffer) { setData(buffer); } /* Use an input data pointer to set each variable. */ void setData(void *buffer) { char *buf = (char *) buffer; int longLen = sizeof(long); ID = *((long *) buf); bufLen = longLen; name_space = buf + bufLen; bufLen += name_space.size() + 1; name = buf + bufLen; bufLen += name.size() + 1; abbrev = buf + bufLen; bufLen += abbrev.size() + 1; orgID = *((long *) (buf + bufLen)); bufLen += longLen; source = buf + bufLen; bufLen += source.size() + 1; pFlag = buf + bufLen; bufLen += pFlag.size() + 1; link = buf + bufLen; bufLen += link.size() + 1; creator = buf + bufLen; bufLen += creator.size() + 1; addDate = *((long *) (buf + bufLen)); bufLen += longLen; modifier = buf + bufLen; bufLen += modifier.size() + 1; modDate = *((long *) (buf + bufLen)); bufLen += longLen; } /* Initialize data members. */ void clear() { ID = 0; name_space = name = abbrev = ""; orgID = 0; source = pFlag = link = ""; creator = modifier = ""; addDate = modDate = 0; } /* Return combined data members as a single contiguous memory location. */ char * getBuffer() { memset(databuf, 0, 1000); bufLen = 0; int longLen = sizeof(long); memcpy(databuf, &ID, longLen); bufLen += longLen; packString(databuf, name_space); packString(databuf, name); packString(databuf, abbrev); memcpy(databuf + bufLen, &orgID, longLen); bufLen += longLen; packString(databuf, source); packString(databuf, pFlag); packString(databuf, link); packString(databuf, creator); memcpy(databuf + bufLen, &addDate, longLen); bufLen += longLen; packString(databuf, modifier); memcpy(databuf + bufLen, &modDate, longLen); bufLen += longLen; return databuf; } /* Return the size of the buffer. */ inline int getBufferSize() { return bufLen; } /* Print out all data members. */ void show() { printf("Region ID: %ld\n", ID); printf("Region namespace: %s\n", name_space.c_str()); printf("Region name: %s\n", name.c_str()); printf("Region abbreviation: %s\n", abbrev.c_str()); printf("Original ID in source: %ld\n", orgID); printf("Region source: %s\n", source.c_str()); printf("private flag: %s\n", pFlag.c_str()); printf("Region link: %s\n", link.c_str()); printf("Added by: %s\n", creator.c_str()); if (addDate) printf("Region added on: %s", ctime(&addDate)); else printf("Region added on:\n"); printf("Modified by: %s\n", modifier.c_str()); if (modDate) printf("Last modified on: %s", ctime(&modDate)); else printf("Last modified on:\n"); } inline void setID(long inputVal) { ID = inputVal; } inline void setNameSpace(string inputStr) { name_space = inputStr; } inline void setName(string inputStr) { name = inputStr; } inline void setAbbrev(string inputStr) { abbrev = inputStr; } inline void setOrgID(long inputVal) { orgID = inputVal; } inline void setSource(string inputStr) { source = inputStr; } inline void setPrivate(string inputStr) { pFlag = inputStr; } inline void setLink(string inputStr) { link = inputStr; } inline void setCreator(string inputStr) { creator = inputStr; } inline void setAddDate(long inputVal) { addDate = inputVal; } inline void setModifier(string inputStr) { modifier = inputStr; } inline void setModDate(long inputVal) { modDate = inputVal; } inline long getID() { return ID; } inline string getNameSpace() { return name_space; } inline string getName() { return name; } inline string getAbbrev() { return abbrev; } inline long getOrgID() { return orgID; } inline string getSource() { return source; } inline string getPrivate() { return pFlag; } inline string getLink() { return link; } inline string getCreator() { return creator; } inline long getAddDate() { return addDate; } inline string getModifier() { return modifier; } inline long getModDate() { return modDate; } private: /* Utility function that appends a char * to the end of the buffer. */ void packString(char *buffer, string &theString) { int string_size = theString.size() + 1; memcpy(buffer + bufLen, theString.c_str(), string_size); bufLen += string_size; } long ID; string name_space, name, abbrev; long orgID; // original ID from input file, such as ID field in NN2002's hierarchy table string source, pFlag, link; string creator, modifier; long addDate, modDate; int bufLen; char databuf[1000]; }; voxbo-1.8.5~svn1246/brainBrowser/region_name.db000066400000000000000000006000001153177201300213510ustar00rootroot00000000000000b1 @  ®®’’gä£ð8’$ªbLØÕ±DXÕ…H;2ÿ‘ªíP`À‹!kØÌé%öòóVV¼bvä]TÅ(½30fÜÔè¾]-Ëp¦¤DQúIªÆÀ";z¨UŒÝóG;ð#h«ñÍÉ…èof ài¸Ý˜¦ç¦ä¸è¿Ÿ”š×ÁšéøîyKö•ˆ¥+WY1|%CUˆr y'I†`Le'Ü]ìx?_êU£»“J¨îÆfª)ÎLâ^‹sS•—òjÈ«yBû/×·-Ñ<²»HƒGÌÅéäÍ‚áÚÞø1'‚4•1=á ù .N†65½#–cÀ]—Y]îJÐb' ¡‡Æ%WŠY&¹«T)åÈÒÖ0±úíoï J†jYK£Ì¤LÔÓ‡ASš9ìÍ‹ßÎêû±ùfW Ë!¢º+¢+ЛÎù‰Hš÷J)!u3,h€=Æìþ,¼ãíD½FÄÚŠ<Ì5;ƒ|Ço9Ÿ=#‰·›=t×QЫz4÷¢Æ•ÄjdÃzÒ‰°u@ÑqºEG1Èr>ÞZ4SŽ“Ý*=_‰%‰?ë$b­û©}PzÈw•hyÅ!e°/®Ãq` d?ð¸¶}kÚ: ´¼®4^éA@í¢¥9òâF1¤ñ²‚È£¸ØnxÂëeß„)ó)ÄòoûŠ}5¸*à/gu“‚–rÖnBJ›¿LÚš½ž1*š¯j¡‘©Ç” `¥jiúRÒÐa¤îó-¥Acaß´/³Vw˜‹KˆxGœmi?â8— u¨KœÂ-ca/Oì]T·ngã\túUCé˜øy‚“¡”J sÅ\ðÒÆûf-ÅAQ2„.¼®¢în°9[ü?ç¹~‡Gaq!öÊÝQàÃÖcÙ ;fQg–ØJaÿ¶°(…OCNÀoüöê¦"6?#]‚ùjŸRÃ)¾ ü€SÙûAeŸå@Ј\è'f¨uãËPÇ7ú§U‰Éà÷íÇ(ˆtì…´K(Ý{û6“ßtâ”{ðI¾ÃÍÃv”ÅÚ%Ù›¢™0¥¨¨‘þ•5—ׄXcqf+ôKßÚô°ËyIYwSB%U6J»éû—ÚÓ]«P}ó³aÏEÒé!œŽ2‘à¢ÚDöU¼ èà‡BÖ6–×ô7¨ÁÚ¨2…‘9Ÿs7Üò‘±JEýÂWRu„ máªÔ®M B xöÍEf•í{_³4D‡„C"0šXq¨¹Eô§´´=L÷ÑÉcð¨}!nâÎ)çM“<‘´Åï°«]Z å¿‹òtSN4\v¿l™1üÌ›ÀÚjºAöµ²×¯°$¨ï`j'›µG¢ ¸3¯ìOîà`E-xÃÂSÈ„„¤‰&0äµ žºEû³çæM ,zµrD¼Ë"ôõ[,d@ì¸Î²–®»fÔ- ò ma–ü­\»)ðYi7—EøBµÑ”²¿Ði¾q˜J¤?j<Ÿ|Úm¦¦nxLÍ´(Å3ÄØÄzKÓ§ ®-XÜE1õÔ†¿=:¬æ¯°D«(Tk÷¨4ÔÐ ¿{˦|¦DHùë>ý0iµ¸±;Gë°Çh8„sÝ8ïx·–'³*òñ…(þÍ|8Cm×çÐ}åý÷ÍÝ&4|†™#AÉUûßîÿl몊BžíÇ'/@tz EÉ/?8Þ¨QHÏ¿JzYÞ±ài,ºÍeîÐÛ9Í‹Þäׄ :kþÉü6!•´´ î£X¢2("4$à´Eqq€Ì$jï…Š‰Ñ TÝòoQyiÞýß20ñ½hC®!÷›+œ¡‘b¯oXfuÀ·PÝÇýþfîvö+T¬òR£z ¼÷ŽîÛaSPŠ™}}×Vf1ÖV3‚ëÂýís"ýA)~˜/˜Ä^ì׿wŠòLXî‰hV‚·Óz7”õ­ç¾Áð]úb«ù¨¥—^ ÌC¯ªw$Þ’‚V‹þ8/|kfå/Ȉ7öVëÄ´Š–òK‰’†f¢Ï•[L0R)ó  ôXî:ÎØé~[œ:Š¿ªi½ÇªÕж÷¶ôV;cÕ˜‹ý”ûÌnl‚´…ÿîúBdoÑ„Û[?#–zW, zZ®îÊšû’ÁÛÖ?á%ýtàälW9ˆƒuéRªKÓ\lO…ed|E!›º%†Ì0ÞYÊ<%”בՋ9¼ò´ë.|q8•[dÖ1vÓ¶ÒÛy$¥@/L#×ðnÒ¾ÿªYáùñΙd-1£«÷Y{v8b-—ô2^µNHÍlº«³þŸ•jºFÃøV²Ç¶$×Ô0˜ãž`iò±õ&~Ôo<‚œ³NbfÆÀZm vÛqh¤ ˆ¿F…1ø½¯ówü¾?ý§âI¦o¬Ï _'FO€8nðáÕ¤h̹ñ§¦ ´Ž™æÌ<­ï&‚ŠÁsksÌ´«„ê-Z.ý-КòÿÌ^¹>;ÞØhYƒ }ÈjªQ?Ç~b‘Uß9¤y „“þ*Ÿ$´e²•J²A Šô¯ñSû¦Rjßî°þ^aÃ{G„ žH—ö¼€¨¨ô‡èÞE´™ì˜¬ËÞ*þ)›²Ž†cE ÷£Àê—X|»qDFþÛ-Ö†Àbío;ÈUuÁ£ÿÛó‘ÈfqGJ(1Ô‹›È ¢¸ÌæúBUª‰ÅB¤S†&#×Ö/Ü­¬eÓD+A@¬n»fp‹^ì±.&,þ°¡¥@Ιqà˜Ä¤…"Äo–¢¯Ó#G€™ÐªmnW×oÞTXAB²1&ÖcÚŒèq(\þîºñŠTgb¬q{û&6ûê7X`Ia†Î<\:e±þ¾KëÔFhmô–³ÕÉW(¶ÖžÒ¸Û’•‹ CW>Ãy}–·¼€ìG™¸Â/¤'Gáì0tâä&š®¢ltE¸àÃÏÖ`æë6X²(ž^CiO÷ÛÅw„l§çLËíœÏšs±ãLÿ¶~ÌK\ B‘¢lý«F)ÅZÎh { åUß&-½s ÍzèX ZQÍÁÈU8¡ói¶ŒU1šä/¥ª¬T“l³ èe‘*_;íªç· _$1SÖ‰ž4HÀ)ޱ÷I“¿]¥ìQ]#‹xT±xsÒ¥÷Éf‰œìž&3O‹;ÚMi+oÚ——ÑWkéì»d˜@–ÓC5†¼×ýYp£›Rf^þ…Gj)ž×ê˜ÉN® ìt®z¦Ëåý'ú):˜ë©]zcr8gvë<—Ô÷ñRÿ¥\]É2…–&+‰¶åÉeíÃ4swÞ¹Þ¸|vÕÇ ‹üz¦ö·Eê€Öô–Ö=žã„‘E»õD68 ¼AFííèæ}@ðRjáæÔž½?à‰ÛÊÕŸÜÔéÏ€ÕügÀü†(®É_‘¸Ä_dA+g+¤Dl“å\Á1O3&àõnv#ÕSú}=æ„Qç:¥$™‡ðMX?ö‚&8SApY^´™–·Ëc3}Qõ üi+6¿ãs¯eîWÌ%|©²6XBù˨wå4Э_™pvHŠêB˜ñþä@¦9韭厢'Áÿ#6H°«%Ý-1òÄõi¸'{b(r˜¢†áfV²ÇÐ^ˆxêE‡ä.EÑXÎ j ÝŽ¼£3¹RÞ²ü›Æè”jB€0M‡L 9‰OZì~°B+ú”TðúWnZlÊ…í”’ ¤Þ^j[Ä»Ôx÷‘Ʋ}µ´?¯7@÷ÈTy¸×…£90gœ•+ô£…ohᕌohMü@±V©=Z"5é‰ì•S XG.s\ÇšYˆÉ©x_õ¢*jY^ œâ $ÅnÍlSÕÐà7¾‡©zJOÞ¸¤3¿*Óô ¶CËÅ6 ¿%é¹}q ¥"b>hHaN9\ŒT¶º¯"“’»‰õKf†‡LÞÁ‚CCå·å¡…¢-l;c¹‡sNª—DBÙohcØÓœžø“ö‘ÈÍŒ.{©  ‘óû›ìK§KKtþÆl×…pK=öÇÑFSƒ kYþª¶5È;ñÃ#F昨#CeÿöfÆ 6$=AKS)ù˜×%¾ZZÖ’éi…­5Y›Ö:Èþ(;ÔTµ6;6HÕuŠ™ËÓ Z]/ @QW:ÿÖc‹]=§b`6LBLÕà|³a7Þa€¿ÃIþ®årêà)Ê-âFO¿“ÑD*Ì1ê‰z¦7Us\ô;„Ìeئª×É å«ë.“­·«ìÚ=HJ+6¬Òë–“î]%­0BÞ5©ÙöÄAî#TæýÙ¹Sàt+k¿ŸWnM…òˆs:ò û›î1ýû'ÄŠU‹+ìháfæê®—âƒXȱâ £Ø*ÔQò:÷ú¦“¼U~ìÉrôš¨mæœ÷?ňûoi|ö²=«äƒÞˆ¾>—EOq¥Ó­'Ñ7ÄíQ¯ Ïêã{ÁvâšüYfƒs§â5±,q>MNéOjæ=úŸ1 ô ¦=³Ȳý|áÈ…’>ªe©!09þe€l|LqqåÃ|¢™,¯yfeËD ¸fõÐ^³¥)¨ïÑŽhMØ(Ö¿/lÀ~ÿÚY´Rs.‘³Ýþtë Õ¦B5Mâç›ë&³0…OPé5S8Úš#“ÛÝâj*VXˆˆë«…ÀtC™ "4¦utÇ"½—,L›æ|8¬|:Ò)ÿîÕR׆¬üvAKÙòx˜ÜϨŽœ˜®m±o)éí¾÷v#äÄì^Žå“è‚‹Ä$/0¯½]².Óéôáqé«™ƒÔ¬©4üƒG,i”WK¾ X|ê'ñÛû.ÿ¹xƒ]\x=™|IG4¯ÚÉm›<áƒ_¹0 /:œW>^ÀD|¨ãŠŒ£ m–ª?©ˆ¯»œdÀýÀÜݲôÍd œòÑÉΡu£4 /5ÜÙvS'PçXöƒ/ë–Òj³A$…´Ö1@Üøî*|ã窼‡DÌNŠ-~§€î £V“߬Ÿž¬ªô°´¶&1h3”ëĶÍÉ-ò¼° ø^ÁÈ'€™»S2ÒptÉ—óçí@ÝÕ0X¶gOk‹ir÷f¿÷ËØ‰´þ2˜–Ô¯±—'\˜ì¯¦Ð‚¨q](ØZ>lmV)·ÿE˜inÓjÔ³Äð@°ÈŸÑJ;ý[ïJL¦×’© s®pù6 º 4†…4ü†½ëî~TÂÑ̽ôwø]„“˜7¬µ XËPS”4z®¬¿iÓ`Ù'rïèCnð‹ðœÔŸ0^(ó²Ž.Äú#3κ»._}ÕGŽÖjq”ZÕæ»!hæAƒã(¿Ô$ݬ¬ áœÔºùnTÀëŽÉØu[Ð|ÁúÞ†‚KØô~¥„D@Iñ ö;·™Rð"X r×¹®»^…Òï}s›£¬_GܯPKV9äYQM­IgÖ¼±n© ¶p`Ñ’Ç>…ÿç›$¼G@jÇäÚÓ¶ï$àäÏmìòƒÄ#›R]Ö¼.™˜ÝGáÞíiþq«¤í;^Æß×t™¸ïe„]S´ËNß³+ÀtÄé„C Õ ñ¶UÊà7þ%ò˜³÷ €ArZû\ªI0K3(jß’‘¯‹xBgçYO y‹1£ßr)¬Èõ3/N„pJœ%MŸµù8+†QZWqgnïÏ8„‚¡¸à.Ô RW8>šþ'ØÉ¿‚r…[Tâãõ% "¹!ì©{š¡FyñW1ƒ¦¹v¬ŠTÖªJÛmÙŒáÐõgŸ­GwÉMk\ãØMê!·ÿíKî BÛu&íþÁ#¶?e֙ψÉjT˜CòŠlÌäPHiŸB ÁzŒ­Ù£†×ÀlÀUb€•þš¢Aú‡Qìh'qbjGnª±–~ŸkoeB§îwøáÃbý r,1žõ‰Þ­@‡ÕÕE™éKÆè&ÖaKœ! æG§cñw1+d[Í-¸rJÄ7è}þÉ…b¶ÎŠOëà 2ýyPñCTòµK!9çväTQ"0¼çÂ= `Òq!e—4¸ñ¶?…$)Ühè©Ú#Ê……õÔ6»¦ü-”{àú&A V=¹Pì70ƒΤíxerÚ5;¾©øp‡=VfÏÕ—šb¬ÊZ]]Ó:·u°ìj¿ÀÀ–0WÝòs(·320þJêI9ªÚn‹y²Í‡.5>¾^C&Æ/¾è0 †I×Ô´9¿JHÛ)ÆjÆÆs9×D±õ 46#Y·¸Ã¸~0ÕvY1h ã-S›éåçyࣵ\I©\ÒDáK‡Òã?E ÓRŒ²µ4ƒ~ú[ÀTšk¥¤œ9*@ÄarA ÛÎ.G@WDן¼Ø£-,'…)k%ÎFýM9.b娢lZıÞÁv¾,wMZam{T´Æº !yâ°xàî¶Š;ðLñ $k¿YË~zæ—Lu!fù·Ó+¨ò"†Ó@ÿhF¿Œ]bªæ%2èkØA‹8½ù¤®rˆo‚ÉûžÃ”ŠcGƒ úÑ„KK¹ çµÓ#(wµóÖÅ–@`2pÊ È¸rö)A©HEÛ?eä;<ŸÕ7ºý´0Ž[Á!tæc+•JÀ³Ž¶=ëkç­û4Zbô¸î2Vjn\Ç#d=§ÝXòXtîä{âÓÁ èo7kÖ˜Aþí õÙ^nMÁ—lT°ØùFÀW4”ô”ÿÃÄYjã¨fõâ« ÀirËaÛ†¸5)IZ(º×jLCl£>óõ³÷G ‡>BC0B«o7[ÕB®Ý©MÃêIËO‚„oÛßMÄåµ[/=£¹õd.þ˜1”³!2T)³4öÇ$ã‡0Ý4šî¨ÐËPþãkƒÄ\ÙäròÄNÍë‚.±.ýuWLýñÚ=¬ïU£ôFØ+$2ÐÓ!n:½VÑØß‹Ä#Õ)?¡s9Ò-¸˜K0\àø“rÐÝž,Â]O£ó÷Ó«7<˜BkÕ¢„H 97…K18F c Íæùt·r¯\ŽŒ°B×ÂcoOÎË™Gà•Ð1f=²ÓWJg·ÆO»ä,®·•>I½rä}¨âb>þeØŸŒêâ:Êö Æ•TÅØ‰ÕÙõ¢Jçx?êï@ÚZÅKó»XÁÇרdøÄFIÚ”×´Ïw Âj ×D>~-øT³ þl)½9Ùtñ~ñ\Ø›1>ÔúzWˆ› D §ÿ«¨–EñSÆ7WI)ŽoÍ–ÍŠ«±Ù¯ÏpK«À|o]ÙÝÎÝ] ûlB#Aëšzß‚°*ãS¬¥ñ „$QȨ{i@]§3¬}Ví&&ƒ)’½äM{JÇ¤ËÆìwoÉ› xÜÅÑàm©þ2šòWkupÉô[¥‘¼˜TI*V¸ Üçò²:…¨ß £k›" ©ú¶ëÑ/ ân×>;ëï½Rbît l»’‡x&µîr3¿°õ#TÅòó©¹(N˜vŒcÄ |fR(FmH:Ö ìã[@C´»6‰×85ï(ª Ø”Ø5;(Cüë7+Ðë69.ItÝä+ i€‚?÷UÒ—L-ó–PÉÓQ•—8mAGë6uMÿdÓÂø ±><\göÀ ¢lb×l ’ñ Ëý¿êåÏF4q;Ï@õ@|sîM#×À?2‹|^Ï/T'Qïq»™-üšô·dÈó9mnµý ÿ$Z6[®â²×-èogOŸ‡=ãDåNu”‹ ;† › ‰TƒnyËùš Üxrà vµ¶<ŸjmEàÚ¨ýÿ-‘GTFÈ`} Ñ}¸ûÛz*Ê鯜0Ô†âÞpÞŽ…—kbë/°4g¯°<ž±žÙ N~?“ƒhi§Î—[˪£Iz›1ëàˆ/v<½õ©5—¥¦¸±e*á(Ü"V›(Ó«K×rˆÛÑqž‚¾þTNê=95qÛý©Ã}6>½¥kÚyœ£ð¯ ‚Òƒ?™æã#> <·*ºˆ>À}B—6¢½Ù=÷0c¯MNÎÌ—³Þª3ðyÀ´iWÑZ7æ[ŸÐ§„" ›(VbG*”&Îuãv¶*ïoÆL&qåuû ïvtfà’»{kÀÚGüæI=ÌOžg¹6òT ‰° à'çv3ÀF‚½Fo+ò_KjÛbóš?`…Èé¹/×µñ;Ò_»é,ðpGêãïæVºF–«0º<èâþï즡ÐG ˜VýiBá€Â\¸o%Ú:ŒÀ'ëQ®{ú˜8¯Æ*Iæñ½;šiO+|x“à"v#-ÈoÉ8˜»Ä¦-ó ó|BÕÛÚ Ð× ÃÈR›1´MËð.É“"2æoþª läou‚‹~Úï¤+k`BNa8 Óˆ¼œá§mêªÒÌ¢‡N6Ò×C*UqAU-0'ê(RÍñ{Ìæ¸Ø5OM«ÚôÐ?TƒJ¥$+"-f4 ?RÌL´³÷ö¹6Ür-6y§F,¾¥ZH¹j“Œ2Ф¾Æ&" ôà V*By‚ÿôŽ!³@ß 7IýÍhníGoÈ®ýEcîÂû—Xïk[÷G_Vaºù¬úh†t@¥\Á}À—ò®ð¡VušäÀ Å66ë=SŸ\OUvíçÒ%¢ã-²1À–dS‚À5á_߇áèÉÙ2ó³(GÑßÎz®ƒO¹»5Å8 qôDWÝTÑl„UÏlY¾aYìŠ~XWÐXµÓÀÖŠõBÎÕrÉ÷aíhÓ=g¦"é7$~ÛN`/²wé覎,)¬FÚ1€²óLŸÏžM*‹P …Òµˆ:^¶Sؾ=Éyž·ŠÞÙííó™(s/ºU賉¿F"oÍ–/õ×Ïå 6!¸ÄŒÁyEò7}îKÄ¥é±BŽ…*¿½L<¢XV{ Å Zó®¬)/ʼnµY<׉`;¼ã=w€½vpF:ªÝÞâ'1jí¦‚ßïÛĬ¾Ç%ŒuGÀù ¹ ì/ŽZ¦‚hV6ª¿óÎk\¬|Wª?PC…ê&—ïŒU•:Õ!ûN 5to&œ¦ùÐ×½, ‰Z¦ýÙ=ÌŸ‹È­•ûìô&·/Ó(%›6Óƒ{½®Ù¦Sø/¿Ý4aÇÒèç_Žè3<ÏBûÞµº‹iñÑýÑ%:ý,+¹óÊ¢h^¼Éi=hv#EùTm•¢£é~ ³ÊÚz¾ôùŠT æ­þC=~†'Á«•¸² û>h;Œ†÷ K§- å{©×ˆÀì$RPFÖÍýGUU4¥'ïR•0ÍUQ&îë-Õ]3Y…ï(p§ÓxƒPæaa%ÈÝ/˜;)p¶Fëëü`vn³ááxI`£'FeüνoËeF1 g4÷펱É"éwvN+ŽM›$$üõbgjÓŸì¿JÙ/%¦®ŸF©¢Û²ð È_II u²¬³ü½7ã|æu€˜:ËŸ±‰„BUÃ>¾4Ý­5lüR=å#—0–p]l7÷Ïw¿/ UÄUíhBÉA—à€Ø)üº« !¯œÒ\äx-@âwœÎ±˜¸ †3óª;jf‘‡%I<˜£g+BBŒùùVÿ¿ûm~ÁFd^òñùGÛgê Øz*ãªC °§AñË&IäŒV>øÃXf ™ä/«àƒ7=z¼Z•ª©R ä¼qÐE¿ªrö¢*f]Š.$i^ â^Ž)¿E'«8X¬8 ýyù•‡¾7síŒø,Sÿ»ð’ýY´|ó£Š(W”";ÞP¬ŒùÅî…þYfwömô Ý8ˆ …–z€Õv8¿t@*+I!²˜”OaŒmk³½Õ‚ÇJ‚žž¸ÓTkiõß'âï96‘a š *qOõü;á$ ­&±Þa$ëyæéìƒZ]€Ä9cälÒªpUÆò1>Â&Òl…sÊÛ5š¤aˬ7U(¬ªÚ2ÞÎóY²,Üð]tãÞ}½e-¶s…ɉr™³û ¤·YËÞ/‰ÙTŒË°åŠ·Le•»ÿF òIѫǾàeÈÎ5ìÿžuð°ãªxE®’H«6îjŸGÞ#œžŸpölœW& …úª\öGÍRg$±Èá ¬K|®pBÜnà‘XÙ2†Ü¼Cý*ËÝZÌ8X·t´‡68Cš»ðEž”¸WȽ2µk–d1Îý6ÊÍù¤yVšþW_…¬È‡‚‘7ì PJ^.áW/4º¬º.4nXv'}<˜æ[ËiË?x>î[UÛ­}†°Uú@7öNkÅ|R®¿¥§ôg¦ø1O¤~¡+VÍu)2‰•j‹ç"MfÆàRÞ´’³³íã“1D )ÔÅYãÎhwÑPá`Ìâ8ýÔ7¨—ðjÖÖâË"€OôÒíü‹¼Ÿ>$nÀö˜gÖÕŽÆKKÌJã0ÊÑÊ~ÇVj¡ï{CZÔ²JÉŠ—®ˆBóÚ€€ív_ºƒÙwµì;q%Ø#:èÄ5ÒÌÛ@4#_Û \—gê²ýsíq¯÷„›„[‰–ÑO® šØƒn¯ "i2õVC[˜H-ó†€O‹x¶˜ Þ½-𘜅lö£Aµ¹k¼ö&"¼H4:Ñ“)o‡<^T+H\­u-Á46Z/W1“šÙzkÅ®±Eê 4ǹ “—âÞ€¤â•g2Ñ¥'  æmP4%£Üè–µ6 @à¸ÇrGh²Áa³L5±Ï)MOJ^µ2‹&dÅ9–žRlFÒ­pÕv¤l¾„ÀQŽþiúIw?‹Óv_ú¤îäéBâ,=]§ïœŠ Ι‹­Žð#šþ(°!º£`óY¿Sì¹Ìƒ5¶­ó(ÞjÉ´çk gØ9Q_‚¨)«0뛸\åèÖÅÇÿDyÔjúÌßÒÅY©T²[OÒ©•8ñ¤,˨ª)Z¿]ÒC„|®­Ü§ð¨vÌ=oÏ2"=Ý‘ï›ñçÊ*ÉPü‹Ç¢“,ÌŸ``)¬¶6G„Ådϳœtè@ø'Œ&³KÚøl¦!ùÅ—³mÊΗ·îrŒbþV.Ý ŠœÍHhJQ£vï³,¬P7®HX©`Ïr² Ê!õê[<6 ˜ñ Ö …*¿ž0ÈѼb637Mv«Ã¤±ÌO9Gpö^a³W% 1¶PÝm"A©Ká& Ð3§èƒuÂ>ÐNÞv*£LXÄ`–œñ—-W¤ ñµí6<åÑU6>ñï×ÇÃøk û£ûz’‚ºCT®ñûŒW¥gúætªÏMÌzŠ²Ä ð#¾H-Ç\@œâ#—,ªù\ÛŽ—|Û²ŸNd A:¤m5F.j`Цр/¨–‹RWO—L%BW=•1Aqà$(ÔèjÈ4ß±%½\‹(Š+ÖýãcIýBg–Æ|…V9Í6ó‹+PÚÒHÒGçO #‹ZÈ©lîzþ{7§‘B>x~ #˜wæJĪºÛ.›X·ßÅ`­^j,°{YQø oøÆ2Å ¿¯ÎØõ¿Éؘ¸ÔÕ”ëë\/•˜uqb$¤-i÷jóºctÞ±<{åßëŠMäo}Ü ù$ˆyëK‹•5ÚRrýJ–õýmçMU¨sãŽùö¼¼Ja1l¸X1˜„n·:gî|Àèòg@äLOÒãûX–Š¥±ð6-q8v„”ý•: ùetNô©àEPƒ·Ì¬=ê4”g¸fd9Š„ÎM¶²êH3˜ Ä÷Ã3Ó®=Ýßjï¶['|Ï*öÚ7˜ž\Ö/zÇ-@•9ô%P‰k.úÌKò.N'Oÿ÷çCØú¦Ól;ێݘn÷;KŸòt›ÚqùÔYg(5äJ$u¥†ëÆù…Rô!³ÙFåRZ5Û¡Ò†‚eF°ûxºQ39—\,6ˆ_ôå°Nz„IR‡DÝ]4Î5| ïÒ}$ƾI„¨òÐûÊè‹bCxh•J/­\73TIÈq9ÏG}v!‰½«'÷E·ªxÄg«.‘€`äc^šÿŸÈjŸ­Ò6§h¸ÌÕNú°EXþtÍÊ£\•ž­È¤Á^ÙãŸÞÐr°Ì.< ‘$RrÃ=Æ%5ýu_aŒ±.›\å9KH)©‘ÏA<e³´à;l™£M——cÿ!‰„8}›Í$™k&¡îòÆŠå w.ßg;”®3×´üFn¶ZM™:®ün²WÊú(brÖèbе™½@™"è2®žü²‰òÎËr׃¶3…» “ã>68§µ²¤æ’ˆŽì©(Zk…Äζ³ËÙ±‡Ñl}¦èoyöãJ9eJ‘ä˜rΧqýsWÃË÷“K®æªÔÄp½ts¹se2¤e¯XÈ0þg‘ ¼Jñ‘yÚmø»«¿3%©›ë•Ÿ×»Xúµz’’¶ÄÆJ‡"BÏhœ>ˆógSÛ¼èèÍGB¼ˆÙmìýv¡Ü´b:>ÜÉÀŠE¡9ZûëCÕb9ö‘}ŠOQ” Ê•I®ðDn¥L¥ˆòñÄÇÒìlX¿éÉÎó®êÜV+OtEµÏ†~ÚP:ÎpkWxënæó¥yõÑÏa«¢ñlôv=ˆy³!öEŽša&"Ê“+•Óß\@"Rþ)ß·§“ër/<±÷qI±þ¸²¹ž|k 6¥r5ŠÒOÚ@M^ãÖ®OÇÜ øðÒÉ'k‚ƒ÷ÛdÂŽeÈl$ÎZÙ„Šw›4ßì]QVË¢[—ÄžXì`ú°{ÐA5»OÌ(i j`Øœ‚?áz>Xm@Ôõiu-±½¥‘‹ë¼\Ê_ˆP Ÿ7‡Ð1…WÝÌè1ƒü¢Ü‹ žŸ´ôBONì˜ötž8ºJÊNɺ©òY6¥EC¨}†‚FŽë€XAGÕõ5³%²Y»=tKÊ¢na°¦ÝSl·´¸õ{f“–ͶÄ9Ž8u[ù6•Ò×7uM Åî$Uj@,õOG[Ÿ¡ºÐ°|»V ¹‹®ž q­ #‰Ë$%} #9.¤\&|¸t›=Œ/A‘ðsKÒç+ÀË̱‡934"uL5LØýÐÙš,á•Êós¤*§Z¼4×…$kámT²ô_S{'dëp“Mí¶~Énl PÐ…YlØÏ1×ã¿ü¦¨…ús£('‹§}×÷iÁW]SèÀÆúÈ(•áÛw^)•ån @ÊÅÝgµ‘íÔ•fOøè˜/’˜t<8¹º+\? Lý2”CNŸ‹êÿ¼ÅlŠµÊ˜UÊè|R\ŒM¾À Õ{ñ4ðwãgŒ+"´”}öf’œh~ï5iÙIonB`¥—uJ¼Ê—ÃÄF9¨_}»>ë)ø ×vÚ²Óòb-6êœÞ4=”S©É…jûÐÈ´’B50cÉ¢A€ü ˆ²Ù%.a³lßÂê(O ÜL<5Šý–“Kc]aï Ë!WHC,–êF„õ‚O]©eµ ¼Š&¨¶¾'¶K&¹gÙ…»#É‘hº‚µ/ (Ôš$wa´+FÉ0oÁ‚© ê/ýߨnNå&¯¾åÖá¢$ø‡@yûëøŽzHSÝk-¨fbzÜî?ª3îme"^§€R9×fÝŒÆ8áÓpÚ.jUíØÖ/@ß]ÓUuò0ü2?`Ê•˜Ío,€ÐÉEI_iêëFR}¤ û òé+NŸœquÄBGFwÿ†{Ê @Åh2Ľ¥?0—«Ñ‡Ú”¾Ã8¦]ÏrOÞ”oX{8®Îg±·õ¬Y#ÿß2*Þÿ³‹<Ó¸.!tÉ}þ²(•nCpE‹VéI"çœ-þ6“ ƒ~¼8Ø€\mñÞÅu/‘¿ƒ[zfbâ°Q”R=·ýVÍDaÈw<°ß*¾¿sûé^ôBˆ™ôä¿tÞÙ³ï£Ù>ÖX˜´J ÿ±’Â:!làÈ»ÞÓ"WXˆ¾³ðøÌUBÑÆeTŒ"“;¼.Au=+Ÿݺåv;omÎv„Z1Ëæ´z4û¥?ƒ%úŸHØÒ¿|ÎA”Ö¿Ïþ!k0R©D9'Õ¦O`9”kž}myS¿0eNCåE½>=çjøÄ¹cÀ¼ˆãì!´Ññïgð²Ax”GèL@÷zÖÔ®0ƒÍÁFüH«A8SÖ¶E1¼j#]@– ç°¹þÙ ~´=µ3{X©êKö‰­l#óÿ±EF$©’€30ïç èŒnTZJ%# ØÑ0Õ¿Ñ”ñ#¿Žf*xÓ)€ô¼\öN<… Pd¹ÃñÁæœCó—8¦Ùíž#†Riå("¯Ä‡hŒçí¡Þ0›X‚_[Â%upµ± oü ­Û0:™loüÊ}öY·S¸:p;¦ÑÜgRWF N¹®˜7ÛÚ¥ÍccÂK T|ž‘ÚÒÍQu¤qâàc9AY¿R@5k©*!ì!Ñó|›¬ãhÅ‚‘Ÿ]¦ž¹?,jÌ.P)•É,AA‚WÅý¾b´(‹Ýo-ÍúТü“;ßšFŸ4®q²Å r»HKdñYB€÷»Ê=-^!vÁ½“b ¼¬0;ÃSñOÍ©k³×þÚ¬2e³ÞS½öE­q…fz¨n†º_TAD|S ÿ9£7sДœ\Êlé|ñ²:™š*îà ñ"Ê–HÑ…ÑJVY«é4˜Ó*kÒÅÔÛþá³Ïû¬í@ ‡]V‰ ™œ½Èšñ/tN¦X!³À |i—4š‹Æœ)%EÄ¢­Ðxµ÷ÊÜØÎ~àéyåÑX,¼T—Ñ`o^‹Ú+DœíVÕ'ëgmþßý®BâÕJðJj"gÞ›Õ¾¹%çL{¾P0b¢"J‘C„cUÛ7ž4û½òi) DW_'–L„ÕE3nkpA˜¾"FÞ7Æ„5øXøørëwËaér”¢fÍR²²£Û²`ŒLN³6Ë*«%¬Œê*KSæLj+ú” §ö7•ê¶Rd¥ª®Q,<¦p™Úq·L¸»qÙ³€/7Z}ŸJVˆó 7—Fˆf8B„ÁpU“ ’ÿÆ9ýƆ6: ^xèæO,õŸ‹%y÷Áª°sM¾îF„;‘,wŸô%” þîu_Ñ?‹Y-/=nÊ/:Z¿Æ"¡ÐV\圴Ÿ _OVî ~ϰŠóÿä² !+'”UÌÆ–à³~ù=»lþô–ÑàÓΚ„™Ôg "Úœ—+fŸ||6{j±ŒÈtpøLšÓ$OøãÆo™>J¿; ² ‘ut÷zeÆh°W²70³î,õqº˜XÍÁ4BGÆZ™UâO§¬ÕgŽýÁ޹š2Þ*ÿ[~`ù3'¨lAÄ€#á“ÀÂÒVʳ Ù-mU`Õ–¬ºNqH0ô³Þ?”«·dÊÿêŽS<S,’t82‘R ^ÎSÏ£ÑQ'á­¶ëìñªb©ô[Ú¶~H߈eˆ Å¢õµƒgŠ@ |då«õºÔn17©N…Á” z »/|ú£/\Š&‚yý†iW,I˜›ÐH¼¤²Å¥#•íMb¯Zéó©l­¡¶K]†øT®‚Ò^kMÀ–!êzÕ0pm 5¦ñ˜ƒTK×ÔlŸV%?O)²YüõNÕ°ñBVYQôÒ,ˆô¬(>€”¤ïGx"*Ê)©§žrÉl›2ôt"hsòÀüø%7WSý‹Ù¢¸¹aþô Y¡AÀ·LŽG›ý·Ößq§ÑâpÌöÑú’)18÷ÀBº‚wBŠ*„›ª"W*ˆWö±r®¾‘ihøbUü “‰:Chø"œ”·Fþlåßü‰uáß'¿#v,'UËNÍ..rM®X\sÌØÌºHb3ìôÚÞø Í <˜—òkfÑ9î<˜¡øæàEÖU$€Ø^1L·%¼=6‡]é®êŸQ+á¢ú„ðHÓ­zêÿbtq`÷“óq™~F˜å2ÁcÝËtÙÖ‘‹ÙþÔ¦† Á7%ï\Mí2±µ;ÏØìãs>tðÈíeÔùÊ •·µå“7Uç˲ÓЖ|¾½w±˜—iš™Ò6ºÒv!Õöÿ[vúâz$.~Va ‡UÏ*n£ûç¤D\0í\èŒO»3<,z£Cpñm?5fBÏÞ G2p=÷ šã’%mEtÎÖ&Y˜YâôòiºN á£CnXÙê»iû…«Õ ó¯C¸WY'sLMê:ì®T I}¨¤_W bÅ}¹£»•Ò1]~}·B“CåïêmwKÀbS¦(Ãø¼ì™§Ž#m Õ)+_Ž%oÞGEghJ°TÀþ÷0¨ð³š¿n ¹ß7~$QÚ•Ý8ú¯¦óúím0Ü1lóÑdý´Ë=é;´ãóL;]ïÕÙ.¯›aV¡W¸´ÇsïmdYpá£0¶á f}&41Í…ñ!Ù• ;&WÓ!<Àp£8¨ç’ýD 8hc\ ô º;}çƒ@´ÏþôGÜÝ(ˆÁ«U¤ÿsc¨Cê“ë&J5!÷JÿðìpÕ’Šë ëû4,€Jjá™À êîö§iö{TÆMÑC|öÏICÊåýൟËP“‡Äͳñ(jx­ÀŒÀ»î_ÔÕòÆþ”r@`“èÐ*­zÍõ¾ñ¡àÓnº33ª\‚ IÍJèR€úêâKç Û¸¸®Õ„—‚mïÒ„áÁstbŠUæÜÌŒ‹x¹Ùá¨éœ³ô–…JHÞuEñßÙB¼H·Šµ¾(PÕ–%ÀžîùãyH‘ßhœÿÁ–o#‘òß_Mòi¤ï…úã5Æ#‘5 Ijž¦ÿ]×âuƒØÙ›³T“:IÃ@Äj¥ð5fú§JœV™X Ï#œé­’»Ä‡<óÜ ‰7æchU£pr,«ï½‚²Ú•éj­Û²©ÁÄQÛ˜hh´Á¨ºµÊÃI¸¯Ý¿¸`wÁRµ U¡‰r÷N»xLNæŽy—‡ƒtÏÓ?Ÿãq|P:ü­Akâ:&9™0‹­7ËW´J´rO¸hª¥e$ny YG¿7 Ê €A.ß–þ˜é×nœNˆü+ZaÅ™Bç‹H‘!ëîð¶¹ •Ž*2 y=б˜Å ÂŽ,}þ =­”~å:gùzÌÐ&â«}cbCÆféÙhÒ…jÿ!PÙ]O Z’ïâ²h!# ¦¼ª¤NuÏA®N…w¾»aûëlS±ð¯Ú6xÊAÒ«Œ·½*‘yß°¾#XH<®ÄØ`§”y{¾x¸µ×—ó FH*5@ÿ–BýS–!”“ ~Š´ÕUöÇß|WF«28ÊYKÛ'üㄚ›…Õƒ®Ü-V“â›Zíý­<ƒx$#^Ó•OEr,þ% kåÀn%B6Ñ{ô3DZ8]Á„•,8§{„.ˆÃIä¢ëRíxêPGªÇ“R&ƒ‡OE9ûû¬sXS‹¾[-à{÷øŸ*ÛÑ^Â_«£º¿àɘraØŸ½ ÷Áï”I‡ÁéU™ÞKT¿B„_tSVLßrïózײg+…¤µ&_âFØ&€Éu{Bx<€чz8B[žÁB<šëKŸ³£R{Ïð‡èÅ=Ô°-H Ü~Y `9ýûG‡øÏ–þ×äp èm©àÌ*m‘$ÐáÚ'â¼°äïñõÖ<¥UÜWÎ03ß›†Ã±- Ÿ‚y…Ç¿xáèâÓ-çY$«e•À`zùÊê^§Ñ®Ì+;¿ñU~Åun†}ôSÙŠbûðèMa¶Wƒõ³IÛŽxreäþ PÇ'œrñY ?”å YÍái´Š‚ÄÄäÍ7äÌTMÌAÕг¤7”åì*¤P ìf2nJFÐÊü0^Tï³Ì=¼MÃÂûË3¦÷’”6£‹ëÁc‘dïÛÀoðܬ,Äcd©•gÉqÈý”‰‘#‡DLŠ’›íဇî¦gÔ™¯ÍÓ õP«ÏÅ‹ô~©c­H*o PW/œ}•…°E;‚àØý£EA“­ø¦ÿÈ^d„‚3»Rá:V¨òp.•1·nWdõq_tHærOº±â!rxŒjd7éî j¬û¹…Pñä XƒÆkPˆ­O¯öaÛ aB4ùóK™k!n{«(¼£7ŠéÀ=”‰Ø¡ q90‰¡íÚ…ª<ýÎ¥7øb‰­/Ñâj$`Kø\ÒR´-¨º¾(q÷]0@eiº*\™†5à‚Ï{ôÏšëO­ˆÍƒvá¾(í! 5SûTz4º ÊSéåüô†Ä(N-ìb¥SH;›\èòôºß:v¾\**«ï(;]î2îr=e“àø«„2H'ÃÞ 0oÞâ¹K‰h`Üm:ø=iŽ¦Ë¼¦¼Áq‘DÊŽ·ú!Hc©ô ­VVòFÜuý¹.þa¡ ߸øÿJ}žþŽa¶”cR…µmì0ßÑ)·Uœ`4ó¹zyÍ·×Æ'€ûÍ hVA Äz³eÉ#˜*Í `ö]DåXö4LéOëÖ@ët·Qu4²œQ3ã."Á"ÐdeºÄÎiô÷½;Í&ú+€ótŒ-^S¸»’âœÍb“Ö-GŠÂÜ ?M6â/L–Öm†úÑ…r{k„×A(´ÞºÌÔÝ"~È„–ª„3+ Ýùgí èȶ¨C¬.ÜñÇ73  v^Žtp6â)yO©·æT¨¥<ŽÆÍÚÎ5 4¯¿=çBm®#«T^¬ÝûPjm¬+ͼQó¢- ÷t‘åÑñÌ­¿{Ažh{ÉAô#áæ¬kž*SEdÒ—<½!U‹’-I’{r¸z3®q¶¤;6rKØgì’"Íþ—ì „rºÊèáå—ƒ¨Ë{âÀãlá`•‘ ‰½O‡¥·Št©ºÚ)sDÊ*á§åç“ÕÍÅ<Œ,³ÊWé^·H:$œHYX-*ÌRúévc+ÏÔUnÿMsnW¶š#Žðž÷Ä Qu!ÐË>L÷#ÖÜYëp¨$d¾Qr´ìR–yN†¼ÃdnÇ®IºyfK’òʘÁ…P³+pú‹¿_Ï»23-QÑþ̽ ö’ê"œ¯ã•}zfÈû:ñ–¸ÿ5Á¢0Ò¿¿ XB= heµMWͼg,9­ýÜŠp›-ÇP‹Î;· }.ûaRR‚?/êªGÂj_ps8 ÛH ¥èŽ|LݰÓl´á’=£v¬Z6Í~ƒ><ÑÞ›ôá)SGfž8;M$HŠÙ»<þ¸2Ç_;ÊTSZ¢dņžè_& ;ɱ¦|¼k)°aJŒ±5“®‚¿Ž%€aüÃæŠRXp§F²ÍM²![ýò×%qKkë{æoÁÝóé­î¸Ð®éŦ'b†Â;}êöGÞt  Ë6YB[´;tyluogÈcÀ wækÔ:• ñ¥ƒXÍΖÖ³¬ ÞSä^Ün¢^¥Hâ¹ûn +œrEVÉv 6–¢‚Rh–K£–X™øVr{GÛòŒ^pÞKFSchÄeà鱬>Ú½Uǥ唷9Ü8ÿ.½jù3§GÙ÷þágNŸ óÊã§¢òLcbélÐcì9_Chj@¡Ç €ýy˜ ¹.oge¡þÔª•<±£œÕ¤M¯íøâ»ÙÇBœA»k[G3ûáw’áÎJe¤(wkLMçÆ— ¢ùD¨tðŠ(“T3š7íÈ7fú‡Ô]ÕP(誃^aY†˜_Þï¦|2-2OçRƒ“¯ “W×c…5ŒQÅ0⮃âÙµ¨ôl®Š(ó>*xlžœG‚ wEv+ÂÁ† ƺneV¿ÿÉeEFùRnï*·¡-ÛžwÊy‚¾NæÒ²ØKH%Nøú“>¸û¦˜¥Æ²ªÃ7ûU œ˜i—¶Vói$ÈÝT{Úl ¶ aè1D¸ÁÿæE*îÆ@ì€~úŸ•Í×.U !Êbê p…æ…Z˨?!I\îVÅÃ=ÝøšýLµ,zál©•e^M’ëƒtg‰nlPñ o/ÛUÛ„6bƒÉÕðeûþït2²C´¼ì¬_í­‘Ã™{7ËΙ±¡#×ç‹oML=TÔI¢†±WFµÖ/²ÍòÈÜ8ÿ@e¬Aià× îϾ„XŠ‹egoérYXEê0è7íy¦ &êEk°C_/Vi‚™¢¾^Ö9Y‹j ê7(6b´ë&ìB4»góYŸ¬’s¯÷m::/  ð=?áe˜ñsʦíu˜ ë T€þû…57]FÓì¿Ùÿì´÷’/Ô ±Î¸ú†×þÑ©9z 6T×Cën±wçç.âª!ÕÊ8QâßWÞ—Šª*LßZOK‰Ï¡ÓwÒ2zOIžú´RÈà ³ô§¢‚§ùôT¢z énÃ<(ClÁ=°Û@òì¨;/‘{IçèAF:n'ÑîÊbº5}–?›Õ[Œ“šËPÛ•tÿ=Ñ—(ìz>‡b¸Î€”Rœ&²þ‹&£¥7M´>&Õ£-;W}'}Ñ=YÍŠÓ [w‘ç$àóZ3H‰B£N9aÃÞ#¶a2”‘Šª: ƒ)(foaSû[¤;¢1õPŮǽNü7ù#cæ}g"kXD¢î]XÂY£èP6UÛȲ|è á¢ßÅ«µüÁ4îh¶;¬ïidFJŸƒE‡F•ƒöÆvˆÏþlš7¯;~ ü5ÕòTQ%^4åä¯6_ŽAoÎý¾/a.Æò%pŸ­h†#y:ú„ Ÿ ‡´³oþÓ¨yûš+ûhM‘Xµ¹Š%Ž9Ç™‚d¦…Xúo¿}%Yî€H0%¹jî¼!L5K´åò xzç•DRáã'Cn 0už)†žü=|Š€õ–?ê0Œzد^‹ŠŠvA­{™O=‡¤Ô×àë.Ο¹ß\‹ò=ÔòJ§"ŽÕùœï¤òò¯®Ê0Ó¾ÊC/¤x r 84@9gv;"ž³òÓTr8Ý0ü6ñ·7`ý»›,}UIr.ۀћ|ÚgäcêlSË7Æqmõ; ´X]4(²YëØj Y/z¬ •2¬$ª6µìtYvß}é`JKÂ2¬²à#¼ÝfRÖžÝÄ mK ±œÃã,ï·®šÍ–ÆN.Ÿ'ƒóFQ¸¾ôxi.kM C>¹Yÿô?ô5žhrˆùÃqÀ÷äW¤>p¢!÷ìl„» Ò)¯5è ™]»2ocwq« ²[¬a¾ „K¸vÿZ)è£Æ'Aiu0rÅŽ÷’¨lÎ1DZoPøHzIaa2Ê ÞnOgÏpRQ|â9+MÓM= {ZÔ#Ž3N."`ÈB´‚Iz6ðÔêŠ>út9Õ¡ù¢3£làþZº¤¯æ3_X`šXµYq ­ì#3,L^]â`ß½.yÝÙ8YÒ¶}A¦5HKm³>×WN^;¯ôûs†uÐê¦$(‚4þ˜Ž×òæùIñ@~¥È/„9Sü•FâLgÍWOT‹ÙiG`mêÙnÅ=ÒUUœ2 ®ö´©F¤Éz7P±ä ]Õldõ¹¾Bj„]N³Þçx96Vá:vϳ“&;µÄø@ËC¬ÿï1åÏ5MwØcxÇÅÿd*ðÐ#%|Veœu'L­B­AIQÞs4—cë+nXT ›^R\Ž\ôøÞG©Ê²»™ÏG…þÍc Åß_§5¢Y:æXƼz1AGåÿOYP-tÁÀâ ¤ûÏvU¿ß-ˆþ@¸Ò½ÁCƒÏì¡H²|>u.™‚ÍÇ!÷;à |öZ!Ѿ%{j„®HÍk¸ìYR•²}«õß¶,VŸÕ Å¬$ñÚï[æ7µÇ\ó9UG–Ÿßñc$Æño éUêÙšˆÁ¦™óA]B¾³U¨‘ |´†˜fNž,T%[£ì}{7ÎÁÿävlB´†Ûˈq¹­ÌY<À©ÅpÖ+”„³D¯-Á¥­J9Ü ÓU°˜³l3ò,‡a ذs±i"q¹™hÊ5Çt3¡¶´¿¯Mv^ñq4†û™›m\ ÝÅç´0ë¬Ûë!S+<ãÛè+sO‚{v¦§ €Æã‘íÀ\igÊö+{ [Ù“ûZûÀ`Ø!ï$ÒÊþVAZÿN »FJÐ ¥qòÀŽÙÞµá‰hÚºÂè~…Úbņqü™º^ÉÓ½z8¨8h7 ªøäƒH䨮úH«¹yÄ×m§~OB(ºßäÚjýÊ]HýÕxqÇé,…H1 ©ž;:ȱÖ<d¡ÄÖ£åß\2êºZ~„k»W+dù0i J¹7Þ…“ÄíÍ`wç|Âç¬cÞ›£™•¤¹€KÛ¹o=è!_q>ÂÝèp &UÄKîà`W›2EDq-;sv¡‹hPïó^õŽúö´5} c{¦ïÿeˆî—¦šâ¦Þ4«F¦'Ÿ°Fæù¦\­[ÂÆ/Ã×™uk`mºÏÏ ¡lÓùoÃGm>¦qò㉨I¸ä:15ÎV1‘i8;Œåõ @Á'ä›|¿ÀpæÏrS×ë¡ ÒæP¡Q…x5¢Ct±S!þQ‘Ž÷ý)åh_–ÖÍ‚êy€[a×Å3ƒ-ø$ÇØ.–3,4… aúí!à¤^no¬ov(ò=ÆKKJwËÌKq_ÿ§e^ì±WÔ³;A+¥æ“Ÿ] ®5l4_͙֜Óׯ´I.‘yã'ÆD¤€4ÜI,ùQûøðI -Q ©è”Yd¨u²æ“›/ó.ö © éúÝð­Ü–ÈD¿\šÌÕ&ñ‹ˆ^ðJöª(DŠlCè|ïÕ+o’ £ cþP<ƒš]ó‚“Ji -7Æ5aks:êY2u}§ó7¢Ö(Àý6Coœ™³ñ¹ß 2¶œÛþ{%ªÉ±éL=Q­Y33&Y<Þg¿[úÃj ˆéb) Œtéö¨ç!h÷;ã½UI–øÎ’ŽhI»ìá<³Þ$",Ó­Õ š™ÄÎÌ¢Ê;¦è«m“¼ÛL—‡»Ðd øµ pÿˆÓg›ŽQ•柪çÜøî!½¤gZ`wvT·‚ú¢]cmøÿ% Œ(&M¡ª¸ônü•ä&ê©è4ÏtYçKêUµEôÐà[1øŠf³Š?þ½Z†ðoÑqœ¿ëskå”4Iazw†Â˜dá6›ao¿NF†jrqY9Þ\*9)B9öàâL-nhXžœf=ꞎ§V¸®:ïe[²r #cz1‰87õé%™ÆIí ü3Ea¶ÖÄ‚îLfàÛÌ­E¼ÚY¼{GNxUaxþÕ(0)s†®?fi{™!èR3/Wt¸Ù `0as–z;ˆ+@ž¦õNeZÚײÅ"nh¸àˆÕר†äY$!ú+ åФ@,/@²Uä¢n±|MÕ:ÊHJ7Û¬+ Jýûhõ?¹ý£‹pýw¹Eã¨Ì“þu¬=úô{ÜÚ20¬dºÞØãªt雋´ø¤­1£$½K²[˜ÓªÛî6»/C˜?’è’ä¾O{…2¼+Ø=]Ó^ý ú­åã•0]EOÕH“ý=¹‹=³Çñ¿I=kV¢'BçÆ^"·­@èévNÇwŒ2&äÒÛÉFÊZ»ù~‘&èàð#aºåµëÌ3’dPè×1é"bæ¾ë·òn %ê‘qä@W%ëªÏ­ZgCîõX?WÌ÷#Rî¶æ^Ö€‚|˜’ÚRWn€ÅÿŒÎ³`ÂÔ·¥<¤ö·‚®V.ºÇ°Ômʌ܃Y¶P1‰,iAxiê_äEªžàRÊöá‰:óž¾o‹8hþöxtË»9¼Ÿ/gU:ñqØa+ãÉáêßP¦ÂTYM±ÙóÓϽ'WÎb~:ÐÆ^7"ê=)pq(…ͽ¹#òÍRßð)“2Êog_k}Ï£oö> °ªÆh*uçäâ‡fۡȯ]¡}°¤™:vÜú¤ã]H^N%Áâ­— +¹eÊüÅœGÆe!£‹xø7Ù4èO*oC¢#Í÷˜¹e,ðCÄku¡yÁWÈJ ³_¼y§’|oÅoî-æjàêQœÃÛTþkºkx-©Íx[)A¥t–‡@øgÙíÆ©¡ù*%”ÓŠz5ByDÐ*}k—© 7´`¤—ûÕœW>}Ad¾ e¡È2œ9°(ŸC[ +j cÆ~µ‹Rô”ذ›=Ùs=òç‹)w¢ ±öFÊlÚ¬ÑÏzÚ{°j¬QïóC x0çF%éh$‡aßJ‘tÆðžrÛVùîvÓÝyO½Àl뇺öÂ5>ÕHó/ÛçyÊ—3ãÊ(%1¿Þc‚ÊdÎ>œš¯Ew‰Öõ‹»¹hŒG¢Ý8£Xí&Bê²¼¿R3VÌ0…çnÁbY{i¦-,ª ¨iù.ºy±ÜBCÄ©º7¬cf¸+ëÀ&¹ñqøTP?ÊØçg!É•`lÞ:‹ç¤ )— ~!ždd‹Ë”ª6`µn‡  ó_’‡Iw1žôò&<"SwüîBuqG(D•PtÙÂÂ`}9ë%ÍåE`ÅÚ%Ò‡­èSÄB™”VfÜH™Š;Â̹™z²:ÛNn½„"«ðo‘ÌŽ<%ïµbm1¯DŠƒ »rJð‡.¾i5v±K4ËêyŠ”*ÅHx-{ÈT5Ví‘‘uƒ© ³U¿Âα8Dôw̶¥Žå÷rä3»§Öðo…’ÖY ¥ªÄ!˜þœo5 ÿ=¢Bï{+Ò1"ÿr:å:†Çiõ0ÎB$zÀÐC2T±@þЗ9Yš4Ÿà{65•í`XÞM|ó0³þN§#ð:äZÒDCµÕ§¡ˆÝöqÕë»mý®°b=nc}VÑêX¶Õ“áÍ ‘4ѸàùG¹> Jg`|Ã÷$r»iØ%àŠ.aBCš\´SO*fÈËT)¢ÀjG,‹fN%›Tq(á¥÷!J—BÇo]ánÿà€H;Á:@[9Km˜p"aW2L¶¥|`[<¤ÿQä1ãjCúÜSŸ\L¹˜7j2jj1Ÿ'Ð ûrœh»!bk+ë$¢2ñ¨ç侊3!ãBáž¡òÜMEÈ5¡þ…jJä% îh‡5©ØT#~ð Æ;Åk¼Î|gF|ÝÊ{ÃK6z[Ƈ;æS–¥Ò9ØÛl »p»|Ô s …í5'~~HaøE•RŒ3/kËHc ψs ØIWû‘òÆàˆTÿV‹`¹g:êÏàüå6ìoÎ %<Ä¢8•¹ž _ί;‚ûÄW× /#x%_DJÝu¸òô€M/]%ß_'ÌÑðòä€Ý–°L‡˜Ÿ]:0ŒÄ?Y-ç»Ôùóá{ádó’5D÷ýÇýñÆ}úAÓ<ü#ÖmþÚ"ŸtÚª1AýòáÌÀ8±rô^Ç…¸YœŽ¯¹æ(êïFzÊ$qÚ XÃHl Ô£%[Ãd3~mxÊ&_8¢ÿ1‰Ý‘ÔÐ Zð“«BC£æÙá8¨ÌÑRhÍìÜ àg 8~)g N-ævb¶n•-•|¦Yì>”,àä÷ Ýe@sy¹g“سzw»rèÿ`ËØïFí¦UÑn¦ƒ˜<Þ¯²V ÇS¨'7í˜g33U}£°l† JR=UÀ!·HJoª6̲Z²ñtŸ[‹I‘¹@ã46´²Ì1æ^Í{ý®éS­¯6Ú^YˆG° A}Ý- û7¬Ä]OsÇ"apLBŘ}xß\­~Èp€°D-¡m²‚ÿÿ­TŠZû´2öÂíH)|,UÚIC׬6gÕJ6¡•ÅM¦ñò ]b0ZOwX\OYš3v,tý-½6ø‡¹ jc#pž}Qi3FÉÝk)¼¦VÉo!rÞfŽÑ©ÉŸ Œb™-Ê5êç¾”ìóê¯úDI¾rUýŒÙD`bÒQ&›ïr—ž@¹ÀöÆ’10¼„Ýþ€ië´$©Ø)›Ø 9Aà!Gû-‘T§ gÆ/¸•ºwZ m‘,Üšjô.øbÞ­ùbFT‘%®wÆlK^i¿v]‡ûäÃcQW© °»1=dŠÃcäN$\ ÐˆÂ—%Á¡8ƒ«O¯ä+tŸU‰¸ŸA¬N”Æšê ¼/¿|»B³þõÆ¡ R•žTAñšíþá0QÄÈšÐ×1 ý±åê Þ©®v¹®íÔ™« ¸œYòÌ`ù­’JO@µøµ]9e;H¦B!®Üešm}Õ2;û_Dò¦P8 kªü ?Ì·Ѐ_鮲¿“D;–Ü» F´Â:ƹpoº´`ì—¯;”%™Nà[øÂ…zäöO»)5õéwÚ翊zè}ca3iÉz\XX‚aWVÈíõ # Çí‡áÚøô΀"•ݹÌKÈ,%¦÷o¥\ˆu׫IµÜ\'rçá#´ ÌáNc¥ø|¶ã“Ÿ%¢Ì2‰hÔþëº4àŸþ—z ’väZ6Z̼»òŸ¥Sùzã`g#6ÙV“ªé§s©cþzÔ‡¤¹å§”¶þ¾üÛ?‹ÜJÙDXÍ/š‡,®pOÇù0K2Í+‚…Õ#Ëqï À³¸uòÅ!J|CÜäõ¤a"[;Ôèˆz½Ÿö#N¸]qñº40G}ÄÒý¿•ÃdóŒ€ DØæˆ8^íK7gMsü^1Bl‘_G$“^Ž›[è*•¶S=“¨Ð^JNšï2ÌÎ2sŸö9ÊÂZ4‰ò',¼CøWóÝ.úVÑh§Ú7gÈ• *¥úµ±¶@¬[d0m`ÄR§ÀØrŸEÜ WÌ¢VæãCWê ÃÄ<ÛÍg`ý?(,Ë´÷£b«‚cGÝ =¦ˆætÛ>JhÕIÁXš2_ @n@BUWC¡r¯Åtc6øBôIÏ=*ýÂY¶ý¼¢~‚=Š;®g£íÈ…ÿÞ®Ao#Áœ*m D$NA=4"f`÷&7H°„áÛÛ££,øß·è…NÒ:Ú>õ¿8ã?« ÚßFéÁ|ëxwé‡Ó¡>nQP¬ÇÔ‡Z ¤)ÙbÄeÁ˜Çä=žù1ø\ý¥bL¦ÈŒ¥ÛÈÖ ]xÆü廤1l?ô¶q2¢ :…ç 9¨4"†kíF+·&}ë7:’ãq–âw+€#qëÙóÕ”ø*!{²ò/ëŠG0:µÙPδ%A>²¡°+Z=ñãsKj´à¿ZdqdÔ•,‡§Ï¿š¬æiü™ÈõÛž†/anÀÍÃ#×ÌA”º~¼Î\÷ØôGj«s¨™UËr¹â×ð‡ªw+CƒAÅGQW¦h”!WN˜Ù½FÅ‹dø/]@ÁÈÁJ2ÓyÁ¦Ú¾všñ(=ì¢=ÆUÞ(d˘ÈÏS°„ʇÊ1+Éum´âž~Ù®ãZâGõo»ì7ó¤q.YAÊÑž1eãªú£´äÛד¶þÊý{½òžuî’]•ã«¿]ا(ºÑÇmÐK9_~ñ"º ìÝë óÅϱn©|²ð/»Õ·žEpCÓû—‹9㢞z΋õVð#ó*ëJÃö‘^‘ä%h°‘¬øŸE3¯™âªÿ$yûÌ‚7™ã_b¼Ùïo´ÿG*ÙcSEÔš¥¡\ ‰Õ‡»»YdŽHsû§æh#z-­¥|˜¯t¿Wž Hž$V¾Ìø*ÈVÏ`@ä`’#óhSmFbèåŽm¢™XÏ0”e3‰l±Þ#ܱuÈóÖÂU°šA*“CÖÎ’ßC" ¼Šf7ÆUÄIä‡Ì\’&5@Õòý°S_+øA ÏBâÙ˜¦xìᇅï:M¨ãÉ]'ësôY¹'I ‚¡…ßÖ?cïrà5Éâ²N_šJ?ù6Ĉ;¢¥Šdã‰?m457Úðá,Î2f4+Ë*ƒ‚ì!éî8UþSŒˆ5.F:*íXµx÷ù¹Ò:˜~[ëYÝ $ÿ­ c5ß:™ θ7bœLÉG€-[¸ »¶òLÄ&`=ê÷]‚uÍFNüíEµÅnò2ßܨó¬Mú¡%/@øpìåbEµNj¾3£†¸l1Û2*ú'ĤÎ뜕„JX¬‹æ—²¯L[=YÇnß‘üî+/ÜY\ pþÇ™ß}÷öògG~ˆST"ûóŠI ´ú²Ex¢Š–ì$QT?MÃZy»&zÆìOGÕWM ¯Sö(ùxMùGîBè.¶‡²Ë÷bå£N!±0Â=Ápò<˜ü«5@„¬¯¯’ ûR„úÕ¤ç¦B%JHÜJGŸsÖœiÞú9˜ŠiÚe DˈܣhY"èmÁ­J5ÞÁ)È Ÿ?ÃKóQ²ºÇ<—´Ó± ÂqÿŽ.ù”dö+×™f#öq½ylÓ]ZBùïlTEýEE†u³aÀOÌ&(ÕO-áà¾ghË&}}}ܤ¼ ØŠü|6;…ïHõÚDxÎ-îu`ÑÝ£ kæØ¡H01·Â]?2mòëÙGõ¨Sw=z§6µë ?RE=ѯº@ïÈà$»5®´¦Åïu¶®‰Ç1hðùH»58¨›"Ú·wYßç8sæ~~»Hí>%4'ˆ» –íð¡¡$/cr%ûÅÉ+ø1ÀÙä_íkŒž”¬6³š3Û äÎ7³¾WF,Œ™ãÀR@§Õ^ŽÔÒü¦O7µ„Oåî÷ÄÁ¨@EôüÛÔ«HïÅc[ô pVºDµÝ‚À¦Érð”ÐqVÛ*ºåñý^ìEÇ,…Þh¿æ¨'óÞÖ™vEâ›gÎ$ñw±+îCÇÑrÇWI,‰_šI±nŽ1”-:¼µêÈ·­ rײ¯"J““ppÌõÐ0SçPÏÎÙþ2:ùæÂšcW+ĉH?_M96 ‚ë}Ç/áežÕ²Q2¥¤ “øhá5f0j}ñœî>dŽ^¹hƒ ‡ îš31—¼AÔ©w æDËØ'ÛF¸@q{«ŸReùõü-Ä¥rÍA—!õ®¤´‚R3º‹yæòœÎw÷:ªµâæÂ]©±×OÄ®PÝ+mþiÚ<S× \èÏ屺IºÏ’Û×-p`ns?é`ÂÝÆãß=ÛCë¾ÏÄÌàû̑æ{Ò+2—”¨ˆÁù¤áØmè>éÄë¨Xuú'Öºç£w•2WSI¹åŒl)õßÜ’ço”L ôÖ¯ÀA¾e§‚´Üª^dYfWg—äõ1Šv…"DQ?p4ÙŠ^õ@iûÖ@(ÑE0›d—%‡N6KŽ´`¼@„ì»aÕÀ¡D¾”J·6=NÞúðû<ú5 å4f+ŽŽÒãuò}‹žM É,%ÍA•.åzÀÍð‰û¼‹9qá jŒyÎskB¾UÑn_ŸCØð£±Ø}{»1ô­"o`.÷ü7f¾LLoÍK1=ÇBUÿ|HT8È”‘Gt·G9HcÝS©T´‚N ‹}0žàQ›M”©Ñ(ð|æ S¤éL8_þªB?y­º‘uczoŽšŸîœO ŒPv9RíËþKk¸ƒ‹£öøMØ›m%÷ØU&f ,LÌ kµßâd‚#ƒÙ2º8Aú¦@Ï]ùÍu“7•= »Ÿñ6þÂÿ ꀇžœ÷¿ùˆ‡äVÿnFXN-Ï PŒ*8WX‡¯S*ÐuSOƒFøõ_C µR”ú¼€ÃF™Ìs¬oêÓénžNÜÖ(†ê ¹Öb©ÉÌ®sus7×`-è7•]­OWbØ?fÈÙ*˜)…=uct½±Â]3­ÅH]±ïsØõ§ÇJä)Ž ¬¢3é~˜FÚ•HÒ”ÞföÑ4Ï Á½Ûô޼ȳœ€ i!¬ÿ.öcæÄ¿syi³Ykßs¡GNøn;vi»~ç™BÕ"æüšUÊYú~"m¥œN+Ô5r¾´Àâr‹¨fé5¡¬»P¶4³%–‡Ê§þøªXo%®®{2w1Êä:ó†Bæ¡ ÕXbÏè¸mU¡=÷IÇ*ǤîR{´peóœhiÞu½ÕÀ>OÓhº²ÚC[µš‹€·ô¥=?3ĉ0¾.§q«–Ô aÑèýÁÌÑÍ⬠ϡ4ýó M·¸—2¹RêÚÍáÈJCº n< Òþ…n{í¶´}Ø:m¢ã̉TÇ ˆU(hÿßû€ç:ePßv2œlŽò¹aÐ%£vlÜnbÃÈ‘T¡|Pó—‡ðÆ¿+!–j$ÝÀįÜAhxØPŽ‚V6sÏ›=¤µJÐULÛá9ØéÂâ.Ô«¢ÙIñÅßÂ. çºÀ® ›à–Št§ï rj šòÓ½YÙî‚O¦iX=4ë0­wŒs$ÁÃ6Ö(QZ[e¢èL!Áý,9Çsìpuï´Á×Ô€Ò} Õ/u!ß \;U`žµÝÄW»óÏÎä>Œö¢Sï• .åŠÐ‰Ï{3ƒWŽá‡y Ô½¸gIæú™öZ¿¶®t «¬ZSä,M¨në~Ã÷*¾ŽI ¡gón·Ë<—ž-–­6¿|«X¶/¯×ãì¨8E{3žäëÑÃ̺$¿Eäìè©Ø ADÒ°ÓÞ“kœÂB5«µÍš‹ObE F*--阬€A¶`6¡Ks.Ïÿª ™ÏÉd8Z'½”ç($Ô“2FJ?¥p² DNK,Ú,8X3ŠO8”Ö]¦-]…•©“ª›+7cOkŠZâFÏP©±ê4Ç·ZwÖ‡¸„¹‰ù¸“ ø½cŠš;Ÿ±¯•Jh礃4Jj´ãWÆ„hyÕ¹.÷I®†ÏL€kg›â8/m,>,ÿzë”m$íysÒêïß Îb£]n¿¹‚¢:5zÁ4mŸ`ä—ʉ¨9Ã>àÆKh+± @n:6ö'Ñ@6† ב²QùÑõ•G5…ÓùkÒ!¯3+à«Oß)qݧ9"Å(ZX ÒD^èÍC[h™k¾Üâ¨6ÖÀMäù šKGœ X~d¸àR® «ZÏy=°óžµÈô%žþ‘)p‡"Òiå<æ çeþYÚbÒÖÛâwl‚Ò)&©¯Vö.'„&z$Û ½×FTis¥kÕ€âŽ$eû¥94C-lDüÇ£ A8Õ×Ý=F°O}ãèµ ÃÞuƒ9³’ÙŒ÷X×%4r—ðAe'k~EqVÅꦓQ þBU/ëµÙ‹S¬ZT•׊u.>ò>Yhëõ*¤Kaƒeìë`#¢òˆ1ÔÊ=Jâlž¬ ôÍ"ºòŒó¤ÒÔÕÞeÒ{èÀòs¹U昕‚‰g®²$ •ùN¯?1ÛÁƒ(®ÞT:šYéÞû#01DhçBmQs`d/q)l‡WJÍb¹¤QægéûÔiÛ•®o mXª+)ÿ5ý;O¿|è½ËßèÔ²èÈõŸN&Ĺ}ùíÉ\Èùjö;П“ïÙ·”¾KÍwKtBdön£ŒS«éX¶’õ¢I—Œ¤mm©î||’\œzÇ)lX D[/ ¿ÝUº=Ê~HŽÆ>&áÜÐ5CfŒ` Z¦µ;à` Rõ©Š%¸- `¶ÿ}n~Ø î*WQ‘ÂÖ;L `©5§©ÕÔGÍô³ñgnaÆ*ÁÕkpÛ9AÓÑ–>ªBÂØþbâûÝ•°úlèüxC…ªú¡ùÛ„g¾#º«ÞÔ\óÔŸ¥+T…ò/ï Ùù¥“r©Þia2#÷"‡|-+Ë0@ùBé_C€½-ÿ S¸ÐÅ7Ê|7»î ç«ÿ˜îruh’q0kJ¯Fb3OeX†´™×%°sagS¢<³7ù*Ty¯«Í& tcô¸–[Ýõ}!Çnñ­{¾v·>r¹a¦!M^£Ýn9ÕpS*Áõ¦cÞq+É!¢'‰ Mûª£œ‚õü×QC]€mi°ŸõϦŒ£ ňs#¯`ç›÷ ÍŽUo0#]ªKE.kï·ÿÖž›]U0Ë2Rr J 6æFpH¿¨r åãÏž)‡R†•ò­ïüºAÿÚ5¢êpÍêPmZ¢ø‘'wšö«™ÁSëâG5ê×Ç"#ËP–Ÿ%mŽúlÈrÈŒC°[ªóå9^œ¼=çÃÍj­Æ¬Hó‘W³eɤxÇ>”fŠÉBD´™&Hñå@µÕCÝ@2:£aüZ_TÐëåU[½'ày¿3mtÁÐÍK7îrò¾é­áÐQ‰Ë‰e†zá€Ó0[ê\öùÏ:¢–R ر$¹¼1ëÿ ÝýGSŸL„L!üLqõ²ÐpMÀ`02Ïuè’ƒL1ž›V‹šÑ/o<Îᚆ•”WŒ2YÕßâáq¼ýré×¼­8|‘ìZ¬*_ëâ éΕ´s¿ÂTV¢ó7¦³{w¼Q¯€izã;]‡ãTçe6UN–T§YO°¬¢ºça¢öªš/¯õ㢮ê¬ýí…¤¢OÒ|m2†6â:”…†‡z4É5åi°ìB^@cubFr%Ø )Üâ'A°™´ KV¦G€Ó횉¶ÞÓzš‡k\í&*øÊƒóŠX¬Úݦ˪úHX!Çn‹:™½K"¦4¥2Í ÕZñ£ù J*™¶azFÖ­b”=‰Ôr¿áÀZ";3ex÷/]QêÑÄÜ› †\CzÂx6'* ös²+6Á\¢¤§R  C«ƒÛ:8í㺨Šûš Iõ ÷i’7ÍIø·é¶Aè±×÷ËÏœËUN;WÜUê»8ù2¥›‚Eïm yvmxÏ…Ydës!G,‹+üÌ5‚–Ëciy\Ý/W[¿ðaÕe&¦þ['äã[·ž+Ô’­uˆ½i”±"âNƒÝóÒg:âï5Ÿ¼)'q£®–·eÉFàÂìQIŒbÌ—pøˆ b›ZÅtЯåu?á¹Å LírëÒ(nàøXG“m8LW:0 ßÖC2šÝwôtJñ€}¦Ð狊¸±ýpúY¨½~ã<ô/%,0%ç ÄÅæ}ô½+yë6-:Ž;¬"ˆ®r<…\\JÐNõɾOê`ï'CôÞýÚ«8ÓU#ªK±žp†ªùÓa~ë§j×£Bx³ˆ¿úy¬ù‰ŽR¬U+:øÌVì™_Gƒ– -})%~÷<ÈO;*åM|„¯×xÆŸÙ©a¢½ŠŽ_X!¤ëVË îOÉ÷[ì¼µñ°Ë^=•ÓÞOð!6šœÿ¹»tª‡ð΀laq™ÁëÉ•)ÓlfdÙÖ¾1ù·- 2Gl¹^”ì¢7ÙÚˆD¨!`Iò[WšÝ@Z"ôùó2ˆêãë‚€r‘³1™n1×ÀÇÙÚX€ì'½²´¥ðä’6©'ÞvÌž.2­)Õ€Ý鋾ç|Ì$E¥õÜ¥DSôÛ¿Ì4ä¶RÌ_S·9[ 4åuN~ö ñ÷g‘U3[5“­Í½Þbÿß8—= >m êÑ›@·¾<‘Ûå'‡q}¶BؼÙC+ñE1› º’–iJQ'b:œ*̰Z¬CeØý~&&Wêû#‰Sêç ¨ž =Û¬WÞ©¤'‚áÞUY¨×M޲GSf)Ëê!,O€¶«HŸs©C5K0¥ÅËk.’!ÏÔ51+Á6ãßÔ”{•¿ý›C]¢+ÆSü¯C ÉQþVB‰å6ÆÕ×Ïv³Ü1Vv”wûšÀ)ÚÌçxµ‡@j{ºÔ;dÍÎ&ºbÁÒ»WFpú–#†ôV… œáTU#¨¯žwŒ³™’9Æ Í£ e|ö *5‰ûÙR6š½é03¥Ú¸­%dV…ãø°ÅoY_„n"1? ¾—ÚqfT_K bª‹î°.n:y¶´š³%–býàŸQžÊ` ¹è»Ô*«˜ƒa-˜á?´Ë}c?…°uš£X8U®ê”¢#õûtZñX1¬V^ª5î=;ëˆSøw+Bž4=`Âã|Š/Ò‚¾Ä”W•#ò´ö¹8Ï}%tŒåø-¹\ñøÀÔNò“KyŸf+¶¬LŒÄu)¦ß™‚"¾rÑBŒ•U¨¨²ÈN¦§ÜW=¦ô[Qw­P-Íj#‘25`ñ6ß—ñ©£úäÿ ¢ t wœõÍ^ƒÃÏ;ÝãJ×c¦›Ž6z½v^Gö›WÍ-%˜®HÜLð€Âg.¸ˆù‚i›lbç 0eÑ€‰BŠåze3ñ6*À²$Åjº”ÔŠI¬QK­•]ös¤MT4_î°0£þVFMl×½ˆŒa,é”\±$þ¾n­U4ã9W$&ö¶|mñ  _à^ÀÏ•kçáÛeÓÆoÖ÷噯 Tô©‹Ù7¼ýi!΀xn³òdo‘{XO\UPe·ØùÜÕ^YCm6°™…|>ëÕÝm…y´«W:x)0õ6åø‰zÄÕŽÜQˆ.ª-^É!>ÐêýÅâ!Ór)æ1 Œ~ô¹¦~}§þE_ÖÏEÝej†]%ý EvqÚÚgVK¹òÏ«U0i°,z¡¢¬ƒ ?T†±¨Ê,‰ÇÏ¿€˜¸$«-:IT;lÙÍ>£„Ö’ëžžÕfäø¿£QŒÑbh¨\˜Lé ª“Š›º ´äÊ þïO$• OîÅ7ßñé;]ÓM߸¯¾÷än}¸-¬ ïúPž†,‘ôqVÈ6­G2lZ߆Þ4lÝÏÒçårVܧ‹Ûo­»Îaj7†MÂËÒB9XEÚà¬UÅЋ8çzòµZC^ Àz©€C)6íÃs‡èâªô˜½¨àKÔíÂq[ñª=¬6ÍË Q_³åàíŸp3OiZ$—ð7Á²–ÑÏ$½¬B&Á!«NèÖíXi´Q¥ºª«]¾ê«.Фը\[LB„Åt4$ìs†ã)Ü—Ë–ŒÀÑD›s"¹ª¥¢ÕÀå—š0þå̪S·mÐQ‘hxH‰!sg”´…7ÿl-¶J¥éM«ÍŽª5šü“µ¨Çsú%,Q‰Âͧ÷‚á¢Ë a1š‰lcîè¸zCò×Zv'GÕîIAìŽÙüÚteüUé_Âû«¡~ZôÆÚ5 M›ØÚð/Ò¬G¯S0wTc>ƒyJŸ0š'Áý’ô Ò€Æ&ig»«ðPÇ4~ÈbŒ¦ŠKìEaÙÔd][Sȇž,²ˆ+õaÉû?;†Y…Eêmi"û~N éµ›Cìá}XO¨…Fëµr¶~t¤"ÂÛáó]¢²"2õ¹”Ýyžþ¯„Í@£Úš!gÒ93]©Áè¤%e´&Å‹$$–¦é*xÉ»¸?Ä|)Ø ‚èU+›!°Sº_3Iê ·§˜7ª[GR{¸ÑïÍ#X:#ÿ2kÏPË |ç1áëk*F9RÝ /Åìì’¡Ç[ÿëÛ\vÖq'‹ñûæÿ¯³h‹¯±nMæ$<˼+[(ä~ Asm "¥Wõ+¤†_Lõ°cCH¥fèO"&žã•Þ’ŠqO†›ö¦9g&²*÷'PÕñ„†¥9™HVeEvÔíÌ}±Øôj_ ÂØ¸×ÿÓÓ7âMß²fþÔ_io“p×VÏ9ÐDF­ƒÎv~œƒ/¡J ;˜x±*(GôÁ…y}X±y6V«UÚ­—ë )Ëp¼uŽEÌ´òŽ€(¥t~=÷Ad‰F½$xŸÏ¦!´$O‡ucj „Ÿë™Öeko–!]¶fj1ÍL|ìO¥Ó3Öã Œ¤iÅA£1±×šis_ë6à Õ%0š q«^+ËEkû– çÛ¢ÛÍ¢q£Å‚ùìÄ’ä•°c§HÀS¢M¯¹&§¹l$[ç9V(ú“Ú—’y¥'Çðáp™”Ÿ:ÛKðþ¢ÄC!÷u©Ä«¢Y@í zd9ÝÇø¬K­T“öáýZå̱@ óëÁ"ÜrõrSÀ£Çó[²â> ÌQ²":æ¸MQ¸c!‰ü »8ׄfúí»òîñ•½ ‘ûWÊσDdTõ$ÍÄä1Ï9¹b$ ç=¹½k‰G 'j…™cçîÒl‹ny:NæÊ>ÇUe_vƒÈûV Ï€>tJOuZõ"n°†öý›!ó[ a#‡Z!¨l™M{®0¿YATû‚…@ÑJŠ~œmWËþÿ¢aËÙKÊ©\Ú}¦¡·Ú¢kœ™s‡¦•åDWÛ]¡48USÚ#¸ÁÁ"W”N/˜SG>¾±›ÏÐ-(Å×H‚Áä2¨~úR0Ê)x3ÑRÃ2e*pšÍ.Ã7<Åé–=¥I O=œ†’EU" NÈðk^ŒýÅMŠo”°Dd/¾H’è2 BB=ÖÓVÉËg×ãªÞ• Ò ˆÀqMj¾¤ËH J³ÍëÌkí|•¿ ’°‚yZóNú&t3ÞâpG÷©/ßú&ÂTó•ñÐY÷0N†x5rT=%/'zˆ—Ð~i¹áT¦aA =ÞÃð^²ß~.ì.MìÌË3QÎÐ6¦Ã²}+57Àù‡”aÌ[³r@'©ÈCYA*i¡j?tO‡ïÞíAû¢\0ôÎpáùÓF%Ý}{¼‚zvëÀR°ãë¤ü#öß¡ŠÃ/Ù5¶ÀêilicõY±Î¬iP×­zð&7¹yg©{€û/~o;Þ¼Êñ²© [ÀJ$攜ðuÞ[¶ Co@˜Î«Ißã¶÷¸÷õsè±è!Eµ#·j–Qj—ñEæªyª‘¡=ë²Ô5žóf‡F‚LjVê—G⹇®€;ñ„ýh"bAë“þü`„Ü´üqÜGFcìo×ÈöÓ.¼)¨ÿ¶Óå¡B~ãAY6!Hæîµ_µÅ‰[ Ëû“Â-úÜöJvÁjNw0¸Á+‘)(I86"[ÝyÝÞ}yl§ŸÝì]i†N1S¡p„4˜wKs—•oy†‘÷Û9=ÂÔë²”UÎÁ•ÈŠL ™þžíÉ æÒš›±Q´)Ö]kR»ßk £Ç »†Æ½‘Þ¬ m@NlnúÕSlù8§9Yª|Ðô\¼Þåñ Þzò2ZwÄtè Yé2Ëñðá‡îyï@»Ýþc|ÅĦlÒÊV¥‰øI’Hiœ{Ê·Î2LÁøÙ±3e8“È" ˜ M\,<õö’ÅìL¨UOÖÑa§5–«·_pÆL’•;|që›\Ži p˜‘I„õ»à‡Vß{ ˆ´Ö‰ÈáÇé˜xf@X×ûm‹å`Ùí¼dev£ÙÕ• „”6Å¿!sÓcÐDúÍÔ(ÇyU@¹¨þ®)õɰ•³ÏŒ"dÒXMŽìŠÜ>eÑk¼p tÃ!˜;¢+/ç ȶ\ÙD1Ÿ,ªL-&ˆo©hH}QXŽ+訜$ÏÍ\~<Žìô?4oý BV&à°²yòäÛƒaåÁ¸ÞÀÚ0¤ŠD¿›¢sýYJËÅÒ_åãÚKßW#ƾ±W^)pf^Yßfscßh`ʆÛÖ¤:—“N«¯‹ðÅIz:ÀIwdaÔ¸)2‡ºãüx‹5®$x0û­ÜàÈ]ïqWc”¶Üßë 4q--OÅ¥œˆ++1Ny•Q5<8ð®ŒÙ€Ø Íþ—ã¿™JLØaœj þ#Sié_TVD½iJÇQû`)óƒK>IÔóûˆ¯4H}§ógÜö°E }µv“9¼Ãxlÿæi:Ãâõk¬fœœ®1žð?LÙ iĶé¼KÁò—Cʺ”ä °§$"¼ê2·Ê¬µ'xgÿ"`v¶ðÒI!äž­²I>¶×õzÓéÿ…Üþiêdô£]@A¼ô™)[ö—EÖÍ[Ïà~q#(3S…îøŽ»2ý¾ç¬u÷ÿͬ,š”7ì(~ë.h²u»žH"W^ ßZ}þl‰±‚ Ñ4m€¹~ùz¦—L­`)ô¥Î±žSç‚ÿ2>.>,Äë½Ê+Á_Óœ2l•Çfy?œTò‚[uê¿F-ñ\Õš 8 yç`Ö²êÀÊy4’„“CßÞèg"ÿ ‹´À Í ™ ¸—Èq‚õú93T¦%ÃÅ}¸[c½ƒeVV°=wë»llêÏpï‰2%Ê®‚r§ÓOÄ86hàǧ~¦V!²"ÁgXuÆ=á|ÃŒÌâVBîÉŽ«È¬Ñ1z_xˆáy[2Ýl®‹·—ú!W9Õ»ßLËd=/:&5«¯ÇkQË+×Y9¿ ÓÜçW÷ÉŽC÷¿^ÔäãÅùAó앇 è½#æ$V˜™*fY÷-oâ(†é®âńν¦=Ѿ”£È¬ ÿé5ì?Rù}ä4赿Ì,Wéô—2›®˜­mÇ«¡àƒ>´öð|Ö®Ó#r€…~êÀY‘€x¹~~÷Q2.S)ý*¿Á̰ÆÇ×’¾hÒycxÄrµsÌ)ŽÀ4‰œa±t¦KHiVBüo2™v ]G$-¾ÆÖ}›E”[>;3€íN/4LæiÚTc(ʯC`/Œ–уÖÂËÍ x˜‘ Üì»W¨¬ñì’˜P@WM¸DmégáC§Xn£üîû³ECÖîc˜OïK-jQДkî:pC£Ù³ÐŒI Å™¢#3Etî:úq ÈSƒ/”`ÖMþIUá=ø˜&½ñë˜BÔ{o5Eøòz²¼VƒÜ;Z~¢ ‡DKT|Áyôª‡ˆp=¤>œ-šëðƒ¼w¶Ô:Ï,\5Û^/!Á‰#ÅR#f0 µ>©„Õp¿;µN Ø–Ž|²mè“ÑiÓ1ße:å=¸òƒNaüe+U; ¯Ëe4;Ók¬û*Óq'uÎØ7­ø_=³/0ÜeqÑx„kÀÛ`M<Û Óþä¬ 0ƒ¼ò"^Š„üX _àna1û€@k<Ìð•;ÊPKÜ ›õì¼2(U¶H²Õúw'깺EöaE=¡Î£Ñ›7DÃ’Ckn(ƒø¡†ªÈŽ+€u"H//4¯—}f³²$ äʵPüõú’Šx¬2u2»¤Ý=Ñ T@O&•- v~‚~5†àé?ø¯Ä_¯+²–ÿúŸŒsZ¨IX˜N°=t±bŠò}Zffg—¦ˆyI»¤„Œsä^å<]z¡fàAÅÔÈK²¶_8­NÊL@Ò,Û]dÄÔŒÖÒÁêÂ<»Eñ+uæ›´bÉÎD?,S$áÄèÀî˜JûÂïEÎK2¶*€üMž@—Œ×át†â%>ƒtM.ìTØŽz1ó;L¤Dg-}ÑnþuþtíɰRÆdðíQ‹D;5+Û)ØE VÇ…hGZs4Ó= lÇœõŸè‡Ì“>m¦Q™°‹³¶'Ü| Yú åçÑm–¾àû]ö5A*ÄëœÈ=#7<½|¢¢Õª“¸fK_ŽD Ëõµ©9M-¶]iµµ ‡)épW²Âú,}IMJq3\kÁ%B ¥åbõMâ¯"…¸ÜËó-³€ÑtÙ¤ ´&Hî“L)†“Ú0Znê´êNÛ‰(Œ”…ß ÅAT„ÌžðGufÎ*#Ëþœ©¼Hóí Éù:°¹+põ´J1¨t~Æãf\Í©íó¬ã[óV›¦tÂ$³rŒ²­u°—7åïáUmYÞ¡—Ë•5bþߺ•U±¿m™UoÝÍi7ŸÙ÷9Ÿ” UÍe„«\>Ù “޹Íœ,ÔPô™;‘yŠ™Ù‰„¿aÃ; ê½ÄãÔ+P£¬tX%² “¡MA»›ðDÁ޵Pìà¾&’¦W­MªÉư+§ùi8´>Ò² ¹hÃ[{·Ÿ%EpÙL”ó?G±¾‹%„B50™u€BZRƒÇªŠÎ“X¸ø¾:Ï ©§}¥cë—6kž H:Òð°šêDÔÙ«‡ <ÃeÍêÒèÚB@$hàÜ$‡X¶’4ªúmÂSÚtðú©i3kl6‡ÍF² Y öà ®*›¬)bu3ŒPî=k0TôÖ•éh׿ ›ãíÆ¼XƒM¸xïÖäADív©€$ùD¡µ ˜èÏul*%TÙaäQaÍgèƒèÖç|Áªe^À v*=¡ˆˆëöuk1b&ùÌ-Ç{K"Œ£mfúÕÙà`âÝ5³Þþ.ÒÝÑøP¼¹P;ìþ4 ÓÁÊYÿŸ9ev[´ˆš~E­w`¡s“½8áÇŠƒÁbß$•FšGà VöÉf‰w¼îÅ}J}_âíœÅ¶Ù;W¬î)Eá«Ëk5Ú.}½Å•šûí3;è9í²ž\éþ*š% É_º`Ä&0(±•y´ü@ÓßÙ}¦:Tö§?ö)ªê¯ìÒ÷ñ)²ÉãýžïÝÆÛuÁÓ œHýŒiº—u!)så_,öRÀÓˆoáÕd“^CÙ䇕ïØ"3r®C¨q7+:Š£B¼Ô#w#±Õ)(`Œ÷ç‡B ›;ÄAî‹O‘^• ¿ô]KDÙa…ºdþu”>A=ª)ªŸx"[z_\“3ˆ“>M8HwÒ“&rQ”i„އ#ÜÑ]3#¿î]:C<—¾ïXé(ûåiÏS ¡Rš•ìAÍ(ÈV¶éDVƒ»¾ £ÕÜa“ÌnRYd;@J:ÏÆwÇÜ"N¬1©âÝ›# ôé´BS£g‹?éÜ{]ãaüCêƒð$eHºø`JÍ)7ù`ˆ)=®WÕÖ:ÎG3{ú¶ÑÒõЩ×^Þ‰WÉuì8ÿ”Ú~ÒmÃ×w²èÚñ4+§<ž-ÒêmÚCH> ’«“òzáŒkM‡¥,‡‘m÷ª%¥Zü­‰™¶|íö )T­êbPhf Ç>Lйà´F¬¥˜ ÑA:–øà/uƒ³¸ÛLšÃÀåÐLõg©{ÕŽ§7Xa²_µúá†ò'•g6R˜u4õOôßb3ß ä“Éîè;¨3zE©U3R’ýyÈ£TÄÞAqJY•yÒ>SÆ*È©m’cù4f 4ÈE´šëåùéOAÑl ZíÈàX¸Ž¹¶°támU/r„`s›¾®í"~ñÞo|<ÃÀV:Þ¼aÐ[ðíìî…û‡ÒnCw5J®Õ¹¿² ³W}V_—ïA˜gv$á`å$h/ÔÌm‰påÈ~Î!ò°ƒ æH£MÇ5]âø)6˜±Ô;^>èü†w`ÔH£ Xž7Xòó•ÌTÕ¿«Yªwˆ8â8€¡ ›ªå]Ëá¿È¼WûÏéL_œ¥VPÆ©!MQ#Vt\¶Ïq†‡ë1º³ ÐMZââðñ35\N½ß­~ÎèqÉ÷¨ ë§{n­¾¢Rð㔜¬+nëÔía£+ÊáLpZH#­±åXbx)Pcœ„Û¾9ÞˆŽ”©¿d»9 ÎÙcePr'ú@±9%{ÁíÁ­’Ý~YÍ‚â{Þ6œÞ.‡—Näòÿ²UÊiSR™¼!æiÎÒü…NOcÂ$xOõ÷8LÐ÷ æv¾Æ C‚ß)«+ªì­òHI‡ÀAðà "9æó6ÿcÂýQ&fþ`q" ú Z3k_ú¤<®;íkç ª›Ë3=ÒAåOß¹ØÉ²¤$%ÀÙB³£,•‘<ÀNy~]0}!t,]Yÿ/ªM³¾kqlæô¶¸$}¾'7úÉt;÷@Á…_’«{)ÆÈ>{Af´ç›;µƒÚ‘Œno§Ëì „^TsÕ¨{™µÚ< ^º&4Õñc¼àé÷õP “ÈÏŽ dˆ”SЭS>ê=+{ç§ ;tzÁxö©j­Âµp™ÅÓÉdnàGã½LÃ÷á:•.áÖùüE:a¶¤îŸ83ÄIí.øDz®…I„oSц㗯™9·—9´éÌ¥¿7ËYÃ5»†õLL¥ˆ|i•„†‹5)3h¾N-Ç.bÂgýBjoAQåïò%ýv H–8vùœÒjõIÅÍÁãœÖ篺¨³«G÷Äò'<…d|ÏÕB•=}ªÛ\2þvF·Á-J¿\l!—¬sÌVTIÌñdß&–+$ÅâåÕ¦åë‘ìËdÛ2ôñ«pÔ+ͤ,ðRÞÑ}‘?ÉN=ãbÏ`ã”C–Ìߩ7rX¤´Õ]½=“ä¼ÞÑX%jÜý$&#—þr?øÍ+½4õ«O’\š¤¸kd©š[»ÎÃRÐŽõ§/ÿ3¯•ÑÊ«?T¼m^f6×ôïXTÒAa! ¬ûVù W?—ãG*qôíâ8¸eD7ÖÀºËš²wò·ÅìíW>k Ù ¬’èÖ—:~vYÍÍÍ.mM8ªshí[î0.àƒ%}³ÈâlH9á\ëjT†P%ÓPgO=pòÒ®Ë)ˆJÜëÞ>§_£Äsè±3ð³Þçbå6Ï×âžé9­‡(¯c%Þ*Ô4_”™ñMÙ¥úÀ®fÑxy“BËI‡ád—Ýw„gO¸˜Üóó§ßÌ=dÍÔ¸¾òj8)‹uü!(Æ&b…ç Éôtô©+Ïï`6(™†ï·Ý÷ðe4¿$ƒ'ÆÑÀŸsg©ìʃ ×Wû °î¨I0ꇇµügTï7”ô¶99 ç™÷Z‰q6 40É¡˜aŠ¢ /Y掠M/@^Xý'¢aÓo«ŽnŸ®ñ• +kF„™¤¨®]±íª“ã#^Û›…þ{tTùð£²üèz;zõƒ|Æ f}§ àGþ„k ¥Ÿ]f©>D(›.ÌNIFõ"¦ùÁJ”[SVÎî1èfùA^"U$Çà´³n”Óï1†RîÚ[ûÏVìz+• H|4f,*’cÑÈ B±!˜´UjS˜6³—ñó¾-²QF-N;ÂìãþµY|¥n%v†û•Æh»£§C\w¯‹b$ÝW!é"tfÿÿdñ{i¨Ï‚Âé nþíoN¥®â¶# ."ÐÂB^¾‡ê˶ç•m™nª”î5DŸ­Çâ½TQ«Í~l’Õ‘*&Ÿ.z¸ *•*ØÊJ|~©$Î/šÈ=A®÷!¨šj4G”°¶do¯ƒ+dh |è4æôöé/Ð4`·.%–Ýxç!ÊörÕsÁŽ›¡¥áœJ…†6Câu¤‚§Þâg²>çêÀ1޶ÿö’èq{_?ãüµÍvP °¾Ø”S!ì¡ïœ&±Œ]„fˆ j€õNÒ"Ñ×;‰DÈ%Ýÿ9¼ˆçÅŽ]p~¸êË6[.û¦ ¯E2Öo}¿5éÆuì”QÊ|ë§©‡öSX½ýGQ½F~ºmnAw|gùÍË/SbYs ѵF‘»SË!ªÅHÔ©qŸ]¸§\­Î½meºƒÎò¥üíãkñþØ{Ûø=dÚÝ*%uZ±pl •o²÷3Š:í…¬r{"Œ\ UG7ØPþô•ŸZõŠV¾§Éßå0ƒÊ'!ŽNøë{ÞÄ5²³U6ˆ Ößp pŠÉóY³qýËýB¬ûQVUkûÃbç¹XI Øä³Åƒv©æ ’Ÿ?;œêÝü××QsÜ«Eâ;-éÓ1¦¸¢>ÆÝdówQ±ý Óz‚›1¬ÅCJ¯ïº¼áÉàR5Ã?xhFmxíÊŠxuÁ`xAqOêzµ˜¿k8„<>!/ÐésÇÂQã&²QÎwÞrÍ"•2ˆR,(i˜1£©­‚£ëÎ78dB–ÏÔÙ_½Ý•¤g@rÚ)®µ#÷hx1·)kN ‚Âiæ]ŠãÝ\ÜÒÉÅ˳`LuXl© á ¡;hSU‰¹_À@䢷1îG²’–,í‰úÒd¦:ÿø(ŒÑžK:v$§LsÖ6ÞÉÃòוHxùLä@ûßÒ®f-Z—öÄzšI ïð-ñLÔ$Ø÷$‚öÃÍë¦Ðìa׳]ß/ZlŒqÕ=DFwLœ‚á8—-3¯&sÖ_by2bbCå:ÁWžyŽ›w𢠴 F]…{±ÐIy¼ÆWµ³Œít{u[~DÂ÷¾uèŸe!”I0‡’š×…ÁžïÓÁÅe "Ã"?é$Õ,™@Óט_‡=‘˜Â|œÍsõõkÛ1¾ NV]þ1É"çîÕ*Øc²‹7»ów‰Obž¦ñàS5r<ý€*dísÐ ´cÙ 4ã€8_[©ÿÂùÛ–‘Í´2V^Žîª©ÃxÌ] ûRK]~©ÄôAj(¾ø?RôpmÍ–+dW§i4ï&ÅèÍÍ ­™ÖLt±ÓßòéÀ0P^s®î`¤úÓÌ5º$j¸I|,J5Mè  ìê\EsóÜDºhŒˆ¯­Çìgªè–·„fe¸Ÿõþîé(*:Íû²¦Üæ²úÔuœ †r %Ö'}QgÝVAó@}ƒ–ÐlT,SÓÅq÷œèëÝæ 6·O<ÀÝ€§Ì¢ºùW‘ÄîËBRDÏŠ£vÛá@ùOÆIªÉã€k?çùôïæKdi‘ZŠ ››™TÈü^|¸k\èöÉH<îTüS 6ÞU&ÍãH%~˜šëÜHDGÛ¤¬ÌTß4s\vùX¨`z‡^-<åø*Àóre¼˜EI}^ü‡°æAtš1».¯5%¸ß#¹ÅÈ–.I5ˆäåv±„Ç?K_ÿñÜîDrp?m˰à ;× _s2Võ(Ã]þÁ<¡cþ¿jõÿÕs/ åüî„͉J—qE`AÀÕ×c-Y.ÄŰz…^š³³EjW)§eë•\d^±0˜Î#àVrw„L³Þ| Ìºc-²ÜûNàCYÚR?yð jõÅèicŠÉÍKïÅkTœ1ACËÏÇKŠ0 Q§‰_žú˜³\p&®Ç`Òo1$®š;ì£M_êó4B‹òߺÊööüÈo»´\¼ØX‘„ǶB¡jx¬5«¨q¦äVŠeá¹&íƒîÚB”uí±Œ§H§¦>o+S‚çÉ ÁT#ØLÆ¡<`î}Qæt‘ä¢o5¢…„eÁ%-ë;ž@X~^¼Ó[V£äu®:3-AŒ2Ë'¬JSž¾óè¼ %r8põh.µøn%BE7Ð,•ÜIjY§-rØòà(;ë²Púbæy¡jÁ䀪mZJònÈí?0 ¡ˆ˜ÿÿ‘¨IÖ‡gu1§ÞǸ)0o㿳¢ŽÀ¹…‘Ü©V*J"Ú›j¿ÐK.°â0­ìt¤îÑQBô¹eóEðõn âà’æ|ê}a îÇÄ ¿Ö$µ$Q° oÅ1ãé¼éÕ›æ^ü³Nœ2ª£5ô¨ñIl༩zÄã6é°piõeÀະ#T¬Â+Xþj¯‡•¦z)O¡›M®æÿrhïGYše…ÒGþcƒXCZFÞ–ãÉGï€êGºxã]lˆÉ¥ý‰’3ÒÉE- ¸“ÜrxÛKuB“ìª ÌWìu[AÙꢫXÇ•œ–FIzg'¸ãzó¶Ì`ÇÒ'Ë  ùý^áYú~F{gÓc”‰ü/Þ(ã·šèfIâãÒ|"½îsÙMŠò©ï½ýØ…Ü©¢Ö·ö¾Á—âÅÒýòÕ+¼A¡ëºjɺáô®¹ÖçQN-_ 3T$¸Ac¥ ïŸ*=Åï’ÿÐ óJâ­ûÇeABg@ùmôhĦPžì]ßd´¿T ¤N9ÿ‚ØLÈøè–Y¡7Åp&^¸t9s`ýü´+`eÉÜUãp^¤»µBv…O ÄhÉIí&Éèìúìv-¹Yx„tÔ:ïg—ðÍ´ƒËÏ@2÷ðÄõò¤;šf­<¾•¹òâá_oÅ›œè.2×ùÆ¿š™óáµÕnN>‰ØØå'0;ܶŽk:™ÂN/´7EBº‘å „ßïUv¯Ê”>ØŠ,áÕžþ3RC$í~|ÖškØ€„õ¯#uj%dãASèå…Ï vŠÅ²œ'óúl0 Ûö´’)³¨ÑžŠ.]˜x¸ çØ²ò{dˆæ…J€3š †G;=V²HÏXnnûùÏÁsö…<ãïæ‰|£—±7’éªè?0W4ã”Nä{gÔÀ±âyö )ù)ï $âp³ƒ÷½Vœq ´(CO0'-[%fR/¤¿þ¡H‚§"%¥ §œp}Pëƒغ£¼#U”LvÈ1Þt°ÿVÝLÉR¥.Öh¬jy¿UÄ%Óf~tlÑ硇Ç')Uv¡óp4Ÿ[˜J”éWèÀ™ëôÍÙ\“28­MlÇŠy¡$²©ºÉûµIÎCäé&¿ß°,#›6v_–f<€‡ý£ó$Í“ö6šÊ-; S$Êi²ÖÌbÛ‘‡ß(˜Ó‹NÞxÅ\IÝÂ>³´k¯Vò¼¤í…¤F ’dâî÷‰0†ŒõµÖÄÈ¼ÈØÚX2äQÙ¬áj’€¯›"P¤Ë{¤O½’ð³»¼ù –~ëÅj©0}ö•†¦ó¨øŸ ¤L_ØïýÉñ3Ÿþ +»øRàà3XEFH>‘ Ûs•â§¼È5F^q·¡§‹é«b˜nH­¾V ¾eD…èoc;/¾=wˆ[LÓ”°*Ýœ¶ûµŒ¸¶V²¼ï¹Î£Ò|ʦáòÛk,‚(H3õžäúßV¦¹¦z8X¾U$9‰z8Å’z‡D­ß€`øÌ ‘ÜÈã™¶óÔîª`= {;E·ÓiËsüó2w  þŽiÉÐÕÍÀ€³å+Ä9@éíM¶ŽÊ^k0—ºšwÿI53cÖ±õ†ÊÓ/âBfˆ(P¾½ÍWA¢d¯ÔWÔT9K%­n_Á¤>ÕÅ'§^kGØÝ÷ˆzD‡â½Äü†&l=*ISŸ®p OÒmÀ93G/æþðRDþen´eñ9Y˜}äG¤¹¶¶ Á‘»o¤`/ äl¼»bT\/¿eøNAÈK§æ‡kd!Þ"hwä®–Ô0©dÜ”Mîù_›2Xâaâà)T—Eð,ìSø²Z9ôÏj L±D½Î£‘|ü\Ëî^ÉKù º¾¯T t%1Q¹çS˜×ÖßA6•fÛ¦¾k,™ðN½7¾€Œ0š#$ôL$ŒìS¬µ Àãξ¸vŸ4§Us›ÅZÈ-gWŒ0pÖý˜Ç4­2›rʨ6.Z bJ.4ÔÀ“[rv"ÞžOòˆcá1r½‰—æðk¼tZƒÑ@Ü:übÈÏOR3=ŒêË’î.¹;€ä²OêepY«p}9Ö¹Y`&C+|©þ4ƒë~ ÌMÆZ"\†a=#ãÚ©ò Î΢õ'‘%ñ•ìÚ(ÒOqn³–ØBƒ¦Lt~-‘3_Ñ>”ÞャÂ`Â/ô¬"/?) xÉ<~üI²&ia®hcÃÆ´*\¹tŒéRî__~çè²WÙ©{¿V$”òõ :“ 1–ÜÍ!oŽVåŠ$â—æbÉï^’¸ð±i0(ÕR%HÉr§?‡# h¤Hüg.òž‘Ýxé?‡Ü‘GßöÆ¡?š3 ¸ŠXu‰I°EÌ­ÈfÖ&±{3y_To⠲孥Xã{÷áÎu†Í(3q˜KÂièâpÖΦ»EÂV–Ý€‘‚dÁf!q ê½—Xvm2 ‹ºýSܶreãÍ/º§âÕ»èýz©kj/Áyº6Õgëù rÇü‚%-ÜóàâÔf,ÏVžõ÷g®yìÛÒoÄO6#CƒãÑÏ’¾Ñåvª¼´7@’{„óŠ èã„ÿ…Éß !¥æèkÔ¤êØöðIõñâ0;h½Ì悉üÕ|§uÉq‘$†ôˆ€©BüÅIÚ€ë¤c®–I…Lv~2ùüš¿ëy67&‰å½xK²Ê+)ÊߎE25«Ï ä[}¤r«µâ†ÉœœjiÄXÜœv¡Î>ªEvHCÄÂÿà ‘¢t¬“8n©5Ú±H :ì_¥nႚ"{šýñ Ë(KÂ’oíqe¬*›À­/Šcý\ï¾:é @ÆÖ£æn‘LXeýaç…Há0vl_¼¯ÐÆz=6þYôANƒF~Á£¶¦mo®óÑU툚yFÜcEømK$_ªÇ€½+á²Ù™u"ÿ\Ç%¦?÷”fàöÜSÛÅê^®ð’™e¯­x>7!¼JïCY›ÉA3Ÿ«¿£†KúAûlAh„XXEüÂOÿe@ŒÝñÙ2$ë©ØThΧ–!”&:öîÖGñ5_†õÅ ÇfÇ:Üb\X:ûB³‹‘Îy4ðlY¹µló&ÄŒŸ»ÚÿÌC–¸ÐUþmU‹±Ú¼nÐäþ'±Q<\qXÔ=‘ZnŽœ¤qú@tË ýÿx…Hé62}¡îU<‰£×ÚMXÔå~ÈdÆ[ø´Á#&oYï7©†-S£F)Á¦# EV· ¶eDî ªD`é âo ¤;¾,õd‚b¾íÖz` %`cXŠÕýWpçÒ˜‰z³B¯÷H,õWÚÝq“íRß+É/Ö0tçN…ŽðE~~JÑ(X&:9»^÷b7ƒS‚}ôSb»É,£Wof^H^¬uÝM°a4èuÝøx Ö/±a.ø¥s<‡)ž}†´úæÒô5—:EP[#˜Ÿ šÏÀ›m)ƒî¹NžÇP§Þ]’°óup¦…˜*Õ`c“ñ[·E*B<í:3(x³=]8×.‘w1·ÄÝâýI½Å¹I k“57•'|ó†Lçþ§—ÆøiÓ`XC¢²ž“‡¬$ýb4Æ-0w´ ÍyDN\¦´!­gw”e]_ª±¹¥9$ìš0=q„S´0í•|®¢1XíÚÆ-5†ŸÍŒI™É¹xá¦BÅ!ü²:¥Qe:½®L„9«I;MÐŒ< º°[±gÝyK¿*åºz·“™"FŸ=©”EØ]±hé'ú÷ÌôéÃØý×s¬P. yx€Z[ù6ÊÊ5âýó'SÆM‚CÊy²!«G¡+?Ã\™ìø”@¦†#∔݉-c Ñ’Ù®ƒõÁ1ûÝ‘½ÿLº£zo§Jt¤Œô¿ñlR‘ФžR]K!nØZÕ®B³D¥‚=†Ä%´÷üóWq<*³Ûpé)6í pÅ#”a·®Þò€¯øÁ2‘爕%íÓJz‡“X¯ÝFíÄ ä„:T¨Àì:MMX0‚€|)õdEJa _5é.»Ÿ‘)„$ç¦S%Úp(c{¦• ®¥M6 WÕæ@~ݸ„âN{µ;eö¥%Ž“˜?DQš~}YùÃ0Ðx·ˆ^É’¤ž£†ÃXPn]öKÆÜƒéÈâfî¡x#À¥øk!Zå©—ÞGì%í` $š´‘ï·P‹ÐDYµú\DÉôý•ºÈ}B7Fƒ®Ãä:ú''™Ì½.;ü¿Y×/›üÿÑ ÀfŠ¿‘šQÓär§’û³ 3¯kçGª‰CC;XŸ*p Ø©;'¼Rk<ôÚé†$Dæ­%óÖoÉr#!bbZBc…‚ã–fí/ˆrßP®#ÜÞš“¿ñ­¶F¯f†ì‚*þo5>Ä€ypIî®|¸Ííñ—cŒn²Ëè9ŸTyƒ†0ùk46úôˆí@Ò%»ÜøÇi¾l á^äÏ»^Å¿h´Kš@b:ÕÏ#¤ÚjØÔùÀ¹cçM¤…¼õ³HôYÈIŸ1¼/"g騴²E=ÏðUžŠdAUá&X.Úç–Õ¯ØæÅš¢æ¿nÕÍ=ŸÇ·9ê%ÑŠ'ô}GÜ­¡úQ^L°Ò3À…?¡iûž>Å$CþéIPި͕P%Šó¿¦Ä\…ùNJI§`™#–ëuÆWHöMwn±ÛÎÐwKö ”s˜#*—°çˆ^¤ýPB7»ì؈û ãá8´´€Ãí'ã3Bîk<šüí¢¥õei'¦C©Ô¦Š>ùtŠš5^î¿hH9>ç|`YžWåWŠÉÈ-Ð|°c´sÎ ó@E^bSbxkQÈO|†¡rÜtI[‘Á6sÔm„)غ[m¿ÞslEÓEÇÆ½ÝžäÝ›åaÜ žõ'K¼:†ø9ð,ÓøY.¹Ù~O£wQ'e[Czë‰H>þh>H~£C CÆÔx‚†=€×Šþ‘;>Ÿ ž¾R"‡öz¾ê2ÔdЛmî÷%Ý1k^ºî[ÏÅ«ËCŒÝýþ‹I´˜rV•ŒmaÚF(á¡o”Ð× ‹â­¨BÀ¹Û=½œT¥Éˆqî¾ÂƒJþŒ[Á~Ýb›Í™`vy}u¿s^lÜqµ&"Ü âògT•væ4ÁVR*V޼p-v”„èÅsñEg¹Úêã{’ÒàîÒZ˜ç}Oú5‚?YÆÃ2A›ü[ÚÞá@¬ÑwG'î~eT¢§$¾rIµ“ƒƒïß®õñËöÑ®Ø/~×äË9³IIÔš#û[Û0{ŸÕUé¿ù‘Á òšá½”:¥2ï¼ º6ç8‰ýŽ å"ðQ¨nÅA³w.]9!îб¸+œj@”YXÍù²†hp·UÍÁ”^úf[{3guyàkjcØ ¬ûšÑµÜ^‚& (°–"ßbŒ¡Ôvßä< Ÿä[%vϤ?Gj’]³±ÎàLÅ ò(‘ø /Ör–b™¨ÓDÐ\cìª^éWLn‚§ŽY…qoî$µfíX¶¥Kÿ¥öŽúó D}Y\£žÑ’.´óž ¹)š§µÿrñ9åÑZõ¹nf6r*ÀR’ˆ'¿d¿cTfP‚UÑO¦n®ù}ŠeG/Nÿ_ò“îzc @,sƒÍ«ßmÔ—L>]¡‰‚ÑiPsnþÎÇQœ`^âƒó%²ùÚûóf†D#û±²N©©[HQŸ2ˆ·<üë\¿Ïµg|ÕyŸ4^¹¾ñ\»Š-ð‹?Ž"À˜ð28¶ëî??õ«]’²£×ë ÷Rå.T²ñ3<9ƒþ8GÛ­ÆNh«Ÿ¢žì§/›m\ÜYì·"–') žUµaŸÏÂÓ­V ”RsaŠ’4žo-‹ ê0O*­„w1ZN] º¶]mÓÛðÜ2çLX¸é(®OK´u°p {›iL™"ãm— $å0\ÒäyckÖy¨*¬ð^[KCU!”9Bݯ¶ª£þ ayòHv Â<þ£DŸÆj­­g^K•1Öc@/‰ @o•Û×]Žû×½¦¼%YÊoþ¶ û%c‰ÿ0µX…SÌÎQMëš)“ô9³ØáÏ6DJç;É?Îx]–jÜ}èUBg„*žFõ ¦¯‘t×Éãós–ß!þ(íOæ^8Ð9.K–ƒ°ŒÛO€Âj4ºø×•¡Ë`ŠÒjû„=MäÀ50ö`b9N4hãÇ“Íx°fLk2ª€°UóJÕÄ †j]¯J6]HWèžåXÖjïD†ÍóºLèõ+M;;pI[ö$|æÿ%vùnÒ¸·O®qu!yû}H±Úm<·~ê¸Ý…ÿ±rO fGKÿí.ÑÄÒXTƒf‹AG =j™êÂVj¬:3«70‡èí+}ÌVé×ç1þ˜‰“éM÷´îöø_žû6Z«0©÷M‘³[àØNma%’I?HÿmZ¨C…Usùyÿ4xÂÌ»+®·nx“¾Ê¾Î1¯+ÒsHi8µƒÌ¸jú\ šÕè}5ê ”_éÛ¨I˺ÉïÉÉèÄ'ëòâ¡—MàNCM¯ó;¨–PÉkL–£ˆÊ8\RKÜ«‰0²;¥ƒ«¼âµ¬A…˜¡†AÏÔ5˜<ÙÙáÝcµ¦GóùÂCΪtR˜á×§#äZnv#ÉGÉßÄ€öQc*çÿ‚*HgïóªŠØ¢«°G2G÷—1ožÂ]—œ»Ù±ÞlPg$¬X¸J´~SÓ ¼~ŒµZ“RŠÌo~k4…‰¿3û?íŠAð"Àÿôî?øOÕB…øem*QçÝå=ý V¡æl}gTý,X„!ÇʉùSWæ×* €cfáv€*×úzŒ6r‹fx#øäÀÛ ÎBHÔÎñ tr­ æ€þŸ0I`¬Eƒüúˆ êeòB `â¨Zê\‡Qï‹Ø@ü nKtE®ÿ@œÕ/-ì• OD5s§ã—«*ëïSëÅ´ØñŽŠ^ .öôNÌ6CâbW³sºÑñ`ôuT–Mø4D¡ÙÜ\ª—É´»ÂùéyZqz¬­Ý¶u”yÎLúp†þI M4h$μg™{¡XW˜Ò8‹“ìô1m¢/pxU‚§]2µ›Û|‚-GŸÓaãéÊúV¶(êc…Ä‚~ôùvÓ2¨šÊcN5Jà‘wîj"–ø´Â¡ÿÔ2ÂrÉB̼ˆVñ¡SºG„Y½{˜²/þ©T´»ÔÄb»ª7ôYkò}Ø‚œ¤TÅAægÿŒ5éñw‡KÈ¢þ?ôµ^¸;ôì¿eåJc{¤~0Ýt´›b¨õi·ðX‡Ž!bî*ïm®Àty´Ú Ü-ç,ñÏÉÁcP’Y‘ÏK„•ª„ïÄWÈŸšíËÃYW"Á †L(³ÅJ‚ª›cíÀµg®—-hìi 4Ïr‰«}™„ÚfÊöæ%RZf}¥¹šë¨=:ÍÆCá»­K”YwÀšx[T!±ÛS5v9VYÝÒ‡õòôJKì=óD ê1&ÈóÛÒ³±jHÔ\}ÂtÎw¾ý_l¡þíPü‘F¾´mSû+£Š‚s³¶ŸÏþž€i«c¡‘C¤·‡gîO1<:U=˜$ j¾GyKŠy\åÔnøð;[øW`¾®„ÿ‹×%Ј%È£<2ûÆÝ~E &ÉCãµmòWóìƒó…ÿJqSÇ n½[.ãF£C/0@º¼“Ë—qßôª›?ŒŽAðO Áü ¾Ù>Ù]àâûR­)‚ª¸EٸЄu å}hÄ8‰F€ÆKß[¬›‘ ‰VWvjvÌ> ýÙÔ›­ÁJQÔ“½M*寺­ç¥Lz‡ÿIñ}ø§ô™G",O.)F!´À þùƒ‚+PíéØdŽƒã!Ld ÁiúÆñBD­"T–QjwÙ×…Êé×ZÞòÈF,ȱhP®gŸvrï´¸ßÛb!}±Z¶ mÔì¨Âê3-:à´ï- CLa¶³¨b+6ªFä½#íó3iðå¹k<-àþ!µ¹Ãu+3ÄŠÜ\ÊÉt2ñtÛ ÌH|Ìò•"…2ÿv2Øû¹Qü.vȬ±6σåÊAAt–oxµ0ø±0=sncÇ<ñþªLèT#…¾—Š’ï\úÙ¼ked§ÈEmèè¡ÉÙ&ž7Oåùަ¥+3]ó/+!ƹ¸^ Ãb»¢ß¸Ù¿ ëuÝvðd­a=…G·{ѳ}¾‰ß™ÉÚ­#Èå&zéñ´z’‹œ6y=‘¡é~_òжXôÔ½—>¶*ó0N‘‡8¼) Â5‘žcb!V.è»KE#la¨ýP4H#ôŠÜ5™Ê×&O/Ú!#[í[ð „úVzÆPí¶ÎÙ³­7Iâpˆ¹üGEØ™¯˜8èœ!‰“¾¶?#§uÆ ½`­&±çt•_x(£ò¶ ;ŽMZ#hí™"“`´ý™£Yòn>ìDÐ+êÂGêÇwb—O;P/ß/óžtw–t/5é–ˆ.Jýü¶UŽŽCu¹–!ˆKp9éf’ `rÇŸ§¯µ` rô€wÞäÕo s=ßÔzÓŽÁbgªX’Rد8/ ßQRDÞ´'«ÁîÆÀöùc¢‹tzâ+xå±É®ïº1v)=Óº›Z4Ck´ZgîÖÊTãÚ")—´½,Åç‚0R°Fxëáçxpt»¡VËÍOvO$%Æ9è­ ‰[ Ø2°ì Lô-þY›ŠLB3žöÒAÃj–ìæ™ÿܦu¤o{t~ÃÀX^V8ì+z¢_IU‰_÷ÔÑ*³›ÔéQ̇P$r(T¿W‘ølx Tl¾Dçˆæ¾¬$DpO°S^Êw M: ÀB󾎃‚”/pvî¥Ög;–ÃîE #ü¾ÊãýB—syÛ>¿]i¡ƒ¸OÖöé ÑÔÇNj Ùþêoèk—ƒë¤ˆ±ŽÃÈÚÓ.:ŠõЗˆËv½ãµcX0Í•"Íýú‚$yj6Å5b6™ÁYdù¨ÞrÈë¡^NOëK÷'ªoi!¬}6 IÏNZÇŽûy>ñgK\-6#¡ ¦óT‡JÛ½œw0^]'a‰¿ØÀC‚.þœÓ`èåþ›Vc/N7˜p=Ðý1ô ,µÛëïÙÊÕ4?çÆøõ?htuñm^V’þ2_ ª„@înQ!Ü"8}®šŒ”bÊü2À@†Q h^¥0øÙŒVmØrÔBàS¦,ˆhtÃCSY0¼û \4qq ';³Yœ­p_»^"Wè0Ç!r¡¸iÓãM6ÝØB3Þk"©W)- £ga—r—W¶AÑF×5ϵÇKž‹«ÿo†d±¹°qÖƒ¯øzþÀSäm“%è/+ü*òÜ<Œœ^‚ª DØÁba5 H\5žÅ/«³yÚ@·–”ã9[ƒ Nµp¿øß:L—ðZ×nû$FÙ΃s@Ž<Ïç°è¬É‡|©÷qÖ<ãÛt¦'‹’Øa!àr%y¥wB¢” úˆ”Ô uæ9àþt³gˆ¹Ú9Tzr`ù•j]—éÐ8C±ÏÅ Z7Ÿ¨µÍõU}’ªák~ÙÆüí‰aÂüåÃ}¯ƒ-%¼¦P£%7?Þ8%hÄÙ¨+{hÞƒä°#-´Ä!³.H㤎¨jt`>ð‡K¨õ£© ³¾\eɲÅRÖ6·Ø³nÜ…ñG2M·¨Š7Õ’2س)‰ÉÀ(Æe‰ÊŸø”.RSk¼‰ÄyZ±àR³ä†FfK±'iø; f5ˆn!»¼†£‚®œ*â¼kýö8ݰ6C´nY]ëðy¶OEûg¥/YJsï…†ÂÏ^ØÉUÌ*Û¦¬š°p¬aM›÷U÷0«HF‘Æ$çUا•îˆïi!¹b]»nÐÉvÚ"7µ ꥚Šž•µD­þ iHøÌë{?ù3"Æ ›/, –Ÿ9-Ë6“SŸ¤ëÍø=5šò­™hõ­tdÌDWW ê‰iËGìb6ÎtF¯s­¶"Bµ…Îâïý§§2J€òÜ0"þ$š²ÿg#^¸_’nÛ‡rØÞ,¼D’è1±€ÒSFÇng 95’8G’ºVpåYW>ì+Ý[öÁÒå÷¶Ð¬r¯uÌ¡ŒVúà¼-c²eú‹Üÿ›üzlXÄ‚ÅQ¦Öb¿ *¿S×iyv¦­j–°ÒÒn’LƒåIr¦#ì[‚¿ðtò+Ù.dl@R9yž¶LÄ¿%Úñ”¡‚YáàÎ[   ÞA]øUý]jM<ý–˜7õ¨ø–/Ѥë÷=ÓZTÑ ‘¦;Ú±ÙIØS¸ßíäºäûdÜÀ>¾YƒÙîi„c&v“›>J€Î1ó¾ºß ÍîãöJÚ=³14Àøå9…+ TõPk¦µTy/ &³¾aìjOL'?þ4ÍáeMk®µÉiÖXˆpò£¶™ê¨^pÏLJPÂʦ&£rN‚L{iJÚDîGM€¥ •°±â…øÜnD2 {··›×¨Ê„yé"Í÷”ŠèV¥‚p¤¬- ó³‹8c†K9OPêÊ+Þa³ØÔüfˆäEÄdÎ+)Ú£A[%´FáJÌÌŒ¸Ó#³Ncz ŠšV¬pð,Œ#šž“o<Ž”òÍTÑ祇ЬÁꨠs.Ô¸—1 n۪ſ>MåM«ãòLø0‹Š‡õL{h"T:«òŠýµjx]óÓ?©ú öJmº.Ÿ06æñðvë¯Mp‹Á-ô}÷zATïCæŽëTylÂt©èä|ûcê¹™§hY7›ÇV?=mL}Òá`]Ž ÈÆ^´Ýe>¶äá3ÞÎáÇÒ¯¤råW‹6K˜ÍïóæÏ9 Ãòµ«0_Èü<£dß^5ü"§®ÿtÏ!á>o 789…Ó–óp•‚@PZ–æ´OÓfÕgV RÚ.eû߉IZØ«Ðv±±Ô÷š`O:BEMã5_@ñ+–$ŒõÓ„ÓjþÓ•GñšŠP¨ì`ãŸú+ Á|ןmæÁ€W@ï,6ù–I'£ 3ß¾®£' <ŸªC‘·Ãƒv*ò«J~„ ïš‹¶!÷ñcd äˆvªC^²þ‰-{$M]sÄÚéÔljjY£2¥˜Z¯¢KИËeš-•ÉHÇÎAªËáË\ïrÊÖñ=­3â¦IùyÑ¤ŠÆæx!ø ûâ t³ƨuà0+ù"ßÃþ#M7´fCCG€BË¡e/(aèAH¼÷š§s¹©›ÝªR” ò^MXÛÉ2"çB7{L,Ô±‡S~ü– PÕû1sªm➉^¶nzA6q‘h•qn¢»éõ¸*N§ZùŸ³TñÊ{V,”ý³Ž]R·Å×\VˆÀÓ@]ÓN‡, ®=bh¯Cë%ÒdhK< ú œš¤ÝPŸÜ’«3 9ÖÖ1/Óñ¬Ã÷YÇ;¯†&ó7Φ_Î1„@«¿ƒdLÏb]:• lTâ©e Ûú\zº(|³‚lR–¾E¶˜—„؜֯³ßˆï¾ìŽ(&gwÅàܘf& ˜©¸:(¬·öÌg,bÔŒ™[IÇ”ì»ýQ‹¿Ñ¼èËYá°È:V¯ô1ËÿGujÕ+n Xëðhž1—ÙC\ÿÎÞ¾7ëÝ“ÜäÕ˜yƒ•/\®"D2¢ã³EªÌ½h Ú­¨UÞ1wJ³ý ŸÒoÔ´n´)wLÇèÄZAò3p^"7ƒÑ¬MÓ»x]úFg•¶S$ ™g@V}éltŽäìj?”ÙXƒ_–Sµ‚WªvƒbëB(µàz¯‰=Øígg»š«Ù5Háui“"&¤Œ ‡ ±‘%f¡j÷ˆó¾ö`¹#` ŠjU`zõ>9¯BÁ•VìØ~w‹'fj?ÇV癫®Vä8Ÿ, Å:¾cp»mÁñeK>ŸoÀ\HHªý]2$MÙïÚûÅÔ žŽýçFš °K`–²8†0Aâ©™UkØÙìKÀ«,=›T•Rj|œìœâÄwlAÕœÃò´Úé!|ÆÎ¢ÐÜ\w¿ö1†ÛïÙ!ðVT³m5€IgÛÅ8{^•JÑqç{íÔlZîtTV.¤˜J¥8b R´Ç°á¿l7ºÁ¾Ü[ËšýYP‰›,¿Q¥I*†ƒœ×ÝñèîfÛ!U‰¢ÚS½Îñ×¼¸¿ù(BhÒµ)5S¯ªÇæÓöŠýé=üͲYÊô»jæ èlbd íP|Ù\ —{‡„è¥(Ôbè# ¯@­è €ˆ!¾ùÛdž…<í˜öfmÈþ¢™»uXq¹3Öcù Äïz~ÆÁyAAÏ…ï)ÇìO9°9ÁY2æ¯1û×8Þ=çzÒP¶u:š@‘›NȲ|¯ä`íKìP‚êb:Ë«eü¸‹w9k‡¤Ë޽ì Ä‹(ãY(iˆ„Cs=“¾½s¦VÂß2„<ŠWˆ€ùnMØ[ê†ÛR!%W»c­Æ“¤d1(©¶ÿ1SS:v¡`#pŒZ/‰` eÂ!ñtÙ+ÄVƒ¹I‡·ÊA–kîL1>¦?O9¼•8fÞ¸0’OÃT¦Y61Óí0 ¤Rî›å™#žXøT„ü»ØF· €/¥¦Îéø,C‘9Ž´!«àT$Ma£ø Eœ E Ÿéš´ƒ|6™B—ôæRe"™;uƃÒ¼étÑx»]ðµ‰5•ðÙƒŽ&)Ù<Ž}¬’ÝkIklKoçæÜ_¯wrªõ·Žœ ‡i?¢qÝèñÁAä‚%ËëÙõFgý$£Ì­Øn¼‘íì\1|˜npì†9ñáy|çv .XU‚¼k‡ËI2§ÚhB(ÀÚ­ná S.ªw¥½Q‹vˆ_äì ˆ¹è*èr¦—аp¢Î%×–}¬ó5òÿFû‚î»õHÁ(«29Ó¡ HdÛ»´ÇßÍ£"æ>©Xü{ð,&ÀösÈØú\vª%ãuÅl¥_=gé´˜Ìð& ð8gêIw”®¨ÔmšÛH AàêÎ˧ïÛ“‡q`F¾¾¥¦¥5ŠRª¹\Òˆ?xlçµLõ¸¸I6¿—öä+”GÙo„”ÉN/ö)IâLVãܘùf#Ïæ0¤Uå’¦Ï+Z@z`ßxÇ&‹¥«Ë3ËÈ»t%ë@­ÑÑÑ(Ÿ™æB#8)¤Íéó^¦ökœâ¥R©’Öë#‘ ÈœúhB4Ú"QØn k9£G£ÁU VèÑa„m4˜ƒCò;T ZYQ7¬Œ”ïgh}¿Yð¬áìÄ=|.ß! ø·n¥i*Æ Ó»R)A ìuG­}–…)Öµ5ôO•5kxéä{=¬ríg¬­„:‚N yb_O·¢¯åÉ~¶ZX¡L‹Ä¿ ò[à­¯€B1ý„ã×õ©Ôº§õÓcáXIд’¨ýqgÎ’/QÅdþ€°I‚¹[N#¤9@& ºÍU³aÛ­MMÌv£Ÿ½G#‹ì3˜;¢aŒhbYø|#G’2îD5w,H6Ô5sS1 rnÊ}ÑW©ÿ1KîÆÃðz["f ë µ•|U¬m2‹@"öOÑR5„vï‡îĨ”tÑ-bôÚßd]Zc^o ’ÔÕ7 LŒYþDõ0„øÈ“GÓÖVP)Éж dõ îåÖªVO›ca‰Ž#ÕõXo|_°eéC)²_r8Ðzæõñ c ÑÔá\G ÖR3„z’±©àÕöê3ZÓYí<‚_µBUÊî°ÛZJ$ÅÕô&œË…fÉ8Ø~ÒXì¼H¯3g‡GuN¦ƒ1 ÒÜãz­ÖÑØÃ<êÕËbO•Áì»…@la‘O²W„€„ýÖ¿2_޹¨>A*|ÜkNèîi¸¥”¼¼ÿæ^zÞ |ŸÆ&ƲŒö~uúÎW«€þ½©€Ÿþš à4ëàXàïm†6'S1¦ùv™ñbáüÂs‰¦9ðC¶TmWW'ú°öºXj÷‚ýúA@ú‘¸RŽKÆt·¯¥à¿âþÍ}òði¬ß,¨¾²w•–.Vè4ŽØ8’_ c|õ_š˜›LX]`›çò"i”[lÎRã‹É¬ß®g®7+ ópÊŒ‘b«‹Î-O™ç/NSÉ7^3šJG…òWœßQ¢Ù{‰t„ÔßÓ­.AÖÔGÇH¨@¾‹å´ò¡>”„:Û„‰¸3d]‹ªg¨žRs ›3rÚ䀡÷¡:GÞœæåïn Ws4®»F±IÇø§¬M-PÈu-¿=±)çAÞ¤1bd²e¯,v¿8áo:ÑqRÇò¹)mCºÃ§Ÿ—2çß§mŹTK˜9ü–Û,«beë¨u#bªŒ©Õε—*Š'–//ŽX.FØMùùÛ6âO ÚMÍž* ‹µÏd…àÃ[ [mÕPË/@M%·çþp»0¸ilÊìqó5ºŠvÁFâÇ&ëù¿4†vs&g×es“ùñ…ÇQ!"Ië4WÐ:L—0ðMlð´ãüž3L€ì@ü¤7ø _ÿ(Pqù3“z¸þÔ„¬¼8”’ÿ°6ò'Ë‹éŽ[ÀÎ\Þe¢LÓ£7˜Øí©ÆP¹ž3èzêj N34y?'¨fZß91¼Çs :ÓýUЮ«Ôÿå¬Nœ~ ÀB7XWŠY•bR™óñ½`½uòߨTÃnŠºÁ»~ì:6x‡*z±Gô,ä Pç×F 8µÑ…‹u*~þ‹ÍˆÕæ!oC°èTÎðÁø>‡m(@Kþ#x?gë>ÚOê—֢ɯ2-`—#ñ2_¼ôæÜÍesø#i(Uþò7ƒÂ_¬(-qñ%¶ÅœNÉ]Die-]ϦŒ^ðÛ—íœð)O"6j P¿œ^û9…ãW˜Ý PË›^"Lb¦–¥/`‡.Ϩšíó™v$(ñVá:"_„ßV§7>qcíV†e!µ ‚°]¹ix«¤¾!û4mv?Œ©3Aç•k pYÉ‚‚UÍ”L3ÆmC]Õ’’NÁ!H"$ó sÎi`öÚæú¬æ#U$õ•߆ÿœ‘æ; —ßàþ7¸ŒovȘã&dº«Èð*èv‹FÉ€¿/¢{6fª½Ú0ÈŒçˆñ;Žª”âá+_/ÈûôÃÍQU¯«xl2{mOr˜mÙ|RGjA˜i‹ƒ`îý[û~o‘OrþàšÒ‹!J -:Ä«Oõ;BÙl`ü¢Ñ0&Wº«÷Žãñ©Ûà!΋P.ûäøˆñ²²]­0¤ ÕÀø²Ø¯AX"`ŠYfDåÚÅnE„Âa.Qa¿ÿ=g¤‚Ž=È(ºZ3‹æŽ9£Î.@à¹i.£ŒyJ% c?Ùô~üÞ~Ã+’sÑK¨y17ΞrÆÙ㺦Q±d=6Â?Adp»‰F©†±Ö´ó1n&zú—° Ò¥­ÿ¿¦d2úHm¼›?Æž…ºz»¦úÌÊgÆÁŒÃ rê­s”’³Gñi›×´‰d~ž¼ Â=s¬»ŠK'Söʳ.ji9pÚ ¨êîÑô¤ZãÚÏ–›§ì5Ǽq„t‹?ˆ-ŒIÖBÉçë)Ég mé¾±;æ&\¨ƒ®mïý)¨2$‹¯4Rƒ½N¼¢•W½-‘*&ЯÂ*b {[qòÇ8kqsýÄG/:¸ª›éçö"€?ã¥wêGR6‹ÅÔs4›¸Q¸Œó[ya)M¤°O’Ê‚ž~Uù瓈ÍUé¤I~~~Ç–Æ3­ÉBÖ7`AŸŸFRÔ òá_¢Ç¥t«±1ŒU>-û?rp¬·ODJܵ¼“l²NT-¶¸p¤ª"ÏZ4 µbèe4eßX­ß¶dj¥Né»LÕG”Âþ_*j¯Mv´ð)åhî/·3ê‹5ðV1Ô©žŠ#» (kyVbû´…÷L8²ÂPYÉçÏâwA™jƒÃ,£IÝOH)jkÉê>cQŠTyX.ø”?¥Lºß 5i%'#$ƒ¤ x˜Qš(ZÊaì¹3û©9vÈKœþÎãÒæòÓ}’[;™ ’8¦”…®¨½Ã¿ì 'µí?x¾®‘Ó_ÃÐqCÕMy–7¡\ ሌ”ᤋí(‚#×ù-æÒHê֎‡b/7êšÎ}°ŒÂ²Jù <“òÚýálDl¬IàÃÜ6%´4kµšÓ]d/´8ƒØæàú~{‘™“ÊxfáI'H9VÓµ4Q *›/"róÃ8 zš©" ®9êÙñÏ_VÌìö÷ÔCQÅa5:D*ö¾ÈØ£ÔM•€ÇŽ®>QŒû'Y,7‹ØÕoƒˆsª3Ä»I q·@ë+@ÇÉT¬t»><臲É[“d… ïÂM)^÷g¢>U÷'F ˆ²³Ãtð™`7}­†_·æÛý¿ÅF„éñÆÚ–¬¦0ޛʟ”«×!áaQÖ%•*W'‡Ëj€«èÔ|¿@ &Xª‚ÝÍîáP`ñOäÐhdÔÿ÷»IQ$g~‘<ÇjÍßo¡•R )6óðc’Ãÿ7CyÁ>R% Ìâi, œºˆÑ®°!ºÃ©5N»óH§Äs!7?Õ<°ä(MùŸ +@«@ùñ[àF;žN@ÃsÛ¶µó‘ÞÊ ‹Ö+}it°û ’ã[e@¸ÂG“°’XUjnäqÃué*PJtœ6㫹nžŽØÇ›¨vj;…h<ɼu³ÿpúm6WFþ`ƒ»{^õ^ZŸqáú¤¼âoýþ'Œ'#0a+4-ÿneérUD&²ÈÄáÙ£N÷s™  Ïa½ìõZ!±ÔÑVñ5ç37‡GŒz×Ù·ÎßAj°P¬]ë¯'nJQ_üÂ|ùôÍ|8dÒ/zd;“„¾Ù°S¹ËÆI:æÓ;%8M­²|@¾Lo¨ØŒ=Kú„W{=Èë@ÔR}þ^€ZQ,IíLRõCŸ-Â*7›êN¼c—êzv<%< üÕå½hß7±7ÚýFÈ_ñYb›Î¯4ÆÒ+Ìë´<ûð“`=Y/|õ˘äÇ’£ï[ðƒ S½·Êw´Ã ¤õfਰô¢hÅ}ŠM"CÇ ¼¥ uË@—iPõÔŠÒbˆÅ¢ò7ÈÀNÆ'>ügùMCF ]dsØr¨…÷PÍ ¯ˆ€V’|SµiJ}a ÞôÊÖêÞš¨KÀ¨‚棿Sòåz§r+ÎSM|É`÷½ùEòÇ&Qñ÷–8Í#ôÿ)÷“B›q„—˜ˆ­½¼·Ò’kpÖ€ÿ)‹ZúµÊKrÇøTò:j×ô ðûú ©¨ßgÈ&J.-%ÇÖ„‘ä†Yf_5b«åÖ”ÒØ?áñ`YV½®õÒz#Ì;3¹þ•ûô:!ŠOŽWÞâ̶g¡¸@¹)MóTþ%YÏ´^!‡”ôP©›Í"Iú>.®ÄÏs üoµ@_ïÑs§OÙ“ N¥eÍÇ!ÅÑ_¨Ã‘ i­yuô(ŒvÛËR—àghÅ.!À6EifòÌ׭·²0˜Sp†qˆ’«3ÝÓ"ÒÝ[)tHç †¦A´14u9C? O z#l9vñÍtÓ*®þmdÁ?A–´ûT]“ß®S)ju·Í Ö$¼÷ɱªÒ'lŸÔw1 –¹[ç‡2<ä<œ®þ€{£†Q.Äü×®G©MìÀˆ(Ž…§óÂ8±ô·7ëè*º>’Ãc¢¶zžO`}Ó«|€&¯ÒWë<{¦c XÌ÷øc[ðØã†¦2P×~±Úvò®@qáh§SÃðwlRö—æ‘:`Ó V¬¬Û÷—¥O üdó–­<~mÀÍÓöAˆê#GæûN 9r½œý‘òqßm{˜¬ÏªÓa;%ºËOPWÖÆÒóŸ ì:OÍ_Š\íès36c'¦í§žŠòySVqŒ©c< U•h쫦FR²áëF›Û¥•(ÄÇÇó}¡y‡¡ÀZ6Î_ozi#!ƒí&çó+ÝwvŒJ‡/ÓLõ®¤»ìï‡Uã·X%hü‹ h ".ˆ¦Ä™P>ð0!œ5°±ò#1oÌŽf™*Åù ‘–çþ‡vS©‘g@­Öt[Ž3"Hn‚ÖÅ÷¸®ÜÊ¥pæÏæÇl”=¹™ˆBÓ‰µêêWœŒíô,Àkß—[–àð£É$õ‚ ê¨LuI^©Õ ö Œ±Ùx¼l=ÕxdýöB†íûr“d‚QÙßv0LÑ¡# 8û(gWIL„^arÚ¾X—Åýí©dàòzƒïÏZH×@÷/¿ÿ›-ðµÓ|Ô2l±Ü}/VîÑ‚t«ó“tÐpRŠÇŠ'çÂJÆ@¾Éÿ™‡Ò<³å= ¨°™Ï.µâΣv™)±yÊñ ~nn0¦}Ô¥6}q8jø‡ëï)i×_þù »ÞÄ>=¾3ˆÇœt%Ü) ÈÍÖáÚ^¤±5Ä Î¨¹|Y{@ê5Le¤UãÓš­i†Ýì)Éâ¶d¤ƒ$?F°É^€žÝæ.|ø CÈ[¼FãQlC«¤í9ûÓö²:À4-NÃ>»ákÑníFT˜‚ð9)ßöpÇÜ\6WÇŽ Ë´ªÝÎbW¨µ¬/Ç^å²MiÉó&ød¨5ºb.éúÔž¸¶ð(yaô“ã6øc ¥YØ‚÷ºÔQE|Ø‚•s“ªÀ¬MÐ(7MŸ§ Å—üä+ôÐ%ÎèüÚ:ã”Õ3¬÷¢4šDÝÌMÐ~ÍFtœJ‘±«Kv &?Ûe=~_<Ë?7GïþÚSÐf¤5©Òf˜mÏ&R½ 2ùùð{›¸}dS‘`…Yr,qñžI¶åÒ­+òËÑø¡XHã´Æ3uTÚrºÓFq5Ãê¶çÕÂ#ûmEy°\ŒW.U´Ñ{È=«S‡GÓ~BæØrèÂw¤÷G+›ÂY¦%ïÇ–¤‘g½Dê•™7H95ðÝ…‡ÉxìâZØþB3uù¬Oßä)uºÕï>Ê¡el{eFòÂ^@Ü3׊¨O‹ÉüÄ/ŠUÖRbÛÌy+†ÄÏA"‘ikC$£ò¦˜úðõVˆ±@;¡HqˆÓÝqÌöŽZ|á{Dƒ¹Ôé}źUC ÷ž·Úü’Þ°¼×Ù12[!¢ý4ÁóíFqæp¥\Jª7”ÿ«ùÒÌ•øRêX¡Iž*‘.YF. \tÕ7ÇZ” ýn]»žÆïÜey ˜ÜôNf„°ÕȰÇ8ªC‘Ä•oqCé*må/ îî)÷.M¤:toê·½]ôË×Ù2ÒˆÖ‰=Ú€/ZCDd»Žå{㌼°Ý 9JG›ÍquÜŽû“° ¹æ( ƒ´Æ‹—ŸÀãRcóÚk:ÿy¥ƒUÃp9yÁ;ÀÝd«ÚÉT ,:ê^á÷Ö6ò;#Åz컵¥uDù%_´¥bbé¾4CM˜ŸTBG ŠÉ–/¬9ýú!`jT,Ã`r” póàj#”°½]çñµì$8s7ôЮ§ã)¼’›–8>9ùX7— `îçf<ç.ÕÓ®zB.¿z³(–Nà {£Ce{ zy®Ä×›àÆ0ä÷)Z‹¹A!¹üIC'ݼ?íÙÙ34Í Ö¹7Û>‰ù Å‘-mSó·É#=ÒÖª ž¦©wóP$‰¨b¡‡ 41e*¸®¶ü‚ µ,¹ÍgDyÔAÜRƒ+ó;ÄÀí)mô5Ôý>}B_´ÔÝ]d€1`Î`ï=s$Ém·sàðx@N¶çku'$·)KÞÞþ·hh>«Àgìåê™V€ðô%œ Ù±¡Ì 1ÜÍ+—·¸²–O©,“ÉFä =‘GˆÍšâ/°M^Ûàç"\®Oû_ñ›G=às,4ø ÆjÓðв"-Ý?÷ ©TQL]©î.iŒe“ã V ýsI:Œž¡yî^LMÂç»`EàªéØ®¯µìgBÇù+%´D3zF]}jÓ,Ú)ÌðûL:¦7f(ÿ…~§À\~))†Sk¾y_PnT¾½—Ì17©=´Â‡”eŒv¡>Û(Ÿ(c‹ÌŸýžúH :"ô#!Žˆ©ÜíþŠý‹ìK¾öv·šýÛÄÅGwv–C®)å;>D,5–´S©=s\¸_1ùn%0‘`bÒ dUM¨Ý«ÄKe“¹ÓÀÄŽþQOÙù¡ùÄ®(ÉO èþ§¶ ÃöbV+sãÀœÖõjÞÓ=xFÓ%6²d¼Érú{â²ÖùN‡—ÑÆÎ*e$ƒ¤è‘õX<nS¶¶ ZkÀÆpn¯|ÏÅ&lÙ7°˜UO3×l¼ZEëøã‡4ŸZW…þi:}J>Ucl½e%7#¦·îatC½”ZpÑTkn¢31Cã·ÙŸ!fµÁ>ûçMÔµæI¸Ÿ÷íÙÖ„b*üjû~#Y”Oò^-†ÉÛl+n¾¿¥[7[«öÉñ/àñœ%’¾Q¾Û›?A´¡@­ ØÃ<Üi’òQÁòOC"îR¬À@Õcà€àZ°HW¥Üoy2»'®Àu°më¹°w% Ùõ ºqþãÎH ¹%ZeooPá›’&¯@sÙÚ#²íoæäÀƒ¦ûØ økX×¹~É¢ЬͺÜ}™ä“®€¼ yKl–.J¤/ä´×-ÑM®6¢ŠÐW홈L¸aõ®#vøžÕý¥£…Ío|ë¡Û‘ôºŠ¦¼e`0iùˆì؇V£›qRº˜¤Üŵ‰øäÊÆêŒ'ÚhN…r·\½eßÔ•¬EÀüÑÝ1Öš¹cKè%§²á}ìпôobÊ]c\^j‚üóë5p69f¢©ž½ƒ[™­Ò6LI`p[Ï@¬$A@\³“ñ—ãŸ`3] î4GL” ú)ak»'€ò³–Üé°£xÑ!x¦øwÄ_Yø–4È÷XÃ4?¡Ü³ ]ˆ­¶ø—z5¢‡àRhg÷VaEÐÊòµöÍ­JÖYïÓˆ•„0%«1xF¡íRà‰ÄâL,­ˆ%ŒyÌöjó˜”;IH¨VGˆ¹Çzý:´æÁX äZØA.êì'¡¡¿l ¨-¯n¼/ÓvgmEpë9·>Ͼí+âêIh[ëJ}ö %¯1ìwôJ˜ûëF‹‹Îðé[Kz½%ÁýÖ$FéQTU„íÝÈo;µ¯¬3Ny‚M€ï :·qÌr zŒ› Q[YM z‰aŽàûÚPkXùC®Z'Û¿ˆpa83C°MlßçòžeÙî¬jôˆ«žÙ¥ÿð4¥´Á‘Ö8!(È>¯!Ò Oäïš-æ} ýð^NKÜJö…äR¹W‚Á¡TâÈ¡Uù!ýÿ»X!ïéqØÚµ2xÊH\þkëf÷X0™3Êž‡¤â¢¯¥ŸKyƒ0ôxYb:Ë7ô›²xÂ3Rô8HäžÄ…»’GuR]½âØ'’VŽÊþ8ÀKfа¥B¯õ y—fÀKƧæÕН…Bæ#ò[úÿñ½$; 9«s iÀ)ˆ[«Ô+c~ôߢCñÈÕ0\¶4ÄžÚú‰tiÖTéa;‘¬$æJ§º_’gÉÖ 8Ù+ë«ù.e§ÖpÇ H÷é.g§"~+¦@èMåãq%{¹rH›Œ%òÐ7€ï±´h*=‘sD€[Ë ¨`¢ãê hý7G!”;Í_½p®®x´èÿ /7NJIT[Sÿ0n-=gxÿe¥æ6wΤg½Õt®ÌÆyb!\ýó+HodÛsŠ@ÏQ<¨Ý2O„›ÝÖwËÑ)#ñÍiÓrÄ彺øŒ!¿ ÉC–‘ïI”ÀnnÅyÞ8~P‰mO«-%Žª"T$Ñ0'…d 6±k8+ZÎÁÑ“q=íÃåH=‰@à)5Ù!ˆmŸ66!µ¶iã2ÏŠÏîT6Ò!Í2Dpº¤Çf§‰ ¢5Ôôz ó‡tå„>ðŸ(¦zï9o}²Ê‹¹ʪ‹h²ru+^2/4\ö ZƒéÎUœó&X7µ®±_Œ¹‰§)„Ä2"èxã?ª²äv;­ê±~LvH+tZ¿Š±"è ˆ1h]µ| s'Jü¼%ŠæSÑ` ÿ¯uêqϪAqp:eL ¢ ÅOÛ@mûáj›þœ ,ú)H[¥T¡}E Ñéáy–Ö^í^¹iŸôÃÂ㣚k‚ošìJOÑ‘v0ò­†å»U;¾Sɺcs$‚ ¯h¥r 7ªé.Ë4m$)eª ó¿Iþ„ö¹øÑà¬õ595:°ðÙ·k —9Ýq4Þ0}:ËÉ’¼ùx4e<Ž1´Ct:œÇ·f]GLA¥H ¥îà=1s'DMA){ÄPÞ[‰¬ëUËaYc9ÚÿM2³Ï•eúqâoÉçRâ~Å9 Î¥•)Ð^“õ¢Sé•g·hU­VuÊxSÝ ¨1·Rù׿!Ï]I„³RkBÎT"¶*Áíe¾Ô;uóìñH@„ê!Šô’J;ú!×àQ*Ú±·º&]¿ÉÅfo4wx Ó£ÿv{ÝmwêzÃL‰’µ»&5J½¶½â6ëé,«–ùz£áÚãYÊz”„Rºê#Ãì‘4þæ ù¬a·`žƒ'íÈD‰Ä¤»É FºWk¶¯sPYw»ßW;Շ͓“'¦¨‰´¿Ú‚îÌNÊ*L7°JãëáT Òà‚­“Ù'4D"ò ‹îÆœìY‚‹«Z&Åí ‚4)ƒ™·YÖd@†뼫ÙüA9õ>í1§§ßìçþÙüàYImö?æé¯^г: ÇBV~BÒDoGéô÷½Üö㈮(þ‚…gV0zçöc×8É8Luž^g|,>ÔWÜ4^¢%©Å ²Zôo½ rÕÒt{š ÊÒOa"M%^ä½?D½EéàaýcXÒN7•ÔÞsöe ž‡Ëÿ‰Ÿ–±†˜*RâF„«­’ÿZiNá›2𖟶ˆ´&ýUÉj¬ÛN—ñbÝÚ¬}Í ‘ƒol*,£q®]—_Ãnm%þVLƒ$/`Ê4cw`GT´/Ê’ô ¨š3‘dLÁ=ùTC¶[!\þã§iÒeÞ3{ö DŠn{Ú-=QÈ´“€wü·wÆ4_°wôÿ‹>K1œØÓ¯^Ù]0 V¤‚yÛ(Qå܈ܧc:yþ±oE¨±‹ÆM&QI ‘DöŠo9\òLTL­èð‹W›«Ób¢²–δó™ÙfÀ·±å D,¾'ŸRe:MÊMGÃ3‰SöV¾Y æø/#v쯳ÑéϵØo‰ÈŽö&ÿÏ>óÍ<Ãßtž .U™1™dð±ýßÔs‚º°f]SáÊSblú]ý垲ͱ¿}ù!Y“`ï#„Ñj[‚Ó¦,(üÏw‘+“¶â:¸[6+½ÊX±`iŠݧaîQdÐñÆuhÇçDUu¨uôÕ*~û\Û ÏÄj㦺|aÝqŸ¦Ô¥‘@ÎRžÆTù=ÓJ:¯ˆ`åÏÙÛ-$ÔV^o Uú·‡¿!¨}k¬*ѼÅ[o^€é\cßÊ¥.ñkdÑÂà«yYn¡¼JÊ]x˜ž¤4̲Â|\#]ñ¹uÏFUgn‚á0R‡-° ¥›~X=o]Ën°boØ*¤È\ÝIdY»Osÿp•‡õ|£’ÐŽ/@é óMþÃÎÞ‡èt‹=¨×ñ±Ö¡9ô‹zaõcâE[n ¡\kæEö¸CÄæZ<tdCí“m° ÑàÜSáÞ,™.Fw…ôÓˆõÑŸzžŽÙ¾HäZôZÑ·çø& FZ4ˆ®{¨ýJ9o&cÜç{(t?ah32¶ÊÙ”ÿ´ññd¤6G«ÛOƒ².%·ïʧ.3©ÿúzÝV¿tׯ÷druÆt}ÅÓꉣ,Mê¿ìå * ÿ!M¸¥qäÖ–<Fð­–ñAP1n;Oé˜Ö„“IF^u¬ç;Qrx˜BQ¼·ÔÜÚ€®ú°-åκãÜp$ΔPÆÝ°iô"Ä7!Jr':Û•Ÿàñ‡ÈVyå?8±r(ýàèsA½c÷ vû ˜ég”×9¦¸’¨w1h^?œ*fiÖ„ žßD)÷é-ù‚Ò¼"*ð1ÅoT¬¼Ëô|sƒ{ãy…è5g×a |â×âÇ+{và‰5·_ƒ™³±O 'ƒhæ&|ÙJÀzTÜØ `QJÇ@3¸PÙ_ýNÐÜñƒ–U ­‡úá¼»I б„=R\Íð~âYòçüènäð '…– éÇ}†da·ƒ£w±Á !íÜ–^Ñ‚j…äû=9¦†'‘x•ƒ%ôÛTñòP§–ã”IFxaŸw±\@—:…ƒÞ Âÿš9‡ä4,z x1Sëò.öl¦œ1k-ëUuÏX(~P6 ƒŠú§<9•£áüžj€5}¤->¥ò™i¬Î¹ò£#³#Ûš9$—3|ŠYy(´2”'úˆHÏ7 öšÁÅ?¹£nɇ#Ɉ°ÐWláHçËf÷ž#ÀSo}þb‡S½—Ò£ñ‘ÏKYºÜyÌɺFç#•RsÏ Ýr‘/Æ!³â“¤Œþ=ÈÎô:©û9Òr»ºFr¬:õ2êu$\”¬ißHò%©ˆ` ͱ«¯ÖÜŸ:PÚA–‘²+G)`Ǩ/l%ö-•0ÆçÞö×Lrêu6´æ¬éœÕ%(Åý¥2’~qy–òÈ ¶‘bÀæ·2É]+s¾ºêÕ£êu 4Ÿð0û!ñ!Z^>•帿ë.2ê“· ¯E+€ý‹ë5(™‘„²VÃ<{“n9¯í@·){‰ãLÌ¢€`¤5Ìm­óc”8bÆJcP~Á€yßÀ*9Cµ¬¨ÙO«.¨ ´jE(û”Îæ‘Z_ãlã{MdI>®ˆnœÆ8¡ö¼rÏj.G ´ä ëhI‹i/›%r™*Ñe„ùÄ߃꿟"à:ÑP\Œ*וã@ Ü)%(G·Ú|«Ód6^NÌ99Ž˜gªt¯áøv.[±õ¶µEa‰Ý‘‰™†½ðAÞÆËÂFqÔÿ2É?Êà¹SÌwž×…˯S1Ì,aª¬0fNïŒe@¬Îý!:åZ‹œE­&rÈxÍ–x³§=¿( eî2" ‰%ýL…TNìÈ»­Ôq}¢_•l@Èh¥v¢%eì´“±‡Ð­â¾Z:*©á·ÜV } Ö™·¯l¢•ñú< Ü8¢ÑÙá)&È»0%ÝN®Qû·®«•[ ½ywþöŽc˜¾v`’…¬¨ÞTèpå2¤›É™­ŒJGf¤×>*5(€¿¬gÀPìî¼PVÊÑ1^Ôb!£³ÈjFRìÆpñ~SÜu­ºH#æ3©æ®ÿ@8j|1=j¦·ÉÙo«N™fÞ8íQóy¦º1Y8S«›ô.nˆš-6Ü'×îª]åy½”ÉQrÁÜsGèó/4 ¦3‚&ÕêʯüÐ=Œ”Ú¯E ™?‹üóIˆ»"¨ÒlQ£Ùš hí2g–½¤íëÚd›'Þà!Õ øÔB>ЉÐèKhÃðDà^VØ£·AtXC·‰D²ìoFαmñÉÙÚ·™FO…‹Ì|2[û¬÷÷ ð ž6ùó؉Î)gþìýá7òX¯n‘¢ð„¦ºÛi:£†)8´Ò³a€­{Öð Ð#H`g,zŠo Ýå™Ìx=ÐŒò’T] õ¡(Ô§6 J„ÉöØÖÊ޲Þ(F™œfÞ¸'^3ûÖ)ç(Sú¶k.6 :Íc·øî¤«tÛ¥”1Fyë>+ù)TþRòû“Íਭ­†d;ðˆÖÍHœ„r®§žbg³¶{•AϼðyѹÀ3ˆU¦·ÀàÔ^|Ç‘ñhTÊ|Ü[h¬ ¬ï”_Fmá>³¯ÅÎä†Tk)icz›ö"6r…·÷öÆ…Ÿhèn Zßôq%nþò½õt¾Ñ‡ÆÁïk$~ái®ýÐÍJðYÿjg3WKõÔ3ðŸ%»’) x^{N'ä•þ}–áz5õ“ŒW鼨ÈOÊ)N˜¡ÚâµÛÎF”Öv=Å™p[è—¤‰½°ß¾¾}ŸRÈ‘%âÇÞCXÃâg¤ešj˜Ww Äb¡Ê\¢ÜkjµÁÿ<ƒi¼t]Ä¡NÏëryÁd¥ËC½c~ào¨/eŠ$É࢒žn>#r=@LÕ½)"!3‹÷¼ÅÃ8Å>xsV†vÁÛ¦¥8wóÙñ„KÁËc‹ƒVV²ÀšmK9LÖç©…/ýõõÑÃó“XÏraˆýÚ`ÈY’Ù£êtÙ]QÄ»²[6Xõà]‚lõf˜öZ ­b}‚i}ßÃÈ, j¿ÄÐê?ûâ(ñlh%uÙ®×*¶ëƒxìnŒ L§^îÒô#…Òø^²“Œ“{]A# 3¾=¿`ãe$–àØ#µÒßg–ΔŒxn’˜Œß£éS)µ(F ó{ï!¤æ$=–ÙD«W„-bfåøVgÎç̵—KÇ½Š¡Ç»°ø1Å’÷c §ˆ¡EEÏö &@›³j¥{Ë Ã ½WÒúåê[ŸZkö`¶ªoÅwdਰ§å9×1jÓë3Q,YˆBÔ—¦Ü§ß[pcïAœ£Ý“ÿèz¨˜iÐeA!ußVó«uçOšzEÈìãtšÑVÿûÕK®²V¡Œ-6VŒHx¼¨B333—¬'ª°dœÑ†¦ÎŒŸÂ„0WF`áª8{îåX—[8×ï<•Bû¾MLuÏñE±ýWI؉ÚÙ™Êße̊σQæµö[[D ¨D—.§n’ŸFêîྗsX7%ù/%’ÌÚÑ'à%V\Uüô&…”#–8öZ"{OoSgsöw'y[x]Ý‘&ðÇcuá.3Xr”V¹Ê@øLhŒ6ÔÛø(]¯©ÚE-rLD–~Õ~h ËÆ!\ÈmÛœ!ŒÏ|#šÒšèuW0‚t1øEzê+ÑMz’/hôQ0ÓÊÈ%ÕÔüéÖÍèêè}ê.ú­…e‹§H+ÔaÊx¨Åkµ§˜käÙ[ÈCÒˆÊî‹Ë°0’?}-}QdãªjD ðŠG•¾Ñb›EõO[ )„Tº©3D““Fü´k¹×Ëù ©‰ò¸j¿˜”Œ,|mÌ€H‡0qØi#‡˜Ôh©v®g¦w4©s‹ÿÐi:&#SmÉWu Z ^'w‰‰4T'¦ßË„K‚?éÿ ú t×½FÁJ3‹n™ÛŠ?ˆ&oæS™ó=­CßWv¿Y¼³ëc”j‰Þ9Á@!7¾›`°ÚYÍ–9º»;>Lf[þ’ÅŸÙ xoégüèOüDßÿÛ¬—ñðÀÄÊÆNJÅ{»P‰©†µøo£4À ˜4T¿oQw=qUBÆ5Ék`} ~Àî­éªî;¶c–‘ò<ÉÉå–åíÙ~ÛnJ¨!åTo>¨ÒLù B=¡Ý5ýZÎÜÚºEÛ9˜.©÷] 6ωœü4Ês²à±p=-òž^»k'ÄüYñªä™.OŒIh5•I4êtºÃ¥]øÛ7ˆ›¨dîE[Úþãº*Mkâ)óGòôÚ§¦ï"Ì÷¡›G±©BY²î ‡@ ïÍòõZføÂí +Å©_ûÙË1Hªm^^XK) gÝ>ñ _UR]èê·AQ¯à—„«Ø?Ó»Díç»tG ì’£ †,)£Ç§—ñ°­p‡õP"}Ù÷Þ£@_ï܉NûÈ"‹›BíQu<–å4' ­"ß©ÅÛÁeÕT3”ÕúKÑÉ·T!…ìσÐy•„@öjç ¢¬J x‡•GT0£È¥ÃªBWb+€ç<Ί¿~ëXðž³GÂ<ÕD@ûYj-NT×Òû02*1N’s÷¡¬!ã@<ªD´ºa±f õAt>¿£ ÜmAÝÀ&éÝÃx¡èd±é?vÅ8\dzP1a:øqqH-¹baü¸Ç"¿v, 1\H5Æ€‡îkaƒI>©`:³¨OF1Ñçpôë Ò`%V>lèy­“#ª'ÍûX¯p5m~†‡3ŠE=@%öè®ÁÀ³SPÜ#JýdCxnîÌX%ªÒ'zxU6žIv‘vÍt¬úI©^pz9®Ñ—VU‘Em²"êÀΧ:x¨Zæé@;ŠnHûÀÖ¢”jîÖäÜ—ZE ^F¢C¡œÇ]Oiû¬Œ¼¨ûmBè™<_XˆË£_]œ6 ~p3`Œ2®c' èþ° Zæ¹xsˆ°÷ù|º_Ô°¥ŒZi"‚yPó(aàùYe'ܺõN“ºEG}ì{š‚*2â¼ù}àƒ²ëÞso² ÅMÿqø’¼lV÷°L"ºŸjÚ–·Øí"t³D”q¦X[õöY†XšÏìÂ/L¹¸„Á Í‚4Yvq· ·¥BÈÆÐ#^´#ñ4n +¹r8Ñòx5r˜§“ï <¸‰Íe•~ßñh{KÛîÉtèP7h‘#Eü#üLLrŸX«áñÈñ±$ÙH–½Šú熚É.Õ>¸—",”ç…ú˜!›áv ¨xe°µ­f‘âÓ¨ÉeE¦šBH¾ÆÑcƒ'j†=+—C‚›‡óG/Ô’þ”àÜ×/»A!L¥•C¸_Þ™+RµŽÿgŸdÀ^ÛwÑÍÖ“îû×?ßæõ5 cx>kÍ<[¤ÆÙ`*gcàƒ¸ &Ì «ü¼—¨s#äË–œ‡Ÿ´ËAžI~¡#Ëãp‚“‚¶RX€ó}bÔeë4M¬N€x:Æþ)#¾%Ñ'üœ¤G[ÁDªÓHÑxÚ³ãì®XØX®Æîhh[# ìjMOKfì…Îôá^ð–Õ:y­öGöcÓ7$Îâ«EÔi(N ±TG[.=@cÓð |Ñ÷·Ë+{S”š?±f^К¨òf ñ}&¶‚ßëÍúx¥‹‹î¿qY¨oòéªáÁÇ•s; ‡–ð3„(•|ÙôGp9Bæ¼M´7Q0Ù6„ék¹GÄ úϯó($j³%EÎ7ôqO0{²G2þ¶Z4gU;K2險3n¥?­{¡xLès9tZ? اL4&´ÖŸ4dªPmD©Ì5Tݤ€Þý!l £°×6(Úþ$g(®Ïms(GµýTyĺ£‰b‡X9ÚÄÚÙËö €G´{ªT3Z°Ï}©uQ| 3MÕ?3/û¨£ð>ž˜ù>2Öcf‚~K¡ÕÔД!7æ(Ö¨b›³¦2)<-À&úšB(ÏÅÕ omocÐÃ×ÚçAö RÿW𒦬—ív.+½ÊËÔ—Aw.(·E6È©í• A‹¬Q ¹áÅ =•«ƒ'³Ào™Â[VCÖàµpZe1IŸÍ?×~4£éÜö’)®úÑã—-ãzÏü:þý NC¡Ú±Œ®êʈÿÓ×ÿw‰tg ËNnø,6Á§Å ³ý†cÆ>‹µkU‹ËËä›)_7¼9Ò·àëgqÕ¬ìœ(f¯žÄƒ¾tº8¥(˜×‹*½~ Ÿb«D×NÞ"/2ŒöV5¹Ž¢§W—ˆž3oæåÊ<÷‚µÆY2bÛõÒw‰Y)N™l3W­ e•º’¯P3ò]ÖöYªB“¤ÁqÞ IE xsä¨Qx’ÏÕ@ƒaÇ”*¬ôñÙjDEoŸ“6¼œÿ5b¸6}|‘ƒVâKwS[ @fŒí©ç Œî„úC#58ç$Æ(O>¹LFy*IBpªmïUE“içxzwª°_Œ5QP:ƒâÿÝARÉ’±òÓÝN—TÇ‹‰0)ݘÏÐn'©4R–T_0Ã÷`-‡GüÛg ¢Qi Ó˜ÿsäwKÍ,Ä”e üDQõ3R:´Ùw_b>Žú@î¢Ó>Ù *YñÒôº>´z?ú3 Ôÿl>X˜­þ¼Q«a=?]³e¹™D‰­àÝå/5à³.¨}•_/›½+/ÐZvŸ¹²ÜwÅîµA®ÝGaäÄWÖ¨f©†Ÿf0šJÜdñ ÓzºšýÝ|Ió>4Ò¡¶ÃV~¨B¿'£[u²­Ûo ?pÑ”XHžnÅî/*ö©±úák}`U$×}Œòs8ó£ŽQõÍ-YþÏ ¬PªÃÆ^%uq‹¿¶qéÿXøl >ŽÝMCHatõÈÒhHFÎÞ'§Mþœ@5à…~rgím¬´3¿6RV7Ü:«h°‘,8ù<É ævºšj˜`ÛL„K Üe"®™çæ/#öa Þ1ÅœN‰÷-é!JÝõêé+½pôM Ö÷¾_g'¥= j­±Xfèðàû¾ D„,hÀA›ϲwZÜUÐ4C?öä³G¸÷g5e9zˆ ž!?½¶ÎÕb`å-Þ§QœF£‡L?¸Í¶ùæ=vŠ3 Ù_s`CàØE‡EWQ¨èF6woÇúãç|Åö3’µ…ˆGžXÁÕù-lÅa¥êÂ^öJR1—`oU^¹Ï„¹óE>õû1äÎþ‘‰y½àkú x¡îiø®ÂWƒÇ9%%°UñS+chŸÂè騗Ž%´ Yµ˜ ¤¬?9jG*0¨s÷jY?6bþ̬ßçÎË ·ÑŒçgDG§òËìÀ×èä{ 6›*o”%À÷Æþ¬Ž‚[àóœÝè8ðç¡.({2¶5 ž&>ô$ùQwàrêg¶C$ÞÔ—ÅEòözýÓs^\)KBYZÓ©†Á]ãìî‚C›¾Â+ßÜh¬,%Ç<Ó¥u .?[oñ‰žSu·“¥ZÔ2œ›ui „Azå_¡ÊC\°kicU‘ʧ ““B¨eÏ1Xh⿲2ö®´5z9Ó’Djµ¥sÜt§–’hÂdE?¹`Çä`Ê‚…ÖÞ,>³é„ŠÕ’eÕJÛ×ý®@ä^øúãqÞœ]^ÅBn·EÌL>xÐf*ˆsñg“³7êÝ{š24†¼d—Ææ¼K o§ÓVÇ[0"îúƒKè£÷¿–.±×²'+!u#þ,T‚¤?îçúSµ1„Ó_#RÁˈ@ÀºÊnì_oþ§2Å̼ŒÅk bÀAô‰B ¾HJò ‡ÈÒ—¢E!Fiã(Ì Ó}¼ ¶I¯œÚ2‡¥F¹ƒ•ÂûãDÄ[‡G¬dº¶Þ$¨)*pYF²@œ(²¯ö1Kùhï}I–.Zi>S ³ËõÈ+û‘Üý¤QxÁ—D¼…1òZa éoFËÀ¥Á‡S[áèÜÝÛ-j¶5Ñ,nT³%¡“£l>4œöú±…NšÖn—\ÁnQ*÷¾ûï Û$Ç~X"ù£ØÉ«ïƒw› 8á+ýq‡1¶+³%›ÉhsgùK_Ëf_…Çcº0ËP6h±Übÿr`§4Xt÷ŸF°‹HAèÐ6Ó6ïoYwÛ—ÙƒÃ~üݘÝÃõÜç½xå³kÄÓ–6ÑYϯ½‹TG_ošÏ®ä]«ò)ôëÉòZðùuªÝ[ÁÊ ]¦½[qZÓéë­2F£Ï¾ u &ºŸ3CмÇï¨ú"MìÚf˜0£Ž‚r âzÒxÞ?—?fÞÄw›±ç"õ²Z!HúfCŸ³ÃsŸá€ë¿–ÓÒ'4bÊë¸ÞÌóœo>V£%G1,)æÇ`s»¬ø[Ø»Ùa&PðÝçœKuÛ$+)7]y³–Z`ÜÊSžgTz:ÖYxµÆ&Ê+À¡]\W4S7VF*`%Ü]ž¦õé†NÑx¯-¯//M@J~YÛ33ÐiÉaQ%%Ì{Gû“]þþ]º€®¥66T žÅ9÷¿r©}^ øR[Ìeû¡XJù2oõ’ ©|¿E¯ ¸›lf¬9«JêÆÌLÒ@rå;¡EWŒëA4­&ŠžÿxãéÌT¼.|Ò–Ž3:v¤@â,ˆš/áñ§rïÀO¥Uxj#t‹ÄˆŒaæÊN¡çóÈ ns ÁªTíêOe!-}fUœ q!áÈXÊ ×ó;)#î@—[ÛB«¯ÚKb1© $cÇv“XÒŽë±(5¯ ¸É1d ã;Œ{‘b}·Ý¹ÛÆãY˜Â àM-Rö^ÍÌ[Lœ¥¼í³õ6wÁuN!Á¡ó¶®8õ† j]J³hr6Ûq~£íÒ£ÝiÂ~ÆKOSñéW°‚ñœ°Œ¨ïÞ™ÌóÑÓ>mðÌNY ³2=ng€¥ŽŽ_OÛFg|ÓÝ7GÑ¥”2HA²„xG/!þ{?Šs!X$y“P}„¸“z*ìpr›§U5üèt9Äwh§´4+ÏuW¿Ï¸RDç¹óŒf#èE¿H±zÂúWÙjñ­ј“ñk©]~¸ß4jÅë6Ÿ,8j]çÍt‚B/Û Úf5Ǹ3â«‘Á÷Î˱uæ Àqë6ó‰xö‰™¸¡?Óuûœ/$ v=››ø¯IׯíA5²ìpiˆ:†>ة߰¼G?ÁãÆž>À¢§ðÉÏ/ˆ} ñ l)Þ÷’uçlô‡HåîBÒjb²ÿ«F¥%Ž8øÆª®©zÄÊ{í¹?ªXÊôBŸTö\Ø]8üŸ o¡R®HñÏz…4}K§vüß5vFÆuº®ð÷  ×oHÊyv¶šºW…£ hÃrò`9Ý òý$œröÿÿ©¼«°vdáæ¥ô¸mí<ÐÎ*Û}êÚ—›°‡³ ±ÔEO½¶b³üŽi#lþÏ ¼ØmÁrñ…x—õ_“¯•…@ñi^9:¸4<³—ƒ œíá˜Å˜Æ­QÁ¬QÖ˜ÃæXѧEykÿ*Ú=ËÄ~˜£½TO”#1CB7eípkЧOç"ø¡>9åTż§[òlp%ÿu5ÈnûÑGÈÿ¶ô‘!)‰_]°z™èê+q,µÏátÄàJ’Î_md¿a”ÊAú§÷×ò ñ+u~™ÌýôüP(cX/9‰ciž‘”wÒ¹§ãé€e‡ ©Nâq—oOŒØ|ª¸h’¥FTá.9§ØÝx "™jqÑ噸>U±Dá5ëqEШt+¾[mwò¼`Á-çÇX‹Ýîþžºým%cÛpgLµ4ÂJÖk™5M:¦P=ØÍŒ=,ú%Òq¹,Z,^q ŸÄ´ÿ|&k\hûÀ-â²y'cpYzLôeT¢0bæÄç43ucøæP¾™°ÛM…fsâ®7bЪdz°±ásGÏ—æƒâQ÷%3’ _l‘FlrÕÚÅÙN!©"¬/rQ¡ªŠÉñ4üUµ€Aÿ¸”2wkìÒ §·Ûù3G1YZ¨Q=ÏS’p+ ‹|QØãˆÑD‡a“¿;_t‘¿3ØÂJ”­»[¢]ÝÂ&ÿäTf˜&S˜m0j%öÍÏὋeÂGöeß ¼LÑwë±­m‰eGJ«lVÚÒ±ƒ“M íx}~ͼÖ+ â£|ˆÕÐèDÚ'í “XWõÜåïýÊЂàÊ]¤xá^ §Š4N®(‡I GɰðAåf]Öï‰î“þôI m jDñƒøÆ¹býáBŸOQ õyáíÀ^ Rå7p¸sQO K$~Õ8ö9o´áÛŠ¤‹U;Ê]µÆÎð÷„ÃaÚö¢ºUñ5¬Xi¢¸i?¢éî3¦-åzÂ/àk2§ãñ¿EÆ <ºTÂ[º+=jØ >`»†y>œ®ú¶nLxر*ìhˆ(Æü1¯ ¿¯ΠMÚı£œ¦1©X)ÒA*AÄ{àõ•šŒj­¤J£´j;ü〡çÙlqÐ;Œ>ÔwäÏ0îøNbÞïžøÇ÷’ŠŽ]í¹¡y¼{;ý.(sOî©S!J¹é«G|óÈÞa7ÍlͲ@À¥tŒY½lc¹†š 5ò½?Š”ïÉÿh3Ò•«¾rKƒ½¡Ó­ÁòÏ*wIz¢*æ¤ñ~_-—©–ù«ˆãJ«$EáÁ¢}S+Qƒ÷b`2¤ŒÏ^ZÀËFcciýޝ3Tñõ€Áh£Oúä3!Tb%SÖ0ÈWçí_c— ˜ºäAÄÑ/Ð4ŒRŽ´Ùþ‡ô·ôcà< ‰•oŠg]ï|–3b$•KYˆd˜«cÓéË—å§Æ.ûjíµù)†•…=$ÿå².ªÙK¸i)v}®r.‹ßë5¬Ì7"»4—†CšÐw•¤ÔH줟?¢sÕB!…Ü…àï1kp’F=( ÝÜþÎÖ×ù £þ3EnïÇHWUôïµRgî?‰¨‰__ã'jÀH¥N9˜É*&YÜÐc†¶×U9¿ø}³ƒ"¸Ö°Ä\(ÕÒî@T>îÉéX%û,m·ùøÚéN³íú«Û|AB^% |n£ãd‹/$ˆìðahé•ÛàJM^`òBZ캠äw1ÙV‘3¤{Ev·³lµ›aàº] Å¥Mž°Ê‚!Ú'¦WI5Vçc¼Í =(Í…­’ç¿7„f•ÉRçò©¡ŒW)Yë´pÈ~fGéýœ¿&¹ÆÊñ[§˜ß–b6N¹æZI–Üû1œ¹rf§U^h3›HÞµNbÅIø4»óéó®éö=›·Ë_˜Ô°Ü¬ÚÊ9©„iò*u¯M˜Û“Ú„cËi¶7Ã8b¼”jfÞØÀx£NX6H;oçñ4\É&v SiB5$æð²ž„²– ƒ>HúrXiÆ {ܼQéå!OØÎ°›öðåbä%Ó¡ >‹çÒ[îu×À…è„Qï:y>©Î"0= a¹ˆÎxÀˆ‡ÿ=‘÷§¡Ö9ô¾¤|*] ¨»ª%†âìÓBWEÛhLðVyx¦f6íót-¾8¹“;˜Os”£ž¶ân‡OPô¿®ŒzMV#Jzuºå$’‰èµJ9ñS‘í!uag°ÒbôoÜþø`¾Hت_Øô‚Ϥk4öÊôp,|PòûÇͶ2Ø¡ëòTðÛOÎ<ƒ(ß…iFEúTüÝçctp«TwИ0'äl­GBgÖ"¸¥s`{á¸à:D]séX1ˆDêÁ˰“å#E Š9™qúû¿8ùAÑp€ky““PØ~É÷ù3ˆUPë Ö H}!÷3ZÎŽó„G·árxÁº± ɽü~”÷¢?t•¾ Ú;UÕ|ª¡ ”àRsÊ;¹søÇž„ u³ô²Cuáyû¹…HüsŸÇÕë¼ç;¤>êwš¶èá“*íþD_¿#»Uh§vÕÚ@1{þ&ô 9Š|/r÷ÁÆ©ˆ¤|ˆ¸›5´ Nve?’¬F®Ûç Åšüêõ4’4`™ÝM®1Z­þ×ÊY$R§Øª mð!°êûUTiùmK@⯪mìÊWtÃŽR­ûÄX•<åo¥òÉ&üÜ‹Xž³ÒÃí•{¾“re¥ýç¶£nƒLáæ=wðäŠéªÍ“ŠeÕÍœÜDË.ñ*±T„4Ÿt>C rÅNЪáÑÓðàè—”m þG"ÇÑÎäBߎed ÐÓ¥/䳋U¾Ô4}ΗlÓ+FJ bõZ ™Èú¥>Ë“äÔvŽ¹Ô‹ñg£œõÌ öƒpâ˼—Ã×Þ¶¬ß1%Ìi)‹%M·“Ž¡èfNCô!î˜ ‡\ö• ù3ؘ’KÏ9T}@é+A1+¾í1­º†Ãþ¤M™QIp_Ïw¢4ÈmRÙ%ð #^©’ÃXS(vã6Ò•Fÿ_+Æ J«ÌŸÍ3öHU[¤ÄŽï-D?—kILf(îÑ'[‡*PѹþM¸í˜˜Û »ìHÌZ¸4ýãSÉÉÝè©mrf÷…uWÁ}„$5#å‚>L°G–[Êû #¼ß¦>ѲŽÔ2ÏB-q }ÇךÒT*@p£+)Ì&`¢*ýÎ@R Ä#Û\ŠV"œilhµgºí—83UË6b§?³Á~èÊhͪ꫹ÝÀš Ô¤.ñlªÖ²S~-FKºE¥F¾"Cfœzè´À|E|y`õ&×§á”–©a"›4mBƒŸÇÃÝF•IsÉùä¨8ëÞÉ-¡XFÝßoßBö„P$ˆ€ÙyذR7¿ZiãÐó­×ìc7ÄIo¦#tž¾Î•„=Î9ij!ŽG]ˆZ}´Ð«ó¾ÅžiÀœ 3¯‰Ø×€¥GnÒ®‹,¯sS‚šŽížåeXéàù°ß ÆHßù¯S}r—\œO£¼¡©WüYÐr›j;„¾ùb˜Ò4ÄÔ >^_vC·JÂ?ëoªeäbkx‘pë;ïM}øÿ™¨³ñ9Ç*ï4#¸±…ÏícT‡Ù\+‰B û¿ª®S1“’„Á‡«)õåh«ùÝá²…tÛÞF½ßMqXP}®Þ‰`Y¯ªMÉZúò‚+:ÄC4àˆY(˓ϼÊÈÅC«Zpl¦ãžÊ´÷3t'¼ã¨ÕÆM>£ öZ·ù&/1Þëmèj7­°ü´.³¯„¬fÝaÂ]±Ö,Má;vgOÄ̱roˆI)IÛƒxºPVhŽŠ9›ië…s—ýk$ÂØúÂ3‡2@(0GííÅ×’~´†AknbΉ¢ K!××÷{ëË;® lˆ¡A8æ{éWIOÀ›•DPò„ÞØHæ„yW‰–-úTM]¬õëâ"ªN"•… ²uʧ‘¾ûgf‡ÖI3ûŸåtzßæð¬tymÈñû§ºÛ•’·Zn¿íX.BP;BF~åù¾­=ÉW7ÃúëÕ_ã8eÌ P‡ê׋Uˆ¡êã'ÑÇ5àõNM†Êß#AüÕ<ÅŒh.{»˜29--éó¼E`´Ôþ-L>Et¸;HùÒªáø%Þe ¡Òõ3ÈòÎì_­+ÖIÇI•¶öý#Â߂öåÔ‡i%ÿžþfŽ æ‹Â‰6Öýä^×Å/€ä+AºjØÌpÕõ©]¸5{PÇ¡¹C½ p•“L6 Z„a¥­1ÚWvÕ{L°,$µ@n²oÜ¥/i @@;M‡Þ¹¡lN,Ε«MdgTZ|ÅVyN.8φÓ>cÙZ¬ÎµÈ)Pv=Ý@lµš îgøÔ¦Ð«'Þ[ᛈÃ$ズº0Zž$g qj¼9wU|J7PýÔ½±pë{¾üs¶øähk³‘vn’ÞßRè,÷"7-â:¥ÂÌÐõÖ¥²yÿ«lÈOiÞ^òæ¯ñw Ϧ¢97uº­3MÙð¶Ó–÷¦'lüýcÍrbG‰hݤEQm ÇPÏ;Ú"ÂÂ%zý:˜„8"Vo}*OMME—íz{ꌉÒÞ-U\ÑKѼÌäµ1£´¸’énÚÕ^ç¨åð‰L#eJÉ3ßQ>¾yúCÚY®9 þè;6 _ØññæÃŸfXÑL?$›·>–¥'o€ã¶™˜ŠXožæµ=–ñ±PΙ8öèˆfn© ¥9«£Áìü¢d%v#ŽTÕæ—>¤Yâr|>ôäp>¸ÀRÀ' Î÷Ñz Uö'hš§éÇ((`K?A`HF†j9?+¿›ÿá&ßÌN e¢‚ífG½H—CeË©µpò½¹¾•Щ%åƒ$Ç$+/´$HØY]Ú ˆÇNÝæ t¦<ÜQÀʺ4ŸNSðAœ 9qÿÛgþAw›uüQ€†ÆÁÀÆ0{·ßâ¾D].:e¯ˆÔR“äXläËxY!É"«æ-‰¸§¤?²1¨ãF'œ¦¨]ïîhôFи˶.\¦ýDäú'b6ÓÖ5„ÙÊï#Ò± ƒN_ôºŒ¤0ˆÓŠ"î(3Yº”ÂßìëöµéÔ7Û "±ÆSC> 98üDaâò¼!^ãP{Ô´ö¬fÆŸ·lC8ö©¦Æ`i‰ýY•my[Ðf-§d&Xý¼b˜ð@èô¨éqŠ`Ÿè6(òÍ“ä¡¶Ž ñÜxŸÓŒ}´ªŠy;öKÝOxÈŒ…§§J‡¬Çóç¢Ègé| Vó£wKVúµz—ÑÈ{uËÔœ´Ù²ö“ßü>mþžÈPï,xë¥kœ‘lG‘Á¡rÚ†á¿ÅlqƒûBqìÊ@RcÒû:­õµKŠæ*´§P‡÷có¨D/è'÷\¶:›#EÔÜt]®í™ÿÀ¨ýêöeЋrûMù$¿øBˆè³Ì";µa“©ÛÒ¶–’N¿Û/É’Lä’4ÔF;r##Z1ä:càªvRÅG³ýðñ_%u˜áFü‘ñé'9wrüz¢ºÀAP•c!óY….C…ô<ÑÎ7¤°éo¡ –\E[†ÙÓ3ÏþNµ»^Šò™–°¹Ã êC²k•©SJ¤ó·×`.ÅØìËqWñËúdqå÷•ó?CݦxXc݈7+Bé]OP϶5®ƒÿÃuÍZ˜dûTNhÍ™®êb«`~¸ŒŠ½£E ÷BÀ: I¦ñ—tlG‰{ŽàÏóõôŪ©Ï–·AÈõ—d(ÆT(ƒ*Ýš»xåˆ×l…Dom¨Ü»vÃ?C_€þN¨FÛ«7ëIMÉ;î?ßæ (Òˆëˆ6þ{qr.ž¨¹bϬÔ1fç3í¨/ˆ5~c3»Ø·™öÏZ(›ÒR^†=.ÖrÌ­ î©ð8g"MÐM/‚}7WÙ‹”,Ë6oÜèñw“뿰ݳ—‡B‰í™…iÁ™ŠÎº{]ÐÜä?j†ÚwvÕÃó14>þ–©D1Ý]¦ÚGP¦gÇá—úbã9îuÊÆÙ«g‚p(Î(qNVû%ºÎ¥Žõ e¬ñ*%$1>u×p’Í„gÜŸ^XDRò¯ÿQh2á› ï@ Z×c˜ ÷5’•ž¬fCtR>aõ„ƒ/Av]¥Uæ”U¼Ç"mÙ£ÝÞÞ ¡rX4þ›ØHа¬m>`. &©;Žúë#o)„›„î.0üªŒ¬v>ïÃKÕ§ Ì•ÙC}mžF¶û)JG›]½*µm~ö0÷¾ê°³ Р»ä—ÛÛN|9«i ÁªcFd0ô²›ZYfl¸·.n ÑDUŒç¹KD—¯½œ ék ¥P÷RåÐù¼pF™t‚ëЩº]¬Jél¹L€ž7çÍ"£Vþ¶8d¾m¼Šîü¤X;z'ø ð 4ijÎÒ`’B–¸eé /$X:.}§z¡•ʼn~3Vn×úˆ[n–ZFÌ]œ…)©Î *¥ã€KΡ’À^„©}ˆ‘4ÈþçâOùUgLÜW?+ Sþ{o5Á`‡ Ï·™xûËsûôÀ—ŠßâzoÙ#Èé Ék-nö­Ÿ˜.!Ys§'ç; ²Ëìu½ÚqHù ô ¯†S™± qiO&š&CLQ‚|Â($3X”œèàŽn,3³Í6…ö”7¼ÌψÁJ±ÊkZj‰½ÓÔê̯k?<ë›T`€6¬j—¸Ë´>§X¬)Q¡D›Pî?Ùƒ/5§÷ºlr=Æ%§Þ% òÕºÊ0bªX“sõøãF¾Ë ¥cÅŽfòä'Q dFhÉk‹×!Àh{Y|éfØWryPÞÈ.]B"ºè¿øH݈!û‚î¡WvÍ{ýµå×)“ÏžYðªE-W˜qê#ͨ¨PŒ©ìQõ®ÄÄŽ-yJ´LÓ½°€cÃÁ\‹ŠØhF%,'jš Üý¯/¤GÜ5©N2±IÅæË³øùXõ3³"Nc×wU†µ“|¬H±—T ³vÌH >²ë+,.êš¾ÖŸ©ýB_* ŸN>]Á²;]å%Ò÷Nĉfõ9 ¸ÊBo§™u¬nú…>.Š•A§|ëJ1Ÿ…©b)#yÝcfF`5|Ž3ü!nOFë°øÅt ÊØKâË ßë—•(Ù àÃ7éÈDt#ÇéȜؽpe}r¹ÿ­¨³¤¤3øtÀÿêè?£C@:@;5 ûfÚµKЧ™¹ÕñÐ}!ÿñ‰%w*Žá.Y¯bùj0³Þø¾= “‡ZàGØÄü§†Ï0DÎoÜ{ÌíXÙQ\€±»{ìpâa,Làᯯñq˜½³‹Å÷ˆü]^ñÎYÂÅ Ûâ,@I|ÍüF6:ãï„2~H~ò ²¢|œ» ·o›˜ò·Î\TãÕã0sp-cKIF™d÷ìZÁglî@Ù,ýªõÒü”zÙɆ}8¡ÁÂ$×íÞB‰NõS7ÇÞ™‘;‚³?5à„›77åʘÐð]Á@Îá€üþ¤#­ÅÊAq£Çïy¢,À…©|ö|©¨.™ }3‹ÆJÿwî\A[!‡»=Ü/“¥€¼ÎÏ¿Å,DˆjQjék3L‚qa€WB»›½L¨|H´×Â`ÏP׬µ¤ dmî®Ó|ð®.Àp7!„§gΣcý <õò×n8ª^£&.à A#¶£ 05 èá;T«u”P÷él1ªªÓ Ç>^9_ê³E ·KîΦa"Ø:.ó©[YEÑ+þÙÆòØ çÝ»ë®C:FܺSº¢K¦(»å«4 /0ÙÔ€æÿ RáÉ>?_ª-%¶pRÁÔ/ÉX7ÐO)ëx´$wﲑb¿ÈBGD¦›¥^ýÅ&¨É?`µÍ¢'‹Í‡'•ƒxU¿T‹ª8ÝüŸš…ÞhÊ€LeÁF½Âšªp%µ©>òLjW#pÒñ0xÁ%V÷èsG¼™r)¿½ ø‰‚ÅxW#”¼CW}0a¤ïÉZÙy(]šX\ ‹÷ˆTWlëQ¨Éë»tràz!ÕeXÈ®r«ø¯Ä§^Wÿ; .vï9Ï™äv»Z ÅÜx»© K5{eS.¼úÃ'ú ^[ìa67‡dÜCÄ¿Kc6äFyÝÔ ,—Ev 4^¨²Ä¼Ã~q`æ») ÏÁ(pÿ} ´)¿Û¨-¹Ûqé±[;‡É”üÍøüõYЮWÿ˜l˘xy&ŒÏåžÿ˜ãë,lÖœ=ª(ìH·¿ÙP â ëÔ¹½½|Ê–4]õØÍ‚&:æzÅI^-ʆ è2ïµñzÒ±Â0™Ÿa¯Cir¼,»ÇF )gŒ?ùÆ>ì}s(\Z–œ|‹Ês$F Ä.?BaíOU6Òã ÁëŸËM¼m»þ»Ñ¾ÇºðÓZM õäéçXTAÙgXuè^É lã@ÔlJ댊ůq:%lü“ž>úÀV%r°¡ÉÃ|øÂ3Û®•S»JN7ià÷¶¯p²6ýÕ’P¦¥9Å.ó¸õ _ïòöœ†Ú±N¢H3'#ÿ±p4Þ—G‹‰¦ßk­NäçÊùg…'DN½¸žèMTÁOk1ðæY¡k{ÚS‹4È}èc¬;¾VÇ!¯§z2±ssv¾üS¡K d]ÞŽ¶Æ mãÜŽ#0yè†Ñî IÞZøØ±²½G$aâä¤F1Q¸Pœ2ˆÖ]de Vˆtð³@è+3ûzkþj…¦ÅÒìˆ_#J±yL4‹yuSPkÓµú T<ß³b”¥¥3Ò1ph§ìÆ=¼P>—ö`hDÐÏz=r?…§Á>·Yí7*§ÙîBnþô¥ñYÁ¼ð¯Å¥|XÇFZÚ f RKFµE.„Ÿò BlŒ²˜{2 k•MžßQGÈ¢‚2W“M–Ô]äâ&ºA‰UÕ¦gÎ/µGÛ.ÕF}ž+^*`à8¯Ùü0¬ "òáÁÛÿh,Êys%²®¹-ä禢ÃÞ‡´WOK~n1½E±qöå×6I¥ ¼>;bª)¢&G0»¹^¾>oA’˜J—(÷Æ>%ZQžT®ï%ÑNºs ¸ÉƒÝiû/šÒ Ñî¡kà9WÎìé‚‘˜B}[¸æêÚ vÔŠqÝ!•=¥È3°bLô k5ûyÅ´ù9ÅÚm#ȆäÎÝ~>j³ÏŠ3WÂj>-¦"`‘üiÿy©0ß܉nöx‘e¾&Ueä/œ©t‰—ïðÛO…ã´Hç²5ó )$¤»öâ·†¿pjåÒYï×Ct¼·Ã H£MÁPª>Nà&8 €ú[£WÅ9Å6ƒE ›®fÆsjëK˜Ìí€.°C¨îaÚýö,UöÝê²5IG°lÎþK®~.¸Í±‡{ñ…¿Ž.³W ?jjãp==FÆxŠç*@˜pò,H³zþádöÖ`xÀÃ?¡¢nY9é#¯mÀÿ°`wÃBÉí«fìIä²$ìM©È ˆ ׉ p"ôý@§±½ t6t6O]¶&„¬u ~z†b>ýàÖ£›ó—‰ÊV_j‰¯úDxÁÌâ-x Hþb†ÖD>>{Ïûÿ†N.P€ : ðßÛÖÛƒSp¬,Œx« ÿmh:TÜÀ#ÝÀ:Žíó²ˆ+¨ÔßàVÂuÍû£  _ Xî^Z+Wú†É’­!às£œ÷-=—>â6iFp¾)‰|ƒ[¾‘”䦘_8ôUÈ}“”¯¬—µ¿@Ýò7ê/‘íºe’¤Qž„Ô=ø Á¡ E§éíÞ‡¾Á[‘Q’} *†•ÏÎÞÏv¯1S?Í]÷Òˆ]©N_Õ*ÏŸ{§rx™Ö­åª«Kn>ÑaÔ·—e£ Û»Yå"`˜¿Üº†@`$7õº|¹p«ˆåÏ;0ã€4/Å‚‘'õÖ6€+¤ bÓßÜ´Z[hŒAiA¦Ê¾Þ¦oŽM•] {<ð]é àzÒ8 ÚÉ®þ¦—2·D2¢hyIÁ#– Yz„×çÜ~wŒb‰ÛƒP0ŸVa-ЊNífƒ¡ûÖ/ÂX'ò³<ÂÕþm#OTêh¡S;ðabL£x…hÇÚDVƒ¸²¯ðÚH?Ù¹vqgÔ[ßyàR…®ìÀi_¦”aú×ÝC× DX:0- á.“ùpÌY┤4±kkÈ$…t&Ñ“šôü¾Ì¤¥†bª½€2†æ$U¸E_2R¼Ÿ-êl•³Ñ²rI v`<=„Àì öîIðOxý篆¯ñ~…òRFa`½d­ûY›ÒÜë-^åmT ÓÖ¶Öˆ˜Kì´Ÿ=*| ¦Ùo¨!‚ÜõL†*+²€`1AÒdHª+wž‹âm‚±ÙOŽÙø”Þzûžëš‡s-&(2Š<ÞNh¢=…µB"dCK8Ô“Hªž:Sì³Ã/NËrrÌùoCŠ1×|7,7Tw‚AÃþ6˜yð!D(3ÄS!`˰4Å»™òâs7{HÃæÉkoyó š#°§:xëÓ:–·UÌ†ÎØmSØj021Ž»ë,fê#:ñ-¦H­âB¹—fb3 ¨Üɯ ÿO`OK¹w> Tƒªs[ĵ:!~P„°Æ8<Ýç–’V¶»cÀáË·W‰×¶Èœy…ˆÀ )dnv½Í†>ä‹ûydú:©¿'YÚ•ìÀ õûj‰m¡_aø™)ç<¡[oò tæ þ‹J;³0ãåtù pTÖ·|˼,àØ¶áå~G² IƒÎ[fÇÝ_òãÞœÞ5¥0vI ª¾T‡ 9ùº¤eååOYÒqë©64 e´ ôéf60y,=U~~.Ô…>1ØýÛã—H‹Jÿ‚h’^CŸ«}ÿ |>{p|\K‹²o‹j‰‚Ìçp•ñµèËÙÕÀCDûIb:À%Ô‘N‘'²$¯=ýü¼+ã³'|°b÷±ãNÓc%3tpõ9iNJî0·¨WDkP€ØÓÛo4†´àxMØ´[¢Aþ8"1¬scñÖãÄ ›iåm,°ãÓr¾?Ö±r5ä3?å Ô®-MaÕ9©O:¬Æ×c…–?;?þŽ—ÔýŒ­Á[¿’è&!¹»ï €<¼»rÒ¶û+ŠíIvÁæ¶½ e?~AˆÌOŽ´Ý¯Ò÷5ɯРZéãQ9=™øªN’Ör•ä9QHMÑî ÒÄC(â UsS/ÍuÚPò—íTÚ(ÞÔèi»?­Z›)ºz¹Ðá-ùn6÷>úe:n€zùò+ÜV2;ë©pèD·”·‹pxذÜÜ31ŠYœDªO›È‹ÿo~¥I)^èŽá_2ºä¶ýó kuÈð¦Ñk¥ýQ°¥J 5C˜¸°àrqHR<õ{€‹ícÙ—áfL†ÀZëM°yƒAznúÉ9¦Ÿ€t … ûêØ ]_t}Í­ÔáÉE0zÐÃOÔƒp¢ÉÏŒ- S·ÍÀŠW FËí8. DŠì~³Cmi°l:û5zýI}jヹï–]„†96Yе–ˆ\ £‡Ò¡I"Áø ì–Tt% G^íñ¨°&ªØ£·7¿ñÈ/GAŠ„ŸkI­ªã Ì;¥Ã¾ÎÒ•‹bÚ°žV ìï¤ÂCÎ{ÒQa_'ôHì“Cb6Š .À½uýXóž²ëGò.¶4“9rŽw$p½#òÏ.¥sªBIÛBþ â‹ÛCª9ÙØô¾óæ¦g~Wm¨ðÊÅ5Ž##߆0kíɃ“ ãz6p{lèúÄ·@1¾ÈÜÁÒ!šÒ…ÙEhVYÚ•½8¡iÎf4”"'”{€umâ"*St ìœ.{—‡@ é)! Ë=*‘£6=:æã÷“ÕêÙL7­¸Í²}œ:m½]×\?½ ¯M×éÉ\~H‰ßÕ+càÒ^på%éÏõ-²%# ØãXZnáx*qY6”}¦ó­sIYÕHícQÆpÒuGïëùæg,^ VQÞVôôíª¡-,Iˆx¿»:mƉÖbìK–°g@Ä£a¶+ûU¡….P¦‡>¿á°°¿#4¾GÝOºIÈŒ= Õ½Hô‹âs/ÇVóB’V’cu,$…o¬z—œ±½ye¸í{™0àþ¦4ˆ½#„,­hÆñÒBµíwOé'-=A4Jûo6ŒnÂÔ [óÇPÏ}‰Ì=•jdzG‰‘]o/á8éfÌëóUA噂vñ•ïÑ}÷ûµ‡)ÉÏ•2£úL)ÛD@k)¤z öú£°žð‚²YHY%ßÖ#n~@[„]êŠ[gâ¸úâò‹‘ÐH‘ så Ÿñ£Ò!‹˜oÉ>'¥’™ˆ÷tû OàŸVU†aus¶ºçðó«¶’ lØ cºmiŠ{OáV%Q»g\Ǽ=lZìÿ´fõ zhZÖq5ì4#O¡XôßËU9ª²«¬Ñz¯Ãi<škÈ_ãí)ß?½¤ðôðIDʺÌ[Ý;qK€žE™ß Rº`®Œ±,ʈrt¸N­p"› >ìhÔ 2¬¦3¡ï=žÎ«L…ZÄ™ªF3i†žÊ¼úŠu"ÿÿËG=5áÀ1Rt…ô3ÌJ|WÓ©úÑÞª"œ4:!P§ò¢Õ÷Všÿlí|ž—j¯;cdZA¥É¨¸‡ˆéÉ¥ÛØÕJ.nð\¢Cϱ¾RHíδ<¤žh#u„êå¾éªT÷ù/~aªºj™DpДl–aòâ¿ 9¿«æ¾ÀéKXç÷}‘FaLÌáˆÝú&[EËÝÍbíAÕ—ÓTžYO’ïa¨xüü¬$¼GÐa$Òz=j*33ðI68•r? : _Š8ÁÚ­+6Wücò’]ÌaÙ¶jcõ‘Øù>„g=‡L©ÞYu7è>6Š5 à˜´ÿóvµ©½€9 û˜áDñãëû>mÅNn‘´„÷¿Ë#±ò…%… GÛ—¹#*óð„«“ùƒ÷h™›DÕ;­?ñ•écá`Œ@7—™\xƒ©ìôj.©g96 Èš¥öã`=:_6c¾o†Ð7·†Yª“ýµßئø.whtí…˜!Öm¡>½¨®Ú/x²Y˜ š|9Ú_Þõª–CM‘ãï(Q¿dͨ­[Ñ™"&§AoŽÏÍ@ùÈá—!Ž3>÷Qµ5³RXÕ9µ¼5ˆø·²ó•mF¬›5ìW6äÍ»LèvÖBxÁÌãÊ`í±dðì‹’šŠÔÄï-p¿'ýÆÑ{Õy¨2ÀhŠan\î¤ ­G‹–ûö _'ÌÛ™¡Ã™÷ëÍâŠlT!—´«ókè¨Yù±1x—í½èžÝ÷®¡‡~lxk;£µYFP—,ÿcKè„ ÇAêï' Ժ߿Ò0¢Ô­øÄ¶Íä³§°=³«½i´°mj̽I$Í$§"œ(·ñ>ôWFe—ïÄD’²Û·T[}ã=¾•ä×áéà©sþϽ)I—3×Ln~-¨ÆœOö3†|™,]Å™$ˆOƒ(!,ÁUý蹑·¤9Ÿ*zâºí³ø¾'Â"ãN!>hAH)V0à@.Øþ:ð¥,ytÓ_uÉ¡5>5}@/ö'â Y箈¥qßmšhpP8õÅÑæÌ×âråkW¦¤h룡Ê@l#É¥ª¡c™ÈðÿŠöçþ*Ðnëzp˜iRl`ø^ÆýÄ)¯2ÄH€“+Ùp -SÞYqêþ(Í¿‘ž°éÚÞâ‰reÞ8¡µ¼ fp8¶ ”˜‰”±†»«½ÎÝ@iŠ÷Ç`*0®`{æœç¢eúµ³dîÜf<ü[¸á;l}°h´ ˆ6ñØឱw)iž\Ê ÑvXÃûö©LÙöW*€ÁY¯‰ûâäQçĵ ùölpÅ)J½îúç¬.†¦Ä’{¡™W7%g˜k§®e ^þðÿ\8æTä•ÙÇ]†@ÐuæŽsEA(÷±ùCÂ8¤!ÕI‡cˆ<Ú’ Å’y‚2?œõáž Ðîöí!#¥°cnœæ;Ñ4ð‡SûiõZTÃHù*ÈàEo2ÎA)Ývíû&„n5 ¢´`0Qˆ?ˆ›è fÞÌÀLì=ô9ç~ñbI©û°<OÔ轕ê¨p ñ-ƬX3ñéEUÑ1L„m/ѧ4ਸ਼-Ûô «Ÿ"§Ù:¸“‚1k+Œ6¶»Ãì/^oA“\±y; c¿¯¡ vð@ËÜKVxÁâ'û©gª+÷…xb ôÔÔ@I[¼EuÑU¥øC#ÁXŸþ›žÎíÔÊÎæóÞBïÓV >ëX¼X Š7£i+zæ"u(Ù='oI°]…ð½TK*¤$é%/•h©‡’•2©ôgª¶-}ò²Ì DЧŒ„,ìùü:ÂöôňՆ)ÓÀRs”ÌðÐt¿°êÅxõ›”Oä yñ"¢Âë¹óÍôž¹X„þ…u™ V÷jŠ f2ý“ò5ͼJ8wL[””2æú•‡-X­1ìÙ)í'€ÖX{õެ®Ü)cáÞ|Ÿ¤áÁ± 2f'[^uHmyJvÁþqÒ̦Æéaƒ`-% ÿ¶QãüzY4¿§è]öBÐÃP‰¹#´>r¸Ì²t±:Äâ•¶‡%/`—ÂÒ²"XS?TášžOÚ‘iþÞZ¢í¡ž¨6»”–Eä„ËÕÅN‚cmRùI)Ók¼&Zú·Â®ý©ðÑf‚,Q‹Þd&<ü-ìp7)0cC‹9ôé²O9¤l"[¿éí^¡1ö>x¤2 ùI-Ú4ÅŒÕÉ} ] WÄ¿,¹4{ö& nhb¢]M­{ªz:Q¿9è}Þ¥¢qn¥›sö‰gí§WÎ3_¾‘£Ÿl(-äòváÌì†î*¦,J—šè“>~P¸‹iƒ7‡¶ ÷¯“tÁ<`ýø†´Yý8u½Î騅&“ÈØ^BX†tý®6u¼[ÈRÄÌÃêG„+¯°ѵ[Bñ‹Æá±L&‡CÝÿ_©ZA7‡è{u®åNx-J´ù™³üð1qžÉÏH†øæÿ=9º·ª^íþ¿×Î×vhúl=G¾=«cðl|K…‡~×i°oëž>²¨™ógL‡E¿NÈ^6!¡¤”97üEˆšzT©®¾(ü!]þM`d°žc¿|+;PcátÎ Z&IÉ)'¾,M©Dt³eͽmPjþDÕë2QQ•Kò‰£+Áý•Ô\ÃȰÔ* KcÛf8øR‡ã“ùrþ¯’\õd‘#x3;Ù’Œj‚+µÝ[bÚvIhkµµ–ÒÍÅùôaþèÁá㔆ëÜ{FÃÙÓ¿`5õJ« ŽÍJg™Õ_ÒµÅH‡“äÁñn¤H•®(Fˆª?³0i¹Î¸©Sq£¹GšTUc2ºy5YQ{DšTûÄÿÓßHÛ @ xë—fúû Uõq?Áþ¸gß>QZ¸ÁjE³QBr¤tH\¶dyü!gü¼àõŸ›Tò€ï¬‹¬—&²7½ ¿ToQºz'¼DB­ÃNÆ?Êq™@­2© 9)‡’ÝËj»"5/öñ3GüvM}ª>¤FPœ>¥ä>‚÷f:0X7…¬$.`¿’È;ÕªZ 5òaü1'‹<ÿì–ö0p¯TŸ8„õ4ðè3ƒ8¦¾~%™ð? ‰²Ú××ëߢTƒã¾‚Lj`¬4 C­DsšŒ±¯Ö/>žï³™ AÿÌw²NaeÞµ¬ºÑÕ:™5’ÅØKÄ@-šD9NÚ›UpófÖ–E2tõïÕÂ/˜¥½}UJÍ·9Nù¤5òfXó °úPs‹_žQçÒ÷ N¿K2.3ÃßÿòeÞéwªgM³’›]ꔜ¸±Œ–%ÙõÿþԲ”mwÑöîmÞ6û zlòÔ°( ñ„ms/³Ÿg8¥=d«ß»©ð¼]‘V¡Ó›¨ôÿ£q ýð̼´¼%Áô˜Ð{`Ђ~ú!y–PÈÔ3H¡¹.éñÍìYÿìØ)Dqd».4‰«enŒ¤jÝT9Ûcºµ>ìî”"`Û„!ƒß¾¹wË_yl|‚ õ,3~F¹ ¢$IÙdbÿ5ã™ìxÔG®Í_¹áº(DÔ@NÚ¾ª‘ÿʳüh(P°ë¨l†¦nçäÙè)zæêì˜~N5s¹/Ëô1£€^òôÃQ½K«ôµøó–8©Í Q!ìâ:h夊|ƒSªþ-ª1ñA A¾DS3Ú)Ü0¾¯mÖ t„N^¬Ç1gžAóˆ[- &2´êÊذPñ¢Õ Øn°Klü“VOv=0[MýšÁ9áYF"Ò4î#Ôá'²Y߬¦ß±/¸©‘WÞyÙ äÖz™†Ö«g†¡ ©:È$–‘v“?X †öüyàá2M__j–€\ž{÷ü÷„ú'M ª!íT7Ž7š ÝѺ`—$…‘÷‹ät(´d¥µ-/¨ÛÍ{O‰ g1+©g0`gwbU¤žšë<–`%áŸ7 K†‚ö†ÅÚ-Q~¬ÔÝàÌ%"ìÒ.|5“zb+Ä#Ö.sŠÑu=–çñæU ߥW€¯…Ð}•FÜ÷çÜ«SçC>GhùøR,ˆ×1ï¿XÒ!U,´ !èP¼$ÊäUìqÉú¾½¸XGÜ©'€Kö³\!Ú¨Ä=Ñíês39¾Zq*ẇZoHæ·~W|Þͪ‘¹@ņ¾+Õ*’ gf•wÌþØ~5GK/Z¨«=xD—¢žõ†²ÏÈÂeÃE€—ZL ¢?~òež“mõ~.(†’áøÿ‰d¬æm±,ˆg:„*ašº}_!Žú¯ˆHÕ•…×9y«5œ¥IŠ [Äí¢±ÞÙ è„;~iÞá¤d«„š®Xm÷L9ÚT›H~ñÊÍÏî¶6Q¦hYp¼ýç[†Ñô v* MÁÒÏ\Z©ìœ¯Ð›Ux+‰œPþÿ} ëûoY†[‘O.4(Ññ“œ­ÔOÓf¨¾˜$*/¯ÜïÞžã¦2(•)dÂqÚüÇÂ#h†»æEo÷w«ÄrÖ™äï8q©õ¸ê vÍ5 6óÑÒà =td ×ü=;xŠý1C df§÷L8ÚçN;l7À2hú>õ:.»ÌÚ¯¿E½±Œ‰IòþÍÐö„(á ó/Üóó-7€Û[ÅyEB4Æ2ªŸoò]jä3ÐѹrïO19{7¿§VaÀ»ÁQQêMMü¿ÁìÂAdë@;úªµ)=ëÑÕ [– çyCltoN–U$Ɇõ3K.†”lÇFë4jSÐ`ù^›;ðp3àôCrša¯~¡›Ke|Bl‚Iê‚Úç!÷ÐëòÏ£ Õò^£¦ÿ4d[~=çÛ!±ó…-ÊhÁ¶³4?ÀßZó%-4|c”ˆõÓÊÃ5ú„^Ð^ä+MTêzÒçìög´¶Ùd&¶º‹‹ÓbÑRÇ[rd'’LÕÖ©Á+ ß·óÁãº8)4÷yØõ•¦jG`Ÿe0™¹É©$»O>ÎwíÂÚQÊðèJr¸ðjˆ°Ü\V1-Ò˜´ ƒÀB$à˜ñTÔ(‚`!Ÿ/öÄœ‚–»¦°ê÷ûw]‡úü²ðÂ_¤è´­Ó‚Éî|.Öõav óšžä pœ’•¢ãäÉkKP¾Ù1H@ ×iÑPoô½]UóÇ‹5àržG4w§Ò`ÑOÅûY(‹j³©®)Ç"ƒp'oßÍ«B.(¥½²ZÄ©ŒŽò§ü„1+DùŒ qÑ´·ŸÈ¯H‰æQB~ñô×¹å•Yè#;g[`q OV‚¼œL”¼Úù²š[17°3©Š”/"$Èa`ê–ãpF7lhÖ€·7h@gÖ1û®),mzFfïßt¨ýóh?3…ûšÍ$w®bkвóS&}°%"ZÑ÷y9rŽÌ\Œ”Fî˜p ç$aFiÄáwŸe t‘ËOÆ uJošTdç5¯t݈zv­)Ä~Èô¶*ÏÑ2sVpàjƒí©þ³Ž%!øwƒÕtFÔæsù{‚õM(XŠoÚæ~TJœdœ3ßœ—o©PÙª²â}tÓd¿L/aÚÐf_vp¸¸„ü/%jåV/-g'+lÞâ~WX0y12—…öp3è­ꤡÛÐMÇáY’qBî/†ê{7*ôÅ¥êñ[`mdÀ)ÜEµ×G¬¦l**{ÕŽÏ×psØî°n;=HFÀÞz_!—Äçö³$`B¤½,f~vÏŸÁò ž‰Jt]W1bDòô@î/ ×Ko8¦84Ùc “bYK&ž›:XË€…Èìæðãèû?µ“)Ónõž¾ØœôKœ"ÿ›ô}ylÎòY…°C§kÀ Ã]RI 5€b U¯^T“B{®ùã]dìÔv ÏÀ ŸqÀ æðvcí£'Ì Räž~ñ_ŸßC ‹ŒO xJ:ö%;ãðiÖušàÉ8º“ CjšÛñaÉ6Ûz„I%6î1Þ®÷‘~ç–œülŽÆýhô>œOÒ‹C¤ ÛQI¡aé¹3S$ÂùÎÛ5ÙùÉ=w`@Ÿïé’E ÔK)0¬¬Þ¸6Z‰Ö ÏŸ““ ¥ºCH½ýùn:›~$GàP‹—ö±½Ý Ò™‰ÜEï@5*y5r,fØ[šI aƒ·×&loÃü®)¹¶»N'Cr-#¹„œZRmE.l¦D a c' ò‰“úVɬˆú_玅.@ƘL°ò›¾{é•yZ Y'#tÕãñ•G§ÔÐO6IܳÖS³*(­%»Ù_¨´NZ_û}d޹Ì;ºbwPÂò^dóïŽ cQm¦+ÆB/p‡-DZ•È9OÎ?0GŒÔœj[;ßO·ä+•rÙ~–)D#öñø€¿G„œ4)Žcp;`Ì[¿@Úäoñ©Óÿ6&Ì#™U7×±.#Æ}!Ôü(Ք˟È,Ö’¶Ó>êh'XD§«ùº«mKŸ'îvâ¶–´²EÙ«ÇïžpM<ÓÃZ_¹ÅðáÙ ˆÔ…ûdòãñx·MéÔëöRSÿ#æ–y?¹Éß»•EÊeGÆöàŽTÑÀf£ÈÎ’#þ&©ã|2uoˆ¾#³,‚Ó;×`—Aô8P‡Qºe'ÑÅüMŠÛ4ÒóÂ#jY|òÙÂ0¬ôCýeâ%î—U5g ‚âþþED‹5jÄâ ¤?ÁÎtÇ$Cä`žö¡ªÝK{QõÍG1ñ'¢˜jâUÙ†Ö6A‰ÄiòGU•ðõα·öx-xûÏCcÐïq±NÖqb¥S>Ø¿I–_C‡,ÚÓÒ6Á yY&lûÓ̇¸øc÷To…ât>SO¢ÒÌÏŒ˜T€pmyWV+SQLõªGnº:Û×uÙ{å0aÌ:ô¸¶òo®ác.#k 3Ì3 OÍO…4¬*Š—Ð&oÀj)ÅvdE›…m¡b×è!/ySDÁ ó]¤/Ê ¼ùÜûš÷o°Z°sAèÓÀ¤À3GèQ™,?™|fjÃ$!°êÍj Þ Ù …XEŸQ¹%T'ÐÆ÷;-ùOÓ_OoÞ ŸHÁÞœ9?êHðóqX?€u²MM‘Úl\Âü–uÑ› @½õ)Œxi‹#£ƒ?$_' lqFàŸdÑ ñ¶ Qt»7† ±…ÌÕ*8AH†5è—dagƒ=¡ÆD˜|³Þhs žZ‰GÏ»eÝ€àõV‚cô‡”­ys^ï“÷èZøvZ×@¿:Ý^öKï­PίȊÀð ÿl9¦ d÷–³]-(«F.Ÿ*{síÆ€Y6LEu‘ühÆ"ã»)êo¦å‹F´²K„˜èÃåx\Ui÷$ø/DP/ä—; ½]J3ÎvjÉã/)r)IjeÆŽ³|R‘ .MOûœ){)Ø9/¯¥%]51n¾æ ]ô$¤(wš>…ɯsv&¼hlr´ÀXp®‚çëˆw|T“¬0Ìzõ>ªGTàB !´·¢xó+O˜É—OT #×{ŸŽ‘v¸'¼&:`¾õ*ÉÅ|B$-Ο=¯KD‹=è‰9ð̶˜êl™ìšn©…ÃqŸ0êm¯ØñøØ« n±ù¼ÛiTÐdùºÄ?Qð3W‡b?¾Œ`#Ч̰õVðïÀ’Mˆ ú»SSZÅvs¢¬íÂ+wʰí¥mš•'yœ&™·&ís“.Ã5;º|óÊ×{ppØomb‡÷D_©ô´¸ZŽÙýS”"]ÜwÕ©M³WYF)£À~ÊÍ„.o»1%‚‰õ¤}77 “TÝ›.9„ ÁW\‚_å©öBÜ~¡ùAãcì¤ ’‘ñÚX…Q…7¬—MBÐE ,-œþ‘kµS#]ÍK5„ü”)uQV¾£ÎøÕ¦€Û¶Áî^KPZb2¾Üs• ¶U!"Δ"dáí܇=ýc˜#ÉXœ¼6Î9j?žiÐ m^dk»ßL5óºÇ =vBŒ– 9:¿ý¹’Ê¿FÞá±/±aË/h'¿ïÇlÖ¸`lái–v”j «'#.ïZ©C…áßð+N_i†hÛ² f —Ôv#úâÌB úŒ°Þ{©µ·õ¶Õ¸žÌ“*¨ ûhsݨDßðBŸm¤rÿ >µÿ†/¶$vÕĨêwð"”pê(ÌÄÿmÙ±feçÛwQèàüËÂxSL,ºŸ"Û‚JUDZ°ÕPL¤=æCs\ìðÿ¡ãB{~ÄiÐ˸êcΡz&¸t¹‹d¥~wÎ:ú|z¥M,7¨DË}ó°c‰ùkå~ hú„ëT ¼¶—Q¿­2lÔ¨Ëßóéc»Rxð«hFè™Ug„lÜ Þ .2Éû8óÑÛ:ÇàpõÃUÆÔ7þ»Äá“bœv›E× ±'3ÉF÷ïÔ¼ÃrÜJ¨Dûy¤lg…|–ª: ûéÐßüàÒ§‰j⑬qÄéø!蟺][“NØ ÃYÌK ëóv’ÃjaõWþ¿Ô¼´&DŸšn™Ñ ä¾ßaXË1låDYªrJaÚÿ­QÖ€ÛÒ®ƒjÔâæú'úýS̶Ò®3o¦Íº âÃ0ì4 RLs9¹CÖ!ç4ò€=öwݳw7 —%Ss#à¼ýPO•Áf"”':g i¸‹R^^ÿe4/!ð×2ðÌüÜñO.±viúÒ%8¸n—B­Èƒ»3€Ü”tŽÑQ1˜DN0i÷ÁCædž?ƒQ»¸Cn6äØz2Ñ+_.a0¢xõ}ˆQ%k?…Œm~Iâô—´X E±{4‚h{"á©ãć›v¿ùå1-ËbÞCèz÷rswì¼çñíèL)ê`ǨL\Y§4Y*)u)¦+€©dµ\0ºœÐ:á K6 – ¼ë,‹ËBì?Åßë¹¶ÓmÒ2UÊæ¸úk3MkQƒòLm´šªhŒƒÆ%ÿçÓSlÐ1K~šCäÉ¢¥`A|ø>ã¢XAaì²£XïÙ-paGbAÕö¬Ï¼ËHE.ÞLjšë7è7Ţ๭ŠE­¾/LïNïM“áÊ`+œA wõê8!÷–¼³ÑV¡#,¿ª‘»5ÀZuº¢ÍbyÉ.Ì>ϵoÕÉ4íC²î#_/·ENÆ#*·¸”¡O³†'’æeYK˜§÷Xhgó‘~ô…€Ì‘÷ˆñÚsd¨ß ðê Q†Å8À{Uµn• ÜÔ³Dcxú rŸÿ,ÎEì°¾ò¤(Ä …E9*VÝ9ÍØáŸ‘¹7–,S mh‹ÚŸt;Avï§'XÔBÉžK¿ô4Ñ· I\Â/ F8Ñ£“ÁøïvfßÈ1ã?Ü ÿdÚcAwÐ*{+wÁjÙ«ÖŸŠ ¶rç |Ós6üÇ&yücÁQ A±¤âçe»©ª¢PqÑå {ùRïwûs±\¤Wè] ~a;žx‰H¾e…¥ëãp3Ñ2;³l¤~]€  Ekï1<®¸~Ÿb…–Ëwˆß£œ:†hºoÇÂ+ñ6€Ñc"“·„ÉFá‰ÕßÉ\¨öw»f‘M^­n‚Í]ÀKé8ºi~kÚÍ_QtõcÖ¬£í]á·PqšBÐN¬`!ņq“n{™<63r)Èë‚—Ÿñ©Ï ‹ÒÚnOÉè!V €ÿ_UÊ'ÑMÔ›cÙåÕ]Ž7§Ž›Ñ}ÛŒÚS¯‘ ¦GZ7µ›¥… bê,o:y*òžh¸£$‘8½–›2ä~<¢æÒõâÃÚQ‘ÚLÿpë‰oO7Utûs}ÝÚÛpqÛE[µOtÝ}À@œ*¶•Èe -ÿ³`s‡^PCŒ2iÆ­¤›2%×.§@ohæqú <‹Õ´ø<«;8¯+[:ñmyV­¸$b/(’¼‹VÅ™„I´fIƒr?ÿ>ÁÿP“Êãé†u]ß§ùÖßh×P÷ >È´#¡¨6?ÑÉØÜ?úo¹à}å×seà×î¯|7v˜V%6&m¬k ÊuÛYŸT,˜„7 :®JªäO_4"¯Á€æÔ½Ûò §ëÁ‡¼ÑÔ£ôŠfÊ©ÉÑdÄsŽÉ6Ô©ç´‹Õ2P¯è¿qÉgþJMÕbµ1»AÀ+%G@P³Ñ;³£‰oe^Ÿ:ü>¿P¾"J¡{#5Ó×ð[Å;ŽÔ#ˆßÜØ…1D1š?ßÅõ‚;€f¬$ìƒH<†ýc¨b¥òò¼@‹9h¸ 1JÕ*jVºtf×4ïùl`^¥Ñü{GÿŽb}Ý×Ï|óÍQŠö(ëú%Q¹¿èKÙÚAò²æ‚Q[”õŽƒŒ}à¦ôŽUm˜‚íÍ}ètÊX%̨œ;®~Ñö¤QÊî¤æ¶7ìIÖÊî9/¢œWº°¦Ë:w@BJ^?m^ü_"sŠtõGkÊ8¿aÂÀûµÒ¬¬Tˆ/ƒ;Nöý¨OŠ¡ÄªŸÕ€žáû´ZÅ¢Õø77÷VœO1ðÄs~}Ë[ ‹©’ROÉ_œev¤ù}LÕÊ’‹}¬) gŸ$Šñè^³d>õZv—8ß|ønl>x#÷Jt£P/ÛT”±ë•Øá´¢Ý7A†\ïäU›Õ.¿gÎÅó}»'Y UWUOŸ”ÝŠó9ĈRÉ"ÊŸÑDŠQæ‘›(·uä’@ vöãmeHˆîKÙQ‚r^ß@Rà¥Ûx´bPްèéj2¬`>39fmBÔ«j½Û‰Ê»iÆrà1qÎ…×xƒuœÞ´#(K½6ÒO> CỺ¨ïW÷¼ÚRI~q +·‹~ÓÆávf yS ²_ùÔ4å÷èܽ’Ô£§Y`¨ê(ùs9Š>¼æ·-B`!Ëö‚ß­¡5çÕ â܉<‚õÿVh"#>nÚTs›Ú²;G %¢žCËû ·àÂÚ{ÉÔÎDCª’^ б˛Å_Uø¯gÐ:ØâD*Ÿ"ùb­Õk)a¼®,•ò]jÉ2 |" ¦,Ð5¨BÝ©!tïñmüîÃâ(%!ÿÜ.4d–É5ÑÃZ1žkÔÓßQW’éL ÞžPm,ó5—¹¡fÅ8>ë> 5†éŽ’ÁÒSÌ$:‘Àì!ìúéçîNÀ^-¹óáÝraÒ(ÚÒvçú§Ôè&¨3f¬¾¤Ìù»ÜÜÁëiêƒCaXÑGt%×ÿxK (ùÈþÛvouJ’ZVèÄeÇ#+E éŽÂ>ÞiÚ êÒCy´N"A³”ëºT&‡ÚÙÍŽü‡fªþµÆ4¢ˆ•wÀ5=þsο,b?5”©åð;˜`OÖLž›QÐrø×wGiû„Rû©ˆÅ©n:Et L1!|¿ç‘Ób J÷Àí:IªwEjÃ,¾Äë9p±ó1 sÀw—*9'›U õïÜ2Ævhß²ù£í+æÀÝPJÁžÔF…¾V§<ø­WD]ÊBS†¿mžyØæ*6ëöƒãreó‚*E–Sû?=0>¨ŒhvQî<·1¯DuwjÞôm„üï’c.(, -=S©`U0¯¢bÂ7ÓÇãŸ>ó[{?·‹.l«mÎ×x« Ì‹E‹c˜è²Q¶[:íî”N£}W§/#dhTgu¥°X¨4ˆwt¯»:µ&¦b_ÕW ¼ïÔ7C³ˆ—³xÝK*ª%挪ziC' œÐv%P UŠÍ¹?>o¹“9ßô«¬RA?ò‡»°Ò>CýûZ/—R|ôÔšG Ì?VYbÈ­ÓÉçrÛÂïàËߊ_þ#͕Չ+.Ù wNñÆ÷å2NÜMïBôÖÍÎÈšœçª[= X1c5üòï²{2ÏÏòþ^€`Ä'›„najWŠþí{ÐW5ƒ†—J—[•ùJ²1%>ywgV¢æwaq"^áSc2ù¯¢lóÈU•¾í E¥‡}ã8ø=Lÿ‰$î,N›Ã\<’ᶉc7 vÇ>מ¢`–ËžÊãs°jâÑõ%%â‹#Y»h¾µ¢ÑC­ ‚ЈyºepN©m‚rËð«ÇHëœ\1A\TµØn–'ÃV õÔoç!ÄFÐAùÅ Žó˜…% Ãè À}Ö¯¨ÂQÅ$?1®X Uƒ– TTîÚÉp|x¼¾s«+$ô¶lðƒw° n½®V {&ô,I–#Ũ«í=¸©l'w-º ísT©ÞþQáñØŽå\¢g?BÞ&Ý]2.ñ……’ÍÆ)z[ä=qóS¨í§Õ&^Á½ÁÅ’ÒŒ1ç¡ \öÝä”M?„ Ðv€_ä¯-Q| Š3à U0è i¤ò;æþ‡˜¯Åˆ¦ãØÌF>‘Æ ]@Pl_A#OåºQ¨Eˆ]^ýÚÒ‡dÏ„P°¼.±íôÛ¤:7„©bí4xTšLøŠ =®ïZ¯³tíó¯?ì¯é§2‹’õ­qÑ €^r#S´ÎU~¶ÝKpËæì`D¶ÇþÇ€YöŠ~äNY¿y8ÞOvü_ ‘Ûàƒ¶y­Ý𨱪¾k޹¬GÐ3îSä̾ßèc"[%¦[š`H[øÝ™z;V³€ Xf•™eb.Á]dð5ýÐo{h%2ïõ¯dðeq.ÍDm;òæånuû§S€^ÈF_v¤`LÎH9Ð3yÍ,ꕱð7{|¥ŠÅL³†Ñî©×ÏGÛ¼dš¿»ý‰zÎûÁ<瑦3q¥(%-Kms?q¹Æ×¡„ÌþÔFô-Ó‡ÊoØðÏ­Œ|´Üìö?d [{øÕÉšWg4Z‡»fiÂlÁjBÆÒ8O°bõ;ÄÄ1çá›ûÀ:·4Ma«ôô€ßÔiüÇ˃ªŽsóDŠ‘)°sÿÎ8?:ܾ%Tµ‘èlžQûî#ö'=ŒtSfAL -!zÎ|Z3ÕJ+L2è^™¡;I®!§6$ÒŸ%²í§ïáM"¤–™[ ؼÏñ&?¤»:i-­ ÿjŠÒÊQ3º“`É’Xëqù^"¥m«®ÜÁ=ñ„Z²t¸Õ!gQ‡ƒ MP¦a”eÒ2¶hElõW2šX#•Õ§x CEênÆ#gžçï÷èÚÓë4|› qNâæ—‚v¾¿ I”¤@mõ™¼m°ÉJº† ¼ÉXéä‚ý­¨û·U륫4£–ät‰¬{Th”mö&[ã ¢¶ ¾èGOP‹¥—ç›9éÝöÁ8ê(qÛ÷¥nçºIð÷þÖì¤ätw¶ÕéN—ùº7ºXDXÚQ •x®…EzÛ+ªtUxŒ‹E–êâ52[ z:E~RAj$û"󖇳qÜ„¶Yÿ1Sï[ ªçœšg*öt!-®ô6©ø|jùÜÔØtK…ᤴLnº­ÜÙí ë°öûpEõýý­$û€]êMøó]ˆ~±×Ê3]2ìGº#7Ûø ð/þ­d\f¯‘’ºgéG˜ÓÐÂi²š< GÏ®”×ööëVQ»a³ |hðWx²ØÿVÈÿ$fV8ê4‘§²GG:!ÕôÓßè¥ú\ÙI«a çGùæó¶Ÿù†è• 5ÜW÷Ü 5Ђ!›ù¡Œ¨Ø ÄöÓ5Ârþ:Z–Pg¢M2˜x›Ö X!‡ªð(A,È€C!à7•ÅÑY±¦)ùŒ@Qöçëyˆ‘µÒÈ+¾gÔ™?—/dFйö yÎ-,Å>×·ïú³/‹Ô¸m•ªYñ6@Pv–ã¬vîüвCþ]Ÿ$‡:X ¹;Š+–£ÀE‘gÜ›Ððš¡ä;'€3oò©„{mè,~¬^ûãgÜXãruÈ×ä¶B0îXxœHY×e9¨I`EôÔ'b¶ªÜxøÖ8Ó³sgíÏ›)ä£db!@7œu’ÏÓ¦TO6dsY‰#mñjú*”/3É‹‡Wã“c¨sÄ4xéŽòø$@­|õBÕA¦µnI zûžßˉB iÿÆl€?¢U–p“('X’žAn›ajxnø5JN–FÞr)}=Jzðáæâ^”„èD¦Òµš0k×°z±ð‡5¨Øø“nwW¯Ô»Ó)t›öO®Rqˆ*GB¦ÌãbbÅC¨;ÆOï&Ž6Ù2šªSáÏêÈ}üG¸5Pž¨~h@ ¶¯BØÑ[9 ìcš<-‡þ6|-•Þ¶¡9œžMÙÐadÜœëØ…”Í R‚ý’2ŒѨq¥è$…d¨Ø1‹ûq¢Ç^ƲÞp¡7D4Ói6¹÷Nª[ÝúÆÝÊŸÚxô¶a}^$ÔfœgÄìÌD÷ ÊAç÷ÁRóé`-E\&¾éfL¸¸ )m®Õ”²¼2¡ª´+¡°ë)ÛŽdð*Lù†úã%úÑ|›¾aQ=a§«> `>ñÈ´ÃéÀñôØGʧ‘”b\-ШùüÏAP!•3*¹í=gR6Qa×é¡À×µžâ*ïŽB!½}“oÂR«û­öyˆjÇÛ«ðÑþWjž‘êÓµ9æf`LÞ^'õåa‘ŸcÐ}‚ã7>˜X›Ômƒ½l¢ÝGÃIÀeô³iQ9õí8B³˜„-×ç´ÊÛ:©¢Ôs’L݉¨mùO-ø!\KZG¨•dÔróNZÛ”Çd!PÑ©T PyUzùf—Ne3ØùؼÑνÖO+3'áh]¡± fÅêßÉ·®ì{‡.Ní18ÔìT¦ªúÎ<‡nHÃÜ–­È±† вžŒáÖ!^t¶Þ ð Sc@zF à†:2²ìW Z#Ì-ß'ƒÇËñ ö]°ö©ßKD]‹ÊDAPô6sz¯ÃUe–Œd=ä¼¢Èa;ÊLì“pP!HZ&žym1UJPØ‚j=ø`]bˆ(¯ƒ©…lÄ7;à„²K̈Ì)݄ӞÅåUm´,¿…™ªM“£Šb×ϰûbd; :9àgzô[‡g¦ùØ 'LìÇ2”;R%ÿŒ–$¬ŠŽÔ±{üæ½ø#•´VŒæ.ïI=hKjB2+™¯6”}ì}ß/_YLF‹‚gIª/ZI$ÁÔ -]$J»~ýû™;K¼8.#µ2Åg’´·hàðÇîç >Õµìãß×GÍ@Öùè«“v½Â[¥¦©«H )Bg¢º²¬¢¹à¦#Š ²;îmÕŸ1äÆê;t; ~þŒdÄÔ&'W«AϨFK¡/Wšç˜’ÛXM§i‹&澊!–µn‡œÑĺ¹Ý'•6 Öfq\¯”¡ÝT+&ð<€ÆT²Â…b¯¬EæêãC^OçJ¤*Ô9´³¸@rPfˆ7ÖFLÐY—`¾¼Þ¯À;§&Ìa–zŒ¨ræùî/z´e½iüÉW´¥Y ¥þæêô¸—{¶ ºVÅÏa¥¢I¾õM\çktårœË¢PnŠ%^eh±«oÕ|ÊPz™cŠü€TGˆžË™e&³,À5 Î8¼#@]¾M 5­œªÜ|w:TD‹ßUÏ–-W`zÇAñTÅiÚöV>ÍŠòi–‡½hë·þJÕ9„uµ°“è±ÑUepeK‚@‰))–Ò;ŽSÎÍ®eóÂdÿW\öfà¨ìÎÖCÎ ù¡È0›JÍR‘f“hÉ:–…øÒ$%äö³M)Æ2/íA'y„æ ¾%D䌌å á–õa¹Û‘¯Ïþ‹c;Ç{¨é™Š d±-äA³“ˆ †‚ô¨ùs[Ò’'ئÛØ—v'›ŠˆSuBjntµž¨ÎÚ skµ˜‹þ;DäX2Úź†€½¦‡a™F¡Á Š[=!^ð Õ£ê°ô "›%¦3±(8ðñ,¥„©õj5Võ\öæ=s67ZðꤰQíç&üÉÝÝC$°¸ekˆ6è_ÙRù ÷úÁz5c2ë· ÏYü°œ“²°èñtQ머¾š_yšþtñ‚ d«™Àô1¦ÔÁ/“´MÞ@Ç…w™î ÛG•ìf~Ü˦_N ¦ÁóC ý&!U$Ã"‰p bàM›Fîn:sÜRµÄì6¯d¬n×^áâ¶ ³Ä<—Y#. û}ˆÁl}‹2ªóÝa'¸òáÜ> üSQö/·_âÁØ´’Ô}ö‚Vþ„ÆÞEËïå>:ß}ÁÔøÓÛ5ô˜E©10Ô–C¦ÊHï üi@¬E/é‡êëU»X]ê­ÓÍX8vKê<½#ÞˆÆMÚîÁ-.Ss^=ïꛓÐ-ÌЋ"nÌ~GŽ8r"RúuG7'ü¬v?É4оŸxht\:sê÷J®>?+ŒLB‘-V¹ó,P‘˜ÏØk<žÿªt‚ìÀáˆì>~ckâÉÛ¾ÞÛ¢  §Yðh ;4„þ¦0å.5~«V¸Z-×pÓ 3„(¦blÎf¢˜ÅEUt¹ðÜ2Q0;òbHÛ˜VÖ$É­ ×’‡Å Tæ%x%ikÝögH™»Ž5RÑì ² eñ çþõýú ý°¹ç Ìš³Ë?AMÉû&JT¶“ÊÐþ;'ÅŽý Îd©|£Aü™ßåŒ&“J”ùs—*ªïª¬¾‚ø’ùç3>îíg¬ƒ_áŠÊ`ëÏC,…HÂÀˆ½6)Äv;•>7MSÕ«’õŰä)3¤ëãÐ ÷9uÝÅÜùo*t§M†ÒÏCüätU!ÇË»Hkr½­ûÈڈ᡻î]ÃAÍ’#ctÁ–S0”Ž‰È˜S ª®éÓ#Ðó+ŠË”Ø‹¸ Ûpì¯ë‹ch4~uð˜/¤Ì5“×›Àqü²wf4¨n)¯fIõY êCãÀç™6§?ñ>mY¸à—Zº±8qüñ^ôÄ},¦ª/çûÒá“4mY­®¿î©lÊOÝ63-~‚•õ/æ€`þÖ°Ï6ôÞboÁ—¼er8Þ•dÿn2m&‡ÕÅhCº˜{—¨® ÄF»"¦\í%„„X°Áó%[ ­ó KR8´÷é—‹l2«©^– ýÔ«çµEÕ9 MG¥t ¶/Ü*¦åÚ¤ÍbÖA&f¢Ò-„øßÀâ^‹,&>5¯ÒWTOØ]¢_¥4Ù»ù“ç>Ðí“Xi0vÿÿi¢ŽÚÐÝÔ4Ö8ýˆPF\ mùòkª›Çÿ½´5æ“}Pî¶F+üâ{¯­å:À_ööI’©lèc!)Û»u9SÂÌ¢íÙ~Qº¼F§B ã›i,àÕ¹‹¼aÀ8Uò¥ƒ1léúáJÇmöfKiè$1ˆGÜnùƒÌ®å®4_ŸÀ.9xôÊ~Ç‹ŒðÉ€j‹Ðñ޹/^°vÛu!“zÁvw ÉÇÏ!N&2¦¤`ˆ ñ›â~æ =RgÊÏ~Âæ]W\á_j¬¶Q7.þÛÏt[\4Ù*ý®w$y™¢òéxŒÇ027Ñ_â7^Tl*ÙÏÈmº™mŸ+QTÉŸÑh«!²8 Q°ÿïš¼Ÿì…cÄÔ†e7?¥Õ^ÜŸüѵm ÀªöOªÆmTÂLªy@$®&ƒE©,©˜“ý þ@Zµ½º/\tš¿là‡…Ý_Z®Bä¬!9!©ìVÛgNH‘u¡$e´%ܶn¤žú²;Z±1RãçlB£´Ð¡E½n·ìSר¦~"Û}‡úइÉÓ ”䯇;‹Uu¸íIý]EòêÃMa Äî)Ç…ÒC[«éÆ.‘„N ¿”-0Ð+R1#FëºÇMY—gÑÈ3èbH!»}ì&Ÿ,òëÀF~ŒÖð^˜ŽœÙjH6aL^%9²Ý¾¸½)•÷,:BÎûB(ÅjÈ sÌÃ’ ¥†¬kÓ%ç£J¡ÿ YÒC–1èÇÉA˜k<|)SúІóë¸ù%}Àg‘ ±µ…ù¤ÿ k´+ÛÊ”¿_ú=Øg..ü°)eYe.DUÀc “¸^ýA€xù„TŸ)Õá¨,IŸ$ו…©pÒ™ÿ7ZЪ Mj´ÆÜñó2œOYßÇ:ŸýR§„¥:—}€ *¦&ˆý÷ÏooIMjٖ܈Jß% ©//¡Ó X¥€¨ .£Ø tßÕ¥s›v˜äOOžã<Ó“»’íj¡ÒÈö£kÿÅor¶ýç·•Ðád7Ÿ/Ñ!j¹¾S«Àg˜Èž {òˆ›? ‹ZŸTõ·°Y¸Õ¢c+K4aQçǘØ.+²-Á}«·=е>°ÄDÊY…`Vþ éÙÑ®ú,>ïuë!PæO?¸¿>Yߓի6× 2^)À¤vŒ±)=Ï9êœ3䶨Øõ(V´"3ĺ3ÁÜf·¾ ü•d•_‰éCcòî•o:´ë¹_ÇŒº0•’/°¸ê¨ãv¦0\üȤ€T¢Zð²ñH3_$¾ï5Ö0Þ©²ñâQBw… V¸ÄÎÀ®‘¦rÜLú$ÖÌ¿Çd{?HËÚñ(Æî—l æ ÿúHîiÖ÷„H\8Ìg=` ±3ÔÅ£¿Eè­'Él Í0Œ¸-|…ò{“éZìþ¦5§¥F HûõB”øŒ@éaÝWí³Š¼Ï\=ÀÌ4«¿<ÙÙ¾Û4U*Q&õ bËA ˜’»e^–1ôËQÑ({³|üóY`B†r¯¼¯‰_)Ýcj„)>A×Í_¸ªÁðq ÍŶâ.Y=fU‡ä3(¡2“LšñTÙ²Y½×v’X[ªÀ©ÀU†òï›T Q„¼‹Õèú÷}9ôë#ý¥ðcþr©©y|Ö^£ëh×Ó¶[œ§ã;trÆH¹Nã¶])+ý TäÐ' |õaúJ…Qš—´Ñ7@ªpï²gÀ\!}ž ^æ! ±‚æ•8à ÕêÁê¾H¢8ÎÚøC]¡‘iBööŽÿJÍ”eLÂÊV[éË#úÚY¨þíÛ»xwì»o`ê?J|øÖÁ nkWÌåü—l¤âQ‚½wï!C {ø*BòÀ°…ß!"ÙøcpΦØóñìÿ>…óèãÜál3ÍÀ¢ºYPl…‹(?#ð†+Ÿä!;²[ÒÁŠ©ÌhäؽUüæ-‚âÉöî,€Bñ-Í)[0ôצ—ð'­’]ðe±ýf3;¾zy»•èD%ˆ¤í%Ó·{ú'€ÆÈ¡çGó;^G5—\ãÏBº > \ˆoÆLµ!ÁG(ÌŠe¥»œ·‘O³HY_Q¾['j^ ë…Ljjšb|¡ö†y‡´6 ‚U÷–èižÍ ÓN5(ËrúeòV}bfêB¬d&Êø,ö²,Ó vnu –®7´Àî$Íþ”Ãy_ÎŒÂ+CJ9çˆÈ[œxȪ©jŒ¾C‰Ž Ó!÷c­ª´Ó– ÊhOUh6F.øÎÄþ?©ú£¾ ·¥¦yIÈÞRÖHGÍÍ¥×Ûl¤=3üãf¬÷"ý,DèlÌm;Æ‡Æø¾Ô,–ì.¨¶Ïy\™Ê4 uº-] {è%ÑûüUA ;aŸÐm‰´§LÒ•ÐF3:4( øØÛp¬ÀElp8„¼f 6ºqe†ß[%4‘¹`óÆŠJI$ÕlWB’Æj²ïçexý®›„«2‹·äýû䇫ÌJúϦ®U†ÈMF<‘¡ÝAOãC»(Åš[DU¯ŽŠŒ–÷ãKí¾†œä½¹ƒ”ÁÎÍ_û(ðtý>9ë£5s¹ªœÍ­“3"!`ûLm)m"j',‘ hò¬QÕSß=âÁ¨: Ò‹$tU^ƒo Ä-9`µ÷øë@e·±¯Ó‹ÞB*g²m®S?íÍë„ ñ>­ÃòË/g‡3R2ø!9usGWÿ`((?TnÏëÈ­m» ÷ñŽ®õžê ÄR °MÕ¥žZeÍútA˜_Û(ZÉ !¡ÁöìIPUm©>ͧƒ†’ ¯ˆEò¥™í¡¿Lý…ÇJ°‡G‘협I9Lo,ˆ¿>÷f Â{ˆMù¨æ=Tí5{{l¥ã[÷zˆu%ºMætßâÙ#ñHóºHGˆxÍòÂðñ€C Êpuî÷ià!rlëwa,=1ИJ‹*ŽæÊ@ÞD·I“fŽ_&„‘—5x÷"»UýŠZOâ±QXŠw”­rÚÿ „¿Sýõ»ÆCe†=º:;¾è®âQ^)‰•¸Z÷¼|gÁ¨¼s¹öÚÀ<ÃýÍÒ¡ ME)Npж ¦œÛØQÒ\ ÆNvq@s„MûD¿òjEÉ)ãC%ׂ& ™äñá±xâçºCsNdo1ðAÌ¢º0ÇF[ÐYÂQÝ}æ+ØÃh­;|‘d£ÃJU´¤ËÿÑîàcaÂÛ†e·ËGNÄlÖ6'%£?³ÿç.¤åÂIÉúƒcC…Î,é´‹“WhC‚4$£›ÐdÚcVm)-ÛvûqðKÆ©œ1z|;ò³íýõMÇ%Ý(HÓX6½ñ¨ä/ò”D„  EÕECíRKwÓ4^[aâ€Á[4q¶Ä‚ìÃ(^O Ìløñpâ9ü>Ÿè/uæì¶ô|“âO€xªÙ4ZÞpÿ†ðþh‚gFÌË*7>n sB]S=•ÉÿT΋¤{=ÿ‹vçû,2m¤~¥‹PM£ž¥²sÖ$Ô© ÏeÞ+¼Êg4,†\)ýÁëc¦ÍöÎïXíéŸn‚ß™ñIgÇÃ÷n æ‹!Ä¥©ž0¾ŒN¶€OÇ á }Î˜ÆØ?suÒ,"µ(Ä}PÿÕs+:¦♸u$Z”M|Òñ]dølÑ´,/Ü©°”‹|fê¥7¥iÿ°­ÿ›C_D×ùJ#•ã\þ™£Qñ°¾ñ|“öd¡¸êÖ›‚˜Hý¿$5Ñþ¸Û[±¦Ñ¼Ím *OB<' ‹ï® ( ’†Tj KŒˆK³ž2UøgÌtР«tW¨åYƒ”¡I2kW©ù5[Ìãà@Z5¦È¤C0ß‚Øã)2&—®þ}eߪjCÚ~®`Ó`梡Y6+ô¼Z†à€˜.i8hME³(ñÝXÕå'ðTDŒŸÞ£kH"—É vRsÍ×vÁ¬$Á—{ØÑjí}¨-ëññ>åÂÓE^*ëäH”±ð­ Þ*|¼L‚nðÕã±!ðí0°ÊÀuò`õ2¦)§='´}îBT›ÁÖµHÛC©S5±bgQ( ÂÔÊEsÊd„Ä„\^權H¥|¤Îÿ`O;ãÖ%ýܬ€Ü´8é¿»r¦þìmŸ˜±ìCõzÉg¸ „Ï93wënëÛ ¹w5™Ùø€!ùl £ …GH¶#;»ñЛz1*5'À÷½0BmnÓç‹Ýî9ÕphŠ|rfüæ27Y{©e€Ô™¯Oíg8}‰=@ü;³ '°§š‰Ü©m]‡Ö€bFmJž~§trwEh(úâÎ,Á’{¨Æ˜D^Ê#ˆ{´šü¿ÆÊÑVöHÙb*¿güÐ’Ñ=…Žââx´HpìÇ5q1¸µÔ•«;q¼F˜2J¤Jd&ŸjP­Ê–þÏ@¾ Ôo"ØöªêçKß±€¾m¬È“4Ý!âæeÉib?ê0í.rKy¹šÕ}/ô!c¹c)yŽ7W ,ÝòßO‡ëÖúRà0sÃi¸ÙNó£ø]-™Œ]Ú’òµñÖÎcrUI| ¦cT“焽šÍ¥ J´"&í[üÈàÿÑë6Y·¦~ª‰A¿9uMP_!b•ÝgîYj²É®7nµ|zúú–:È÷ÖÏo†`JUTU@òÞw ‡õzñô0»ao´ê›½C~`u÷'åöT<·øJ©h@€®R]¬ck‘ñ\!')$‘ÅP±»ò~ƒ:]åzý)5üï*tç€| c0µ^ØoÁ ]K«bìY!ëÍ1@4f­­C·ËL‡UƒÃæð˜v<Ñ•mc:y6r –,Æ0$u˜ŽÝvFƪ]‰Áß?Îx!9óÒ_]gñi€ïºø¿¤SwˆèD€ Âí ‰s°†ã-Ni>’Ù‡ {û">Mðì «6ßk=> ]gd°CÜ4?ŽvÞ« ¹¼xLK¹MKWùÖÿk3LØj ¶=B‘ø³ÂYK•¨eåQ?`]ê/?ûz²¤q}Wç —fUËhHh¼íÉ´ñy-)u Phx;ëÅ={&ÿ;¡(ßÖìT#ìe—Ââó÷ÖÛø†ÑÐò ¾—BÎ(ÉhÍüÊ<ö3A7¬ù<µå³Bÿø‰—¢†)j0Qº²ã‡Ž“s\±H'ËÊ¡ UŸ¬OÍÒ{d¹!sŒ<ÎËÆ{Mý3¿±&R ×›e °E.‰þÛ×¾•Î!!5 î?ÊܺÂ7ËÐ2× —`tòÑ' ƒ)§§¸>8ã%—¡E†ŸãíÄÛæ)ÌíÂÀ¯ƒvmw——h0÷ôK·xFBÛˆûÅÁ¥L}Ò_tp²'W>¢ô"•Ø|aSˆü[íùo=©l€bàaûïeÎ^Á)Àÿö¦‰úÛ%ãÈñ¿€x‘b×C\£X޵ªa“×þðWûY­XmÝ vç ¨œ]GŽÅÄo)º,ï?¯¼š2'Ï.áèÇ¢ùyŠy;°ôSèÍ?pm†¾M;!ÈX†B>Mòfpè*Ý:c¿•ëWómö+fRj¹Öy"ød̘zµ[ôpýb¼ÃQ+Så¥qõòH¿"Ê%SÇhˆn©ûÇ1°Ñø¸I ó€éÝ¢‰÷â¥LE“v<> féÄX$œ30¼»ÕŽ{H¡¸>7YãŸáäª厳 3SPä{ß!»ø]H¼Â›W< Vë›}³~Dèà70‚4Ü¥®ð/äG&žäbÇÍÕ™~jLÊr·£4—v¡ÕÜýžÒ¹*8€ Ç>æD+X™j²?êüç†]ëyÏl›öMŒéTÕ[¾Yk`¨ÃdÝJ¸#3B‰j´ ­Øª.U%%XÚ”Lı’ºÑîÅTÅQ}õW»„Ö)GHÂ>y´â16õTÄ­¾‘äU4o «¡ùÛ>sXÎëONß¡½h91 d1ðý?4é#ÖOÖq,cÛÿHã˪*®å,&ë6;²mvÈjù3d?Ô”Ôá1:ÔH‘\ûñ%HŒ@pÄ :ÆwzŸ‰E÷+-t±t_Íb ‰FŽêK–#Úµ"É»š_ŸÓÅþµ$Ê÷ÿßS:v¹¹1àC³‹sô'˜³ý‚ÞóÉ«~ %OUÜ›O÷`y÷W ¤rjŠd¦ýµ<¤Ye—‘5ŠžGg}V>í}ˆ(Ai71ª•TÊT§Î{v]ð}ev®™øà@ ¯oufF/dÙÔ¡=cè#t ÷¦異h¸³Âç€@5ô?ÓþÒ‰¾Cˆ™Û¡]®"?ÍÌÄG0dVéˆ<¨„ØWí—Mü±m6Š1« Cµ\¨ÚË¿à.Ç]§ëË4ÊPܸ’‡‡S­×É6 " …J0ÎN(?YrDá2´6ý”ºßÍÿtOT¥ÿ-ñ? “˜4šFÕ×lþóÅõ¹G ‡¿"‰wÁç@è ¾Š8)ˆ»es•(õEìjÓPNö?6$O÷–h¯ÀT´ý;ëœtyÒ_¼Þ7û~Þ—8‰‡ ¤ógºì"|”Ýv|Y+±C¹þÉ$²ô›+Ô}kÞm–AÈ~5«zÔ +!Ly‡ÿØ ‘熛’ÅeTÆÄ°Ì·†]_YR¼p+rÙœ-ÛV9–ÿÊ%÷òý‘·}¶?ŒøPü%hö£«î÷'÷Í6D î´ Ö$Í#ñ9ÈJÔ¦ê|¨\Ü-îyŒñIj Z5JiÈóúkÿ¯ŸG‹0–ˆwš>@)þÂn)'¯¶Æcd—£Åy$Ò(VD9ÐC ®l^du’ãV,‹[•C¯ ~å‘,èöOÛL-ŠÊgº”&Ð*gèï.šõ|½Žsy3((ð>%~΢/˜7i!;J]3Ïä\»Í{—z<´y1 Z˜:œÿSgžñûOax½ä–Ôªäò[–ç¤b]bʲa{48dC’¿Ç>‡OQùz‰”%Fĉ ÐäMx뛿R}¶eˆY8~j–O}aÄT =¢_3ç. O4Sú9Õèc™y/8¹Taf9WØTþ_ÆËìa g5¿A*÷¥Á—Òù#c†9éÑ’¶îNF:d³§wR‚žâ;|îÑí$Þ°b^¡0áH3ü¸ÚÇ—âsž‹ø"?]EÁ”Ç2sn/ñ1>c?øÇ0¾,ßZìõ;¡—*s~¦½E;YО¸­½®‡LȽ}wѾ-Í-!~ë&WØ÷ž¢ÌcüºÐBûÖ̬ӄÏOÏ’£ª ÿª+yO¼îÊ®ŽU td”+ è33³pœv,@¨«©"®~ÛÐ¥º§ß¨áS@´øä¼;lWö.~‚þü ‹éÓºí¡‡Ãê>å–:4ÕÞhÍà‚3è%ˆÓ{n…ŽÇ+Ô?zô…ÊûœÍóÇû$úgQ{–bèóÍ(ÃcfE˜£©CÛ%·Øg7h¤2üž]´e] °±'í©>ªQÂRaåjŒÄéèIÙ†3b/_Ð]Y–˜îmex˜]@ð ^±c5¾ƒ~a^[¢¡ÊHTœxH²6HÒ :ådÉ ;<Ð_|Žó”/[¯ÕºÅš®ßo±Éåö™ZÇ@¦"`Ÿmi]üÐjV8Ù™’´oö3Šñ”À_+è@ß¿{ÚûÃwÈŠÌYA?3¥cÏ;Ù­+ÑKŠv@ËwÑýÊcGUF½Ž}!62uòÓï}Äzµó#¯¯ÞÆìy±ûUÅ×#ýŸiBA—ê„DªDZí[ pÙLmH ï qsw ²N"–¾|ëqÏUZ‡m˜,FnzkÝbÂf'vdϹ¹>‘&¨>·ƒhÁ‡Foþ_ýE=›ì×aÊÎÍU@ê·POÁŒöMv,wZ‚Ì+z¡ËÍõŠ ÂW'€®ˆO\D­‰UÊŸÿ+? Ñ_î›-ÎïCDܳKYÍa9λ¿Í+;_øÜÿC|S¹…C˜¾F¾øV¹œ kódË®5áxW)ç Š÷ÁÀŽÎ>íêŒ}eìllyÃ'Ñ´„¤~m™0¥ÙÈД’°bÐ`ã— íMúã»+¸üºOĸ3=š ‰œúÛþÊÃ)éú˜´Ç§öQqÀh!mB9z@FD ¼>Kë ›²šAÇ!%ñÐ2æï÷¶XAôt¹LoëÊ.ÎŒìß"Ü“ð4Bj…ጲ5e¬|û\(ã>IòšŠÁupwcÜ,R+xÞã¶óD¡¯pЇAÕºáƒõcW Ý@Šr0~œ¸x €·)8ö9FÑ“nb(9nÿ=)‚ þÂM-7HïEI-0\xä¶0Aÿ.¢÷ãƒLW¤ Oü¬o¾ù*Ke¶]·zLj`¼ò‚ÔÜŽO­ ìq¢CÀÞ¶«Õf””œà­€E ðﰔܨ‹b˜ß¯:EÇ5ˆ\#DšÚ§Fá-†®®v ÀT¹.T1“Yˆ³Î­Ÿ‹~”ö|Aÿó_››nаÓúEÖtY#?Æ“¦rçóyP Þ®Ž/K鈧[¸nñ ‰C®õ  Pð9qì/£e@1s”×´Í΃–çâY‰Š)“wB4uõ}þÌf3Óv­Ò^³BW»UÙh £$÷zŠÅº[RM+¹O9cT©a-‰”XÖM¹$ƒQi½ÞÖ=õB~V•yx¾w±Ó;5”U˜ÆöÚ¬Ólj&ÎúO/¢l³äƒÊÌ›$­—¾hÍ4&æM¡’˜qoNNÆUŠ’+È”P%ºù%. Ö¨¡ìD'Gß]‘cCÅCç8Îoï a‡ÿ­¤äµ­ÛÄ-TúOò@EJƒëuÖöyÎswÿý‡OÂÆÍ8è¾îÜ#œ-ìÏS­·l¿>s3ꆑ´Á|U[›åìIМýÔ§ªº••T­½1÷ó½K”Ü/ë£õ¢Ö‹Ÿc(Û#î¿»¥h¯Ü¨ÿŠ2]+! ÇòÂ:½ê±Éf©â$Yhú¥>wb»Õá;D+Òã7JyÖÒðMе?Õ©¦û¾v3ü^«Ï¯ ~9ü"·NGQ’+6M)º„;%Þ¯.“XUĘzç™}u}ºiA~¤e|"V €¯–Åáì®ô#ËG舄ˆ$éXRžbŸZ£Ö‚ó-c Ûxñðç“™"fˆdòâÐ)ñúÛ¢ù‡Þ%_Ã&´uíe.øßCãì@$aœ”žÉŒ&Ab»¤ömK°{©”08ôÛ§tÜüPF^¯#„ê\w›EÏÍÕ}ŒÀWÆðl5vÑWSãà[ˆ -mßÑIQ À›A&0a6²¬P1~,øFeõt8"QóUKó*¬ÇuÎB,Í”ælºÖçq˜ßvY½2†ß÷÷ÚႬ]U0,7B]lºt'QXmNê "Î,GÂx¿4£Ýs=küôȉikuKÉá™·Ž.Õ—"•.å’ž¹ÔÓ…•FúÑíÁlÙ7—HÈ!žWLòob‰(ö{?Óoaý)RM±J‚›ô›4ôÉÕÃ;”Ngg=Œv –ß—_äuh¾%õ%öƶã¢YÎãÒ˜òÔ€O ¼Z¿w Ùµ}{Ci|AAwÝK6ÏZ¨‹§ å²RÀSH­u1åZÎ@QÔÜV_> çìÜŠ¤+ %„/÷ÊG>MÖB­'À•¤Z_•žš€Ÿ¬½#O˜ewÕGõTnFÍDµÑ*qY0ñ«8rÌOoùóŠºl°€R‚Uœ3"×Ú%¦)`Å­[l¶ÝŠž"B&mu´–] ~óX¬+ÏV ÉK­Á- jèö•r>w³¹›øÍSµ=C)??Å;©x”sbZÚæ #dýèÿÇ+ñÌŒV6üaü{/Kö$'·`Õ*ODK|äJ˜^w/[°M`™êA§¨?}ûCXÑßäAM§?ŒGÇ£¬À³•DÓÐW2§F¼ì¸2?¦W¬y´‡±3`' âÄ…»Y‰E0dçÂñÅ+tv nÞšr}…ïW>"NgÕEm²u¹À#&Bn<]°¨_´rQäjk•y"k¯\OÇR°’C{M“ñgpH©Ö,é6D*…zØ>j¤TP®4œIHãh\ô›¥ –„%ýy¦Í³•f ?ÔÉKuÜGu¦ÆwʆP}Ä‘ógX\5r‡@Î'>?§\ñL·“ß,Ê "õ[€õkuÊZ\®5S˜¨cËòß—GŸ–!m5hò=ìoç'$°45¶p­ø5ÌÃ!Ëç» qÅ#ŠQÞiÚt @ÊÕ@¥Á¤ñ†Õ»ÑX ü¶FÞ„_”Ø*(†ú*¨+V>.'!2^áÀÝ4î%Á)µ¦Yà“Úï ®LxN÷‰ðt0êoœ #:Òä¸Ä~¡“ ýʤ:®g“*ÞùØ(:±nYù+/…€“b"Âü@_¤5‡’Ë‮KÑV|Èkrì÷#@÷}%»x¤Ë€ò°zßÓXOc§ÒY75Aþ#J“Œæ"$…h5d>k™Ôd,»‡N¿8‰ÿ°YLºN™Z[ó>!ÃqÆ~½´°=$»Äx©ã“±ñáÇsYû]‰[¸×l×9Ò#÷±@zœÃf¹¨Æ`t·Ôåš3ZÄÓÃɬG“†ƒT[ižÔ ƒ'÷WÇ ?Y‰gK+ì¥(œhWüÖÒ(Iö¦àþ:Þã”iÓ(;L–=Ê’E¾_ø¥Ï(ïré´5ú_TðaCº±‡Í~K‚o[W(ìÕæÐb`U³Zfu¹û$eîó¯‡+ÆÌ©Â§<¾[\EÌØ‹‚Œoš>v™ý2u>àÊâ3¶ž#©Š/wXçÈå¦m¡ãÿtdØDš ÃÚ¢…ë³¢6>~®ÏlêÛÓWµ±º7Û™$ÛU¯ôs…®žØ ¤ÕÌt¨¿ ™„·í(—*æ«^oÌŒ…‹AE¹ÑžN“-8v¿†©¹.‡Ïiô)ɦ‚ÌÛrÓÊQÆÑϱð›#—±¬#•P·`7µ*CT‘¡F#½€Ô¸]V›…”–ü'¸Yy{&üŸ3NÓ©BåjÛ¸ßYî0L˜âYLÆßàጄ퓵-ÿ´Þ”öÏø"jø_ºj\6Ôa–Z ìñ2"¤éæ.ÆyþÕ?ù°x…£{‘Z£ #…Æ·'D™•iç4âk¥M´)’FÇÃÎÚ“Å¿àŒñHáÞs8ˆÓÓn ú9PÛ÷nX[奯ãJ ²„½6d’˜‘€_(r­mÉà]P®]d»GXwXsBêjk@w`ü.¼%,“tI±]ýî œôdŠ JŽp^­«”ï³x©Ø–6eI9°ê7!Dè'#£ Üu4+U7¢¾ˆ?Ï‚:šº.©ñú¾ëcMD¢{éAæ×ŸмÒNÞ…÷Ñ+·.ÑD±B†JºLú‡†„é2bû_Ø«k<»å”uºÑîÊ ¼?3ùQFŠ]k]tÛÒ @„ 9欉µÌ R©SÆuæGyp„˜Îò¤Ã`S­ïmKåFÈÝS¨œ3ŽÃÇK“˜Rð’FDäl®ƒBÕýƶù¥äÇ:‡9³QY–È”¤ÊÞ!ŒLº/Q=¶L< n™@š#æ¦rX¸‰=ö©ûî ?pÛ2œûåùTïŒämk!F¹~×]’‡ÅÍ_$󭜀ºyHß~Ù¼˜HÎÝØñ¶·ùÎŒÑ=²P—¹éQgÉk|iÆ}[ŒD•¨‰íwjø7GMú;¤ŒUùúWÊüEnÄ ‹vO³Ê»*,{ w>¯¤ÓŽáÍ^t§O#ͼ½i”ÃÔ+ T4Ö^z"noj©ÃwóåÓ}nÓðïƒ ãÑòÙæH·^ðg$žhl;ܫי`=Šœ?ÑpQÓùùܽԇYøq%@ÿ$øÕæIQÛt¹·ñXË©±0 ãÍŒ¨Y£`VZ Ö èŽžžp"rMúôRì¸úGŸ€DUB’±šZÈÅÕºàÅžÇý(}vxN½¥ZÑKŒü–÷FKSWt#–$Vâ¬ÚD{ºº›"KfÊh»YG‰Ìß àL”?ŽJ¯HlŒÓÅÊÑi‰" ¤Ö÷˜cÖàóäŠÈï§Ø¹ÿ¼æ¯#Öd?›<ö»Y³õ/«û ¬;k7ˆæ€è2Ë«‚_@jþÐnÒt™µœ±à:xb9I¯çÙ.uuª)GÅ3ªÆ‡dǼZ.6xJŽéÀ É ž­èк Ðâmà²"æuem;æ)4=ü1Ló™¬KA²_Ò²dÌ ®ÿ=¨¿HW.ª±Í`×cðLÇ Ä/C¦k™¼l¿z«vwÈ9*¥¡Ö\íЫ®Í-?É´|ìtò? Ëk@Ô ¬Ž9ðL-Nh€–n»UU" ?žéa#£g:¯÷Ǧ=·²GG·ã¯WI‹2‹o@¯Ì -©*γïÏOÂ<Ïí1xO7Ìör(µ…yŠºiYtz¹Ø,ÕFèNŠÊ“²îeD®QY¹݃ïP»VWžFîh‘¤rŸë¦mX`mè%ö»ÎÔíºæ½â¨ nªÂ §œ3äJ8ºÞ$"ìáx4i¤Ë‰Ö˜|ãdKí0«<¸t°…•Í+»ëùèh)j³ û+Ûì€ý7©\,#;@ØÃçÔ’B C5GÆëja¸FÚyswÞ˜*KÉÍsÙ(†;4wë­µüFúXGqÕáŒBõ1!ËÎaÄ/ƒºù—ÁÅý”:`ïòžò?zL¹é“²¸1x“”ÅÝ×Â×­-MÀzxàÿŽcîž:À£9€¡ìbÙžò[1¥É£Ú»ì‘4 £6Ä;o݉4 í 04Pmo¿ËÏ"ù½F¿&E4²€vàû4Ëçdv³~†Ãs)€D)òšÅGUL?»¶oÌt˜†!–¨$~†áV&HEú®Úc™…ò>ÁŽ©5ÕÇÛ|X {Nf+H†ás÷zj·lE Èÿn>Î[új%ë ›#†¸¬Jìô\?P; 1’ñ$DŸ¡Â"€suÁzo ­œ³RÅv`™`޶F¥cšP:nÓ˜L³Òxµ(‘ ýoksàŒûõ©QàºÊÈ©ÐyèÎañX°ÏZ4ûþ€öÙ]Ëj¿ë²e*šÇ4È„³ð‹ûý‘lô]·‹Pœu}&øŸIóƒóŠôîÒPMÚçYòeîx%º º˜R:ó(;ªqv«Ëwþø´)Ñ= V›~ Ó‚ŠiNjáp\ª‚Aš.ù#H[¤®ëú• 6®>9µÉ”Ä ˆŒ…0*’…VÉ<ϰª%öuÜúkÅnõøK»ÚÛ"Š Ã¥úÿ-ÅÀ$פŒvª×`°&û~ítR̾Y”¢Q¥ˆim2BòxMdg—¦ô"ÙÂ7Ä;Ž“¿Že`nö'ã´oS”¹¢,+myBz;é+lÉŸiŒœH,~ð"Îê2â2{qÝ RÈ]m³2²ÛZùÂ’Ï„œm^ë,çô'¹vÖ¯¸Úc’°¢Âqø9ï»·so ¦¹óÄŒk´QÊ¿Òt?·h$|† r²ù)€jñCÛ/2Gò®šË©ßÆgq8†Ô MÇP\R0B-ñHAéºïP{§qLà|°Åó„6â±²¾”»ß¶vc¯ÜéwÙ Åæš¿!ð·wÉXõ ×öª P_%<ú{ŒSYÀD2k‡®Y(†Ó÷ŽŽ—È( þI¿ ɸUXÃUol}Á²ÿüa½\Ž«E&$XVZȼÌÖT/î$ÚºHöLJ[ÿpmøðÓH»€2€ •„ ´žüçp™Ûî½KÙ¤Y,£d–t›Í2Ø Þ)>ekçÅíM=Ÿsïý(þô8öì¦ÆÈžÇø?m$iPIÿd.‰d%†€ž[TW€?“bšG€i_M©Ýd¹}ÈŠ #½áP• 2[A-È&ÅíÝ<˜ƒ@O~¢ú†ˆÛ´M“D¡“Úƒ]âœs u½‘ÁÎs´<º*+?€}òI`psg˜…š¥æwã—|¤hPà$u3WLË`õ/I±—ä­·‡@î9xóÐ<tÆ4Vêxkº»RÆ:*¦¹ì*Û„É¡¯ÂÔæœ±9x=¶+ &U4pM“Gxøˆ8zì5¸cˆâ ÔY»7¦„ ò¯Ï§Ã”~—óx+wžAäánsµ~–zЇk®šÏÝ0ºEÑȧ4a½++`>iã`…g YØXnH)ÖÅžÀl(`yú°ïØÞÛåU,fÓƒ“Ú…YäÒŸ¬;FÂBIO¨#_^z“ÌåþqkÏPî¾â¡æŽ«òôþÆCúÂËW’‹ãCzc¶ÌSä!Û¯O+ÊÛó>Žú¹sX+ÌÓ©CÈÕñ¬6h0·œp´ã–8‹>Ÿq À²Ä–“ïΆ“ Šx˜è£ïES¹—CÛL´3wAÜpÜ»)4D9Øß€,Wî•m~ø­F®ó!Ö~÷t€À«\ÌB¦£1‹ò,ÁWÍ…} ʾ,ÁïåÙFä5DÚr¨%¯oŒê4+&AžÙZaŒôÐ^£—2UÈ­ÏØ0B(Î.ê0e¯B<™Uw\J%VxMg*³‹‹G~ŸÊó;~MgìKLÕ»}pÞî U$ $¿ƒÔévñ˜¼ÛÒy`Dµ–¹“Á›½žå]Ñ,ŒÀE•I›Ø­ ±ºþøB”b»˜5ãÚ?5 ³?Ãm)¶Êm²Y…Ú;Ì®`üe#k»¡iK1 Áÿ}/†ÚY* Bi ˆÀ´óõ™gãZ¤Ž„][Ǫ*öd4²ÜÇÒ±-R#ݹ™†T‹ú0ò¸ªŠãLZúéëôMQâY{»Bç›ALQ< ؠ㇢ØN:(Å5è6øõõÜñ¬Ät°†;'Gmo,“QµBÍûW• ð“Y'ƒBë‘/ÿkxwXíò™] @¦Ò´Z¼}«iÁâhZ²þ›„b&g)S¹@P/2}îs»v2?9¢’ùÙ$!Åç4@Y}R bÂÓ’´¹J˜1öj7Êñ|šÅÒ“Åt|Rí¬”SЦ|º¤XɽýËP=%z¾‚•E/5³\IÆ IQ\Ê^—ÜÏÌǹnóO@8È6¥D“Ë1å!úœ´K2O˜ƒÉ[ÓMb³ër¤î‰­F«·.<†û”S§rbÙÖa”!¬ø„™¥…t抪‚H0„ެ¤K GpÜ:k²ß# er>ðË`¸(mWÍ& ýLv'g´|=B¸áÐX¼”Ëïjµ[2¹BIc®úÆ”®ŒkŒEu4Û½§)¿zŸ`F÷ÄDæ—‘c0àªåj¦rÓ¨< ãI­òï>ÂÄ„fþë ëЙqàÑ0´Öž5ø.Ṵ́¬aÿ7çÀñwÞÁnég8b›¨ Ü7wH‡­;õjÍ«ü=Hý©Qy4;ŽD9Ë¡k^DŒ.<˜|O< óÃÇÎúvQi¡×9ñ[àÒHlj¯L8…’L~Í5²\@…®VÅGž—à9œ¿Cá{lHžöuþpÖ•ÅÔÛÊ‹‚ÒäOö Û[/œÞ8®–?*b6¾ºþtðfà!„m/§hRûWó“˜Jg*¨Ð¿ßRÍ>¾'›%—0‚x$ ÉzGÃÁrÈ @t’w EAÊcv]»h›'òýA¾ÔXÙ[»0,õ¡Äcÿàš2  h{8¿Wdfs5Áê²p¥‡…‘_AN#ÖŠ…þnë²Þ´Àp@ô˜kº§½å.Æ1~‚„ñvŠl™x‚ñ2Þ§PFWèü''«Å®1^54óq„§ŒðKX ­A sdÏÈ•¢f¡5ÈY¨c¬ÇÜÓº^ÆžR§É4ŽÝãè¢ßeo;´w$¢ÔÆáÊ ­Kg!£…z¾Ð¼4jº6sMC“ý ÖèIÉ0žûý6­Ö}ÕÖŠ`ü ‹¶·Ê@¿æ²˜õS~Cˆ<Ì[­×Ckø„’ÂÆJ…÷è¢@W5Âl_CÙŸhî X‡F<Üæv!zR¥ØÕ†÷KµŽâãiT¾ RŒ7~]žþì·q|*q@|ØýLmJœÐprAÝ£^ϧQ…VZÖa½Ö¸0©]ÅDqH=®C7ŽägÐá~ÿ×õ⚌£ðk°rù+¨§·#7Ö$8?ê)çdˆ¿€`öCÌ©¬‘KVê6˜<¸ôgå ¸•Ö eÑ Ð™.ûµãì—ÏRˆ0‡¶¢¦V?5nÚc£ê_Àé§ìÛ‚ NúÅâ‘p‰³)‰oJÀ.1ó ¥LtühÃsÿôà…HGzΞÅÙÀI€Dk+Û£1aì —Š+ƒµ)©$¸V59­7:ñf§ÆÎXì´ïG!Ý_¿é™aqý{ß4]/³Þ@q;ûµvÑ’M~¦#sEñ޲9f5&èt†ùË%ªµ¡wÉvتoÝ;IâÖ„ãcÓ£Ïf>2öMITº*@(·Cî­õS,›Õ=ÿ¨h¬Ô^¡t{^Dþ±M©šbcû xSBêÌõ>lIªÌÒ@¢¬–®b¸Ñ£·cŸEBþÓݧ÷gŒOr"‰Î|46ÚŒdʹ¿&Qæ!¶–_!‚§×söf fM0åftõèPêEGk@ýC9°é/ɈŠÛqÄZòÄ£øÿmÓ¡†Â'm†ól ÒN¡àè‹£#ó³ÈpEh¾ª§}ÒT±CֱμkdNf†C!ê Ú‘~ˆ-Þ‹ý€tŠAˆx3MüS‘âŠE‰=&y˜Ÿ;çÓp·Ô›yÊé³—çvti¾|¢"QÒ- w„˜tµY*9<ÞðÅca¿@ÚÚ¹ÐLLXÅ?¡µWX‡¡ rXèüÜv^d¾ª³b2¼ ç {]™•3˜JªÙ}Ñx~!ߺ¯(øåž¡‰v#1j’s…ª#´|u¨’r¯Ñ@.t;/“§]‘>±Y¸t*„1B Q¢—Y6 ¹}›Û½S¥N¤p@šiJ@¢œÝ¹/ÖøÞŒÐìçÁŒÉ³ì°0åÈÁ ¶ªäÖ®‰ÆIâ²Z5™yù3ÀV;}ç{!V* ‘ÏÑ(b'D7ÓôëD4ÍÓ´V )ÿ®¿¿ n_ã©.APUéRAº#äÿ¬·3(ØöÙ‘7¸ÏF EªC ÜþòÝòZ/º§c5)ù MÅ6"F—‘å ©(UJ“lvé9¿Z˜­÷Ýïéró‰¼'ÔËv—<Ä—–nR@†S¶ë}>TÑωb`ÄR/hÁ)EëlK­¾‚÷­ï¥Ï4*¶G"šF˜Ò²dDðU­F!& ûäþjg.Úâ:P£úHüâùذ÷ ŸíúãddQH*¡2íHªÙ²¥R¾Ù: ~9žÆúÄ]q¢Èj;,/ Ð4½“UkZX½[eùf÷⯂6=81Fùào^.Ýû&¼E=,ñö¤I Ë æt66ŒZÍú6­¤Af׶ꘪêÔ‘À‰¸¯ Å/¡•E0NG=»€Ý¯­Ûik4|á?qMHýåÜÙàw «pvC¸wv6íršC™¿Àå¤6`i6ÆÇ**~ºù…¾ëo.ÏÇÞÐ;a»ØÌGÑxÙMäP‚šhÇùeéi¬ÐABÛ…¦n~YBSl;©7t=¬Îò\ôî–êóNª<ü…|SôÖ@ÊÜýòœt?r1‚QüÎÆ]m% 8ÐÛâÝG…Ul ®=‹¹GO9ÂçXâ5Fß “”‹à*LücJÆ­ºÛ¢õ5Ñž™ R˜mm€üˆ¨„ë K(Þ¼ç0hñ\C‹~¶}†€±?áºÿûô›,h>˜×Öqö­Áޱdßy‘VÏrôû{êÝÍ©?h‰±- ¾5ä…ÖN+NËÖvš1Ù×-7›ßnîÖXÆÜR:·n ÐÊš®8Fj+„Žj-ÕZøilt°¶'¸–/÷+º†ýþÚÝò ãôQAÁq.§±²KôñZ¥$àuz¢;Áßs뙫t!qá •='ÄQâ”ÀðâÔoÂØ‹öHvÄîb؈_P^.dD¶cÖ4õOJÌ0Õé"9ÉŠåìN²œÙ(AfËEçõyŽj^“j>wbÞ1>PN!»‰¨‰¨¬IæìnYõãË)£­ãŽOÛH$4‡\Bƒö›õ0ÊJší®,óQhá™1fÀÃeƒ-ý»O M[%Ьȡ†úúM•âÛwøg«€ ó¿4í3‚0¬šnšŸljùõ~m‘lîš”˜cì#:1‘ä­íÙG¾×H?ÎÜäØGsDºYEøé‚︅±hìíulú* 9¹2Õé€ LÕH°ð nc¯Êw¶ôžy Q«fú›µ!ƒCITnmgø°ÏË2Î˯«5œãvº{MDœ¿#¥ªôšø ÷pš_j¯xõºè–‰[¸Øx¸)}ͨ½Ÿx«ù¿s„—1lÄL÷|Û¾D¢úº ¦ÿØ%¤uáh&J?C`2÷ý:þU˜ç ;îð©§3B =þ%Ûi \ÜT·¶ÄýGh­¬É|+ô¿ÒεßkÏH% Ák‹‚Òµ‡–(¨WêljtsæX{¿²(øjˆÔš¹“Ï2né ×~#ˆ‚ÇH¸ðƃ×íâ³÷±C0ÕPç‘ üÙ‘ì1Â/îE:×Q²?îÔöœ÷ÔÐfZ~Ç;,äÄhn¼äürU'ÞÜ$¥·¹°%î±Å+)$ôX|+Ïeg0›™Û[ ç­4‚2ž­ñü5Ç£roS¥ØNxÌ]xKò Ý“ÑÇ0ñ‹ÐI:>…ÙI®p/†œ+v,6!V)Öð­Iôk˜‹çóÛí/¼äPi…\Òb’nÁ¡s¤m • t•5¨î6°Cæ-¾HŸÂ-!Ú…Û ®M2‰¬6úÍ eŽ| \¨uÞßÓâØ‹êtÊER%OôŸ^Ù•(xZŸ›hfÊ Ç º ÕòiÃbûKH£Üë’ų:ñˆ^NÊÊ ¸I"YŒ‚í ÌM·{}ƒú.rÞ‹nhQè ±ä̵Ói Eá³Î•nÐìï l…º¾’•Àæ{éDá©t ˆ0MqI,Ë-‚˜ê1¥€S>£Ž8PF7›WÎ=™'º$.¶F£rwÓ+‹v.Äï²éy”†¯³25 Ÿ…+¶ã]Ñ…©¨[:×—…°Ÿq„®_‹©èÁ@@q¦í]jdÇ¡0¾ŒÛàÞ×ÙÇ=O#zËZõ„¹9 …ÙêªÝCÌ0c»z;€4ºXGž]ÜsÃo$Ù¯n6Í{Ž,œMñhFÆÎçœÑ³&.ÒF#ðüªÌÔ!âvè’5Y5³·º›£V·DÉD|n %Våÿ{?kuWýÊuþS…°§ÈsRbZGá/y6UJ²ø ‰iLMÊÇ‘ÌöOêúÄØ{_ÖÁìž»=0,ýZ;°?ßbËíÙÊ.ÕãD&|óøåÒ)óÕô\Êë½<#›/й t§W]{~ßÃÀذw–MŽ0æ±ÖŒ<ì8Hv”D† ‹y~hm|)+íÉ~ó ¦xKTP,ò†y9²ÝOЋ}–F‹‚Z ”Â`—KÕÉ^.ÌÆÆ\¹¬C\P,ƒ6¿¾(¬øD[ɺ¿‘4”zo€‘¸~wÿ°;ÊaÚ‰€8íõò'h~j¬0)Sçl &õþƒ$/‡>D5’þ}¢ñ›Ù¤üWŠÚKŒgD“ôkþ4|ã%vÒÅÙt¸¼÷VXs­[jn…¿ú÷4U T8s²öÀ0¢„’³>ÓeDÈÄ¢‰IÛE`@¯ ÍÎé:Yp\¯FÈö«Ðƒ[=ÇER2îB]“Ññ] Z;èp¼]v:ñuHCËÆQNíÔ©DÅjSÉŸL ä§ò“Bí7|v?U¥ÏwÈv4ÚúIB;7%ták‘}R÷l¸b‡?ü_,i| ˆ˜M-Ùr_ÑÈe<™·.^ƒŒ)u£Þ´Ñ·s’‡àfxõpJÅBØ©ƒzB§ÿáî[F‰žÎPc( .mi&Å ›&ÃÊ*ÌÙHu@ì4 èÍ£/´ìŠˆé<œ‰9Ž<×kF®ýñácuÃb‘þÁÐ ¦òoV¯…2°£Ø˜eÊv«- ‘›É^¦ë’nr)G‹®à‘ Ô™­ç7”°ïá,†]+ÃþA4÷ I3ù*ˆ—|O*r·Ü/ÒŠ¿04lg´˜¬t±Q´M³êŠM"¯^xÖ‰€W0ç°YEwb×ËßÛNÚ×€Ô˜ægŠd 7‹ñ]yU8Dß'ÍÂq´ >¿Ü& ŬÖÆòl¸€|•i=¢9£»ð:ÞD2ѱ®îÔYŽ)—øÙ¼æeñgã‰õ8xÒðsôE‘{<\¶oÉÕD~ð{àŒquFÂ4b¨Ìd(™þ…HöÚçÝ™þÂþÄ¶à–˜•«Œaf.s¡.qš0ÏÃ*º"$ ˆ2ž îI¸M׉5ä¹UœÁ᱆ÚÅõtú%‹&òNYwð˜ ÙJøgllY¦¶“=­ØìÅD†^¦2mòg‚Ü-.5WP&‚x¡?s1žxCˆÃ†2šþ¬J{ç9nyE‹+#AЖ)Y&» ‡$™u'Œ]hý¹–KñRHÐ9-&0ÏÌ “–ôÑ÷€Â&CÕe5K~(ÎÄcc8Ù”è׋eµ{âÚ¿¤©ã²Ly†˜FP£Â#ø±ÿ†¾=Mà@xHï-8ˆ|¤ÂLÏÛ˜:¾À4aŒúë‡1»ëpÈF´øUf÷TP1›J]ý@¹À gºlÄͦK"7Nc?/É–ð-»—ô󈮓›2Hû"pï[QºL×d–E³¥÷å=ˆ‰ÜŸwY|#‡ ™Õ-12–n¡Xj\EÚ%{w¥¾7ªrÌ”­8›àtôQµVŸ›Ö]IþíÀ d$qëyq¡¢½#Ø¢”tâΣ7çÂK\«ÎI3¡9ýñj,Os‚Bá­z’ìæÍ½Š\Õ´±pç¢aQEz,G™—P¿ìûP×ZÒû4e]…äB{Åô¢2J)Iƹ@;œ#Âa™ó–Û^U€¢)ª®A¥(bû?µÄæS¡øŠ”œb˸µý߇ïÞò¤þXó„‰Èq€2Ý^P€í72jçÞ˼„Éu&Øsô¢)CEœÅ[]ös§Ôªs© &¶J CûŒo‚ŠãÖ²¿U‚ù9¾$k¾fã#ó8­¨–Q€äzõÜ;©¸ÅÆH a~lÙW.Ò\¬_ò—WêY†4QUy:œððq1ʲÖTÛ¦y—›j®°"’Ñc%7;ØÔëjßñŠÝ½§ªÅ±àãÎÞYåDãÁ²ÕY/Š`h†ëMæ®Ý¤ÆH-â}apód(§¼aاÒîKÛ:%WßëBf½Ã*gkäæ;Ľ¥jMv¬ÌY'þ¦mmôš`d¾$)9ÂZîc¡I;«ÍÙ×V>c¡M êH®qŒ'vC¾Ú'—¹_ðÈW$öw™SV4»JÖ˯›:§d†Ÿ€w8h¶:îmösÙ@;mV»b€éšßà oòþ™)ôBaJnˤæÀ¾>owQhoƵfÑ\ËØãÚ®m¬ÐBó·E]ˆT®ý+ÐQ_¶©É3þ`E™a$eØ—¥nb›„nC¦šÚžd•°XPðÃ7–ðXHàý¸-ɉ¨äíw£ØM¶ä·¢L?vø^šû T˜ ‰‚IZLÖ š÷6Ø*~¯èùåV¦G0Ð;-q«)s G/ñ©dþ^Ív°PÁ¨Éªû'˜s“HŽË…ö}“îpݨå@ð¡‹¿¯¸Ž®Nd§ïÍéó"‹$-SßÁJŠªŒ1Wm4¶@'HKʼòó']]^ÓÝ9Q÷€1oV$í)ÏbÇ&¿©È)HXˆõõvåH8ÊÊX¶Ì«ê¥Sžg-É>¯fÊ@¹¬Ç5yxíµˆŽ÷¼«¤§‡†vÏôùëì¯P3‚µx#Eµ¥†!«“?E®¡+Nsi*V‘6*¶[Í|¼ç] ⯻‘‘¥*Q<ñ«õ {¹Î wÜ w€Â;ÔTÏåk3ù>œ…8Ù  æð!€H¡àÎG1.ï†ÏoñoùY£€ågØ(}aê”&~#ÿ .k»õ‘›‰ÜfixÑÿþ†ðÎ̉õb=°öÆÍu”âÓÐW”uñœ½|f<:X§í`ÕaºdÑ'±õ)aM0ü÷äò:¶· pºöÌ‘Nûq vR#‡ÜÈ "Ò·JHc÷4¸¶.u¢­µÝu9©ûÃlâá–•pÐôæ äÍQJlMà^pK‘ÔÏý¹²};¬¤îîN¦˜é'µ§Aœ›èÈ.s=’´FkäˆáÃZ9⛣‰º‚ì05d&”¨ T{ú‹¬¼êÕŸ‰ÊÙ•§À%ùwPˆ¸)Ðÿ/3ðq³Ü5 ´CŒWÝ—ôz“º®™ºÑ`‹:/jDˆæ"\ß“°ÅÀËÇ«§–[¿qÎH¸Óv­`YpÙ->Ö+Wㄽk‹@ÆýˆXQXäëò—¹„=äTK—"ÀB‘‘c5öö\Ù7õ„_8<"Q–*š\»ÄÛ#‘|kf#TÇéŒØr5qßYìSÈ@ Xê¾NÜÁz¥È0Äd4ÈÛ›ƒÔ,}uQõí…– OêëØ•óU=¾Ú¥5'⇪ï¹eü!«šñh–Ŧg†Û”zĂߣlyбf1 j£']Ë}•äf6 4þ¹ƒ}¹Ò´ªÆ=:°ÈÖîJÄ_ ¤Q2"¹õ©†¦Áë J¿×w!1Ãç”Ö@ÑwìO‹©—Øý 67À••Ü<§Ø<;%bɸ«ô§l¥Z¥\‘…£¹ºk¯Ç?®:Gä"Q¢ì`"4 æé+z#ôð=4MÒ&÷ìè/ ç"TJBë塘R}í-ØD)!ªVûÜ*¶XnëæF}Tž²Ó Z©›^»«óq~Eõ[uý!Þ¢áSG×j-z›&56NÈNЪ "€c¢û‡•L¤r¢{8ÁàB Öä’2ª•6öuµ@T"åÏ_Èöœ'óžð1i¾—­ÿ£¤4s=FM´ñûš‹¾ëþ¹5ßîWÇËd ¥ûºanuC;Ī›’½&ñ+·PÜbC=//ô(¤?㪉¾$ýz  sy6µ&/“@ÊÑ|¬¢xAOщÎúÆÓÓ²‘ès·•im M_µÊ‚#[ö´m›bÓQ¬¬êb¤Tâ,dPôí=S¿-æ“üIõÄ*lÍzºlñó"ÜFä´m6pQ}\ìu¯Ç°ª€Ö¯~ýâ¡tŠ/ä´¥³*Ù,‹>\µ³è¤9›^d'Kï©[ŠD}¢¸— f)hXáµ.&‹h4O;¯øD”·7®¦5b^[øpXžaÀé…^´âs’z[³·m4‹UêA}ìkq(` Å™;Gfß)‡¡ËqŸŠ` FhÀûÐæ ö­w)DŬ–Ý­ÝøŠ¾ßdÓ,cðmj7qËÚäÌÙ/¿^^úW䨭Ú{ð•žù9lБ#J™ú•ñ˜Ô>àÈB^ü yœM{šýPj‹þ¥¢ºÇ"Ž»:>s"„ª9w˜%^xuh{ì×b%ãoŒMjr6¥ g]Um´"Ëý‰ü¾3U²D9W«z4µÇN(ŽüZµ VX` Ç*c¡àZØNˆÿáÁh±½uŸÿ@žxÚÔiº–¾%u—g°MO‡PΛôâÝS áFz5ñ²M%G­ýªƒÿ»½–ì‚ÇO¹Äº»Žuµ*b$áx˜˜>º IyR,Ñhâ¬&XÿG,âhCμ±å1l‚]1ýÆ+Ù¿ú"ö‡¢áß ¢¶Ý?EgЖ-1þü¿ÔÂôX2Ô;ö8PÄr‘ŽŸ’£DÊ•’·*§uN“Bà@±…ùb‰íË_ø‹Y ¯õ˜ÅÉñ9âÒh§DyÆÑ sŽ­õK‘íi{Ó¼¤“Ô£‚"Ñ‘,PõvªK¡Þ±¢ÚM*'›Æ“‰Ñ5p)êUmzŽ7—¡²^ªÐÍ$wŒ'û¸Îà•Øojæˆw¿2D3žU„4™D&^liŒûØ×Žô#VgiÃ@Ô‘Ýó°K¹.¹©âçÁö°Y9~]É‚jÆZ·™Ó9Ïÿ3¥}VÏßrËx||.êÌnÇ\ƒÍs¦Èžsj!Þ`,®TLj ”%¼â}1¿wwd‰nwùR-s‰t:φdn‹]M 5n±°Tê§dڙɬÑÑf, ¯µéÎÝ¢Àêºxs›l´âÓ¹FD3iY£^¾ÆèŒÈh2Ó¢¾Vš}µ{è1c9¼­»¶ë¿S¬1úÂdJ4ÖÄYûeÿ=¾Pl_µ‡)…S½²÷k–)@bauþªþ“ õjwnprÛNœþ÷ë3X†"ëÝ_—Îj¸ÉžtF•ef¸4)ÛB)É ï$ ‘¹Á½–“þ‰Ù½Æì{Oÿ³°œ‘®€ú›Ç?[õdþxô€#¼­¿vn¤ÞÍÔh‘ ïY sz¨Ó ·Ÿr°öMìI‡š/Òøëȵñ"ô¤³tÞцêš%¹yvoYuíB&‹wˆ¬lÇgNÒ}\UiˆIHkŒbKõ˵ÐT@Èk'ïù²í$XºEר¸Š$'‰"ÇTÏ(÷ƒV¥ ùߨ¿}µ‰lc€h,£Ð?!Ëê!³ü›¿Ë™K½ñÌÚæÊ faNnTL7Ç$êÄÞ ñ¢l¼Ÿ N4ÕØ¤¶ìàZ¿ÕÂ7º2'Öïðîá¼E:hÝv¡ðh>kžëÁ|hnîàÔ³æö¸Éε#„F§íÏ$?`ƒµUA¡nO–ÆÏY|¯éÑ™¾½Þ±ÎÆ>áÀh»0”ÑkÉq*4ÄX]=-œ&;‘ïféÃ2t{¹üŸlå=æ­ÿðFÆgœëóDмÕÉoôpE§Ò…¶¼`Š8ÊÚ­öNã[ߎ2µþŸw«:ŸK¾­¨3sÉ÷ê€-ëÒ‡åYM0PO9h¾4Ö§y7]á‘)> WÀO¦P!5Ђ¡»¯|wH¼øõ½¡Ê8ê·ØòNÌke»¾ógã+Ñê¢íµ\èçX ®‡®|WGbä”wÁÂ#ˆ©jöÜ`,wÿÑ•·äè:"Þ@é‰O _OCí¢YÊÕUîl" HPdŽ\}?Z|mJ¨)fUÂñ5k' Ai›¦ÔÁO{o8å>,Ȧj𭺺žŸáœàû>~Hý1r6;•â=P$Qæ½ÍL† 9@².²EÔžÅ(,̳Ÿ-\7hù‰‡©wûfø^y‡ž¡‹G䜂摛®èÔp,º« €¤óëuT1ÏÜMø´·Ùjîé)+ö”]ú}…¶#ÒÖ}øÿÉ Žô{Æ@S¾´ÉT=@4LG‡]>Þ+iÈý°"ýhÒv›pàÁ¤z˜Ñ<AßÔ›uÓ¿Ÿ‰/™º ìW¼?4hYQà¹9»¦®ß|…4UgqÆU¶WRµÌ·,ŽŸ««ŸÄŠ¢$ …b[y4ªð"øcíêÍ…Cþ}bNÞ»¸VFeü’Ò« r²ÈÐÃ,IˆúSdª'ýtfä/¹Û܃ 9¸¾VN¢2¯I  ÷(ý¨L(›r*£ʾé—õ9ÕÃ*Üç^g› 2€ØX~¨A}?F`³ï=OµÇởj4´Ìïáš>ßÉɳž¾fÃ=¹ú"ã#Î\¸µ™¡>pkSäž`ò«Ò¦¬c)ÕuòÜS~^I”4´|¯o¡@cºåñ+fçE4FÞ˜³™eÑ1d)‰!´‹œëé—fËDiùñ€‡ßnîyo${É=Ý£Ö+)­`m,L¨vã7€÷ ò7`¼›Ÿ¶ìëf‚ÀŠZéLsë¯Þºmì¸ý½§ß2 SÆFÎÛP|C9ûòp,¨ÅÝ™Á8îÞ±©  ¾‘“˜áåÇ.v{ÏØÍÿëtd¨ògTý›8ø®'û˜†¯ºF€³^YsÛ!3Ãr§6ÙÞÕF÷¼ØQ_×VÙWÉ^qV )ÀB¼Ëànb|¬ðàÊgû ½~P£6cZ¦´£\\"NŽ8Îy¬$ï‚D¤2Rûª¶ÄôÝKÒ93Ê=ÈD&ïÇJðF²ÏôÎû%vV…ÉwúÊÖoLâfp“—Çj¡Iìjˆ"LOSs϶ÜSºÀ|Ú(tÿð ¤ý„IRðȽŠÎÓ…’—"k}“-æ™û¸éý„ð£]±B°f„Ý`Ãò^vlQ©§ºS<ÍÍSbÅOK¨Î?täˆK¦–àåݹŠ( ¾ãD1CIúýn]·\cž`']J Ú©T6ƒ&?ú"îL{¯=ñ5À[D*¥;çXçPFfâ)-¨ÌB3¥ðîŸ2!;àBÆ݉Ú”B}Ó]žšŸRaçx2~Ä®OÏúI:ƒ«ŸswvzÉ'ïãÀÙxÅv³Š$q¬œó`×yq™M®fÝyfÍDб Å–ˆ ’wÃÍ^—%<œÖ#Av§÷ƒM’ëyÝ9FÏ?(?‡*“Û¨ÍjS“Aƒo’øY¢{×>3üc…å¶{õ°ÐV“*ºÙ¬X/Ä¡ÜàN>Ö†wt/n¤º]’D‡ç5Ú8ìªY%16h·³ƒáùýa£b‘–y„b>žpȳìÝ>sHk÷äJ‚û -f²ùÐ.1:–¿:[*©½uTõ‰“V aÃí‘Bõ\{Å0I8Ô_o«ÛNîV¢»“Ž‘.3ù#ÑüF\úµfX2ZPL!„Ï!9Æ·µ´/í´s"‡ãÂ©ÎæHÍØ¢ác|ÊOxózt;gNS­QK3$1wZÏkÓ‰B{=!£ŸÅëtÐϾyWÌ{¤0ßyù{á’älE …o"Í—°°sÚ€#¾½¤ t±¼ 4å$¬dfŠÕæ _Ä+­ŸDÍ{þ=ÒrCÔ•›š ãᙎ¤²;~ƒZ·hF;>¶¢´Ýy™8ªL÷^Å z¶[®ÿD²×> ôOeèåøÇ„̪ÈdtAÁy±þû6KïëZðs<Íwö®Øåâ»{TòZ¥6 (õ éÏF%òzZ\/ Ò’G´t^°á€p‡£¨ð3zçV¦ÏãG óòÛ™ß@©?˜œµq]jwItâNûŸ<äµ›ƒÖm©¶Ü}v—%„– Z5©Ÿm±À/iX¢.kÙ#úê4CgŒãh8^á¡VÊ–.´¾PÀC¿ÿ××,6È´€ïté"Ådý9.y².¿S™­×õð@Ð͢粦¶QFf¯þ©õænÆ"©²:`äS‰Lµ†ZD / V¸¶=qî!G£*‘$V»œè,;[<Ÿƒ¼¿OáBs™‘*©ksx6zá¿ozÅÍþFŠŸ¨Ã hù4Í@­M¬#/F«mµƒ/µŽ#GF „CkhÄ:þu2G ß– AVÆ—ÁÐs¬-0‡D&ëde.”£æ:MíDžŠÆUÞ®÷›ÌÙá ¿FÉöŒ+Në"¥Å‡X’zÉ™^íç_zÁrœgÎ ̘X¡û|ÁFô³Ye]üÜ|SOÐÈ»àÐMXÂÈlæD’Ñ+k§%³óòÕM¨q\žs° ÒßztûïÊÄÁ¼÷ì˜ðƒˆ¨M·ï\‰ªêfcrcóˆj Pd7/þEbÎwÝÓøHHî Oo„Î ÿáÓiáþmý—‘ÎŽwïwuŒ¼d6$LšjJ!O$q8Glnnvð;c+±u÷>nc7¾‹®_ ×p¬ÂÇžS'zɰ‹}îÍ9:‰#‡7í‡Í¬þéasêj½³·]ý­.¢ÝpR¤wºj)þ&¶…]—Fw1¹…œ°Ój^Íʽ\ú'M{=µ= @1ä×âå2yf_ÆšUŒ3[ÆMŒÉìåªä¯gpœ·0ÁÅ?ôNî‘xqX”2·?°°»©Csà*tß5ÍáqBibL¸5`å  ù©$Gÿ5s>Éá¡i"7="Ý;…\DÛÂ…öä%NC´‡lŒk/gÌìVw8 ±uÈxŒY9+´^8ÏÞåî-Mh…].泜÷Öï™ìïJ<ƒäÿ•t!=ª!¯+Æ>Ì:bŒhdËšg“øKº,2¯ã–Òრ¥ŸRJ`(©¡P¾Dûùd$ã”)óÈ\§ª“Q¢yùÎ/Á÷¶¯[XÆûCøH~Ín¼…‹²F)æªüÍõbxľ-ÎÈâÝjb)S„wà²Wöœ?±“›ä‘À—G/\Ør„¸ºG#yÊZ‚£l¯ÙÝg,át…Föb¡ðí†ËÜÚÍa)Éu¡h”TA¥éìÍR.ˆ~D›Â'!?tõ‡úN—¹®·}ÇB¬DìÀ9ƒÔq­‘†³¥¢bÉ`Ãý!¡!m}ˆgòbªÊÑ+r̲¼$±çܶE–BxµyN½ ¤¯ó+#ayf~áðÌ•>§6ÚÞ³PÿÒIs>ÒvçcZâg Õ@úÿÄÔö&$¹:«7Û;×áÇ;|Ùn6\øE"ƒÖ‘>Ʊ굿¤ôçjJ÷=ž¾TÇ–©‚¸M€6¨|$v u³ •æKòµõ¼Kà±yXMÖX½Ð\m½a@Ù).&sÓÆ9;½(‰¾’»az$ü“ œVšo\ÿ‡vÅ—ø#¯vLú…¡ùݡܛ"¯²0ÂíõÝ¡é0¤æn|ÿGt•ÿ7d¢(/Î+™ø²QÑ÷ÓJ´ÈíñØVožÛeÈ1^Y<.=ÚCµÑø¹Ô ¢Ä8“™äð…Ìîà5Ý¢YålO}dñ_ÿZó7ƒÚìÚ¼n¿¥ñ Iñð;ŒÝç«ãu–•> XÁ¹uÅ„I1¹¹“ß& ׌™vzc 9ÛëOSkîYq øªUuJg!¨eþrÌ’³éi$AoÇ:ÉWì›Ó¬¥Â¡œi/cÛQMW/§ÁÂQ¿&¤›á˜*FñÐK+IÄш<áY}ž—ÇTh±åO#湘sú7#2"/ƒõ´€ä†hV̵d"ßÇP÷_/àâévý¿Æû^10SÌ¥óY ·bòn†c7«Y ·ý'(¢‹bIJý¹c]ïŒò+bëÌÏNo2Õ@µp°8\ý”»îÈ–ú‹ÐQèKáù”â/ÇÿÿüÝÀuݨD’·dŽG.ßed*â_9ZîRJø8«Q2W|ÁlPú7þ¶ØêÐ3V @a„ÈsLòòÃr]]! Ðþ('j¿x“J9T窗òØ`9¯P(»^ô7cU»jf¨‚¶[   M™Oò¦ƒÄçīφ}4s»rÍT™µž@g–ªªUlnú·®Œñ?OØr8ßáEEn˜ŽvtqVÅÃdz§w‰¯uó„o z¿3¾· x\쨈îãîo?~ñ-àò+•¤ÅWn¿ž„ã¢Qȧ#e͵ Ö¸Óbî!ÀNŸØO‚mL¿ÅþµÒíÛk‹…^Žú¤ÿ†VZÎ6Žÿ  ºK‘¯Ò èàžü›4e÷®Îsó‡… Huðz"©Ûßeï»ÿˆ9V NÉ]JW<ªÏ6¦\Š}uvÅ¡®‘Û……´SÍÎÚµæQ’]tHÀM!8Eþ\NâZvD2#±”¹iguø}æŒðþÎí ˆ´ê ìÏ.´JóûV8Þ­Fºð©_,ûmr» ¯ú¤jÄáë{ÃØmHwŸ<û¿­Ö×î†Æw¼tgÕäƒÎyê°uu/R¥2Õêh E¥âˆwB 7+ˆYÁ¦X)=ض2c€ ¿§›'fV¯Õ‡™ÇdLÙÞª³º0ºíÔÖŽãà(''è/Ú®™ÛmßÅÿÑàÛ^²ÂdÎÄqJUÒ—Jy:p&Åy$n‡ÇÚà ŸÚÞœpŒ—ÙÙôÄsU'6NŠ]‚á úæËcxý°{ n¹¨üA'I±s±«—ì£ HloÄã½YÿÕ›V½Ø·ꆊ„ö$mìÌŒÝñõ!äU«¤‹Pqø’¼¤¼)Óœ ` CüÇEzÿ²Ðõ¼*˜D¶8(F+¤ÛiKwÂ|úò-Ù—Q™oÑß}}數ì´[‚î ˆùrÕA Ó«¹†¸Nº#‰Ž¿¶Fhx…˜EîæÂPGZRèæ8'ÄþEiG+< koxñ1×wõ{ “JQžÞÒ‚?ÔY¬Z‹Y ØíÑGÖÊEF•W-8¨?Zíb0>ϼۓpÜŠ¦SùÇF-¬“ÑÝ¥a7÷L[¯–0ÆûeM³£l$Ŷ3²è…´²½Y?*VXwóp´ ±=léBfNÿíX¶—ÅÙw§™±§9q©°·í#}|]´"¥g²¼Í °§`Á¢:½Úà§jSåÃÝ)iðtjB§´Jí…a€Èo 4°Ç8ñyx{y¶Sî‡kû7f?³DµMco=å«=WAû|åwòŠÆËÏÆ³÷Ffë¶š|Ú¿?¯c¿«Íäeâ,Q˜èôß]cÿ]ÁRΔ õæ ‹e.Œ’³•+ bw+IkÄÊ{`ivÝxq#ט¶šíåÛ®X]ï@-YwU 7MC‰Õ¤ÉE™äÀxwœYƒ\ó(%¬ÍþˆVî{xŽÝcÅ'3ñ†gGnÚ˜ïÂEˆm5r0©Oal\ž°²$–lp†åçªüÚS™Ìó°ÿ¨:Ça ˜~#!ËN 0Yd‡ ðýÀŸ‡æCqgÇð«§u§»î‘þŽ–íuB`þÑûï;Ÿ¡ª¹ûÝP&Š9Fë!V\˜ÀJVq5˜úçîAºÞ€V¾™ö³,š¿÷é´Í ÑÕ€»šjÍþhü›·$ë^Ĩ)ò hƒ35KtÏ”jÉ c4Ë u˜d®Ú2ã­r¢˜í4_â >2Ppâº{*Wy±ðöEå¨Ðÿ•…g¶7¿«ÖÍ\ðgÑ67‚®¿TV1(§þö†¶ÔTíÂFzv{ prù—a‘$9€õj;%=·ÚíÝ0é •ísïFŠ›N)>¬*òóXÄî&ÿ(& ]Æå É>€ÿÈAcFg8P]8ÕÎ_¸Â¤U£XçÏ«,$ì08ß­ ^/ø•U¨âûE/£6$|³YÝ/ýÈÈ\ÝàrI.kˆ¤4ÑN2¡“^;ñ°Q=5Á¬RƒÆè–ù^·|ŽDøÜo/1‘Ítœcû4œõçý>jâÁÅu&‰è°¾JSO¾ˆµë¹Š \÷¾1nuUÖŽó&$¶šÌÔ'+[%H~&þÀšs9VQ£çÖ¡¸‚¨ÌE9ø0Ûìóy‰‰‘ŒÌ0ÿ £Ék·ÚhNãpÅà77\“Zs³«Xžºlúj»8–ƒ!˜:‰yŠ£¨$}¸O4žXf¨ôÍŠá\GšºÙ/íE5 œƒZY•Äm<ƒÕɃí—·Ø›ÆÁÊ ÷Û‚loSdNu:û_¨›§Æ‹iÇE#us9éHA¹ÄÆNÚß6|ìp;l_7wΡØÓŽw ¢Iu8ÖÑ#â2î);­…Ńá/ù±Î!we ÞÏ„Ôíë”Ñ.?裣¶¦/,xÅ*¼JçÆïh æb Fží„SÑ0ùÂŘ|ßÈQk· ¬túÌ]haaŽêW(U+LaÜŠˆ„’~:ó±á•2³ã²÷n™Õ%N¹*1‡à§9d ´{ –¦ªYÐz¬eG0·ÐeÎk iAÝ…QUÏ\LÇ®Æû¾í¿-;TKÇø÷Njí‡Ásä{4Ü¢ÜX(SªfZþe¤¤/4ò뽆Ä_Dh"µûÐ}wái„bunì¡KÒ k&kßÛ8LïÒ¾–Œr°2OõÉ<òº:Áw QU+A3§nƒ@®­x¸šírÝ}g;®ƒÆ:Yh£Aèh À¥PDY†»¼¡;Äü„¨5*-6ìËPxX÷ÿ`³ÐÿêÔKw˜üÔÖúµP²XFnáW•ô¦RF¿íK÷ªð…ÞéC-såÏ“p¾lºwwÇ:Z:RRˆx_gNúÇ«¨¸%Š·Ÿ±‡áÿ*5ú‚+bÍ;¸šºCcD+ç~¼Özs·X‚zL¥¸Ï¿JнÊcmº:è< ä ‰ÁvÎsm1OØÝšMÇÔší¯',vkpÊ£WÓ‡Uç‹®VÓkÐÐCnÍóyÞœ0°Nd $¹"ø>j€O®%OµUnxFÿWZØ2E’ºL<Ÿ¸ÞMƒHÍ8¸ØI*äæJs*»þöÓ_šü œk6pSyÔzü©ùŠÏRœPHéöGpZÛx[C›PTœ;õàqC=èghÙŸF툈-…+“p)Áei(nÂå®p¼yÆG‹QÁ ªáJÝHÊÙc3–ÕÕÖèÔ;eñnª+™ám=Y1S eËÖüë4›ï"Œ=Xøcëv ‹AP 76¦kh&"ãõk¾m dD æ»êá ¹TÞcaÿ†ïxö QvÌG&âä\§]¸"4ûìÈ3>Ù•ðu=i {ô&…3< gú§üJ^4F_ïW¤+cJ8¬(žt÷h ´'½­¶ƒÆˆÞ¹Ÿ«" ¶WJ_u…¨W†V!½˜yo¨¾aH‰ÕF¡DæŒao2ëñÈ­åF>«\( w,ë÷1˜[12Ø~Ÿ¨àÓü˜0mk}ËáN¬¬tßçwkg C(!m²':šÿ|pÆf/ÒÝrGn/)J¿{L!›Ôõ'Û˜ß4~óºx#´tzdVdDýy³î§Þ¢Re¤Í9³X)3˜Áxb§™ÃDJJ$ó>rH?˜Áƒ¸EEfÃC<þMðfÂê¹UXiìܨgÚŠÿ O(0.èO`,t7ð°ê¶øB‡b̽MLR»äk3c“LM}rp7bc×1šð˺ü²$ÄÍËkÂæ[Wš(¯:O놽W†ºX²Ò"Ànw½“/V@]a\½=³ 5Íh®â†x,n~z:&b‰4r+…kAûãP¨š6Ûòf£(ì=\ÊØ:ޤÄá߀ØÜ¹¿Ï–‰€yÅ ÷)Åå(Ûêuc]Žw^haõé¯ÔMkëM“]R™*¥gîð§aÇ“ÎÊЈS­B»­ëãBSõôgV24-A÷^opèñƒ†Ï°° À¸Ƕ”ÓæäÔ N‘¾?¼ª*öÀA¾Ç‚æ' ò¿KÊWdù\HÍÄieR¶9ª*#ŸM¤T¨PÙs¸3V¥f}¥ŒL«æGûÂÙÏÏŸ9àÁpø‡Ý½—ú¢·¼¿ÎÒ×à™PÉå&–hæ…Fnl6†K?¿Ò¨yž¦ïÜ.×È©©^7-Ã_È‹n}ŸÐZ²&ê:Ÿ‰ûÈ÷+LXZÌ\ß¿\ýfùPTwOJA™ɸ šgü‘€wu$r´ïÁËò:ʨøi] ¥¥Å³ÝŠZrkb›ó›ÿxt%sPç ›éíœ5©ì­Ã”^Be†ð×}ÿ<ÒÑn(å®NQ¡ nÞ˜ûN˜6 ýyxœ»ŽoAÇ „2ɨ¹)N“„–‚ëæy[Ù5¡/Vâk¸IÝ€sÆ]S(z ~¶<Õ”ß¢× f5EP&v?ñ„/s«Jdÿ)êCÙc½rtg?åÒëÞ¹05å‚ÞB”+øöÅ™ò£VÏ®fy‘•æä¡ûDÉjô%‡ ”‘ÇhY¶î… ;9Ù¬{dÚº·mßâÄ^x¬‚÷ØÒ#Ño ýB®Ç™K|›QjÆø€¨ €°ô€ÀÖa€•ÎK/<è!7„ª-Bkuñ\gªvI ø’žÎè–k O…^ÍœŒ AªÎÑä0ƒUßNÛ•ý ù™k¾ÞOp-V ßoZ—‹²ÚŒwi}MXWá^Ò+÷ׯkÒgÞˆ LÞL‚jæï^©¿ÿMøAìÐòÙ¸¦´×õÆ$´?V*J¬HÚÕ" `$‚GÛ}0`w[£È v{_îòG*ÉA>É1fí <òjñ@Ï›µrÕ¿œœÄ9!‰å¶ëÔ¾¡j䥼Jôü“ˆs¢3ó<7cü\Šm;Ñ… Süš ¶´Ót` L äs#‹-ÔÝp¯„ þ(#5‚G§Ü1YÔ–ÆwMÝøéFôA`,‚ö+ø]ѽ~8]‚å¦üàC¶gc…Ìš|“×d஘w˜ƒ¼ç©·a‰HSà î´;~"Ól~:mhð^™˜ÚÄÒ)ƒ‚¼íä©ÒŠM×ÌwXn¶¿i°ÎO·ù'D³^[‹h^P†Qv{¢NN Êä|Ks#ºâDÁ¿W£5ÊVIªÀP¤vhµn-bÇ@ȇGWÝanåL-:ñý6D?W»Îšï®¨ttâÙ×qOÕôxY›2·I2µ;mçIs™÷ß}vmvr÷vÆÒï-[ŠÎ^ j2±ì¬?‚Iž—nt1ë…®‚h3y»Õ. ð|¹qâ=¨ö»"…ßh”¡8ëD’°ÝJã ý­òÉ8䎮¦ã^þð"8çäpÝŒBQ U+ÈŒõÐáÛ‡¡uxšʋ£¬Šl…ÿ8î‡6ÌD»ú2 ÐØÙV¢ 'b/2¥ë'„‹®`æ8É)õËÀ°Ó¹RÊ´™%j7-ìÌÙyuè™7Q°`O ^—oÜZ–/’*[p±WVúö!…8àÍd±ç%Ã=v¦x9ýn+xj9cVcû»´lùnÕD¼Ü{(k™ÁO…Ã4É ò¹ÈOÄR§“ ²ÍˆÜð&vnh=g6`Í+K¡nR¢åÊÁGÛÛ>ó¿2B{­"Ì•ÆõŽÕÚ;ü~!b»‚Œ.;rìë`Tœ£Ô­>´VRCsÞC³É-‡GiñtnÖc<ìEåiõfÚÃòK]&ž !n9¦ÎK±ÁA0N˜*-Áêíõ²}è>I†ŽIp¯ÿÕ]äõÐVµ.òÀû;sÐäLI™”Z ²i‰·\Cú"ªORÌš¾m/ÇÈPò¥Z0ÚçµR¥7ß©WžUÉíI·$ê7f¢‰B½â‚c‡[+8fB2^¯ë"ÂÚÔxMˆÎ[C0Ë·ˆ·*¢f…ô(Cßìkò.iF˾‹‹‘À¨º„„ËÚÙ/Ä(²ˆRãIóÐE‘­ðµ¹b(vYV‡Œãpas“ç)°[úø}æI.¨<ÒÀ ímç–2’†›_Ÿ0ULš0Vï.–XÝA$”h ê:q ³/¸r¤böÓ‰`jZÜ”ÂÔu¡2T:ñÁ‹œ%–cÔðå#^ä4&RdÎI*b•¯™K_oí„A^ÆB´žR3îõtÉáIJ• ºˆ¬ÿ¡,U_ò¤;2ÙTÍÛŠÅT:àØ>Í/Ññ¤r†Ñ9^Ïn8CM<”ä¡73xž÷ÄÅÙ•‘QÛdƒ¸WZ€<¤ëëQÜã_ö¦è@Èß-ƒ…ŤJHÄÔø äP‰;ÛRÂÔë‰8\«8Ï2zÕsòUz-aר}EäRŠð®ˆ§íµ¹dÏ8vûm{E‰à"½d¨-‹Ç ªq9dSf•H.$…Gõï GKÂÁ¸ v¤|DULÉaëzu›Ë%2?¶—¢¦·‰Ilò%;Iĸ›¡†)³1ü6ºN§ ,dV1ü­Èªžƒ ¢!‡ÞÖ„d¢ÃÍ÷£pø¶¼,—€ªìà3¨Å+|ó úEE3N\^Èã×Ãd3(,1\0þ#j³9jU‹Pç%7r•Þ(ñó.,[Üš)û×µ`J§a}øBÙ}¼î1<éÅ™!‡BÌËvº¡3­ßºªÿ.·¤OäEs .g2Tá®íßñ™æ;k°^:W¶iAâ@H³gH)ëûcOn}Ò&çuã‚{Š•ÿ½¬¿g(¸R"½Ð:ñ;›T]à7‹ßŸÝž;|Å"œîÂÞð‹–j«Wº2g€X¡Äº\Ò£/ÝR­†Ô:p¤„ô)…‘ºÎü#–õÕ~û=WbHð¡ñ…¿*: ‘*§îR+Âw%Só0o¨DÅ…dÜ[(Z‚+þɰHVQ€T9ÿUþ$ ^¥ì˺P¸;jù†X÷öH`$¹Ó*G¥!øƒï¡òào›|;û‹òë!Ø’—qd3ñ¾sLåºrYt|Œ´ænbNDË1NˆH3Ùñ×ÝÛ/å§ #–T/W/v7Ž,™8LA¾)*Õ2 Ëò¢ÃŸúŒ.m ùò\_@ÿbP"JbƒE`••²%ò¼Î°W. žTž·î2™?ã²ûé`pxP­Ñþã·x05{툙‰ÁÞ+Ÿ©E’òKÜ¢=$퓲Ê×P?¢Å[]0\ Ðr¦¡çË¿ïýÙݰj7 J«W§ëœ(1Úåï¼@®'ÀÔ]ªLü<á®lÛ8ÊþÄ@ó¸HÏ(c(Gæt·#ù?‰Š^+ÂG‚ö¦A&^îÒ…JaZ·T6µ¾ÂÙ›1‰¶ªPiºÔIƒ8ô®~Na/×Ë]·ày¿K$_¡³03”¥\cîÓ›^Ì—\ÞQ°Î¡*e_v Í>ú&±xÁºº]fîíÓ¾ú#Úƒ ÔCŸ3ÛóÑ_¸ûÛù( ißÁY§Àê²"æ©Ñù;¦„,&SÜô¬,BÌõ-2—ö‚ óµFfÍtÖºéÃÁ·}¥ñÉVTs˜*q,‹ì€o)7ì>¬Ó½Ù—¥\±c·}/ŠÕœÁÒcðØs/¢S_6?W(¥n§Æ#¾¢bbÅjÔ6wO†YÉ{E.ð3îñ·6 ¦*_¹˱¯qtnbúøÏÈeoE^F]Ðõì;µ3‚6†Ö9~®e‚¸n7UOÜ[ýŒÝZ¥ó\9o ‰úeíéueÇhÇUuoPdÊ峨È5a–r:x*Çm’ƒÚirë× \»ÛÎô¯‹§OÜ‘YáMœ…C+h›g8y xVìÁ¼¾<ª…c¡ÎÉjÀ´Ï!=i>ÁÚg÷_pÇÉoA¶³AOå,p£bË牆lû¥ œÂÿÒÚñVYz¢~õ7o2$0‚^nÁ…)YG+׋¼ iñÆ;FµüÀøÉŬ‘!ính1†ñô#?dý ý|ýÕ ë÷v}+Np¦w<±Þì…ŠÕã”Të;JÐ*.Å.ï;CàÅÂ-å­üÉQk'o°$Í‹ ó‚—?—?O\€H?ê:RÿAA°õö?ú§ý”|ï@ã %òî (ñÍ=Žïzá!Y‡í4zsÄRÅiˆp¹€xä |’÷<’ðt )›G˜"ÕÙ6&?lúËŠY7â Þv[£[q€}›k9Š'Œ¥Ð‘\^xèÞ´èFŽ wÙïFumƒ•Ghåw 0E=2 f^³6M°XWJçè‹ãVuÁô¯ÐÖÝ»éD8¼J’ l»¡ÆW¢vVùqd¨»Ó_ðEx#ÍFþ|x©ô ‰W|È¿D£õÈ ç¶4àíø8MÈ‘÷4ðåsŽ¢rÑm°é«–Ö2[—IÀÐD9΂aÎL܉<ôCÿK÷éŽ3 šcWàà‘÷ÉAa½~ñý}wCŽ˜Y5y€¿Éó£ÈA$þN™;°˜“”Ò­tÖ«WÈ‘m‰×§Q) %öo<ú€¥èïwû®xý¤Õë ª1Êg‹Fo‡#Ki-0øŠá€©üOcþ›)üZmîj·ªDéi›”qlOl»&¾:KÙ‘`ùòXî>Þ•¸æë©ÉÞµ„óÍò+»Ú”…Ð&Åè}™Àò, ²Lc§6*!I'©‘vuäSµ¹@Ÿuu0ÖÆû¤²–X­<ªûÂJžÑz› jÑ%ýt‹ð¯·Ð¦op½æ ¾Eƒá¸l8VüÓ¦óù’ÍÄE¸+ðGAÓsÊß4guݱ<{²ÉÛÜ_8yd%ÇOã.[DÏ«»ÍYZœôxx~›å…•eWÕœ@>èD”gçNf4Å‚¹q½ÍQÍ'Ó)IvD±ÄGÖNZ„tNúD2?ýˆ†“Ê»ª²|ùŽ–ì;ˆ5ï®#ë É——=·³‹›'­±‰»Zú÷Þ€Æ À©C5¨íeº.¥`é[D÷ÊåŸÅWd¨ÖÈkÁÒ|>,›PËK«W  ¢¡’ ÊH_áñÛíØ6€vy„d=ŽƒæšuÌç Ñ®Züa6ó¤âjƒ6L øH Rï~³ÁȽ|¢ÈÂ@ÐÀT|"Êk{ò!r¥ËÖÌ{ÁMu)íãÀã«ü¯È{yÔ®4üß*¾]ãbÈõõÊ÷ex’]áRž¯aY{X·ýâà‡KnêU›vî[Vu/¥/Dc¢ë,2!»«‡ú[½ÒÚUÎ9VÍ‹æÃ0›"ÅÙÉ3¦¥ÂÊë2Ù°eÀÚ,¼Ôo»»ß@š{'žtÞIGˆdõž+õå@Í}ºTU¡Ê÷¿cc}>‚Žûõ™ËH~›Z›Ù_ç8 ›…ªšØ;ƒEÕ’uƒ; `NÔè4ý%“±õ©;7Yä鯴Ò2‹½Ÿ~5é3h´ÅR¨Ïf.ѤñæN»žç —™ &ho !3š‰ ¦$ ‹E-ÿX‹ %ÙöûË«`æ¸3u'˜þ—(Ó#ÌEǹubßPÿ’¤Hf”b‡Õ¼õÌj°2Erü›>}Çm`uëÑY³{ÆT¥~'ÎâÓ%Õ(vëfW(Õ—TµøP -AÝ^=P0D°Ák<™ì)ì³_Ôô&ËZU¤hü"bFÿ±bcs/ŽxÐ2½Úᶦóï5ý¾<Å™z2õPU Oj1õ ÞûX ,ý„PCÖbQöÌžp3 ´‘ËY®.Aw¨þ³B%çãW«ð›ž‡TÈpJù@…!¸Ú„J²bXü¦ªq@ÔdDÒ"Q—ïck¤¶ÒöëýÆþ'š+–oÆŠv[ë5á™”Îÿ‰y Æ2å(ô3äÉVKuÞ<‰ážæ‘3õfW-…îŒhù³¨“S¹Œhâmm™Aû¨Öí÷ã‹ ÃaúH¦Š†›ƒi[8»'ˆêŠÚà}Õ·¤« =Â\$a<´R`‡!P0,¯- …0ˆ N¦Þ1Y2ÿž½(>¡ê'ZhRÞò) ›kªwžH3ä‘.R´|…à\šô%×ÑËïdÿîqõÅP˜týáA¡âÆg`Ö3™~TÊžª.-†¹µ!µ s\j»ÛÙêòò…Ót\jæ4"³˜µO\…S5\gRIcéÇC¢»Òz~ÊKô´Xš°¸Z‹(ŸѯÃ%‹¤è‚m!§Î7·¬Ç«ŽÔÁ’In¯°¬îÁu3Ÿ)go²xr ­ôH±=:]CX5°ëö!j±|¾ ”÷q.m>5¬=š¤è°DbŽ7_¹ÁÃM‚pŠ1‹¾BÙ€y®géb€‹–Cm¬¯Šz%ŰҾî£Á,”}ûõgæ MÃì¸Íê%#¡Áˆº ‚—Qw4ÕGgSögý"¢î¡ù(0UKj”üñÛƒ!#‡ ÝÔ]yLCe²ë×ù‰sP÷cü4©"2bdÛ4ð8Qx*¬°4Oè þ‹™fE«iÿ1w.°l›“ƒ̆¡nXö™4.|óüX“ìâó>«ÑV«4!8¢štxkB¿ÛÇÒ÷ÏhvÚ4a3no?pþƒ¹yPæVÝyT†çÂÕëî‰þ{{&ã²ø<¢´î§‰?ÉHzìiú½ELy^ ¨p"˜ÓñÖ•¢¸Z=p/|áÞZoðÎ|r}W  n(™b3M«6I6`£%x~o…ÑMEtɪh¤s~+»€{Ø™9fhzdŽÅ§¼œÀM{RCÚIÿ£”)˜†riæ‹(H¿=ň"\'a¹û®ó’8ù«7~yÉ’zw·ñêEvÊ %ÇMe%Z2„£AÒ%M½…`4¸kò‰c˜ÀŸb] ÑÝ͸ rÍÃE›+†¨9úÝdì|Ú*çqô I=³ú[>{÷š–ÒÇ%Ú~«®Çéqõ 2!¡[Ñ}`/^§rLwn%ì^{Šþ—ÞH-Zö.ñÌ“«`6H —3 É{{’ÓRÀI³a²\ºl‚ÄwdF‡U@ù 6ó6éQZŒ7lKÑOmª·³ÊÔ Õâ>à8}²‹^…%2ôw¢Ÿ]âA%K;’÷DK“³%߃ƒ)Qk_‘_…Öi¹ÒE•™à«j3Ý›g€âH"_D¶HÖžGdï/¨uÖ>~õ«&c°+ž®'ûžÚuÞ‘}Ìir¡TfLÖçtY.ZÎè\2õ.69‚ëå•§ EÿÐ%l1èzY¿p‡Ž¾}ÐÞF–邃C³+yÒ7JŠš)ÑŽñÞ3R(þ¸5ŒE·» ‹¥ ’Ûl M/ÄÛ¡²ñ“\\VÉçú=Ú' Yñ<¯Æ9‚+ÅÊ!¾é…<‘cœc¨(³–y쬟ÏÎÙž3O„½Û¤åqCý:q5Î蕜Tš² õA¾z[_a2ùkÓ¶êÇÿp¥Œ,aQÖ~}zí)ˆÇü<û­'E‘Ñ̸Á—á™nq>¶‹“凂ÊÔó<Æ_0 è÷o°¿LcV7ù¸zëù‹]cÃ;~ÜxíÂKŸ©ÁçÞÂ{üÝjþª"ˆ9…µßó²L¨N#ÚêÝÈ€_1»Ñ¹Ø{½,íŸÛБx½ì¤’§ê&ÇÙÅj±·Ênðgz …my ›íiu*çd5T;çö>>råayÉDóªøžðénßlƒX„¼¹:gXEKíN¿­±D‰¶<ïõ˜YeYä¹z´/Ø»ö¥@ùu´s5À>0õuu¼JX×aÈiW5W¢©w‘ÖÌE‚¿Xü¡M\÷¿FDÖÇé¡Éšé!ºÆ‚Ú¤T ¬—ŠWú7ÿ°7þ•U¾{䄺k¿pæ+ÕplÙ=…óß Ëk †7LN=‘ð̲³ár–é ¾;ág¦°WNI uÆê¹ÙŽïöYÙî;úìTTþ´Ó¤,|!Š“l9p3vY‚P Ž<“Õ³itˆÁ;®ûì–T%Ó-BS'ßS7MðP¨j˜ux ïÊ:ªù3Hv ­É r–¢³­6=·©ÔÆáà¡Iï6EÓÎhûÕÚPmÿÙ)šÈ÷аzã:xC^òÐ’£hó+É)>`t¬ "ÍÇÄåäZ«:šäxšFvè;™¨Æëʦ\K'Öe‚À02åÊöÿçn_Ö‘sy™Ín{³ËÏwòvléø†ÇžŽ2ŠÖã¼%)ÜCɶ¬G1ÝÏeÙ½ ¿OŸ›•X?6bX Í8ÂW\¥)ªFùiÛ ‡Þáö<>t‚ÚN¢7Ô¹|É›&©iüÛ—¥Ø°ë¾Ñ\¼Éeá[,ÊK:ަCD™ȭ÷©~ 3á.JÂÿ'–oú€I@ÆIÎþwkG$nÊIa’CºP¼l»µàöd•pMÎ÷.'*Õ¼˜J¯•‡®naY³Ê™H)ó=˩骒›5j£UÅ\ð"ú{Áü™íçó«(–KxédZ¿ÑC´oØ®2wÒ‘_Ý\å?4DÏÇÞ€JþpþÇaøâ%¹RjŽäþìT‹_Ó ¥«@1hOé·–š®"èQÄ›C&1> ¸>YþØ8u„á€=½3=šnLmˆª û‘lÕûžýÄîTŠOùk³}Xkã² ’qMþVezªåЛtÁ³Ùû tJgWX „< ¯Yo8²®§ï\S>è|ÚâƒiR´N½c}Ù×hÑy>p?D®:»Þ?œ®:ñßÞ*A¢/u_¾|ÚÇÄ“~pEšz'Ž“—"~"c@#‡Á]®½w‡J‰SE\²Ìž[’Eåå\‘’ œŠ XÒ*âÃo 2Aü8Šñý†Ã nþ¶•…R°ÖÕùû¿Ô«TE|‰z 4ÌçÖwĪ)]d'Aÿ T1áêCÅÈ"¼ü„X9ï+8Ųžó¦rúÈ@}°1èƒF)±œ‰ñc¯ Ouп-Æéw— éø C-ƒünÞ›‘ˆßÔxµÅj'¦-e@AœRÉ2tåö¼;d d …ÛÚ”%Bñ+“iÊ?XüÅ1+*1q´&²¶3”%áAl &U½Tzî;k%™ ÏÕ›‚êU'[õ*Äf‰ÍÃFŒO¿¾™G–_N—J[HÞQ×=í¶?ÊßÁèµÝ8Žgnªsáó†üDS¶[B›Ë;â¡íûååmÊy°é‰îë#éÛi¹;ÈB|ÚOì±ý* ó~’> ï¢Xoçc¾‹ËÓß½½©…Ø9ÜÇÅ‹Ð9r8¥ŒÕ% @º®Ýá/¿;Ê#¼StëצžHJäR†‚ÛNyËÒ*2jz率§ùa^Næ•l}äZj °Ð3”†™)sŠ 3|R;¾ö@-FË\­ÅB@µ|^®•}xã‡íDHñ¢Ò[ù2ÒMñ!ÒKGi#iSwòtcž¢µV3ÑÄÆäP0äö³”Øõfì‚U„±1<Ñá?Øྱ‰Ê°Ÿ³€^ŤËìþë,ÂkSºFû1Æ^[›øå&zá]o‡jØ:¶JEìÝÕ]sò¥N—MăØÃ.ùÐ ÁÉŸ-–`'†}mB“ %Ü=g †YGóÂøÍá¸jLñ#Ž? ¿é¼ °°¼,(ñ¥=³ÔUC—Ï pÉЩ¨†]l@O.àÀëñ*y•zölPež\w39Ãmµ¾lö³zRy¦úޟ݃)-ɶaIâPÀt.ñd×>ŒåŸœ¿=‚AH˜Íú‰¶ÃW¡Ÿ_à´Å{¦] Oì‰ (Ë^' 0|·ô$±èjVÝëf–Ò‘Ý©Gp÷˜£…AYàfMtbÿg æ;DÇÈø ýtÝùOh 3%8yí9Xýu¢I¹ ÿ&ê/¢â%ŽÐJ*ƒmHûoÂÐï¸4ˆÚµE-ut¼…ŠŸý0è8CðŽBX^0G!ðuéGêŸh€+œr<|<ŒË@YÅä‚·Ê©:‚†Â¢ÞPwU…ÑÁ֟䟸}Ì"81$p牚ÌAP>â f™W «nÂù³êÅÓ 6M·~`æìðr¥~Û0 爖ñ“²Vþ@vA„QFgBÛ4„‚ônÊì>ZðÖ“å¹&dT΄GÁ1à‘ [ð£¨øŠvÆM8jøs²eÞ g)Äœ$2âM}ŒÂŠcˆÔ¤¯Ê?øÕmÔh]~l,ƒ;ýW@îIPJ‰‘4²\µÿÎ.p‹™~ñÄö–f/úc–³¥‡Z|ï05ø“º!Ip ÕÅ%°;mÀ[¨™±Ñ Ý×NRN¨ã±YŒb4xú?P}ÿ¨<¦¦MÁ€†î6f*Ì:t­w7Rc—ê,Y׋šöž軄†vξxaq_çqW¹¡l°møå~κöÒà a©ö¥û†Wþ$¡Òš–âL$j°YhkÛc[i#+¶7ž«ÒÉ*ÂX3NpüäžÕdÊA]_í²|7ÄÃóù¤Ä¡Ñד6e¼Í¼–¸:OkTç[÷µ.Ñûìƒ8®«¼ö“Sþ±Á”¼-6ý6cDòŸùVΣ mÚ™U­'"¤¡€%&²ë¦aˆùﺯ9¥ÞŽ×"y4zô^÷Ëx†œ¥ºÿ RÄ„ý‘ñ^†cEºOŽ?ˆ³_^VzF­ç_±;¬«ÛY¡øV;Úš™íÁ,°£çM@tm!V#Žû†ü&Ä™rûëJ9h€nOÛ¢|µ@áœ8nx¾ç?S7»'K™mÕèD§L„lòÂlÀÌ]š–ïõIu† Ñ|0~úHUªKüý˜÷jüt%mg¬G¤E>|kÇûúZÏøÜjÈ—ìÇ’ó0¼È8žBÚgÑ—Y¨y?a#‘ì–E<– ƒ’ë1l'ZÕ ÌqŸÝTáDÃ+„ÀAцֱ$pÀKü2ÍÀæ·'³?“Î- ·\²ÞÏ>Ÿµ`Ä&hÊ­¯ÐE8¿³[CÍãWêHŒš¥á9q*óÏt… [›‹6nh]y«ødÀ Ø1Ä\ºiÑ3Ù» µüyÕ˜ž%9«ZRs&Ôeïñk‘Ʀœœ–küÊ?!ÿ Bi¿ªÌµA´à,x>¥”R߯zçÑÿƒ<Îäÿ~s‹ˆ—C»0$uÏ9ªéùÄÇ Ø…à é'öª:î\ðéßÁ÷‚Yš«iÜh¶H‡­a°cpÜ;í=¾‡ÜÛœ©ò¯rz~˜ûŽ’~I;4Í¢wÆË§»àƒg˜"qE@‡>¶mr@ðÏ–ãf.U{d®µA­]íðd@ÓÐ{:s+ÿ§Öh4‰ä¾&y¬¶RI~!Û[g½§D8úXv$ FdnX)N$©€ ¤Tö¯ý‚†ï®ë!ÙF¯ãhçë–Æ½ÔMDKPñ®ÞøÕ§±Î|–‰$·ï¯¡.&Ö-Só½Ç^ÿ8  ÔÆŸ”õˆX$Ø·Ä&õ5ëx­»½‹É‰}ãÆ­ ÿÿªy€ß‡—ƒÍn< 4Y·¼Ù\Ö̈ëôòE£\úþ}¦Ùî…Ia°~Å0y×ér»²Ú5+i(½ÎÇ;ÓÝ\ˆ˜O®œóZ=Àvy‘Þ›e§ˆvam+(wž&\“|/Ûsy™ ž|xÅiÿ»rÖ‚™m¢i µâ>ªFs*˜!Ú´BJO@Ü•Bÿ:F+ìN2=ßœÑ.m}¬óÄçS~{~áð5žšþ<›d¶‹ÞÝ˜Ž¯$^õ÷ö­LÓxÔ¬È\ûÙ  EÏiÚw´}f#å-#~2È4q¼Ì1%àž‹¡ï5!Z×—u‘¨2 ¸„mõÍÇ×ÞÊõ¬<¶Q7±õÔÎ*ቓ̷ã⛇ù8Â)(Û»®?eî\$ÿ+aÖ'öz³pYµY(øPœkç§ÿ’+ñéE`N±ònœIz™ôý½À̵B+OýþÊ(j|M òŶú$-âZ¤´ Rþœfƒ#%Z.ö b(]‚c†S u|UµSÙUºs¬…íg{íˆH Ëb™p™z(”[[ëÍ“ìXwÛX€užgð¹6ì{tŠ³× ôD÷‰[{o¿sC›,témó>¦DW0³,m< šórú !gôŒ‹€¼Á$`ãâCo'GøC ×zú °:è6³^ð)¯7ú† ÷„Í0ä? qS‚‡¨1_ú(&3Ça¦=?EnH)G5ëû½#š!v±he¨ç°ãö©çV5Ìyê›  3taÛž¶ï(^MR òOËÝ™¾X'Ãý6mñ&­ýûZÆNt>W:5Ú:Œª¶• ž¼M]°BcýàNIˆ5À­ÀÁNøwݸ©5}tŠÕ? ÌP°àË-U•Þj$„igrû]ñܵ±´|-øå­<‡þvP]¢´Èø\úÍíÓ@é¨Ê…©XJ‰Ë>™#sßôwÎ>‡3ÎöÁœïzö¨õ™+d>Ùp­a—@#Ÿ·îž Ì7ÅÇÉ™0›ÙÏÍ«ª(ðDÛlŠØïÚ›EØP²³^Þm¼¾›„¬qªo¢¦†Mˆ+© šŒÌ*GÈR/ˆÍ¦2ÞÇUHã5ÕvÌÿÓŠÛÚ^ØT¡4áË€Ÿ± h7¡¯æËôâgW”ý,ý1Áœødøn×{𑸝Ì;cPÙÒ#Ï£j ~›»ÑC.Ò˜˜DGžî¿ïÿÈÔ¦ò‡b“Ü´ÕߥW? ”v4¿Ÿ0 µ=k%y5”¾Ì)ìdþ›€›Ö¬:—ÎçkÚBƒ·oEG¨eB^‘Ì+Þ,²G‚æ¾W­X;„_§ZÌ˰"%¡/ †õ`éäµê•ÕõàÈÏ ©Ož„Eô¯E²~ògùE½æŽÿ>c(¦êЄÓ7§ràìbì§³vb”B=mÒª–en'ÉÀ7UÖ“~I-IºóbG5<ô=h¥ × œÙb/²>Îůª5ѲêOt– jÀ¬öÓ±\-ú1} ü:ý.6ÐÙ”C‹Ô[êKùf‰ýk°så˜ú†f›œ‹Ê•TÀªÙt¡ògR­—* ;jo2C#§Ý~Yé.¸øÉygF1<ˆý]ºR†J4(Óö$gNdHF€—fN~°«€¹Ä õ…škÆôr[“sóî8CÂë2žbÓÑ¿ÛTáôî„Â6qÉm¶ˆÁ/ æ Í8PÀ£³šáß’p×>Á^6·É}˜yþÊÑJPÙ¸ P‚¨FC!Øm–_GD8›Ý8^+ Ü16HúZ£hY[ö•\;×àvsYb¦F<±Ó»Ë :Vâ]‚›àþ>2¿2:KrþV5&‰|¢ƒfyž×¢þVÒ×̃-œ8GsX&•öM<òg¹:$Á3ø9¬[páŸlF ¾nPUýgÃgì{#q>*“KU1}Á½U“²ZÔJW ½©}· ¤‰ríÈN6RKý¤Ûý`;Ê—©‰ 2Œvò+ùM¬žý}òõŽÜHÙlý%xm ¡—_Ê féh±%?­1§·?¬œ.@±&¢— ¸©°’p¬mÌ‘Í6A ò ]™)ß5?;òºz_²†äÈ^ “=}h ‹Òn!¨°§£òœ6´gœæ:ôJurJlßÉu%׸QsÞÚé òAçŽN’¾1¯g’ËÄæ{~Õ³—=ö‚­ßü‚§‰jÀòÕS_GÑ~‚©ŸÄ0ÅIƒ¿HÉO†Ë–XÏUèµ#vã‘~d}-Q`Ê!0 ‡)m1;SÎýÐ ëÊÚ¯¦ÚÄõMXÆ»<s>%<@ŸxþDu[Ñódµ³‰w«-?c§ãKwTÛUTAÑ’6^ N ×É“$|çÄ–ðy­«y¹c¶,Dá½ëOÕ]nþ¾¥eúcMýþuT¿û§f®Aú=¤‹ÛÙ[®a#›§ .T!wn;Õ ›³<[¸G !\§¼¢*øNñ¿êß’×áú+žƒ–\®—OðFÓ¨Rõ%ø.¥U:ì¹0XqÓãÐ` ¬—_ÚÄŽ×ZcÌ”õ{G 3…z”)”ºÂ.¼|A€Ög‡ýtj Ej QÅVQ`ã\YÚßRà˜¿#ÏÆi $½7Œ-… §Z¨ô »ÄìЮšëô¿ášzÌSÈ{q+GÕäWùðA+ ¯H1‹Jsæ<‹²)1|+Qÿû4‰X¢¿i+ŠÃ ô»Âs6›’˜ ‘ÈÚ«4}+Òøº†µéÆ€û; Р‘b°´EÅøð ÿV0¼þãê˜Õ#îŸdä'¹ë‰îäi0ÜØ4·ˆ©Ž Ê[}d;yT_Ÿ»/U‘ò‚!{ž¢uñ…²ËÀRíÞó!ž;ÐüNQ˜×¤I®bѺã¡ë>sg¸>÷3ÝSIÿJYõMêÚ¦ò:ÆBo–ìSî¥Dìú ¥ÙŠp\ŒËùÚÈ÷(IÚô,k»ã˜o/–ꆸ\Èܮ߼ã÷Õà›d¼}Œö>}ÚÈjÑ´©ÉÈÁÔ–v"…a|=a!žÐþäÛ9ûΛµ÷4Á¢+¾Ž~tLZF‹ß}A}ÖBr㌫Þ-T 5^†[’#†[6°˜«RVXI,œ^BEHV5ðô= Š¢Y¹Ï¥5 ˜¬ã¬‘!É}ü`çÏS3Së…ãÓâhá.AÓ¹éph}æî™düí™`/þ®_GÐ({š¯ Úa%ùz¼oi=¢3ñÒú²[ö„¡‘ŒœÚÕ:+gt´]QšQÜüýèOZ$JÆ%𦨠?<à2/‚D@ ËgeÝÊU’îA5­Ü%ƒœNm”D0@ª pú{®ÅS³]b,N Š9ïë„RI{Ïo;} ,å¼y)Ú’c0ÈÖÞ@Å’Éú Æ‚3.:'±°ÿ¬ª3‹“bk—ANpƒ+C…ÌtQ{4Šž(»/žøê«¢´+x§ìÒå§t$šùÓ÷ž’õ]^Œì:Gby±nTáòp`„_}8e¦B;O0ùQRœá¯`²³Us8•ð_ÿ]ù]~Õ‚rÕPƒÙ渼éLñ‚ ÓÏg2 ¿ë1kídÞòÃf xLjc-K!ÿ¿Æ `˜^ÅÞ¡¿)ýˆx™?H9fö£¢e™[KuÝêø¤P_ÈÑ5ÚÚo’FÒØíÀ×µ:bft£Œ%ñÞ¨²ç}ˆ{4ÿl·¿ãí2Gv'vñ”z¨c ÞŒ¯ùý÷}‰:LKŒ Ñ"ÐF>/INô”Ê­e/ÙfÎW‘r:K"Ê4mÞy&>º ê¾ä盟æeݳ3'oü19Š;*&Ń0ž¢+d9…­9(êQVU”e úd~Åo3³›Å$ø÷¡RowÇü¶‚—)ñšç,rÂgÄüøî—›OmA-qE«äÒ¾R#›9'Ðë(Û‘¶-ƒ½%寢õ3¤å§_³.‘³»¥³B ~*ïÆsÝS„Öâß5¸ðX’–ËÙ¹bø ¨-ºÚëâôuqç¼Ä¼X$1® ÒôÎãQßlMY‘­sÜïÙ»ýd9ü"?„ÌYÑýrWYÇŒg¾Wž¾¨~ñýpT¹nâiÌì³aà}G½!¤o“'Ǫ CP1Ÿå†]Þ ~ç‰Ûš•Œ­Žáˤ€”êÓ”'ì©s{§Íw4çOÃ3k¬bcutK‹ä­¿}9€[ECÀ…þ›Ür埭cÊÉPS“R¢½6ãwXýà' ߎ 3rDÒ?ÐÃP".Jx€nô¿—à‘ª›ˆ…žlÔ|ÇY~¨Å•&‘U> ©†wGþ® ¾;8Cê&:8AÍ#9wÙØÄBS%NO—¿4]u}cü•C"hÀA&¦'ºèH=-óQbî`ÿÖ6AÿWÅAé:ZÇᬻו¼ mBÖчŽMÃøcÙO'×–ÜÅ8­¸Tš†*‘æ>;ï ·ìjù±‚Ø»nM†"î¯ìÔY‹ ¨·-vC0§û# |‘^”~üFE@ÇãíƒP©}ÉV«YâuxMÄ•áÃv2ì;IкÚCT£Š-4H?ëŽéOAöx°7õŸê°ÌáéR¨ dõ³º{’ŽtðPV=<2ÁèôÁM£¼dbÅ|¶­Iù: „®ÈPÕ¸UMÚ\òܼqÞÿ¢÷”ò§OuqGs”G˜O%owÏTä´Sp=§²ûÒd ™êþ±_û¼Wô×o¼ÚëRòxq[+!\^ÑŽˆí¶W…¬TB~j~¤ÒlÆÑ‚XÈàØ»°Ó“€XOÏk1©a† ÖÃ#cEå‰PÓn"áÐlòjEØ™ëÑ÷…U.EÃsŠp責…b¶¼ùQœ›XC&·ì}?‚`FGé—Ö< È[Òç‹lÞŸ ¥+[5¬²À〃á.F[² µÙh€9Ú+ãIv:“@rô/µ }áOŒ}·e–Ö#æmm71­ˆØqÓE‹µË,o3S=Ú¸Êøúœ9¨œŸtþu/ÄN›Ü >¥À{`KCKxâî!Ço‡;Ü/gðà¡—BHYŒÜ¦S;¤¿ßibÔÓ1÷Ãb:Æ Ôëü“QNíê Ö2WÊz_726=&¡Á¢É‰¶Jó3:¸n›­Ø'Q£™ºè¾Mb¬ÞQOäS†p”´f‹ßHƒ\ÀFé”Rü©1º7NñGéÊŠ²Þ%ä<ü•³²Û'ª»÷[BüLÐ_}­0i„Õ”â.é¶Ø€ü2Vzô„ý‡×wùDêRü‚Aœè¹#²f½x`Kˆ‚‰™¸Z #ÆÕœìg-:ßiÏ)Öæ›zÊVe¹®Ð^Óƒ÷ { óvã‰Á}¸~?­ u÷¥çpaHÇÆ¨în–È%|3mŠÃ‹!±&¡CÕÒ°­!.y¾ùަÀø´›V!O)²›ƒjßÝõîŠ0) øÀÞÓæ°1ŒšÂJÔ—Š,}ô—UNŸ=*¬z£<Õæµ6éåÖ-18(Å3zø…þ{uótÆóŸ'\ˆ…üA CPÕ!Øç¿˜;ð ‰NË_±æþ9£ŽõNzœO”ˆsîõ¼Î̳«³¾ëZšÌ,6ãý2Ú‘/°1Þ(ñ}i‰¢|J9'›^ Èm'*‚õɯ)<íHê»ÿziqéï¬l<4l£ï9‹*V–&ÖN‰9Êö›­ŸImÓ9H”)åu쪃!'8Ã& …S¬’’ Dµ($1:ã ŸÀ cM0&F|ÇÀëë³Xß'IÞ%J`™øå,f6&€J<¢ÍÆî˜N |Öé¸êÝ“zÖ˜ÿ4³1å.9å $ wå¥B ‘ø ùئ{¦þ{BšíûEFP “|¹tîçýMÑG6p…•ë87']o™ä}ù@¬TÝö*¾<¡(Cr¯‰a$ߤ…µ¢ñ;’4âäЃ&ï<†UÁ Æb™Oà)fÇ@¤|o&}A"1Ðü¢¬õ47¢aÇý.ò1;YX!‘c¸µfZ=MûpþV‚É2{"«ƒùÀ\æ/:¾Ë¯\’ƒÌL‘ðÊiot˜ÂîJL¹˜q79ñMÐÅ»öPf¤· åy 䢿ފºc.ˆƒ6±IW•ÁU d ú§vàòMݳdÖäp|XÏsÌc×›Bí¼(¹¾—0.¹5µù^’Ý8‡öÇrØð-=Ü ,VâBŒ‡X­Œpei3$¦¶GÚøÇÙ"q,Ì/™INº„iúKYvéJVÖ´cyh…)ÆÍäêŽ6\X¾µv^|úŽMQÍeQSqГمeô|KÌkONÙY†alT÷²X^ò¶e§åŠÖ¢tp\’"¤½]Ð@”×@è[ÅÅÙ\kEq’qQZçÜ_õZ”*Õ •€0–#;Âà1À†î4jB×0Ùüé7$ny‰Gø÷º7é’é÷E‚¨ÔéN_“rWW=*×””C%K d²EµXùÄ9çç û+çoöª›Ì ¾’Öñ®Ì·sÏD‚9ƒÑ^ä 0•AžB†d¢ ó㛲٬Ûz "*ÚL¼T…Sçàõd.‰ïæ?Ï4ŸŽœùiF_ß;wºœq¥ f6çÓcרž6ƒFy4L¨Agw4©iTH]éÊbߨ«ƒ„àü@9zmÕ2©^p^Â¥–&³Õs5nGª¨©¾%‡g× ’ò]y/9BéNgòocÿylx¥½T=;Éb¹·K™I!^2¸ñ÷¹ÆÿhÊYÞ ÿ¼kAnº”Ê5ȦnÓñ(;±VJšÉ¨Ýùñ¢.gü‰ª}û1Îv­Ý7ÀÐ*[ŒrÅ|E*VÜÙq‹IEo(»ÿ#e¢Víbƒ«á3Gàë©\y]Ï I5Û=´–îðÁ+ÆÄ,Î6逎 ùF»|`„ ÿ}ƒL0j€I¸ÂŘTt€¶ÔläÈ9¼V=7\à‰Ã¼„1-#š0©ªcѬœu§¤S„ŽpxÿþçÂf^²fGþ’íP !$ßøú™`œZ…÷Þã;‹ œo˜Pôô_&Vƒ×OibjyŠâý"ùAØU©ÈˆA Gå» %ó8 çßÄ \õÛS§!%ú,]ùJ+¾ƒl)9jð“-×..ݯDîÛëu-¹¯wbœ&†¹ +PÈ£2 ‰†ßN]ÒpJáœD_ X¼_®Ž®›ݰ²t§¡¥uPdý‘©û‡ÍÐ.€Q,ü¿ "3cÒõ™ÆÊ„TwWŽD W3K/OOùøzð† ÆOƒFƒö®–1ï={ªìpóœŠbôþãAsþ¤zóöü@KR´ï™ë<0ñod=%äÈ–ú?˜wç6|Ö¯òq}·š¬@ ë)× \¨ I¡ðquê"ût%y–Ž¿whß] $+ B`²€Ý–Ýãß@’Œ¼øL{ZŠ=ÇïeZÁGäøG3äàÚê•«_±Ü~~0›Ü:”Òg0ãTÏéÈíÁü‘t:Èa…lÎe«ê­óã`çÍïh±X¢KDW:ô¯Y»ÏP:PüBè5 Šfƒâa¹w•>Ñm1Î&¬ØmOðseñ´ÅÑ»„•PPvÖB¹Æ·ÓhÈëÍ,SKÖ~ô~äR(½qiLÐ^ߢÌm¡‰ô‡ä,¨%õrhÂýš­’ï>ècBE<ÉÇF—ñ ­•/IÎä]„·Ú 4saHí0`±QWõÌVyPÝ>v‚hmjòZlÂD{†Þ¨Ý2«_¤íBq¾»Ö]Šu‡„ß‹îà$¢‡å¥q?Ä$p+A·îüñŒ+o‘€á¹Çm‹‰Á`³âÙàžÃáƒ5t†Í™’ÜpY¡§æéï 8–ZÏ&™ýo=ÊFGµ¢+ú‹¨ž#Ú„¹æÍèÍO[’ú»˜Û ¬K¨MÞ û£o¥o°*~ñÃ$¿c̈}dLrV…p÷¹ÉCyÌý»³ÞÛN…ŽðÌI8"ZëŒ|uéI~ÿ±qîS‚ ùæ˜["çEâ¤VøkKšQJ—@wîk=ëúÅuü–ôö¼Ô¥×–Eðî†rþ×—J±6CŒ'C¥LT*®šÞqôËu ɹæ³ZÄ£DO’çéÎ’‡ÝZµ0Ñ}âÚûäDµႇt©šk{ª˜ø¼Ž©<í¹0tÍhçº p›–»Úwæ˜Mu‡wçQÁZ«ÍŠNïÊÕ€Ì`ÊFç¦÷Þ¡ZhU«iwgŸûo7Xi”#°‚—‰‚'…ŸFžžyçíŒ$s¯m lxZ¿V¯ ®Ä3: ÃʼZ¿åœnÓbóHš[ýYøw†£³¦Ñ–u!z ”ü–'ŒÌ6 24ÛÒcªTAíuðú½©*‘b³QÖökìŒ_@-c§D¶ð~EãúGS%“ˆÁ«æf(YLÀs¹7==þÞ.L£LUÌlkƒºÛ°‡Î–ýZùû¡rùWð„@±áºõÔkÆ6–€•4H!$Þš‰$gÉ<’>M„6A/xè´°‡Ð_ÍͼùO½M1¶:Dó,e·y@]]Ü›gÌìûÎóßùþ•郕«¼lçïô‹Ë¯ÞsqÖì¥8´'¥¨s’Vò³o­tÍd· þÁ5—š8ˆø‡ ¨¹€£†hã´ÀÃôœz{@ :1øë&áòÑÿ”#ö%ú¥¤]í«YÁ Ô|¼< ä?²$ÏÊÞë?‹­ö–Uj|Ú® ,!º'õ¢×ú¯úÛ¦G$©Ð{uv.[5¦©|cmâˆqMì%X'ž‹#“©‘‘‘Xôô²¹Ê騖:Ÿ¥z%ºzöÂ@v+ÐR°þ}~¾Gë–£‘c&6Üz¸¦ETÍ¡¬ü:©Z ë¼ì&V.Œ YÊ`x“½Œ{í‚¢dêÄFÚÉòHíˆnÌ|»š ³6+ùÒ»– 0Ágª,ÎÇÈ€0vÆ1÷—=hƒåŒ¸…œ©±íê®Ô5D›2VVÝ&Ë *Áùrø1CMÊÙ¢?<F–Êó1Çqû±©‘«¼üÿ,½ƒ]CûqÀ.ùŠÐ²¨H‘¾7ýQìdjé©8ÿ%åßq’fÏ|‹ù¸ Ø}ºDÉ“ÿ~Õ»¨íÉ€G—¬¢î/@ÓÙ㎽eMD d_» G„v„LWeØuãÊéÒzaŸŸÃ•îÙ` 妥ê¦çy]"ü‰ã–Ÿé 5ëéŠà6ˆ|®tH:761FùJ47 ÈñPÇr¥S±Ãž!ü%8­aCFþ'©t"ÿryp÷¾cº¿ôФ%ñɦq†÷À@»úÕô ¹îpn6Éô»Ú®lŠ|Žßxï;¨ž>Z96JºÎßžÑçx5£K¸Å&E'xh=kªŸÅõéÞݱOJ±KÂy/&Í·"w½TŸÄ.á µwƒvjÔ’·9Ÿ*äH,ùe“Î1AW‘t €|™wU-Éi¾9™–ËÉ…•Õl˯_+ÓAŒ¦Š¯ Ú¡cv<~†9o{CE˜Rùéš'–ˆ DbnÊäÜ:Úµh[Kv£©ùD¬>èì5JtqGó×NŒú…5ÔßcºkÃ×K<¬>qSÌ pãÌ0Uqy^ÊÞ¶~?)o?hÒß‹ü<ë/ÛÑ”Ì8„t!pºCí¢FºÑN“?BŒh–îTÛ& 8’k,º^äÃ5{Æ"çaùf¤ò›àÝE(R_›¤{m`¦Ÿ§úÓ *{ÎæüÛa¡ ²i[¸x$ x¢%Õ¸\YL.QhÛZ3u•b±HO¦+ô‘×ÒÁ|eä@%M¬¥ì’jf6Õ§’ð* ó!Ç墄KT o5°Fæº cÔqt%J‰)H¢>@=‘Ÿ†ÍQ°ðU[CÍpOzF ³”¤zS]ÀT9B¯Ä7É_6À0Çû%ÉQÓÆä>aO*‰Ù¶»ýþfÇ)ݘS½jÌ5Ëã^¸FŠ(Òƒ[‡.G?VH-ylà÷w&óغíLÙæ]µõ-Có£­\îØÖ@ÖúþöOîJÀ6ÿ:bŸ³fØo i[|\‹ÏMç5nµÍ\Å/üî6éÔ~.å‡j,g6w¬ïÝ#w¬!W7’è8nš §MøÄR%dÃ+[™p^Ô¾JíÝý]VVk×ѪG׬xV¸U…ÜyêŠö&.áÛ÷aÌÉ ò!dµ@GÃêkéû Î0fÇMã;X)q€½¾¨ …Ý]âš.¼t¥Ý&wtºƒ”ÜõÃËÊÌ‹B•L0kôÕ­jßµnëá©Ò¬*³1šlІk/ÃïÁ‚e[³U¸ØPïóÔ¡N[OëÚl­’ëØÄÎш‰kö¥™çŸçls¡eI^اˋëÚ8­6F£€ÓŠ´bÎŒ{ð¯×WŽÜ¬f–lk8KÚ®mTˆ+­ýhX¸<ò}?-×àÔÄ1|!„E©mÔÅÐû,R¨”=¶°ÕjèCýFÀÈÓ=»e£°¬ê4¹ÖÌÊZ—'?•å-»âRß]v–K¿ VÕŽœµå5¾Ã ³uCdé<”ZæJÃ|ê-pUæ¡«øÐA‹§w`öóûdo7~Ux/Ž®0nŸYPºòÌÞ¯iSæ:T¡uèÄœš±ÝP®ªÆJmóubµ5iÀ±±2x Cµ ¤VrìFö¨Ï¥©·®¥uãbe]6°lõµx\¢œO¼ãç€&Œ]ˆ,"¨ã DÍ?¤vßè¾ueoö¨+»™.‰+[J8¹J™.&7½®FÂŽ€Å¶jaŠûŸ™G‰Aœÿª½Wk#ƺ!}e‚öì±” »#c[fZGÕã­kÀÔtŠ„ãÉÒ-7þ …3Å1Î&ïP,g×;Lªë{ž]ž·ÊŸJ\þíL Ül6OsPx§ƒ÷Ó¸ëæè=°Ü³šûØ®;ÓoÍèìò™ÀU‘?à ˜Fv9÷dJ.ÿÌäª8Í®Gí‚÷³á•R臊•ÑNpë-²Shuù‡þdF[ú"3$Ãfb¨Ö&Æ[4û‹ßcþ/‘Ún !.:ÏÀÆ9—˜jyÚ› ÜÛN 9}tîãX†pcQ]þÿLÆzê¬N$J£ì×Ê £ZÆ…?-Ù¸™‚hG){ò­‡Fcl##¡Ú”À›k™HÒ¶}D0¸¦÷5µüØ»)R 0ú´Ø¼¼«’±äõ¾yÖø4¿>M4ý¦:]å•><¡öø)¾zŒ·|[Fyûž+º-¦TZE.ò§Ï¹IϯÖÍÙü>qŸ]q‘£hYÛHûhHÜP=Òé„O×®¦çó=P[TÏ=Yµ¾»à K&7®éPŸ7\*4 n‹ê_h1¥Ò’+SøŸt¬7E}qE4'›ËAt†d[h1Y{:6¤½¨Ï߸`ö×|lnGÝvÈ ³ˆ™+t T°è¯×$㶯 5b#iÔzŽáÌ~0aÊÒÅ~μœ¾ež„NbXL‹p$­9kØ›X n¨‰ßšÃ± ¥ X †T®å; ·5‰â‰Ý|…{nîY—-´Ë(I‡£l„Ðã#øq·C/Ù­ñEŸ}RZ&…vÀqnB­‡êÅÊØ/¬.OŒ_Nk–ú]bæ‰eýëÆC7Õ²Œ²fKQ•2~§uÉy ráv0Á¶ü^0éšP#}F—Kˆp£j9úW«™o¯\JÍZsòÁ 8P# ~ëTó^:çÛr?RÉ ëÅÛÀ|¨üFpþ#¡üOKºvšÈÝ„·–ÀcJQdi©E¢¾ñèÈoÇSðÀæ|ƒ‰¯Ÿ•/ŽJ[°]4À;9=M.P£6É“˜@¿_°$Ç­ü›'ÀÉ/(î°§*Íûeäzš¤'çs͈j¶¦KV}âŠä¶<2p•#T1µ®nl¬× Uñ$ƒOâ$ö„°*œÌáÀÄîc¶«ÝåÀDç' pÍsÒ¬o˜bÁƒâÀ}`e)Æœç¢À#§kÊã”ÛD¡¼Ý…¨È~gR’¬2wBºâv{ÆžN/Øãoö18 ùÂrmd!ÑØ¡l>.t÷JŠ}UÆ?ƒ¥Uf©ÃÎù©rØ·×n>IXM5-Z÷å‹ô³þö¿jüMà<ĺë·ó¨mùò$_€yVkíWeµ+ƒN0ï×W @¦7KV²!˜‘¿—h<ã×–>•ó&ÜÜÏ3d\öø6–W£|†Ôë¥#™”óo}ª¬pvJ•ñ០êL<óºü£Šƒ~> w?+W*~’o‹AR„+Ï€ú¦IêêÅ[y,«15u†Ýl¼®Q¨M‰ù±Ž«£ÅmB]M!5o‡ÀVÞÍ~—›‰‰ðp(uJÇ(têŸF#¥Is!¡7œ| 1EhÊÒ¥òMë5:2’„îÚ±ÞWWP…ªWI2á&ñÀ§5Q%‘B/âÞ3m\rEÐ÷G_}^O¾75Ç‚C©/äy›.û”ù—^ê‰. ;FjÑaƒ]1‹@ö;«“Ur\éeß&…/y»'ºà sîääûtËeII h‡.¶=qZkè²ÇN˜°]‚uþyOñ:ï³/>ÌÄvÅQ˜à³Œ4›dÆ[À"¹ê5-Çf“mPWÔÙIdÏsù:¦¥My¥r,ùKÈåÁi\í!é†<ŒåäÈGÞ›œc_Hõ ½ka¥Q` -›”ke Œ'yÇ}àÛ,WXdÎÓ;û…øÌp«z Ò@ñouøM¥Í¶²æº]°ÝtX„óTõSF;l¡ösîMáki–ƒš-Y Ïœ!»èÀ#óõ€yG¥ìIò/Î1ƶÚçë‰S¡›8Ë©#K¤q÷(U·Ã"E¥a@$¯qmàéêÛ·Àa‰XÙ@-)þÌ–ÓºšÜŒ†â°Ÿk©ÆºöŠÕdƓն§? A!§=«—<ëýojD¼ùJFcv®Þ`ÿ\ˆ¥“õ þÒ¡|r}HV?áMröôPÁ÷aTàa«Qg]ÄÄxÌš_rMU¯¹rŠöÉ⤬xô×r7røX\4…œ _h6¤Y«ˆ[ïZW¶£ëôŒbYŒµ`Tl‘¸³ì=`Ló1dM*#é`­’ÿ@-Î$$"ØUsYÛ³Ýߤ<÷Ït¼™§yçø¿€ŽÂ¥«•:õÌàþÉ ;Ûíô,,rLÂó•yi(Ï _GÇþ´N¾}¸`kãwY•5s£_÷ê铹ޔĶ•+Á}ö% „¸Ç6 ˆP—4Â3ÊBE~ßi®BUf:Úö+±Ïðb8#‚ÔÖ3¾"±lì¶,=((ÁÑ€Wœ?¦ö2ŸÀ=pSK© ®OÍx¼ß”ý”$…· ¸ llŠßìm¨@îf;í—Y¹˜ÁL¥Áµ1'·ñF¹ÏÚæðv¤}XYÏ„=?΋-T%ÿaRÚm!Rp—z™¯#¾A”/QxœUIÀmùO#üU°äv°M•ðž”Zj>a,ŸÃ]†]¾‡j©³«Ê$À“Ðjuͬ»±¨±nÇø'1/¼©4}Ķ,Ønÿ=øáënOWá¼ÀTÔDÅ`ÿ¸o.ÇÞ=ro!K¦F^(‘Yìůyt&TÎ1½Ê¸ Èpÿ_E<ƒ¥¤vB)&\‰îSÐ VdÞ’IZ¼w'–r‘<¦C¦ñõ÷ŸLq1Z³EY“û'šh“£Ršõì{¬3¯Ž'B¿3ÊdcU‹JäüPûS0jiOwf<~Ôá_]O®Â] Ÿ”kœ„;M¤ÙEPVñí°ì•3© ošo‡Â—þR›ÊÁ¨Ÿ|Ó}•ƒ†¶üaeÇ×Ùà«b¾ÿòj©„•™ˆ#yµ¹=u6”D½Æ{M! ½5GÞB'*M¤ùµyôF;× ¸À´nâüÓ¤SÕ;AD7Wß^)Q±•þó”5ù‚÷¬áìqAì¸Áä 6‰N’,f™Ibl–ž°« ¼9ZM0# ¬€§-ÆÆ$ÝÎÈ3ÒÛÌj—GMœÄÎÆôP¡…úî€\-só@…+ÅËÀ!§¼~§ô`²/38„4¿åQC–ÁM9‘ž²™S'ˆªöj×,¦ÌQƒ¹Gu¥Ë†ëëÁøì´ýÖ…0£H^êðíýCäk8\wôÂ^¨ÏÜËSÞÒñÂsÄë-Œî»wÌ tuªTëÃÒLåÊ6Óô6o»?zêÖ¨VìòâN\ÌW)Åïí)Ï¢7Gq] û¡’ÚøáË=[9ö[-Ðgv(v³_an1o6·Ç! 3äÌkŒñÄÀßhlMÕpˆ Gª ,¹èé ÇÞ`Ñ5}§ÂÜa8wšòBӵĢ¿Uû‡×Ë;ø¿˜·?¬þ‘?‡Ì$F`Ð}›ÊßJÔ=‰w IM˜ªLŠÚR8%uôô(‡Ù b}|­ödg¦³ÌÜ›‘WVÀe°´ic€{Êêy†tƒÑ aÙq—Ws4©«²YOuÿ7¡1@lyÍL­Æ ÑÛ»ðq­>Å€£çˆ ÍŠ«(·ü˜81’¶Úá„VQx¯¢cTD‚é¯HãŸà·ß)Hèè±EAí™ÚÎ.Ôˆh]£M ‚“ŠÕ¬ý9µbqúTãdijÓ³è¤3áAQË­M(Фõ9Qrªè¼ê†Jê±ÔÆæÔ‡KîÅ|Þ9À;‹1GܼZkY5 ‰Ó™ ¹Q x£ŠÖvf½ƒê Áí1Ë’ ÕÆ3D¹9îTŽÏá¶ñÃã C“Ç[­ïàØ¥T ¢êŒJ’[Éæ¸8cãá¾»ÀqÜK÷+tÀf…* :Ëî& t^“@Õbò´ž,Z¢¡Gí´p‹òóTy&ÕíçÃmìÅÞ.zWMiG{?—Z¸âsAè;A™¼Dá'Úɽ\–Éb šÕ£A»Y1ÚÑM -j£¸±Gð)'dpYOG Ž+Ür¢¬}þø¸­=yülTGâ7¼Š«å¤i ŸQˆT*%ÿ7 9žF×0Â)ÖÌ)ŠšEhAfêÏšújj‰¦Ä‚WHÀõ\–Ær+Y›åçhý¦õ-*º0ñe¹øzvLR¬˜èkêà6þã+êvŒù“÷o…ßù|Ñ‚(„ïsûؘò.‘ÖMìGôU|i¢ä ˜:'KþÆì÷ò·›ËÜÉ6TJ-©ÇØJøÅ¼´Ölu”ù­ÌŸ5Tlq0Uk0 Ü*u†l/÷B§&yõ¥tÞVêD1ÈBsLåüà5ÀŠeÓ«?eSKÖH^y@y Ý˜Skâ°4~Ãg¢/?øK5ld ‰8Œ=.EíqŠò8ßùzŽœG“É^¤W–œÿàŽTÙÛ¤Ï&lˆ¤¼ ?¸Ž…|Ó°Ït1.¸‡Lø ðN3Ä‘Ù^|W¯e±>ó9ú¬TÕ¡ Ì*qª¼ºc«ÇŽÚ=› *ûÄî£ÞUÕp—ùºÎÈnYj$$Ѐ9Ó3Úî‡à¼¨¬h¯T±ÅÁ§pé68+ÿWïô‚¤ãåí³O}­–=œ›¼(Ñw8ùò¯rUY†EÝn㌆¯È|›+Ý;Èð*zåÐÙdpZátI}­ü'Ÿ!¢çœ T1‡§‹$í°#C{–c¿ŠMf®Ÿ¿(Ä¥äád†˜?À_OÂl€íÄvý¥Æ/Z8ÕH=Dd´QúÍY9\{!³üü¬_fò¦®ùÏôê[éR_Lß`¼¥ùùz""C|·å*&gûDauè÷’ÛÏGSR¨Û=:ÇÑé;8ùÚM/}3¹ amÊp^¢cÛìù€ÆG*tš„µ­ò,fY‚žÕµAÍDÆsçÎ7 ‚N½¶§Š—ÙB²…lfL“æÕ8gfu•|p¿Â€ùWŽK/`å¥btÌ>Þr'Õ™ª†¡"ˆl.=å꞊õ<^1$œåxùÐí‰ñÃ8©+%2FÎZ"îHµˆÒ7Tã>˜ òÖ¹ìB[¸Å éÜ âbrj½QØÚÑ#P€^žé‡‹;G£;U¨w­ZøÙià›½Ð@¾Žkµ'(·Vƒ7˜ g+)Å—cÈåH¼WšÞóz·„W®¾ó†û'9’ÑÉ]óÀÛ†e¸ãõ×ú¦wh$²eÙH6ñ]¾ $A3ùNˆ +ç÷¨|Y­Êú$‰[zìêLÆþ'%‘÷«úg~Ž4ÙÚÅ÷ÌýÊ5Ë6lFÀçƒwåU`ƒì½”Ù*!Ч”‘!ÚJ<žxcô~ø&Q¾bA‰XߘøC•AªQ §~XzB©‚„éAÜ>û™JÙE‚y®0Dd f`S9~Òv‰‰…+¬$:'# ›Ô¾eˆÕ C™ÇŠ ÛɃÒQé!KóÀ‰VHÈÐÇjÞuÔŸ QÖíJtvá è‰küГ|¹mùA[Ùz]ÓªG®|T@ˆV”Idáç·Xj>ÍT3ãOHltŸ)žª9°Õ„Õ±)k9Y2yšØ¶ÇEæÖ;œ]Åsr ƒVNØè~Û’/ȳ°M$p:å5ž[u”;û;µ»9ÄY tqo ìŠX«GåæS†I Í#ðqI-(\õåZ'úhe”úv¢SE«õÆG Y9’¬]}!±êÁÂöõBôgÄq¨$4>9Ç$KáƒÃø³m†,ç&¹g’,Í †‡ž ê«+± ´×cúïÃê½-¿[EŠ·Ÿ"͘Æ_` ø¾c! žùßS~$LDò¿¼mîF„üÄø#ÿLEfÎ仂žÓO–-6ô^D§º®µjÎådAÙ¯rn¹nᆱŠÔ¨±Ê’ ùþza8 ©„$¡ª°5Yl+&”®õ¾ƒ–"}þE]"–i}bOoÞ…ZtŒâÛC'”ôhÇ»Íþ}*$˘ê…žwsk/ŒâÕ8…?\VSžÒ\1×·ûè—©Ñÿ€øƒ©0úS΀gg0 sݰË+~Èc-nÅè¹nòßðÛejÿš„QÝÜìÓË类B"ãtU›(H[Ïo3}½±„êŒÑ:³5Í{íHŤøÒ$u(Þ&@ÿÈ^çÖûEîÀÊ0ä(7Ç–hÇ:5 “ û¯/Ô Ã ªTñÀÑO‰¯®\>·€”CõF ÊÓòY¼SÀUÍgü[ÍjàˆÌ¥K ©¦,‡“§i5Ša™³âÉKƒŽ • úÚiO5b/0ÇУ„§(îAÙY6 SèOéÃ÷+P”^0þäÉ´‚Cçxsé,Žù»ÞQ—¤ŠÀ²}_øþ¥Z5ØéWØþ7ÝÍé{Ò^ßÕo뵬‹÷K_­üÓÑ&ÈIL³Ñ|¬mSAÙÑ"ÙeŒæ©š5k !iÏ*¯•“éu@+0Aiè8‡ÓùÍ<ÛÄĉzÚ{#²¤/Kj>ø·%õ+>ÀoãòXÍÍRrŽ /-éÃ@š¶y­Q÷†tÞóù.ä¾ì&ð=ŸÍÆWåy*&·DúBæM;™<¹ªœCeáôÚÍë.’b¨ƒTµçèV»xLGú†nšfʲ'YK%&˜!k)- aÎ {ñàÑ©D €ue(„Ø+dË 1Î^˜Í\ÄsÃL" ‰ºÊ­ym¸Ñ›Ôtc“¢ÜÙíâ6uYôwâLÌsÔÇã‹o2–úßbi"f\ºØDb'¾èÐõÆ×§ÿl¶e ^iÀÂw*ÖI¢³ß<™:¢[ÁAÏç!#‚ }IWïWO‡ò°+«ÊáŒ[/oé@Ó(1½Á¸½’Âx䪠çS«¨*·,‚Ú²Ë=±` TPó$ÛBRèã ²ŠdìoÆL½•«[^=MÎwW¢ˆæk05˜*^«xubª«~~ÔSkÉÒ1WÍsN$1w¶ãL°’*†Tt>ú) ìÎè¬è9á3³y v¢>ia=ã@ 4Œz,Í'ξ#–Z„qJñ>"´â.g£ˆÓ€õ´‘|–,Ú~”öà „Åä h›W×›ÜmÌkš¦—ÅPÈ)d¸HÀ ÿVõ”!.¬:LÀØÍ.®ü÷—õŒ5ö~]¾ˆ Þ ¾Ð7hÛž\fpr>Šy’{°hmü“ÖÔåx'ƒFäþ¢•ĺ>)THÔïÇ’˜T¤üéJ ( Ñ—ƒ°8Á4ÊQ½!§jùˆv¸mwË-)?Éu…ßîìYÏ7diå’ êžu’)užˆ.[nÙ­ì 30â•%ÍGN÷Ö åp'¼´MZAýQ†òŒ)cê1œ¡Õ§¶µ¬Ì dả»– rNÃ’ ÷#¬u÷†Ò©Š•4Úº¹óPªÊ9ŒÞ ö'º™]tà¨dŸâiãm{bGH ­%Î/ík™AM*ÏKêB¨Ã°(}`fÅØtÍ-‡a¡l/Ž€±fbÔî—B8¿- ë—çDl[Щ+6]šK|Ù]?ÜV¨Ë a^Æe¬Cˆ‹C‹Êà3­hJ;õw? ‚"-K¾åž¬w^Ù Ò}S^›JÍÖî)sóU¾32“Å£@§¸ÊAµ»Úí/íÅøÒ§Vç#Øî‰l¯\Fhñ„×e8H=ÉÃÐÖÐÙD‘³;o\TQ.¥ÍjËÊ+Áf³TÁâ ª.«qWÍz…ਯºyÊ4 Hn±~zâß=Žh⨢oà£l<«X@2—´kKìŠî¼’ÆÜ?'ߺ;µBEtûuüû´22‘^ÛSÇG‡—l¢lÉÙÑ3ÙøN.3ôäܾ/>;1ëໂ Khèòasr¯«ÉÿLµ¢˜YûÓyŽf-Ò7øH/ã7Š•:nVÁA4éâ+‹¥¾ë)ˆ\œ‚ó›ëòN-›@^¤xr+Á'Š$¼¾ëd:€+‡6'¨E<î³U¿oúMêÇ;`⊘†€>_]Ð |^a¯ð¬ù][Áÿøm&ºñûë+õ„—! "M°´õÀ|ÐhF_8Ižíœ 9œ×Q×Ç4 “õ¼5ÙåÞËP-f™¼~UÞ†JƒË"у¿ëÌ©gI5<ˆ,޳Û@6¾lº„¾‡œAügHr -oþòº(Þ° À4p4B;ï® NÕjÍ V%Cª–kàÍv °G'íVøª :MÎ OJ4d aÍè¨ñrÓ0˜šY—gâàÌeb$xÜ“¼î½ÐDdžfÿ¶âûßFTµ$czcÆDˆÃˆI†šØúm4Š“#0ÖÙÉ]7­t&½úRoìïŒ38ØÍ ˆ/@I'ïTëˆóÎ{ÂÐÜöß%Šß,$gaКž.sà+ ãÊïA–¥÷UªœägÌJã¶çjéK”ÊÒ³¯‹GQA‹EA…káˆàJª©…!"þF”o`¸ãeé+XTÕs6 ÷•@8¤\-ZaM’·tþnû›`”'ä4§¿ĉã4OÝ}£ô¥lðý§]Lˆnd½L¥d€ðos"ч C£ž¸»ÄCûº¿jµX]û` ø‡M;ê1¾twktšÀ[¶@ÎßštÇaYƒÅ Pù­J8»ŠÆòß±* œ‚ ͸#“=OË™´èµqnz\Ë •»fÒdºjSübfá¿Û>q(üêf:íÓ¾2q1Ñ©[2žÛžC+qvœt¤ø@ë•Sb.ÎÛ'Bš~Zgg¡{íܨ¤1ÆÔt€—^ìv³` 9Úìä w2£Uë!ãŠZgÔ†§rxîQxR*zPiªiêOOy͆0÷—z3S‘Slý䦘£ê{‡é±k:ðú} A»jzÒî'ù¶³( vÆýpòHæ›:|øhW=6ò¼|eF P7û|ñø‰Þ//ú­û6i«øgU™í41A¸S{äMMÉišüÉ1Ú«áI–MtÈ÷c60ðü»tÒ5"è~´Uû^½˜xå‹9*, ¥x& ·Â”Ÿ€BêrXîëN8zÉè&¾(±‰ýrž„°brs DPþž+½ ¦LåÂ{2|òEMVÛÌÐ1lƒ§@Ë¥›Vî¥H—+Êä `–=™-=M&^{uXF¦Cã{/*tu¹£s×]K»ÇêÝû(N¿â/Ú2_¯·¸ª C+Ìj2S!¡Õb’À¬+6á Ö(=Š</ ‰t.ÂÙCÚf( z¤h3É2Kn˜séÖ,üšÜ>i6*£VdÍ#ïimŸ/8Nüœóñ TO¹kšB;E)·‹ÖsÐMJ;R_ªŠÓöÞOÂJñHC_ñt7z5§Sžwæ!zvåàs3h4J`ofÈüÀG¸áÐK“¸T²ƒ’-Gk¾DVàÏ(#ã“ §M\3‘æ¹ÒE—™Øy£ÅÙ%¾V’¸¬«ÐÄöfªJDê. 9cÖB°q»Ö+ c4\ž™éKêw‰Ãç={Q"³Œ™¬ÃÌŸýÇ…í i,j²Üi«Ã“Q}rrã–w©°qŸq‡ŸYEàµSLV¸¤­Á<½ÏÏ î£K–ãw$Â¥²Ï¼W^Àà–%LµË(y'÷òF;•G„J<77ODc€)_>Þ àS²ý˜ðPÍ´úG0>JÃBzUŒãÏäè4YÝi0-U›ƒ|ìrF  _—‰©dXMã ‚]Ç!ÊdÁLײÍj´c°Š& §g—PÍ[´ò¼ MÀöi›µÃo‚ŸÁ)“ˆŸë÷êYV¤øŽÛ~5  9m=ÐÞϸ}Þw½l„Aõfm†lÆ„rlÁ®¼ä0±ª'¶¤+]½4tWR?ð@áµ.{û,|Îagfyzú}­9é)i®X‰.eö!"c¸a ×Ii.N˜’¹öOBºñ¥‘•![8%=Ÿ·ùeè!ß[_‡›‡Áä;7egëÞÙÂ1ð’¿„s£Hp ëçºç|Ÿ¸ÔwꙆeº‰\)nH±×É똔=âFk(µ‹ Ýâ©ìñ³ÆXÀeÙá¾äçš³H_Ä LGξ¨ŠûÜ ' z{ O"ƒÿ#y^±Ú9.¨eà@^Ë3=/2Ù¼oª$ ÙDÛ†kªzŠ®ZÚ>ßûf¼–¶á Qݲþ*£±Ýz1 ð6lé'ë$pVþÕem9 ˜Gï W¨d ¥Ðp¦}Ebëm]z›O 0¤&xŒã x°¾&°»|t2 ³…eàRuà –Üm‘*ør Im‰Ê`_d¹&yØ!ÑýâNQ„QAø±Ç·½'Ë”m·vìµÓNÂÑû€Íà¡›ZóÉ-…½¶÷nü“–]J1÷/4ÿ6×Ñ~“ }‚¨ìm’}䘇2Ç׿aÙáiZœû‚ÏA_€üv6`2VósÅCY [~EÊ S½¸xsiÎfY(¾UäÆ I­ÝH¨º°55Ô©”Lž;çÔ ÄöÛøMzbÅÒyÕ 35™ãìt @”·y÷Š©{3Ÿ\®®6yü®ô·3)±9Ȉl2›© ç‚£Ñ[Nس¾oV.qëà°I.QÈY¡±ÇXPwᨱÍ=óÌ+%PZí®¦1€ÓxÑRK‘¥‘5ÜÏÄ Àt.fká*}÷°ÎDB°k™ç³()ÛÍú³8Õ‚Œd ýX4ËÅ—=lÞû©þ ,2»Edð¹ƒ9%ÞË«6¥B€›Ftz‰Óï_ºKÞÝåÎW´Üh¾u§Ñ~\ñZåD d‚ñ‘»H”}w‹I³daÙ—ŠãÕ ¯=DEÚ´Óïí>–ˈ›„×f/–:ܺ;°Ôe¾€º*[oÂ¥¦éì³%zê5%;ÅžßPÿKïY?ΉAìô«éñÅu–â!¶íÐ빎ôæ#_ÿVBêÐ9¡ÿ|‹š8:|¾ý$H B(%ì§ü˜‰Œ’^—ë'£|”WwY¿5bE†-£¡g¾ºŽŠmåâ%q zp“$jùGÝJùcßÎãW9è7¤KB½ð‚®/ÑÕD3Œç"¥"Ñf—.s¾4ׇÁRŽª•š݅p¾ØCÙËgRyäž[ŽX˜]³|&=Æ«MžmÊdµ N Wù} ÀÛ… .ÝT{ÙïÀjõòh“ø1v±üc»KÉYÇo—ìŸì¦éͺ#K°û¡„87jË’9“égq6æ§Ú/.³K;KÁ¦E|®u~ãiGÏ"3.˜7ƒ±ºp=]É®To¸œE’Óy™{ï“@œ¤[c¢½¥HÌ»ÐÙPIÈîQ°çýÿZóþqbcÃ{3—Ó£ŽH9û×&gè©ö¾ôze˜ÀMNûÊ\Ò"û?3­±¼ÿBÛ,y0Žxà½aF¾ Žnì}gXØÓî-z*ÅV›¥Tv»ã*5Ùiû µl¦©"Žg#žÕxºMŽ1<ǹ²o2;28Ç"pj¾²ø!Æý„ãK«³úÒMÌ)lEE*Ú ÅñÀŸA¯bmõþõ¯–‘ŰÀ¦q‘Y‡3ȶZù$ö@”ë½Då%¤¥F1³axŠÃ”1sT³Ÿ/ÌgýøHÎ6˾w1âÞ×Ðò½Þ ùhÄ ¡?]' ½à]†ÍM´ª¹Ã˜ºó7;@XÌ(å^û=‡«uD¾¥ïX©w”ã›""¥º>ø¢D"”$OìŸ#:ðErìô[/ú¹›V—M#ªÍ ªTÌ!Ô“k!à ®ØsH;î$¦G}F‰©Åðs¨ÿÏøK¼úqZÿZy líšK»’?œ[\¡rÁ‚0{k4äáû÷¾‰6 õcï©ö7Œßh è¯b¹RÇE …0áŧcë/¨gêŸJÂàNyzHnCÝMëßÀ7ˆ”2,¼ÔWÕ]à®tyc Ú— nvfÂ8YíkµÆêÜáz¡Ðæ]Ëzu/›ôx8ù“ï/BiŒiaÚÑh ýôð`2ÅFþZß ¤Ü’ZÑ¿¶Ì‚ñõã­yB^ )ù4b´‡Gú“惤˜ÈÖWÅ2ћּæêXVøwwº^§Ázú¢ˆ¾CjÁVûŠ£™^Ç£óÑóSu õœ‰Ôw'’ð»ªì䲘|S·.o&_ÝnÓÀxÒµýP Ñb{6ª[ž0ò»÷Wð×¾ÏÓUTâ±qºfÛØCö6×6Z^†ÔG µS4ùo2ÜÎn›bs•Ñ[Õž.l…Šü„NŽmO^'í¦2î`ÚÓ@ 1ëÈ¢üIׯ5ÛÇ0_˜‹»Ùè …/roczZÀƒüæÇƒš#»Z#*ƒãß¾´ÀY!t“1Òl_F1þ(žJµÎ,·`d£NI„œ:~åÔšÃjì®uòT³«ƒ;b`ªvðl¥þÃö!)ÚÖüÍâDø<«O—¼™Uz¹ €éÎyº|¸ÌŒÁ°‹µ›4¼Š=Ü—Ý ²³L Qÿºê…ÞÐGbîè–ýSA?çùgÇÕܨ«ï´yÈà¨ÿýвÑ["¸ÕЋQSOÄäœQ›ÈÂODŽ@ßþj1¯Ð¬ú±e5 ùR‘äS¼´r&\#>`¹ÑExÍ7G¿ý†Š†G%«ÐÂ}^^þé!ä4ø# E|þOµKàÄÛÍüFÞºÒ¯Àa‹OÞ;ª tfˆLn›2½¼QÍÌF]À×%|(m²Gã–d•©B7†Êµpø“ißðâªIÖý°ôI Å/EX  ž9¤aˆ ÀéÐÕuM{mülS“>ù;Y|ì~9Ã<™aºàNC&o¤OÉ’ÐæŸÀx‹(OÅ×ÃN}Ĥžq”^–õk#v £ý$ÆáÅÆâNV|ÞÛž¾(¿ÅiC£[fœ+Šz§=½Ã"DN¨%OÄ´qTT\9F±ë­t» þâŠC€O/JRžš¨é[˜7f„T½ÈR§·1*Xýò¶“¿Û0¥«d¨‰në£ÂŠ_j°«Úê ãŸ=ˆ ÏúùEîò°2ZŽŸ!WRò3œ»3×ììe´K²ÎeÏ³Š¼ßÞ±• aŒï? ç>L-t¹YÄ*ÖTy2ü? 5Ó]mZákèûÕÜŽüOEE-õîÌúÖ|¦ú•'ß#.ßafÿ¸&hÌlØk’âÄyâN°Š‰5+˜7VÏæƒ;=p²¦> nÕŸÂW…ÐÂØj†úãZsôLMJh Ø31°eÓÏt GÔx_ ²»±LvCŽYP®ò¯8sþùñáZƯ8¾z9XIxGšIÞ(!ê×W'vÊ˾oà±³Ümßm1ž§[Z8‘vÖ­‚¾*»¶·ÀáŽHRÛcCË‚¥Ã•”¡*¤Îv€c;Øåå5O’µEG E+U~¯óàŒ5–@:ŠÞ*ÒVttÚ^É ¿ÂÇÉðîµätn\X®‡º,ɬ» ò-™G »ÄÑ¡bÞ¢\ÉC…$‚˜Ãu½*€gå­S\%í&[mÒ/uk›–z ¨ükM‹ ¸ø²³9d8 5¸ºVòÒ¼€{Y€RBg@)\7‰56¬vm^£‹bÄN™@ÉZ”!â¡t¹u»·öj†?ù“S7D^‰á ‘L¤*ç 2—FU“×HVh©–e3&Õ°åeÊо¿µ/½ð˜ãÏŠAÄÄõ@,ß¼8€‰±²„òö%IÐ&:ðo¨ )“†è–ˆ¥3©“{ {­à/gú¯Zj Õ²Ië]ÌLg#v†0Ôʉɻ@%Ý}íú¥+ôMçÙ”™óËR¬Ç<¤wˬi§ÿ^¤„$ÝNEŸL¶e«Ç_8TгFþ_¾ÿîÔpð××Ê\Qzó/;'m ý<êx w Ü")—õPz&XÙã/N¸—;Y<à…9ž(l¯R´g€úšŠ½¼MÝh&Ôž;Šÿ,Ã_V£mÏl´k\±)U”k‹°¹€ô$P{H­HmáN`KÞÝÑXñ «öý Ökùù’M:NØ{ânîîr©`èÎǶiãNä™^¬³qÞØ“?ÖxnúšëW7HÕ]ߪµÝ wžÄÔÊÐŒXˆïÿ¯³Ž»¯ˆœÏ gTYÃ/ºÝ¦œ%UÔãŒ;ó׉1‚iaFä·j¾ÿ0¾­?õŽÒ €>eÁ¤\B èñà‚ Å;¶ù² ¥¥›ëîô‘«Eñk¥~/ 8ð_É!"p½D^¤ZÁ‘ õ­¢Ðæbg°\ zׯ}Jñ[¾ †-Y723{ôm£1wʳ!ì«já2ÊÝ ¹µ”AøÓ£,¡¦ko ^z SÏ"Æ:€ É"eoÀ(ÞyQ1‹ôà ¬ä ég¸zHQÚI ñâfϼŸ~µKMán .¬8rëHã„ôi¾ðà×¢§í¶{ˆ‰¹.q*:ǵæ£÷ÙÎ=¨ ñ':CâÏÛe×"Bñ Ï1D„'aõ K[#fïǸùñ%Ç @ö¢An¹|š@žªñC8ðñlÉòqÖ´U3_âÓ+»;׈Ï:k·¤PŽßsçß½Õ9<ì%F~‚l«è#mÓ X­uŸIØõƒM|qõ°9†ÁV«×Hƒ–s‰ºŒ¢°ÓùuŠŸÚŒ$Hªå™#XªEøh»ž8#ô>WwÎ0©ÙäBÂìf4 -e7P„–攽C¢b×{^2R89Id²#øÄ/w_ƒ–»p’¯¯rÆ–®ÑB޶b®‚®IíØÕ>z…ᤠ%Sd7_5‰æ;Q)-ìÛ57toe†”GdÙ vб¦q(¸ï †“Ö ï4OPÐùÐ  úûþñÜϼ<Ãe0&Õ)ØŒ3ÛaÀºî}#äbåQ?䘀¬\¿,ŒÉb]LéðG±ùö¯ Ì×K„¶C(ùH¢5Â^_›'9ZAd:°Ìªþ?bê]„TŒ’o¢Zu<+þszû‹Ó×@œÐ§"òÁV+VäB´]ú.9úî:ÂëJ LGü/’Í«}Ù¨µú<Â! Ë]¶RRÓ]dm öãs‰.ÑÍù¦Še>`à.‰$—™AV s&nôô[t&æòýlÁƒýŽY›ñŠÒT\aó£„&Âw$£ n™(™ázXØfÚ³¨qâúõ…üÞ¿°”$×Ô‚ñ›¾pQ݈‡›öQ Àã>cæ€Ì9‡eq(ôXÈÈ{ã.ŒI¸¡æ)á0@‡•×€WeÔ Qá&§5_Dò "Q³+SÏZ»wíäãfõîçj¹9ã¹Ö…£Ýãö!2I[i^ìÁ ~Îû¤¨ø$7±àz{´ƒŸNòŸéxÆ¿•,×^=¡4Ñ,ˆWbqºšçõï• 9– °¨ h8¾_/Ž•ÏÛ¼’¼©æVA3ÔòcšÂ޽ðýgéÅ”©©´Uo‘4bߨ»àÿaL¯ÆÞ<"ð¿ºNI:É4¾9l ´?8Ö­bã,kNµŠ=ùå&þ{ùY'dצ¦BáeË>j#øÕ&i¶5!cؾËèÈþ ÌDåÜä²÷DGÔ>C·Á³våÄlÖÃÚ7…Ëè©Oì>Ö½‹’#H‘ô¿¯tm‡zIÄ©dcõõ¢{ÖÉRgh¸n3to[Ó3'üd“ì›/&éHúÀfŠ×5¼¯¾ì¬ì¦ÅýEïp¨Ä2¸GéÚ$*Ð:Hêp‹1jþ¤àš<€s©ªi“uýR]tŽß} ѺëÏÌ… ¢ÞžŒ‡eû\.ã h«·|WN3)¬±î:(©È£œfG—áŽ3SAŽŠb&‡9òµ…ó>ˆ °ÏõÉ6¬Áü]Ñ‚OkÎb?j¬:ºÑ2ƒ±º&° QKZV W¿84·È1>ðá¬gê£.<ôóê¹Ô· «o™6Xîý¨­&–Ô}NBÀÞEòvJ£ªk#Þåå¼]Û1(”骘xWäü¨«‹`›übüt$Ð:`(bu_á ÇÞÿ™×4¢¶Øy»CwÎÛûöì}ŃÕ¬ØL™¼™0Öª®íç\j>:N\ù2 GŠ5´â¶Åå„´óµÕ£™Ë -Z(K.œ†îïÌD¯ú=!9“Æ:9Ùé .h±ý¤Ã}ÄPGP½Ga“ æê‡—4^Q_uªÓ¯Gqô)^Ü¢®øÞäß!€½‡M[Q–‘v×tî@ék9š€È~¯X@&@çZÚ ¡mȘ‡­l õBôzN€{U³’:žRcº9Q¶Å­‹>±èö9ÒJÙ€EV£Œã`r½fib‚éþÃj-QÙ}·yRîWoï¿¿W°y€µþ>ïò¦¢\›é½zVªq§ïÊþK"‰ñÍChŒ•˃)Ì9œ)á)AnÀtH õÕšÅÓº5}Ê:;?sZ;03}#x*9ím—>ú€_–ûKzù'Txõö]wÌr‡½¨|Zžqè6/Ÿ‹ÌÅk©‹ø]ïGÁ§´ 72]ô–ŽƒJ¶+ sÉ}ëÓwuú¨½ŠÖ1D´ Öy+BWQ›Åè€Ö—áq@Ì›ËØôLÎf©ˆ¤ ^ÒÒ?é•Ýñ‚¦ƒ) ™½gÉ̶j›)êlÆ_<Æñož[ ÌO½ìTÜg ·‚k#Ü;çËlgÅñ‚¯ªSu­Æ9ÞlJMús4|²~̨Ýyûö3”Êí>îv Æ8l íñá(¡n$û}'žB8’'b3z/åÏL ¤»Jª—%‚%{È&˜iÂàZÅCÈôb…ÂACCJ%ôÌn|qÁOÅ’{ B·K¶ƒþä¼õJã¦sSnÎɘ·óÄ…|“»"o=á31ÛÊgqLƨ…Y‚Õ.õš™”óš©#azÎ;®ãèSqs;+€Kkÿõh`&Mbå/åhj®ˆý/5qAÓ|E™Óãð­ƒÈt”Ð8»¤st7²wØÚ3A²ÖVšm"ä¡Ã2öVºFJ¥`£XSÔÈ/Æc›œO†fþŒ^ XMXeö¡h`»É\,°»õ8[§Î˜%~±o¥»¤OŸ!íò SÒCZæhÃgNÖ„‡  “Î?{/ßï†8/êÌ'K•QV6ï!G®Î!rŽûR5 B$ñA¤‹Ã±X"Ï }XkdFÆa&ÖWÖ:ù<Ô°[#-[Iª*ûÿ¹Âo¤'Ÿ Ô!gȵY °óÿ7`aÛÛÛ(°› ³ùZþöÓ{–ƒ,V´‹)l[—‹m({ý™úpƒÜý)Öß "®“D¶ÇCõŠXy4äík<=ÚF1–E“&Þ¤ÅãåØÏ‰þÞb}0ýQîÌð.ʃK.ü¡ŠÙù¥ Û¼&|(`¡Lv¦ï®âˆ<&õ /¾MP›$õÐÓn$4–Ég7@ƒÆgýhCxΘ4lQñg…9˜†O’»Pò¸_Ú¶3uûN'-¦Ó”ªóÖ;âÅ{Úå°A(ÞgþÕ­n)YyÕôQÀÈ=Žä$$ü¢ØX20f_²dÊ;Ƨ2¶^¹”G:Ê ‚'Uˆ ™‚ÕB£¶Ñc¿Ç³dk]<ääÃîDdâ±õ1æ;|·}\ámjÎ\Órž J,—­F%LÉ-n÷6ÿX ¬Sçº#z4¸×´–ß[š¿F‘ƒÝX6ÍS%Ì:’Ÿex*Ÿ"á2¿\0žX³š ÐMä¨u´xຆ^GsÿÎÀ›}“„¢¼‡4½eÜhfãó¡©&Ð@=¹CU y>®…iÀõðç$öä1ÞëGjø’ÑlüßÂI§ÉMÇдWòþæ™}ò_DeÖ›éĦGlÞ5‘E{¾1á.¢íŒ‚.fLÆO£Ïqf8ýãÅÂã&ü¬þ ”?°Ù ¾ý<ÓQЕ ûxÜAÁ ³&ì¬w¥.„qÚ¥’ˆºÛÇ:˜4•ž=ß9(©|û#x–ÐNRâDøë¿ËêÇX`_¦:»Æn¯£oÌcÅe'®h‘´§TYT!>~øÁº¼B|æ€o‚ˆ$¨ölÞŒÓÛ“³FàñɃínBN)KNàú P°;q>Ø‘J’éï£e¥HóÄÛá¶süÛ9üQA­IäÒŸ w掠ˆ±‡C‡LƦ/¢v€Ó>ö£^ÝDg]EU•Ý‚¤SºL©âÇ&¯>3_Èö½ñÑä.Æ’‡Ü ßwƒ°ÞsýÛµÜ()ˆ„º</J.6^–ž·ÆIfðs / (G@ÜÍR,Ñ­ÔÀ—éQÑ­üs£Ý& äêpkšS㯀a«ç7)ܱâfQÆI°¥ÿšØ?pW¹f€ ŒO§ÞÅâ\Gư)².6&êO†ÄûNãbéµdÇYÛL=üéeémžO&'Å’«úØ!=VcÁ&à‹Ú;tãÒ3ª91ß´Æfðs@"•<ªÅg}ÛYkÎËmkÇ~Š•{ŇÉÔÔÔøUjr'G[gJ+ZBc¯Yè¢J§\]ß¶‹µ+†îPÔt úîV´!i¦·Ï ¨Î¸Õ Ûý"‘î0ŸyªÔ1Ö­oâ9`¿¦PInµ~àô¹vãvŽ#‹ {siÝx”;ÜY1gû2(2¬%L¨&&¨¬Í#ЫVÔbÞHÊr ®ä˜®û•çTPܱ¶™-÷ÖY”Äý†ÓkQy4§ÐM…<¸Ê†Ü‰G;4·²x¢¦ dÒGb $µyžã˜…ý.Dá^þ¬`‚±6±éFWo´:TL] >O¿%ëÂvdÌ(¶þd´›fC¥`ž6!} &¡ò±“¥i²¼ËË`S¶&ÚQ‘Oòüi³ •©f9¢+äj•ÈÓÒ*,=£Ï]euWÒa–çÚı•X­ +¼°¹µþnœ¾G•©möÙš¼€uË…Ä|pYè¢*QçÉ'Äß,ŒÝWeßIŒuFÔŽv³–î6_x¡N qÔ/ˆøÑ”hlé³…N[ÔÛéÿ/•‘ƒŸÓf”º#I{ºÐè@„Ç"m8FJæ~|9/YTJåöËþb»†sq©<"kîL˜[£Jªr ®Ú—ei_Ÿͽɸµ´„xæSè½ã˜L´¤Ê2âÖëåvè£S *8³H¡F™ ¸A>(Jr$†Zd"–¾A·FcYಂÒaJë}K÷æ»u±ûÒ:ðWÖ¨-Pk *°ØÝþAf*² &¸k]ÄDê±*¥B#gÑÚ ÔbWÖꇱËtDŽÌ¸«N¿î1¢E’/HƒßJÇÉ3x{j|— {kÔ9æUe:›Ýëi‡[‡8Úó#(’pE­~Ua{Íð„UŠeGƒkÒl]ð‘ YcµeážµJ&׸ÉÖRíâƒß4Gz'N§D“‘À•¡J¿!ËýFN‚€¤£è¼-{?Kj¦•‘;–_’(ØíH·h|W*? J°°a7Ü¥r²¬6Ð3ŸÝ¤`“Ó8¿¢»Ý+¥8»2Æäšž‚¯N ¥Û±ÇŽÎ ÷1e ²ÍŸïFÑ[÷X<»^Š?XL~šìz“ÈÑEM6îÃWu&~ýP‚*/#T/ò×­†mY‘ÛÙ ]¥bø2èÒuT|oüˆþ/*S6…ÖëA*£˜KM[k±6œŽþÑìœÈ— +x"Öþ‚¥u63œr¿ GÛH䡯àD‚™qtÒîLnó3a½ñåˆJGÙ„Ÿ‹4 ¬=¸ò)â cÝ€Yp¯$hoŽP ˜åû +;~;BË^¸h=  —G”0Ô×½¦¬MP\›:æÓv xÅÌü4螬ÌCÓe‰±òï•ñÆ”y~׉)²4FSÄO0‡ëåj.TÅð7lQ¸]Æ~yw\¸©«÷<†Ðb9P~Z|D÷t‘*žát¸W´ ²¤çAßZ¯  áEÇÍHôoC”uXÎÆªƒCî=¬Lm×ZÖ%›¡]­eá"ó=Éz×1½Ñ½Å4S3h‰Çh^?Ù”»½¥ø†ì_—ÄDµ8°.ïýiÓ{©ÑI—AwPéäƒÀLLe2tÇÇÎWË3ýmŽ´›Défö“…°2ò¹Hà^`+ÑQtêÝÛè·“‹¢µå±h’ð!iÍì=#¸ZOš(§ CK$q²†Uˆ!¤“9üXQº©òî𑈶¸¶O©î‡éL×Ѐ,qÈÙEôjþ’™Ìµ!‡ÿ±H£›åxPáQ7NhæÚŽˆ™zŽ>Î܈|€Ýou™7r¶(?~ jß]ÜÑãâ,Õ#)p¾5”çrî.v-Öz.ù±:ò–y¹G„{?œ(ê²3ª/eZÜÚwyW‘ù'ÁêWØ9rÓgØbï@½4îÑbEiw_ÊzȺۋ¦è¥ù!¯À¬ÿ,€zCN†”[ÑõJÛ²ÉñvùÍšdMöo…X馥¤Ï\+š}¬ZB‘C@áÖ0¾,>¬gEçRŽÈ‰{ñ n,Ì÷×:¢Öcºa®w~ÀìsvôßTÙçà×gòÍÛjS¿îÙ0ÃzxïjóQg–¹¿Ä'Ždñð%±öToëÎ÷MʶGllè•OpaÊfËJ¾-ƒ¨b^×ËÛýçä ¯Yå&KV\*A=€u+þ>õ‰X£0]×;ɾho Ò:à¦_1®ÚÁ”ù¿Ñ…j‚ªÙ}"¢~ûÍ‹ÙÿÃÌ’b¶M†¦¢‡0ŒöF~¯¢C ¼Ø£Ù­`ôwK«{r°­¥{uCpq‰øÛƒ´}?ØDñ\H²9µ€Ä´¨ÓæŒ,*”ÿpúcìb¢Aô²',¥A^ÉÚ`*|#­»×]Øß‹ÿ¼ÉÉ6X°—oûnÃ>–äˆÛc“ô ŸPàðça|‹Š˜÷Ûã J{®³'£yt[1±k7 ,+Ñ쵯þå¼-ézœ õ¤A$êÅÅúض,­¥/rnb¼»0Ú‚‡± µžð­±^CÏ»­ 7{öHoöæmÐÀ•äó·NæëäßÂÓ+‰O¯:ׯ(2ÔS9žB-U2þòúxÃ5å+ê0ظ*Á›2 d⌲e$¸¹ÒkÝ ='µY?z ®Ù P'´‚"ù&ˆõ/\ô‡kpËŽ¬† …×gBl²qϊ棹7{ è¡Gýš}¤f©|jBÔ5þt³-aäÜþŸRvUŠƒ^"(oµQÕNWëÄ9@ÞqÁE2£,õˆßUFYåŒ2Þ·ƒ(‘dhìÞÍbrðËû @à½ËN¾„@3ü¥.2DDç2¶2ú”JAý9Üïž÷W>¸YêÂô[ XY4>öÇ“_¤u›ä0ªXÉðoÔy2:Õwop×·Eëç² ÂUA0ñÞ¨¢ Cd»Bq:ëUÛY¨Ñþ‹£É·cøkÍèÿ¸6ÄÞy"«¢ d° gÒØ0•,8©áwßD2¸|ö#昵 GÔFÌË<¶òÃdH·šÍ_C䘯;†ý„êK³`Û!§ÉÞ‚³Ñ‹˜¡V‰×>æí.°ËùÑJSÐk‡2&¢Uù½‚e³ìH¹Ð(t »_ȤMÕ¦Þ}(T!.š-ÌwQ…V}$¹€;ö÷Þíj·Ø}a·Ö±MÍ5²…xmJ0$ xØ¢¨ø?e€’9›0g®ëÌÄfLK™w|÷¬ºYÌ’S¯ˆÔc6d¸Üþ~±Wá…ìƒÕú5>;‡‡ÒûKòÔoï*Ãø¿¶5ZG!\ÍiI³lãÚ„‡y[ lÃÏ ²Q¼QžÒÁ‡ÌûöE»ä¾È ðžÞ:P/Vßl™|*^ó J±,­¶ž QZ{ü†D®#ÒgžZUŧùdÝïQ_ž„N ;ëšë{›¹ü| Å â½Ù®gXåXnR(Pâ¦P3ÓKÄøæ>ŠõÛ¤«~Vnm˜DA ¢óµìw×@ä¶­ê 4Öe™»],ºdÀ19i> XpÚQ—}:¡3ô°—ÍÂ`.}÷k}Òî§CþâúÔ " IÛð%móÏÅjº"„=mËùdœ9©Ê,þ먙›Íòi•IRóâDü‰‰Ú„%4ô×%È|JØtîw¤#2²B•[àP;oE0 YAæ.¤Ý(ÆÝ“ÝZxÿüçP¶hn3³r¥”äêú\Ð8ª<'Y«C%*6Ä+ úÃî6õJí¯ûù´HÝH‰N*Èl¶HƒÖö¶r¶ÌV=Ô)³mÿ­ê…‘²ç ƒè"q'ÄÚ2¦NL#DhˆOìTfªÄ/U©3·ÃvÌz_2q2;Ìs‰æ ÿyB’'>†¼9¥üm'3¬N>´¿yg¡¼&~η…^:ùÉô Üÿ§\ð°]¼';YòŸõDߢoÛeàîÀaXÄw=þG‹1±±ËÄQ?eM "7.ªHê˜+ÆàË#8G½r‰ÚI#›7,1y¬¿_¸S|8¾%ÊÚR¦3M /'&g¶ø^ÿ¥€v5s-9æäZùµ¸óÑY?tÆKúµ³"éçÒaœ–÷Î*LI ¹8¼à§û:] œéòÈæ7?š Ðì é$®.}3ú× “4T¯¯}Q8nCCªÐÎÑg™(6Œ0L´“ÙA5< Š”2|}Ó ã{]¿¬ ¼ Ëˆ¨§N>Y¦µø¢üpp>Ò¥ô6ü“”¿N$ "è˜jÓúŒ„4xÔ»ôÏ,G¿ž°@örâÚTAåy÷ÑhåÇuŠ›¢Ø£8˜=ß½oªÊ`‡.•‹b|pa˘üsä¡Ì>‡3)W ›ï‚ÃW±±¬ð,X_7—@ÚEÙ7Á1s¬§£ÓªøìÙ±‘3+}6t·ÌÉžåþ{6™meíI¸8·%9t øïõWî†'nØÕÑ?Ê€ÿ¿Æ3Y%÷éþßË5«*FîPÅÝxp^ÏÊ7v ‹c&}.k°ä'‡Ûô Î^™é¼Œ[àŽä÷Ëp øâ«3 Ğݞ&í¯%"ƒ¹r°•§´¥¿tE… óÌ1v‡VÒ kÆ¿ëœi>9í•£úEýÅŒh´W'QJ°xK­Á:úV Ós“(i9gw‚gÔQ“ËðÌE}D%_9ÔK(‡sSÞM:™öظÖ|m}~¹Šsiyƒ€ Fp¿1fÑf¶ïô¤~ÒA?‚  éSUp?`i¸œUå!ÃÿŒkêË ‹[ªàé*7CÒ¨³-~t¦D\–áeVuËFmÏÔˆÕÇŠ¯¼ñmÄsfµ(ê@f¦l7ÔÝ×$‹YÕÀd³Ç3ë°ºÊhä÷Eëà ¡ÒScg±I?jtßs_Ä®×Im”«)Ò5b(ÍÞ„H®ò¡ ÁhÔýj’ÐiÉèw¡Dkpg(‘ÂÁû •#ê4Mi0íDŠ&ymlN(fŒPÔʹõBlض*üýÒÆÀ:kýøN±ö°æ}Pû"1e¤@Bw¤‰9ŽÙŽp©Ç†N—£Býzð÷{£|DìYÏíð9Üô¨ïz¶»„þΤ*¯Ð§øÒxNìÏw›\Q$íIOX ·úîbWªð(˜Qî‘ZŸ ,4!ªµÉû³=PYE_?¡…ùKOßC̦èµéÝø)Rõ˜|üâô5À4»¥ì,Vg3…æÒ¾â)°ßöÓ=œŸŒ{´^Tû[ð4Ñ-´K›Yì¬|¨ùì§3•²õ8vWM×ÓMW ?l¡ÆÔ‹X|ùÑ\ÔºAŒ¸év7Ò0¤†½!̇·7#2 I`ŽãRg×ÝûH1væ‘ç î1÷l÷”5ª"­ñF÷û+ôŒ0Æ Š¥ Ì—%V5ä)¬OOcf?4ÿ¬ \Xs'3gî:'Zb2´6·~€T-¼ŽjôfŒ®,[M¤ú]I}o+WÖ«Æ/À !¥ŸL ­†ó:á¬Iýv²ª»²Fê6c 3½HÈ)Ý`E“¢#Œ@5‹Ôˆ/¥×JÇ0¿»'R»—jꪯ6¶WJ €·˜ õº›JÞÛ5ˆŽÈ¦™døÃ ^—+e‰ÅÇn(æ¸>þ¤=ÎË0Ç•ùÇSÍó‡zö *eïxþJ—önôp 8Ø4ŒÂÂjUóœÊÎÌ~(Ó[X¸™Bž™ØMÔ‰ñhšê…:£"« tjÄþ¢ùX×+äî!•â‚0d[«ÅM¥"¢k7‘OºŒj¡CʼÎQ<®`"DÅ€+c‖צʃlZ ̆/6%Ø–Äõ–üÃâ¯HlÄ«Jóx×Â9D’õœ.lS*è—óLJj³ V+0åŠ Û¨üĨ®Ê׌ ‰:RŒT:ÚRÓSgûÀb^oÚØD5­ˆUMoÔm’‹2kfodJûû…wïˆjšq™Hˆñ&ªŽ§üL ,ÿ Öl€kMiN»´íˆ •4ßÈÈ£d0³5c+ƒj Æ\^T÷íX©FŽ+Ž.Qöˆ±™6 7óJ‚ Žï̤¥ ~`!Pq•’*´7GS±%R‚Ë^±ÁžY… ‘ùMƒÂ¶áUÝÄú²¢÷(åx¤R'Ÿ^Ææ¬ ¯}¢°Ï˜Vݲ ²†¨WŠ#YB$š««|«Îì`V‰”%ˆL5>Ø<´U÷’–c­âÙÃö¤®r漏¾ÃÞ %?+¼ Ï)ÙþSàlÚK}J›mHÙdÐ_€šn#¦â‰tQ~€”Ÿ3øÚk õËSœÃÎm¬õA;ªÏ­"tMaà o ¸†¿*X:y´V·PC²‹nÞÇaÅžÜ-Ñ–€'dƒÞÛ4 cw"vEcë¡€a¢yˆ;1“ÅH£˜¯v?üàŽCÂ|ûw†`ã?Þg³ì1GPý†Öcoªð»Ü®-ä_WŽÂü`Öh‘ÑÎf×j¼ZðÇ!>"õË3¾ãÙÅ­Ã^EfbŽõ‰æáÞÙðïb1þðƒŠ°ôøÑ¦XŸRé"=Ñ’àÆwøÉæ˜í—\2-9GXãE&möª*ÙH½Ñü$ €­<ҽ϶­¹Àóášïüxÿò-ßtj¬È», Aˆ˜HÒÛÁ´Ø{úu¶Üú„‡|‘Ð ÙÖhVe¶Éäñ$ýãõ’úžÖº$|¼¼‹ßòÉçxF9’"J¤ú0~Öå»A“jÇŠG2 övF˾ÀëLJVz‚ Ó ÕoËÃ\:È´ooj6 šòÁ€°ŠŒ:º@X¢‰ö_d[è=D„Ï.6þâTgÙ3óPí­µ¿"»¤à/Ž{Ð 6SÞµKu"TYf†k¯áÃaÕFS[õ´B3å}aasµî9ÊPŠe3[Ü6V×£ÁûYrØ–È¡5¨©œ/µ4§½Š¬i¤«¼TòÏ^ëÅ"?î5 ѹŸ®2¿í¼ˆ!Âm#"w´7Z;‘”„Ê#äçæ&s#󨀉§0ôÒºšE·bfíI½¤ÇN]ÎìòÓÃJ–:Œ\^èiåž?Ó0CWÍOF_tW½ÄJA9öKŽæø;žiÓ½èCÆ jÓà¾Æ¹‚ÇÐ¥„ýúg؜䘸R:Ý*Y­9ü¶/ÞÝDGQíd†Øa[¢ tP\™‰$F%XÉïy†ÁB[\4d¡Fô";tÊúæùgó¥_H/©CGõ´EZ´¿yß—«Žd‹ýˆÙÓÕ¡Ãñ—)枪®¶eZÚ…"¨~ÄP¶RóØ1_ž@5 f]©m$Ñâ®F1Ké•yŸŽÈ¥sKÜŽìå± ¾uKfüqdm-O]»&î~á‰ô$ày3j#¦ÅúbâѲ„€ì“Ìæ@$º"~W"SÓQ%ù^_!K&Öà&yreµ{à Mü±kAÁ,ÀXI÷œD™ïG tXÍ0ØüÑ u¸µŸ÷Ÿ¤é2ÜAÞ“´Ž~ÏðÅG/à´\ízkê< aG•GÊ0¶ÛRM´Æ+Œ ³%ý"üY÷žæèýŽäu2'¢Å>0 ¯»I©Ç®§„‚Vžjí2ÃÌ—EXÏï×§Š *u<ÜL0iÁÕR&«„w G 9â‘—¼_oåìIÚªù îMÏr]KÝÎf’²Ði”`TtZçu( ÇÅçídr³q£‹ÅsdЩÄÝ'JµDów™:ѬOd ´ê!›"Óߘýx¨6¼Þ»Ó×6Þ~Äwd×M%€ }bXˆ1¬ ë#Æ ræ]d‹s*ÈŽÿ‡„KâSÓÕ&_¨þÊüü@Ì\p#DçÆºýâ+*— ¾]k8Ü^àýFGsŽ[¬ñäP£PÛWê#Ì-Õrcï«Îܰx¸µ_³ÈKn|92i6Ó0_W¢‡83¦ù¤E`gÔ!èÂëw*Áí±¡É’„š#ïcß‘ÌjC¨×HYš]%u?Ínývv5ä7TŸ¡ŽŠüQ€k€xŽ©45ÕÎм/—.íúg1%~voxbo-1.8.5~svn1246/brainBrowser/region_relation.db000066400000000000000000003400001153177201300222470ustar00rootroot00000000000000b1 @ ……•’e ÿWŽÞÚ˜Œ(g|&ékù®>Ôc ³‡XžwÕI*2( nb'{Pi¼KÕ6· z:0mBüWɵ–œ¯c;XŠS¸²¯Â'„8ÎA€Z³øTÄî ȾQ˜ªM>}âø­J6<ËáɶãÄôK§3âQeùs0¨j—àvDQ{B9 ®»óúÉèÓÆ“npâe÷ÊìÜ[qbÌ׬ùr:"°'j cqW¥¡óŽz‹tÊ(«¸•†Pús$ŽLÌ*¯XM3¤h±AýçwÉô˜Ñº?&9ª«<9|©ÃÙõ&j{? 68d¦ËŠùÅÝÛ¡ŽB*d)¯úÕä&^yhŒ Ö7÷¤sÊÔeu$±(6mTŠ|8s3ãÀ]Ægñ'ÂÇÏVÃ9ð¨`Yp6A` _(AUÏg—Î=胜A ªeÍøÝ¼”…K³QM ×}Yü¾g~ëRv›‰OÓgpÁ’Sž\žèz$Œ{WÍ¡NVKüïabgæ«t 2§l×ï»ë9£¯^ª<œ¡”0O ÕO3×Çt(ÂôT8ü{²Ï‘@WãðÆØfU‘o*3´?f¥‹¿¼±{/ɽ;J¾z-›FÍçI«fò ›<ŽìË5PÛNC‹¯ïC6ž¬˜\MÅjð¦çkP~¾4I~Že™ód7$?$¾DHFœ‰ø»‘b·§òüÙ'f¤— ×fZ,;q?jåo¡«}ypk¡ «š’4 WáÍ‘}l‘·»Ùj@€VöÁ§~¢G=ÃP ó*Š2*£ jy‹M8œÖïhA°¤6¦q/ëúñU¡{´€¡i.ùÚÎVÄùÉå¨ÙÔ|ÃMÙpk´ú;燧ÕA #Çθa)‘»¶kRÛ«3z#1®=¨,ªëâ¬eÙ⪑RF^ éfµøDÓ×=‹V8› oVn1ªª“ñ¾ŠÍŽëÍ!™ÇÊž‡Bü--ö!OííSâÀ+DºðtÂd–(NÊ;Ó„ëtnrç¬_²Šßì§ø®“áÎ6,ßÄæž~•Ž‹”×ðÂä ªÏ>©;J`Q;Ü&>0[ð«Ç–Õ‰ìç°â0'9ÑLÃ3Ð=ªA+bâ¼ h Œw¤-—bnKrø•:ÁK^°–á)>WïFWýA¨¡ÚŒdËÖKG@Á?1Áí&Ê|¡`:š¢ÄJ~ŽÒy3-ÒÜžÄå(ˆæG|M¨xbTwºv¿¼&oãÅ178¨AÿÊ«!Kس[aq¤¨°‘ö3^…}.æŠR!Ïô±ìHº% ÒÎÃ`û<ê?®¿ÚFGŠâ›žÇTW²}?.ñ1Fè¸c´¼[™i¢á‡Òq5ìv;óÊô”¬®ÀŠfè†-Š i*XãÿÑKÃ}rw¨Î;RzáóGß\ã›SNBq.¡GùÀœlö€:Æ·Öbâ„®{~DZ3(33~dïÊ^°ƒ"A;4…ó%EÔÛçÂÁ€hSµé¥îL¨ÓX,æ ôŸ¡ºfdÿ+@ü ›¦gsW]3´º-²îhA{Ö›ÆÈl\jÝ FÇS\® TMȵ;²Ëoñ›rP4z´I} 9Eý[6†æÔ͵¡¦ÁïƒJ’|E‡?/Ö`PD¡½íLÕÖ°„}Û‡ðë¶æ(,ù—¨)ý0P]nÉü,ä6t “IËÇè8´Ôœ•¦#¦Ì°(ƒ!°xÙˆˆTxX˜„7äaé˜SÝüÃD1žŠg³"±Kà†m·úS¼Ò³ÖëZŸoUa „ŸÁãSûÃÞ$*w%s¿ð*–'°Ððk™ïlxiÙŠ ;±@rÔþÂoxÏ0-Š<ßßm"ÖÍy ñŸ±¥<¼ûEòKæØ¬Íb €ݘ¦SRÕò’û®v€oè¼£JG¯Z9QD?ž‘×Y¬&ɪmhúË*XÄ·‰s=¤ÈU^©ßÌ´µ±rØøÐ Œ³8ç–jˆ1ŒQGÂ1[Z¦bÄ÷oüÚ1•p pR§Ôû/¬P¯ç6èϽ¹²]4T0“(²¢X A® 6UõÂJ@ð2ß`;ÆÁõ[jX` ¯/Y™A8Ô~0Š3=fïXçc™T¯{ZŒ“ âˆXé@±Y—øÔÛ®2 Õ\6á?u0ŠÂbݨgâ|^]Q"™š™°iûÄzË8§JEÇr|íÐéÎŽ ‡ë=<{µcÞ9ª¬†Ã ¤ùë©“ÈŠEÔ°¢ôp=ycDõçDˆ†,«¹W÷l§‰Ä×ë¿{®/ß&მ÷|Q²>=:NNv£ŸGÀL ˆv˜–eÙ.OA‘ò!0”xë8nÐö?Éè‘Ä„0§%›™À:ͲlET¦@·Æ9ÛÙ@¢÷3ç­Ó»×.€wfÏ#—=ôƒ¿Ë˜VIÍöÛ Åê뚃”L¡ïúæ²K¨¨Òeºî—i¡âQË—?¶‹¼d’Wüiñ5ýÙÝWNT²}19lCæ¤ÅGË$.…Ir,~Û™^æ§jLlû¡VÈd7mJŠøK+œöRUä?(¦”¿«‹D÷ûØü‰ßq£Ö<_³öþ¶/©­žÿÿ³ˆžGÁ9Rp"ÍdåÉùcpâ¸Úº†Pœœassª†.ùŠyì (­ˆlœíœü©œî-à…1™÷Žß¿Ôn?÷ ws_qÌ·›à×Y2¼º²pHŒg…ä[(U,¾â#ªx È\Wü;±<þiYµÉÔû~‘´™Lt&4¨k¬qSRci‚ëýøºZ|,¼XÜÒ„¸É¤DÊÕzÕuëY|®µ55¨IÑM` AuÍ ¼yã|¶õæodÑ"dð©†iã™Ê§U§¶~Q"£ ÁSV°<ÏéŒW»2žÐy-Ÿ}¹Í!,P #&/v.´¼$-Åâõ©5‡Ž núŸ·Òè¢Ñ>eÂq½ÓÛvpß!®fñ·g)NÂ7 À €I—éÿOmMº¾e%¸PwÀÀ—4AKd8ñ^ÞÒjꪜχGí4F¸LHž÷GzÓhì]íGòc‡]ôPW¤Æ“›$úºF 0ØjÀ…¡“ZŸ÷${#©2«™¥0fsÆËRdkK˜dТ}»¿ïGãä 3¼šTžEîcßt»<-ÎýØ‘ë.†ÙAy+¿ýLkc¯Þý–=^F؈ìÑ‘¡®žøTž¶Z…cpÁëÇå”d.Ä!o š "ܼTlNÈ¡³½‡QŸ  4´!Æ È4Ýf[¶uŸ”€zÂ"!˜R“æMò#G²Le©ý.Ù]a/ÄïUѵ÷ÎêB‰)5G«2b Œú"‡~uñò:‚²»4™Ã«mnûüê±äf.Y¯yIgôë¹;¦,ÓÜ;þ/~ÈÊÅö¹ü½á[¢í8‹½‘g£7ÖÀd×P‘èæÌ—L\–(Ф„ Ùq®Ï¦Z½õe#Ñìøè0Td¼åD 4ô›,¦sU¶ŸJ6²~3IaL˜~(Ö= EŽZV¥ŒçHvÂh%8{œ>™Ø=¦P“m³w+1¥ê¨I‘”ýºÛ—%Ä y Û!OªyÅ’àÆÛa‘½Ás2½?3¶Ë°±Â òV„Z³L(à:DÀ7Q+PQü·6¼÷\k§ióCZªH´ºÇxpCyƒ]¥Í´¿` ¬ùQæCv¾HçLBMËjô;IœÄé£MÞÈoÿá´ëo¬Ð‹ gë—~çzÃ Š¾¬I\¾¢~ÛŠ¦]-òøÃÜcŸÅõÎÃÿ‰© ܃˜î©À17¿˜d8O÷´×Iå55ÈݱH–BŠžÅƒH†ý}òa§CÀòÇøÝIû›Œ÷ã^åp¬Zµõz’é·û&SmSPEî¥ÎˆÃÐE@Z¯ä±‘ñz¢Õ!JG2¶‘²£rkÃÔí«0‹üûR«³Š°/Ò1j–Q ÷k€Y¯´èÎ÷Pšð¦1çMözm·.<Æíš¬•*m” Hëfqé}ƞςéhK!W÷ùe"àFUþñJ¥ÐhplÜb…x¿È ÌÁ¬¦Ga@éN \÷ÄçËÜdÿe¼ŸÇc¹õi‘Œ´ðÓ}hÒà4«¢š§–Šð˜¢{ ÍˆVÉ‚Á›ŸmäÞ1`êc.öWM"þ Š#ûéH¡ë‰‚ÏZWÖû†nØ=¿éëJ`£¦¼ÈðãY†;·)ៃãæÄfŸ üÙ>´¨MŒeŒÜw#«ZÚÑEÜK”‡¾îD*–1QŸTžzïõ—vP¦ŸôÒS6§ŽÌœmŸ6”p˜ —>HV¤ŠÂv»tÇ\=pbµäŸ×®¶Ûñ’{^¼%G¾œµ”¡Nè½f—u8É„-y¿Ï±ÚåTÔvÁQĺ6ŒJü1ÀDŽTNȉ&I@Åvý$#lú„ÓäŒÀ­¬Gs‘FëX?¼ÿnåÅ©;ljªÞT8ú'ˤ«éQéÇå˜PÈ ŽôH`–cÄ9÷Ì’ ú–íÏ?“Í"L<ûoÁ2 ŽˆÊ:xkõ*õs1™Jð-‘wyÕ€ ôjÝòÚ”ÿöÏ7eC±>\øhA8‘ŽžŸ½Î1ÜYìˆñ9‚$Â7ËïMJ)ubîžõjBpþJÊEÉÈÂ8Ú¢ìÏ·¡ÇÍtr ¢õ°6øöo–äžeöÐWÈQB}Á½>îÌsÍX™+%”>yCºH;¦ÎÞ­×2æ…‹V¦1Xум,@ 0+{s1Ø´á/Ȱ^XÓ›¶+_9µL`½³j×úŠECÅ À9æÊš£þÈ”„ÉHηɧ@ƒô³‹Þoy>¤2aÐ#؃­­ýìSëñƒb7åt îù—|ÅåÃrÙY©¦v>(Ö„Û $°Ž¶Ž/WF˜ëßîh²>pDíþŒ(N˜éCêj8gÿe@îú€‘ÁOÆÄ­…†i'¹3çA#O¾x®_j‘1U_WEÞyõàIî˳vºÎ;Í ‚ºjÀÞ6ˆ¶ðÞP÷þ¼%œ·j¦R}þ†ÕA³E ©ÖÔ¸Aó^o2o¾…ã ƒ§«¢füT…Ì‹›çxòùÀÖF+þÌ6'`a“ئ«gÝwÔMÕ'ÇåM´ ÿ|o.½b•QàóuA§Q½4ÄØ‚¦f°âìÉêìM¨»œÏTĩйŽEIŽ¡y¯6‚ª÷ïp-Ḏ 4ºܼӀF&Æ”síÆ×BsXÏ\Ç„R}•g«§Y—=´];ÛAk·£~„ »…² DGHm½ƒO¦¾>­ÿÞ]ƒ/þh~ã÷ˆîåYÿ)ÿ4eµV¯}.ÛÝ­+Ö4À»)CÞvéÒh0¡¶æ4Ú $5=%«L¾Î±§#ºÚÙƒ|êin(S:M2±mn€ùüƒC2kÑ8p<ôJÜ”xò·®Ï%”¬÷u†›ÒJ´ƒÿ KNŤHeqO•©ÆWxüa8%{cOò5,e†E‰!3#ö£ŽÏØFõ4µS­q %ºÁa­¥¡Ú¶{¹$PiþƒÜµÃ·’!ëÌ9 ‘v¨IáÈ&!Ã{@³Úd%‘ª/0 *¸‘¨04×Ñ.÷Œ¿Fg; /•Åm"zÒN™eÆ=m~üЃ®ƒšzÖ̃xNHÕ•©ze{nBL;çhïçÜ`Q+ª@/«^pv5Ø‘+Jpô h÷œofWÖ\ZÖeX·¨¡™ìíE+ŸÈ'ü7,HÚÎ^¢ýíWlý|ˆ±é#_³f²GEs¨Zû.ÕCÑÍi›x¾rBNŸÍ>¨²/skË*ï£Â•·À…纸=h4ZGoe/b±ãTr •Z9ôQQwsÎ\ú+˜q¶dÌáÛ£ OÞÀÿu:\ޤ<óÙH/€+“BÀn9hNí¼Ö„y1Õ(L’52ûú¿"ç<|çÕ… lSE)8ÜSe«ä£ì¿Þ‡Â¥@qVÕrÑ•HIH—£®õ©¼­ßêb> ú÷¹Ú+…J*O'=S+\ ÑÏTÔ §†S9Oëð¦oŒ<©ªØ„il"ì?‘¬q;¸xšIÍdl×kRïp“TÖ N†y®…›K>zð&¢Fý×ÌÙ7àÍÜãËo{9ëœSirºÆ‰ÝA(ꓹ¹Ã @;üúoY)^yúÛ„,ѧàÂXЖÕì˜qæ¡ ?ÌêøXKÕ*$ä[ c اVØlž(S4µØjní_܉ðQÞ_>‚l&þǽ.TÇè¾nˆdq¢ØbzTT7=Ó¾ïÚqgÁïœp8Ù²ŲĉÚ?G‰pª§j ˆÇ›yÄëDð¤šKé)ƒÜ„Œ3¿ªv˜­;ÂìHDkLH£œå-6¸pÈK,1‚5íwuéo°¿†GïíØÇl-b©Šëi'S”åXòµÃx"óÀ¼$ïKÑ!-2y[Ë®IA§3sý˵£GÍÚõÏaö¹b:g ý¢‹½l KË„×ÀCø‚©¾Yò€›Å WEC7–èÁ2}Nï²^†‹óŠè†x7³K¥_¦Ûs…¡$5¢ T\qÀ¨FäßbÓXS€Ç1MXWgõ¸þ›äëÀcÜx1¨íô¾¤ö¼ý=Lq1þMx•y9Xê°éݹÜX”28;è! 2j,³÷XiÆQü‰g’“¦³´avHZÞý…㌠ŒL=±óuh$…èô1¶=ž vÉ ú–Qºã°TyϾðo0L‘™e^dÓÏ~TˆWXSLÍ¿eIyÛ•Ý2Ý êN^lA.ªBG†5é„_kÆ‹jå‚”B«7ü˜JF¡ƒ–„h© PŸR×;Y²2`2•½ [tÃ4® Tú®c®¶‚¸Njø.$ÎÂQ …dN¡„0›ï‚Ô°Ê3—ט]†^MUÍT€i°O§¯sò\ût íÎ#ù)ézb'Ëžf:û£'lÔÊeó7_ø¸ËÕŸ)MbNí]ªGc‚„¥Ý²êÕìÐPeŸí)2Ÿ“³ÿ¶Øj1³ ·ö²Ê­A¾Fþn)h¾È@G¤|Ëà%~Ÿû¥ƒœeÏ5þa2½°Å~„pÇú˜øƒüY~WòùlòsÀcÛqËe:ã=o}¨b=‡ˆ!¡(³˜s¢i¸X-âG¬P‹Êg‡¢ý-~i7¥±=§Ú ÔS>¥Ì”¥pðøÏÖg’ï7X‡(±¡ï#¬?ònú‰ Z%§ÄãsæqŠ“að´ÂhßNªj¸“ýéïh¡ÑÑ5MDP¯z¶â”@ÅúR¯¢Œ PÐCÜeõÇ*q #õ¹ï‹ó#ÚbàCBÕ¬H3œŒ`˜ ­¡0*T«¼ €ÖCí©Ûª”Çf‘“¦§§ìCm½ª ®^Ÿ¡I”¶™™@Û/í©ÌІ{Ò¼ MsVÎO6·Ìif-V'J¿´}´Ó¹õÒ3c®Ð)­%Ê›¤pdC3ru3š¿"±<tÅVl<Ƭ…+Z¾ €Öã6¨Ö19L¢õTƇÝvŸR)–Åñé^gCè}Ñ(øÈÜ;äz¡rT|¦.ðóÿrMR)G«¶€ é•õbǵ{WˆþvÈôµG» »ÚÞŸ×yú *šïTíûÊÁã»V.;Wìô"´»~‘´MšF#õça\Åf½;‘Ô¢—jÂ/+IDY7Û×?X£çëJu%B¿þk bæ£8ÿ·DŽÖF·]µl—ŸµÌï©ý»ãJôJuì5>©1î°ZýÂÑ®_"¼Ú+K;óžLëáÑî’dÂöA¤ÑmuzbxÞ׿FfÑ+a3«™©bÁ%ëHטÿÚ{:Á‘¶ç1;j ÚÄ<æ© þÄiK[˜¸OsCË“íuà½ÐÄžvlìhL™ì_å‘F5o§ºà@ÍAÐò:Wó¶6:îÕÏÌÖÚ/ vGžJQ ‰]¤hK¨ün<œšm^R¸aNÓ^_Yk‘SKÑs”" ôïšóa3#º£iF8z‚°*߉”ñB«dƉ'Ö¨ ÔI<‹é/Ä4z>¶QCÿ~6ÏaCàUMm0•—!^'‚Ú%š¨MinVrãaRFHÇëÛºƒ^²÷¬§Aû04’øì1Áfâ¡ÆW>RDÔC`ÃB " ]½t0Ö¶±¥f'ñ®gÙ°[,ߥºyM¬!ŸÇAÈ 9C@ñçåzÝ0æNè9~ãp›L1B½ô¦ûæfrÑ ø=ƒua iy¢üèÄIn° òtOõ$”.QPzÅîõ/tÆM_mðV [ŠXñ¦ñÊY(žµ¹˜äÒk‰’ALL­b²c¿ŠZ‘·©·ÄŽrk‡Ç4´‘‚„™øÜÿÎ{Q»pUÚøþ&úšÝDÔ³í´Žî´))!¹³>g¨û·k V3Ñ~ÆË£€ç5i¾ «qðlÞB§€šôÖ©èÆOp«Š‹FFÝ›mÌiíS(Oz µüG`RÛCDŠ\¾à¸·E¬!×/k ö)•A ü—ºžj¿EäœWo¯ÅÀVÔ°€0ë™"|Êj¬0Ñ[ç §“ö”«Íbt„&ÒߺÒïTª: ™Å</ê"«]¬Y?Øy}EÙ{–ýÂRè[ü3Fº½˜ìAz¿DÙÑË?¥¤‚R×ÃOâƒysÒ âsèUÄ©H,3ó P&]lø»µ%¨p3FÒwOBs*ä:8#(á†ñÒ†¸Û¯4ìÅù¸ÓE¿£QÛC”0þ1W‚‰SCll3ÿ~ o†6[ûvùSË}gT‰šé˜÷+_™¬E’§ä“zâsflÖÝÑøV×zE ìΈ8ò#¿ « \Œ<¿sê‘ZßÿUYòûIfc[[è<ÿýï€8Á§o\´=ÛÞÌeN?¸„úÙÿ·Ê_•HhGÝåó³|ÁöBÜ·mç3k9x†ã.ú%/É¥]#A , ?çœDU²SJK¿+©áT=¹>‚”wÌûå·2·Ý-;†Nè‘n»E“í¾aµÛPF>A2rºŠÙÞC¶ƒ «÷ì‚Ô2ÿ¼Þ‚¯B¡XM1³¬¾ W.‰ iªjã£Ú€ÖcS1×¼*QšzZ󛘿i\M½õEH*sKöî3Zbûúí õ ÇÌÑ-m^HR•¶Ñ×ÔÎ¥”B£.¾)§‰Î.{ÉV>òaü<¾×µµ¿È•ÇLUÐÂ…V+šNCúüûbDÚ†¡VeK‡ºò{ÁëâÈìÊhZ®.£ñý~©õŸýºuyiî&LÁ>ò¯zr;1©IêÁš‚UÍØõè+ýI^Ýšc$¨Ñ ³@zkV–eoÌgõwÔÂ2©q¨½»þÑw¢:6lýzl™Yœ÷EÀ…Gެt¥|m¥Ù‰5÷X;*{Z!²mnÊñvæ+Æ,3³/¤Áæ!Óqw»ç2ˆý8SÉF÷i"U® QÒzè—ß¼S~¯œ-õÉ’uãE%†¨ÄÄïõNZðyÙ®Â(‘­u{F"3÷ñ‡¦´×pÒ¼ PµÞ·i`À Z=¿Ñ›£A·ï–pÐn©Æ °ª¶Ë©+žÑ˜9H€tõ¢8»šWw'nûïQµfXo3Þúå²Ú›PU“Ô³l¾Ÿ³ßüP³`à=8›zLn|d”m©VCíGGœG'R× UüAiip}Nø88–V®µÃ9úŽê¡b;+e•tl4i­‹iÑpI+dðÑ!W4¿›âïñk{´…ˆŽì¾zf¶‹í'=~ý¨†;/öºc5Cb¹ÿ3±ò8À#ŒK:kX•q«e"˜®¨ÎUª@‚ºl–œ:Ü~xœ®É½Sñ¬'&RB¬ÖŒ EþOSÒsëêRÂË—u™\¼7Š’5†^ EdÅ( &ý´é×r!jx÷z/¤U XhÑêI"Ù'ÇÎV×üÌ:ÇÒnLæÄXkt>ÿq•‘#J+À7­qžÎþB ‰±Iò»ïØi2#ÏjÝQ~Š (ç ^:RU-é³ÕWS}`®Ï-좈¿Ô¹.œU´÷Fá5BpÉ–}€0“6Õ1/s²ýÒžóͦe^©"Å„W4 ²ùÍ~§Ú‡{` œg±G¿þÝ·fF?ø—ºéI_ÉS7е›qà'úä…2?o×Ê™’ãÊ3N.\ú؇źðÖ‚ÎŽéI1—ÛŒÒÚx#™ ÒUItÑF(ÒQ›E‘Æ`8øá``@¯Î3M âòÅŠÇïþž'©¯¤RPï0ïo ÇË¡:O¦Ì#}9q/Lï5õ[Ùð±Ì› l%KÄOlâ¾!üôƒ_å࣮ëù†êÇ|+‘):"5Ÿ¿T—*ØFÞ†) ŒÏK÷+WKÉAö+ ªjdÌ1¯Ë¬nUNã‹z‹(D–ý=‰Ûq•–™²±ÀA[QîUÓ=ÏFŅÚ#\h„¸ÌÕ{ —%ý¹d–d îè ‹Nùchf{Žm£ÌsÿIÃÊò÷®Ý¬4áZšºzЄ¡é$¥dÓÕª¤,7·t…F§:³öòÔõ”óz;(¼X4Uò ;ÛÜÔóyà]E@£ef‚LöŒD”¥³"{MÓÀ1ôyC¶•Áé Êí¯œÆ!´møñ¸¦H‘µÇKKˆ©¥yÎŒéß’¶[éhnÓ'_ý’–o”ÖF6w+A³•Bµ¹Ñó}´“ÖŠ­¸®ÏßåP:æ{ã‚‘Z}?vAzî_ò`5{ïÜØÁ¶¿÷ÇÎvšßÑÊaRR®1ßÜEjFiçÚ¢} °ÊÿÀž"g<Ûm¬ÈkË(­¸¦e¼/Ã"ŒPÜÏ¥#ih:qˆ—p¯´Ég\S zNÊÏ‚½ÅBßøW;ÝaÞ 7.ÿ(*‚Õa››M:bAmÝÃÛ¬åoùQ_ep>«â˜gD§^PQ8Ð〈ÆqtUæ¡.xM” ª‰WöølÙP¸ýPýök¿®Õ/€ˆ©œòé 6!Úû§êßÊ㪉¦¨îÝû'Ác—÷VþêL÷÷¯XÅÁküæ •,·¸×æ9ÓrÊ–÷Ý+4¤†ÊˆHý`Ç̆[°MªÞ†‡X׿1­FÅ 9Ç£Œ4 ¤v'¿1;[¿ùmÛ-d‰H²4Ñ zS„°«½ŒÜ+ó½,v ¢¬|_*…uq{ÕäVJò_\‹Œf2 ²׃{¹G‡™Jk°.-ØŠlùËzö³­Ì³=\½fúê )FÐ5yŠ6Ø=·š´Ø-UØ%±­¼(Çñæÿf@ƒ“wÇNABÏV Þ´o]k™0§R©”1d½˜ã)kç9~”YLÉ\d4Ž×‘³{é8lÃXi섳Pò¹RŽ¿>U²[ ÿ¥ò¢­C„o«›0T̃õ‘1Éú•Î{Д…˜DJò’)q‘ƒŸÀ‘êÜS—-2£}>Á[ÌH7©ŒêBÍŽSØ-2:þù¼ïˆXĆ^%ÊcÄazýSHëwd’‹úÏ=1¬l°ª‰âÏÁŸvœËEù×NØâ|ª«ÑôqA%(£ŽÐÏvñÌ ÷3°ˆf§VM ‡‚Ö†PžC<ϱøðÒà üé})HV6‹2X%M4~ Œ×nõ8:™! ‹ÇQ̶kû“‚8±Û©Ì»W 4eŽ/¾YÉøkŠƒEôÃޛȚàf¡:¹4uÁålnþ-.ô£/6*’ñPñ*ÓwT$·ÀaÕbà/C“Dç™Ònn×FÁ8ÜÇÞ¦^,Ú©¤Ÿâ“z®Œ†úª‡=¨û«ðú˜ŸUØU1´ûÝà^¢…#GktÞ=÷%ƒf“ëÝjLˆ·Xó<öŠÒp$a†”½ç'ˆ~5]Vÿ’ÛÞ˜ª8ý+]4)?\Xø% ØñRÏŠ ¾…Êgz0’P÷oÕÎrðXÕždxý‹_àfM-Ÿ!íCÉ0ždpÿÔ¬îB>ƒß‘`ËØ`+Jž,rUѧr¤zöó2#ñBfÂmðáz#á ÄÔ‘YiÅ*Š%Ò,ëŽ1‹ EõÏêr5®|þ,Ë!Í0¹õ1ÊL0¾öCßoµ(•B¬Ë3›ÅÌaøS¤«2ÏÀ¹~3„ˆŠGÕîf&BjIÑrˆ¾ ø”jË­ôÄ\(G£(òÚ®÷ÆÁV¡"`ö%ScjïáP$$Æiùtè¬ßCå†ÂÐ\¥D[ð»@5úõÝ“Kú ™l+¹ÓS'Ö›ï6 êðö¼ÐU…(5¥ë÷Ïeä.5èÍòAÝ«K¯Ÿ lB žèÚ0&Å‘ÁGÆÎVG~X¡ƒ)`¶x‰õt(NJK]ú¨sþ«ÃÙQ¸òÆa ½*Ò…ŠµšÊ®ªó` r/õE„ ©¸µïéFEæK‡Äþ÷+áYCCbc¾Od¢{›_çóz ¬§×ˆè›ÚÏ#ÂmHAê ç‹`À͵.Ë5šelk6…³ÎTÀÃb/ 4êåXos+!Åã"°VÈ÷^R{Škó¦ßLæ¤gòLÈsšÕ¬É¢£ë¼»µ›UÛð×õÉ C°ñQ‚ÞÈ/{`RK¶}ÒLçÞpm~<äÿ½;#•G8‰qGp™ÑJ¼.®G›t¨õ±óý¬ýWÍfA!àëKÀüÌ,‰kC‰^#óus©Nf{ nÎFwˆ´–zB1¸z Ò Gê«×û >f«‹ ‰,p>ˆ"JCØû6E9ŸÈ|Oè;4Ò*þFíO”°õ¦LTr¯$÷3žàI9~&ݲí7ˆŽ\Ô3£ŒyÍasòÚ‚-·j»-ÖÌÂ^XÜ´É#¥SÜa0AÛZkÀë[´ð¼7|›c—Þð­BUšÁüšñf\ˆ;UÖKd0š½æÖâ$ìF î†‹«ñðJ—ôšx„ÁCð ;P„%áa=h’2ÉX›Rœ‰X´vGt3{Ñß=%d ¥¾è]wR×Dø#úÛNUPpyàßÑÜ«`–ñäz/¥/ŒÅº:òÆN`À`º.,› È ”[âÉéf[‰˜;Kd"ÄÄÒd¦†½ÖphŠ™Bä»Df † 9"½i¼Ë°îŸ- ·ˆ*Î3à±ê-É?ê1sËÒ=!¸ÃÁr¿¶Ì&RÞѺ¶™Šš‘‹ïmWš¤2á\_Åt äº‡Þ%õ_£~qAÀ".N~Z%+Úo0„¡}מYåÞኒ:ÔGm)M¥^­îzÞ*y }·A/†€Äxz,zÓºÙCiÇõR. .Ú¢[™{Íj4“(öG:7‘’+29+^ÞôÚ´ÙILª¯/1eòÄIa%ïKÙ8<å'8Bu¹ÌŠL^†?%=¡¼¬Ç³¿ k¸bY«ã,×Û@1‹u`€ž—±;«Jw£s.¥ÅæµÐºÞËú}ÊJüý+OS®I½à0;"ãP_ñ+n¨þ$NYÿšˆèšÝZ?u(}6ê‹§s.[. 7c•µÏM÷×R¿o¤†„#a¢¶ÁÈ¢è«n1ü—õ ÌxØù(%ð(ºûÌ["|½õEŽ–ÅÑU+Úúÿ«A%PGØ““׳¼Ìêáò±ZÀÉÃgÁó*l Ѳ“d3þˆctƒh­ªÏLu6õ¾À;}8GD£}´*) {¿­ÂÂÄtYê·4ù}è­ààKxCFxÅ¡&ãRYÅ· ¥ZãŽ&]ž¾GS —­@üú§“cHÅ;Þ}^{ø&öêCŒËÒKP߇¯è+``·€Æ Q†>ó†‘ê2K¦—3æðY]1§]×ìºËxkÜÔÁ+à}Ñw ".-Ij<UÜt¡Å*„ÇÃ*ÙõVÆ} Kßb¥ZôܲÜÖv'ÕïýÿeƒOÏ„Ïp- ÞáªK„ƒâ5N«*˜LiµÑô¨r~Ì>"Š*Ó;ü%„¼Ü$¸Ãü«a YéßÉü‡÷Ýsƒ aÑ2Y6ô]ï[S¯ållœ"OBek[þçΔ\·C •ÑzÜ‘ûÊa-bOI–§9Z¤Æ4$ô~:I÷d½z|Zñî–Qåààñ0Ž£–Ž#š÷zóÏw¦÷âQ$çyû$ªòÐ%=ºn­ö­•ðâÈÛyddi÷>ƒ²Ÿón…ž ŠiGì›÷ :²$ŽN†„µ$'yaÚ Ø}±ád:¬Ñ/º„0{«CÒ8*5ù¯ˆ±ã15kZ?*Þ4_&ߺÂQ\åQbraÎé{†qï!´Ýn/ë“l ý)áÂßRv¢ 5&’g˜ÄýéÁ Ð¼ÊÆíQª³—þ×Ç«jÕVÊŠÙ¼"Ä­¡Ã\4µ”Ž3¿þ­OÐ$÷ˆGúI§pAD߸ô>Ó•Ü]ȼ*Tѱ… µÊÔ±FÅ#o7ñX_¿5®€Œ8XÀ~rPâƒ93å9P)„gy±«ÔUkÞ½„˜ñ®áG5ñ¿BøÏ‘–kËòj¼tÇRΞƒôýà6ÒDŸ@wZ(¤/ÈŇ£5_x‹¸geÆ%qþ-“qÓá\|›³ý|ô**í/¦ÊàAî—Q½Äm ž„?ìk%Цý 0yÿ”³ Ž'tœ<¼ô‡/…λËÞEX¶û?Ÿå(¿–…”9 ºš"pêGo31ÿ«!ôúT4‰ˆôšålŽKÏ~ ˆÕüB_"„ÓLhº0¦k É/ô¸tFÓ-4Ò…G*¬‹öØ*[à“vÉìuÌϳŽ9hÚt§FJ¢M}…¼kï¾N)Ý\€Ð+Mœ-ÿ’{/†y‰ ©†ËÃà0|,×E5ã7J¢|»Èˆ±ï̽θp‚á^Ú;~sÁò|{Ý×ùÞ"2¨rhª®±±Ê?B²+OÈÛt>°_+E˜—ïJ C)s…˜Š4f@VŸœùT3Û|MqP)®ï¯ò™öéÞFý†% Ã9(O×û‚ O@ø/ŠMbo¼Ä$ÓÔ2‘8ÆÞÐ ‹©øóñûÀïLOúº}ò}±ÈNϦ®} Á¦wÚͼ–6U%!Ó2œ† W“zM2ó°méýÈz榜Gf·ÚU\nJNâ` ys}Æ Æ .”}A¿{˜´æ_È|ýQJš ÉO^—Ç/U>Y‚: a+z©“´^®¹»“/ãk"¯©ºéÓÍ2Ye~Ssf5¶Ûcã0 (l ói«)4qéÀÏ· «ÔÒZ?­-´U&`–ðïE/ñ,ÛÊ|Ý…sàÀ;!îæ¸Ûˆä(ß]ftïåcN¢G⵬äiM@vÄ‚×OµÌ¶‹zŠˆWÑEŠÉ(d6X‚3Ð?w_ÿ/û3_ÐØ í‹\Ð+bןrõ7 :Åt ƒ¹¹‘q{|K|vÙš±Ÿ_‹ömZ¾çJÊ‘Dßëå›Pƒãäs].P2š`gãˆïD—}‘"\ä,¨‰9Û7.t)zÖ\ÖÏ®‰s‡\¬Î+ŸàY¢d Å-À–=S¦'f wÅ_¶ä%ëAØZ-9nÁº ä½™‰^‡PØ’ŠSؼð}1®›øuw8˜eùš«ÞßäÅE-ç»­¾7¶$Ÿ„tæBéj=ô*ÊÆÐ„¦¤N¹‘ïx»”-Ž·ifœ*O3†Iø ä±%ùQÆh@pÉÄ*ÛFÛøVL}š‰ º×~,®8°µvñ&- ä&S)5¦ ÃÿKMhg¸‘²`Ë•Ù]ï©Ü—Á*ÙÁÂ6lP†×W²Hó¿JÕ†¤ßY¢ËéÊŸÿ1Ó2¼$P^mP"xêתú4ØÞaÆV ÙÏ©7ÊÏ(D™Ç‰x±ü¢åd¶¸AsŠ™ŠÅÃØ“]FÁ˜½§‰QWgN%ÆÉ9fù°ÅyOò&¹ªb+à—Þo‹b¨O—r¸¹“ƒ尌ꈈvŽƒ]ÒKy ‚-пP‰^ÿ> Ÿ½+9’…‚ˆ9ò­Uyó äŒ–°:†ÒÙ»ž†È$ˆŠýµÏŽü‚TòcÁ‚Õ-âÐmRù­ ¿^Ü/*ûÇfÏÝ­vÛ$V#qègD À êÍQ±šW"«Dÿ|—èaW-d†_7´Mù?«Á1v;iY¯ÂäbýFfzƒi{À®Gí‡,‚.mê™VÜ2y™3g åÔ:Ô¸©ZWðÅó½åÙ§¨.A^øÑþ=†ìN¸NºK¶nPUø¸Fä°@¸ÖÖ]¶!«bܪ9»P®Z­S|JÞÌT!sdªÏžôÁØ•xžüV6,< À°ö¥ùq‰aMÖޏ…ݵDÒÍ¿: ©’Ò*½Œ*§'Žá£2!¬5R(Î.mby+¡e5÷ôÈ*UDÁh_“´ƒ…†¬àÞ'p­›;õÉ&pô—ú5¾6¶€ mQ9ÉsC g¯4ÞøÂ ª˜âÇèü3–M3”$qz¢²*)OX+úF|ÂU … ýKÁ|ž™¼ŸììBnùK“9‡q‰m<­„î)‹Ýy•ΡÖo¬¾³ÏåèÆmWOÑóì9oé%Ø—^ܪÉiŸ­” ÕÂd4£ %'FÿF˜IIùâÕå…“Ñdt™ôvjUá –®ÏðÖÖ²K=AùmWñ*@¡«t%3â?q ƒ©£EËô/gö£ª¢†·WÍoXŠÛ¤Ÿ™Ðí¶IëwãF´ˆüíÄåÑénørt€ÄIwpnï.úÜ&S´ûºùe«hQîþËôOÃìm·8'hÀ:4ÏFq¹ŠT£sÝÈèÁ‹öO ¡R °w‡¿l¯Ý,^<¡;!‹Grƒ4 ÂÜÀÔO:ç¤rÓfk 9ña6Xã¯T«¹ñ;9qó%i¤ñêƒ" ¥æèj²‚ùHb1ÊTnŒˆžÄ_ÛüQ8P3¨³À'œ.Ø!€8øy•1ûý¦XÙ´ûFƒ<…ù.ÓL­ùHwq(x_’›]¸lXóoüÊÉn¾ó_ÝÚäZ_…Í[—^îsÝÙEÎOb·±Ï”ÁHó!•Q´! ¥ðÏÐc Y‹¾ŽyaØ(B„<× 0¢OWÍ6¢]´åÕ3G‹?<†Ò¯móe~Û« ô™<Çy#Üû†~É$^"'B°»¨µg–ßüÆó@­U”¨ i ÝÔ”„Â5Âè=C*°ùãZ'[Äe—!ISAH™˜3dú}"¶„ºÑèÐmÁZUÛ Þ»ù–Çî!ìé®Ö./ÃШ4P9ïøL[éuf–7¬õ¡>·¾¸PãÚÓr¦%q›r§ÄâÜk³iŠ~ÎLa½k0T®$C놄„7#õ Ë»FÈœ éTÓJ¦áA˜Nú¢ÚÖgÆ¢¡ý9ƒÄ e½òÄþê”O«6â¶®Ò@1q5U,xKlAùwåP—œ† wx‘ ÙcFѱ7rÍ8´ïnä ¯Öì:þöÉìtC Yº<(^²'Gî¯wl‰ÉY‹MšÉØ?}ÃfB ‚uùƒÆž\{¶Å•“&òË —Cý5ìŠüj1„sBó–<íû‡Töœ}Šÿ¾£˜ß¸@‡êÒ"»–Üö× {RCiØÙé§å T"J4hÜNaÍbŸlxd¾¶[dSo¼¼@`²4([-4’„-Ⱥçÿì#~Í_F8ÌšH¯BՉɹ‚†¨¿v1¼zúH AörÌÔ{‘ O§ +2°6bLúm.ΘB ÿ gÕ%vžk åF¡ÿ3" =óñ>P*‰0.zR…Šè‹“¼¹ÂÁ3 ²‰¾arŸäk…„¼pòsR­«Ðuåõ|[¹ªÏ¶Î.¼v/A|™¤C÷ <>ËòïœÛñ‡89¡þ’"Ž<)ˆ‚îþޏïÐOT„,5eWwº}¯>§mú>ˆ>c†ž·GYZ©êèº …ñ|q%Á¯sGƒU÷v? GTþZˆÕÓ"[¦.®ÚLŽ€pÝ× Ùš ®ôÜU(pý>ˆÆŒX *ÓO‡ž…Y5n¤<œ.Þ Èzp qúI,Äñ€ 3KþF°QH›ÍІ Ò8Ü ­ïŒDg®ñ?Œ_Ô³kÝô½³£Ê½¡(NIÓ¬ŠŸºŠ’7Õúì‘L²Áú÷ºŸƒtðçHQÈe‰?à ¼ð"˜ôÀ\>šÄh+E©³Q‹NÕg [nÜÜþ]ú.ÐäYâìî5|5¬såëã¡O~Nð~¥ª°aØL-(b€9bRl i‰H¼àèAT›|þ ¥þmÐ çöv¥]øñ¬×”µ£:1Ò…ù:Y(t!iËe’°ÅÊÈbsl[¬‚:ßIÍí#ê-ÐG˜l?•sÇøìŠœ¿Š’µpëtüÛ¥ŠøQ¥ˆ´çl56 .Sð9¯¤ƒ½ì<‚ºúÌÓÀî æ“þ‚tñJuÀºÈ>³–¾•M9NÂåÑç'ïcµX3‹£$ÍãÇqâ97ßçè¡^«£Š4c1$ˆ}»h¨PäÈ­Ê,<ª~Öã¼äU]1¸¾²_­îß-Üîv[±©w2çìúõ-ë5ϲៅh!œÑI6|º÷Röäþgå4P´\ʈmù¬ “Ù©Èl­X5ö²{{Û¥FXK×/?•œ·ó¿l¼³Ý’!ú6Õ;È"Ù2ò©c²  aêßÎVtí°ãkÈ?!‰q6ÆuOÕ¦ãij8ïÎö÷Êf„ñçP4 ¯&UhIÅ»!DAPD`Û¼@‘1/2¸uã‹(Ic 0>‘–ð öæ*Pѽ² ÜÓKÊr z¸)«žôæJ&½M†ÕÈe\÷Þ™ëÎfZE”;@Za.ãt¿w‹ ‰ ÿ„“<Žô@ñ˜¼•hµúŒ@ŒwOדIat¡ÊÅ޾ÿjV@wÑœùÿ†¸e|B/i^¤héÇÜ_˜¦þŽ2câG‰Ö¡×(AŽÎ¡Ó+«|Ùw•5GñÉQQ#XðKAÁ ýÞÍ fF½BaçÐÚiZˆÇÓXåùgÅ«ýC†˜’à¾|î§\™}T™Ë3P…­è–ËU§õ)†'N¾bIáî6R•]±rtÂ=b®EŒùØy®.Jv‡ ”õn`Â+û8²ÛÿSšŽcJðz©’nIè’|_¶›¹î:~¦ò²AMÞV†N/®<ßuç]ªs>tp‰øÄ“,>- ¡JõœRÝ mæŸB²¡pJ„óžNJA3† K†‡Y„'ù?­¢º£{ý«}µ.ÿ2+r}NgãZÛ\Ñ#¼2L±ÞÑØn+14ͧŒ"EèI€à6åÙÿ­á®l™ž>ÕŸdµŒY7%æ†o9¾)4ûú†N¥?ÀêË©²ñØ%º½_ L¶½ÓÍ?TªsZ›âR£†BÜÁm·J£žöúõ+-«CHþ£Ë쌋‚n­Öü5eZGíí&Ÿš†¼")ÀMcí,© ¹ö­$²žÌF~Ci4¼ Žš¥h`t§óþy4z–CÝc‚Ú¥Us¯P®´þº–¨.’jžF¸Ï4q$zbæ<ùóé~Šî¸Ó¯> ŠÎƒ!ê²J¡FÆ„ŒµÒÛ³œÍáñØ}$‹Ù§3)f-±PyʼÓ9ÓJÊW<'¨ïÒY›çÐÔÑÜ®v‹´„ %Ò³z wÇðÌfÍŠ±®è~ïRá÷hæDi|³=sQ€þ¾ Eâí\?R>w?ZðÂ2ïm_@ÄA L"p‰5¢~ãÝgð6<¥#äsÂŽjÎ ´¤¯¶æ#׿’Wæô«€Dºv¸õªHÅ—ùÄ=ù«Q€´Sjëg¦Ù¹…yc.‚%¿ÍÛçÉ{(/Ç>º¶ɶ7%3xÆkÖŠ =kÿÞB;þĽpO’|<µW‘Iû™ÒÕ2zÈ‘«Öó“|ÚgÒÖx˜ #Ã)—)ÈÀ£úëÑÂCæÄÑ;Ô¾kñ+aJ‹r•8¶he/¥Áø¶ãÐo(¢òoâÓ’?ŠCåÌve£çUa^õŸæ{ˆÆõgÒ@ŸìZ…*Pàïuµoÿk\¾iÒYÞti‹d6d€h ÊdXþ‹W"²Ý@c7TO‘8Uúúí¹îÑÏÙ ¸Ä |,qèúóÊëÄ—¿ÜĆìõ.{³W‘UÔ¯ö€E|ÿ­ Gî{ÖdÅD´û>}¯ÇH _Wµ&>ñÍJØ(ºÏu`_‰àK±áYE¿s7¯ Éþ.•ç/ÍöqBa‚‡ßp Ú U˺áðò ¶žÀ¬b¹3Ë„S1_?J%!Íòc¥&[HqR8X’¨¡|ßkÆ[ «Š7OȧC< ét˜C¬×¡ü€¶èhJª#öa«¶Gò~A5ÙEîQÎz¡²?kÅs®hH0’\o>qh£GšÏÇž¸HTdíä[c¯oÔsêß|­ñ—¦y%ºbpÍìa#I„•ßÝpn_–/–¯îd½Ê­óµA7BtÔƒ(M­‰] „-úÀ+µ^ÛÀš°Ë–#3U_†^nEÓ¿m鎆ú‘4&¸ÉÁ}?–8ŸIùS/Es–>Y_ T­€Éïÿ/>…ë úo%צ&*ž|^¤ž-­FJ©AMrÅŽËòŠGyõE(†½ýãÐìÚƒØ 0¤ÂŸÚ¹tí?¢ˆamy: «nD·­¸uj@Ân,vŠì'Õç/>³Ù¹d@¶ª*5­’J ™ƒ-@mÅ’ðé‰×ÈE§Ä¶¾»ôª‚Ö`a/VIµòíEç¡À¨ÛvÑ4ì]í&À{ Š›Éãl[àÔ´¾é48®t@¶õ§T{^‘ýp5PÕ౞ÛtêDR;ºº}ÅqÌ((6°ñþËKtï$‹“ÓŸ@³¶ËÐ}9Jã,Ú—5š7jŸŠŽi_Û Êêá ÁFÀÞ‚›Òj Óð §Ž¯ha‘FE´ÚŠ·þS*Ý>DtÃc¸Ø5Ki/$¡µì ÖY¯ sQÓhŒÄÍõÙ&ƒ=â>Jªá×îÔ⸽Ñ+´/3ÀQü Z€Èî×VúÏmBöÊiÛŽ%—x.h™Tý!£ÿ<Éæ‹· ¦ ÃѶæ,š(ûÃ*“@ß}»†ÂÅúÿß}¾ß(X¹ÂÄE™ãEûhÕ>>‡ÏaÕZ#x£§õK«å hô½›L0d½ÖÇï«úPœÙ0Ä#o ÒT[Ñ_þw‚W”M>B0üŠ"¡ °a.–±Ø‘Y’Ó<(ÜÅ-Ý@×Oi”oè ­:ê%°BÆ;D¯Q?÷ñ_œGg<#ÄBÖ—®„"l¾K¡ßeY#ŸÜZ6¦ß·$š@0%`JdWL&Àü²¦±…1´¯“9CoÍ^Lë@ÞþñB5K±;hÇw—…áhˆ–û¾)LùAå]øïS\­aQ)¯®ðÂ*÷v·«Ãá³±)r)é•Ü©NŠÑ¥ºþ4’~²ÜÎ;bk3RÆ];3™Ë;-ns×RåcUn]¥+QøSÜ^çˆçè«GÂÈ_ŽÓÓö{Õ탤ËaéfâÚÊ‹Õð›Õ³ÔWN¾qÍøÈt¿'šÔ@fìfVÔŽ5X/k»ˆ®ZÁ,œ\ô·úÁu¨êJäúJI‚ú‡»šTSm—ÚõâSI 1jN®;7ˆŒì*Æ|Ö1MÒ[Aºœ`LSîi²Í´£Ó›ÈŽŽ˜a‹ÄÔŸòØâÁ}Kz9ØÅ7?…‹)€q|«)³öŽÃœÎAg‚dì„2÷–]¥½Q7î`á5òJ:ôæ51Ry–ÝYdÝdpP–'ˆÁÞ>~òdE ÎÆ\<ؤj‹ÃåÈ#f_G?>Syßþùé1IAlT þçîÅ-OÛ¥>XÒÔ jGͱèÓLñµ yNØA\çåðŸì¨:ˆ16N=y#+—ñ×L.à9|ü%t’st_‡ kéœ^µ^bäÛ߇ EÔ6xªX‚ïæN¥÷ëÔW…¼”ÊzˆÅdA€}™ƒàö;[…Ëü_Âç£óàÅ• Nù= ÊÜo£×/"WN~>’úîfLˆ}~©ƒK7´ÙwšN R™ꝰërÅ+š‘>¹«y ©iPäõsn¿,"‡fшdHä÷%lj ÃË«pÕhü¥ØÔ´ O ‘)¯qí‘k°PoBÒ X˜ŽƒÅuÑÚÜ$_I¯Þ‹4ç6\t}´Õºqé–QNmcBm1v¦ óqczÍ›‚%oÁn®\ð;“O¡ª?(‡Æl |ßa ö^a8µð}‚ÇCÛӣ逢â¦U$-'‚=o§¦Yø!Ë]Ôžºþú›——Oc(¼cÝYŸE‡…„¦y‰8—³}VŽïÔyâòÈ*© ³J+ˆ`”§ó{å˾„G@=à\­›¶)W ¡~½b-J€ÝJ7œä÷¶ZÙ¹ï5wrètžQEd2jóm¿H1T¾fõz®ù 7‘þçÁÁÔwzl©éì…Î{~\¨¼(%Ðx!¶J~í½ñÜ|o’üêC¸íÉ7¶4à… RßréW½Xx+'@×¼ˆí”)Æ¢³iøüÔy×Ç;¢?uÐ 6Ð_o×TòžãpÊõ™ õ3`Òv‰“Qš)Ä?Ä5†e¯ÍÓ~ÄiV&HF…Ç¢$¸þì7›xŽaDö¬~@ÔìþÂÙqgNf0bÓH,p—À.›½Mœµ«†.Þ<ÿ‹#“©ÒQ² Ò A4g&'„Õ¯ åª-"…ÛˉûUµ¥ó½è4E¡Ã”‰ÊÆ¿#Ar²÷“|!^NýNðÃiã•Kµ\ ãD¹.±ž:vÀ´¨aeˆ\axøs&NµPñ<c}ï“ÆbtlÂdu/ “­RAôQ‚G1uóN¤çŠÈ‹fq[î¼}FÕRÖ⯠1­(gÅý…$ÿ~v„kÁû‘Ûï÷ÂÇ¡þÒ N¿‹`× YVä¸p±}lóÊ(0^qÄ»ó‹’ûuC+Ò„Kœ Îò¢TU !²ò_õÏO²·$ã×¾ª¿'°9ã8¤ŒO~äW­™»‡ÇÅ´3{-×qLbnÁÿo%m~®}`¨¯àÈ‚¾öT7ïŸÃ31·£,g =EáošïpxÌQSª¨ÒâA)gJ—ô¡9±X‰mÚ¨ûØmJ.’0}nó&²êì™%ue©rþÉJ\öŒ?LtPîšzÌße5@äÁÚ±ëÇ}P€äQß:ººWßXe5Y‹¯70±ßåL…¿£ñ•˜ ßü§ËJreÉi@vÖD3±T{ze•þÂÖ`H¨EÙÁê“>j„Z‚à®\}ÉŽ<· G4•+!‘É}úbbgIY×ÜÆ’]‘o¡z µDziá-=ªd± xÍ‹°ßŒ€.°ËÌÎŽÔĦÃö§ 4)û­‰!þ)Ūƒµ>eã ÚÝ|!¿l`ÆšL.U-Sìãä;ðsUŠ ®ƒ"UZ·À¬+Ç&gˆ.σŒÿ$’$y Ž‚,'ûutÞvãÁ‡¹;Õzx ÒoáÙÀÐ<7  \4¼ÅÓ½ªÖ¸/HEä—ƒ9QµËvsû¡½Åoy0 é´V$C·KÔ'yïíŽÉ¬²Aæ¹$Ø[f'ß"#·ƒEáèìÅEºO@Zª˜úÓ²ÈÕ"íˆÎAÉšÊ"ŸÉ¾#ÍóŒ9}?,Ò;¼ßËå«>"dªoÊÛ9îŽz%}nNçï—ì* Y-Œ€ÁÑßTü$;Ä<À‰ô:¯LÒyì"ÂENϕڽCs(±ÎšÕÅâ4J÷‚J| NŒ·P«ãÍ,¾”àéîXŽv 3~^sv:C¼Ä{ -ìí9¢…¾vÏC ‚“PšªNǸ¿:|#b«OÇ›æAv‹Ý;E= #x×w¯Éõú ƒŒnŸNmü>#^„ÔÓGC·’@rsá¤ÀÒA{θ¡®›ÈU×ï²ttîåðóøØjæ}ô!Rí—þá9GTcÞfþô°'êï¦W7xxÏ#ãÔ:‰L¾¶åI—6wèÕÒÑ层„ÇsüjôÆ”kZÔXö{ÃüKÃ%›ŽÕÇßæ‡ã”O¢‘±ü» ˆ?‘³.¬S„1šÂÏbbñ<ˆØ½Ä”¸N·üÞöÉR½ÜItÏ@Ñq¨—æcOeஉ”'*> ÏÝËHå î¤MMOJÌm#U÷Çú|}']`Û`Q/Á%SpK0Hù¾é:$fÄ¥Z·ºëEmgÓ ¡îμz¡(ô;©ÿ_ù×Ù#'Ñì^ë=p•€¯üú¨'+ÿ•ˆ[1]‚}ÏÌÞòÜ$åeƒKctå,±èO¹ZRòj/à`°¬hÃ6Ñ&MëÞ3#”ü¿¶Dº6?Þ3c?³)˜hZëlühvEm:{T¡Á?AGÎeø‹°·¥…;® Ö£F¾¯AP :¨Ä>[§¾‹ç€@*>Ô­~á½H€×ú-WÛ L›|©0uÔzzPJ|)ƒN.¦ÏebC>y‰\‚Áõv×៮+L¾$3z5‰½I*Sü`†Ùúë¯Ø…Î{ô”}zìZØ<Bͨ1®Ôéf“r¡@þÈBcD… x˜=Ǫ^ »Uí6…OJ„Vj… övê)Ï=Ó"™“” RbŽ¢fZÀC •2Ò$dðñá$‘œˆT¨š2©y·0̓òX8òs·žÞíÅ~ä>?©à7ø@¢zµ|—‘ð=‘Ñ(-j«ËRÂõÕmª,Ô¥ŒEôZŒ½1Ô¥YŽžA!¿a[/ˆ’‘áŒ$ÊÓ ’©zi¤GN¤á™cžð·“ÂÕYÕŸ^Hò*þd`¥Tž¼ö5%ýßbÄEM“1bÅ[Aó+úX]ôNŸé ŸÏÍ ^AH»ћ՟ä¯idkOñbg‚^¯âyŠäFl¹ âÔk|®€ît‡ *Aß&ú6éºÇ(NAm\ó‹xŽu¢FŒÍÐÈÞ?ˆžÝ]½Oã„ÿ OÞB4Ä¥ÉÕþ=g“¸Ú“Ðé©zÉYW ÷¿cIA õLuÎv&Ìtš5¡G4!æ¦fiò0`óXŠð7n_¼ðn Òè ©¥Ýµ—Ûò{v€òeÜ¢^“H£AD‘}%SÏE~õ²Œ!Í(eTßÛ@$^éâ…t9|v8¬8zóWTÍèd#"ÿy²¬X)6U²;ìhý¥ûýÅzIÅÃhNñx™ Ì&•Zkû®Gm^üy‚â$#r®Ø?\Ü»“€!ÿšU­ßylZV|N°útéz¡Ën|„¤6˜÷rK–?\ùxÀÜþ1”Ø6âþkUiFµï,³Iá¦RãMÉ |2 á³õûb]dɿгEœ|{EŽ·G…ñ,1L±µŸtœu7€»Ò(Eâäï{Õ>û Ôv_`;¾€¾žá/3 Ñ7çØ"q^%ÑLä£iŽ d¸^|Ë̳¡Ü]©½K„oIiÂMÓ¶C«xívØÝ'Ôñ3À…͌٠gOÁµíŒ5!@k,]”îß'³CÑ¥Û†ý·3ñ%JŒ¤ ߊÝAÝòâ/˜pwþAZEoªv‡wî3ImÚ+3m8l̾G]çn­—¯ëáÁ³Cð׫óûå«öVEùíùæßÿ¤<Ì‘×BE¾-Ç/®Àð™´9ž ßÖ[Š;øhg‹w¥Úµ.±¿¼PDù ˜UÙÅÞU*Õ]å„#¬ZçHž‚ š,àˆŠ3+›ôˆ=?~Z·[EÑ_ŠY‹ä~G󮛀j¤k5,ÐiRxr±R®Ú’3;, *¥hîï¶éTt_„LuµN÷-X’V‹)f Ó(ÁïåÁ;:ç—¾a ãó9ß; ç´È;Ïk„Ãç0É©Su]F àk·]q'AŽºþÏáYAÚØÎv¦àPüÅ…›ÍÞÊЕQ¸¥>.=«ŸæHæ{oÙt ÇQ,íÍtÖÒ‹ ·KSÄùSQ0Lñô±w—Kø^[°+ªèõ¸u„ˆuÇ[1î4hÝM’ xi>™½°$¥Ø»ä#E°§³RÞ½cÙôäÉn\R¢…6¼c óLbÖnî¨%­Ã§ð)÷ÌvnÅ" ü#Bñÿ  á1«:ãý9w2…‹ùM–.‘tÔ]<Ü«Ä@˜ í_Oðch‡ÍÁcÅüDQŸûë5}PRÏÆ«˜}o¬ZU§ÞIïÀ~—˜×wˆoÄ'žºp%8ßu`€xÐæŸ‚»W,šÈ=ÅeŸ¥ž b‚»á>ðåp0ycçß¿DÏü†©Ø{,Jšñ5 ?‘Í.0·–@COz8åó /¹W ~3Ǩì_!ɧlqêeT3©òôÅo"¸£¿úwÑßÀh¢É-åSñ­ýö5:SírÎnüB¾×a“<:!ö†XÝ‚·ãŸ •X&}ù¡ÇtF/NÞæ>9­²©ÎÄ&ÕÄ¿H€k Áõ_‚ 9l{ n,$‰±¹?IÖär"†-ãIÀV¸ebsé‹/xʕɎ~üôsÛÂ"å5ÞY«„Ë\àÀ~˜Ût+ì% ÷ÿVŒ¦m%6ó{Ú¥óâ\YÏŠ×γS ˆE]³ª³—߀ÄA#zÄáêÓr"¹ýÁÑXØÅ)¥VÀ+H"Oý>£B«´¹qFRNèÃÀˆâµº\0‘G|õ~C2‡iÛ®€;M'£¨?]ñ¢Ï-BÄæoJëÎU !r8PûN©ÒcšÍO•f<náprœÔ=ºËL5‘ÝbµL*`úÖaõœÑDi¥BöA8ÜÚRˆYPµÎ󤜑Xˆ0”Ï»rµ‡±È<ø ‘æÓ-Åä_ ¨Q~uÒüzà@¦ó†w‹žjƒU!¸iÆtziœvöMöÝ4FN­ªûÜü#Õ˜´¡µ’f¹aGoKœ¶aXÖ`êè|³ ±çf­Õ…TЯצe¢xrwl_’T#Ãæk"b^„x…ú³êû¡ƶ”0ðUðWYM»C¤Á§›ÖŠÁ¯­á Ãcˆ—ʃw2ÄÊn¥ÈBIšdzdc­wÚ[¶=BzÖè®K9·a1F´—0C² K(ÝÞtÍ(Y¯CRð±ÆÍº®þJXá„üÁn‹§ôÑz¥Ã¤ÄþGV¹F¢Ö7‹9¾í#)Öõ€™³Ë±BlØ·~lGÆK+,XâÁ¾y íówqF(Îĵ«Bâ«wPî¤Êñyz²"ÒùÇvß4uͤg0ʇù¥ïEןB˜¤ Ï8_Ùk‡V±v~Ž#†ÕJn›Lf/2¹[ð4Ã<“ëËÑù5:ŠÒ޶…HH1,¾c M„Z¢1—6®[ľ¯ñ휌Lyèý„xÑÃn62*Þ®‘½‰âäÝ:÷Oô'Ä‚®€t™7ËZkw!C¢¯ ¼[ &gCx\2•?Z C©2Ÿ½+q¶‘à|’HÙˆ¼Sx©¯^’0øØŸë¶ ôp鼨wõ °±. r2??b™“&M3½n{æð§ÑèU®çü×,e­lâVì,ê¦^iOVt6൧%éÝüéwÎB LÄÔ@£•0,n œ÷çÁ‘/ê‹ðèG(ãf á496󨫽<ع2zï\)!Õ*¹“`/JöûÎѬõº6ŠÁ«¬(‹ ãA@yƒ·†ge2f¿ÞiywŽ¢D­Nµ|ÀªA+‡ˆ¯¼•ñê蜒"™†™Ô} Áû€¡ÚLúî$ü ôy5Ö(?r>[ à¡ßžã¾°œÿ@\Û~õT†‡^ßn7bŒLœ1nÛ41fܶBÐ3-9 ,U’¼Û—Ó-1(ÚA꫞ÒMç86”tcFúÛIÚâ$NR{o¿´ü,Ý=ý¢äßë|67Lpo¹§ésŽ`+@ßзÛ=ööëø,¸~¡¬¡|uÂhÙÍgv™z}NnÜ”aºur"ëËGâÈr»öXª®s,ÁÎQ$u:uÖÚPå=é?:ïQÿǶI3ñqNÓ9_gá)'€l«;ŽlNsJuJ· |£Bµ%#6Aöø”QlæÆŸ …ŠeãÀº-’Uëœ}½›‡!\åL _7oK#ÕÅO¢ô`æT ÚßBº Úƒüñú˜*ü4âé—‹ Ž¿Àfç vRöé(Æ0w³ouÌ¥v6ªÍuS¨xÿiÑg2+uƒ¬ )ç@T¼Yñ&×îS±2ÜW‘H°éR¡°ÚV2&­?‘›òéÈÓ!_té·š/cT‹äîå%0Šî‚1àEx¸U¿fùYó˹ßð]:.Û×ÒÚmy„@÷¾½jx0ÛÕ–ýç¥ØEÆ‹¤ÀØò$°¦3± õÁN}C¸1T«Z/;›‰.wwÀà’ôcñ<Šp¾©;[Þ~œ«ñ„Í—O»‹,Tíªf¸±Õ­BðÂ6Qí!ô!ÌàY¸OD‰ÐšÇÈb]*~óŒL k›9áxI M‰©40h¥ZT©RÓ¨¥Ž¨ÍNÈ+*=²úUÏ“ÓËYͪ/³lÿ—Wc‡áaZ^JâÊp,ž4¿’vmF_Â#À®¾,ýXH’[«ë‚<[JîûZŠ\L¤è|X½¼‹³x¿õêt!+²:ïíšQ´ß#ìë&((‚™EEá¼*Eð£ÏÒ'PóbE\Aï«Si+^ƒüwÓo>Ä’`¼ËobÎŒBðù\†f«‚ŠŽ«©'ƒ¹Ø••¬´½Kb- ²Wp#3¤[eŽ˜äÉî òP\z9ª!¹Ôär°ÒÝ6xDùŒ Å`Õ°ÍíØµ$ˆC©Jiq>jù[àwN1íÓFI®Ï¡º ÐLÄYYðÉHx…žÈ¾ªÁ2ô/²»ôhb(d¨]Òãñ¡1ë,iw©4³ÿ˜‹¦\ö¼UÌ[PÌŒãI0öÛË¡´Nˆè NWöqj1kžÝ:ØòûØÚÖI?®Evzþ_ÛZe;ø¹"r @M]gˆ9†m½9ÏÒ²4fŸþf2DÈ8‘(¡»y,~RôÄ~Ó•ŒN$ c\O·Lµ/,ºÐܲ#(ž?Cªoò¥Ðþ£VÍöë&–s£(•1‡¨<0„k€Ë„˜Ô¦Å4/MJñ@„’í3~=Z'Þ¤F™ºìš²Ö!­{á’vy¦Ñb½El݉ @š' ŒÇ™È_·Vß‚Q~fa~Ïçþ‹*jyqdɯÿn†üjºîçB@è5Ø7~¢5‰4r9rqùÕQwYÉ[ꙵ›c-­Ó„™ù5ßBo„µo$ !~^"œ–ÙA¯Še‘žßÑGrVƒ齦Šhߎ!fõd¼qT[¨@Ô)"æ%Å ª/Ó’¬3)˜-ˆÄ‹ ¬Î`ˆµ$kX=ÆŒÒ+û=£]ÓC³º¢á gnVЛ?!Ç“àÒPޱp‰šú^S0odZ(|–á±ö( L5Å\áÆã±ÞŸ*] bNØ!Ö€¥¼0âº-{Zª †W|ê·~:·Êpð05A¸ž3#¦Q?ÖwÐ~oþgz¶èë^‘*«Âp½•C[×GbÕ™¦ âuó6™VÕ„ï†ó}›T„Öh^-þj¯AßõÖ{øCº\uû<Šø÷¿íZ ‘(Ñ7 [§S/ßc& ÖˆEžnP§¨ólW Q€Ï?a*£ÖT­q„]ÕlÍú…¹­þ2í_‹RÀsØc€t´-‘3áJ¿‹ë*? ¯LÜ«+E¾ß˜njFò“õ6·­Ð|yñ#mcèö6»Z¥°<ÆÓ¯NÝŒ“>Yö±Lúê]ÆDÇ é‹-0-ˆIÔ¶A^Þ œÙ0âAt>}>=î‡Êl6 ^SczRWkæF»:NûÀNQªù×X”"<’ô·jބʰ½M0ò÷éÁȸ1¹ÇGX~ýÃUWCð+VZ‡ÎòÛóÍ÷àK¶ÜÇþå– ë¢®ÅÞ`îe/ç'Ìû½(ÙÅfftåis©GJ4úbQ*"·ÖYD|†+ºÂ„{%OTqľ„¼*œéË'bÔâÏ“j©×ËèuÒ ‚;-UízÉ¡%#ñUÚÆÇŸÅ¬@;æ†Ts`)Â|W¾¼¦€•߆Ü!dœ¼_|°rz»xj^!j%¦œö{¥ÕåÇDÔ17³mHT^¥ã”Vÿ‘¼Ï%rQíøÒ<3¾ÞmÙYÇDzÁ¨f2™=fw‚¤šØ%SÞ¤B …pÓÍç˜Ö,åÍiá^!À‹O¿m@$ªƒô)`‚(ò? Š¥è°BÌžÙý Íæ£fêû)÷Ø_ÕÜ™ú$FÑN]ö‹©|¬«»ÞBRQ¨›Hª…Ì{6„žáþhšY¬ññ ÀÒçw·§ Ë*ÑŒ$ÈÎPêñ·³3’ˆgÆÒ"M¯S°=rwaµgS s±ÿ§è€= æ½R™-Ëög裄:‘À ;óäõ,® «ZQIÒòˆ<Ÿ/àñmžæ{äZøtÀ ݈*k± Wp™÷-´Ò •)â¯Kï1p‰Œú8ÏZÁèM8Ÿo}w£'VU¾ ù©=ƒ«ûñ‡@ZkÁw^ÉÆ4™w…á‚•±ÕÇ/¯~:"7Û§wb›ÏšNÆ|ƒ¨K³L<²î{l( Ýà•r¾Ž“n:öì ’F¸€Ü¥ê¸JÉd[ä4·ž?eºœÈ,œ&áð%f¬vfʺ™ðØè#¶7Ô×Ç*¥ê"Æ¿­T{uÖ¥|FÜù“ÖrÓÎyÝɬû<}‚*0z¶âË9ÜW<ÿÖJˆa€+³ÈÝYŒ×tKÝ÷ü“ž×Þ€÷JÂÀòŸ×bùSf\y§@è’< O‹¢ž¢“ª_@„¡ÀyàuqèVcp#DHîM'½µÀÎ|Xþ·¥2Á1*·8ö¾9– aIJiFÞ°æ·¹=Ï®¨Ë+  GD5¢_×å]ÏŒªARcf§H¥ö}fÆ©ÄþRWÑÓþÚϸEGRŸ!áÈzte¢s oqxÔ@“Ò–Á‚Ç휡80m;0ã°g-~ø¨îs/˜+&¶;2g:£_B°Ú^€A  sÞC޽´À&ø >X¡™’÷Ï©ìš(Ö‚–ÐpÎeÿÓæ ŠØû:œ6ü,}ÿz¬‘¯|·„ˆQ(Õ¾Dl:HrF Ù¾’YÈ„0èC{NÀüóEŽù´ÛBº¢ú'çYÏ÷ÈU<"|SJäRä "ñe%¡ÅÇÃ$o·ÚŒ;ÁH΀ÇßËB®:þB¹ùþêµJ¡i|c~øúu† ã»þ®DÚç…ÖÑOôÖ§;yBT•Ïóï—›‚ž~0ý‰¦?Ë´æuËïu€õ &fArìîN›l&UEpãóʽÒÓÕ¾‘MÇ!yEgOŠt—­[PÙÐÒáBrÎe°Hü[šm¯dÐÏÿ-G\êd=$|DuÃ|3j£ë’ôe—€‹Œ)e”áÎF‘ål&ë‰o/Áœ¯1Ç 8‘ÏVƒ#°‹¸Ô2’ÚÚÕ¦Så jét|—²í÷UÕ¹ÎÐs|¡ª\Hô…SHƒì‘U|*¹ Î_…“³:vËb¸çþè™6`¾Â¼îx8P6tßw·ñ§ ·óæYdÂg„úæ\VØâ$ßݵßwÄìËNq„uÝ–¢ZØB“ YŒZÝb8ÒÃñ%9ÀõW0ÝÒÇnÆhìRËñ–Kð#þ<îÓÎóHxM¶^¨1{ªÖc¹‹§Ö@„ÔíÿãoìÌ]žõ|>õNou÷'°;УX%}ãhÉD9ØëhzVÉìPw2Ò‘ÞkrÐÿÕ»x`S8ë2«dèiÿ '‰^’:jŒ° B)a»š¯¡EéEf¤t|¸q*èeºZû·¸üûÚF£¬ºf ŸùN¦Â[zi>˜Ê†:”ÛF’+ {%+` œ+ôÉ Î„–ák(°Â~™áçÁ©ˆw1±ó9Vq[”aëÈÅ·’©ùÇB}iiÜä1£Uœü’ÂÈñÜÇ~?%•G:K›žÛ+ÅK.}ag)Õ`ÒBüc¡@šõÓ…Cã×(­¡Î¿9Ì0¬Í—ê<\…¿‡§]>8ñ¸¸Ñw²¸·Ž ·I¨¯~»Óòz4sÆQÂ0‡)NϪDu>òª ÖqÔûEEÒ€\µ6c:à¼6ê”å©ÎÌ8u){ÆNW*Ð߯US«„øÙÉ‡ÅІNXê¦f…}ÁRÀ:‰û º 6{í¹L@¶Gc¡€Ú[Ý¢g€¤ò…vÆ:×Zå×/ÑŠ"9v¦…˜³7NÞÙǦ_SK™á,Åž®m{h¡q<]d{Ü’¿¿Œ¨Ù †Èg³$8Š(¬Åc4ó¦áB Rõ ?œ_ÞBkZ­{oÂÜ´'4ÉàeßµOØG÷·?ç:¬@Já°KüO<ªíÄ=»Q˜DÝÒOžÇöÊ´²×Àz¸š¶]Üï^BÚoùÉ:xISiºÚ=ÆñW÷Ÿ0ü¾©wMJz°‚‚õ~+øt`hù¼ ‰WÓÜ÷Öíî WE?iµÀ¼çÌ«w*íÂlŒb[£*õå2{0‘'ÇIÄàÿ,GÇ>Ùž¾ÂáU„X™â[Éd›Ç ø#V7žIþv–ÕIò3XeVM ²T&ÌÏãÖyÒÅI<~p¦e9®3p½XÒÇf­¾”mkö#¡q$PçhX§Bzè™Î¾¼DB!£%ú>C [ÚC¸lvÚeEè—­ïµ£g¾p°4û]ŸØºÌã¦Æt¥ûTvé,ª¼ôŠPþ­ç¹¢&q¤'©2y2yD$¼c€ŽZ7#ž.hGýNN/wBí*¨+½Ç‘ABKè³MÇ0Ú釛â_º¶R™ñf!gí¦¨yˆº¦î DÏ\M>„Z»#'V,퀙ޛp,ê°5oØ:džö<¯Ã]¢ï PK 2\3ó$S¹ïÇÁxÒ~ˆë_ŠGÓGAšŠÛÑ(3½I¢Ô˜p<è›™¹C’ÔìT§å¶Ã¬?‰¡S~„™~¨šÉ"–åÏ’VMø›òJtÿá„ä>®*ò|³¼f;컟N<ÛAÚ çAÌaÖCÓØ0ÒOâ cªç]UŒZhž ê£÷„toÙÂÖÀ8—^_(ÏY 4œŸWR)×Ïiçw{YÁÀö½·’í³Y¿V{‡t€Ÿè®+;Å8,]ò£rÑCoaµc:J©1Ô~Sóy–Ñ‘³ó¸ËôbŠJK´N!ÊàLÁ€K0Lv¨ÀéõÈö%„C—æoÈT…\`'\—Ä{UD Zm †[~(¾§:ÐCç깆Ÿ´ŽÚÿ‰WVÇC`F)9M~îŽI°ioTým&^õ_³Pá 71ĺc)À=/JRã¿°n¹ù¶±y,äó9(ÜÆë9œÐ¡ãU ä'ðDü /–3yÐ>o¥ºV:ÈžL‹«¢U9Ndû{à*øH?º7qÙÕÛZþ½ÒÞiÚlÇu™ä„÷ﱉÐ9ÞÌÿËi‰^_yäšÀZs(m1kBDOpGZ•ôô/&<Ø‘´h™•0Èýå΋l ;·™¥U{…³’o?Ó¶UóÄÁÆò­¬X èëîÇaÑÉÙ¯wš~%¾q"Œau3(PBÒèã•Ì﵇ <ººÆEÓñÜÃö¦…˜½:?ûl“…÷œEûDW6·}ÙC<ÀŸ0ŸN’Õ½‡5¡¸æCÈ{}°N€8@¶Æ#ò?Öã;±g~z‹^;“Ñézÿ`}+Wõ»7d}Úõ„5‘ªŽ†©j÷¿¢§©PÔÔWßÑÿ™µ R$„% Tpt,2±ÏäúoÃK™^ºÛÝ`;iCÖ®b±Zw¼j‘§ÓDN ÌÙä·~Âï’ò™Gé\zM}OL|¡y·¼;(Dq¦8øò¯b^,^çÇA»c¹¨Ž((âã—q.áÏç.ŵÏkì+ò«pœPn[Éaj¥©Ôþ>P¿}ÎçžÁÛ4ðÆïGúO¤× 'H E".ÆC9+¥‚ï„ ÉñŸm<^¥gu¦©ÿýÀn1׈2× fß& )Àã&¦I.¬1OŠLoÆ}TXãj!ï- 5P¨9¢…%;Vú¨5rK£œî‹¬J`òlÔK¡±è}ž“lbnþsÔCö-…=£ú$YŸJïj#à«PЏf“h£ÌóÁ¯“;òÖEЈ”¦¼êÐhYKÊM€#þ‡ôLó×ⶦ²ù™@ÒMoÔ‡<ÈÔ/ÐVíÅIîe¤Æˆ&o£t!/Ó*fÇ_™µ–½½b„ïñ¢2¶<í²/l†X1XÑl jòëyrzÎ(:bõiS'²Àý1þÊ›PÌ­iQl§Ãf•ÚIwe“¬ä¸ìZ¯;ĹØQm·1UIá§tÙiÄI šòe…\¯à9Þ ¾‘RßÈc!~ïMÙõ•¬kŸOäOz,#ñ^•©þÚa¬Žg»W85{›'ë Õþ6!‡asÁÁHÑ·J×”F5¡˜dSýç…Ù¸8â5ÙΨ‹9iߤ÷Êå»–`ºœ³Xâaé`¥]¼}4ßuÓ~éþÇ1°Sš0 ˇ`dý”ø/Bß”ËLeµ1eú6iÚ„å!Ð2“+Âï°WcIwq î*²g²ÞÛ¯¦lÃEUä‘"·K“T0Û@ƒ™B0ªÖIjiUh,éîh[€8z]:œ°ÞÔT]ßluVc)ÆÍw'd?—?8p<W±üíà W8B³ì—*ŠR¶Ðb(î*Û¥p¥åë.k%DŸã§çz2©§=&:ÿ2h _€–/Sìr…Kà ½)‹TœS¹0\¤-_žã'`Ÿ B\48 ˆ5ƒ¦„ír·§t\†ÙlzÇ1uIÿ“Çmõ2¶h*áC­\w°&:e}¢§•;Ò)Ká,TãÓc ÃÌ}´Y„øfæÆ‰ˆ¨oÉ¢^“ó­j[¶¿mŒûaÂJÏ[­‘Ý#ø xW!ûì[³£¾Ãhý6õm•n£Ûà…­k#¤üKPÄÆ²2d"iÖ™´À1!÷<«uô#‡üg2ßž,£¼nU>¼ïË6v·EBb ‹ådáà>ÓfJÂgfÂðýù]7kß×ñ*lq©ªðï¢JÕfrr)[©ƒv6É¢ªî¸ö¬ä`\Æ|þŸÖèoÆ€‚N²ËÑgǃ}ª,™'@o ûüª‚Zh®ÊÚ!îk…&5é@b€Î®jcX—ufÚ#Á¦ŸuFuÌÌÕó囌1›|LFz Òf{`´m ß;»¤ø6<§çµü‰&’…OõöÆÀ·´ àDÊ-Òõ2{K"/Mææ#í¡9^1?šûs>u¹Ì‹·Zƒ Æõ7k¾*õŒ¦~%?šNÒr´Òo&l¢EFù(`œkcÎÖ<žiÔl_y&(àq™Ùü}Ôa„5UJ™í‰wøg¥'ðè#ÇTÇ2Ä–Ù¡'¨>Ivµãçf6ë+Ä…YãΪ rX­0Çc^I×óÐãL†H™3Û·–D²"&Bÿ´¬8«ÐËUuÃÃÑb¶l­xÑC¢9æbYkÖ_ã¿SXYKOšZ‹Ï|á™VA‡ðgË]¬íûŒ@V$ /Ó#³·ú Öþ‰çÅ af–:ŠÝAvÁä€ÔÕ˜‹uˆ!Á’j•5¹~í€X"·zÉfc‚×î>0ÞWoi!YR•áññ\¾e+Ž—–“2~De\Ý&W‘BM’žÑ4ò%¤ø¿žEÊS>ÉÕ†¹• °›{+ ªgL¢þkHþº vL•›™Ú.¤­ªÎãQ;ft…YvgïPjµ•1]µc|†1´©ºk¾Þeð¶é¾E˜1Áx}hób†Ác™`n„"ª,H’èLš†êZ–LѦèØçs›{ýqÂ}â©e[ùBš9ËgÉßú¬ÊÖ¹—ƒgĶøÀƒ¦§11 ›ö~|©”¥ o )…¾¢‘±Š1Á&ÉAÎ,;ŸÎªLÁê¡ñVu9õ¼õt©ýƒ|ˆjØÆÅ‰›;z¨$ˆ‡R„äJœÃrY¢MsK-|³`ÔÓ¸NŠ-DÆú·ýŽhƒ»´£ùÿÈçªYJä;ž7-Ž[žT¶÷\ô,Fë.Üì±Lã {Fÿ­’ÕLaÅWi‹ÿ´ÂIÀì.¾ôäL»ÿdŸy°`¾…‹ù,b0]º¸`U‹§7Ý-«®ò®êX”[½E)‰g’. äg„ 8tà9àBdhÁôp¤`ªóÇv~}Åø›Æ7©vHàjsnŸìª¿*¡%ÐñÒ;­¸WC±ea`N÷Wk(VŒª"e‘ó×S¿ÔÕ!Ð%é^cZŽ9,QM”1ó³ëÏ¡» Ü–Hÿ–|b Z«û¾X=s¶úoiÂpLzêªBéü€ò묭åÄ‹ÆR6Ð[ÙÉHÝ=µ–_;¶¹-}%´'@m$o!nàXDÊŠqí WÖ9—~1ˆã“`Ïk}$î¢`Š9³H9*lƒ±ªvì\Dçxd0ùì@zàqè®&zI¯;tFèßqiÀKGò8›‚{˜ìíR­Fg…]û}¹LâÖÚ;þ8ó‘rct³GpLƒuÔ»\”ãURªaéüÍ‹»1xZp*7RH:´ù¬§L8+ ’i!rן`ÆøÆÜ!ð=Ð߃Bùñ°/¦†~Â’(/ášxå//ù«.Qèa8¸G*W o쬃¿F ‰«¾Gìç¬hþ÷Š6¢B— 6œI‘³9[²RäÃK~ñ>S`ª´œøãºt‰L:>üalæ…w”| à §üѰõõ`Q硾À^ʤÇBÃ-ˆ ŠÚ „ÛÝêþ¹êP< .hY 7ß~Ï$k:¿Í m\HðþQé#µ³à>%3„Ç@T¢ÐiÓJƒþ9xЄ;ÍŽ… ÞÂ@6©ªVc¦Ô¬f÷Õƒ§˜t(§.Òû–~®÷VY¨Ÿ&9ÿ—T“uÃʉ3.8f½!ÿ·Êªìö‘ö53ÈA×IN“q¹…Jªb…ýhÀ`ùÐÚ…hòÁ‡ªú€&ÂÞ²áZúü#¸Gyz±oÞGt oÏxzž9«Pì.èôc¹æ¯äPIìF’)e·… $ÿâ7€šK)UCÄ(yG¹YUŒáB°å³/†½„Ïáÿ/?Œ‚e$÷#IÎþ$.º<ŽY/hí_ÇÐilüí’Ê$/žÄé?Ž;0­šªolëB)˜E…,õ‘/ÂVXì/ö4†lÒ©QÖ„8‹{¢Ü ×cNjL®øYI^µTecâ”oî„2mÜû̦šB&šl&ºX0´Â0ŸÏ?$xsUõo»^Ú#<ņÍU…ãí(¥ÁQ/€«GMÖ«lýä7ñ6»X©Ü\Œ»,þñ3¢¥þ2*DË'íÆ«‚ƵÍÞ›èái™‘æ@†Ë“¶ÈU»{øÚ¼Wf÷ÑÍá£íË`½­øØ“®DnÔ0¼ &O™Ôøm4¥±°Ñ“øQÄA«š"޾&t˜‘núlSc¥w¯½š°ùF1¯¡Q ò•Iví}i4dzËé8ŠIó޽æYâ•aœéý®­¡¡ôçéPé}L¿ù°akïÃU-ǰ€¸~ þG@³Í,‰æ2ó…¢K4²wÆQ+gÊɹi'Ð]xEæ›I†±Eļ[t+cÜ®•–“¤®@¶‡6t›UºnS¡¼úÊÙ ƒ R‰¬ÅMßÄìca¥ÂÉd6/b«Ì»×»‚Ñ¿‚âðGˆ’§ižÓx¼Y]ju–ýn¢Ã ×Ä&hïãs¢žMýí'Âtˆ,̸2J sEÁ þ¼¾kSù,*ÿMO¦™¨þŸìª,C”Qº8j±‰¼AM,4¿z°¾E_ ³JÑo¦ëí¬øù¨](Ìô~0ÈS雃m5ÝFëAE—‘\ÍÝQ+\A¾0wüyŠœö ŽÂDY­Õ ®X—Ïø™R¼s¨Ï)Ù ó˜$"ÅÁÐÀØô R‹±c° Ñ}¦ñVºîžnpgD W;‹rÛnÝ(ªë:³5`]²O dš%¿-e“R8hß ÑlFÍ$ÄUþÌ´ bŒm§c )Å<È…¿yœ/ÛpkôHx£ë}€ï¼úöt@ˆ"¾“;#FÍ®pÌÙÔtÃoJm{“ñaˆß¿ÜÖ z|/é9°EZß³¯™Ô,r¢:z›½F¶KOAГ_\ã: ÃnÀ8|—ât^•+S4tÎPÃÊâ2_!ž‹†·¨pû¯f:ñBÞÐE $©n ®åñ›~1Îc²Ð°Y‹Ñˆ7©¬Ý©bXF0[8Ú¾¨^Õ‡&UêßEžD ·ŠŽüLô“õ@m’3T=Uø`ôÞ-TÍ}@eOއ½1X'JÒ»Vr?ÆëI™ïTLy´¹pÃVenD®4åi`}¥2°z=zñãdN}µœ¢íä¯fGˆéâ}¡C¬$_@ç€ÛJ‡0ôF?|ÈrÎäßµ«YmH ,6›ZûêÔ õÂÁ%LU¨¬d’a " LŽÕBLvsñO-À «¬Ú8®hÁ1cTpÊMaááÜÆ7· ¿«³öù}§5^ð 4Ÿ}µØZp ¿ÂcÑùŸøúk¯4 Ö?ýB±ß"@; 16mjûqŽB-ÍKõ”²<ÌŒà×ÑÐ܆*n[òG’´)b5aÄÆC¾ 56½!ûyñLWÁ%W×¹êBX°2 Lñ¼V»aÄH¼Ì“pˆ¢§å{ÂUÓK£îvZìU&uI³4øD;›Ò„)¡uŒw/Ø“l{#“bôÖ!7Ót>Ä@&öMhN“æ{X¥íŽÍŒ«Òy`ÅÕ°¿ÚS ¿Gðå¥ÀRWÁ5áÎ3 †¹”ò#³®ð³´{M½â’Íüx8n3=e"l¤V=&Á§5üÛ„\Oöÿ±· ‰ëÎÜûq†{™EBvAw9|Ûz|/GMÓáqnì @I¬®²e¡s¥²6¦¨#vjhJ‰ó;ÞHeš—¤^Þw³=¡æZT©è61fÔ+õ÷uH›7lPN¼$0Œg™à‡ŽìK+yaµ–E/Iõ±Ú T˜ kŒShôçÜ%óÞ¿K · f[®}õ¤½ÆÊ)‡œìd’ÃñE_’içôÇ(a1Ô𥒯D:M¿À|®W FP”AÕRmŠÍOÌ´°¡S—pzX×bˉ+ïÓ i±Ú#rçHפ㵰í ÕîQÒøæªTZ¿æÑR†–@3Õó­nVïìÿy*Ø”nÿ“!~q¨¢/åëÜø\éÁk -¬iJ HÔê S°µ3\å(Õs¥&žµ˜mQ…Áö µÌÚ&#ÁZ¤T©ìËNEޤV×Å?oÛ®$óJª£‘ƒ\Ûƒa€ËETh!𤗥SÍÿ%.'Q>(¡j¤zKȆ´iU>Ñ"l˜#œAô¥æ|êc GÕRÃÂϽ,íÀ—ýUÊò92óÃä~ÛÒ¥ÅâoWTy¶C`#½nÉN}‚¡nz¥¦cÅ‘âfÿxà´s+hÞΛ4÷K£HÇþ+AÓ‰Þ;Ø×´·¿{PêHÿ}Aÿ½Ñ É J¨od­ý­j ³¾óMúéÖÁªg+þ_3FUcXáiï8h œc2…üßìwxÝ`y¹ÄŠ&B(9ÎÖC»šŸÅŸý©8<6'¡ÛÎdœÞ¡šjOðŽãCû´çSƒ–‰þXLf¡Û‚Ã?ÿ–aµˆ›Ò†Ö~JŽAø#ÇÂ%AŠ65ã Dš ººñya3d-ÄûC=æ¸oŠº¸‡™ŠÀù4”çT€© ÏïEc­·?Ìøe‹j]•è¸&ií¤ 270*Ü£“w—N°ë£f¤šz¡![5E¡%ŒÄÇ}^ÂámîW!C,Ÿ9%R0 FJ4Aï9(šf‡¶Ÿbp3öä2'ð •:‰ÚŠÞ¡§•yÅCãóNs q$ cH +nB€”ãŽó¸y ìyi¬Âk†x¡oȬ¥ÔËF4Ò’atpä’¶ˆ{”"—ÙEË“JX‘¯"õ%·šx쌴YÛpfÒò[xH fViJÅcQ'YÏðB¡¯é ÓEàDQ?Ú=°ÈÐâX@ª[z²¾—oÿÇMYÝÀn¿³™sNÙ)KoÀ–w½Ú'yW• qH¬õsõ-|ºñæ(Yh<û 3Äq0Oˆ\pR¯ÆñªfTóWO—h-£!þÖ¶àº}ÁȪt´’¿@ 7ŒW¨%uèI⥘(i´Ö þ= º,‚ÆÈj Ä[éÊ–D¤!‘ìÌÅÞ!é‹#;ÄEŸ¿1ÌA){9'À½ÌC¢ÑŽ;ˆBï$ƒn{w7~ éˆæü½ÀNo´ý±ìî—¢˜nó^?:Àkå ÆúÍÄ2ÿ‚ 1©wxÐI¾úª]VôèiAn­ïÈZ­Ó˾«˜±YÛìºG__ð„‰mðqÀž¼k‘‚¹ý_ÌYŠâœÀ#ذ•Ilþ³r¨”\äÐm­%ÖÉ;(R&²i_)k–šˆ9 *ˆ B¥Ѐ‘ëžùãC§ÙoYØ ±`鬒̃!c BD¼øô^f[qA ͨAÎSÓb\‰&Å‹Û_6Xi¿ˆ½ð´Vò¤¦©³]¿­ÜWl/T!dÌw€ÐY*Q²3*¶Ô¸ UçÀåÜy}îƒvMÏuä M‚ÇÎO?.A3ªtø„ ɘ®Z–åo‹_%B¾wï®R ":ôöcÀfó¾Ó-D ¦â'fk/y”ì>T1'ÖMÙCûЀŽo_Ìå µòS&9I¼ é]Ì’òì¤Ø4##‘Éðëˆ|jTÐGÁ^UÙŠênÍ_3Óì–.:瀽%ÉiºÌt¢ºµ7›MrtÎu5©œ~­Ó¦p‹+‚o´a§/ÃZuceì±ßÄê%Q‹ x®wœ³Ú8ßÀ}Yè¨N}ãýê¼'ƒz›À»ÑKÏ÷ïSͬbér)î³–)"ÊØ.›‡nè¤J‰rRÆ$FòbAì“Z¢q‘=ùekù&ðXi-„=Ѷ5­î 6g‘É’‹PXp+@H™ê87†MÃ>ÅóëU»Í= Ä¶ ö¢³²©Mðï$å5ÍùA“‰bÉBF3Î>÷$«…ˆŸ·c#üP 2¢ãŸ][ÙÎ(]*ã°‰3 ꮥSbœhá÷úÛ]<÷êªùH?¶´Íô7ÛC¶I< œr% îíÉ·X~'¥-&–ìîNèêNr8Rþ(JÐÓ1> 0OCài}*Ï•ºž’Ä‚âörxÛ¶žß³#JàåÉ—ÜŽãÿì¾|ÊÌQt ïÉ7,Û)cijTÊ(þŠ@Sîa¡'÷€/@*xtÊøÎ£‚]àÁ(ÍOŒ€Âá{rU)1.Å'ÆR\pQa'¼3ÿÔ§k“á§ ˜Mùv2¢4[;„ý²ë®ÂòÄBÿFH„&,KÙ´ÅqQ²Ÿ(ÀÈ[b ¼víIå.†´õ—¡•Ä1?uR€å+áúy»‚ îiaO{Ùîðúá-h@ ¹¤÷…ãZéû­‰€Kƒ)ôY\@ßLç¿x@–4 ønÆO²ñyôŠœ‚dŒ¦lö !6I¾–—?@LfdX,ƒÃ² ¤“$[ë­?©f@¬ƒ6ýŸñ„2emW5î~ø{µ*ûAýN4Øk£rÓ/ç~oUc˜ÆãO4 yN†-wѶWð×~LnAöâOðÈà¡’(+CËx„RMSˆ¬6J¼dÔ rýø´H<õüÿ•]Ç“ÙIážßUüZ:ˆAýøî¤mÕÏGSÙêVU—¤åɹ–L÷S.Y¶¶9ìä&°ä9”N×]>u „Š’-­´'ç¯Ë»[#6ÍýËÙcÈ…dþ|+i8þöF fÈ^ÑABE’ó Vú¥0JDS"=BÍLôkú)Ç%¡ÊžC΢û%í¬ò‚ÎJHÖ" mj^L܆Á4~5°€£Ø|¥z^›•áΉbw£ºà侜M’P_$šeöCþlÿàEŒ[¼ùÊ% ò4®jò~ ¾¾pTÈN–|Ë`§ð¥c„íy­æ³WõÙ™š^ŒÊzIRvfVsr3óÊ s,vê߯Gàs† Vvn˜Öí¼FâÏúÄ}õOC·F‡õ¼û žÍ ]GAðSiÏÈš‚y  YgSÙ^ú ”V!çu'šA‰! ÜT8âdžç|ÚdÝP}¨.·yQY $Xf¥ljºŽ½€ šðÀQÛ?z2pd¸›<-+ðIŠÇ^j?PRƒ—éˆÙâ°ÝVæ²í’1.^ë ¿auveˆç”›ýž¯ –ç´æËÖ åM‰ò›Í†ì¯7y–I]›ÒŸz›„ÜÌ—þ Efib7Ý·;l/ûÄŽcús‚¦­]Q Î,kOÐ30¬Qÿ!dÅ>f« Ï»Q©<èíÕÆ(‚ó¢ÂÌfqV¢¾FbÈóG[*Jfáõç‰LÛ*{Þ™ ,°üÏ7wwQ KgBú.j1û¦ÿ€ŽÐ£Òyœ[•Ï®‚§í#Ysþ< ¥nŸJ%?j3êIK:êwÀ£È/ y„0ß!€ÒñÊø—ȾS3‹3~ä€)NÖMyä'…Ì;˜Ve`“Ÿ7YðKó+é}­ÉsÛÉ1ÅHþå‹»YÍøÁ¥ÁEq.|3L§^Ëg~Õ cé"…âãf¦÷m;²RšŽÈD§ëÕ½íÔ”IyÙkž0êupÝI')áýÄîƒ:\óì­8®úc ÆåX@²¯=ìtÞ¢öš,¶·rŽ MŽ ^ EStžìôæpµ9æy]©ÙÒ¢Op2\[ƒãŒ‰ÙÞšC&vè¡©ì& ƺnÞO¥ly‚À!±ÎDiÙtùX°àoÓÖ'}¯ÖuWlžùŒ>¾—)Z “,@·Pg!ÂÜP3ð;&ZäùƉ™Œ%)o)¿#ü¦ì¼WtꮩU° Ty°Í•VXÃù!Æ;4¿Ù$6K>î&䟓náòêŠ9€M¶apRX}Ó¶½ì”7¸\Hlì,¶¤K)íâj§ÈIRH~ pÑÕXvÌørw[1èKÐ’¤ý:4Þ\ÔìO–kêúú™öשGÛþ[‹›-H…èXÂ`,]Þy ŠÖìYªüò}ÄŒUøþÿRÞ€¯æ•ó,g§÷j™úâ„tž€›]J3EK¢²çuš™á û„8m“D!)Sy¨Ÿ]N#ÌŽW¦ñ9Ì>W:Pꬷþ Zqþbˆu¾b™Eøw®O¿`¢¦–›GµÎ–¿”a÷+ž †Ã–{IÔçŽR¯ }l×ÝÌ‹`›‡¦ãuKªÎFí»y—Tg¯Dåê àš$VJŠU¯ÿ}sUíW¨÷m§(5Žù§ZL=5vI Dg¾ÉŠï*ç²S®~n'Kcf>i€nŒÊg逜v&šÅ‰AžüHW•‰™a­©rMd'I²V©ˆß UqFzâpßb#‡ùÒž‹i!QÙè(Wˆvˆd`[~ëh¿”4ÝM,›9ó:wäP^ƒI”kÉ£Hh6Ð8°À ƒÒqj6É…X»~àHb´ïB¹”\»iPö¥üão:‹ç„9Y,‚(ð\(á<95WؼçEkBk+$gc>Tñ`ÏÙ'î†ü_¨‹ÅV‹dLÄi¥`šóÝxÇú¢H‚cÜSÅJ)1šÇ>̼ â8T'jü!c<Q_ú¶Ì2 )'£Ö]Ò…ÊX#d®½V†kT˜ydqÏæw†E˜¢sP=¿y·³çÍ='¬zÙCåÃ,Ý >åp¸È¯Á@ª9Ž%1®—2÷¬×û„Œ([" `¢À¢^ÍIÃQ ¤»¥ jˆ0ÃIÓñ îì(àïä¸ñ³zg®í3¢º;Y‰¬ÿŠœ‡çm¶øµ»>RÜ ¾6¯3X¬4#4ÿëã½MY J¼±Ï’®P%³'j¡ŠœeÌ„H[ÚÄ\v)ïð¢Ñòˆ0º¢]ÂL©”Uz×¢£Óæžs½ -Qª>³[GÖ$1ŒweåA©¹UIj)ÈWKö2UÈ]ÐÉöÚÁòû/´»þà¿tÿÑL×ð@¶»­âGbØ(ƒ>25mð¨ªÐ73u“ÊÒ›î¹ÜÚBž¸J!.0ç”sosÕuP÷¹óPÇV–¿IþODøþ¤œC¥ÜÆQšAÑ‹ f© †!6Ps Äê0¸zïëxɳá[·h5øh#ðX¡t½“b%=K,ëc§xóu(W2Äþ qïºÆúú­¿ïÅñ­eÖ6»ç-Ú˜ÀZË)ÊŽX:¸xžÈJh,rÃ|Çc.0*Ø!º±!ÕÔPÁ8òŠË/TðûA´!Ÿ¸ïÚ:s*†¢zV}m‘c”mÉ%©/¼ÆØÒßò¹éÒ¬¤bWÂ@xJÛVOÝ`n¸2}—"ØÐ«!¢ÀöVóŒJtqŽ÷ae¾Ý?õóÎ9è0ÇnKœ%[ÉÓ$,Á_6©fñ¶êÇÎèù>ÈšT(,\ø*E¿dêÙ=uÄÍë•9—g=s›}0÷½‚=yg‚bG ˆwÇÓ]Ô@Jx|èA<;g@!yƒÿ.û=¿k‚&\@*²æ=®€Ÿ©ÙWÖËP‰q…qXFÆúc2ƒaÆcžgÒÞûhisÛøE‡ìx‘tmhÉt¬ÐÁØÏÇlj‚÷-@û”[éšñ¾ˆçúÒĸªœQù@QÚcL\åTåL^FQLÕY®Ô¸£ ˜¬ðÏÀòIzi4è#‰â˜Á>")v¼Rx˜ËŸE|òëöúõ‘  @ž*OÇ{$ØKSî¢orºÏ{)ÊVæô]],OožÏVÐ×+ŸÐë"Òÿ&06V2 —HºDeGW¯cv¦Èá [\jÛ9×´úºÓLŸ K{×­B®¥?2mÓ]Ïè:Œ•Ö…` „Þ"}@6c¶©–”í…¸%±¨½'¸‡iÉÁ€À0>aFÔRCK™›:(êŽû§)†¦*à…k3Aþøâ>ÛÍúoMGïÖ‘Ë(ñÉqnæÑ¤lN!ªXG”¶½Æ²ãB„³5ñ á'!é[[œKóãUîaÑ{×Uf©~²¦–ªØY¢¼ð—i±,“{Ñ!_¼}C~¦ Ôkܶ>ÆòY›~»jMcMnp‰+¬Ö4Vv‡~Ì/ Àšé†ø ÆFt4Ÿ@2¼Oé}ýîEG5cÀ4+bšé»-¼™ö3?I õK ®¾Î¥›ñj aå[¸6mZÂowŠLN"ºô! D|ûU\üÄë‹«.töY֚İG•$~lðlbÚ@q†ˆ©æŒIÝCÛ:÷ªï÷Þ£V'i+°ve_pâM6ÿIîëò³vDíoMâ¼=íþ–ü¶$ÂõÁù¨Ý}gïUn+mU›ž!>ŽKlÿB™àæ:ÄIß ÜíÇV’š{g­›aÓ6ÔwÄŽê›Szßz~è)ÆÆón”-¹°ºpáU QÿoyD¨S..¬ð³âÇ?‹ÏBQI•ó¼Rœ{?Å!×Ö°¨}Ü¡°ËÅ”a¥W=èXÇv6Ïeò½X¹ö-»ª£™f ØÔûnñl¸tÉ@Ê wTf†á×ÈnÄšˆz«cxûxQ?KÜ&qà´UÂDŸ€0¶ÍÓ9‡®gŠÂ]>Œ[Ö>-F*ØÙÛסÞÞ?gw¼´IÈüϼcRÚš'z3€­W¤íWa‹JR%-ˆh }àÇåøNªçBSHg»k‰Ò×óyS9Ðåq›-îU'ð¼B÷kÜî:Ä2ÙñÐ'5(‡½p[Õf]GÁ $½Gg²Ô“nBaÊ2‡'FÚ^8aTñꈭüƒûBÑ<=FÙÒó/ùí¹z2ScYi~l-‚Þ½eïÕð12èœÍoÕ¾õQd>®&"òx¥Ô@^cRö!œù¿;ÀIæÎKmN ·°˜ÏäùQ[²Y>ôolõu}Ñ›³íå —„"ô·Ûobœþ߿Ʒtø3æ¶VÇòM_/A*!|`Ö‹GgöÄ´ŸäYV»´…I½ Fº† ÞA0?mƒÎ”ŽíÞ–?¾ã˜ñÌ ­ú]VoËP¡ô•²&›ÁªGìð»ôKH”ƒ¤ý´G7›_®h?´•èΧ‰¢¾ñŠéZL™O+«Ã9© Œs¨¡I€šüÅá‘#* mCãE‹Eç•5J æçÙo$³6ôf`°ÔJd¤]Ì)NPbÛGcI“(7{¯”ÙQí—|[=h’T~õˆw ÍAy‘e:Ã&"ð¥™å=Ýò¼~&ýkj³š8\,gžÝÆçº°åö“þ`ts×Dqü!žøaµ‹çÁ&ÆÀ*(hWž4ãë8[åmç( Kãì–þVç$X;%Û2AÃ$õà²6¾U¥ú$}s[wz_ÓÆ@ «®dX· @ŒYm=˜¹¥ÑÆéíÊô[QÿA“•?9Œï ß8¿GDé4•‡šö"\ÅÑriñ|ÉhhŒR,œ-ãHj+cKޝÊgõ§±Ô B£jAL¼#³’ÔWAöÒ±á:ñ”\FI¨& id—gñ`—¨'÷à>ÍÐDù•=¨¶j¨yåº× øð mqŸÒø17§)Ëp):¶µ+™¿£Õú×HŽŸ ö…`ÎÚ’U Ÿ¢ÁÍèÔ…Aø5”r_ªÔi™ðtr‹¢% 6ßó’Á9 ¾W~\d=—šªì%Y@)¤Ñ¯ïòxL_œÍsÌ¡²P¸ +1 à¶*S–c´@:ä-t)8bxÿº€‘lí â5üu²p{Á–YZQð G.×ÐãÆ5(Š0B/Pµb‚Éûƒ¿éwЫÚõWº‡Ï­%›1—$Iço ŸNfõõS#úïìTÍ(¿R¾¸'£ŸþPAxÞ¯º›ï……–Xj6‘¼R»©!ãâlà4XÐsÀæò#4¦iøvæÙfÒ‰>ÈoaÕçvÞÖ8^¼;?‹Êér@]rVói.‘#èPGÂ;€Drþ…Çö#Ø^ÈHÙpaË>-®k+ŸyõyÞ,W9ÿ!¥Ï„RÙ¾N{RìÝI‚gY"­.Ê—_¾`9"O=ÐÔH×¶p°¤÷:4ôûij.¸ ÿÌKˆj”„qc¤UM]-›¼>õHww&½Ç6¹ÍÚ2ŒG"¹‹•CŠ%Ò€ù¿½ˆZ/²åÉ FÞ¬±! ÙºCßÍÿ=êj†HÉ·õ¡å+<³©]r©NæÆå;l¡FnǽbMŇÉÙ6°.¼¥?r€bÊÄG}KŠƒl°aQ§þFºœ,;rOS{Àå>.ËHc¹|¤pâàR©BÅÑÇKæ‹LQzNܧºî“¦ 8ôþúœMEÇ$Ð`« —k¤BÕ2¤¥ÄÃh΀,J ûA4.ùÿ'ÖUÿµ›}<îÆ6×áÅRò'ÜåKh”9hd i<ÎqK<ü蘗çÆjÜZ5îPíd¬9·ˆÇbV6Ò¡T¿9«Ú >ÅVº'/üÜ]b÷÷Ú°íÚGlQçc2è[üÝK½w¿ø±¼À‡¾KµLÞÔ.­NÐRLÆV’ÞüÒq®t„MóµIZ&îÀ¹I%‹dÆÞ±H×v°]0ßð9u,ì™ØŠÎþë4·™M‰*ÐçÅÏî#HŸ©¸‚ìhïè¦4§ww>„º*¢ GëfAÛ“ýˆ’ú·„[à¢BÉI®™3ÜSeätˆ>Þ Ÿ^®˜ÔònŸ¾§?ZŒ3üv`³÷r¿Žîú7ÕòC7zÔÿYw´v-õND à]RŽl„L[„ûlÃþ‚lË”µeqŽJ@Ê&ŠËٔɦ9„šzfr¾¨ÝÙ«å]*P£,1„´™Ñµi"^ç#ÌËYE@—  ƒ ¿…AÌò•ºífˆ¿Å6EJ:;c3KÙj„ÞdXÀ é¼q`ÍFq<<µ"¶Á?O~»¢­¨5f+"þß…;m)<˜Mé”þšÊ U„…ç«N–í¸èĺ&e-e9§È¤›+ënªŸK!±ŸðlaõÃL]µË3&a­ŠsK¦ž)f;ê%93³|é¡î¥2¸îp1ú2˜>á«”‘x!Í(U•æ-»1•LBÚ*~à@b`òçîDÃJ,‡i!(’MfµH+\šùœÞÏÛ˜y3)öP¯Œ)´æŸ °a©µ²R÷BKßäž»x¬x«ÍaµâÌ쬎#|ŠùŒwŸ¡†d`‹–Ïç¸ÜæÍòø C¶¤ÇéOº{´ ˆæjUúå õ†ÛõP¡˜ûhq8H+Ñ[4ˇwêœ.¥ªY' ©í³lÄ €ÿH¯*JjÍQ²‰Y‰ß¿ßˆ]½œª2wˆ˜Ï³Wøc™œG—/ÿÙEpVûù-‰™j7§*trF”(7–<9¸‡8ºôIjA€û ríYpŽÒ¦é Ђ[ÓB@'<ÖŸŸ¬(ÐôŽè:íMöà±Î¹G’•\É33Ž{Cfjû"ø ƒ5dV×þìÓs„êÊ6¸éÂ¥÷Ê¢4ÁônÉ&½!É z5˜Ý…[hϵ×ç‚µÄ MZÔG.l´ëöt°7­¦@ ”á½ß€ñmwß.Õ¹Sr—Lô5~8ð–‘ÿ¾+ãÀ•h°Géa.~of#E@U&Oÿ4ù$W¬•t60ï‚e]4ØsaÙ¦ºS oC]ðÊóІopn^w‚~€gÂ3²QM§Xéâs²ÐT§G`–¼Å^ÕËç{R€33s&ªî’(€¡ƒþ_¨ý[ù÷_‘¢4Bc¥*&뜶ê›kç¶®YVZ@OáRCf|PŸtNWý¦€.²óÛ®R±eÙh» mú YŠ ¡obM&;½¥ÚLýWu¢Q¯yÀh«¨jc[µW‡>æŠû‚_˜¨Ö‘N 6ÅLÉe‰ƒF‹ [~þvÌ…6%£î";÷— Ü8ïµÓT[çX: ߆xLJ&{\Í»“Ë7‡Fv0¹mwù\t\ž mÁ,Ê!ÙЀžtœ0D¦9¦ì½š ÊÞ næ#ë}èÛu U3—j,í@»oÄgh Ée°•¸ñ:Vîåbm9¡>n W(õ¼Ü¯sD1¡ÜÎ}@ Ùr#z|à8ñ/zåí¤$ð(l°9>ß:æ68á²$ëÚÆKo­jI­ ³0¡¼(šwM&Éh«_:;J ­ið¡­1#—·^G)}•64˜Í¶aàÃ+ 8ñÜJ§Y¸u¼?'è¾¼û*Üe5Iiˆ“Ʀl¾ÈÖ0aNïÁóPC‰b·SoaS’¨Ñíẕ€­ ŒŒœ³æÁÿÞ°©£QÌðîþ6ÄYzÛ{s •#;Çs„LªuÍPû¼ÎÏÞþgŸg –XŽ>Ý#jOfl⻸ñòퟎ)ò|*íõ‹:x³¥…Ìw¯"ø[½ÉÔLíJ@oÏ«µWaGV”IrJîs‹ˆh€mÀ¦&ƒu<<Ÿæ£nåü?>Œgðäºnõ˜„òÃnLï!Þtn|¿N„Og’ý>«¾I€4#ùô‚!Ÿjû€*!š:-]é2VŸ2“Æ"ã2Ò“&$7›òÌtÚ³±.ÒŸ˜¶Î‹½ï K¼L”QUÏDs/D³ˆk¦ä'dϹŒ ¿W/3見D”·5”Æ&‹òÿÍnªŒ™ñšO1öuÝ^ŠÍd ™±©³xÑV!ǼºJ¥a{w€Ü»PSo·§ é¹8IUUåSsßcím©XL2QPЋ]² Š)‚>ô ˜]‚™- < ­Õf³Rˆ°ì7ÞNtas„¾†ërÒÿbd°ƒºÑãâ†÷ J½6èÖ{Ü(( ¨IÐêTúô¸Uß—/ú~Ø‹ÐGÍw *½œÃéHÄÎnß°æ¿’ìo°]™|=+_¾µªÿ7zTP'ïæ—¼2‰­ÁÄ»á Ôy¶á… £â0¯I›zw…UØç¾L¸¿*wh ÚØFçÊ„Ÿ¯ šnkþƒ¨Òä Ö3~“3],aÃ^•–ßpe¼3³M¡YPrœÅ.ò÷¹øµWtj­Ÿ°Óp8J^™@M¯ pÍ?’yS–Êy=ú/^µ³W ˆ¢)ͧþ" §¦†õý,öz]¸§¢}ù† ze‡gcqò®z˜ëСj‰¼ÙÔ~ïÂy½¹®ƒ¼3)ûó&ý}·²L6rÿëœr)<é{køVh±\,–_¯ÂR·/¦#Úz6.Ôè£q¥x ‚Ö6^Š@_ "J™àýÕFôÙ¤8jpÔCg8]¡S1Pê>O<Ùö¨paû·i¡þ4öÆãóÞCíÒU}Ì-l‡Í+93ZY—™è݉Þ`´¿©ùÎVfÂ3c*d ¶æ JWë!ËêëAŠ'¶‚—ÖÀ\«Š=ä²Ç–Ї©á‡CzEO¡x2¯šc¶ôä°ZôðS˜)Rm@ÅŽ* À¾-ÀØYs½%cµ©DÈò¹Æ+*!îá.PÃãDY+^QxyÚ€ß?óÄÄ—¢6˜ÓY1|ý¯En cåçå-N3QJŸ9ø$²œâI•Ò>«É4‰ø‹°š /œWU3Æ ¬vœ@ÃâȯHûP°óDOUçÙö3ú<~¸rìÖÔc2d]›6–¥£Ê1¶iè*7„ÝLä†QÏÊìÓVu3°oþ¾H ]ʪ¥ç\ÀäYãw4Öíú!¤§)ÏSùèöi§öÁ×w#š_^À‚ýÎ5êÉî<èêq‡ïÉpDÅ· ó#îâʾw?øÏ0ò‰…(œ§€J ²)WtÜœ]×µJL^^•ôx:hµ‹å´oÝd½Oºh¼?OL¬îXü¥Ka[ ÃÖ£!ÏÌ;€\áËN—WsˈÚý–kÃó?,O;ðPÓ4ÓŽA|Ü&F¦[Xÿ^¿+™¡pœV‹Ws<Ȧ¢TU6‹ªˆÌÿ*\3¸ˆ¼Ÿçü¨†Ëü{@þŽ‹H«ÏØùÅ Ži¼¥5h„绌ŽMÌn«ììüÙX?û¯çòF‚Ã\ËÿÉž·wÉFG=—Ö+k½Û8Bú{&ù“ˆ°ƒ–‘BKBdLÙ‡ô°¹ñ|>²%Â3¦Me;udýèÔ×ÃWëµÉ¡þê‡ý‰±‘æÜ 5ÚJ*Ä·Z©øŠðÎ,»;“;<í Zj¯Fè 3úŽïxVj¥_¥æRZë±Öú¿ÞÛçÏ_ƒÇ’S ði*Ë‹¡Í/DVÝ'Ò“’žJø7?eæ˜÷#ư+”¤Åª2Lj”}·cçl˜ÎO†V¡pi?Ä‚~ÇAͬ†}7éªoi+1“vèòÉA›É”Çš k¿‡â°¸)­€Ãƽ½\QgêÛ„î"··´‹!úœ4ýÓŒƒzàlõý÷^×ÚØ‘‡ß+·ð»ªëþÈv|%7E4p¹eª=òuÄ/´»ß[£Yìâ¤ç¬:þh×ïE™ú;ó’j¢uˆ±dtl•é¼}Ö7–;â˜úÚ‘¨çÈ:ºx§ì J^Ddlþ;–;vàÖÍœþ=v©;LÅÂXuû7Ëý'O[1äðGuëÐêŸøðç8¿¬“±ªp§eÿyq¶?o’­â8tÙð³žÙ˜¬»WÜÒ‰…u ‹Q-0`8Ü!)%Ê<¦ŒêMwWqðƒ¡f¥ûÑóÄmèû3N0HVé¶ý*»ôÔC‹Yë5Å~¶ÎcŠX¥Ãf 5Õ©³j³FïW¡z<€#©Šàs¥eo—þ°¶>jµÂߪ‘`\J ËçÛg®ßFƒ|ØŒãïÿ & €gR«:—w2l¤Û“"°á¯÷€õ r/„.¡w³fà¤êƪMÏTŠ+‡¿9AgT± ËLÙ`nàÚMD(I>lñ¥Rû< 7a}“ñ­à‹–¹¨ÇãèöLH5"23å€a±ˆ•Ô€ÕŽYÒÆP6‡¹©àèßFkÜ,f\-aÍìar‚fA‘­CÐѾT!ç5ܦ”Z,æœ\ñL®zßr…†;Mº/LºkC°£^šð*,v¢~·º5£5U”£@Ž£÷p E_#;Ì#'‹!Åÿ•®hIÓÐCñËZí [ àëØ‰QHeæÌ8³1ÃýdÁ)Eï…ê ”D*øÙ²‡èC †çñïûg+ëQqW}Š& 9}lá¨ÖäÿYÞPŽ9qUçÑ«!i´Øq^ß«>I¹›ø¬ÇTE#mqnë±l¬Ó% EgŽ4ÿ⯬ñI“yå‘I–Yóû¯=$XTýâå/pãÓ!Ê(ã)Ñ‘ñm‡,-nȯžÙk.1FãP'ÈDlØÍ4CY÷Þ1ÀR Ñ×.¸Ú¬‰³,—Á½¦­ZàÊÉ'hPþè®ÀƦ]Q䓾¶°Ù;ÄN>Fz4õ‹9áЦ6‚C‘œ¼ÿ`„{*]Ù¡n㦚I\¼T³“ È®n—)˜ÑWÒ&ã%zñ¾oló"'àÄ*» o·ûIçk«­ÖÚ:r›h½ðn&Hiª˜Â˜´ìOhLàÄò•;¹uú±ÜI|)Å@­ªåìàßp®›šWÿ²+miœðeg©¢AÝ2ò‹k~þÿu~Ýf&×ú+8[aŠÛÓ­Í™²7(ûc¦ªHzÓ­.®þäb›Œø9O::«ØÌµd{ €”ÿÇjvüêü é«áûD‰z <‘ô™gÓ6`uxÃR\eÝ?O‰YŽù¡Ð’ÃÛ}ý¹(Z§&9ü–•˜Ü+)ÛÊÈÿc“9pçïqf›œ;oqÞ¤‚d`y¢“ÒmÊùÿš{r\a~"cC¯=ÎÑ‚:ÄüYá4×/·, ˜¤£…2L }_ºt.ºrí­áVlÌ»Znçô8EºÝãGva·ÇòÁR®âÝ )©o¨”Ýyþ3VA›~;5ðj"=eDòRU ©ÿŠËékL‹H}ìo~ô׎Ljy©¢Xˆã”n½Õývã$•peçäÚ8ü˜tÉTòÔÛüµ ³ÂÅ m” e5lï<.¯›OïI9à·´”>§ÿ©²é§µ–cOLÉàÍadÎ@jeZÁE ö7Óù(›éЧAyÙ·N\*Æñþ îx“ç$IÁßèQ©{t2\dµ–Mí*–+ìÀ÷äõø›»è«10Ý8œ=’spÜa'?XilS^¢Gs”‚^˱I˜ R3¼k­•]âÌ©Ib0H#ï¶Nvádx!š4„òÚÜ`P ¹ÕÝoý$e$\NGÖƒQ@\r=h^bBXð"ˆóϤ‘-Ìwäåþ@^X[·W€ÃKô’˜ûCÏ)¢6—É †­$ø€þpzŠóJü¢¬GZ1óŸ»÷!‘ßÉ€ŸðO:sñΩ±zxxÛ9ñ3Ôœ>%Ô+Ö•{ãÓûÇM«¢ÓêE ÷ž½!{âu&”ÿÜ,su·ï:é{ »èÑ@Ž.*m'92|j‘’z>¬PÕ°d¾©Šìøx(шŠNúˆ£cÐp™¡gÂÆLª†”r9*¥?Cl;e#¼oν}.íØÄýü|j3gÐ O¾dGë£]Š[ Ob~ÜßtV ±ò¸ÃÀ}$H~ñÛæP… (<аyÙ~ñ€-íÊOši-›pI¨ÏÕyïÆøcL8Íô¾ t‡ln˜Ö‚„[j†+~þ×–Ì@ļEôËÞ?Ý>ÔÐÀ‡Ñ±Á&Ì1ž¡‚u,¤ùËœuv¦ªø/hÉõ(ìÎ|›Ø?—e;˜œM›ÿ#MÞ%ò­Úb¼ÄŸþ›£lÆŒIšü^ô|À2çÃ¥ëR6ïLÓäÍzÐÀ—ßê¼ë{DN ¤sŒââ‰Úù‡½Ý—Co×ÛQ‘5÷cƒ¾gã/›PÒKÊþ^Ñeð ú×Z¶¶Ž{ {^-½3=Ìm¹oâ6”-ÐÀ&·Í†ÔÝáè¬" óõ‘EÐÄtRK$BM~yÐÚŸO^<ôoŸ•@G­ÛϯL Æ±Rß ©Ïó4v#ÓŒUÌΧ÷¹Wıã%^ðXYë!O2‚­’•æËëoëbBbvî£2´ïöÿÍFðªí6Â2£Ø«4†tvÖui!užkèñ^lÙÈ~ ¼ŸG(WÖ7c˜‹s=]÷N‡ ~·Qghp»†ýìzfˆÄ½:ºaõ‘½€ôÔ6Y+äëÀ²ƒ•&{D˶ŽÞBz÷¹7u˜“…ƒèï'‚§|Ηs £“žòq_k‘øä8ÿÀ"}\š#¤ÇŸje‰ÞåëÂr)ïÐùíÜ6kßx0M ʼèMåo,ñô~@öÞ ëbÓUаw§æŸ×"ÞLŒ¹ª03!ù>‘ù× «y,ïªHíÅo5~'ŸÒþ@D3öéòÙÔF¥h\¨”‘ïð½{ G §m‰n~é¡,Ô/N<ªSî¹%0ºÏ-ùÚævcªƒéÀ2ŒŽ9•üP7v] (ÊKqMÀ_¸;äëí—žƒˆÐdRéÄ­î/n^¥E[£Ä*Q þ‘œ¶i´TlªmaZ~Cèi HðÙéI’$zòè{¹Ü/u¦T–? ìÒn¯3ü¥…•"YYæl„zÍÔÅù7c''Áöâ:·g\`Úóh‰±h=Ü Žxfdd Öånöx)³JsMçêõXíßK0#sñœ—º^xÞ÷K½ÕM6<ýnËoIí+;ÈqNP‹ñcH¨y¬ÈmÖMW ÉRô*dC¨RšøBBïa”OÙ DveœþBC¤^Ð#S‘ôU¾áÿ‡±ªUR†±çy8µò… å‹gîA ÈX3´Ia­È…zørd*q¨`„‡*Èvp•þ~ÌÒa©ôZge°¿ˆÜ"w\gõL5gÖŸS Ä‘qóM¾<CŽÌH=Űp^Ãðnr|-ꂉY'"Ôd¹ÖŸªHsG‡P‘$Ý ›ó)ù0È…aÞl3@C“ZŸ/ž¢³¶ˆD¶9„æw®Ön; ÃS¢ï´«ÞÂF’ÆæE §ÈÄ.ã²?Dv ý'cFà>ï¶P ”°SH¸=Û^·,úñ>Îf2't3ýVWsÔ·vÓ¯ì¼÷…6œþ +`2h‰j1÷ ú~‘zÿ:°«õ¾¢V”µ&1çB`yæ_ŽYäOÒeÚÎ9Æ„ Ú'q¨]Æ"»EøJ_*å@-¼X`ù–ê‹k€EyüNjìRʃ٥±Xä¿1Œ•\BãÉX½¡/w؇ñŽëåH¸¥ðÕx8£9+ÇA öâ7Ÿè¶§#f|V«#rÈ÷p`J€›œJÿ[aÔ«3ìVýþhŽ{¶ç8?=ÁO'DúØžXæœ-,›Àô‘Xa9j¤ÈNÞq뜈 vœ 6Â$ûÔÇôÐ|1ïŽÃ†*Òc[{)rÐä²"ºÿ$³pÿ3TwSÒEþ½þ$Š®Õnj`^ª×ž,/‡!޶šia%-á]ó½:QêCX€“°Cfœ>}†íuy9 Ô:û­,³¡±oKy.)&ÉEU¸D¬$]!ʨ[5ÇzàN?m‚c¦éˆh­Oq$ß²3v„12¾2ÜœŽî1W‚ÉG ßƒ–ìÎ&ܥȹ8•­ß˜u9b%ìxŽ>vâf9U›jé’TZ7·yÒVòdE¦Xe…%£Ç P5Ù¹K‰›JŽáigrÞ(‰ä–Ÿ}c0¸ä½k¡²y¨Õö'ï@ïñþÁ×ýp-¬µÀ` ¡ ·uoº|ÜßTcžµ6oìü.ÆêÇoxªxÓ®ikñì…ñø&ˆ;H”ÒåjËD“dw/Z—§fJ¶Þ#@þy/ù"¥Õ¤” ?â„bÉ<ÓˆRéK°'ÛâòTó­3¥h/!vÊ ü·Ýa& š„4iúeåú i¨3yL¢¼À§ŠÐ†›m\'‘½à¶8Û©PäÒy ‰ÙÃç‡:µVÞH:*0¥¹û«(ˆN­Sj ªÞVšNÿR$óð;¸Ý¦3ÉMß-x¬ø ¦ØÈÔô*Œôï&\}5ûEWÒVlãЅݸJêI•£äí-4>(â⨔ã8)Zܹðh“5._r4\ì_žó[ðö8°*(à[ÇtùT÷{’,.;¼?ãÐ$ï å›q©™4}¹S8kù€?uœBá!½Ã·ß6˜2"žÿަÁ5ä,î0fNÿ9‘ êi€ R‚öÿl¾.‚·Æ5/c«ó°î®PùPÅÆÈîç—p’ËC=©éyLÚƒØþš.çU»Ëú»²»wô˜´ÁôÀÊ4tm9ÈŸÞgÐÖËÛbå5­3è(ßx ·i d]eÎtîÐa;x©½—Ë\å1¦š/3’BÑ„ý¼¹¬ mjÄœÁ£Cl‰¿ »B·_'/|YL²û§=‰V=ŠT¾àŸæüÆ…J‹ú‚–ÕLצLgãìÐÇ3øZ>‚¿¼€¬‘·ÀÆf*"25<…O–½@²}!ý$Oú-‘é6›ƒØ¦8@áØÎiÀêò,óQ©–•ÓªŽÄðÛdzÖj%áio÷ŽÈ×¥ˆ\@>ÞõkA-°…¦cÞ>£²ŽÙ†:aF¿…€‚ÆH`®l&¢îsp´@¨ùóÒûôh¼)U±7µ›2æ)©2ÂòÓØC‹}n_w²» AËàgXe½Ñ?Æ­Þ0%D²«¾-Ǫ[–®&v‘Ìz¶ æD¡aõrh«—}Kâ|®E,ÑÒ\µK‰\Í£ÑÊI÷Ù(?Îÿ|E¤}¿ïfÙ®%û=‹ÒAÈL3Â,‰ÌíÏ>GÂë§ïÑÚOD߸‚²³J^ŒPK* –Љ/æ…[¾Ÿ‘AýÄ,lª×ZÈí.i`ìãÓï ††“¦ÛEÁÒÙk6¥ü>³˜F¬êL?çÏi? ù[Ïå•+X¥TO rê_óW)½ö÷ªŒ“ßWȺU¹)Õé%±’Ô?¹‚ÊøœÏ9¬úÁäïðMp¼g1îf8°¹‚k‡LÚûCôë$VФN³t¨Èÿå<þ¶Z/¬ÃÁ{ZD½›D_œtЀլԧ‡ÕÁiîO¹ã99ù…¥Õ¡rª&-1ņtª$òF¢»A“·@˜£e\ˆ u6u!†„þP º×;Æ2Iyó!t÷Öð6BqK½èزÒùj°¦¸ÑWílŸ_âö‘°Áš|Y¶Q]V§Õ{QyËùoŸÔÛ$ðIJ°.¾¾(B"àœ\ê@.Ñ¥JÀHøa³¢{A]¼£ïW ç¤Æ–œúM˜Gžk»k<Íù9Q‰à‡ËÒôOn´@"|Ãd|ýz d—àcñàt±KþÄ{è©"Ûe©XEšØžh[3E&UˆW#6¯¥m”áßÝËaN¶Tˆà„aîú·h;mú °ÿ^46­·ÂEõÚ[âFIJÊ'Ku~í\FÉ‚’ºÊ{ÎÁzis–ò1qy7øNvff¢'ÍbÐ;„¡Hœÿ_Ü > b$DrØáˆ]L¬„0€ÿÓ‚[gšsñ³˜ögé@~6ÉKÂnkêF©v†h“Ì3ÕÍšxÀkÏÔ˃R–`ïk±6Ò4áIÚîp¸ÜˆoTBwµ@¾ílà6`·#Ã×&CÞÀHŠÒ2i¨,ÐI‘”UkÊ/Áª7Æ…ð‚LÐO²°“ TzOjøXþ%ÄvøPpk|šÐiE“|6 Ù~=¹ƒäoÜ𥈩JK“0:¾>à­?®?ÞXRdL•1aÁeŽc)dvE @^ÊD­UÚ²¤"ÄÆ ¸Dé¶OBtì£ÊçEå“Á°ýöá;§p÷b¨<{«2½±Z!“´¹ŠÐ ¹¤/•6J 0Q’ËÓ_·•ŸÆ"F.·šá @åi<ÚJû‰Êó4OØ/¨ üŒäÊ‚#jA¶GžRtÕ%ˆ–ˆN¡ >XI%«J ÒVX¯t+cl¯ZøUŒ»T,:®wß²ÆØa–ñF7ä F#wC&»¡u_ pØÛ³§ñø¨]b,ÒÃubºÜÀYè‹ ÒW(pÊÞ3ù¡Ê[5x×ö©Ñ²Ò”öòSTÌ÷zF‹Ÿ0B‡ |‰L±bê GõtxÌEK/ˆp| º…SÞ($½| ®yɃô’Žƒ «RVÇ×Q©Фì‘h‘eÖÇ–éZq oó R~qëøWsóÎ27ÂĨ'ì~Þ£ˆõ~>~w<›’s%_ï"}Møþ=“Tþ>œ\£ÍDSÎÑÛ"9‚9WÆ MsFû«Iœwê«ùð=tX†ËØ¥ÙcæÇí­0(±ŽRÜúM:"%Ð(ñfNЙë+rùó]HÆ‘—3ý 7‡6+çã(Bâ®±ýXžù€’ÃIÙôn?¡Û(L`¤Â·Ê휹›&[ÌýKmõªlUàŠ˜@BÓ' *•¾[Á( QjêT¢|î° 5¿¾ vµ ÿ(ŒAÑñ~žYéÖ8?2¬¼uÂgÕ割ÛÇw:?µ"Æ›oÃDOº±tlùN²p@†u¢ÃÂ'v8ù9f„ÏбUŠÃâÊm†`Ä¢Û3xr6ùͶ¡rá+F™c gÌ>!Ã+uø#&ñ4Û)w"ãõÛ¿¾36µÛ/ØÅˆÀÐÊpÿÉ]Ýç”Ò¸îTîÓÐ7(>&·¦÷B­'ÐmMp˜š—r ±îY¦ÄœE`°%AKi'9CçPD·:ã ¸ !ÑÁeå]ÁÆÖn|”üË©iÂ,ÛG¼òg7Îi¥v4˜–éê B‹â_1`Õ1óŽRãT#$çëC?—šyšÃ”ªoލ94±œËH-â¿yôe³ð¬ȸ·`÷GÎÈPJUc•Pã·-íBÑš> Èþ~f]"œ3Fü=%…ŸìYÄ8ÏÎXžÁZ¼ê ¡Wy”²©C±§L¢[ÎØŸ:}ÖÈHýŒ6p¯[½—¤ iß‚xe*Ó{#cÖÛwiäàC8öÞq ‰ô»‰§k›]¤ì³ÞÎÔjÜ^¥qqXÆW(é»òÌîì(v¢ÿ$g?Ë}@ÂQœã*AWk­8^V|ùæpÏa…JÐQø¦œ= f=KŠ4HÖÂÅÝ’ý\GÝÈîsD&á$H$oX½6É!îÄ,¾š0f‹Xþ¤¬¦ŠL]'Š?5ÝsœäPe2bôúê Þ·‹^ëÄGØŸúé&ügƒ…¹„¤€,›‰ë1Ó_ÿö¥%º5±§jEýc°Æ2ò¶ß¥£]Š>2á~V·Ð3°ìÍÄ Üjºi.l)±÷jŒÂ7 4þ?ÿ=¹õ·l·?ˆ­î§ÁSOž„ÎToVTg¡áj¤£> Ĭh =ȲM3DØeQü(ýøý-bml'¯à·i»£R³õ“=nyÎ-Ñ‘siú~KìqÊ_”ŠîŽ2Á«$ZÆ…RJ qì Þ?i;tÎÉÁ ‹Âàf—&¡HáÆ‚÷œû¢üï=­ ÕÖ‰å]§q¡r ì8Ä]\ù›¦ É#Õ»I¯øá‹ìóoÏFm¸‚}W£ì¿Ó 5—äÔ—,öz½¬·ø«À:KøL¯T¼ù›9í ða¦Îy†£qKDû€füÊÃJz̓5ojè´ãézáÎÌÙÐõ¸£ð†ê98*²)Н_¡wõ ÓçŸf<¤'ßÀþLÁ¸ÊêzÔÝÎåa”- qßL1š‰ÒóL¶k÷V4n I~í÷½‹˜ëuË,¯ê$ç®øaj.rÔ-r°%F).2Û¤:fÃ{heXƒ¦HåÐXôéêØ áý­.ÂÜ‘2ex ýä!výVhPòi8‰Ý¡E9ibnA˜Ù€LÞÙ‚XNF¤Çœ`è’½âEô¼+úõ-sUÙôKÂv;¢‰¼PݔϢnúx:â$/{6xÎ= snËÿºæDÇuåɶmH8oãú8@Ë,j…Öý?Ï©÷á&SdæñÌ:¥YZÃñåZº§Íñi3r·&üÝ´°ŽóÊj·Ìd²,6;x¯Á»¢ÒmýVF³xŠ¥6Ñú ‡ü¦¥¡.“Ë<úúD»eë¶Ã °ÖzU80ppZ€_Ô:wUÔ|Š"¬;ã¡B‹F£ŠV÷ ãû¦ Kþ(~Ö®3µìd¶¨ô¹@ø£ñ™‘w–n8&q!çB¯™ÀÊlO&"=ÑXõÒÝ6 »ãI!1jBýÞwˆ}Lë2$?Ÿ¾CþŠòÁß}Ë(*6Ú·ƒá/ 0=²I¬Öd¿åÍHÑÈ`å{P&5ƒÂ!À0t¨üH ¨Z,•T´4:>Š[!È2N3sy÷ÉoÁ¡ž­ c‘U,.w‚{B5ÑÔ#Þxªÿ¿?v\Íwbž¼(8M—±Ó( þ®³zËN0}ÊÔ"k ÜǺ”òt¨z¬¡ºPàPe¼wlxDÊœ֎Ƨøó³×UGi½€ï@ìÍà^Ä0ò^Àšs G÷‘ŒKÏCÏLÁ†«.ÿB‹WI°Ï?‘/ÂaΨƒÆ +Úº;O™¤Ý À\Ÿ@?wÀÿèªìD~¡‚•~kR°¾ó…"<ä_¹úv°ßhu3Â¥‚›ÉDÀ"Gz¿ŸF÷Œò JŠ ~÷Sdèj[_•ÿ¨:þòòF'ҀﷅIãÕX"Ê]›Rym |Ùä0§é5©WJÕ$ó[|4D“dÛm²ÂŸVø³iÄà±ÂŽÄUQÍÝF|ßý‰ºW¥ˆ§ |¿ëŠþI’½ªÝPÇÿ£æ”‹8k%­G.‰• h`qÛı' šñÛ†7¤ Î·tZ ÿÞ:æqH 0úôr†óÓòìkŠ_Žiºk¢D"ø&óvÚãž«1äçÒë…‹BǸ™Î¿“æ)›öí¹^*‚÷yã5†Ö jkû&m.-žèWWw<`nÏ_[ƒ»]cöàpxVG0Ü}MÈÿMÃÅ x´ö iÁ–êûŠ»—ÿÐï›Oµ‘×|ðÊ]”e1¿*§#M)èÔšÌÎ 52š}㔜¶=¸šóK¯œ{/¿yÍcÄ¿Êlç¡·äKDÜj7NŸö¡.9‘þ‹€¿8+hýœ ‹ X¦ÜnÕ Gާqäqo!OD™V ›–Ï×–m»c¯ ûìj¨ÃØ9n§ël½ÛôP™žª¨¤˜êè”ÈÆA2¬Eý2ö·•$y#>/]ÓJëZ¥S¥" ,~†°Í“Ús¼eóǹØUñþ¦Z¬Œ'b•"bÊ•´!ÿzH‹lùÎ(–Ðs:íäýá-O]â–ëæc¡Ðœü“áPÃøóýæuOÀÿ嘉ø¨·ÌÇWˆm‹º"æ“Nú)>²l\¾(¶‹Á"~3˜©û1E« ÆoêÕæÏÌKË,`sÞPÞš @‹†wQNäš³b›òé&µŽ.Aì¹zz?¥O‰ fôi*Ã΢ñ®ZÆ“Q8 _ô*³ˆuW’êPÎ6QÁƒì,œínapÎxªøg¦.šŽÓõš_V± H7É´¸hãJÓ»|Éhì¶¥Óo 2pl®³­76µt4ºqQeN²jqßû W:8D×gS³ÚBzaÑö‡ÝRÄ=q‘þ"’°ˆSÌUH­aò#¨¤ßÛ‡ ß“þ©÷(™ÌkÓïu±$‡‰ <é-0¦þy”’J†Ðã½&DváÀp#îX+üä×J3¢:ÿëç½/Ãf—áŠÆÍáGÛQ¦!ËPÙÙ¿Û¾pŸ|ˆ¨tèpnšÕ°¨Äð®‚Ós¦¨î³üQ÷‘OغACïáÍ/Ó²Vð¸‚í¯èDéyb‘ŒˆïYñÅ9é>J—g)ÌûU³†±èä2 š‡ì¼ŸòD|ê¨?Çú3q«Õj‡ödBÎ Š_ày£Ííi9“qÉ?&ü–a¦­6ì>û‚Õ".K‹ÐE¼˜á³ºÓ¶ÙN>`ºß LŠ-ÃZD¾7Þ[¾ …7"åÜ6øKòÍL·£ ¥ŒSçô­‚LVú@N´"¨Cë0ânߘJ#쨷58ýÓ$&ˆÆd/ؾpÊQjÁ&¹Úÿ~’7ö.³ªÏ‡lT"¡«úÿ€#m´m¸3q0¾£ _diÖÁxñ7Ur ѨÛשSÀ¢WOÄÿ€û$¿47ø^€¯f¸üê-û²ß¯ƒóÀu§ÞUZ|¹¦‚è$Ò}û5Éž´—3?Ìèí;.Øñ5P¿ÿö¦‰KTkW˜u†t·ÁÚÌ8G¯YPØXûÍ„aúEP˜2ŒÒhˆØ‹µ¶žHGv6Ž C¬$%‚‰´Ñ¹5Öþ`3%7m?>€ˆ¿_ %zƒekÌ/pgpZC8algEp¥ˆrî‡Þ8c~zå@ämØÖši "…cÞ11HÕê¶ß‹[§â6B®ÝCö“9ºÍ˜ijŽÃ òxB"ÊX& ñ¨†”mäúð¿8)’8'w¹ªÀ?.€ßãUóÐb†‚j9¥9¸ÖÜ…€sôÜ“³¿óeêŒê¡šöHK{ëÜV#&žŸ÷…²lYÝCõþ>ˆr(¯M4«]ñSÐP2Èl¯RÆ®Áì½ôJÐZ”Æ_;Ûê òY +4Ù§S× 9¤‘çèÝwlµí ÎÓ&p+ŬÁÅÃÌ~.ÑiXP/«s„áÒ3wK‡/¼^°ܬnÿüð-·i ¹Ei+Í÷4ûœTWðÛœíK'z²ø·ý¶O"†ìÎbË tN úÚ>„Ñ cxˆe•v`ôaß“&Ðâæéy¤0o´ü¶¦‘n/Ìíhw<.$´ X¿‰8[ÿoù‚Óh–‰-%.‡ÀYrÛ !Hݵe󥜹$SÑ;øû›û-?Áˆ)–¸zfêP¶SíU~ªtO´TÙÊP¢½œ4 Úè/¤Z†ŒÚLàntBêò±äÙK"(‰ ÃfIÌ¢YÃCìëzm£PeÔøRZ[9BŒŽû¯¯Yû©Om¢à̺ŽWñ(y䬈¥HèÙSϹ¡O}pòÇÿRôïko$S”aƒQðxáIG[ɨ”˜‚ûQ®ÀQ{‰tC`9sÊ,ÖŠUòÍñÕÜû:y­=è T`Q¦Y_û&Ú¯V"tϽߌÞ3B/ÍüõØ&`ˆœ(â&vÜÄ¡²ƒ„ ÿŠ]Ù&¦èd $w lÈÞ1°§¨Í S¤7XÃHb1Üîÿ—N}Ôž2)µ-Õx)— í±ŠØ­ã€û¾ HÍÓ6 )å#¬^d™_$ÊÇ»¨|€›ÎŒ"Ô‹U—œÃx¹ƒ»9øw–ãxÜüç“ë”…%•¥''€þNAi6>rn“©1»ŠwÇK+6”^‹˜H&ÄK•ЇsÂ.±Èö“âõ yL“±iRýY);WšÆÕÆÛƠ昞¬rp’ÓTê:>ü/orL@ïÿòúEÎC¶Oö¥6•ñ¡‹ë j°ZÊ)M͵Ãx5?ÓWš`­)ííeºìMRÅvÑD\T n‰aœ lRíÞFo¶ì[¨!·1ÌÇ$…H_â©ñØsuÿUwÚßÖ1¯„êó˳W]vιlE"Z¥rg~Œìù¹ŠÖ‹°ãò­(d¹“cxÉ_3á[ð-Ë nû%ò¶~-r‚b1t¤1Î|²(FnƒC3Â%µ:MüÕŠj¢wù©õ£ÿÎÒá[Q–Þo}¯¢W©Ææ<‰‚nþ†«…Ê×Ù6[)©«hñ6—½~;‚°T1ðoßD¨×ŒšùyÅ1´¿% M„γÇ|W± ·óØwîLA¸ÊeòŸoù³'ËÉ Z0†â»à’!œÝ©y2ELêº=0TcHX'/-3D¦Ï²‹LÙüÇš²!¶óòÙYÿhîá¨xÚ–Cçæh/²Y~ÜÞ_OþÚ&Ìa`ÞGéè!0„6¡„÷ƒm8žYù ±8q†7fÿrtbͯ ÔoB Ð.^ËSy3ŸÑXβ>mG ÞŒf'7Nã/0¡AN(§;/$S£VÖK¸^ x*J¨ÿ(¶Ï1PÏ£­(Æ|:ìcç¨9­½-ÄÞÑwöWáy‰TZ"6ÞdpT¯âfLoŸ!,rØ|ÅÑ)O™ K[)oí¥î”l•žÛÓï°šÛÇ´²XIR¥ÓõË :+sþôª(DæÒö°PùaÖ"íxUϘ$Drtyðµñáƒúž¬ÜoÜ雄¤x؈k qboþUœèzϯ“·¹$ØXG$A$ä;*ce‹w•ïË=f¡û3ÿÞÌÑw.¶*üeîɸêGýÍs+ôÚéŒû‡¸‚ƒpa+Øß\åø,}ß´ª‹Ì4:†ÅÕ¯áÓXEb½£TÆH¬û ¼ÞÏq|W¢ªøP Ê…z¬0¢¯]³¬™Û¼gœ’µH«ËÚ[û˜j ^J½Ø`"’BI•e á1¡={2¤ó¿<\`3!€gWiºOÓNâT—ŸZš€Fù˜Š1s¼Æ–ú5T7n)hJ¬ãºqJ3ý–‚—ÉÅ7’7}½ òN]Z\fÚÎq^ÀÁó,sï¤%7þ‹ªËÀð‚±¿.±ñ…dDÖLï’”RÓhe€r¤Ìh˜¢]|ú%bK«/$Ï.¡ïš¾è5¬ü#qð«[¹î,¿8?s¢VÆbÀ2 §Î€’ôƒIô“yPVñi¼¶üx§‚êþ JÀ÷ÉîLùfÌ¡zÙËzú’N¸Ai‰«?­ß,>þ0®Å›Ñàd*ß>Å?©-~ÿùÔ×yK6_>"0¬q¹[ %SôiSV jr€° ç‡Ipÿ7HðîHHj¨¾™ „¹ß#Ü–MbñnDÛCªQ>öÚXOhÅOm\¯ò¤-M•ûÊ1TeðA{ëM%…°Ä5–Š<¶ÿ”zÝv{ÀU=ÄÈ(÷ÿ/‡«XÈöy!$B·þüûe£7P[u¹ßLr#ôÿÀµ}ûEWdÑÁf‹ªç]†Õ’Ÿ}ï7°'£Ò»¢ø`Åœ1·×øÈÊìüOÜh^xPÉ¢K ~îëPGoAD ÊÕªÒÏž^ëPa‹™Ëiâmqý|¥x±ýr?ÐÄô@W†uÌó?™Ñ£Èr£ÇcÃyN‹"­/$Ö‚±H¼aÖ ¾Vk­ýíê ŒuL7ã¡0ŽàÏÄ{Ä%Ú›áú¾ÊxÐÛ,¡${·ä‡>5TÇÏ`¶ûûWù;3ÌvÀž¼!šÊ<|F\zï\q]IkšÙË ³,&æ»õ»ÐF’Zu°ù›ÇKiØþETqðRQºúø‚IJΧz-ü5j+ˆYÀzž¢u×òx¡ì=mü²j>»¿VdöæVæë¦½HÔ™‹ycòvø.ð1~ãŸrAÛ«žQ#@‹®îNs·Îå@ T‹9ÞuXÉB§Ón’:†,›#ƒˆdu‚}ì´¦ž׏=hd¬þéÌýWXÑŽnLªYÕ"Bsz5ÄÝÌm™B˜®;ÈE5nëõ™‹",uò•³Béif·ÇypLºÝ>¹R 'Q{Q@ˆ y«™Ì?,ü$©C{ˆqEQcc¾ói–^og„Á±UÆj—‹©ÔR"À|ç‘¶:k±5685殜Yö }“ÜØæ˜þ–CeóY-–²Žiw3ÙÔLºŒç¶BpI[z× *Õ÷ ù­£8¤çBǸÁä±ïR6ôâï§k£^u€æ¡îOd2F´{ "–„0€¾^„È® ¯¨³ÆvL=z«–¾í}° ÒP>ˆxªérØ/è–O­þ³|Ô*êh/gWTGc4Ilzç³Yæ?g}ø4/^\Vµ0†â.'1œ~ì*¾ÝarÓĸáE iñ|¬ Å¥Ï ¯å #Ë*£-‹µ¬áÿOA$;²ˆ§1GÿvYü0ë„….‰üïñß»Y¨‡IžT­\‡<2¥ž”¾{c:Bt‚l&ŽÑ¯7=ðÆRy£²Öð‚>À²@ˆö3à´Ð*†X¾~Ë:†‡Ò*†ú×P®ÉZKîŸå™!Í ï¤Æ˜„E>DCÊC9èC€ºnÀ6d8ÙËÂàw¡P²ò‰è> „‚e ã@7üç¾PD‡¢fr}?2X:öüm:aG‹_ç– ˆmÓã—̇´>hú½Ìf0ke£I†;$"(¾q`ˆ9}oP»†ÒHŠ.‰Giu^€ éN6ÈíÑsçó7¼àÐæÇ7£µ®Œ]Pý¾i1Êç>²"†B%™‘#aæÅ¥•â'|³J°Ñü±4P™¸¬#ñ|rÿ9ƒìêN—¤±Ò¨@k'ûÛ@f+Mt¨;ÃEEBŠ >Å®µÂ”!î¨BH² “)ÆÙ 8:¹þµ‡-T<× ‘¦Ò¶£0-™:xþzëÞ2$Ý/RçE—ô8¨PD½t,ÒE°@xÞ+h•4^Ê”Wœh œFÍé7)KÏ©`3_ÂÁ”å¯%îMP£,ÆMu¼–vö]š«;­ÊlñÛU5ÍG8¢ÿ2gêþŽë§y´rçûÁ=¨Ì%®ÉN{€P\3Ff]Œ¦DK)É£ <+æÀJ¾Ä'9Ç9üÜ9×IžÅ\þlˆN 0/ŽºDQY§¡ óÃüex°5âœ,Ô€9t—èãúíiL59™òSSKN9M÷»0ºàfÎV@™Šå1ɬ¢*üåï©7Lš]U±×þ<=,ᯆErÛYa ‘¶q½Y&ît«–`´%e~™ÛÁÌ¦Ç b†9)þ¢qtÃn­_ëÍÏö)ûcj¡ÂÖ'è7Ô&P"lŒÏ…üS*<“X¯K¢Å¤…;ò­„Q½Ð¾:ßj™ÊGJl«›HÓ"R—LL={W<Řø[þ`ý5؄śy)ùg¥½›2ìªÙûo…êæï£I¥õ”Ì3È#¸Y=)-¬Ò}huBuÎ=A<@†€|ä ÿM¢„ä¥*&×Í"C**ªÉ æ¬ŽÙë³,Õëƒ<|ªÑãEÜ­Að=!Ý×ï:Œ÷²~}¦he ùV¦MŽÏè¡øVGä'¦¶ýAs®V6Vò·æ'Hn¦{–ª÷Ò^“ÓéþN¬ËÎzô»Á?*Ú'g·,ƒä|$ψQýÂC+ž†ô]®l<ïÓåA1 KDÉÚ{¹Îè!“hÅf,fÔ¹x73Ð ×äP£ŽN WÌ[1;Z#úK6DWN¼&À[ïÿYxNÌ.¡¿ 5¾<ÖEæ!d£ól÷52(R3lþåÆb‹­1¥l3.ö}5l&¸ÈqÉ<Ñœótl>±|n©ÊVÜrª¯Ô7,ùy–¯a@Ú?òabSDHÿ Î.W‚c<™þ«…¼3\ºÊÎ%»Æ²ìad^Ù]ÙÆ¶{<@ »1ýhîÜlvw”Ã!ÿÇT\²ÙGú@ïÓ[…£ƒzN×ò~ð‡¨)L2I)6oM榞lîÀ<ëðÿdL©¤‘Nà¯þムño×[—xŽ-…ñ‡Ú;•ô)Î ÃYU.ò¦i}b2£ð«Ö<3Yݦâ[«™…®ï}c6öˆ ઒‡_¢Ÿßxå Ÿ^5Ó%‚ÜStõù9òm.BFÒ#µçMù˜´·oß‘Zò€¬Ûo®UØ =6òˆRóöd§x÷G“®‰ÉÓ§­`Á£ÒûVƒfÿ™,•î±u/›a[}YÈœ¹ùŽšÆß`°6)á †âž¬Á-R)á‡gÐZ­Œx—Z‹hkÀ œºk&IÓ¥‚Nï||6lø¤Ím^åû=ù–êe÷{]­û Éo§ÒˆŒöžÍz»{òzwbh“’Mßêÿžˆ‹óÛ\zFû•ï2x¦h†ù 걯wáw–À2mK3IT(,b0j½s3W4*äLÌ•.^1WåDÃ+§vü˜¥²‚£¤M!>H‡˜Oi Ï—õÜtÈ ÇùÁ®¿æ s|¦Mظ2ûZ@Ê 3±¢‡ “yh!þIÇìý—LXjLH‘ÜäSò­Dd˜‚ÛD ÷"ÊnÄ„÷'0Èa>ÓX‘ˆí»–€³%zï¼VÿµOnÎFp‰›¹lVMü„Y7&¯YÓ/Îw§|Ÿƒ´A(GAV›¦Ñ6{B¾0èEoV¯\#ðÇ„};žÐrT+û²¿î9Gñÿ3Æ¢èóE¶>¡}_'¯4ÿòÑðÝZ%Á£:fŽÙý U§z€²Áû–…”qp8œÛû.þr›‹}/#jTÑäÚiŒW ‡B*zQéþ(O9â³^Øé<À£_=ºÏEµhŠb›ŠBóYøÐ`)ª„…"iÞo¨áÅ22þK0?¹fëWÑœÖDQG,Ñt¾âÉ üŸ~-_ôóžzÕJ0ìÖE‚|\ð¡`¯{ Œ“Ûè}Cª¤çËŒ•ð>¹4*q4Ùý¿ò¤bW׫:À¤Â‰gvζÔU™&ë•å¹NRÂzqLÑaµX»6š—®"Æá4Üé½G Å#^½¬S;g®¶8ãÒµkÃâä ù5îa´Ê'H•X Ö6¯”ÿ¼ÎO+¬Q¡nº ©Sð/3¿KgmZ^ùwÇOÃ:´ŸÏ³.ë;C—bßo^j6ér}§ôª¼kLÀ-Ô†nEɺƒ„Òãh{ˆDôôÌ—ìüœƒÎi‘[8ßÖ˜ /׌Yÿhp­ˆÏëPL ¶Q´=K|kô™‚%Š „Ñ'ò#hª¸s Ã­—äÁΖÅWοz:n<#¼åÃ<@{%à‘Ö4IQ‡~Da¸iZ0·d]>‘²´¤Ü÷®1‚PµSÊî‰,áèèÐãògrÃW‹Õäû•Ï¿MLu6p©?_‹v=í²Xަs‡ÂkIä•cT³AN³ØÒ liÌ3¡5K©mºØç¥\  Å”Ÿé\ÖŠõ§hÖáü ËVMÂâH4²×51ûÝŒÒ ÅsT¡ërúÛ ¼»dÂ3»L]ßæÞᲯ<èÆ+¨p1mßÍEê¬å ×ÍwTARMÄa`Î’ iüÏ:BôTæÅN½jzõW„¿ÝJÏ©ªîk‡Uó-øª±]QÃkä–Cn˜# "µõ3ë'•ÆZv¥èöþ`ª˜€ÊŸŸ#&íÎÊ/C× ]¤,d©Gwðþr):6Á à#/ZhvDùŸiкP~Ê!]8U«ûsè{MG©—"ù3ƒÄΘþU•f ž$\(¿"€ö#DvÅÇ ǰ;ÅÝ.£I‘¿¢>jw,0IÆF7Æ‘ º(×¹b€3%жÁrÐ…nÖ¤§vëÆfÝ1ǵï#¡­#3ÎsuÝâÉ;üXxÕüÙ  ™×›üènisÙ¥éAWheqÙüˤ¢™†¸áî9á9¡4Î1æ–IªBЂÐßÙ“€Ha|ôÈ@ò®óÐ*æÆâŠ‘Ø½·fR`ñÓe–ê_×ÅMäXMî‚öÙK¿.Kûzk'Áyÿ»¶8Å™ö ÄÜ•è©z¡æ~Wƒ‚õôm~»ÅöÉä¼à‹ø¬o-15èÓ;û†dÙò4å*`KÚ¢ÕŒÄèÅ@Ò§€Yû˜@EG0à½54_g ÝLJ$§÷vþ@}[5PÎU_¯MϪÂê‹Ó®Ú:>Bï"…ŽTËA_Á—|¿Ä ±’æ?!%oÉÅ¿®€ø)³šyý^™cg»Xj"©œVx¡Në²ÄDØ ðCVÜ»B zChƹü:1g,œ²½ Iw€…ØKPgóYA¶R%cGð³½ÇYžÚª50Xh bE¾‹úÀã‹/”§>?Û¸(Áós¤ßÿcêÀ?hÕ¹50üfgJ’´æ»sýRX|—‹€ZU@:wt RÚäãÄ{N9@,@,E81Þ‰Œ ö¹å̲k¢Ì‚‰˜.׸{¾ '4|ô¥cùN×ÉíçñßFÛqÚù8t|iôÒ˜*ä6¥ça˜n¯tVŒë8ø€Pðgƒ‘½•Þ¯‰åo6°sœK ]šÑXùkßøÚݾ¦š÷Âà§4w­F¨·*yIpéûŽùÉιt1Mº9@R;y„ÙÜýý¦È­ÅÔ€—p1ðhEÒ&OÁQ¾LXÐf‘*¸ÇöÞ\Á¾ètËå%oÞ܈áÿVbmxÙXXÏ‘½wRdÊ\ŠßÐâ6÷i ÆçŠ•Pu6»`¤’S¤«¶]]ûJ8Ó«0ì‰ù|’õ+ÿ÷m!eƒöš .Ü/‘7Œ_Peìíror“Ües˜‡šoŽòK¥Å…M 2¢ô̸a@0m¹9¦c""òˆIŠe¾¦pû Ÿµa€þêa0iV -¡Áâ2Ù´Ýe „"n›a¶ƒƒ–o`«ÝGÊñªƒ#$·K[L£‡ôNó_L¹že¢lŠÃëænåÔtŠÚˆ^c½°²×ë†éÒ¥í ð_ñùßñä„Ðm^žOÌéW3tbá¢ÏsÎqG¥uÑ U2ËB­ ñºT:Ùü¼îi®ô6,|Ç­;ð¶æÊVØæ°P+Q! òÕfäçHº$Jt³ÏMpüкÁ ,Ún B•7Õ½¸½Ø¿09ÓîºH ì-&ï æFŸ¾s “—oxxrØO/ªùæº| ™Ïð2–ZÄ¢¥Œ¥ x±®X.åFt%IÅéZ¡†Y¸ðYK¶ë@/a’ýBü¶Z¢$щ~:hÁ`À*»¯zZ´©ŽŒ8hTìZCS—OehÉ/Ùäµ4ç¬qñ³ìÏ}ÅŬ<Ô-ʋʠà•XêÐÞS666Ê¢¡ècè2K:¤6ç³ÜgÊzùRÍ”Y¶ N5 ©ä<"ªVÊ¡`ÕÒ6¿ÿ“jž*:HjG깼ܫ“ó÷—rï4°X¦nÌìÓŽ‡â]"F¸S›ãà ë?ÄÓX3¯]°1ŸaR¥”hщ,v9K6ÑáÄoÕ¬ôÎt^:Šý»3ˆXªãc“³‰¯ôVÖ»¤XÉðT ]—Å­ÚŠžšüj^2ÒDÛ tãJ ÞEîÔ[©–¬·•~AÔ ;BêŠÌ¸ŠŸK²©Ò½š+³’Ä*›¶í˜ú%]“úF ðæ÷VoõQé#÷€L®nÔðöxYk ¸:,§kÛ¥UÝgÂÿ°|NIæ¥XÑ¢ûÜãûÒ!|5Š?B£QR?àìÃÖÆaþÍÎÆÎ´ò}oð˪º#m”­Ô‚ßÅNóÍ ÿ‘vš èþñä“LÓs<èÊ…ôÝIìb*¾aל?@ûÊ2)þmœ ‚· RLh&ر(¡™K …^Æ×”™¾uô ô9&ݨֆ™Gî?\ÍDu!/W54ôõ¤ØÞ;Ý`•Bê¹Äµñ_Ú=9:÷›ùü) !(¬Â0åN²>¾i9 Læ@-kIŸÐü}kïß]%â,2gN«—ˆ¢€Xó@êk˜Õ“µðÿX[f™q|„ØÓ_ÀMˆókeE£Ùü4F+`¾sÉqŽd¸[j™·Ç¹º€È½z݈dø³âJXþÿ8¸›Ã|:|,Ý‚Û9‰ý”x_¥yrÙÍ–h€´ìß­-eÕE~U´^úÐ4wÔÄĽÑLгÖ; 8ß(ÀíÓ?“”y†zEé®Êù~ñŽËÄõž:ž›€êúÆ%ù£ˆA ´d¢™7MØf¥ö¥1rô꽊†«,¨B嬊³r‘Wñ þ^8ù‡gé¿ê\yY”‰+2 .¼^Ÿ‘&œƒr$°ß9I`xWËÚÝ0YV¸;z$E0dŒgHò®nÐ$,k›ûWB*8K;=\Ï_ÖÓ©#¬C_Mx<…Ç2‡óö fžQÐîS“&WÞŠpM f©4˜ãZ‹ÎŒ3 v¢¨/)M¹¿Æ?Eæý♼Å=?R6,²õô–WHìâRµy0ˆrŸûOúek·Ûb J›øó¹˜ìazdîv±X—oQ0Ó 2Ì9¼â.€+Aƒ´¤Ý? ’CËËS?ÿvOä 1àã.µ½ëe·Æ£¡IѾƒÑÅHE53X }†Û`ѹ]`9Ïåû²x;†_íx¸ZLž5ØZ~ÒL@DÓ=&}5E‰¦sˆ¦O|w©Çç•1ˆ §…á•Õ™Ö '’ø$…X>fæ1ðA×II7 ß …¹‘Å…pp—èyT;º<é$©<å'Â;/æ5å7::æ²›CJ÷w¦™þ/Y oÝ–¯ñQ4»3ÜnåC_{ª£¾RäÛbCÒMÅá~ïr>ÐÝJ_ž,f©òç,'c‹ƒb[G{Ñ>¸Î<¸}ž¥­K(¤­4]rå^·y%¦EŽx˜\B8iÍ·tÅì;L“=žDŸ’kNÀ÷¡ª—†EUüìW`A Åf!², ‚Ùú-â¾ãM^©èvê Ó¡Õ›¤˜Ô*izB¸œÔ–ëìÛ·H¬Ñáyn"›ËÅÒäòµŸ¶ !ò‚r\ßÒ­VSàÊû¼JŠhí©j›-§õ?$³tõ¡Y9D Hã±h[ÚœŒ.qP%_ÉÉ;ß“T£AT7oýu J2‡KYNøsà¥W ÑªÌ±$(y¾ågéÉæàï±¥\7™Ü7(HŒåG.Ô»re¾Ã¶ÐˆávÎt‡_ÍmDôÑð±¦ëc®Ÿ3ÜŠÓª —³:¹0 ÷ç*0í>WUÀIuk”uq2È bµÚYi\)l{‡oýHݹÅì©Kª¬õœÂlñ´ÞýÿP¢©g·xÆ•@Ãz“ÎÑd8ÈÚòLÿTi¨°o¿tÙ².xu9ñ{]ÈÔ߸~sˆæ¥_šAe:q™`8 ãPŸ5º Ð\œwáW¾]/ú¢?zôd×+~tè^t²XšUé 6¸2}°¿5ŸŒrçé>y±¼²¿N‰6™©Äup™Ië&ÏŶ—¹tòø¯v¸‰ÈD(Jø±¨F¤Lmç¼ÒYá9ùª²×·D/' ·#quMÇê”1ÞfŠÎær÷Êï59Ĭ‹ŠÄÝûÊQ%ÚŽ÷÷’î 8ûßÝelª¸ Ä.2]KÓ ô·«ª -PqDºÓn종‹£Ú,”rù¯ôßøÑÊS´y¤2ÉÝG†Lð_Ð$1²MŽOìë-½]Lƒ0¤=w|?‹§2ßµ”Ô€ëß±yo-OÅ}£% ï÷EÁ,Ôûa|úÝŽ”6:÷B×^õ‚¥T\˜€ÁÿúVu·†ú`riïþúWè'`‡öÉ ìŠ¿Ü•Ù¸±îCW=0ûïêÙvk(-)UCjÑñ¸Üz:±=E·c¶dðk]·ýz"7³fVͶR`d‘3ݪµ‡üEBOHØì Þ!`͈¾(IiîöÀtQÜIy{ÙR½o°•‰º…‡ÚÇfÛô|ìjöôÄÆCºfZv‹ýz©F½JÅZ¿?^RãD]„"Ó?P_Hû~ocKˆ?§e%ÂχS:G‡%•w«E¡Û¢+"À¹:¼Ž9Ü&xþs€¨9u™ç))›Q_„Á\Æv,Z‡5t‹í”5»í¾#œÆ£ÛÍð)0•Aj6y0W<Çi Òú`æ®6ÃõÈ Á©ùÅQ^õëMYƒÄßWèp| j*äþï¹€Ö«n^cn¶O¡1 n\_ò}= Ñо¿ªsäÜÖ1XJm>±?äåƒ+qSø–Àü%ì‘oÄìœàÞfℲ«öJd¢Éeãß™žÜ ’fwŽiÈ‚²»¢¾ác*‡ §¹˜Œ{ó¬‡V—¦œS'NIuT¿Àe5 ÷³yµ9ø&÷AAé8½^ârvR§5• ¾†ý™ÆóÔÅqâ?7z•ðÁXâ R=˜JÚ«Ž¢~_]â ¦šËzÁ¡òs ”:ÆÌd'½eO|ý´œýsDG:2~2M;™í-¼´iä–^??B×8FFDŸNh2Ž˜‰Xh68Þ〈ÔËÙx({Û@v ÖŠÙˆb gp Ic4 õ<»Ñ,ä`IØ„¾ÝÒÔô†|ex¿’uÅ köÖÅ|>Ïé±i)/0a¢ )ÁmŒ#s+/Q㇗ƒJñF€@=Û&ÏD9xó;©eTeW}¹Y)ý˜gä@ñkñ†?{–’PÚæ9ÐÛ÷|¼ÔÒm6Ÿ²ËÚOdúì¼x:§Žÿ.ÞÑŸ¨]Xruñ^'l­ÕZ¶ö«ƒüa vžšûTÅ‹…üÚ8PŒ¤——µxÎ ]nÐðæ.†FA܇ßÌò¬’ÅŽ>x:ÊrHu²¯d_bÃ$W‡¾L]Uµ/’'¨éaôòWF ÎZ£ºááÔRáeA¦®‘˜Z|ã|‡Kÿ9óÝZX÷×½1oó ~g‡¢ '9Saõ¨*¿fÌk©êÊj×äÄAçH«ÆUÀ:ñîE]o°3;ÖÚˆϽú%ÛbÝ%—\Gt·âiâ3B oONë‹ù(¸˜êx $–TA]율îS'ùT¹.éû瓹œnA¶c_ 6'(vk²xÝrè)éÖ°h!ð¼’1|ɼ®JË8xW^jc.äÚÊÞˆB¤<õ×ôža +^üw÷ê±")TýΑ"gɬۄ™2ÒäHUÛ•ù1JçäQŽkOÞá,„Ù››ºqÃMƒ8HÛˆRˆ®|Ôú¯žÁˆtëÄ’ÒŠk`Î~/GöпÐY†£!¡ªš°Ì“QÆä&V¢_èb)c}Ò/<´haqM¾6È=›T)ûYûaF"ß6olæOH²bp0Íé6Þ+ļïRµO„'´³£JO|5C5Í&kÙ@ù’³\Ò‘§y#hRR^äsm9AæêñR‡¯<!Zr¾E9ÈrI5Æ/»ÏŠÐe¥ÓUÿÓݱÁ¿88Â(,óv®L9’ ýئ¶÷‘…|O(YÈúÀ«üÜÿžó;ÔC/¨úY™¨ð-%´úÌ% Œý÷· -•L˜u1f'á!¼lÓÁÓ?rý㌳WYw˦FŽù ˶%ˆZK‹T%l¸Œ°5©{WÙZ R;m²õ[–IVd2tù.­Pö/¡¸+¥W[Uq»ŒÐB\@å¿ß¶ªÒõ# ¼í´déô…¿ ŒškuˆÌí"ë„1Ê=~ …ù¥ËÉ‚ Û÷ ýÔ‚Z-Ów@X*»UºÂÞ¡u©#>Àðסq È8‘JÄýMá•õy@£ˆÙ¢ÙŸ•¡cØùCY+,Wç,ÃÀÈrfÆVûéî씎zE¶w‡ÈËÍŠyЕÁ™[e_쬨ãêPÛ-Ç †‰ç‘Û‘‰0úù50:,œ™Î\>ÜJ¾ÅÜ~í_o[I„í/U0b“¡ÿµýÏ„…f34h‹cˆùFÎÄ£Jl°Éc1Ó»)^¼€gá’ÓÏÝeÜ’Úðвªù¨ž *RHü}Íj±R©íy.åÄóúqÇ>—¯ë·E[>K5˜†Y1G™æµÂáÃL…ë¦ñÿ d·¬MÞ9jÛeÃ»ÜÆr晽ØlÿT¾É¶øÃñÚÄRuˆoTÆõbŸ3Dëjrí æP@:Ÿ‘šM€8Å£×ÈN”`N•­ù1jËæŽß)2s· ‚¯Xo % ½¦c£'PL†˜ò»¬Åïþ\üA[ÏT{Ôꢻ.cæPq×İ«ZFÁñˆ'jzÔ>jZL±J•XpžOí#~Öí•Î0ÛŠ4§/Ñ­ß—%ÿ‘žž\ÈÞÉ|m|pfÓPSIçšÊb‚‘j9 Ê)¡>±b—N¿Ò÷j%§ò –á|g¿ß€sLG¡47S+š; Hj/|Ož6àÚ¬ŒòÍX´&UÌÁ;wT5¤è©t…ŠIßLø tW9.¥b?ì€êìá¹ãÀE'¾`.eÿ&.ï^HüÑZÐf›¢ÚÕ}¹™ãø©|ª„%jz5îšVŸÝ±«½C"­ùeU…ÆË ™%¢O«¿‘ ÇN1¢<Õ‡L|Z×"¯¨¤Šd޾YN-§P}ÌŽQD@…B0Y+ã_;ß©y Åuxx–›jÆs©íq*›•÷>°ïÍ,œ4y§…¡ä\?—IËá#`Îúš¿²´×Û¼í~ æ®íUÔ‚ë·šÀÊ{ÂßãWmˆkƒÒn( ˜ „q¶®Âtú¼&ƒŽ]ÛeÙÚ€g»awIÓš*XÕ†ga§&©¤ý%þiV}ŒD„¼_ÃÿJü8€ÄV;G–ð•ÝpŸžõŽ}89òD0ö{ù2î·ÏS—æLÆDðË ŸXÏ’P½‘´Q”·¤ŠÔµm¦ sd$¬œwè³ÄÄMÄ#qæÈ#þ‚4U0”Yá¼…»3kº„…†|e¸ï¥ø†‚7ÑE.ì-.üûZØÈ¿(73­…ÙñÌs%ÛFѫ̞ÿ†„2Mæýº®Ëp¬`¢ôÔìBvD·à¿½; jÙNÊÇX…( ú÷¿k+3'óâÞgê“Ï=^p~v”ý·ê«ð\q'“~󯵃ø ÿ?Üß Ü÷«B¹ÈK üÏMë.™2ãYšªê™økÔ ˆªù¦}¦‘I‡Iç?žºüQBÒžh‹µ¯2êÕ¾­KÙ‡]È.@V7æ\ž† t [[_Dck ½ç×_9ïXVJ¤Â?³°ü(û—ôG `££pÈ© pxgŽÑðÃŽß<åœV.0öÒz˜Ú&hÚíSÜÅØhÜm¯« 3Àü_·ÇYñvè éŸ i®;&Øn( ·Uœ‰TüI)Ñü„_Õô³ªÒ)5!\ ÞX³¯aïèü˜Vb7' Ĺñ*Ìî°2­ñh üIÜí¬mÙ\àcçyyŒý&VÀp$ȃڽҎ’F™¦/gýg§r²%¤_fàl}òò§¨±Æ™ìVŸؖËún¡Ð( ðŸU j»±¹ºÏÕ8›¾´Ë=ôiÎÛ0Š ?r~줸ºº‡žfC7N—ü´0æöÝÊûàt|\)¶áN‡]0jt`l |ÛÎüRƒcâ n ¾=òÖ7âô±“* Ü–Z¡• ÅYy±¸€cP‡Ývkå§>¦_µÀåÿ5kõŸ¹9s꯹¾•Ïϳ¬‹ƒ#ý*Ô¤°È¬aF¬CaéKÕ~Šþ¤˜cûœ,ÔP÷dÎç*Yî@&î~M›;õ' Ø]?Ñ}%…ÞR„7·ƒeëJ@¤‰+k{Wê -gŒç¸Æ˜±ÙRç› ›&­èm/™D iî½î_$¬‰«?íX*T¥â5lU6¢ b¾%ûÓ]Àß~(œ#¨‚ }Ýbzj›ýS–M0uºíÌDouœ tíceøÐEH·^§ZF%î¦oÑSÂŒ³²}¡WÿmžL¯?'¿ Tá<—q\…Ù´éëN khDýxQô2ªÕ=^¬÷-¯¼qHlöj^²Îô¨¹–Ç×óuÝü솜±CÀ"õÁ›k oö_O|ñq™CÎÔ\GIáö{© ‡ÒÜ ?»ŸôÇàÁœlì,\¨J ©2epâ d/›IÞÎð³o&„—”Ëu)±•€™ÿ\U÷¸E‰Oœ÷áÌ9ÏK}~hÑ’`vØ¢ÿ¸ y£}rr¦Y]6­rß w©êrÓŸ +Û|5laÀÙ=â1.¢!½]%Ú ýxz;Nb·B '2p%{·ÃžzÛž¸Iw 4ŸÓ¿žé•#ÎQ8X¥sºTâx®]÷lÔtÚi8ø^ÜClyd®†¾põŸ–§¬õûO9þ¨eÑUqT3}àK¬ËÆM®"¤¡(Æ7xE|n‚8*ôÛB ]ývß–«Õ$Ðñ¹BhÑŒŒLur»£‘ð³jV¼àb WVgä|KÒKÍË[’*¯ã©´òEÆßN ¾d¶PÔÈ`ògýrús"^Ò•­Ãr?)I*’,-Š+–r BœàY}éÖÐíGl}ê‡\ÚŸluoÓÚW[°ÀÙùèˆCóøìó~«°áa°YaØã€Ž@vS¾ØÎÊ´Á@àH¶9žH0~©5:Cœ4fœp<>fÈ2@§í6¢ÏwíêFÜŽq?Çó-#Ø»×ùýæÑƒ—­…BQB¹Øx°ŽƒL#ê]û ê·ÆgÆIj@€õBÆeÏ¡$ê%ÚK´[Řl$gÁ÷ñc¹i4¦j! •’®#É:'~h…+GX,ÎÓg@s4ÐÝñ}ÑlQ1‘ÚnÙu—Fõµæ“ô|€‹¤ìœW^‹¬Xó±ñSk-ž×fÁ‰4m`ó™ªÀ:¯ÝcÛ¼ö#öˆ÷Ë2º­õ0t0µ|8Èæ«V^ä7·¬\²ˆzPPm¦ûßÃ0W±‚ sŽÛ•+#ct = ‡HVUçCe×Ö[ĶYrgPÀwa—0Œ¨çO+*ê$)A¼ãÖ­?JÊu°%'/fàLkð;¡O v§QkÛÅbq›'ŒôÏq‰œA‹ñ9Ë1†ç· Yà¹m-t>4*/ðAuU®6—Ól%Ay?E4ìÚî\$ã`9Ѫ™òF›þ¶`A–ˆt©*1>þ&š¨F¦¢ÙF’˜‘£UA p‚ÅvÔX–þ”ºIšM,Þ6ÿ˜óî"ññ±ÍÄS9¼¤9ȱ©?Š µ“ýÚÐ"xwm¸‘< ܦ»ÄäX¨vÍí­øÀ±èã­©¥ôéU‹ÉÅ<ÈœÜAž •Ü÷jF‰t¤a]6"'ŠÈGÕìÜ`—r÷hÌtš5­ƒÇrš|úÂÊ‘æ‚#:´çï lSá³€ÂáŒI=ÁþqñïÙXÉÓ5˜¸ ”øè1ì;ÿ7 "Ö-Aç *óß“‰&)yx¿ªCÞ~tÔÏ}L¿rz[\Þ#\Œ.¼¯¿0Kš)$ëÁ Nƒ»›õðˆv&Ÿ_ß%å§° ã]3On ×T‡r(Z‘«ã©*ã¥8T-4ÿžÍjÏÇ¥üb{€n!ÏÀ<È î3%/`˜TŒTr×v'l€^ºŸŸ"§^•<Õ…Ù}M—ŒBÍ&›ršm¦½¡M–·á§°°é ;b§Ø.êý°]²Ïö­b[Ab©þÇ*QxF†€ˆ¶±±û¨üTŸÙBùÒèµî™MÄUì|º¥ä"b‹Ëi¢±3žÓz¨Ü—”'ó‚~©Ý£›hî  $át ³mʰ~]P©Ö3Êû×üÌzmãP§Á¡¶},›U ¢Òü]y…³Ö0^ÐxF“bÙ¸æÐ–#gPHتãÍ‘×6<²Û¾p&‹“6Z¤#3 Õø^K4¶¥µå[Ö ?ÕOÀ¼{冧Üâ4»íWÞºÉâŒøvŠ_ÖÝPÍñ2‹¶ (¾u¯ ‚@¼Æ¼µ?Œ´ÄkcûµTð3v^ÑÑzWª af„ Xê­½\f‘kû‡Ã«m‰ËnHTƒ¥^zª¿¿p’MC^'Œn1 ­¯m6ÿÓÎ!:K+Ùä( ¼9ÌÏf-í6!Wú (ÿ2¥C8 úë$ÑÏÕä7ð•’‡–|¶€ À«AÈE°ÓJ­‹ÈÓÇáÆAJ…O:O"n÷µ÷NpIž9k­õ»ú\¦æíX™ÂWΚßýŸçô.Þ|±Cò0¡[{žF÷üB;=2µã=iÃÌ`à’™ƒ`Õ=αð´~Ø‹›Á"ûì›ÎvÐ É]>ÚwC’åh%›­!9E ÅÛî¶qƒ†äNÑÀ°Ý®·ˆå!³¢a0½´qz{çd‚äo“ÙåH±ž? ÐH¦>‡5DÔÏæýâ¸VL<{&Wä°ò|§ÿì.ÓÖ8mÎäDÁþuóxn¤™A S8†©Ei©ŽQ”D +@"¿"°FfŒndñ·Plçø¦×·bñuµ–– mv² ìµAk­FÑÑqÑñŠyjñXw!¯«a&ÐfÜgs>lˆÎÕã&²h<½÷ñ]èËwä£#0§›ñ~¦- o«œcXn´¸¼#¬|àÖôs_ $+<‡ª¾oÉx:Ìá"?,g›}‚C ²²æ7õò |–º~ RM‚~ž0°aÕ‘9Ä÷õø!a!^Þ¨´„ÚLƒ>#$5h(GîÐýXØ”mlQczaU%»‘Ûg—è( fPÐ\‰Z›Q!Îý,ˆ)7ɨ¡Ôb¢}›AÄÀ;©¨DrKOMT2ƒoߢ€rR­ §›Ë‰ø¾ê&rimEþäsÌbå)øAt­.ÔËÞŠÑ9¸$ËòôxeÇ£ça©;öâ.>#7IøöNÛ?ªÇ¤Rrü­v0'ÚAHìdŒRyPJ1ÎÏ%½áìKMß|3<¶e¦tI÷}H§GªûÝ‘4 ƒ<òãÀ "ÂóS^l⸶7xúOÉl¾ØDtÔd<æ®ÏÔlºš¥%qÄÛ¹ÎîŸûøçN7Wû¹BÖéd!hxvÞS‡®šïoá èQß ºŠ€7nϺ~ VõÔÔ &ïùÉÒÀsW¼qóŸåŸKwI[•Ô&¶æé‰{Ì¿ä$Xs2ã åìˆÝä¸êô?éò †)Œ,ª‘Â뵕óÕ4$2¬OêýæA· ‡™y2õG¦;j8™Åè:Wk˜AoÇñËb‡˜]·¾+°áÈ%L^+ðtþ¹Àñ‰S)Ok¾Œ–J‚àC;€ð÷©÷Öùû¯|p×Dø°·¢K%¶LðZÏf̃àþ˜¿€P¦—˜“L@ûcE›÷A)h¿í®×'ÃhUѤëÂ* yÅâ«€{¼\̾’£{L z’1¨ºyYê>¦fÏÒŠݺ¯lRã!«lR^„Ø¸Î•Ï a¨R•{lç zþ¨ dY®,ZN Їe4ÄMSØ[G6ôÜ_j"Œaà•G‡è”‘p›ÄŒ £­)=j°äˆØST½=ò6ñ¤7ïy'@ÉhÚss)5ÍzIt͹ ÷”WÖ:·ÌÍÝÁ4i9º²0hïÐ!fJèÃZ"{Ï j(h-sqß|+(õ6pùíOn±\n©ÖJ³Ú­„Kêûù3?‚#bÁQà-Ò"ѳ©¨q(gÄaÏÓÐø3jŽÎµí'Boå£Ö¼gNBcÎ®í»Œ6£jݤ‚oùúûëæ”õ|Ÿª‚ tPlf4ÖÛ•4ÄZVÀìé†Â#HJ‰T—7'¬.ÌVðOÚLLÕ“ÃéO¹dÅÖ[Œ.XÙW÷GôaGCo L|Œì„2’ߟ øTóó³u] çš$Ç=s *èÑ<PpÛ¢¾–5¢oZ‹™|»]ÊË„äEîy_¢D˜ÈÀ¡]ç(ƒŽix¦ÄH}ù^Œ«¿÷ÒS·ˆ:ˆ5:ÈY->Щz¬SO¢£€ÄAú1À³ˆèäy}¤5k›i!y¡#¨4®è§1L/Qÿ ŒcIGÿqÎל^‡*§̾/ã§laV$ í‹ôRšBPfTM˜‰÷ã ³/ס‘ >÷—£€o#[SvX(jåÚ E?Ê"nE£Š¥©ñŽÕ5Ñ>mmõÑ&_¯§ÏšMR »ãíøk¨fŠä•õÒõ”<ÔJU‰;;© sr6¨Ëp—[Öà.PIÓ„kbS9`SwÃ9ŽMÐÿw‡)AÿòQê|\¬§ˆ÷F‹ÖŸÙà"{ãKi+ݖIJ窱¦½Ç1äNëH¢¾¿*ùHóBìÜQeªJ8®üˆûÅ|ºGÎXfü›¨—Á¸Ìj5?wfhˆÿ{ª“´±p%ôx9|ÝõÏM†oõf?þÖµHYIŽ´_$OñÆgK¦²´Õ$+ì¶Õ[ö33þ¹•7ë¿IeÔO6ìênßÁ;o<™¸Ýe_fÕ4÷5€¦?µt¨ ”“˜`ÁG2¸zÒèÝ-H¢\û5Ø»Rq|©Ò?¼‘C -Np¹<>ÇOÑ4iõp¼…]sû}º¦Ìç,ùÓŠŸ{í½ýº© HˆÔx´O÷P ÖYð¿1εr‡ù¯[}ˆ»v:Õ.¾¼`N˜Eaà{ã@å ¨Y³L`ûïuØIÌ ÃHoòϧ [Ò;òTq~º)>i£‚‘Æ«H¨ ì–|«mß*OMæxU×êÑI ˪¿UT÷\šúBäž[X6Þ4pø ÏÝˤe &6ߢi…àz~yÇ<ÿአ½D Ä³ïåi%o·%?“«K°Ýꔽr~YŠJ/¥qReáSö'™[µ'uÁÙÛK»;ÕŸþ£ç8MIÊo:땍–±@Mа[âc_–m™ªºµ6Wª"„Ôáõ¥ƒeù®!—q“KKÀ‰-Ö¢(*1œí:´=ÎÄ=ßùíJP ¬¨ Ç0ðsáªñt$)6P&x ½ƒÀqå.&§J÷½ ‚Ø« ¯Qƒùœu©ÝKV’ÃtCŽr{‹jå%:'mº(f6ÍI;^´/Ž¿/ð‡ÆÞª‚δ#~êiµhX²ðb>;z=|†1Ì«[ c×N´¶gáµ5 Ç—Vã%ÌPÕ6›‹Ôí÷ª…c«_É%ïï¦8^‘AùD’¶z(Á¬ÿ±:§ž_€&Wñ"šVx•S®ržò\ЬíÝ|£#ÑOúUÞÔ+9 ½‰‹~P•œ"oôZ]J-ê­ÁpQÝN/œ7—EêŽàU-(”þUÑu[jñ¾¼¸8 kfÖ‚LP‡’(î5õJÌÒ2§¸lÌö ~n¹¬ãswÍͤ´5¯Éð¡"œwòüsõ¤A½øƒŽuPæ»ÿXj½Ë{P ´¯¢™°Ã0I7 .ªœ!†ò[kŒèöåFú,Ï1± 0blä£,]n+šøjVð«˜LÚ…½Xë3‹vµ€¨ ýê¬Ù7µ0>]L¤á´P¥Êfzã £-ÙÂOB _ÊŸ—'¡[ ”©O›¶ð`¶¸×YËš’ÁGHfZ@9zDÖ¡FÃàV\ôHQÒ*‡”3H7³ƒü^p Á»ÁHû¤¥y-Í Lzôø£x‰ê°-å9ޏ)_Éo¿HÉD¿½´§ô]ðHXéŽ fu¡o—Scç;vüixÝSRŸ%‡çÓüˆÝvVT¨u‚™”2}³#•ŠVM®:+bÝHa¦Cÿ ~vº §¼ÔEÔÊ' ÀIÞ…<´r¼˜²©‚@ïì Zé =—F cHÁ’ꀦe„‡lÔÿ2a}¬Ñr½R¾n/BŠ ~îBûë§Ô¸¦¼qÂ+ÚÌû-4&Ø{ý¢—3¸I&æX‡{à‰rõ)t¾U+0Ã{\BJçÛD¯f¡:œq ÙiSÆ£€Œ¸ž7£I_à oEñÊJ%¥üôÈsk¥d‘Z/ Š—æÄßÚòÇf¢aêoé£0P§ºï@WœÆqtí¯Û'?è­Jæ]«œëƹ_â¯ZÓΈP۫Ę 5öLžb§F”ÙEœ\9á’¡°ø?¼NŠo|r÷üõêª×aæÆ3]Œ²}»+%€ˆ”ÆG5Ùç< €oZK¢ëÞ€ý“è\(M`1>ø4W¯fo ÊóýÀCÚGüÓ)íR|?ã —d»¤§óõÂ6m²@k®Sj ºötOÌ¢ý2W© $Á‡Ò9ƉÍZßÿè=¬×BÊj½»>V0Ö ˆa€ÅŒžVÜ]_cn¯UšuÙ:«QîNï<³ƒ³,3ÅrR%Ä—C¿K†ÌÊæÏú`¸Ÿ›£L¯¡¸Å$„¢aœ¸ ùlgê nc°ö[¹Óp$ëÀ¥Fö~¹XlG–ó éïÄðË_(}æXÑ·lÞèlÕk(w)Âò òƒ‡¶Âƒ“d|~é¨~ C1N}·¤”3Ö]¯m]$½ˆ•ÐFR¶5ŠzO§©T<Î n! p_#^0){¤­ åÒ™‘ß–9Cž‘è†éô*·> çq3_®–Hà÷`áÀ$.Z¯Ýc_·¨/„Oª0.^ûIåðZ>¾Ò$¯Ugñt‹·çÿP•ÊÈ•\Oðdù¿k ßb»ïkm¡}1Õ %öê E=ãì?é9ŤDÇHE+XÍv[± éÝzÉåó§¾܇ö~!œbi…ˆ†‘q´Š“àG· Ü•V‹›Õ»Qqža-òVATоØWX4L§r®z’MS@8ã÷: yß@*7ÿÞ²=‰ê,¸€º!±u‡c'i±wS‘'ï§Q\µƒuh™x^2õd¸ÁíÄB» =Úÿ:W±:›YO!÷·þ Á|­üóù]Ž6‘\Ù¤· 2OŠߨ3œ1®8ºœË‹Œ°—\ççLÅÅ*Ò8k[ËÙí€+ð|‘øþùNq€iX{í¢é})ÆBâ•C`!µ†-îÑQ}»ð^Añf¬ñ­~ÌÔï±¼ÜíÏŠ\ðâÄ0QÄ0ÅüÄ–~3pLk¸ ®ÑÑ<\è°<Œ°Ì+ÚÝPlºYRYÒèÆ–7è½Ó2†oüäï|™>$T‚u4»ß敱À8tÅøý¤HЀ‚.µÁÙ-´ä;Ó”PŸy¦>TÌz4ægõãAs^Iní¼›)æ±’<w•áð]Û´·©ÌÝo ¦Ú’,É=;B”´5s³ÕnYÌx~îœq$4˜S…rMéÎèø«ÒZ1Ž®í¬ör¥°b¤Ë3 ØŸAYLÎÝ P ¤üò]ä"¿!9ѪúªŠ +§G=ݳ´Ù²8ˆôËùPî6H¯›™Xs®Ü±q=œký7+Õ9þärî:q7›Ôñ”ÞSóÛaà¦_RžÀ—|†®z4~ó݇’3¯¼íóWØ×ãz¯âÍò w"P#¬¸Åö‰ñJ ¥cáýtgÓ°®³Ì>ƒÂò ˆI“®4ñPEÓkøhWàdLþ„¢›Œ b·ç¶=!  £'‰ YñødÄ1^3SW£iêÎrŠ=¿ÅåÂÜLRÑ;d4÷v.Ú:dföŠÄÕ;燚ÈfzB k|Sé®nP³ÑUç­¤¶õ$0èhÿïÖ¤É×'¾¼ú¬ø øø¸ +}7IFúj«Êƒ×UÜZC„ºCâÓJåšh¿ôå}“± ¬ºrŸ!2*¬ìÂ&ÃP朊£x-k{ý×½A‘?}CN7 ^]¹SãtŒÂ æ\øýtÅDÞÁ*Æðu‚¼2;‚±©ö΀z‹/Æ‚z'ÃU Ð¦lMsM'ç4Y£Ìÿ¢tñ\[>CâZÎè÷…úÆí«7iRú•µj£c:dôKžë\9ÁEz­FÆ ÀóÙuKòðÂ|þòY¬ÿ‚$;ŽrO»EXôa‚å?”TšÍ ªŽÀÄýEœ¹}•Î@Š ¬¹™“²ÍrvÞ°Ø‘Üpó}Áû§[ÙªW3U8Þá§ö%‚È:•BC¬—Œ„@šìÛ^Lš: ªÍ‰EÔÊDfûN{’áÄ ¸‹S5亲CsÌÙèJ± ¦vãPÑ&Z‡ùÅpxE?ñ:Å åÖkÄ ÍO‰B:®aWW4hóÔJ[­yÖÊãötÜ’lNt¿^¸Þ‰`Útýuçµ¼OÁŽÁã‰üçþÏT4¯J'?ƒ¬2 …Oî½éS‘¯Hv¢bÙô™ù˦ \»ŠGÛÖÔz¢ÿºÆsµ€KÆlÞ©›DLrxÆ]Ëøñ3´ôg>Ú£b˜“hêƒà€u=óÖ\#Å+¨‘5švVìÙz×È^"Çæý‘ý8›À)ÓÄ1¯‡±žÊ¨q§‘(Zë¯=ÈÃ*2Žó³Ø´¼Ò¤sÀ§ÕwŽOõ„ÒŒ&ì„„k˜—ªn DÜjÀN‡@´xï†à&XBE7õŽc°&‰9YSò!°¿$#ãØ²†ÀB«¦Ó-Q½x!kß,c*Tø#5kâwEwß Ì]-ag­é"ÿ4]>Ç.é¬Ï@SÁ†¬û·ï‘åúê#?å#{¢Þëû¼ã3Íy¡¡ÁŠLðØy¢.œtVkÚmµáÍ]Ûöžtx}“R¸ÛzÏã½Mf гOò¤»ùg®;œ(ë†G¥oŠ:“9 õ…é Þ #¨Dm!,ƒGXŽD,Æ5ü›§lljV“aR3n"N Íù™{ßÞ7©\ã+jg×YOΉþ`<ñ§LŠ; zªÍ6õÙKÍœþ þ»Š¢)âçühŒÀÔù½ýK™{5žgõr½<6øwŒª+tLq=UR[†æD›x(ë…:¾ P€8ÿÿr¾}‘¨lû³Oºtݦ¸º‚ÅÐcwTìžÎ½jY[D¾š”’<Û4òÚiav£´çkŽ6ßj²×»±Q[.Ó,^Ñ€¾4IÒü<øˆV^¥DÙŠ¹ ïÄ|ƒý3^Ûò§­Ï»€–Sà‚2®kí¯w~©Ë³€F°ˆêk\iG† P´Ÿ¯æáÎe(r¿Ï‘Ìî¢tÿ'òuž<°ßÙT¯ƒ<¾cMËö¹D;Î>-év.yxHбcÉ‹a&((„6*aÖ©&’ GNÎAü¢èœCº¦“æTr¥|̼¨–§³ùjòx/ªÉki¶QAgÖ·i÷Õ_Mªl{öBq8SN­mÿÝ´<ËIî®¶q[]zBÅ’^ä§Š¢_ú¢ùúï¶ b÷hü¤mNvì™N™´‹3ñÂ&=Êq^ß øK6FÍmC5„Per½·¶>¶¡ Sç`rªúðd•Ÿˆ›@é” :_¬{¤¼‡ïÕIõ1•OZÎnÁ’`ÈÉ™òˆ¥ÀW:Ô4¨‚©(À™ kæ‘ÙãÎhþ Æ­(W€ø#Ìÿ6­ñš¯E)XõÊ:°„‰ƒ°-ÑŽ ¤ Ði:¯~»Ê3rÔþA­æŠyß|fßÖôpe%WPÒ/Òî’©žhk…I@p™x?l3Ç@ì)޶á è[b´j 0ê<{îV 3Cm[»mÌILËŽbò1±vƒáÑæÖJˆ/¤Úèjp­¨pKH¹˜Ž%UëX“„Ýz1ãÅK/Ä%¹ßr úÔôˆ{£bîËŸúâ0ßHY.‰”AÕ\#ORrr™$>×u°¤OÞ|µºã•Q ?IL¿.zŸû¦þ ˜Nd"ßãPŒÏ×.jITW<¬ê}{™KÁÑu™ï+Hý+Ä– Œ¡qQ)Þò)o.uh®èðœÐÄÅæRâ?óé%ýU''£fÕT™™îè2"¼½ñ<™p¯Kšy²ó\÷ÌU?"”1Ún¿ ôØVà†eæßë&3<‚«ßA0x\ìô‡ÕÑ{r)*ùZ”Ÿ•íа Üå³3BK$Æ¢ÙtèÒÎÿÕ€Ghv*%€¶ÍÄîlcÎïgKS³éÊè¦\0-m]XûCÐÐãÒMmíÀÄ'¸Ž°aÇf;<ò!DlwñÖ $Ø ª™Û¿Ó5-£X¼ì•qÝÌÀ…Ñhß.ùȆ Ù²ŠgÕ›êÚ š¼ƒÁ¥ŒÝ’Ž›Pã.«àïúh>ðõS±[ÂDAœ¥ŽÀ¡GïÕ0Â;¥¬µßÿiîýí~§ß. ÿ™¶çxxâV¡ê$ž·<X×'Ó ¹x àïë«=ŽìÃn•?¸WÿÊå¬ÌÅe´™ú£ÚŸÑö0™6ͨHÙ¦œŒ%§Šö:Œá…®^ï¦\¯ØêNþà ]dæD¶¨ËÙzu ë"OO“"]õ·ŸÆ!k¥^×—" l˜Šý‚€ådØð:>0 ª£ —ò8ºŒv|üöï^›3)£Ÿu2ôàñƒâ³8„›Þ‰ó:Ë”˜g> ì­KÛ{\ýÈ0h£z2á•N!1Gó¤ã‘;QJ.œd«Ã¬ ÆUò:®–9«5øùO#ø2ÉU¬C 4Èï-ÒÒÅ-ï€ûà–{W†ûÑõ¾ÎhAø§Ç{ßœ!þØZI8ý?zÁ„ÂhKp<˯Â;~k„| ðSy‰™œŸ$A7C&¥ ê_~€è°Ë ×'˜jüÚðìqº¸b„&Âpù•/DÂVV㲌È< ©`n×VNNߌò/^¢)ø9+޳%°§\•g7"XTú·\,T»ñìÄQÍ7–T 1À…?'ζœ^ª„ï ôóì=:z¿6½ºƒ[™ WzÎO­ÚÖ}V)†,i‚{¨ cÍò±ð'å7n³_  ó]ާ³8»·ËVû÷ÝiT÷(4B®½ ¼­äÞ°yCÚÿ:nba¬ý Rå…ðšX¦lôhnx­ÇQ-ÚwHä—Ça¿›_ãhH¹é™—{!–H…ø\á!°8Âägn‡÷.&nÁm%:kü'ž ölÀ“!£¼Š|Y[+èb ÉAGÃ~³>š*f<Õ,ϯ8!â]` zÒï¶ °Sóõð¢ñ3— ôú~’l¬4|®üv9Á/úu¯…‹˜ß!I0Äro—ƒú)ö÷Ðíp’ ¹Щ‡96³vÔ}(6smÎÌ"ÉÍúJC9k²Õ+ϸ›wÒÖGp¤=«k4kJ®^ G!U¥ ý+ªtÖ¶+·4_D‚ÒtPø…M±öT1|ÐÍ»gÁ N5Èõ"¾jûzœÎâfòú³Êtžœo†Í–¥´ácÝöŸ%[õJsƒ·9½$É¿k$6Ìœx›¾w•éÿ•dG@3oöRª–‚u9w¼Ä"; 8œ$oK75±«ÿÊ"=¹ªK¾=¡Š\ ´#Jæˆr¦@þ°Î WÂÚ©ÒÆèYLO+ÔóÐ*©Vî@iîA-’Áÿ(ÉWs¡›õèùÆÊvèœõPôšÖZ=c~œþ¹Ä3¨à{Ê[*wwoU´ŒQ +ÏÌvú̾Ý5—>JNvzÄò†#ŠhM!…ù¿<Ûí!õEL¿iëêÍAÚË9?¢‰ðpÌiî•¿>=R6Þ4;ø_‘@ýG£Ѥ:Ê"+¡pZ@˜ÙE²åÚò Îh—‚«(³ûq¸ã™Óß2áÿÕ'» _Îq9 \kÁuµpîZk²À&Ö/½kr–`')ò½y\Âç’ÔÛCuýâ§œ6vó¡Yä§érw¾ñÝ$÷<†på{åä—Ñì­€´ùñvÎÆŸa2L'Û–5´˜}ï]‚C9køšó¾,Ésw2¡ˬ 8ZßѺKÔ¦+ ·¢È&R|0….U…<]@-YÆ(n¶q¥ a¹AÞh u÷[w¯Àuü%‚[X^¾·Ê%ÝXÔØwã+!0oÔ«fúqï:ÃP©8 –Í™mM2ªìäo³ÈÃóãÜT0ñÐv?m¤ž…ó#Ç~w‰âæ$Iæ2.–™w„7ã³¶º>r@§.Mù0âÂxÄmìÚÌL‘’Ý@K%N”Xõ˜°å«XüÂt–GP]2.VÈH};ÛÚ?üàÿ[n+ï¶§éŠJVôgÔÜZ»ð„öêµ^9A2hôf_åÉ¥¿ïÏø< "Fßòx¥Í^7FÏJË_ 6Ý„¶ý'Â&äýg€Î§ó²´ôÑP¬˜œªPÜ<îaPlP²Uìðó³bN¾í“•ýtÞÙ,*QÅ3Î(ðÌ&ø!ã¿ë䆚½ïÓ‘h ‰0Æ»»V}ß©tc— 7 @V=öe(QFqÈ‚¥ä+,Í@{®Á==N·Ô·â ÚSG‡G¼¶.›{ÜþsN-Òõ»¦ –ÙÇð(ö«¥’b˶ÿ8*W°é™(²Mý.,Æ™(ªVå#M‘(“—mËØÀƇì½Ü@]ØYƒK»úM\(ÈÊò i— ”³¾ÓÂJÌ-žäŽ\+6U¿¶Y–t!¡Ôi&,+û¡®çeÝ€ì7øÄÉæT©Ú(ß<#zH$ù¶­­4W9ùvÊYK‹ÂÒ%(dG4‡Ôï+?vâoÊ™h€ÞçŒK” ã”dæ2†ZÝ%´ƒL®S’Ç–hZñ“—c݆ZEã" K•, È]¹ø;äÎY QPô—§²Î-äRÐ|/ñ?b®•r{Š$l@²Öô[‹ M…ë·&e›ò”wœ†LCà¤FØGN,—iÄmµѲ°;©ƒåv*‚‘ èã gè-ûÕóÔ“øûŠYÍ$çH/Œóù`ÄUã¶l!ö{»^?œûÿ"0ÿ‚±ˆÑ×cFyóXFú”räSëÈ7 Jëé¯ÔoƵ#·™S\N~è¡`h˧ÊuYkÁ¬ëø6˜]¼£Ûs 1q¬—¦$påP3Tÿ#ö]X^¦AZèªgûÁ©5^Ç0÷.Û¹áÅA†çS¬;KiûGš:£ƒHó/f$­Vd€BÁôðÒu´Ã-m°ÔÞpš®Ú0¼F‰¢Ë}Ù­£„Œ«åp ìäö¬똆 f¶åÑ"ŒW»ºAìï¹æ93®zÎC¥r_´…d§qeEGˆYëZþc€®K †Ö8Ì(@…p4¯sµGíêÅ*÷AñeÝ ó§j„³ ÷Ý ŸíÓ¥Ub^&ff¥À v2×Y,÷4MöuÔNMÃb³XÈßÌCΰˆHAªëÀq„§m-¼šY·n+`z•F®Vâ;h ©#ýUb᥌to¥L øöív7ß­U`9ƒŠG¸È5¿­É'ÑKÝÀõ}ï¹â¶Ój.¢ócë·š,loÒ›D?`èĪ Ž|ڮЖýOþꘇɎ‹*Wk„_‡Ýþ.ƒÑØìS7áã÷|÷ƒL±iäõ*:N7vLÅþ=úzl±?ΈŸÝ,Ýw<€ NCÕ­K.·û3!_+P‹ëo@'Ýå=Äç „9Õa¿{h]àF³Íœ~ô·”ë·Ô{¥²N£‡Æ}]lj™RÓét ›û‡åÕ(‡ó¥ÐÍõ ÞðiH –ç|vl§ÞÅáw´¥ƒž¿OJÐÙž[¥˜w–h„«}·£Â8¬·L[7üRí¯–C1-o§µÿÝ\Š_(šNYò¯üA7ˆæõ6þéX¡³ Jsª&»Ó9L…«ãˆF=mZ·°ÖÌ'ê\5i i ×ϧ"W$­zÅ‚î[ø®ÜÒVÜÉb„tü.+kqÒ¹“¦~ïDìvR•†5±ÿŒUÜê]âGl1ÕÒ÷¦†“éý?‰’ÂM‹p±JîoóùWõX°…šÆFPÊ9VH*ý|GÌéõYí8P°Ïæ²ä%ÉöÞj¤;‰=¡‚£)~kH¶l‡“EÂÖDšÇÌÆDýîóŸÈrí5üzrW"x{¬¡°Øœm3‹0SË- 2¼^Å/$ÄÄæã´Ú kIP¬Ohp|þG {Z8› Ü5ƒôÙ]_ý7c-ö©‡öÊÏ#×Q±„”%^Ù®r‡¢_M]ïŽbð7‰×`„ôˆ}üIN7+íëro|°|þHÛÓ6!K¬W¼‚(wŸ«6 ZäÚ‡àÝû4çá¡Yâc˜8wÕB e :3¨Ü?8P Ýs£îY—Xg‘ñRâµRPu/}Œ7ܲBµN ïÄ<¢4fàYm3r-f{žà€“T®>§S±J²>±ñ]È@ôI@‡ƒSR÷“”3õÚ­£7âÅó­›P bRß&#mñ×#"½°1^¥õ„`…$¡£­¯*}_<÷‹3|¨3ùÓ-dþBvuÂÁ'7Ó!"›„- qÂtÈš]ï”!þ´”¶ Vn¯Çò7hXnÎÀtR«zÊŽo„x|CSêûq9ƒ&H‰ö¯>«–QNõ²ðSL*£6 XZm‘€Ó¢l‹Ñr›%*u¤¢J#, ¸gySPc%† ²–†‰ù9®SÛ„TÄ{?ö™ø•t£Í×xRë£ÁëC. q/ †En­,Š*¹ƒ—rβ]ÎwCYÐùDI´A¼%5>oDAšÂ\fJ®PQªfã]Ñ\f€…jØ—¢B©["˲{l:ÐS¢_:øT;“ÃzAaŸ+'<® »p][µ–:/’Æ(h!tóŠ©Ö[b©³¬JZìði7h”}*;µøÆœ»`W=UäÔ‚«DTL¼¿ º í“¿88¼aöÉ¥°õ¦1s$Od‡Ç0"Žt—Ù <uˆx7+å?Jõ©Òf@™yùæ{]Ìzð?×P$س.ë¢ØàT¦¼èÖ¯&ƒ–:ÉÚ¾þÍ@É!…ÅQõ,¹^dè¶ËÁ%<ñ„ÉôÚ¦Z~´ØW 6×SŒe}]9Òò-?'F$G¡kƒ\æ¿„ã/4¦tXZ@":HÒá^z¢/6¨A—£CH>¶ ‡éM_òԘݹÁÑ;ï$»ì¦ÿxÒ–Ó€Q¨q÷Öfdâr¤ŒÚL1/”Ö:”×›@­ UÅW–è‰ø¿(úo°¬SÌ¢ˆ+A?FÀt½âL,Ž #~À +|AprG#åçqØ–+g[§'Ò_â¥í_î[!õžËR]ëµüÀ‰{ïq,“%Õ ‘Ó}3Þ½ •TE$扨HŸß‰SóVÆ—.òðFÏWÊzNv˜H¢D”¤£È-E”Z:.wѤÞ'ÒÒM¬3µ¾šq*td.õIæÆBû j¾ˆaG²²g×?¹ÃðLö2n•½w³ÔéãvŸÆ™¨wÈo‚`¸y_‘"‰-á¤I‰’Ð ¬Úqq>ˆº‰èEœÿã—ìçíYò©P%ç(ËÑFƒëÕ²WúhYíÿÒB5 ºY„þaÿúYW•\ï(pdFæâÁ×ÝË*Rß`DÚºIõ ?‡SíÀk©Ó¥–ÿŠ– ¼eíÞ¯FÜÔ"?Yæ9™ï¾ÑàIýAAÕ¿/f™æ”¡ !Ð×Ýã’ØÑ„L|“b¤‘ º©²U6&55o8ÒS>'Ô5R6ÑšT1™$%*Ò‰‚Xˆcrõž†‹Ÿ.§éÿ•³¥+O  »ÞI2­Ila9÷éÍýB g\ií-Í!*«ƒö/+Á§÷ÓyaÊb1ÊXìº!x°e@Ô‹BfÒ'v‡8,M,¬?®¹æ­ù:ÞžüL˜ÌSJ€¨?áâb®…ÅÙ]»oèú)‰ç<[VfŽÇ·«â;¬ææBËîMÛ^ë¸>}x>{‹evÙ…Dû*ÉlF\£dᎬif`ÐFçÑ)ãªJ9Ž(c’²7½à•^.Ì&t­K{A4ÜwK̨m›æª›Ö»e¼£õËÏÒ†µ  Ä.ó~`øI¤Ùñ}MúBpå¹ðF•@ÇOª ³¿^Ô"TÚøžÙ-öŽbó)ÒÅö‰îÊå!·aÐç‰S³ÓdÉÀ Bm.Û—AXqÎG÷#Õª#ŽMѵô•>;ã*²AZ“ÜIÁ^õãê>¤ÆÁ$A‡D4\3A$2Ç0-lJ>UmÐ:÷ï2\Ï=Óû~Ê&Ä[ÄÔS;0OºCË6I“}c{­ˆõ^bÉÜu*v.®pˆÁU¨uwÜs`šâ±vþ­HæÅ*“@gÖ€üDZ%¦LÁ$þIQJvJÌÁðá}@@o:+VÈå™?ýá1r¡t?hH›4@)Ÿ~öþ¡ýˆ~f³çÒ™ð‘.É€OsO„_"ºÃij²ýÜýR =¦ço«ÁKúšñ:X¡eO¡©óvüŬ…îôÒ° Ny¿.ÜKcäT}ˆâ»‘u,øªåZcDî¤Y‰ `Š-}Þ%åü|éAúXo ‘\`aAıû5¶Vþ'*iQC×ÕŸÊÉ®HÝi~C -êz"9oR¼Qô%5(óP؃ÒðÈ¡(HÝ.tšNyƒcõÓðD2b­vZºÀàpò^×µ õ±â˜Áëf8ö º~5 „¿›ˆ×ZE-uœûñ<­£y@ÇÌâM¦k¾ –¦P["ääË•þF†Wg|ÂQ‰].Güè5„äo3$^²EËÝÍÌ+ƒøî0ãß½¬ùû´ðì±³¦o8K–Õ‡sí¹ë4¡jÁ¶e @æˆ[a‹_Š L…GD:Ýæ¾4( ù¦ú”«À(”“µ<27?å]¢ñ§O0Ù‘•Æìß´G)âM/gò²”ª–ŸCHÑ)·1W+ÑŠê^# %ÇpË](-SC”U ^™§r€ã¤Þ)¸&Êã-½XÒ“ÑE¤ý­‘Q#gŒï“Mj‰uÙù¨ã`r÷Úè%+[ÂNåŠÝcâ?ñ<|D4.I³ïÅ*Ù•P…¬Š1ßÛñË£HŽ1ß.WÉOÊ·' |k—DBåaõÙ·å€ënÄYb‡!ËT¡kô£­tݱ½þÐÚ}­U¼½ 6Êd©î¥¤Z« p\WäÞû,m!ähÈnìšNB^šðFyë'Í[^’q+T±ÍÔ»÷†’Û2¶ ÌOÉýØi­3À§õ1óüR©mJ2í£s%[i3Û‰Öuk?VØeý+M­‰ŒÑ ¨z>ø»~’Ó1Òc”B6xÍ«eðŠÐzOwŒÿ­[Òp±]ÎŒ/}RÎÒ3–u‹€Ðö6ÔeQþ⃔LD„ºNäÌÿ¹äÓœ­Üä{DhLÓ?•Øm¯õÁ pâÕ/_NÛ³B˜QHÆø8öí,S hè:·éqs°_‰OÙä ~²éá³ã‚ÔY[¯b¡yÀ= ½ra&½Ú¡Kg4Úƒ4GVõL:è bÐ_ë\Iœ·WfHUâ2«€áCj9²®úÌ·I‰}•Š-|®·ÄH˜&]â½àîc£ á:/rÅ𔀆÷f+ý'3Bj¼›1ª³•K!‹zu®1ý§°åœ½®¥Tv3SÞ†¸j„ö_·¯÷ÕNçŒtRå 6¾MëôÁBKRbæmn{ªñDûÒ–Âï½Sámµ&ÏVvi2=&Õ«K¼ur®[ËÇ ©Ò?ïqË }KÅ#¾gìpq,ô . "€¶»E`Ç‚ü”ÌÿÙÏT\Rãë燦I/°–é͆u«”WvŒFõnÚŽdœY>+OfÔB÷‡©Ú æÖù¥ŽoÛ&ÝÇç¸Øx–€ìßHs ç ÀåLžº°Wf}üÚ2©ìJÇ‚Æâ1¿¾[&7íe´<@rÞ,^Ðänêvp¿iTäÃ& µ·HI·`3¯”o¦ÏV?y ÂøBDV ß”F™ '4|ÕÓŒûØ.Ü]üû˜Ú²¶ýu1q´ÄÖG>†ËŸ(L!‡{׃]¬äøÆJC 9~ïØ:q7Ò«QQhò­ŽÎ^tÏ1+÷uk¯ÌE1Q7±ö|¼Øb™_œR˜ÐÔÍçl€žSöËŒ65z”ÍY8tUŽï‹R 7eØor‚ ”DçV±(Ëú#²XxÂòFG^y*ŸZUÑú¯`³Ãï2{ȉõ‰Éìü¹tœw±qB%e9Ac9×Ò:;0 “O ½)Ü# ŸÝëys®år³Ù0T‹ÂýY™!êŽvIÀçj‘@ziˆt€s*ÆÔ"žÀÀ~󻊯7KäR‘Veª™=X¯ŒÁ~¡ßåºõÞ hý ¿EývÜá9{£*„¡‘MC}/õ°ÂÜ‚sJçÉp?Ù/²Á•£¤0ê/FéÎðÎc%}ƒÚ›¸' ã^Ë×ÄÓΔü+»2±hwI3í‘@;ºf>.Œ¶7YÏ#”0®à¦:Š×ÇÛ¤Ÿ(‡6m^oŒa˜rƒM~š–ºR³[¾ÝÉAËpñm®Èj2Æ,RïIØ÷ù]Wz~êi %()“Òê~b¤gˆÑ)´``Ÿdlê!u!cÜ“‹–—œ*îÔ.=Š4Î$ÆéóènÞÐÖ¬ƒÚê¥K Ö¦”'Kø'a¹,å.û} MH—µ 3Õú¹ª|dl 2‘H,ŽTf!¢ëë‘PÛ„fAÞ—¸‹ŽÛòåÏÜ»øl?‚îdt½žféPÀÒŽÈœ–ýbdøoä§²C5x9¬µ}æ}˜†F@ŒÈDÿÚÃç.¬¦áQˆ|Æ7ÖÅ4oE°È@¢ê–ð! &:˜’˜ÚyñÂ'?êƒÃ½Nì@'‡¿w„Gg>²Œäº“”4PÓÓÐZÍx!ÄŬjýæÆÃ/Èk&6±QÜ‘mд‹ËrÑõ0Œ°|ý—esÔÃs«qk²NÃjJecœKŠ,ºŸÝ{ÞÉDÐI¶ÃãšàÓdG çCzœúypJ–l1-çwt`»ªu1W,¤´¬²ù7­NoªÄÑ :Œ‚å›VnŽzÏÕ'ºb裿DŠ4Ð’7…bhpW/ø^H^*ïFÓ 1†Í•Âb°óùÕüŒ½‰g38û>×ù°gvã³¹gkÜæ…Ïh|¼©Z ‘Pd)%qa#†Ô@Hï–°ið0WtáÎ'1‹ƒـѪ‹x¼»RpZÊÎAðM]>6S2e@’×µÜÍÂlGå p{Ɔýðg§”næ×þªÍ•¬é‘tºp5@´Ù0lØÙn+N!*O H4|»¥ã?[bÖ ­™t= î_W'ÍûEª)Ö»GŽ»»o ^ÅdWzÞ‹˜ YãÁ«5ƒÜÊÌD×¥Íqa)’„'Þ¶~‘‘§c¸ Ø•Î6zù|n» K9¹ÿ‰n呞·"­¢Y¦.B¬uù¢ð™n¬ ÂÄÒzÛ%àw¸{e–“Žç!j ×î®â†w£˜D–õ&þ#s~½ôƒo¹Öl™ ̶ˆÊ+«ø–—ÊëÌó'z|otRð…“–Ê˜Çí]¶ÈI·3ba–¤:Ø›{ «v•|[‚èÌ ×&tƬ^QSÑÛÛ®#¨×sòýÝÄU°@ ÛQ©Âê/ªê{)?ÖÖ’6èÒD6ù>‚ƒ1TO…À.cž†Ìê/ØáßÁå¿K\eƒÜÄòÂao0Ó·ï­ëZÈS@óBæ4þí4Še?9¤zðá3ÙÚ“ìJ,pÝuBNCüÌõ}>š›™XÄʈšä:U¾<Ý8`¾Ù$„2×üHcõMÓýCùëN®ø zˆFÂî ‡TÓ§Ù"ã™`ƒù¸¬Ñcv¤¬GÁs-ÌCв qÚPAr¸¸™ÝÜ3MЬóÉW6EìçMè“MÂ~ÚSæQíGVyÿÛÛK|¼oÄlÕ6˜a}Lª\ƒ‹l*Ü®Ý÷óÅ·ÿÅG®¾ Æ5Í3ßdÎs ¤(D%¹V¹Ì†Ñ›!~ñGA§¼×äM–Y,ÌWu¶HhO¸uÃÈšO§¬ Б¸i’éŒê¢²z=tXª½M mYZÎÉhH¤ OþXÞ0üó^²ý«ã^}Lq ”?C‰ µÛÅ&7öOáüèÁOMÎåHášý!ÂÊǧ›)ëàì›ýœKõXf|#ÏnD±m’ŽÎ? ùð&64aNYwíS‘Æ…­+-§¥×l‘Êßbèe§ÊÍ™*ME.„°æËYó¹`*g"H‰$A\ŽðX4áUög´«€v®ÿ&UÖ·¢¿xtL‹¯@°¥£×5Æ¥㉲îB1»®‹ V$|ƒ “/M½ç`d“0ÄÖ¿–÷ýª{­ÿ!L3,—Ü'ßÒy%)÷åÕ‹ØK–®] ÂüõÝ&É)í⑃š6¨ ½üìvi¨/†Úh¥Ó6Y3á@ YG¢’ðÈ–§£è¯’78æ¯>¶Lç?­"¡†©oX#qÓ7ÁiS}] 6>ë ÇÖ™7ÀBöw÷¢YR]Ž x¼†Â;Êéç{6аó,]ËËúMwdk³íŠ4:Ýk(ªÇþyÑ)imt-w_º øU|¬ñÙbÔ9"W‘ ÂDNf/õOÇùqÝs;”EsP]@½köÂ;lþê•]Ѹ¼‹ðvT«±á#ìÌõ#'Å i?eñ·œˆNÒ¿åLµÓb^0/0ØŽSgÔÇ;Ûƒ¤x®©½ïl˜y½ö».Š<¹4íž³xIáTlkxƒW»øúÉA7:öoS¨RØ·Ïl=k/Ù àOnígn$O‚~¶ãzòŽg~žŒ»sCògÒ/ñr 3º-Ú&¬ñÀzPYy ÿ­R4X¥ v…Èä—æ;îõpX&ã¡ÈÃó‹µÑÍâêMûb6LÞ"‰w­´?r±ö™ÂηŠ$Ó Wû&¬7¨Ìßéwï©äµ±71YmnôŠÍpFËvi­GI³âDKRÝ)Ù# Ü]ÀèU`ˆ¬-ƒ×êY§žµÃ>² dyС@¦®`j+–"tbÁKXŽÞȼq¼°m±€úß+ñ$/ú¤FY}× ˜…m4/8pÁ×#ǼƒôŸNuvõa±ÎÒ Ap²1:p¥zóÕ˜ Žh }%ò—pÆcf§íÓ\™Û™7Ôâ ÕEM—]&„3Ý…¶–iÞäs«Áï|t\«@ÿ$^à+ˆNŸå´q#½êâ ú’½ÖJ«ÑÚ­†SûäjšK/ixׂŸ:s”ä©IØÈÄÚˆû„¾PydsB ¹£¯éÖQ‰½æu§A110óîõD/é›Ãߤ(Ug›wÌ%ÌÚ§Óèã=ù!®ú|;ëîXg˜rr9/™<‚³%RŒOñ7s¹0‡Þî%°ÜE_Žæ€û5§“湟\g}œ(|g=]‚™†+~™-"奔P½ä´òJÇ¡Ïh锌0aí'‹ î@²Èj-µùÅiÁ;¿|… ñôšC´é¦“ Ä’ë¯Ô™É0Pª X9àDiËÙßì).@äD+#•A_›B-øŽ"ƒOë[/~»f¥¤~uäIó—Dý„[¾ŒkÌeÓQDζ¸ã)òÃs\¹­fm]öÞo%“s±|(´eÃV^Kx¼¯Œ·Ã ‹ù1DH/5hfz‡ £åù>¬8K‰s‚Q%aß°¿à }ƒk3•º*jÉ]'†¦žÑ` °¤N„Òe¯?”¯‰Õt¸4ŠªXÑ[ÅFí¦DàBÒÓpçyÏ;¿Bˆ…ÏÌ|A‚ïc+FßÒ\#ø„¡áEö¿ÿ>-£më­HÚ# †&LÅÈ4XŸr wçÉ~œv¹øµòŸÉ,µSýÞ¸^êmÄ "ZÛfð>¢Q1ÔÅò9•#çÎ-ýŒ9YcWê†|¦Û æ—7ö€VráÇ#Vˆ˜q06m½Ÿ×¾_ ¤–åñ­¾šü€‰Ü(_¤Þç› ·Ò1Ìããúè¸ìKxI5hHã,¦m—JUhœz…uÉü–?טvÊø ŒB3D),¥ ß…#¨¾&¿Õ’âÀ÷,ž] ±Ëz^ߨû‘×mUÙ UÍ·8ƒ˜‘“pù`Vq4îAô…iCªîÓÆŽA,Ù­Ø %BíÊ+ðþ#AÂú ü{\§@ŸÓ€zEí™×Ñë :ƒØ–j\:VÈsz$+.‹Âk®dÂúŒš’¦•™‹<‹ìâD³ ÷]~ª¬ÙT"ÛÝEj#•HÎzNoR t=t:Dpõ²“ÞƒÎYˆ•ÿå€FÌ~ã­: ÝRjÌË èB‘YÓÍlOQÞT•ÕõåuFüL&.ÛªNmÎÇåX‹ð(cŒÑÈ«UxI_à4Qµ&É?q­ãÎ|KÊz‚ 'kjYY8Œ)ÙŸåç[ÑÿYòŠ[6_f“œZíœé/9µLh‡L´ìp%xˆVá ¼ï߯ˆEmn+ o­³: ²ú "ii *SŸ¹}ó¦ 3xT-Áœ6ûÄ5ÅvL²ºò¨ËÖ>voXyzÑ´ÏÒË·,ý›Â<áŠuÝ«B8Fa]¦ÌÌÔŠ}h*…⌠D`M/5%ð³dÛÅtÑC´j£ðx4OýD]–õ',”!’m("ûÕTËØ5XgÖ@Φt/;eóÔ>¸ªš–¸†im!¦Ã¡´ì!ŸÛ“ù”/|Y¨›°áËñ¡º‡<¼z¤Ð]‹ ãÔˆ;ž$ž‘ŒG [{J NæxÐHú¬ ý[µIH0Mã)Ôt4âC÷ÈM®ÆŽéMu{½Çâo‹‹RðHœÙôíP¤4wt6ç¶¥zFÉ#y_3µ¡úLŸƒ£ÌŸfd:š m„ G÷0½IäðJuéRí%ªè‰S$Ø :v„ÄZ¯ðÏP-ˆq„ÝjŸ—ä—¹W‡ÄøWUû&}°À€™ðõWäÂ]¨®kA5Âz·Áªë1’ERLs; [tO”’_ \Si:qºÖPkDº.uÄFD~]ŠM™Áó]XVÿ¥ˆjÜ¥•eüÕãX5¥QRX°B1מg&£f.Ÿ^ä]9Ákª€”o™@ éõ°áðßüÌÄG72ÊôOÒbUë%v¬å;vÚíÛtqêýHxu:9¬ŠÜ&ˆ X×JmnÒÓY:y½v'T¬EgË]&ØY‘vŠ]WŽWN¡n¶ï¯×®ÒZ8{ä«D×Cž$à‡$‚™µ/sùfè·Fõx‘)nBÑ‚ £€&¦Ã¢€*Ç Ú4aìo¨Z€P@(¨Já•e-«B¼R¶”Ôß* Jé·ÁÒcû-µ™_DKP¦ ¼KºTÃU‰í;ˆ€ÝgžÊ)¿>³•ÍU¢ßt–ËoO.Ù³üC[ð1ÖsCÿt“:ˆ„,‰—2|N¡\]i{þ¸O$Ê p³¢¬…‹B¬póXÿà5k*Hz»"RÄPÙÃ)LK‰…—†U‰ZT †M+ËÊk¼QÉqÃ1å]ø$hÏ“òOx½2‹n»•UAºîѸir» ü2•Ϲ¤9[YËñy+ŒªŸ®„‰E‰ÅJ ‡ºêÎõõ"ô^oú º…÷( €¸—hÒ:;1«½Õh9†š1îUjâkB‹q³;烺Èš“H•†ž~g4L=Èm†sŽÀbMKo^Ç –¨ia®u%uµ+sA Æ‚2CO†Åî;㵇_–R`Ì Ô˜ºA™ã¡Ó}±¶Õ ’YkÑ›èšJÿb*‹±ÄPc©w…¶xñ÷0²ÏϦòã:lQµtœ¸Š>¥Ôªíèˆ+ðÄê{ᄚ”Òñm)@«3@I‘ùjR?wíŸò±ëyÖªiªÝzø«!` !ÇH° v£ê€½Ë]q9}š~¸°ÊF½BWÖ—êm5ŠdNnaÐC¡hDLX\|ÿâ 0‡€{Œz¯:N¼þ…û§)ƒ¼Î »S1/º¦Cò ­°!ÆœW» |o2£†/­¹›‚NbZh)#ÏÌË”?_cßEzY ßnÓ ¾‹â’|Úã¯:«†þMF†òç9!ðHo¿a=Ù¾åÇ 2Y‰yø\a,„‡m‡9ÐñD[ÁK¾ØÌ…ÊÁíÂÚEƒç7Q cš‘ýÊK6µâÿäì(3¹³D}ï^i„ÌÈ*ÒmŒˆÓÿl±À!8#Ò–Qo67Ñy ×õTXÿ‚z’Öí»?¡÷“zy0èó<Òòù(¤i5ó\WÃö`ÜyàîBÏrYßS qÄAãWß!ÚáÐ;¼:úçLØwüí¡™€½ýú‚›ÎÐæBM¡§-H³‰Œ'8¡xKºÒ0ÍäÂ0e&ó_Ì×X0ÙB=Þ¦ñíÆ³‹ûÔ·¬{Z>ï4AjO¨ÿ±¾ïR YHeô`ÿKÏÒ'±w ,“â¼v½ w¡ÜÙ0;Rå´‹Ôn,`ÊA„æÏ…²!¼òæ@%¹-´°ˆÀâ?Yæb^oƒšI3ÞüÏeH ß¿[: Íad¿}I!/ïÔÞ°Ú™Š×˜íq4}êù7Ęº/«i ~aëcDCžòOrà&@ÓšÛ=¨ÑÔ m9¨ê!qºÓíH¿r&,´àߺ;ˆ.-ÃF•¢Áy«\ ÉZG6‚ìäSêÝ~ÌÈDóéº-P×pü„AÚHî¿ÒÐ-g¿´µdµ øšJðBxqžÁï*…V3À5nÉéœ7Cœ4€9j$¹£ç©RÉùýÞÎ AÎvm3CÞ¤Ês>d̈{®òø”ŃQ²\x˸S,Ž“Uc!’ƒ.ôD°øG#èXPEÆí ZvvB97=yUñ{Ìw?›JFÕ4]·¾vÆÞâ#¤?,Ò×1Ô6ôæ\›ZÅ âÜ68ß®éÙ¾„§êÛ‘ÆÅùQ×b¶µ–Q¨ä?ð`Ç®-ìîµN,DqÈÙ°C_»<2Õ‘êÖãDkÑ΄‰ï é±»,Œ³îöü´•]ðMzÅä3[µÞTAµ×+/œTu†±·o*ÇÙÐy=×|ýM]`j\!žˆêÐwCÍ” A¯Šþ2³¨lÝØœ›!|rn+{<)Äê¾äÞÖ‘LjåÄ•Ý!FžƒÔ».[¶m\E€˜ïEß‚#eÝó܆>¿—\V&RhV¶œ7§Åq¡ÔÉQ >5ˡҽgRÝüï`PŠÏ£ë\ê…šš_שͤ5ÞPÆ{3ÞÝ™ñJäo.‰=J8„ŽënªæLô/ggÆ7ÙËRÁ†éâöŸ¾ÕtÓut|uißB·rœ‹EÏ?Zл| q­Ù[&æ·¡LXCf>IÁÕæÂ¾°õÔ-•K“Ž!†«i¼’x—šâÑš˜½Î¾0)Ö>o9 EÀ«+ƒUÌù'½GÕßµhø»ûóÆ!a<ã qôTñÚ%M£¥KÄ\–Ô€‘y&ô¾—¾Ïbo¼ÝE,CR^dŸñ«'zûÎVh×õ²ÐÑièÎe“ Œ²´žŒ yÁTêMüÂ:¯Û(IX“ÿ²B qG1ÇOX´Ÿ%ͳª‡Eõ)­R ú=²8 z1ÈW=É·÷ $l~sÄß[ˆ¥´Z)YS;Ý#aÙù·^YÔ¨ª‹¦Ý ÿKÅM‘÷™Ä`.ås¢VýÁ<YîÓR8œ °…u·®,ø3/3B¯ú¤q_ÁS£Uçïû4üë4¨¬›»G‹ W¤¡Â4†GaÉxÖ=&¡p£ç_镗ЀyH¢ïq4G‹æ~®†~°¨¬§ýoRgŒ-Ñx D²Á쪯ø8‡Lº 89C¢-þƒRºžÜKDµzYK"Œêž¥?8bš”Öw e¥Í6ºcëš“áĸ~Úœ…ˆ¼6#€‚ppºsÕ莕£RZÎ"–§†U®Ÿî$úË+èìkÍgî[ÿÚª° E~}•4ãÇúKJ`ÀÊÿw¬Q)ñdÈ·¨NHèòÆ*ìÉ&¶ ^gƪõ ! üº.ó!DM41Œ=voxbo-1.8.5~svn1246/brainBrowser/region_relation.h000066400000000000000000000124501153177201300221160ustar00rootroot00000000000000 // region_relation.h // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /******************************************************************************* * regionRelationRec class definition: hold region relationship information *******************************************************************************/ using namespace std; #include #include #include class regionRelationRec { public: regionRelationRec() { clear(); } regionRelationRec(void *buffer) { char *buf = (char *) buffer; int longLen = sizeof(long); ID = *((long *) buf); bufLen = longLen; region1 = *((long *) (buf + bufLen)); bufLen += longLen; region2 = *((long *) (buf + bufLen)); bufLen += longLen; relationship = buf + bufLen; bufLen += relationship.size() + 1; qualifier = buf + bufLen; bufLen += qualifier.size() + 1; creator = buf + bufLen; bufLen += creator.size() + 1; addDate = *((long *) (buf + bufLen)); bufLen += sizeof(long); modifier = buf + bufLen; bufLen += modifier.size() + 1; modDate = *((long *) (buf + bufLen)); bufLen += sizeof(long); comments = buf + bufLen; bufLen += comments.size() + 1; } /* Initialize data members. */ void clear() { ID = 0; region1 = region2 = 0; relationship = qualifier = ""; creator = modifier = ""; addDate = modDate = 0; comments = ""; } /* Return the whole data structure. */ char * getBuffer() { memset(databuf, 0, 1000); bufLen = 0; int longLen = sizeof(long); memcpy(databuf, &ID, longLen); bufLen += longLen; memcpy(databuf + bufLen, ®ion1, longLen); bufLen += longLen; memcpy(databuf + bufLen, ®ion2, longLen); bufLen += longLen; packString(databuf, relationship); packString(databuf, qualifier); packString(databuf, creator); memcpy(databuf + bufLen, &addDate, longLen); bufLen += longLen; packString(databuf, modifier); memcpy(databuf + bufLen, &modDate, longLen); bufLen += longLen; packString(databuf, comments); return databuf; } /* Return the size of the buffer. Used for storing. */ inline int getBufferSize() { return bufLen; } /* Print out all data members. */ void show() { printf("Relation ID: %ld\n", ID); printf("Region 1 ID: %ld\n", region1); printf("Region 2 ID: %ld\n", region2); printf("Relationship: %s\n", relationship.c_str()); printf("Qualifier: %s\n", qualifier.c_str()); printf("Added by: %s\n", creator.c_str()); if (addDate) printf("Relation added on: %s", ctime(&addDate)); else printf("Relation added on:\n"); printf("Modified by: %s\n", modifier.c_str()); if (modDate) printf("Last modified on: %s", ctime(&modDate)); else printf("Last modified on:\n"); printf("Comments: %s\n", comments.c_str()); } inline void setID(long inputVal) { ID = inputVal; } inline void setRegion1(long inputVal) { region1 = inputVal; } inline void setRegion2(long inputVal) { region2 = inputVal; } inline void setRelationship(string inputStr) { relationship = inputStr; } inline void setQualifier(string inputStr) { qualifier = inputStr; } inline void setCreator(string inputStr) { creator = inputStr; } inline void setAddDate(long inputVal) { addDate = inputVal; } inline void setModifier(string inputStr) { modifier = inputStr; } inline void setModDate(long inputVal) { modDate = inputVal; } inline void setComments(string inputStr) { comments = inputStr; } inline long getID() { return ID; } inline long getRegion1() { return region1; } inline long getRegion2() { return region2; } inline string getRelationship() { return relationship; } inline string getQualifier() { return qualifier; } inline string getCreator() { return creator; } inline long getAddDate() { return addDate; } inline string getModifier() { return modifier; } inline long getModDate() { return modDate; } inline string getComments() { return comments; } private: /* Utility function that appends a char * to the end of the buffer. */ void packString(char *buffer, string &theString) { int string_size = theString.size() + 1; memcpy(buffer + bufLen, theString.c_str(), string_size); bufLen += string_size; } long ID, region1, region2; string relationship, qualifier; string creator, modifier; long addDate, modDate; string comments; int bufLen; char databuf[1000]; }; voxbo-1.8.5~svn1246/brainBrowser/searchBrain.cpp000066400000000000000000000414161153177201300215160ustar00rootroot00000000000000 // searchBrain.cpp // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* This program searches brain region in text mode. */ #include "searchBrain.h" string dbHome; string rDbName = "region_name.db"; string rrDbName = "region_relation.db"; string sDbName = "synonym.db"; bool a_flag, ik_flag, ins_flag, ir_flag, is_flag; string keyword_in, rName_in, synm_in, ns_in; int main(int argc, char *argv[]) { // Validate arguments int foo = parseArg(argc - 1, argv + 1); if (!foo) help_msg(); // Find directory where bdb files are located if (!setDbDir()) { err_msg(); exit(1); } vector regionList; vector synmList; if (ns_in.length()) { if (keyword_in.length()) { searchRegionName(keyword_in, ik_flag, ns_in, regionList); searchSynonym(keyword_in, ik_flag, ns_in, synmList); } else if (!rName_in.length() && !synm_in.length()) { // collect all names in a certain namespace searchRegionNS(ns_in, regionList); searchSynmNS(ns_in, synmList); } else { if (rName_in.length()) searchRegionName(rName_in, ir_flag, ns_in, regionList); if (synm_in.length()) searchSynonym(synm_in, is_flag, ns_in, synmList); } } else if (keyword_in.length()) { searchRegionName(keyword_in, ik_flag, regionList); searchSynonym(keyword_in, ik_flag, synmList); } else { if (rName_in.length()) searchRegionName(rName_in, ir_flag, regionList); if (synm_in.length()) searchSynonym(synm_in, is_flag, synmList); } showMatches(regionList); showMatches(synmList); return 0; } /* Parse arguments in command line * returns 0 if arguments are in illegal format; * returns 1 otherwise. */ int parseArg(int argNo, char *inputArg[]) { if (argNo == 0) return 0; vector argList; for (int i = 0; i < argNo; i++) { string tmpStr(inputArg[i]); argList.push_back(tmpStr); } // by default, both detailed view and case-insensi a_flag = ik_flag = ins_flag = ir_flag = is_flag = false; for (int j = 0; j < (int) argList.size(); j++) { if (argList[j] == "-h") return 0; if (argList[j] == "-a" && (j == argNo -1 || argList[j + 1][0] == '-')) a_flag = true; else if ((argList[j] == "-k" || argList[j] == "-ik") && j != argNo - 1) { if (rName_in.length() || keyword_in.length() || argList[j + 1][0] == '-') return 0; keyword_in = argList[j + 1]; if (argList[j] == "-ik") ik_flag = true; j++; } else if ((argList[j] == "-r" || argList[j] == "-ir") && j != argNo - 1) { if (rName_in.length() || keyword_in.length() || argList[j + 1][0] == '-') return 0; rName_in = argList[j + 1]; if (argList[j] == "-ir") ir_flag = true; j++; } else if ((argList[j] == "-s" || argList[j] == "-is") && j != argNo - 1) { if (synm_in.length() || keyword_in.length() || argList[j + 1][0] == '-') return 0; synm_in = argList[j + 1]; if (argList[j] == "-is") is_flag = true; j++; } else if ((argList[j] == "-ns" || argList[j] == "-ins") && j != argNo - 1) { if (ns_in.length() || argList[j + 1][0] == '-') return 0; ns_in = argList[j + 1]; if (argList[j] == "-ins") ins_flag = true; j++; } else return 0; } return 1; } /* This is the usage message that will be printed out if the arguments are invalid. */ void help_msg() { printf("Usage: searchBrain [ ] ...\n"); printf("flags:\n"); printf(" -h print out this screen\n"); printf(" -k search both regions names and synonyms by case-sensitive string\n"); printf(" -ik search both regions names and synonyms by case-insensitive string\n"); printf(" -r search regions names by case-sensitive string\n"); printf(" -ir search region names by case-insensitive string\n"); printf(" -s search synonyms by case-sensitive string\n"); printf(" -is search synonyms by case-insensitive string\n"); printf(" -ns search region names and/or synonyms that are in a case-sensitive namespace string\n"); printf(" (NN2002, AAL or Brodmann)\n"); printf(" -ins search region names and/or synonyms that are in a case-insensitive namespace string\n"); printf(" -a print all information available about the matched regions\n"); printf("\n"); printf("======= ACKNOWLEDGEMENTS ========\n\n"); printf("This initial release of the VoxBo Brain Structure Browser was written by Dongbo Hu (code) \ and Daniel Kimberg (sage advice). "); printf("It is distributed along with structure information derived from the NeuroNames project \ (Bowden and Dubach, 2002) as well as the AAL atlas (Automatic Anatomical Labeling, \ Tzourio-Mazoyer et al., 2002).\n\n"); printf("References:\n\n"); printf("* Tzourio-Mazoyer N, Landeau B, Papathanassiou D, Crivello F, Etard O, Delcroix N, \ Mazoyer B, Joliot M (2002). \"Automated Anatomical Labeling of activations in SPM using a Macroscopic Anatomical \ Parcellation of the MNI MRI single-subject brain.\" NeuroImage 15 (1), 273-89.\n\n"); printf("* Bowden D and Dubach M (2003). NeuroNames 2002. Neuroinformatics, 1, 43-59.\n"); printf("\n"); } /* Set location of bdb files. */ bool setDbDir() { vector dirList; dirList.push_back("/usr/share/brainregions/"); dirList.push_back("/usr/local/brainregions/"); char *homeDir = getenv("HOME"); if (homeDir) { string tmpStr(homeDir); tmpStr.append("/brainregions/"); dirList.push_back(string(tmpStr)); } dirList.push_back("./"); unsigned i; for (i = 0; i < dirList.size(); i++) { string fn1 = dirList[i] + rDbName; string fn2 = dirList[i] + rrDbName; string fn3 = dirList[i] + sDbName; if (isReadableReg(fn1) && isReadableReg(fn2) && isReadableReg(fn3)) { dbHome = dirList[i]; break; } } if (i < dirList.size()) return true; return false; } /* Check whether the input file is a regular readable file. */ bool isReadableReg(string inputFile) { struct stat fileInfo; int foo = stat(inputFile.c_str(), &fileInfo); if (foo || !(S_IFREG & fileInfo.st_mode)) return false; if (fileInfo.st_uid == geteuid() && (S_IRUSR & fileInfo.st_mode)) return true; if (fileInfo.st_gid == getegid() && (S_IRGRP & fileInfo.st_mode)) return true; if (S_IROTH & fileInfo.st_mode) return true; return false; } /* Print error message when db files are not found. */ void err_msg() { printf("Database files not found in the following directories:\n"); printf(" /usr/share/brainregions/\n"); printf(" /usr/local/brainregions/\n"); printf(" $HOME/brainregions/\n"); printf(" ./\n"); printf("Application aborted.\n"); } /* This function searches a certain string in region name db and * put matches in outputList. * Returns 0 if search is successful, non-zero otherwise. */ void searchRegionName(string nameStr, bool nameFlag, vector &outputList) { printf("Searching %s%s records that contain %s ...\n", dbHome.c_str(), rDbName.c_str(), nameStr.c_str()); int searchStat = findRegionNames(dbHome, rDbName, nameStr, nameFlag, outputList); if (searchStat) { printf("Search failed in %s\n", rDbName.c_str()); exit(1); } printSummary(outputList.size()); } /* This function searches a certain string in a certain namespace * in region name db and put matches in matchList. * Returns 0 if search is successful, non-zero otherwise. */ void searchRegionName(string nameStr, bool nameFlag, string nsStr, vector &outputList) { printf("Searching %s%s records that contain %s in %s namespace ...\n", dbHome.c_str(), rDbName.c_str(), nameStr.c_str(), nsStr.c_str()); int searchStat = findRegionNames(dbHome, rDbName, nameStr, nameFlag, nsStr, ins_flag, outputList); if (searchStat) { printf("Search failed in %s\n", rDbName.c_str()); exit(1); } printSummary(outputList.size()); } /* This function searches regions that belong to a certain namespace and * put matches in outputList. * Returns 0 if search is successful, non-zero otherwise. */ void searchRegionNS(string nsStr, vector &outputList) { printf("Searching %s%s records that are in %s naemspace ...\n", dbHome.c_str(), rDbName.c_str(), nsStr.c_str()); int searchStat = findRegionNS(dbHome, rDbName, nsStr, ins_flag, outputList); if (searchStat) { printf("Search failed in %s\n", rDbName.c_str()); exit(1); } printSummary(outputList.size()); } /* This function searches a certain string in synonym db and * put matches in outputList. * Returns 0 if search is successful, non-zero otherwise. */ void searchSynonym(string synmStr, bool synmFlag, vector &outputList) { printf("Searching %s%s records that contain %s ...\n", dbHome.c_str(), sDbName.c_str(), synmStr.c_str()); int searchStat = findSynonyms(dbHome, sDbName, synmStr, synmFlag, outputList); if (searchStat) { printf("Search failed in %s\n", sDbName.c_str()); exit(1); } printSummary(outputList.size()); } /* This function searches a certain string in a certain namespace * in synonym db and put matches in matchList. * Returns 0 if search is successful, non-zero otherwise. */ void searchSynonym(string synmStr, bool synmFlag, string nsStr, vector &outputList) { printf("Searching %s%s records that contain %s in %s namespace ...\n", dbHome.c_str(), sDbName.c_str(), synmStr.c_str(), nsStr.c_str()); int searchStat = findSynonyms(dbHome, sDbName, synmStr, synmFlag, nsStr, ins_flag, outputList); if (searchStat) { printf("Search failed in %s\n", sDbName.c_str()); exit(1); } printSummary(outputList.size()); } /* This function searches regions that belong to a certain namespace and * put matches in outputList. * Returns 0 if search is successful, non-zero otherwise. */ void searchSynmNS(string nsStr, vector &outputList) { printf("Searching %s%s records that are in %s namespace ...\n", dbHome.c_str(), sDbName.c_str(), nsStr.c_str()); int searchStat = findSynmNS(dbHome, sDbName, nsStr, ins_flag, outputList); if (searchStat) { printf("Search failed in %s\n", sDbName.c_str()); exit(1); } printSummary(outputList.size()); } /* This function prints out the number of matches. */ void printSummary(unsigned matchNo) { if (matchNo == 0) printf("No match found\n"); else if (matchNo == 1) printf("1 match found\n"); else printf("%u matches found\n", matchNo); } /* This function prints out the matches found. */ void showMatches(vector rList) { unsigned matchNo = rList.size(); if (matchNo == 0) return; printf("\nRecord(s) found in region name db:\n"); // Default brief view for (unsigned i = 0; i < matchNo; i++) { string briefMsg; if (ns_in.length()) briefMsg = rList[i].getName(); else briefMsg = rList[i].getName() + " (" + rList[i].getNameSpace() + ")"; printf("(%u) %s\n", i + 1, briefMsg.c_str()); if (!a_flag) continue; showRegion(rList[i]); } } /* This function prints out the matches found. */ void showMatches(vector sList) { unsigned matchNo = sList.size(); if (matchNo == 0) return; printf("\nRecord(s) found in synonym db:\n"); // Default brief view for (unsigned i = 0; i < matchNo; i++) { string sName = sList[i].getName(); string rName = sList[i].getPrimary(); string briefMsg; if (ns_in.length()) briefMsg = sName + " (synonym of \"" + rName + "\")"; else briefMsg = sName + " (synonym of \"" + rName + "\" in " + sList[i].getNameSpace() + ")"; printf("(%u) %s\n", i + 1, briefMsg.c_str()); if (!a_flag) continue; string nsName = sList[i].getNameSpace(); regionRec myRegion; int foo = getRegionRec(dbHome, rDbName, rName, nsName, myRegion); if (foo != 1) { printf("Region name db error.\n"); return; } showRegion(myRegion); } } /* This function collects a certain region's detailed information and prints them out. */ void showRegion(regionRec myRegion) { long rID = myRegion.getID(); // Get parent and child(ren) information string parentStr; vector cList; int foo = setParentChild(rID, parentStr, cList); if (foo) return; // Get synonyms string rName = myRegion.getName(); string nsName = myRegion.getNameSpace(); vector symList; foo = getSynonym(dbHome, sDbName, rName, nsName, symList); if (foo < 0) { printf("Synonym db exception\n"); return; } // Get relationships vector relList; foo = setRelationships(rID, relList); if (foo) return; printf("Region name: %s\n", myRegion.getName().c_str()); printf("Namespace: %s\n", myRegion.getNameSpace().c_str()); printf("Parent's name: %s\n", parentStr.c_str()); printf("Child(ren)'s name:\n"); for (uint i = 0; i < cList.size(); i++) printf(" * %s\n", cList[i].c_str()); printf("Source: %s\n", myRegion.getSource().c_str()); printf("Link: %s\n", myRegion.getLink().c_str()); printf("Relationship(s):\n"); for (uint j = 0; j < relList.size(); j++) printf(" * %s\n", relList[j].c_str()); printf("\n"); } /* This function returns parent and child names. */ int setParentChild(long rID, string &pStr, vector &cStrList) { long pID = 0; vector cList; int foo = getParentChild(dbHome, rrDbName, rID, &pID, cList); if (foo < 0) { printf("DB error when searching parent and child in showMatches()\n"); return 1; } string spaceStr; if (pID) { foo = getRegionName(dbHome, rDbName, pID, pStr, spaceStr); if (foo != 1) { printf("DB error when getting parent name in showMatches()\n"); return 2; } } for (unsigned i = 0; i < cList.size(); i++) { long cID = cList[i]; string cName, spaceStr; foo = getRegionName(dbHome, rDbName, cID, cName, spaceStr); if (foo != 1) { printf("DB error when getting child name in showMatches()\n"); return 3; } cStrList.push_back(cName); } return 0; } /* This function returns all relationships of a certain region ID and put it in the last argument. */ int setRelationships(long rID, vector &outputList) { vector r2List; vector relList; int foo = getRel_ui(dbHome, rrDbName, rID, r2List, relList); if (foo < 0) { printf("Relationship db error\n"); return 1; } for (unsigned i = 0; i < relList.size(); i++) { string r2_name, r2_space; foo = getRegionName(dbHome, rDbName, r2List[i], r2_name, r2_space); if (foo != 1) { printf("Region name db error\n"); return 2; } string tmpStr = relList[i] + ": " + r2_name + " (" + r2_space + ")"; outputList.push_back(tmpStr); } return 0; } /********************************************************************* * This function is copied from vbutil.cpp (comments removed). * It uses the input regular expression to validate the * input string. If the input regular expression matches the input * string, then true is returned. Otherwise, false is returned. *********************************************************************/ // bool validateString(const char *regularExp, const char *theString) // { // regex_t regex; // memset(®ex, 0, sizeof(regex_t)); // int err = 0; // if ( (err = regcomp(®ex, regularExp, 0)) != 0 ) // { // int len = regerror(err, ®ex, NULL, 0); // char regexErr[len]; // regerror(err, ®ex, regexErr, len); // printf("Compiling regular expression: [%s]", regerror); // exit(1); // } // size_t no_sub = 1; // regmatch_t *result; // if((result = (regmatch_t *) malloc(sizeof(regmatch_t) * no_sub))==0) // { // perror("Unable to allocate memory for a regmatch_t."); // exit(1); // } // if (regexec(®ex, theString, no_sub, result, REG_NOSUB) == 0) // { // regfree(®ex); // return true; // } // regfree(®ex); // return false; // } voxbo-1.8.5~svn1246/brainBrowser/searchBrain.h000066400000000000000000000036041153177201300211600ustar00rootroot00000000000000 // searchBrain.h // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /* This interface allows user to browse/search brain region database. */ #include "br_util.h" #include #include #include #include #include int parseArg(int argc, char *argv[]); bool setDbDir(); bool isReadableReg(string); void help_msg(); void err_msg(); void searchRegionName(string, bool, vector &); void searchRegionName(string, bool, string, vector &); void searchRegionNS(string, vector &); void searchSynonym(string, bool, vector &); void searchSynonym(string, bool, string, vector &); void searchSynmNS(string, vector &); void printSummary(unsigned); void showMatches(vector ); void showMatches(vector ); void showRegion(regionRec); int setParentChild(long, string &, vector &); int setRelationships(long, vector &); //bool validateString(const char *, const char *); voxbo-1.8.5~svn1246/brainBrowser/synonym.db000066400000000000000000013000001153177201300206000ustar00rootroot00000000000000b1 @ Ø Ø ”’ˆÆ¤ —ö«ÄáÄyu\$æc€¥Æ7¤Ù–Bᑹ™Ÿº'“‰¤¬0 ?Šî#ÚCÐÛQ™ø@žqÔi­Ã@²ü²7qÃ3²±×§Zä«Ã½%ÛþˆF›lQSÔÒÖ:)Òꂤ¯ wª†¦üVIGPãT:’°™õÚÙãáÓ4t"fo=^eÄIJ ‹·»%ýNXŒ)h,ÜÑ1 ²cÏ~]çTO°õ/µ|¤‡…M{³žR,0.wvåcÃ…tyQ¾Ëðz_Ñ?GþC»|êvãóÁŽW[T1ÜÃrxqr䔌Ëí*LØk. :¢5so¬´‚ÜLES©¢U“_ o”åó0ò÷''¢Y”šùØ?Èó›&‡U.µ'&Gæ¼# •J*·®¯s`T«{ ákþâ=X"BÔ&’Ò«­Tm—Du†wFt¹€e·lã Ó†/±#®Á§DôqçE³¥)¹ÕÇ€í!óć’ôKž_Tç• b˜—…ÕÇD…ãXõ¯Ø„µ:)öÇÕÚÕ7?œˆqvˆ 2xˆÓôì™bœô!Ö§~a ,C¥uÄ>‡Ij…-¿%,RÃåXýmêJ#’sÚÍZ/¢4¥“ ËçŒE“v ȼò=“ ²©ÔÑÚ%€Ë*‘0uBqïPy+f¢6ß&ÌÓ0Uš`],xcÒäºß§M˜Ÿ„+ûÇ—å@;ÊõïáÑ—ÒÏ2eÑbÁßÊýŠÔˆ¼{£¯ª$±‘/ú4eqS<&iº’9KÒ\ç˜[C[bþYiú%þªëÃO¶䄇°5ì!ñìÞR­äÉMÏr@áÚñüU %ãE/Ýw£"h}%M1¶&DƒÐ!¯g#=nÕ[x9µcšð3KÿÈ óò*¹ÞüëØîÍ%" ÇžÞTä8çÚ#xÅY \×<X¯¾òýQn(àŽÅ‘¯ä¢2©Ð]ô`𠵩“‡¤“Ö3¾B>A(&D¡fDp4SûÉb˜¾óÃíEã?]ÜóœæG¤·ŒI?gÃ3þÈmá'A8cmI. ú´—TéQÝ}¢:<úü4#*VMô¥nϰ6¦2¦ñD˘…ò¢"-uÿÖª³LD†ºóîwx2Zz£¹UµÉw‘sÌPpγÜq¾çaQ©½¹ ݪÌ,'ó˜&Utj¶¶ŒÙ%ŸZ“©3 £mG´#úzj #5—\}”൧+۲𘷛×0G¸-²È¤Ç XñRºúÁëyéd\¿-fë²ðåô†¼C=YƒÓ˜ˆýoéÚ XÖ̉ƒ¡ 5Y[we+"Fp…ø.åYhÿÍÆáWšÛÁÔ9‡8 n“ÐHæg¼O@ B5 R}S^Ÿ±áÆ6¹ÓíP×£LF‡ЀrX ÖKb°<€ýñÆ(,ÉØãû¼°A«õ]"D;ãÂû l2Ä 9÷q¤þû‹õ¦aÙß¼nL(ÆTg®ß:?DÓ@ˆô~û'BP Fˆ Äwôµ“¸Howo_asxdw]¸)xHœ!ªB[ÿr¬M;ºgËT¡!Álûã´‚lˆ5"©FIp«‘ GÌr¬²‚ÝÌjží$:Nâiñ™é|uó?Aˆ’§Ï{ǪÒMø“&×8?ïtM\<’¹÷Œ—V·¥L—ªzçh.œ…÷ ëºæ£†b›ÆwĘ–èµB`†<νø¼T¦ñÚJ£èÿT›æÞ'[Š1m?= !¹M;š~Þ€þÙtLÓ-N{Ü3ÂÏj©Ém®ƒì(Û‡ÖÒª((fíøÏgb|g–íaÖû7ÅÊ_ûh_X ôA<‚{ÄëÞSó÷äwÆ*XïTzÌÿQNûfÓ®,(ohl”À‹ÑÕþ"öñxFi'ßvPÓ kƒÖ1·…´O ^æX{j×ó1HËÙF™Æ€±KáÑ.àñ˜Öš³ ¸5æúhí’‹ )oý5Õ£Àž‡ùŒ³Í.K„Ö©Wð¸Â›´Sra)|•üÎTñàý rW‡{‰|ulÅ`;x¨[9‹õÚ´âÙ…ÎÄÿ ¾ˆ×µßF÷)YúãC¶o¿Tdê¬9Оȓ ”ýgJ8ƒ:€Ä†øyÈr§¬»s’RE¨˜¶úµWìrIþ’¶ÌPáÀ²¬þ¡sèø€£pr ÿåUÓV6²£Ú@ô‘¥2ÝgÊm+§¯ýÜ™†WĘ=~¶„' \ÒžLñ<ÖrÅ@¸[úPTïçWeñ€ÍË… !bÙù¹{Ζ1šØ+ÿ¢P±[^QÝZÿPåc’ËOá4¸"0L‚-6“"ÄýúL]j‚©ù%¡sÆK„"™¶ âHò9Lžâ•® ¡JGŒ'Ÿ½÷ú]‰;¯Ÿ2&ž Ø+\e> DJU)Û´2OþÊ„šf£@ÿ4p¬¤Ñ|åTÔ«Ù6ÕU¢þ¡m/´IEbÃ=Ý~ºV„í4êÖév¨!¨É-‹sµbÉŽ"”Æ<‰×Ñ õ9%–'ÎÛ©ÇApníÓ¸ 5ù¸7åO'¦JÄûÎ)úA¦’NEYë€ùc€î…Sí ª­Øõ÷U«/«¼‚1roÀjvEz“«w/UÍvôÂá2')‹ç֠ˆáã­ÝéU’œô}^ë pà¶ÉòPæV©'v&‚ FËA1ä5ˆ¬€fþÆEþÄqÜ&Ð-^dAE¦œ§ 퀎êsò£°#iɯŸà5}&h¤<¨æFÚ0¾¬Ýå ¦îé§™Ñü2'äßYÙfï‹ep&dÏ/OJd)ÚIAÇ)v]O¡õÞê"šq™h* Ad/àL:d(ÿaß@÷줒{˜}ÌÈ" °* 3·!_z9:sÚg€#ygð.»½ý–j£PÙ·>#/Ò]ÇìMI}èÁí—íÅdÝ¿'‹™°À†§JL„&·ÄªBíøÀ£û1üIBùfW‚¥!mU*vÃAx‚Ê”€M€®ìÒ<{%d(‚#Ü¥ZÍó¬÷‚Zb$_Šy®þ¤ð7 Ö»'‘ È„¤ì¼i œöþe™yH«=ªéÄ€®ŠuËÅ ê·iÈø›·…˰A#ƒ1“pÉÊ€RÿþúÛÿ+|Ø|¼ÜYŽÁb“`ÙŸcFwäÕŽLf¹®Iå|†à­œÕ°#”°zèc÷j4½þ?¨y¹ ÆV_5  Ž$jÞ+ôÍûiÒË›³Nw2iPË飨éfgE(3Fs×d£sžOt¼ð¡9H’ø«×€¢Ø½òFŸTˆhïò“3<éUÌ®øôåÌI„åNn|\µÃBRlâ‚ákn#_!Dw5’‰ìtŒ¢¬¨LÕ¸ã5tIà´C…Ȇ)]=ñJXïK™6†6„§Ò#€ÜÔBHo°ÑTîGhQk}A»m?™Þ "H¦AÊKŢȤ›’} f”Žl¥ápÝ–ÈF”D^£<ÚŸkK×u„´ë š“b­/ÅšO7ÐÇð¾oº¡)‹ß_^¯©5Á×Tm–n®$.!W§D¨Úëeð¯{ç'0$Æ¥¡N2!ÿè8‰üüY÷ºÿ€èóçÈׄߦϋ¬¬htùSÛu!(“ŒÕ™<óìøZ÷Í© Q†Ö‚B;ŽUÖ›’x¿h‡{’ÊèÂ>ºYð4+rt"8hNP«å9¯#$öqsô¿íøù¶OG ÷áþ¸;s†wè¤â=~Þå? ûmùì» +@¶è…¨kTÆ#þ=½W#ŸÜÂCÂý³mŸè•™¦Vèot¾[ŠZ;ò‘¸f!EÑ 9<’Ë·¶XËÊã‡+‰@g·%·ÌYÙ €xNY`hà®-f¦“&×-¡V‚ÅÎ`A¨P°Ú Ü 0Ëî=ÊÐ…ø0}k”yW¸Ï@wñjh­¥Ö(¨”šÔe‹ï¦d—u?Ç‹1XÕ Ú\bdo¸<0™çPÖ²&r:CG¦KoÝíÒ„y Ø+¤â‚ñÛFâA%¬²xë}ßvü K»œ,7ð,fàðƒ#‘£Ð‡ÜšÎ£â/­:à=@ƒ2^¥jW­Ü;$ÉÈOÊY“`l¯£´±09Ì·€ÕÝ"לئï2%ý#ÍðÍÁ Æ uS0ݹˆªI NÕÀG¡±®ö»SÆh]µÝÞ·«®v2òÕŸ½‰lü»$ýÙK׿ý¾$JS\ ‚³E_—6RRµm AÐb # üS4·®Käô³O;$þKåe¯€Ž{$”F›µá¦˜~¥uÉö¡r[‹Á«q[½Öu7Õˆ;_ß<ìØûü”'…UBF(#LãKnû('[¬«àZšIxPC`èX8êìC 8‡÷ý¦øO|õ%£[4œøX}©Þ29|¦lâ§`þÝ 0Ð"÷lBwvÁH¼´G¦?§>ʼ¿ qÛæ$OƒÖ2ºÆP¿YÑ À÷ÓÆú/²¬Ïê6G:1™üM³gÒq gœ¸õ!Uö‘ж6TV7¶.ú¦¿©(ýØåþ>„¿x‡ÞïEÓ@’,–b‹QûNRrX„ÀP»~e™¶kÑA§åsïƒýÒ¤1›(›`ÁÁjRªA0YÙN«Û¨ÈåÁ/Hȳ¬M¡ž³µª8û Ò—N´Šúá1tf`ª€þ¿ p˜°Hî½~bßO#ôÉ8ƒc«ü¥ï®ÎI6mëê„,Ðó¹þ€äO¹ž|ðòƒ;»¿/µ=£váƒ1 qŽ¥ì”ìÊ^ª"Þß ‚<.öÌšƒV_~òðëÐí_Șx×¶)1U íÒ‰òéÇE 3TWÞ†C&BåeƒÏÃüËóðyêMË5±U[tsãm´^gN#I¤£+jðö¿¾M\¤wÿÖ ”ÂM³‘´”¥ KªÂWÞfÇ›ÞЇ³§/ƒÓŽ’¾ÝïÝaEV^Ûq}ÊðÃ1¤”›³g¹ç An ]~ÀºElÈ"õfé¾ÞÁuÁI×I¥>²Û”„àŒø'2°R.Ïß…LöÒºSŒlÇ0‚H¦³P1Ûf•*KØú ›£ÔŸnò.O©W{h_Ý—K_!£6o™?اI˜í¥Gì h¦‰‡~Õ‹:C*¿,Ôb®tÆ×i/öZ~ø_ãÍü«×”O=„ˆf"§Rû;Q ³û:íBJ ›ryHW쯼/TøX±ðP:²çhS¹Åª8ž‰’¹ “7ÄöìàNæ´l¶~úÿߟK–îµæ”›¶_D)½/¤æNܻҗ¸°}¡N›§€nìÙ¨›]æè`ÛÜUú €Îi®eviÿ.ÂsŸÏ‹É3Å¥ÕÂ95T{èÍÓQà·"£  Õ‡;¥‘È—ðÃóPOßœšÍ_šÛ£Ž9UåZh6„h¿üz)t|Û·ôø¼}Ü/J™(¤òbÈH«¹šûzn>½.J.C¶—R»tñ¤ÊÈê»’¾Nõ ˆ/I1ÄY;³}À‹ª´ì˜ýBgÒà/” A©jMG¼žÏ¨?÷C¯3 j*³¡ÀœºdáUä%2A®­ŠM­(x~-«xõM 9s|÷ú<o†ZÏõÏCfõ;Ôä¼äô¡fQ«ð.á_Q¬R{Á !Þ¾"1ªWcÎ0PRÒDÜZ«P…a,¦µ»~ x$^ + •NŽt‡ŽÖMñ?Çî¶<èþÔËî½·ƒ¿­ØÚܸø©ZâÜ`iÑ«_ý+p£|rô!©:!Žì÷£‡F—¢z€Ýݾxý HB/¾ñ‘jh‡Ñ¿]ê4ŸÇû(¦Ví6+‰÷;n˜÷l£OoðJñ;´•v³%²[ùøL±#‚êM“”¬.îO]Ç»J¶ åÞ¿6ƒ¹ºt¡ôëÀnþž±ŒQî8hó>Ö©¶½-E7Šga'…K«ŒBèªú ‹ |"³yÅÿè,ýÅž³o™ÏÝÖ#{V‘eæ@jºÔõUÎ3ŸÊªªù+!Žþéô·»ÏÊ~ 1~qhîœÅ.—QP&ŠjlQä‘ õ²ó˜˜ƒ¨òA€Œ«œ>ÿ~ Õ3™Róúª…ô&éÜÓî‹uO8•°Ó‘ø«LÀm­È°ÒQ‘‡ l{¦Yò†cœH6Þd¥Ñ^— ªf¦ô_†Shú§ó<ר-Z½ ÎM SH•Ø[yáÎhFj»R€w×ÉesÇ0I@!/‡EŒ~>€F­Õç ÄØ¾ñeÜ´»5YgöÄšš(%S]°Ÿù<¦˜ˆ?14ÚÈQ¾Ò=EïfÄ7%§5L‰i›ÐýZçyl‰Ÿ2µWjeTVxå³ F>ÍPîµ2$4žÐý ×ˆÁ»§ƒ¦Ž-™’«vdµìy^÷ùO¹–_Taß ¢âºç=gBUª£\!üŠb{±§ÂÌ¥œˆ´ì‘ÎËóîÖz¾ Á©Q¨oÄiÛz5Z€ïÂŽ=é­G 7±)³ŸuýWC—üp±&¼À;/š=Îôû°õ ­iŸ8ƒ½h+™Úœ†Ñc’ÇŸvÀ·“•8Çô#Ø,§{|¹ ÏòšKÊex‹á?icÕjÀ[¡Ó-öiÞ$ŠM–§|7ÜT:+\Ñ®Œ´ŠÕþïVºv|ê}º áX_ìæ•fHûFø›ðM¾«g¾+ÐA¾¥Ãð¶ mGTf¢`Dßä/x™fqäÖ³X“¾Y[# S ßf@vŠ‘ÒçX#bˆ‡íIo-?‰#ÕÂ^Î\¡.saw¯ø­—·¶P>áf\zD»«aZ„øúP‡…58á„=:¦§ÙûsYu΀^³Æb³xl.AU¨mj=º¯ž„ï]%ˆmn‘„Ç={# ©þë!g,#ϳ™Ð’—Æ€äúL‹ë‰ìÁ Ñ5˜5v$f_¿¼ˆåL-ƒ$[ŠÊä&)b·ni,G‚z¾&×oÕm_†“®OõE (Üa'i§&v(cù$&YjȚF1N]gS`?´«ÉÈ (…«mžÈÏ }ýPtÊk9±´}Ž>9—|÷$#$E†¤½"ƒðÃ5pZ ƒ†¦ñ@Õ&ÆÀ–M±Œ’/4N·k—‡#¸Æð›æ¾_ߦ—Ò4(E"ø‚O2¡=¹ŸsÿiˆÖ³§#|vÞÇ_„Ñ*€u½íIöO¹GG[ÏÌi’üt†ƒ&6ŸÖÏÙÝ-“=ÿQ:F– â–ò+)`ÞïäÜ®0ˆ„ͬú=>êò&6xH¬hæn®È;aðm¤;yP‰ + ÍL²SeNͼwlæ2טPG¯b*U·»nrX¬K{7gÐîîæ þ¾ŽÉÊ–ä×ióÙ†Êàôâ_È…^¬í,¤¶® l‚àgü½Ú•ì°óàêk$"ßÒ'ô…bý\Rœ"9«“3ZÚÀ "0Ópf¨wvîd¿µŒ¢SºVî,‘OM$C€ÃIšÛµ âÛ, xÀ©Yõu„ö©íóž Ý)•K4™‡ꨫI³ƒZþ‡*Ä+ &ÉEtb~ðŒÂúá7ƒW¸Æ~,)eFo,nI¬ˆ ú„×â_È|>—æâ'ߨ`KÊÆ“ìÎÐȲW~aCÒH¡{¤Ð;}aûÓ)B ͲáGœ˜4I¾Jàf£¢Van§ÿFÚ=’’«~„mZÓ?çÛ]žÞ6 éOуªVO霞‘nŽÏ|¼S(®#¿ÿÓ¹†fdúù{bÈòähñÖG´à³vå@ûžnO2êv1N^\´Ü¸^«bhGx—³7ä|ꚃµMêò¡¾°÷ë ‘¾Ò¡K©¼2;ð(oÿe¾¯>²vÏ9×ß'¯ÿ_Qñ}mOõ÷":²Ö$^©wñE´£ì FÄŽÛTã7H5c‹íp”@å¼±9ïÀŽôº´v#»ò,Õžôª@¡céõ}ºø^Cßè¤K3R[uá“\ÞªÚ‰ÿÊH©„S¿ˆÀI?êK÷¤:loh8¥Ž2ÃÅJ&¸ŽˆM].,XÄà ¬ÓH¼¹l™åNèê£!Òp‘wïo/ýXË !‘rNEá¬O4/sc;ô½) €Ê3’ /HÒÝüÊ”èáDJé¿%|°†ýbvC¦B-Ø’ÃÆ<ˆ…ea;øb…*d‘n¯¬Ú"Y†^‚ÁS¨ƒ«î˜D̾#™§º¨tøPíÃ_ dÍ©$ñPPßrÖ2¿ì:ÇïhJ•µx è¿)¥1h„ ËWæP,ˆÐï*cêÛ•Ð;­Âbøc«§ËD¿®,9çN1ë·æ¨™½BÁÈ-a[•ÝiÚ3Õ’ZQ«F,cg¯¢‡_hW’ßóo6ØÝÜê‡Í4·AÕšK¶ÍÛÉQE Ý¥÷‰,'ú¾* K”“>Þeºþk”­Šìòó)ùRú ÊÉÉ Y¡+…ZØã nO¦Èp'‘y‘„¡šÿ¨Å L#·Rúÿß?î ,FÐöß~æ²'–>0ÃË|§0‘ÿŽá1Ç’¦!“ÏÞT}-§K¿—ðSžåeÊÚ6)êÇ–æ‹íVëBIñð}"\»×"„^?S€ǹq¾wu9Ûß1Z¾ …²<ðo¾ò6ç"g[Uêå/>,HY Ú§ÖgÓ’£êˆoQ®©˜  2B7û´áÊšáT9 Æì#°Ø™œnŒ¢õ6/O(’Û9¨· ­ÆãÐW’P;¸ rq9¥Å¨yöƼ•üàÝØ£G¥±{Ã$sÿ¡¹Vq‚žæèúýv7saokå:s¶íÀøX'eeýg-®i5szg]¶…—µ.9¾·^#[CE)‹) `£U´Çuki6¥ w Ürµ‚›uïo(Þó îV{äbîdþÑp|…ÖŸDˆ¤"ûóT½älÖD4ð¹‰HªkÆ,&6c5›•ûê*äâ[J*t’c$°8Õ%ʸ[011ÿÞ¸Ò˜ûx-¬/º_§]ÃIY¼yéä×Ð2Ø‘H6ÉÚûö0`‡ÏÿEŸšd™òº Å-Ö,‘ˆÂÔfú#™€¨rƒÒ ]ôq_§Ö<§^Áæú6.œû’ž?#ÜízóÍߎëJt…Vÿ]µ"YéPw¬ßÕó~þ'[*±€æÕÙL‚-ñŸÌb)ºÝíµnM]{t‘âoóù;_F4“ë嚥pýàF@»HíâNFËç䆘g¾¸Òf;Lö2PÓ|ÉU§„‚·Lçß p0ú@HöC3~rΆôðI&èñ ßT®ûïi?Oü¯XÎôe>®š]µÿmÝ$Z‰'sVΰÿpQoÊ«áWåñUJE`´ŠÖäHFyÒÄzãf×ý¸yù­Ñ‰†Öi³û{"ÖÜFí¸M‰£€‡pÜprÈ‚ÖEéq|$RÜm4$6è­É¿±ú–¶ñ^O宪x’¥KM=‡ˆÔ”™K`‘òù¾ј¹ú€Vž‚v|A WsûN€6ØV }!ÚÞ(áé×qH)C›iV§FS9²˜$:k°êÄÅ“ Æ"œ0#x&KFÆ)ü¼¦]\@%fe¼Y²5«3 «bé¿>½¢ùÇp`™d’ª+Z’ÿ nɼ’…bÉÖï¥g9²¦ÿÆ×µõwLçùºÚ*˜Ì@E)?XiãHºŠzÒˆoÖ*9]Å£ç7r×7„ˆm5KØ÷Ëan«¬ª9Š.j&i£&úæ o±ÖÏîÔ%*B÷y_º{¾®Ðߟ Ô‹°áé"9W¦O½C40G ¼¹}nN iµAÈX©Ï…£wƒÃÀv®÷ÐÙ>¤ä…Ò§ Ôñ`8ËRlûpâ”O¤kæ.\¦¨ÜÖ^Æ~ôymAÙ–‚O§ù­Ê8µÇ‚o8=l#Ñ"ëöÝ+»ÎPä%ÁçÓˆx5x~‹ «4ƒäH4šÑA_‡ë¢IÂϞРgKÐ0n"¥‰í褖HØ(sô<\ø@ê4 Rÿžtüvƒ:™`ÃÙ¶!ÊÏ!Ì“[}’ùæÞú&ØØƒ¢t‘)_n»…ϦX†e#ar²gk©J¶ŽK?ò-áà‚™\.YR¥5è‚ ì®{=*×ATö¦}_èh6Àƒ–L™?u‹ß2ó|è[ÜŒ4„Jõ}EoººËVŽyT¥Jå^@ Žà,ß?‡S¬¿<8·Ôºd¹H(ÉÊäq½â•Ùêz¹èò^Ã6²Õk1÷ýƒ)#x•ÙE6ûi'\rœ±Ú¢=%:)&Ö‰•I¿›`NÙ.&ÇmI9ëhœ¶|…Èm] ×° Ê¿D‡e©$ÅUN`hYÂÄþ¥ hŸºÁ‰õ$€_gÉ÷´ fPêúÁPÜ6³ºGû8|îæ²XË©h϶Æþ\èA‹ -{ÃzKqE/Á”¿Õsªâƒ¬ ?•k —Óµîîf,Ì>âÖÐo*„°i’( WÊ/cŠKRmYKÏrߘú4ß©RáQHØÏÏ:™‡¯aFÝüo±ŸB:IíŒÁú±3[¾¤ÏI’¹Ð+$ùŒWГ㟀H…ÑúJétqöám¿¢t-qÖ~÷¼ˆ¢-ÉëÈ!V]…p2 ŽÜ‚šÿde7Ð~7æ<ÁÀ…¡fˆŸ0ðÊ %Ö`HXðÁ¸Êã вò¾¬BÎÓ´‡NL¹j\äLRt¹H\Øv®ÊVm"Šù±ö.ÜàñpñX¥äºjìë­ýë6Áݾá¢ìt–̆ÞÜÓ1é¾Ãnã1ÿˆ…”J–¸él5i0༩}É^_ÌN`Kz~”†(Õ‚À‰õRÊÔi?ýâk øPí|8É3ÜN‡ £Ùà²W †“ƒUוöÿ\–öÓºïÏ»º¸ï+%Gs:Œ¸…îL ¦Œ’IF=îqW­Ó#m.’!3Û@Ý’â|^-Ã=5¸+çà!GõW+â{^„®¬>Šªc© S ½ñÃIT…¨«06ºÃ7môÎ þL,‘œ[+ËD!%Ú¹UGŠÙk œ|J…*€g㳸5aÔjµè> 7 êªÀŸ§vUšû"ˆžQí3[‹*ÜzQ'g`Ô GãÅÄpƒìÐÆkWº¨e4°âý@péý`ª¦e¦— ô†­Â8ƒ7Kr­UJžœY*ª!NöB'gÅÙ™ãc–0Û3 ò¸·1@"Ïñü ‘´ÁPÉ[Æ2¢¥Ùô#ÊëÙZIö*IkJæ7òzÑj'?Lºý:=>{ÊÌØÐ/›þö4 nŠi“¯Ç?ê]_XŸ+Tþéi„;Kœ ¨›A½w©à™õ íÙKŸµmü;Qu ,çþ¢Ÿ¡šp÷ßóË\¹z æ ¾€›CWGŒP,È0C¡Þtäzº1• Ü\6S©ÚœrÝ’:|œâÑÊã ÷·õª‹Ô>Ô:Š(Xo×¥™çƒÌ#aE}GÐU¾8.ÈÉ +—¡|¾5Hòd1®sIáÒ¼Ýq¡œšx”˜£X­[ã†óFVöÂ’(®ìN±ax ØqXÝ%Yì¶Ð¥ÑðWR;à‰ ‹oÕêÄP-XÛéÆ% +ÄMvÔi{Ñ9áî8eÁúÑÆ8È;ú¬Je´Ùâ¦8µ7p†y0~›?›1¶Æßÿ‘×=,‡˜Xª›—Áz9Ò)ÒlR&ÕÆ½~Ëoa¨¬—ð ©æ{@Ç’¦Y ž&ÿ ÿ‹H|Îbu±&øÔ–_fO…ÚÓ6ç—Ò“+ð”È*Q©­˜l{ ›-3§D’‰s…£†~êÚç]ÅÙŠzÒæû ŠL\²p¨H+ F×ȾؚC=y¨›;kèÇ£©%ö•ˆkQlRCþ²!ð÷š‡ô¢Lšèñnmaq¦¯0ÃÙ#œÖhì½›±TôT½;}iòŠ7~AÊ<æÜ ~´^Hµø.¸Ûkkq1—P-áw¶ÈM»UÍ‘"…=ÙRÐ[Lìcjë ÕO #BìàJ²N¨@º Y,€ßì2_LÅI/{”ˆT zåR¥‚ìÝÿx4° PƒzòÙhšÜºAÑ熡ž¤ùuZv/ßµ¿NŸðÅWë½³2<.±sZ•DŠŽqòP#žJåi°´èþhR5:“kŸ¶žökSj¥â‘F¨ÁΪž0dž¤sÊ~u(¯†Ð2eeå’ƒ-šë£üL+‡Ac¾^3ðÓIœOë:6'õÒ½YÿVc;Ic/!ÕÜ&¤M_“O+Œ'—–k³½¨Ö†ÜÈ7-q«qöaÄ!§^O6_E¤`Ã?0¤ÈoÀÕjWüÛš`Ÿ»ÁjÀt»x*‚YÕ¥< H°izLÔyVË‹a|µ&žhÖX‰÷Æs‘®®Ó¶?<÷jZ?™ ²œ5=óõÕ‘?/¸W›rñ¼Šr‘w€néÈèŠ1ãï´TÑ"ùÍsÎÔ&4^6-¬‘|¿Ev°p#ÈïȽo¬©qµ†Ïuµ ë;Pþh¼ºã9cI õ1ŠšUøNösЇ\Xò&ƯG¼G D/Qi:HAzßvñÝÒNzÔALZf_”ûb°ŠhJ_’cØ*ÊoVÛ¤I®,\‘uh°À}Än[‹þ¢aÔ½ÛC[\ÞLÅëÕ)–¥St08¡p°£ïÝÄ{i_1UôóÄ‘~ÿGbÝÙ÷gèÿ{ ãxסÈsÜRW"篳>Ã-üCÄP=Ú•"L^Êçïz¡@fB¯ãU˜toæ&5×ÝÞr¨ÈíÅA¼9 ÷ÄÌ7ŠÙŒkƒ©ÎAopÇ{é¦~EÜ 6pxV,Ì·íñm3¢íAF3UuÓåu¤–jª"ñ¹šáÙ?“Tµ¯ÉèÉ$X×pK¼l‚ÙRxìvÖÇZ¦l¼½º/˜â(J ÇVÆ Y›µ8©¹]@œfÓåš²ÆHÕuÔ^Pâ’9ƒ²u|zùãU)o¦ 2„Ù,Ž h 0}Ô§¤ת.±-—%µ¼ºm'½ÿ@[QUdÎ1žËäÜäà]S]J÷™Ôm=TÎ4«äv‹¿ë)mt3QÔÍÃîÌ”Y÷Ãá͇§²!­ùԆ韾—kÞdä„lâð´÷m/x³oO)¼ºc[R‹wvkòS}4îg{UwV7—v¯uCgöÎz"m5gÁ²þ/ð<ãm¶a@©Æå¼pÙiÕDjØ÷Ø…g?g)l\¡k#(ܯ$rO;`;Ëg»olÊ7uêWâá[g4ˆyïa œ$2áþù^À=ƒìº6·”«Q¿ yØ0_sÀŽ‹š!Á0†2NÝá:í2%"ÿ™gâàì<øt"AÈw£}®ËrhåÝ¡ÀÿDŽmxþÏN§dû!ÅNœva¦©Ò«9¹àŸãÒÔäØ3uÓ4çåäìÒH´C=.IÔTbVY}‰r:-Ù'23¿)ÞШ;s¾Pù‚kóK9×>!,Œ4v½!{|¬Bå :É×­±Xöx5ZkkÆÕe9”½óQZH +Ì©/·vƱú0R•ãëÍ}f2²Tì¾J¸#⬒9ý¿îÒoþùÝÀ)U‘þÎõq3ÓÿÌoQö­<4Ë0)&V«ð6ø¾|eÃ0ìqiQÀ3%Éââõˆèeȉ6‚,Eç—Ec+ö£]ðÚÎãà+À iÊçH²ÖÇ y¬q˜¶\ÅLKŒ¯Ó7û7"üm™H–:J"oe—6 ’ñŽð°œæÂ]¤”@³dgkÕHZ>0ç-€hËy%QÓM­õßa§ØÃ·.øñÈx¬(§Ãä~j²Vƒ½ÒTj"Ü;¢Ýùo²Vûšœl±G¬E—JæI¹R¦=#¿(g„²¸”/`ʯ}º<ÿ~"¢è圴 g+¯ƒ•ÿ´Ý~«ˆåæeµÁ_Â+$_Ó½M]úäb ߢ¸=H€7‰É«h_–€ÖÞ«žJ¡(‘SòÎô$îݩߓ´ë#ʲ…³üĨýˆGssÒzÓ¤6°h‘ìŦ¹.{rqŒ¥;׋{&™SNõÚç0r_£f SÓÎßà'¹ü†åhm€S›CÅ ¹vÌIâfÈüʱ)¹n»Ž|v±W´ˆÓ¼ÚuCåÙûq¦ÎPº_.ÐqÑ«}ÝÑ?jzôQæ7¤[W*ÖàÈq‡ýÍ­z¡ä¸–$¢¹1X›OÈPBð1*ͤ×qxÞã *DL]F[?ñîÁæÌpפjüK÷s}È.ZbÔ\Ó`ªÎ œ×Rß©„sj¶dZO®cû _&‹—^4ŸA¾ÒBý]ËÈìÔïªHà-¨7(³qE»›·{øëƒ`!@%Zu6±á `3Âvøè`;J÷\ZQ‰ÈaƒM–ì|/0søâ d¸èè·#òsR-c÷Y•u¶V'ûhÓ ‡”[R‹ÊÜK3x%¸.SY[\¦ç¦ÞRÿÃ$Š“EŽÞVüDÿÐè9ä>x˜`…†}ŠAãyõÒÇÍ3)UúüÛg®“¸#™ê#WUÖï IÐ`ÅãòªƒUàœöÕ¡òr Ùvï@ÂÕœ¼ìâ­LUÛ€,ŽÝ ä•ü¼¿µŸïŽMž•R€Qf”Ï£1ºâ6R%Gзç]C8´(½P ÇØD¶Ó`ý¢ç‘¬RBe­õÖ ±•€ §Þh¢ô“Wh‰e^×Õ–ôšš¹1N‚•l–«G­ë”cØ´×o˜‰íÀ85úã@KU•"Z †èÄESŒžˬf£PµÚ6cƸ—p×ױͽÐh((,Y/x}3ªÜ]øäÓuŸBÚ…U˜äÛŠ ~î1@¤®‹ì~$ ^Ø=zîC„Ñ7Ã Ä Rý•uñ«ÿÿéüy¦¦ÁCÚýÇ¥*@ |`#œc ï1k¾óT³9w5‘â?xý_Í\Í/¹éßaM8,J":Ñþ3í»ë+°ÈÄq{¸¬îîâÜ ­X@èòw”þÓ›=ÑøvÞ7³”)Ã@-0Œ^ ¨;EÉ‘iè;3¶µŽ/ÎÆrü¼¤Iû±Vº Ødç:£3[”Ü’’‡ÌZãJ^³cÐ<µBBÄãH“Û½jŽ{1?¸¨M¯‡JH{ÝzöÉ"ÆíÓQÒZh É—ƒ>µËt´Êµ,Ô#vŒ¨èF è°cÏÃPPBÆz“µm@Šb{»¦­^ݯgí·á2Z_!Ý¡”ÖÍÌ$bëå°œÇé§kK\;íª-î†DÎH¬kSmWL+g•ñâ­páÓ ‚MvÕÝ!¯š•ûdò×› oΧŸQº”tÎÌèBsgø8½Ûèÿ üQYT-¿ŠúéTàü÷çÝ˽sævÒ~™æsÏ(ºÛÌWÓ6g·wßøƒ0¯d ‰Ï¿Évj!º.¨Ù`ÚzÛ7«~z±eµo06Žôƒu3!ìé…ŸQ°+ñCÏšn½¶®ì…vΰá4 ºþ¨ºoøˆìzçf.ÍŠšdkŒ’Kåé5'æløœ’pµ$ãŠ@ä¿*{r=:pVP‹‹Jo®qOsƒÙ‡G% õ‚?ÎÞÊTcȽâK JÃÇ_Æœ–R"£(Œ}»4“‘¸û¾óž1Þní£;$ÿxw5î…S]xžù Ÿ>äkæ%¾Ê+HÌŒR0­Á œ‚Žê¼¯íâÒÍöê^¯ôôGáWÙ Ì+#¶®pêI&ŒÄoÕËwSâssªÛû„sv#Uê‚o–šéÕküÃC®GöÙç&Ø/XKº¬™+Ç0fÖë5ßr7¯Ó+€ƒ…cvƒ1ÿ"Ó|Ö Ž!êóše@{3 f9ÊQ׺ÁõXþÅ»¡ûÃi×~™ Ò›ÊZ£{Ò󜵤ù&¾u¹qÁ–ý •H%4YÚ’”Q%¤Úaõ,*ã7®|HB_ׇxG?ãN¡›, ‘Æbp"Ø®KîñlíQÖ&ÕÒg‰¶VªPÜøQÇRþ¡š”fho¢Ø… ¼âVΡ þ÷C/K†¼Ÿ?íqo¥í}…-C¶¿ VÇ·û:+gëðÀ°Kˆ*a?W&x?ëóQt1E .÷3~‹hâu¨¤—¯ŽPÂäÜþìѤ¹*ڠϞŠZdÇÃÇ4¤€“Ђ1D€ì‰£*ñÃÕ. E ¯†Ãìã-+Zƒ8Ë‘¾{tký+„Jþ¹ëQ¯(®ú¬lþJ‡Žêo-óˆÐŠy¤¿g7@ŸtòË!vȾp©¦yðÈE@Ì8Áº#é0 ܱdÝ’ç˜@¢2ùcjlÉ¥T%rs¿ÔFÌ®¾ÛosæíL] õTÿ¨žÂ§˜˜XÕDfèì(• Ð™× Œ¤Km¸§•œq~:üI8ã«ù ¡;wîÓ™x†^™':˜:Wèçk²è +±8æôPFƒÄûÔN©´L¾0Œ¸$ø÷œ˜ )Ó>ŠäÞùF‡ìÔP6=Fg»ªbZa"R±úzŠõô¼UÖñ@ù…ÆútpþðÜ x÷oÛT_¨2â{€*lm®Â+†ù\ºìa ‰Òü¯™ÿß­p!f4»6&…ïRÑ9/wVÞÔBkÔ™þƒ@µ€ëõ÷oì¹¼{š8€]¤_—KëüÞ/9Ç{R×ýŠ?D_ü’¯òÙ‡Þö=`àÙ‘®¶ùÑóâ¹SÖd%¹¶LÏjóÕØÁÌ×r:b,òãXµ;ã¾Þ›rœPŽH k>ˆJfh§çDÁcÓÕí{ŠÐº:&û$†wb~™•.SæØ¥GÀL®‚ˆ¨HC쩺IŸÒ ¿¼¾Ò®ÐC‚$ô>Õy=W:dº1 ûÈq[kÛ•b[nî>ã˜Ãz)08»8pr N ÌvÝ\‡à&‰3:m´ÚDÞ»'½—{´±Q˜î?í_Dv;ÄpsòR Aãâ[{, /€™A ¥ƒÞ|E¨¬Š¬>µD2–är‰C=É&U\w—ûêõÌÎbÍš»,!Ó¿ l+YËŠÙÍÎdb—{tžÌú=)°—E#í2Mî b3ëX™å~Pì2Û›R£PƒŠ/Kö♤üF dežÐfqß…ˆs-“7U5$Óé¸bZv]ßâʹ¨ÚÜ!¨iç:¥“€˜§YØoþ—<ö¸:*“¹²—“Ùmc›¦ØEÆb±/¦€yɾðÙÊøAâ\fŸ›ëº3_â¢DÁŽÿXGáðìôÕóÍl ëËbýP!Ã'ÀÔW¦p3ÇŸêVå)o躜à]ï£T "F£Ú±’%7îÊH¨ºFñ~ÑMO0l~R‰ËדÓìÊòrÞ€·ÜåÚ[ÍcØR+R.¥§çL÷NŸÛÛbuoÊZ.‹Ô»ÂS%³©€»#ó)R/ÜïGF€¤ûé·ú8uuB€©œv+“T¥^.¸Ë: ßw¥:þ¿³“†{·:j±¬r¶qöÐ\I²£½áù}yzf,á¹ öüõ?eQ¥ºõ™ª±’‹´OX>l,Äú´€5nž¹#^_‚K1ÔÎÈ×7#gº+H(Vímt´WYÀ6’áoóWÕ]‚ 4ÀÕsÆi©6¦èM?5)Ìi”;z°MšÞ‚³ÅKÜáF·ÈaB>ޱƒ‡Ÿ³KP 8pægÕEóñà_öÆ¢‘ö—íB@α,ËÄŠÜÍ FaÝnµ™u»^å ðC¯CÒ„r×\C³kjÛ¡¬PwòÊ\ÍgE«àTŽñ†ÅªH!š­f7T,çÙ‡³¹ ŒÍÕxÑ¥þ|ÎYÄkŒ¶ÚAºÒ.fNš+ùqÀ€é·8‹¶ô¿út¾M°LS¡.iÇA<5ƽR;¢¹!ØbÅ5¸ç¾=R¬–bÒ,Ò°ÐÈ ¿îaÃ]u§ñ[àÆ½ Ñéô½{G­„Ô)ÇÓüÌEÿÇ‹›)î œèœf¿XŸŠžL³ÒëëèŒ^NÿC¾ÓW¸×„L.yjŸà¨kþCÔ†ö}\§ÊaRµ´=¨µÔ)è±]¾1òræd:> ƒZã&Y7AëëBœÈûc‚×I¨Jþ£ñΚôuuãaÍËh5~ìŸÝÆ÷È,êïÔò#L¯K6]ºibØDެˆÍÞŠ2A 'ûÇž":FáâWÅ 8Ÿ5…¹Sù¦¥Œ<\–䱨ËlQ74"Mym¨¨ï•$i@€_0ŠâQ¡ü_ª ñ”#ÏUÂêv\cY£|¤€k†YbÇ:àÖ¦E**½†Ú¹—ºrÝ»Ÿ­¤Iìx[ñ“>†ÍzókØ)÷Þø6¿¬!q»˜ofÏR²®BbÚÝ{Õ+ƒ×ÿ7 |j¸IärÑ FHôÞò2æÎ?ú^йãvPuù–×JBEG\äTó…R`µ¹%\?QÜJA½5 «WV månµÇš<˜òZiDˆÄI\´Â?Ãy°nïúv¤'¨ƒà¶¹¦Ü%æHl'§Ž¾Ê¥y:U·TüÑ3F#®•Œœ4õ¬ÓiHÆ*6*¬GºcG= òóé%êO,ðÊ*~ŸÿÅBy›÷LÐ’ËŽ2ÐQp×Ú2^˜£»!qðw˜õú¬%ökz;­A*‘òÀ¼§[qœÙlRY,µ>j¥8üáµÜ{1=9Œûë—”-Ùµsš§èµšû½e.¯è®6s»b W¦@JÊ'#PX¡¾‘•¾ ‚?’«z|©s²vÕg{4jð|M¿›3{ó{ÍÐ+$5±\v}¢œTÛ`ôÉûÄôœ]› ÁìA³åÑIpÖùRÌèaè|;p÷ì%…4 ßLu¬‰¨î?U(¿Ä¥¶$ö°ø4[ŠÏ>;Ĭ8hÈk™—R•|Ë4rTz+¦~A©ÊjýÓ(zÅ »­J6’®v´#.'>ê‘&èû?³Ø]ç•ÅÒ%5v GÆè‚&¥ò ÈÌ+ñ˜j„pf;ja¨Jž³!OòÁÀÅðu?V¶/ NÇk°.HFË6Më*õ“îGäü«þO~4~à†÷æ.Ëž›Uz¦Ôæ>}Dið–Î÷R=8_'õÀžðo¬[Ià[ÄR¶»¯"ÞKS }˜oe\•zJK Í\ò¢F¤¦“ë?k*}º¡ŒËûH£T£“6óv²çˆ IpÑ¿hÊmRM«Ë«dü CºA@4sÉÃ|Ǭ–á¢ëJ½F‘Qög"Ÿ0Î5”s϶øîB8.|ÈIE‘œKmÕÌ›I8 öäLž—Úo#M¹jØœîwSÊ=£òɤD7WÔØÙ¨ õ!e7ñQ¢pXQ÷vÞäfE‹½”–ÕTÉ ©Ô*ohPÁKÛ,ŸéІÒ0±Šµ²½ÀiÔm ~¡;iË:­]hH:TN¨ Üj“–ëþ:ǧ¼×¢ÀÁ5my [YK螤îî®+Èáyà"x»5º(GÛ‰ø¬Å‚50ø\"×1v úJdƒaÖÝ1áç¬?ðZ’£Ÿ;Mh`ø·Gœl¸lCÅõ¦X¡öÏwYcŽ)ˆ¿¢< µà]ËC! =åd×VÝñ¡|ñZ•n<€N;!Íò#þh¶‰'8œ]25Ü>a©Èïöæ'ºx¹§ƒ˜¼6¦ò,Á‡OÉ$Ç.-Œ3k²*õÊ6Uè¤SÙœ/ìó¥yÔÄKMûQz¢^žwsœpH3ÆÅÖø+6rRJ°Øåß)(9ݱ³S·–tc×pÑ£§g¨¼·}ç W®ƒk¸ VY!ýÞÊÎåëß­Åx2T#¹g­£è;7×ì°l¨ÀN¥œYþm9H5´+/³ÅA„JŸC»{nPÑù4*¾\¾õÏté¾ç!e¥e¿+¦•hFž¨ñi%¯B >$…)ל:F#Vý¬ý•VQ4ÈdÃZÓ¾õe+­¡È?3ð†ßú‘Bz»«`dÆÔ Þ˜NbL¾(ØM‡¹Š$•Ò·ißRJK{Y˜ês›«…ÆõÌ]M-Ym߈q–t®dò‡!ÐꜲ;Ö|+¨ +òª# ²-h?c+ˆðª®®ó|Ï›©§°¦¢½~Ü/¦j£ž"à5)»j$®=²¹ÊÖNQ¹AꀠqmÓIÕ….Vsu®D½@ô×WË. ÅÓ…ÿ3®‘#œÿZ%zœ4k£)5yú ÿ-â—Ä\/UQÞÍ' “ˆŸò݇‘1†.% ôá0rF:®ñÒ>šv.?%(ųQa·»†Çeµ!×cóOýf:N¢*™/ ës‹>®¬ö2 UlTo[’½Ñ"«çª›ÒÐCGMa[¨¯#ÞÈüÒ®ph½ÇÑj;ªãrMp-ËRÎCñ^Òqçñp|x{É 4VüñUüͦ¯Â€>jÞ¾B«zßIŽD‰r*¦p y˜Óß’>ˆá=ú΂•2Jw*kðhàe—¿QYüOú®úH\B`C$ ¡LökN¿á×Õá’Y0¥#.޾ŽÉ.ÅÉ¿u_Fÿ¢JâÑTxÂ@^iªÜ›"%M9[»#kW*¯_‚"ÝrŽ=u¿š®Ä"s²ÄíÕÏ{–r $ O0€e÷7§®Vfq¦€‰ö mŸÛ<᜿ØÛ}Ü:ãº0+ÇF…ú$éí)(úJ‘‘=h²4•_t¥3²‚Šù ¥zÃÞKD¯µòЂL|"¾¬ªùWª€»F.r”JưèM­ÄÒò÷ç,$ ¦ >¤#÷ìfnãܚϋ$aƒVp>t+Ÿi2€Xý›þErsû›P>"‘ d3¡.¯ª·VÄì=ŠD÷°^‰Œ°"Rq»f5üuõ†×úáÕ‚<f+ž”ä»#u°dC•þ-§¸Ù=7Å©èVOúd ”ôj”ɇËûØbû/nG_õ †&x£Æ/_è!?JXòžY§_jÒ>³K‰¡ö”€86ÚìúŠf Ø€" ß ¸÷tæ5þÈøB^8…Ï8áºþSÆz¶Ž´ä(äwnW‚9~&ÚŠÑãªWøíõl¸ˆæ]jÎiMgP +‚%ÇîÚ‘Ž°:elðòP¥>¼’z*TCsÏôfÍÇmìÏ{ôÇ®/À³tsóå½X=Ž%@¢âØELéL!`|ð*qÊCæ&Ÿè¨â®¬“ÒÀ; ”|±5(Å«žî– ¬nHf½ &-ø‰¤·¬óžôVÞâ+¬žÕS§ïŠ×¹Sç.ýÁòñ8ò{€3ïìJúMbµçüq~G¢2‘è fž®æ±Úô¶‹é ÄBþånæ=s|®¾¨›oéB²‚ä¾åÁ¦NÙÕv–Ð_x2ÑÎZ”$ÜeËö\GÌÁ…4_Ó`íÕÃ( ÉjŒnU Ûe7z!0·;’F˜SÑõë¹càú®×wrRWÚ}ÝúšùÎ,ˆ"cûƒ~Ú¶wbÿœ¨êò)o™ ÓX¹ÄŸŸ§,YTÙ}ô< y¡uP-‹NŠ µìÙÑÆ´š2Œˆ €= !ìNcÈ]=¹æM˜‘)Æ*tö7Êl!ù›ùòŒÇäè5)'bGÒv¹qr&›õCPµ !^xë¶וRl©®º7KìÌ&¤ï¹¤‘ÂBl……V†D—Ê Vã±Ò¾Z«˜3Nƒ?Y ,ß,šÜþÏò®ÿ)xŠªð`©žíBªXòpŠó4ú‘Þ…dÉs7ºxŒóZ~ÙÁ$Ì›”˜Ènñäù[LVðÌJ%ôgâ;ðAÀŸ î§«­ž &çŠÇHXÿ6ò,àS   Js}Š¿"ß1´ÀqìÖÚ—ðÎÇ—«¬I8=•;@GJㆪ?.z©Ü5þf2㪣 kÃÔñ Ïñ‹G¿ ?73'aKºO³.Õ&Ž=0™¬j{@ß[. Y4,kÍù_b¸19_kþU/uŒ·µž ãøûOv\œqÔ¡ÅÍ}ŠÏßlؽœ†¢Ã6ÎŽ•×óáßÌó £6œ @mƒVDB#á#‡4€Á°RØpWEØ5S  nb k”G‡µÀ-1‡­€’Ï:%&"UYñ»7+n\‚Œ¶öÙð¸)0…Þ̘¿Ú&Ìqê`¶O+ïÞ€mD[Ô¾ÛOÔ˜º?mù"©¨ZêïÞ”˵–BY†ßlâ£$ž«™Âé-êºØqÜ.Ïí¡´O“£Š[ˆžlÁú|1—IžfÚj0 ùî —.›éCìà•&áNäÄ|-rW׎ýhe&âv·t»Qåvµv¾™ðádr¶üÅE[;ýd&þ~FV”F htL;“U²nè€ÀŽ…Ð¥sk¼¯>ã¢XøöÁ¦¦|fÉâZ'*C"mútsè&…-:r€U¹ÏCÉo·áKòèÀéÌÒåðôUi¡û Ë£õ”`¼h ü¥ˆq2a&LLîw´ô'qËÒò K‚7DòÏÎ×Ïæg ç^W»!â|dÅ÷ªñ¾]Ð Z'Í8áÔ‘¥Òy<2‚wÇ&áiÍP;Ê|4äq–îy í1I5OÑêAXî±€ñr¸÷®‰i`¯nI$ÀÑ$ad{'PbqƒÃÛŸëÁšBùC(…ƒ9vv² e‘³ç®"pø>vY5—”sÔì—Ï%Uõv°X¾ƒ-Ë€ûÕ±MY²º¯fc^Ãôô„Ö?˜N…hÍevæÌ¾BÒ¦îj÷@_†lÙl~ÜÑÝ…fIñ[ ­¼(_±ÕãD·V=Ž‘ K´¥j|=õrÜi& ÊTƒa_ äËö›%9ÜêÕ^—BËcIÜ“.f&y>ôŶ,OP’†è¨>Ÿ@Ì,Ql„ÕAÁÏì-š}†:ó¹dÑ=Q)7ìä4=kzǹ2Ý6÷åê“ Ñ®”|aä' CGNÒß']%´ñr¿@xk¥4p !sŒ|ÒÐŽ.TÌUˆœwSÈÃ\Î¥LPL¤”*owªíZÈ]…—ÐôJ™GÚ0Û ¼gq¬“"L‰ËY™5ˆV"âm°¿‹ýÉ¡oS*ž“÷¼LaŠéçŒñ¼0~ŎѾ]Ê]š+r6üoi ø?p¤„£'wËÌž3‹¾ç >p&¶|8WƒNÆ·Ô8]‰K¾Ð$ÍE4PÄ)Ô½†ë–„æn¢-‚kÓ¦,þQ®ü‚ª žµ2çךô6t\¼nCˆØg`^šïm§êÊÀú¾lì®?•PiÕt¡Y3|ð}*yÀ§Ü;¨mð¸&áû¼íᆻ¬Úvþ;ÓIãËÛ“ô“~À—~ cmúVEðZýÑÛm4W›1:ÜÜWE⎡ – uÙg]8£ø,†&ÍÊ'ua©Ú¬ýÔg-e"ÑÆpBöL©ÂÃ2Ä®ç²Py€TEvˆˆ <þ'=#QoÎåÔrcÄF:©f·$@èóËkÇõiÙt8Ã]q<ú ºálŸÁˆ¦°T± ò0Näë uOfzÆ@Ú¸m!~hu,¸ƒäÊ»ƒ²ó¶‡þôT®æÀ20n„9Ŷ‹®Þ¦'Re Ñq’SoÖ^‚È=Ú LràaåYà¸ubu/M\ŠZtâÒ]¸‚§•-öœGÄëÌ9ñI(ÑnC¤Ù±À²ˆ© à–9•E[X´{‹Û OVDskþÏ“Š§¥ùïÉF;¾ÐÔ:FW.¡·õéßnNIáÂz%KA $_AE¯)ÿ¶QÛ™JޤCÒ/RðSúØ©õ¡MßÝÏÌÂþ˜ í²O³ªS-„¹û4G»æK÷…¯9% ¸¼nˆÏoòØáe¯æþ› Š gµ«ÖÎ7o;ßQ~G™Ÿ}`ûøo@:ßגתúrœäÐ+-ƒVñ 3DæFüC[ˆïÞë'Ëjìp}’ütH#ÅT,Ê T¹zŽ\ùcvx`Ö2Ṟï)À1ŽáÉÑòQ4dô@õ!n4œ¿oª¥;4æ>êKG-5&–‘g C•‡¾†!|¯dZ1Av·*8T¤5ˆEv]ÉÌ7Ad¬eËQ·Ž^ í -ò¡žEôGÊ-#w —æÚ&Þ°ói˜Ò7¶…³ ŠÄÆÛ0êWÑãg½­e[9:ŸÁV…ÍvI½;ÍxÑUÓ{n¶<@koxgàóz`¥›YZ¦g£H¾t)71s‘E‰)¸±‹ ™dìüB ô ¡n 6Ë RÍ–ºÏÛ‚[ ÅÓ_Ö7„÷*ä8(*j·óÄ€ô_Ì\3¬Ñb‰oùPt«ðÒœ„¶ÏÀM^Ï…åÛ×=†ñܘÛfìsIÿóŸIÔß!’Kú ÛË(“ކ/ïzFŽCçb7Ôsûy  ²¡6È“ì esñûN8ëó–ñÒ"§#ŽÞ0‹%!Ý/ª®i'‰¾éÿ³.£xjzébîS#”78»´èÖ… i#íI•ú²=‘Pg X£†:8ràƒ¥!€~’]y?ÉTŠÃ'ÐuÉó$ß&1þL#¿qTv±åH_@>)ë×/dH²±c¢ÊjLnÓw£ ÄZR‹l šºÈÔ½ Z}»E*Â[‹b¸ãéE¢'-…ï Ø:M…·8´¤º-oaª,³b Þ ‹¥ìýº¯Ó!¦j¤Œ}ˆK¯™&'ƒ^Þ2tóîÿ#H–ÕʵÅ`Gü’v9ÇRÔ65‘QlcPF”¹Ór.¶ýÏÀ]ÊU`Â{åq {xô•Âè1Þk¹qå^„ÓfÕ#ÈoIä;¸OïÑ È™Y6ü1N5í÷‡_œ •“͆=ÇÙÙ¯ CÝz6Å‘ÜÊŒˆÎ%içë¸N¤%  ™(ÌÄΣÂKÝwüHà@£K€¶ò‚¤öÌ%y1GîÓ öá œA÷Žè XÆHZ:kîv<_É Õñ?—o°eO¯ùÜvþܳ–KÖi±äÛ[ôËœ^9" O½å‰Bœ‘"ƺ SV`Ý.ïÝÕœ}<|-\2Pê«Ñ÷úB4@ó{Ö°zl%HÉS${te|l„в3!Ä%gÎ~ «,,hØÕüE§yIê©2C/P Ã+šGþ2õûY0ROˆLj}å?‹IÄÿTir1«(~„cÕêè ¶#)ÔÛ&‹LfIQ€šn±{Ï v·@ Ø©‹ÃiiÒUÑ¥èKëî ‰¨›sçkKí(Ǩ4Z†•ô[Ãr‚Oº$þ&N<®#©¥B¤;)bl>Ðúš”G[ÍèW~r6ž« M@EŸ—\çJð@×BØ™%7m Hq_œB¿xìÚY¦m–²·µë½qØï!ŒÎ( ßB^ç=… Ù4GîØÅ¤ño*h‹…­„(5½Mõá*)çkª‚úÖáË!2„%K„¦m`HàiD³ æQ¶¶‚LçN=KkSNf¸;‹¸xR#{>_' w¸}4qˆü­g5çFc‘µŠ” R‚“ÿ,¬¾°r¨C]=­_üù78¹î;ÛƒrÑì®Ö¿É(&—¥+w¨‚ùÓÊ>}3+žˆ6æñD½“ÖÌ·I&b⃧D—N&,¼l®æOlÙXö–oacÛ€€ò†5"¬Ðf>²ypæ¯Û‹`SOoÙY-QÏ”à*O ¦ '£ƒ¦ã‹1üMš¢?»ñÕÕMxÚçâu‚¤k=¾/êK”‹rh¸<˜Ú­Ê›Æ"TzåüŽ}yç/;»UdX%™ï‡ €1 De”‡µ«-è^Ýß¡ÇxAçs¦1`ºdHI¨ö0 3õrcLÿX?ˆ7´/çå3³Bôh¦¥ìüGÃúJd‰¿ëEyãï›=M_5 Ü„‡¦5}l¥YÿÓ /Z,§ä{™_â[Qm ä>L®È¾™Po·atí@é1_ìFãKGSB£úf´Þ¥ .q F8˜‹€C‚ž cPc €M[-E²„¡ÍÕöãíuÄlÅׯ ±¿Óƒ0ãöyΊaljj0{yóZpÞwÌzµžÆºhïÙi$góòðí)[¸böâ€ëJ25ùW²êÐù@·ÇØÖr‘È°ð‚ˆ—‘²åä-81I¬Ù*„º áÐÍùŽ®ÁÑÉ0Z¦;Ùœo ñS[RM*MÝCŸÌ¢3Äš×\¾– 'Ðiv%.F¥ ò LnŒ‘œ“LÿºúãRœ$àÀé Ô#%ßý»@Å (ÿK]DºŒ‚Cfœ8@m°Ï™Ã»þâ‹àc_…3šìZ` 45˜YûÒ%T±¥¾‹4}À˜>VBV&éÞ#™¦ÐÕ ­œ+…Ë_ýÀÛ÷à( *wÈãk"ÙC…K|%œöÜ”à“Æ°ûËVEUHKtLz€} :ÁQF—§+õñþþº½ž¸ìãŽTÒKúù^²tʆ#”,|.8µ¡ªŠ™e_†<:âj&G5öÌïêÁ7[ÉzЗýºÀ¥vq^0›]åç{ÎϺj>p|¨•Â1{•ŽŸPçkBÓÒ<3ƒ¼M15ŒíuŸÅQÑki€–-ùl2ƒD†rûÕ+°5 ÑFâÚÅQalÑ>n ¶ôLe q,Y1ƒOYhbç#×]müݤèßýæ¶<%¥·T¢#ø”@gÄ…ƒmÑ"²0¶/Órð)hŒê¦*òä›ÂTîÞ‹Ò« ïm€øølíè=9×àXIßPFãŽTÑß%´@׿X¥¡ì<îš"ë¶#[>ãÊrš‹[‹Eb¼C^8~R.’ë†T¶€Ùfeê¾~Tj·3Ü[6Û8­ ñCb+˜?Ùc^)£“_¸a7?ç¨Àz¿Óšcšö4w»Ô‚"/B1ÅsùráÔ~¸ÚÁ-<;(Jï$Õ_és+þQÙ˜ê/Õmj陥,† ÈqØñÚ:ëØìFÌ·…ËfÌÙóp´ ¶©û:Å‚o|q&ÞëSÓJ©%f 1œƒ$­©"ÚÔ(ƒ¨7HˆÓà'5Ü9A²ï¥Å&¡·3-!æ”ÝÉ3Ïc>iMý‚Û4ôϸùXkÜÊÑ5}Á(å «Í’ì—A°eš~&ˆxû2®ü®äâæÎÐà™Œ¸™ü@·ç #`pÌõ?­ù;ÐAž6K¯ŠÌ”JJàü†`f3( à‘SNé«óIµ½1„:e‡¾Ò¤@5 çuæ¼4JL¬LÚ\TVSNîæ“@Ð8Z@ÎxLpûUàAe¸ÄÓ”>/ß°®üòG.ÓŠZмüºÑdC0« ¸¹ñ‰El'õ[OOö­-T²ó¡¾­žÊ¢2’Ð%аNŽyÉ2ÎDmº!Ødþ5ûéRÉ™å0vtŸ¬Ç^PQP”x§ê„þ¸aZÚ…F˜AÒ¢S>™70Ö.Ä+y-;ªª¿ŽgbîâW‰´Då½ö¥˜-÷#:©8ºWÆ3‹.ÙwåPŠŸ’]¤‘äÅ>j°žoJT¼o1qÈøO¹qxB#Í’óŒ³D©ræ&9ŒªŸ¯Un éÒáä RÎeAZ—÷˜ÅB{ÄèñêjSÃävgãù®qFŽŸÉ³võd’ë~’I–oK‰sšÄ–€òþÅ=+½ªqß*(¯äò¯s:ÝÌÊòUì3Ñ™ïÞÒ²2» Î#Ñ]ñà”øV‘3¤ï¹f ‘}š9cc‰•º-’(BÛz^Ñľÿc&F¼)/õ¸P]%ÞÀ1ˆ5ô ½òȲ'úGca08 *W¶œÉå 5SˆÚÃpå¿HƒðË0•BlþW!žƒ® þ‡´ïˆ"HÉßæMIY¹¿Ψªà¡l«¿e0ãúÀa½è9÷€â»ÆÔ>w®D°$íÜZ&÷¢®÷yPø˜ê&ÞmXtø£ÿÛN}, Úkf3ƒ×2̹mcº‰#IGüq©eX ³‡gœ’6'ŸŽäbQºÛ_HŸ¼t¥׳ñãÀ°’ýÑmÌ“î¤æá.±Z"'„`Ãß7¿üüOöº[Ûî—¨˜sht©ëßu`t¹¼p>ä{ K†Û)~Kp8eon¬§``Éâêe®FÃNê Ë¡äli(ý·Mž±O^ŒÕëRWC¹èî¡æ4¥ÅµðË<€×r„a·Òá]w}öjL²¥ÕXjdLÊQ+òÂJeÿðø,åéÒ¬øxÔåÈÂC¨è мÍcmoAl-¿›¬*þõh+ lÞ\Ê#ê&vèƒ6rÞåšvÿĉäõѪ0µ]xÜzlÛ¬iÝC£À¥x]ˆÕiâˆÏ˜§?<Ñ¡ G´üåñ±OŠ…ÈÖóÖ‡U¸Ù÷¥ZHºý=¿¦¯$&›¦6U6³¾¿5òÂNlyv/WÉnY wDÚÐ8“p à«Ô¬ÜÔ’1RZ™q‘x$àíkÊR×Á[³áCðm²£Î ˼´Óîý¬Tv»¢Z ÕüCð œÝÿÄ\@ke0€R:÷ÕLB§ÝY©‹óÅó"=.ˆBŽOƒ1¥æèŠ —j¾°ËÖQ",d¨à|ùæŽCycS[øÙt_ÂEð—¨AG´ªV4Â\¹ƒ/}úúõÂÜ>ó  ,ˤ¿ô·TÁ k¸š–Ô.Û@ò–¦9ÉÖYô]‰ ¡Ãp…v¾báYEáJÕå)¨ƒ؇lY”ÿÀî{fÞÎQtšÝvÕ¡¨ ø.U© vð6wmyäøüPø/7hgQÔzðrAždäþì¦Õû+»ÉZ­ëQÚ/èOlì'ÁšjªI¯¼ _ÐÒØ…£BDB“âdy†•ƒ9­ e§ë`€Kd¶N WŸ”‰?0^ipË(iXsñZáRþ™I¿bC$T@ÜÞ¶QÕ¸ a!mŒ³ uýÕÆ¼' ¨©¦®Uï$4WŠüu2ØÃb4 G繨(ͪ«¸3 sno `Õ2# Ï2ßüwšuØ-ýÉ4ýŸ¯N1»èÙìEíªÏ˜Õ¬R&å3ÊàÈ¿«²‰‘¤iD­5“¤.ÓýÆù§Þº\C^T“NîÐôÚÉÜ8BÁ‡bª•Õ¼4/¡âÇÎÒFP ¤=¡#©£¿+Í6|mÞ}M‚¡¢‡dÄZ0çDÎ? kËT¢¯÷‹Aý"V†›Z¶í`”»Odl¹Ú$nú+†°M°vŠyÅSHjèræ¬J}rÒW ,«ƒÄLoPÿŒúuM4%™œ‚¢’ïÄL<íÁ¸ÙóÔsûuS§™¬‰»Š—j:‹îãÞ(])“ÆÙ\¨.‚NS–ìU7é/³”´åþ›õ–êÁbÙG¶“¤÷eøæñÈx¿† 2—øô‘’y9çÆj“R}6 …!'íÛˆŒ–ÕØ~÷šôÕòÌC‰y!qhÖ9äMé©¥®"Õ—¼]½)z4¸^[* Tnj,¨à:N‹wÆ|=ái9S ½¦5[”‹¬•˜j¢–Œ_@n´(˜Û>ß.Òš¡Šh¸«Þ¡  <]ŠÍaègܼòÁî©_ð"š¢±ìuc¨âÏ„û½’›-7}FÊf÷;Sûý¿ƒ®õÜLgÍ¢µõ)þãWˆ{Ph¨± —à‰.‹´ÁÀª>‚ûœÎx¬6›Ë¢%‡f³y8”RßB]µÒê·~õÙáݹ«öüBIHòI“ÙÍc«mY}:¯×*vP ŠžË/h…-ñP«#[æp²!øS“urt79ß±Ùì-ˆ­ôfXK’À-;ÐàQÜGÙdöÑ#š’Ü„;þ”¨—lgÍY`dÖn’¡n˜÷GŒLüµrK¬EÁ¸ôKìùG뮥Óª.uÛtŽq'¾Þ\“ÄÉwšâjqív`:“î!âÖìvg-£\÷{?Êì³VtÿSQY@£EflìYè÷ÒÊL^¨Ð÷ )¦Åm÷ƒ_‰‘An_*¢úèKÉ­K²Nµ1ïR Ñhðryu¬Z•3ü#ßH367,µÑ >"5ÚgBÊMd[#¨uZ yuå&rÃ8ÂúHΫ ¦Àí0*rÈ__²°3X5©¶¤m2ã¦aÿTN%OÏ€ãvõ:eï—1†ö!ú¼àYz¿G'âŠA/¾Ë¬30XÃýf%hôùw¼Žªï£w[?JÝß\þà à€P›„PË‹Ýß¿hD[€S¼†uÀv×3Yw‰&\o=$Ò¸Eàú (9ùJÇ$POýä ÐvÚ‡)¯Fà9>`WÍïâ3WÈwÖ—TM(bòœíÕèûõ™l¾ hU…¶Îa´ôäM¹eômLXwsóLR8ãÞW"Og¶i' é&rÜßX)æ*_ùæäòKGfòõt_$¸ÚŠgåÔz?.¢(¢ñÒŠ1ÁíƒÎÒœ‹[‹Í[+‘šáœ«›Üèq]´`0Æ\h¯E†5†ÝÔ”Ò¢ø=l&·–Sóz‘èç$ÚýÏãaǺ7Â#ïôV÷jUWƒ*ìtbiDVõu¾;Åÿ€ÊUÉDp>Œ#¼GøÈ×È{×yFuàF´ø4ü„¢8Z» âÿš¸sŽÚe††(ö òpz¹zÉêÀ 唂E.Aóq »‚ÿ¼z'­=ÿÀÝ‚‡z5‰.â ]ž’w´Šæn´ ˜š5 ©€ßJQ³ÌVŽ–‘Ç‘ÍLß[ð`ýí1Ë5à$=®ˆóÃÚ ÏŠÇ´Ä³Îëz€·GÚ~w®©!ºêð¥–3.ÿº˜UÝ’)ƒrp ËãCõ\¼©I¯Á™‡.˧ÛSWûîJZ RIi³x:mþ@IÜ‚Igì=í$p™°Iâz |£yŒ¼éX¿¢/€¨…@›Ú)q6‡'ZÀ€ Ã…ó+p5Vá1äzóXú¸¦º?„ƒœUÑ1ó(ÍR%ƒd­Ëê…î¢0Y(C$HY(ߪö±ëʬyhê†x]²ÙЉu]ïvðDX L"ÌÚø«hÌè3a–lïsÕ?ˆÍr¬M*éƒ#ôÔX–g 'Ó´œÀàŠq>Ïy=àØš]3½Cq œ côðEEPá—Ç…ÿˆ‚ôžŒCàëU¶ÎÅä+”VýÕ0½5¥µø®·H¢å#>“Œ˜~îá¶î™M¸ ¡Šêe«bâ´ŠŠÉùã×J}Àhñ.V,èщ^rŸÌ²ýÏlÞ ªêuÌÌ{XÌÿ8|šïËiš­æq*Lò%¹@zVÖu¨€×d²Q•?ŒÜ PèðÀG§· €÷‰úôS«O+k\8£Ob€ÃFC¢MyîñQ}@Y7ï/z¸ÙY#xHHÅèä(B÷²¼“VÃN)u™Xk$W‰±ä¢ø*Û`%ÖÚØ¡ÁÆ g€8¦,ZY“ûaþlŸp`´.ÒÀÊÄÖÛ0Õš y úäuÿ†Püº˜ã)å œ EÖVܬ›³Þ§wâ¨#ÌíX 9M‡æwÓ·k&!\*…ßP‰%Ûc&Ú=™tÇ%éYêËË‚@&×l‡}ÖâÆíDH’v2·šžŠ²ïϯ>(#DŽ^Ó³Æa§£Åy4†f ¬z›b NVPXÚëòÍp0 _•cå N!óÎóà0õá&ý'êm«áÕ $µà)hÝ/›Ô\,?C`¿"!WÂ ÃØbÉÈBhøQ3Û°Þˆ·JQ‘“(l¦»M`P?-ø—·™Š X9§º$wzëûƒ¢“§‡(¤ ×Yš>Ârât»QÕóx—εŒtȣĹ0¼l£N#‰WáqLÜŸQ N:”Õo%ôÂ/3ælé•kÆJnÙÃ^¢D/¼gðÃ\]™«<¨ z@fyÚ“Çà¸Éó½Ñ%šž[„•85—Š»~8Ó%ýî V”˜Æ6«˜)¯÷ËÛXaÍ[PÄ›¢ùüuº v÷o Ä6Žî?“%¿{I;´þN°ÞµÛ0äÞ@oyV° HÌ®ÉcJ¯žGdÿŒÀW[!_V‹šêÇ8‰8UàïÛÊ›øxÐ>hƒ¸s»t—ëMœSÏkD1nâ@ÃÃY ´÷¾4r± }ý°8¦¨ÂÚGrðÂÒTõýb@ôZ§nçiÆm`‰Cw ¤QòŽÒ¤·¢¬‡²5,Þ‹\…MÆ( 0¢{Ân^^š¬Ó¢Eï„r¸ò¨ã‘8䨈…°¥j²ù,ØÖÖƒ]KéO K j)³z5C);î‘ξúÿ¶~kÚ<*žûÄ(¥èŸµâ0-–‹¸=:Æ!í ÷6®Ã‡‡ ìUX±Ó}°N~@u…D¨9çãÃÈ âáÂ’6¦•æ>‘]÷ŸšÎ‘IBR‹ f‚êëG’Sx‰ÏC…"V0¥„~‹@þ ž Ô}œ+3`¼ Þ`¯WZÑùTW‘8ÚP`™{Óý·F ÙHÂ$Ë ˜–³³ ™O…{“žù9bsØó½[ÌÀ0› ‚³¾™o0ÓXVf6‚ã%xïxGswZŒ yÙÀéË}­‰Yª5}o~„â\=AæWe¾“pºç?xyŒØ­Šd#oút¤Ü=žñfsôê%z(ëà]B{JÍ·§?G>±´C»ow}˜3õ¬6|oIºÚ¼q²ŸçiyåuÇíbM3Û>L.E‰ò¤gwm‡ià›ã]Mè r_Äyó¢ë¿‚ÞY^™“t}Ù>wôw“x ­»<¨”ÖŸ…¶éË}ÑQëîÆ@¥2û̺‡¸áÁÄ»T’?>”yx® åo>òžHn×ètH- CÈöŒä¾g®»úÙ°‚€2¦È(_ÞÅ0EèÖ¿Þô îMAŸAfͱšå’ßqšù[ÓÉë‰Ûlº4 „Ó©¦ RWÔñÞUxbO9D‹¯ª„3[œæàÄh"Š ¢þo |ldn–I»1>ůí•A¸äÎx˜ÝL/ªÎ哉¡É—ãh-Í@¯x” ‡F>ÉÁèuž}|UiÛŽž‰æî™l½ž†¹Áã‹rŸó–î½dКöê6õL(úöÑeg®c cË*§ˆó‚„¯Âredk˜mf¼å2ž¶ Ç]qÅÒ’ ]‹Ã”Œ"ñ`Ã&e»ŒWi€p“Äô9<&Ì7‹O³ñ©’7›pºLÆ?ñ×C¡âb‡VDkóRÑÅ´`2Ƶ#æ…g%øÔN› jP&†¥ÞšÒ#Ð×3G¿˜0ë6Ðxå–`ÄÂ2à¯6x ÉÏ-áõÃË©Q×TÕ9 çh Z‰ÏÄ&¼N¹«uœ˜†ko`¨¨ß‹û/œá_>¶§a96å“»({óm»µòy’ظ ÀüÆ6cÀGYü‹ë£\”‚hW¼Ó¡Çr³¹0ÎzSŸÀu €ùaò&•2 SöB‘5ù­ÙªLèB½2uËUÖ8s-å1“_¸Á†Si_ý›RMŠxX¯ŠYþœ ì¢-+óÙ*È EE…èÆsvpU9ŒÈqÒÖ• ¢²ob6DWYLÃXŸ kR£!´6Y}‰6$ï·zÃ5 ×Ï_8ϘŸ”ž'Ì A÷A_çÜ­)‘Sº`7œÆ&VÔ’ç@vž›³K›¨BÊ3 $E0C_|z7¬ØxsÕØMY–þ¥‹idÊó/9ç¾ù½e}^E§~m§¥Ÿ;Ô!ç5oéû—äk~4êï¹4—‚^¯òw¯k«‚릉Äz'&+öÕ „äúÿûîsÑjôŒôOô¸ásý=Ÿ‘°¦Má”c!Ü€¿µÅdTD ì™>ÿfkŒ‹… ­æ¹Ê©¡†’V¦*s$Ÿ1m“nã eûåD á†Wƒ|üRâýÑ2$,Dˆ£´KYæTæ 7ÛDAcÖ>Ðõ§î³×—¤’É`_Ãû2M×Î’éÔ. Aœ—$²ìx}.žDrp]þŠ-Üñ5Y·˜ ½xdö´ëddy¡")#`^ð3}¿hùNèÜË4NåžSƒ9 Êìt…K£U=ý±wÊJ”)2Ô­&bc.ýHŸ©þo¬;©¾ñ;S”î÷†Å¥TÐrœZC$L +.×JúïaSú«MÆŽ_gDÙ›ÓÑT]8ÝôE;*0Á=ýõK›­Ã?š<+ª±Z ­9·>Î_îÜ$á–­l2KÿG”»¦èý]ž±€ŽMÉ·ÝUPµé*í q˜³y7maýræmæóÝðÎOU®ÈE÷V®çRQ°¹"Ñ×[AíµN _CO…mùE ˆÞ’ë‹uð‹dÒa¼z­þ©W>×ÞÑ@´)ò~ÒS ¤‡¸ÞœÈíÁ'Ñ̤ÈZ­n`á)R81áþ‹7׊^u-´ýäŸÔ? Ys·›3†ä[R-²ñpÖRA¶xƒåá®Áè`no(H>W-¬jzg€õ$h[öžr(u9÷5e³£h–&ÜHž¸§"Í0ü·†üøt éîÚ­~¥{eV€AÄþñ/6œÍN½$°ýôLW Ž­ñ8äÛÿ¾œ{bÞž¼–àÕ5” x1^¼ÌCÖàHjÄEó&­cåy‘‰ÃG×"£¢.„;¶Ad×ê2noÐþ³ì< òãÇrÝï#ݬO,")PC(ÆဧöÔ Ll£Ù\ßgSÐb±‰â@g ÷Þ,.#¤nfTT.fŸÿÞLíeXàLqÃéd¯Y³´êÍ&*»Ê¼£<ŒÞÇ¨ê žû–þö—ß#S+úLøióHÖ\qµ*«ï¸'ÇÎl9 ìµf>è3îÁ¦^Ù·l毞ö‡&5‰ÚúkÚÉ#²º}ýúß7å®þóLô)®¥·Ê}ù×þ;ÿ)5Þ¨©pöÆ‹S2ÐUÿFGh¸Šã+ØÎá³_¶©*Ó1¼¢÷Õ;®°\†D*4üÔ'9h(u_Qb3›²´å®Ýxû…•_J…Ú\‡ÕÞÓžÞ*&mx2Üg@¹2éK öþq9èŸQÒ ªÚ+ÞY2Üd(U€‹“Œ˜Ÿœ;¶XnqðF[HûÔØ•ðÙ l¾ðÕw7dëÊÎ!׃q¹wYKYñÕš›eaªì'\š” uêñÆ&|‰ìóñÑ+Ü÷ªÕî Ö2]”&ÖFD9>Ø5ÀasDÊ{Yá{iÊ-™£"_©–d.oö7†èªß˜ħ)(,ás{2k¢w°™ùR·ñ°Åu_SÜ”„…§!ʪ8‚’ž‚'(“QÏÉ•MF¸Rh Âé ð(—5þòËœÌCw£ÂÄNF!Ù¼;v”7w `¹AŽ@ºóZdy^œ¨>eUcÓ¹¡:ijõÕ¿úþDz‘ƒÍU`H—\¬$A±Öëù-|‡i¶° Ösã™JþN9¸†÷ÚÝûy‹‚¼Ÿ$Û&*zmjÀ TãŽe ¤'Û¦‰Ôå¤]·Ø—;ÜA¯Uz/ ª¹¼í2ÖßžìòTàLè¾4ò¢a[I‡#fcLÕ˜ML|$Äye™,™”Ì SH #Ã\uÁ ŸöAP¶mI·ùŽÝËÚ Ô×>d,4TÜúßÃçjïq@ŸŽ,’€ÚP«A™ß•XrkÌoœÎ"ôš~—TÔ܇<„S‹}ÐìŸÆ@y¯Üò ¿E…%N®-«5qÛˆ-ŽÂèC؉?ZŒ’Ì›?€ÒÂôtÀ›©# ÊÝ \AÇF·Ž¥“˜Û›íØkø½D˜ý'òa]¨Zû ò§Põ ÇꦖœˆRø?Õú]_¿9Ëgêrò¢lŸ:Ç£Ç×Qßo1rŠâµyú–KÀ<ÞSÔ9ÁÖU›AîÞêÁ¼®éxöÄiw /Œ¢z‡gµ6;hÆò-Sv°4Ž·Jš(ù!È$c¤HvnX*S—Ë BNžZö>œÉøŠP"—ój>Ïdðé…NjˆÖ°äSÜ>,âk±šâ³IQÆDvSˆzOƒÏÛ!µ|zs—zF¶³W„cO— =iˆf;Ê·D¯èÓÌë·@ìlÅÈà€däQ-›Ö…âšÍB)oÚ·Îÿ6îG3z€ü<å RþzàæSF³Ë‚kéA¾Â÷JÏUOÏ•‰²´J‰ø0bp¸:&GðuŠœ‰¸.eªc(Ñd©,÷F~T»q{n,ü¼‚•œ‰›^Åh&ZÝã·NbÔCʬ6“ å¨ñYåÂò®µr@¯³lûíÓ‰¦g~n™±DcÎâ‹S× \³·‰ÿ3@„Á¨{8ÓÉÃaªrAòú¾Â÷:­4zBhRÀÑK2s^>) #÷ZBD—†>;IéÊÔE”7,W YyB•¢–c’.ácµæ:HÂ“Í ‹½6|¡Ò¢W÷u¡žš“LC 4}1¥]G̥͊Åì¾Ùhp‘b°cNQ(ù¿ñ;´àtÝqc=eùÁc¡´c¾"fž2\¬3õÛ£¢è¸‹45>ýôg^LÝíˈüýÜ|ªÌA²EUê,fI_&cÌíÆŽƒÍÿêDuàhÁ¬eê®.b¨~¾rËä×Y÷HQƲ1d£ÉS±¥iYsÍÚ«ÃÕâÖIãÐÿO X køØ¥…aÖè›=ž‰#RT(TR½€m°|ÜÅ )¬Ðx|$ŒxùØ Þs>V7#8xwu¬ó–`'ß½«aÔØêã*^?ý3„˜§r`ï€ÙÂvUm§Ø.YÉöX}4C…´¯Ò¡~œVBB±!8÷ðZäÈŽJ÷Vó”z^‹„\hÜK8G¶aÖÐòÑP—cüXÐ(kRDäAµW´KZ¹m+$(Q’ê{6ŽM\âÇc†‡ çÿ÷4Û/S_„ÔyRŒ»’8öÍô7—WÕOÂçtÄÛs‹]£R(’-ÞðsQ~C^Æjj@MÇZðuƒõÔÿrÁ.’9 S@ä’6ŒÝ‚ÒkÊwøEŽ/bg†LCnÄ͇‚øQÌ£wæi»t^Þ£:ÇÚçôÛ ömÓZ1ê­ê"‹“ZÀ³-.c‹VÚrkš±­o_jœy¥-bÄæÄâºÔ-®H/Þ¢4Ësôñƶž9tnÊ¿yª8#kÀËÁÒ˜ý?Ã8Ïö1`î{ ´Tß•óôÏr*'O‘wŽÃ¯‡²™G­n9—Ë7¹ÖbÏ€9îÄæÇ<ý± œ¤·tü£úÞO²Ýˆ¤#›k³Y¹mRê[ÎÌ´B™Ë€dþØJ‡CFsˆ:+®ÿþÌ«ñľÒ^Â0Ú˜d£Ë ¶0¶óÚˆðÿù@ú@ 7Ù¼f}Æ`A¡Æ_ͧQð”:©pr8œ†Eê•äø9Wûݦ%PÍ:MjS7í-OöGº¢Æ¾ÇØ\¾ Ð}Ó>tùƒ ô…ó]q+M¦€NîÙsYA£”Nj·å/‘“ÙëŽ&®ó¼¾© |—ïtáðèÈ@±,2‰ÉCZ <4圆»fed4êmÑ”…éjnxî±3ÕÉé[ºüOy ­pÃl%uï—²?-sW£ÿw˜èÃê«pét waΛö¨ó~Wtø„»8ŸùdØFbÁÆú*ú‹õÍ?ûwäXfàîBVB½<‡ãܰ½q6*AaOérΘj'/<ñ‡o+µÔÆìc5~{•ÞÑ,ˉ;”í}òÖú’-äãǰSô&OÒŠw¼š æÎõì^âjz¶¬!¡å“󑔊+‰ïþ•åÍç…æŒÕ¬Æ&d•¾GÜ •iÖí§Õ> FLîzVXû-ÐÞZ™s@™çì0Âhñ  ™ÁOb·Œ¨!(84âiÚûñtš=Á) Ayü| ¼ƒ3°tU 1r_¯8VTš ‰Ìã–*Q£ÒãXQÇ›»©dÅ- åÎ,`!5é2lòœiÉ]ëËNÈÁBmÁ±Y’ìe%“ðHyF <ÜòEgÚ@î%9gÑ~Ñ’ª´]é§lócUdæ~@0и*K:Qíé4·}ÜÈûõW$¼°lçÌOâ´ÛÃá’Íÿ‰ù©Ô˽êø‚ e œ“VY@o•¢IqVWÕáÒ¦…X7€g€`O]Š£IFÐJ·ÓíOÎÅÉÌK:_ëåô\J7tlŽ´ÙŠ–’ZŠ|38´M›öA™fæYÑ]jðظO®·ÁðzÔÑpÍç&:æ²ñe¢Ïì¼l—91&iî|âÔþ`m.T±âL—sLý4nÑ„'=b\M!+㎑rÙ n<Ùd˜Û‰žÔ ³¢ù™_ïõ%”“/$CäEÍnŪbØŸ)è«k¢€È7¥5óØz þÌ;”wqüJŸN¸ÎÂô&°pmûíe£¯Ž7Û])ÿË¡iû£ÆW2jPK«ùN_T] ±‚ê, Ýß„ð¯Èeà0æñPàòËŒpÐ4Ýçò0ˆ—5¤Ùo͹‰uúŸ¶{øêýeÝa9HÌ1u¸“9ëR4ÎùA@öÖ8·H"Zr¶É°Àgƒas;*³À>Ãîñ”ÙûWâÆ»c#øëòϼÙ-¦è™›14Áëå1¹†´¡¦Y /Á¸p™“­tÔ~^Õ ØÆg̹Q™S•…‡d¨>Ø}ªjжæØ?¡mk9i0²CD¿Ž ª.‹™¼JÇøÊ¯×f; ýÏçS™ÎÜuBÍÓŸøÄÆ ;õ*šÖÖ­6 7ºÐsöÕ„=ÑJ¨#]4‰–¼$”´y-™CÝo‘Oθf\.p§VÈÁXÇÁ?ëmÔNêA=áV»i…éË.B:X„ÑÝ 5Xu0ÑQ1è˺ÏþBš;ÀØ->ƒßöÚôûªccbœnln–QùèÎëŽ|M­"ÙJü\uE‹O ¶^K"C«Gš£üñ¦¶î‹:’åPõÈÁ: Ó´HæŸ!e¯`¿vç+ƒ}àè+}È9„êiñƒØäºvÏFa5 r>ÅÐK1¹ú#£†¤å*þýmf®7€¤F©–õ)¬‰k{s3lÅPr÷³aOð(Ö¦ÍtBÑsxÐó'žFr¦Õ)qU2”K—KÊ^‘÷ßGT$óάFÇ#÷Ëê„ñ»ø…Íž¢BµC{–æîÛw°6ÀBM¥ˆ%¼Œ‹îòôcCõ⻨äµäC)ãÚ2 `Bé‹vØÔr(Ò©.ýŠèV”½«&å5EƒÉ~ÒiQb A,‡O^²‡µÒ^2¸ƒ}Ìj N%`ìl^¬œhâ9¡Œ Ù%;½åÙ-4¤B6ž8ø›'§%·r‚¨ÆNûæ+.ÚMÚ~.&4 Ã2QcÈ‚¼°{¹ü_HÌšDKÊWÎf9ñ½¿>Î\Z‹ ËÞ7S½ýž}öð?f* ÁÛçS? Éve“åB¾}HòÓ3a9Ù=Féÿ¥—λä+G²©]_¨×€ #~±ð¥^; ~Ú‹¹‹b?YZÇqünŠ $^§ù¦M5¹ôú@ÙœlÛ§•ɳfÏÖð òQa‚š1(ˆ]o.´k#ŽÞ}¶¾•è‡\ªpåEP^‰_¤°OVuzÆQT7võY|dJ –§7ŒÃÊ ‘ ¹¥ñçiJtK;¾Ð5–Û ðC2Sä ÔS Os&x°ö=qŽ|…ÙÁ$¥9|I àD4Î=¿]:ÈÃ1º0þîWí,&ž6k·þ´cz÷{`±­xκvõ=©t&rµfSææåUE³¥ÆVìaZšåK>SNkxDƒ&æÍ|än̓Êëí_hÓq\W\gð]¯$ò}×–¤Mä,iÌãÁHÛUž\×—&Y[øª“y±¼" I¶çè¤ÏŸ-TË~òÌÌQ¼Ê+â°—O¥8ö£Õ|‡"?®æyÑVÚP÷½™WÕ*치½µùcúq…rC“KæQµ}ÊÇRñ\$·'íÖu6få„ özU ~œÌ¤×ûçÿx_äV©Ì»¸,M ã9µ¸§—è@5;|*•Õ+ïW7b›'Ý›ãè† “bãþIæð²pÚÀɇ"^ó€NH?@vÅHÑnû‰”`tM т߶†ýKýï9y‡ûyÒ‰n…º #(=—Ffá~Rë! èôÏZ5½@åùìØ˜[69¥Î“:re ÊÚœAwÕBb”ó¿f‹êØ ¯É»Ã­‘øæbÉMÓqŸ›4h¹ O m£[~ŸC:Ë#l¡ÙzZa!š(7þ§îÖ^éú¹mþqÙ¼ƒl§o£>œô“>R˜…²×˜]øÚÑ—ÐÖ>ÑΡÎÍá‘äÜÕ†¾B^±2"¶{+‰Äˆ[¡æ m·â k¹ÍCƒ¼5úë&Þ»†z‡+•‘Z=¡âí •ëÔéÝw Ÿç¦2T릺̾¢êØ1ò©wÓ?”ó£­è㛾2‚­ó‘} 2÷ŒÛ¦ï?€jH_ø\Iqça@Bžk'¡Ð$Tb<èývýþˆqçkø®!  €_ü›*"ß{,y„0‰SùŠö\wZ³u©¤¤‚uå‹#ÆêÉ‹½€OS„A QâùD#ãÔR—íiéwÇruH™\óL3®è÷ñôMýd²‹:9H¦G:”¶…/J]µªü„×*ÒQªÃcÇÏÊ…ÊÇd[™L§†íz¦î-÷tе³êyõ|Xæ¹nlsH‡×\¶¥í´Üm»©^Ћ™“Þ°ñ~(–'!+÷õÌRÆä½¹Œ)…ÿ¥4×IŽ­úS÷Žœß`ä¥HàÔeÃü>¡2ˆö˜ž:Þ)å“}Šž':°¬9ÜǙ݉i\~òú6¤2Ùð™¦_nÉ 2Kå"{Õ}OÓeo7þEÕ¨úÅ€Qd.þô{r´ßÝ;ÃðÓ¾Äw< ›}l=»j)zj²’Õñ:Ζ|Îø¨ Åñ§Á¥ß~Ni™Š˜´â·>|“ý‰ÒÈ(£“øPX'õÚôÑä«ýõ°‡†û ~Ÿ ”A?<«Ç¼üË$³6â§ŒÍO\qê²X¡[´ùp@»Öfuî!ù=ÚŽÝ6ôØ:„²·ªelî‘”`I} t]ãü†ó"bR¸~¥}m“¢šß¯7rÐR°’'^O®lM N!³ZºÀi9•K 9£Ñ„ÝŽÿR—¯°ÎâPm €_éëÇúêC‡Æ È¿+ˆc£ÇayÆ¢‚§»w §¿D]As4)Úá;TÅÁuT¨ž\ëûI²øòô“½àWßšåTp©E8tyëÉá÷S(¹;°9rª‡‡eÔš­/‰ãDÄy»)BK|²Ö–óRÒ ’C§•jæ”bPö1áâ:ᨱ > |¹lc‘£¬‰,LˆžÐN“í¤ÆêÇ(‚Ï*ó˜ÄåÇ^@x¨X8úíÇ"ävÆ¥w«.Û%ªÌ_Æ¿)ÌfžôìÝ¡l~ÔÂÕ6µØ~¢aÖ5°ÇL Fd¼x´—¹ ‹{â yÊtkÕé\è>ÍÆŸeèÿ7Ñ{™Ãvºb˾h½4s8tÃ#ÖI†${zé³÷_á ž"ÑÍ?Š» ™÷zøœC*%áØ"SG¥Ù³ûN 2‘÷±?¤R‡YJ!Ù)_R0qË‚cDB~w;ðNîœ[€4å)óI¾í¯ôÙLÆ*ƼRr$T5¶É–~fò﫯Ž!£I úSøî!ï+‰Ž8} `íL"j4ƒÉÀ.9•ˆ!:ý΀$’{Ü}ux ¸¶“>rC£~o‘Q·©5å5±ä©K–(Ó~—¤ùé-ßÔ2ÃÁZÁÀ]Ô"Fµœ±Î³ÊAQMÇ.cÛsuàß'èÇ÷‰iÇ´W¡9u~ ³Eëw‰ù[ö–Íð·qUÃŒý& œ)Ïbq9œ*Ç5å5Ç(’’Ùx-c)×ÕS—Ñ ä7¬ÿÝA¦Ö“dÌF˜9b¤]°rLa"Ø¿@Z«.ê“ÂèØñe Í€p݆?š±H‡] X3©~ £&Š’Èú„V|ÝÓ­X*ÙÁ•M’Óu©yŠ3tñÊEUEv_£nCŽê‹¼Ñÿô¿óî«Ó ÛÉM"Z$9Fç=´ )ç 險 ¯Û¡åO&1¦›Øœ„rRSBsr¥´ pÂú¡³%@ЧQNØžÙZT9¢¢ ã‡c¨;­1uŽ  MW:äáÕ‰Yáø–ÝP1à…µN­­º–’¨T¤™!nè°t)©D˜ñ{ø»3zǃ!–r£Œ’ÞaŽ‹=óV36*âÏVîúÂZÜ«’3ö‡U‰UWXµæ·1*¿Ã„Ì»+"ß[­R%¢ºßÎê ±QŒ?@´Uæž™Øïö:Æ4 ¾¯<]Ôƒ:¹Ùµ¤ #q¾_($.µsÚ“¾³jñbõf¬×®Â”úͧ©$]ÍÔ¾Dg¢ÈŸl|ƒV½90$Cù“:°àš“è–êVñß|ãzÿ‡ ˆ5 ¯3Y‰µ Vã|Þã?E~ °ÊŸrmb"¡±ºC|ó­WëSI¶K?6µƒÈMWÃuKU«×}kHŠ÷ïýC±og€‘ä„AIÚÿ>oT+Ck¢ñ£™gÚM;¼þR/)‚ð%Zz¤SP81bÒTbè~…á>]á}"Lì©=y_-D€¢ýG Êc XAÛ!vŒ{'Úe¥UÖ´Ò8ýj/ÊM€m.³m·Z:PùGª£3†òwià¾K´’~ðŠÖ’PQShàs¤ôW +4lT¸bæò Á¦Å˜c˜Î5؇E”‡>“çoD.™GuÁÞFψ”C†ú¥'ä(Çô¾žCM!°)=ÅÙቮ®ŒÊÈ|tå§t™8›„ žf–ø2 NmKGÑøkˆhãÔjpæ¿Ùy䯀À B@OÜ$̪»™~c“¿Ëpn ?•¨a¸‡òÍ÷cæHOɬq€ÊCÞät/6† Ý^?ìÞvñü‚D'fîxvo9ç5é™ÎzcÂjyO×’fÏõˆš3°±g  ÕeÎ]‰¤åk¶ŒÈÉJ2N5$ó­)×mÊÙ×2$Å­€Ø6s¼â@ß; EJ“RJüÃá|)Ùí*‘ÈÝÑêÄá F¤Êîkg8Á:ýÇM8iwµsÿÝiåGÂ{nްI³<ØüåG˜†y[–«‘Ưz£ˆ1ÿȤ¾îMƒ8Ò¡ƒZ>â5ܦ¢¬¥xq8¹z:Þ™»Ïx¸H` %'óúÈ!r/u©û§[alìùÌ&H•t¸‡dSEÇìÝï³<Þr5×E/VõÞ'ZtÀƒ€ý™:èÖhEÏÏáËu‰¤ÐÒð>­t«û½%QS¿lt¦d!ÊÜ…ÝX½ÝŽ@áL4‚ו„©¢ ^ônâñ3ì¿ ò#àæÎåId"ÄÖ([Ñsœë’¡EQÉY.[DÃb]ÐÊ‘þ ­ó˶/, =>ŽWóëÜÞý²jž4ΉGž#¶Æ’ÜÏG´o?ªƒ9Íò£k‹~iñ€·Œ€<àcÅÍœß|COjNU6FéÂ-Nƒ9["ihòÏ—FK&Ãm€còÛ–rF r 6å9é$ƒCþh—0üæaö*va»î?®n§« AGZº¤PÈúòÑ ¦fº9ŽA°ê›®isà»OÔQ­ôúLK:¨œ[57VœÎ*£’I°a.ÒÇ÷ìpñ:‘l¦À›П’õI"ÃBOg³fM®·àý9~;Y€†Ý×ãVs´ähU×\Y­gÇÚØ!â¡Ï6|V/¯_µºYéæjDH¡8 æQ²Q´ô¶À¬E;Å˰åØk©gÊâØöâ."â®Þ…9T‚6^úæÓë(\ºgð_[ž´Da¨œ‡Ïü'ʯ±¢v(Â)úZÑ#/Üæ°°]`ª@VV“[¶¬›˜^õÚ(£}”Ø5jæÊû€"¢ÖõÓÒµÉE$Ï«¬ÚÒ4$¹ÄÅJt78áá|ô܉t›¾·Ìà²óú â²$ŽV:÷\2¹µ%pËùaás"Œ’væÙjŸAè®~ ¸€DKT‘WQØØ§é6)‰ƒ¶„Ŧ‘Ë[ßìCøvö;:5Q7a3Ë€­"ÿ‹|‚ñk ^‹„lWÎýXD/B­«ÐÛÅ•¡›pLt—8­â~ú²l^°6Ôª°ä4Öc-¥¯†V]7PËÿÄ¥ÉǾµà¶¾z #§/IZ\ÝòФYÉv'g…Wé,f³¾ש/O¬Ù;T”ùu˜=N—3¨­½6íh€P‡¦÷YåmÓ8’u©‚–Ì:{Ռۻ>¥òe `tÖ'*ÅÜ“5÷6$4›j(Ñ)Ñö®Žûþºg)AÀ•Ö´Óºœ1ñ6Ç¢Ò‡,·æþÚb<ÕÎås õê(Ð*ÙðkÕ=Ò#ghþ¦äUݹð (ÔQ‹…:ò ò­“8 ²d(T@=ÀãÙf¡³È½xŽ mÑ?cfù÷“…$‹P9O½­úÙUɳÂ%qõr) †› ™WQŒj%-è´ÉjÚÃytéK1,öÄŤHÕ¼D- YŠH9›:Þ5%¬ÏÜCFëMᬠ¤bR½‰^bGXRôtJÿÚ2Îô%‹œO Q{Gý² ƒ0œeoMf¯ÁÀŠ— ñ:Ë[nª¼Ó>pW›ÙÆÔ²OK¹¦0Ò‰´õ} †[y»JóŒß…”“I?âöˆjŒY:ðÌÌiM³$bìÕïŠ5Øãí{=09Hë¼|:Åa¨ÐÞÂ5Ù)†óãò@06 ÝaW.4²‘(À~¶ç!–x¯qÎï9 ÝáÂe¿ô´£½>¥¼q®U'Fî:7·oÛ+Mžèýè’c"NÑ0ÛÖ.蜗vwŵR_%Â}šóîxР(âöëÌŒcÖ­ I^kà »Ë‰ƒ—_$¾!Ìí±*áü@~\ßõ>ê!™…õ˜¥oØŸÔÆ•ÐVÐ-îwãM'©07Ž _‹Dü# ~1½¸À.ÏzêÊ5ÑøX—gÖaF¯ÇûCuiMNÌ Ž—Ý”\„cÅÛŸçÓ=;çηښLÞO-ÜÌpÀs7aã†NŽLNS­ i;=¾%s¾?ÏðŶ5±Õ3ÍØæDÿbT³ÇEtÅÜ “Þï½é¿´˜NgÐ{Á˜ñmÎRc&–BUp2R*K]Å{yêR6þ:N7fŒ4Hê‰\=¨pJQDX‚kB4„½J~%H Wš£É7¶0P•ÚSU~ýîk ô&’^¸pϺ܅4åÎ<)•Û9uÑVÃòY¿“ÏÔbPÍÿFéÿóÈù[WäÄŒj¼s´ßÎNÝ‘ÊÊlÞ¹}×?ÆöuŒ—gø/9íùüßYýã3 Ð¯.XþU8Ôj~Ñ#-¾å`m¶sè!ì0$’«$®—% ¾yÛ’'ÝO¾X"ŽB9´˜÷ÜEî@²š¡ïïaY:6‰MS ËëS°¦Ó‘P cRVw›œº¤¹¬ü–*àÇÖí³`ah%mÏ…Ñ`/®ÐR挟Y“Ä«4fßr\NeŠ‚!fð âVCY± mÖ[$zED­½û¦Eû’ U䊲;½R¥¦ƒú´i`ˆH¾¤ƒ3¥naà ¤§&/„[?xÎÕ:/%3é_—ß,­cÈ6Øtþm-pÙ*q®)Äqoç¢àÃÀ°&ËbíãñJª\˜Æþ·<ÝV’óÙ ;F“Œrž¡úçº~_f•»ºï Pu@—ß²‚4JÞ½ÜU߇ñ+ʶ'˜}µÄ˜Ú ØBÐLô‚ìÿö×£HkÛ5ëEHJ&ÒŒem¤Ü²ÓÜÄÚÑ-£o˜yZáwe1â\[D¥õ>/g#ÑØ @7u<Ìïl»K±ÔzÞ<$[4î" ¯Hj*¶„®vÙ…nºÿ!Â6 “_à%.Ýü+þÃÓÁyàÓ¿ ¶BŒïZγ"S#«‘ o@>´Aƒû˜*Ÿ?„fºê/¸‚â•J®ÆrN)-fNƒéXó ?}肘gB°ù¶E}ßÓÏ)¶ ]Ú_ÔÛïôM¬nQ ?3AÁß¹§ö:÷&9Ûc¦@ZÏ:’sL$}<4ÌVº·¸Q¬÷~ýñÐÜœƒj$NúeV°Ÿ *ãmהּ‹%øæ.aÎÓx)¿æ!˜”Ýäb.¥Íø­áçÅîœõ>_’/&D0…ØÓëLü³á¨6ÈqŠðAáÀ)l[JZuwÈGX\_ÜEÙ …›b47 ‹°ŸÄ;&¡z}šR™WõðèÑâ7ùfAÀ̘E‘éé…ÃH »ß!œÆÉ±šýDöhö¯µ9¿*¼9>èð†2©X"àŸ%ôsŸÝˆÝyÚ[íauÆÍ\,Gù”~ͧ/Fê{mÍõU‰‘ÜŸüuðÎþ’Šîpˆãƒ¸%G-“N•¾0)ãáÿXˆ *Ðn0n à$!KI± d2PeÏ‚‘~2Â.ÉCn· ÎÑÊÇБ/Æ¥ÜþÉ[c^Q·ˆE –ÔšžuŒ=EFgI.¤IBb}£MsC?Å2ª½ô0 á²q†‚ûþ›ÌõBxCY³ïزECÜ{»ðÆ©T$Ù‘.eòçM(Và uµÜÆ¡ÈvÐ?7×MZ¢¼Lß5ªÄ‹ÒÑ(ýšf¸s6©%Á`8Œ½¨¸Ã½‚z…¤„ÿ…§ìb¥Ôens¥pˆ Ÿ³k-ÅLpg•|(,ðmÀëÙޤ ¼ŸSBk$êÑ+KÅæi‡©;½Û1ÕhÕ™K þ±¨maÙ/#F ãèß Fb³hjHùq‡e,‡éVÄζ*\L/n®&dÒ&Ü+s‹ýלæÎqA·0 ¿îzî{q¼*Þ "+ÞmØM\…”tOôßcp~ÈÖWo‘n'…_ÜmõQªK°]“ç ËmK,!¬û)êà% Ó*Õÿ¸Ó£H–ƒ?CòU~X n´Ê¬f d m˜&ûtÙÚáŽßVK¼Ñ*?bñ…áäÂîD•ù`§µ6Õo“722Ø[j…oú0.¨ÄBEÝQÊ1ÛöÃxfÚ/×÷&!Å¢îû¦„N•"!dYdàrW 34½xqnŽãc>ÕÂò‘"&ø˜l®½…Ì$åDÕŠú\:”‘šçMg’W¹$o`{G/¿±,c{ÄBž¹€&äsuÛ'³ñùÍpµåb8ìŠ ýo6´‚ÿ÷o7Hô,û-ïÈÌ6ú gc%Úðpº™ÿ–A‚9‡áÉðÿnE›ß6ìÿ^bñb|KHÞòÿ%fkv]R¤ãÃà¿aõ£.5›–ñ~_Üù>$ÌôTÊ ªØÀ:cЧ"\l>hë…2ˇ’£OB¸s+©ùBF°‘ª»,(¾·à¿ŒöfúÀÊÕ¸Lá0aJ"œµeK­*™ü‡AŸÁº·'ÐWÄÔ[dzÅ1µ¸0â¦3õÙ.üžÚ­^˜nøœár®_‘wUL­ÖåG\¡ W(4Ð:ñ¢c€€Úò”p‘ŸÝfáç³GŠeþ¯¬{ä6‰¶Æ‘G8ך1ˆ(ÕÚ,íÊžª2wœ½‹š5=«†y’¹øe¶dÍŽ`¨Á·5¹BК£J0gÔ7uföÍd‰ÌwA1£M#ËX…°B ½ÚìÊ¥å(:ìªé΃ñ›ëÛU+_r»3 bf¸ˆ2íkˆ¶.´ûoµÒTÉB²£((׊›‚ÄEà.mûª:Ó°:¼IYodb<•·SòÊ”RÔ'ë ü¯`Ò ?×ù¶“»´N×lñ³ãÞ±ÑQÓýÇT6ç ð@KÔCíBláã|Ï]–<œ”)eBE gÏÿ~ cÛ&#b¥ zÞc [¸ß¥bpOˆ°È!O•0θ•ÙÌÏòY¨‹Õ´Àï?3@»X²Ã'›"æQöƳö[y…ïÕH'r¬t«7÷ôÅZ ûZûyTK&í´ ò£ 뮘H傎㭴Ÿ±8Éåá;Ï‘H'jxNâ;ÇÖ4­ÜF©ïzøv_öÐ` D™É\w½C½à09ÃXD~Û:zÓË ¥öÞÃëõâpa¨›xŸwwöîåéd¹Ü2‚LTçƒ9®yTw¤Ëu¼›åèÅÏŠßÈë+f™W¬q@h*îÔ¨QJÂë„}Êë€D°í–ù y¿N¨ìAYÑZ\5?ÿ¹è'¥B¯™„''«Ž39߯œò@äšž’‹møx|,ú¶ƒ\¹|ø ËFRDÐA@5^õMåíH݉ÙÂ\”ãRëö¥âø6žúQ‡zñŒàQÌykó|´ÊÓ®la3`P0³ Õ}s´¼Ëô¥:,¸«¤Îsà'!’V0Äÿu¶ªh4ùà2Mï‚AõxL"ûÒ§Kl‘%¸~ø°„{Zsõ\y°‹i›ú»?{h”!V­%D•_Ïš|ÇË=0<§ I(0FÂÅOºÝiŸxsðuôÐÄ‚3!2ˆsŒð “Â’ì-—z£ÄˆS[_ü娉CfV^Ðú•žÌÚÚ¨jtZKctgêú –zšŸvWä[Ê"™Agùz<‡ïçë-|;IJ´´ØÈ8Õà¹:œXl$ŠLÓ+ãô耘(W¢óŒ6à¨C5Ös<[1Âòéð@YYò½ïüT¹¶Vð4vBßMF*‡<(\&úáóTÉ_t¨šAFÈý™Ùô‹:E‰„’LP‡^ó­+un7»õùŒìלÕP_Ì;óÇs[{×™óm«j\ÓZèüW@¦xÐYt¥Û¾Õ•ùá=±E¼²Õÿ‰Uʧ•â‹ÕXú %¿cŲ¸Ã-Õ1àgüùɈ;¨·¨Ãž©ÐX¼ÍH:Çk3FÜf]1rÕag¼¸á<éüºù˜$FmN–v ÊXÕ»åËûºCÔšXkµBê.¹ÁÊ’ƒ\l®©Åœ;£ÜÐÎÔZ×:"nŸ˜…çsÏ™x.Y@ÿ˜$?nï3‹<@(^ K³Ê HT6‚bÿà±þ õì>S°?ÿˆ@>¬—€È½„ê‹Qá}ˆ9ÑׯŸ•úÍgN´ú:màm,%:tNÚùmãŠŸŠµ(k>Ø!ȾÚ_j+©ñzÍ>‹—˺.SöÚ‘ªè”éêQ1ÛÖ›/•KW× Å å%uh ‚j̺¡E,—ŠñóηnOËůùf‹eÊ>¿L­*³Í$(ˆXê2¤à€h¹†_MQøuDjÂE™xXñIâÑ1Å´¿”lêj]Ö[:€ýK+'5”>§=FN¼ßå*ÉË9¿6mXÕ]§¨Ÿ¤ã1'ª+3BB‹2?”QmPA¾jW]r•a”¿gÐÂA¼Ü»ä>Á¹[N›ºÄyªƒtUºÙ¬gùÌV>Ucz{P£Ö«Ñ¹Ä[\š/"чªøŠh‘±ÖŠfþ£kº†´m—Šž$5*o.Œf|ÝÃòVŸïç5hl&Úº®uŠ`+æWfU 6`ÁS ¼× xœ««co­¸•¨J5!ùs4TÐ4éWÑÖ–r˜Ea.^õB5N…$×2h¤£«¢~Çûµb™]–ôü¶¹|~2rè†Ìº‚j)C4– )¥Â"o6üG&ž5dæ×_k{†ÚEë¡Ã\ò—CˆïŠ ©Îƒþ¹</7Íê©ÛÖíA_”6²5Ó†šs½&…qëÙç6l ޾Ù„¢.ŒÚ0R¿FWÄ‹<ØÃS9oϨˆ+¤Vå¨ë§¡1OaáœÂï÷ø'Àÿ°[8ßr¢>àk¾åׯêÔûL]<½4óÁ9Ÿ Jõ­LÂ:u¼o¯¶l°Mb^ŽpSÊô×ÎÂN[ß¼Pl »šD«ndÁ$e¢›Vÿ(õ>¿aT™ŠŒ +ˆm©i†šUq(•YÅÄiÑNǼú´†Iñ4gå=dOäCþQ êRß…ô¾éä'nfÜ +5‰µ$RiL-àÛÊýS}zNÃúL¦‡ï£³Ÿd„“:1( ½ûN,û˜äy%MtŠzÄe ®¯5–*näˆ.aúø ³›‡íR/*‹ñ÷ʯ`ýýÊÉ—Ù·”‡ÿN”‡‡(ÖXÀ»·^ž÷—SõÚxEjÂò=æ%ÎNÅi>¡…³¾’—Zª›^ÍÙnÑé"µ‚gD|JäMX{`»áÕVjÂqyOqbt,Ø] šÎDæ@8ÉDK¡u`ºù´Æ>R@‹ßläËñŸ=íÞâ«{Œ’ZzÓÔ×DLй'ùJì ͰQ“ÛF”¹Ó''|Ô«ÿàO‘رFS¡Êèák¦¡iì"¯½íÂÇ20Uu#®:¦Õ:Ž'€úýÞ8…*èP¾ŒjiéªýÎ šÆýøØbZ‚•2”§ó9É;=³Djhêög°„ËœQ]ÅÊoê“΀çxö>@ ¿úi“[bRš-!ªÄ×nxÞ¯¡—‘äM…ëü8¾­¹Ä`&5|exË‹©< ëýûÏçvɇUÓÝpbÅ™6 _‚ݑÿ.]7N€ÎH]tÁpÀS ¯qíT.°¬|7èQ>~¦J6Ã8·…’†˜ å œzâÌ"»$žFɼGÊç²ÈÎ~ßÒÜ>·Ó¸L^Áòx§.ßFei¢M[Эq«{‡™smÖ@ä”ÓZk –™ “P΋> Ž;z¯×äïVC!=tçD7ö¥ÔŸõg™›8Øc;iV¬~òúáé¸ ãˆZBwW1™èK¿»"”/= 1>R˜<¦š'úZ(sLÆ=Ⱦ8]Püïèw`¹¸†3¹ÅmuÕ±¥Çg] «‘Ãâ 5¦ÀWQýšjd’Ïë-ïGäëà%h9ƒ¸ñ»LA–Ö.Í1l­nIcÝrJÊB§|‘‰þ$Mãd›/·žTNu~‡5È!§ÊÄò‹ðÕŸ Ù9doÃ{lÌZ'‰Àÿ(ØÒ å¬ÌAUâàqt‚-†y£€”û¸)$ dZpŽ–Ö ÌB¬ýió²…‰:‚]–ÛÄÇðºxƒ@²Ø|R° 9Þm%ñ Ž~(#¸]Ö¯ Üœœ`Ò5­ô›ð1Å42Ê}!D'žN ƒ6Ì{Ÿëõ¨hFÜúE«ôØçûå°£¹h‹æwòéü”‹3Vl5QI0ÞÈðÎ0àGOKP‰Fœ5öû‰Ýâ!¤âÆÓÙàO¥ë}%òº©…VîwÐ(·ð˜íØú„4ÀÑãaƒóÙÇ`¾ïZ]ÏBZëíüóʼn{Fű/ TÍw–)Dº êËsB{‰œÙϹ-æ;%›f·˜æÑ{ÿ/J†Keûq2DX›B¾n$#$þí¹ §¸PZ)uBc°{ ŒJœ>· ¾˜îÚf¢—]Y`xZ„Iñ²¹Û—:È¿$‚«V5ó¼•$b—Ä¢]J#p š¹Cm‰¯CüEÐGHLª£ºs½ i:Õ˜IŠÁ¦Ú÷(~[üÑ«Rƒ*[|â‰]qœäØÆá[<Ù»H±¯É‘¾zC üŸ`á¹À6Ï ¯¹Qf×àƒ@ÔT·EÍÙ3i€=«½–lþ„‹‹ÇãPÁ{ö| >®Ëv³>Ð.Û*¾«Y"¨·Hhò~¥¶ˆÅ „íÿSöS§å_”¬i“-QB.®lj‚YŽ•K¾Þ8ÑÿSuÖÿ.kˆä܈Úã6Œ/••²nLzá×@*%Ö1ÔÅãu[rÏ üìt >¬ÆüxÜ`güô;üÑÌd•àìoEÒê#,{€‰ HÈ]è†ÞEñJö¿W°ÕÜ·H™¸1įæ’ Qa|9XKóšg&ÅÏ Ãýô^à{ßãTTùú7)x–aú#H;¨‰ø‰ñ™mðÖƒ“ª#~ÅðüwùÐòÏ‘c ÏAa¯·åK®¾bå èRØYñÖh…ÁrÀšån;»t‡ÚK ´æ3k`ÊÀmö%2+yœé=§* AÏz¿»—íò\Xç—ŽÊ|iIe=£:qaæMoy3@«õ’“3t²ZHä¹î`¨ô ­Œ^Í"PoéxÚ¦7 7)Âç†ôÖnsË…j˜õ\ÛÝiª¢¤±Jg?¨ß7s„ãâRýˆ^xÏ•ùjf÷ý÷Ÿ.»aÜ‘³‹VVö»…cäÅË׫™Ÿœã ®F»ç€®¾½qyéaämZg°à6¶×ïrW5ë}L§Ô”câžxW¦dþ0ÝöTÿ’0ë ­ÀF‚··œƒ¿Äv«xšà\?Z»Gûƒ&,0Ï E®kDñ}Ø­jø·ÛNʇa{ ‹s·bÂ,éâ`’f±'™‘!ò1aa•`ýJõ;(FÞ“!mÝéòˆETFlÞ/Æ>„±yÎfå*+óS³ahsøÃ¢À3‹LíäVÒ¯>£õB£F|=¹¯þ«xÊ7¤!«hñ²oƒSóŽJ“ C›|©‹ân7 ;(§w£õ¤&?wÍé£Ë¹ ¡©ÿÙ‘©±™’í0¹jë9ÚÀÉ‘ð›õ`¬,=/¶b5m‘_¸ªƒILÍO²+ÐÞv0n’á"ýaßÌP‚ä‹Ê¥G,áà$}ö Ìâ7µ±ÇTl»Ew»ùÑÖó _…äêèŽpV6¿é@P|=±B9ðŒè$5Už`A®™]o9eóÓ7Žšç±;JúF;`*â¡bivõŠy+¹tˆF¥À`_¹ë iœŸGš…3 sÝþáð×ÏnoØÕ:Kúã+„™؉$ºÙlRà¯ÜlÖ–©H¡µïq¯/²´ªg+§GX‘cb˜må̆Dmö–žŠ(¸]Ê=?ëhé~„ó MuídÒœ\½¤`0…è¨ï:ÑkCz–÷ñlCè—-r6 ØøUü=¹Joü£¶Wóð¦œ}ÿfQ˜‹cÄ—¼ k=9Ý ÌĈH&×øÏM šVhØ8„ZTO!u¶WšaÑ6#FSÌ¢v)S'!¥=¶Ù„|àÎF«òZ>!í»¾(†ËÏ¡¤4À¡!¼Z±#ÕõžìL}˨ÿ|¤­ç+¬ lÕ!•msÁuR®¦Á> xÔ±sH]îq÷ùßlö=«ÁÔ¸,”›‡Òèuù˜Âã1gT£ýc¾-Æ)É¢þ`Ø+@×G#SfP\ò·z³-nÀ΂{Ú.Lýk=¸’ªNkÜiÎ(*h ò˜Üf/E…$p?„7ƒ§ÈÕõTŒGËzQÌ„Ùç.ÑDLÀrÕz»µôó]í&¦åæÂ¦#8ó˜HäXêQ›ùŸæGÅj•FË Èªœó7‰ªÁ“A`Pî‰í7è?¾£;ý‚"»UÆ€‡¯`n<7¿¾É:+¸1m~p0¾ÿsôÙˆøuŽ÷qI¥—3Îú&›w.†…€Fç–‚2öHÒÉü}<‰>:OjéïÆÍEZð›\¶¿” Ü»«‡ýxˆ‚f»ä±®ÒüJ gòÆ¢¶Ä«—xŒ#Ëlð"¸(Ô……iøDç·B g3šÓs~–sQ­U˳T'ÏÔ²¨ÿ£I:°0Ïg%K‹é&›¼æ1c>D®Ähú]`óÒ?Ÿ&aûy1ÏÞ`™xüãþƒõð³I9”cè,ÐßêÁÝ©eþ…‹ïzh ^çñ nv°5„{ØñÁ«˜ƒ£›Ð¿]{¡p¡ë »*@•öL–PÄŽíŸ>jü*¡ÑW&¼Tª1•Ó˜áÃá_ªW˜R\IÄÕ‚i–ž¨f²¸õaÑ)+_ÇC­+Æ=ŒÈÖ¯õ \&Ž×áåÐk^T“Ðp/2oŠa[õÕºýR…ʃw¦10Üš¶]|PÀ¥Â|ëÔP8'S®UuŠD‹\Vó@'1ÁD+ÖïÚES|ÛÙ‡ÂÄ~³Ñ8ÀjÄÕl–5ÖW¼þÆ}’ð  ÄøøPQº;5BOŠª@¢Í­~„2Uà*AØãÍ3K{¢çÉ3·˜N'µ#TNWvª;(ú×’ ùÄ›^ül™dˆ•Ÿ=X„2+o³vB­ÂåÁ½¿÷ŒüK›½j0SÉ$¢3Û`±J£¨ÓQÿ:+öÐíóÚ-_Q*ré¨ãå"^¢ê?l_\ J]6E¡g¶«=,‰™²þ’"j››Íx郒§®Zø]æ°M€g–Ì4H½°=ø¢€œ›âÊÏÑäû쀡ß[³¦Ê­SWàÑ€2¤GDù(™îÅ%|O IÆD†Wÿñ,ɤëÞÃE ÁĻᶵ0úRÆ9šEíÙêá û¦¡Zö»äfIàb¦s:Õõ¸x¢v|þØá_3y v7'¯:?¨+†ˆ1»Í53çÉ?a„Ú˜WIëüýÑÔ ômr½¯›º6ßÚFQ Ùyz~^K‰•ÚÇŠ ÕNv€êøßÿuسà¢+ŽI„òoþ*ÚjmÄW;1Ýß^œQ‰‰4€›ßª¤ÀØñ&ÅÞÔ5Fs ò}ŽÓÇ-ovUXÙÎÛW΃G?>·ê½Ð°Qˆö«yî@j©Öý%Q0<âþøu¹V7Ú« Þ2…cJĪt%Rö\]puâ·\p÷¹vKÔݽ¹Ò¸ÓY 0ô%!²É16JU±dÃl¹[}÷m^ü0‹¡qÒ’Dh™[C2¼*@7})^¬àPBÀÃdVŽe0ïÍß\â ­ÝÍ^Øl“оp¯žÿ`mn£ƒY,ŒâK‚ôÀèçðNKÄUjÐ’ÂsIÛ J=ÑÄ:KK<c÷J-6×<-¦\ò­2àËct<õÚV)¶)cèôSò~1 I´“Z#Ñó¥·e@RÍ:cµU‹ñíCȯ<>©YSvqãF¦tl£!*U²Ç*à˜ÔƒNÐ ~Â"í Ó+ÿ˜•-®úìÀŽílj3¬c‚V|š ŽÔQûL®ªÆ0}º¼•BW˜Y>¹«½D*Xjìú_fdFÐu„Žát×ý¯ ^Ù>ÃÀ‰¤ÊZ¢NE¨ôr ¶¡rî@iùÛè#]È.¨?¥`“ÇÆ4z@%vò6•(_‡Øó1pLPl£Ø‹¸zE©¡ŸåsÜAžø±üb{‘ WNvÏÓ‚¥41êtÝ`õdžÄž„3úãV:–¦"*%¥´ý3—Àe´k~b¶R¦€`!Žmƒ‰X/I]¡ô[®Z˜ ‰}Z·L²ö®v€ÉØ,4?+cP#…@1÷‘¿×QtÔѬÃZ’­>ÚבïoBóQt„áloh™òÕËÀ¤åw¨.·*†üÞþá’„T~Ôëûêy1ªùFŸÑã×3R>º³YÂ:4}úeA!l÷hÿQmɮDžJ HÁúH‚Å}E|ÁàØÁÝKœrlk{‚²mêÕWÞ¨í¥qýEæ¤mê‡ðîoÇJ¨ß^ûþ‹}è£ÓŸµÑßyÍ)4¥kU1¯ÙO˜1æ’sÅmWšÝcO/ˆ‚DpIô!Ž €×|†<ÖÝ… — µ)éI€ ì7B,œQ€<»ŽÙöÁßfR% Ú ð'5ôQâFÖÌTøQ)+é¸ñ+vI䊢%y쎽M§Ê”’¢¶ƒÅAbWÏ^'OFüN¸Ækþ0è1ÙAM@L–"þráQäõd’Ø dûºÏÌ«l•5Ò~}9åç[¨·Ïç“÷ƒcÖ¢L¡Ûò/J–Âsÿ¹"'Ž,ã|.š¡“ç< Ó~ê8FÁe)VÓ¸¾¥aÁ¿£åþgáåbFRN˜=Œ‡º^„^éXhÃí,A ï¿¥ >1Q*æwàÜÌź"ªË;d¢AK(ƒWZÙ·«×w$¹ŽQk»CШظ®7/|q¶À(Ï䢑›lÊAõúÞá*©gœ§«{â"PxeÞÐqcn7® à)«dÛŸAžÁ577n`ƾvnëZJ¿*ö丶GrŒØ0µ¡M= H÷0Ùv­#ÖÅŒ÷åª>m^X¡Cb ƒ+UR¼=gi„WÿÆKרû¿d×Ã¥Ñê° ºxöf͹rÎókX0qr!ŽþY»…E7éI^±>æªåËóW(»Ò r0åõ©Ö‘¹åñtÞ^‰QQñ²As¼ù/ Dz´:à¬jþé^ÒÄÃ’Týƒè)…c2¸-SÑ徿T{`†ÞÏ—†ÉàäN€®B£›Rg “EINi5„ú4ªiÑ–ŸÍ«ºKçL‡L±õ»Fö–´º,,›cÞ$Š(J©ŒVí;Œèr¤W›ˆ&Ñöéú¤¡ñ±‚×—Žný—ÊÓÀ§t~F¾züÿ¿ç§aâvBm"/ÚñµêħœH²œçÔ£ˆWrOÄýEÆAÃQ¸ÑŒÜ!zÉMâÍ(=ž¨#.Ú ðá+òé ›*¸Ú«¯ztþ¶“Z?°~ê‡ÕcY#¤–’g®8ÿRÈâ.eÕc¸8W©45&‹dC«¤HпO~ÔBˆö˜ˆÞï(í^Üd»Œ(…ßSѰÏ~†ç‰(A#;§ŠdÂ]H¹21#ÀáÅüUu‰]™Òâõáíë²=“ª*_hùœcåÒ •èÅj_-è €ø‡4•5êgóÆ@B ³‚V7âI½”¤ v}ŸìG’B^ä ’6HL8Îb¢¡Ü'Å»÷œ¡iK¥šÅÒ¯ëÿ âçÍH­Ë%ò«‘$”Õ¬ŒS?g–t.'LÕ®%trP¡º’Þ|4MP ¾ÉH‘â:&ÜGvšHçMñèwKœ•É ˜œ'µä r+aöæ=Ô®ª^h»¦ÍN;轃«_(Ü º?kÙd#Å”‹Mª°¼‰‰+1Ž(‹\l€çW¾Fúë‹Ó›1MÒÞ3,A)ÿO\öñP ·‹ðWòD­œttDÉ—•c¤*‡o!±…*Îë0ežE˜Ñ»ÓY!‘™ào x)£½Ÿ…+¤%Jžýcõˆû‰a!±ÙGG‡×ÆÐæÌœj‘M¿‰×š›P<ÄP³ÎÆi›é¬/ïHî¥ÎÿJ»"_}ýú‡xgáøÝ”4â.I‘RŒ>Ïßun²ƒ¨ê…:Е·Œd9,ÖTÃþT¡’F}§`Z•.¸§ B¹Ý[Å÷ƒJ!3Î /±¨~æ}û‡¤ó IW#&ä’ÆXÍ›nË ­ÜäÇjH]ÆÔ‹ñ·îà¦×x9ðÕïÊïÞð£l«ïL¨ øËx•±ó,¸—3ãæëÛmuÍs’Ÿ„À¹aÏPÔµUA›®xoóð‘r /ÂtšÄCÕ0 û‚Ž`[ g ̘éíø4âx«äÐlg¤ÒW7¬Kùò‡@ ÿ$rfû ëwɦ?÷—[òø3ÅJòüÕ)ÝëMŸ WvÕÝŒÌx=®°{µÕ2æÉÝܸþŠ(Z2cîTÛ ”“¡/ïfŒæÈNˆéÓeëñT‰ôò)Fâc¤°m³¦H’:Baä´.¤4 ÀuKb'IHëÎH²ØuÈêYÈFÅ>֪㡃°ÿýÛÍÎáoâöi"÷—«g¸e¡O¤vî¤tòÐoÇoN&FD8½S…çÆc§¤èô;+Òž1Ýf«®ÇJ©l´â©´aœWb+$ E¿,¯þ£®õëL¿  ÑË\Â' 9ŠŒ&S ëÓÒ)µ‹Qwy)GýÂVô]u_ÄéRñUÿa[„¦?ˆtÅÙ~_‡¥5ò»Ÿ  ”,®Tìï'0:äXØÕÅÙîx¡¾šIçc¨Pž·²õ Ž[6PÛ0üÛ1À ¼È*:Ì´Ú¡V¼†^'±C¸ ¯ kÓüª`˜R=~ AtC- £+ƇEmµá$äØ ¶ÆÆy¥\È“—¬g¸þ8¯®*t¼ŠEÑ%"t<š·&¢_ä¥-ºì åõ]ôI›aB¾hÐGÀÁnÁXâPâ½ –Ó’”»¹í©t©ýr´ëæàY1P€šC2ZÝmþŽ>´È(dO^‡•y+!ZTDPÎ5n‰Ó–=–öÒ]p4rÐ󵮌”¢.8—×$þº“îþpo”/É-®ßœŽa¸f=ÓöÖ ?|/«øa6~Òßéó>K¤ÕI§gÒ}‡:ý, á×îº\åüè˜W×.»l%¯¸f/|°(­¢’î¸+­Ûjë¶ÚA T¡_)¿I¬MPTo¬{¯?-ÞkÊ3Öm¡”ï¨ÖNæaB¥¦'ècŒ¹I§>®5r?S¦ºp'q „°›­bC®¥¯ÁîÙ]5i# i­¹Q«¯H) ‡dUf#ÙsØØ(tb;3]Rò>׿ÑÍÊþ8AƸ ŠÒÆjƒ3‡ø•÷D8‡Ü¦þÝ™†.mþIßmT'º©¨ÐWEìì|;½'|eD¶Q†Øð´Ê ÀÑ÷ì êÒ’(gjÛ±­«ã*ŒOä‚),,ß=Üû¡}!¤¬¼Ø‡h¯3v*¥ ‘ÅN*bÈ÷óÒlK}SÅ òw)Ûâ:jÄ%nS™çÝ tb¨SÁ»rNz¹ŠP‰×^õ7a|mv&0×é‚ݺsòìÔÒ´îìÖ}a /ÖÕÃèË©„ù¯4^j¡ ™yBhÖGç^×ñjÌwc]£bÍúˆËpûó,¡IÕ QS¦H¡åЪ+þÊÐIJFÄ€6Ì]ØMš{þrª&‡ö}¼÷מòÖ½3=aok¶í³ÞR¢E*m ph7ð=( ®S¾´€…uî+%q/Ø>»Ü6`['©~UÚã)Ìv©¯…éø›Xà±ïYÖºf³×¸¯Ê´e¤Ro£‹Šé–žÓ ~.Èt^<'/*™ˆ—=˜\6Ë#'n@G×(šR* ¦Þ_šä=yOvnU ß¢‡”ßIÌÆ1“/9~Á, Æá'žä% Ò8ÚóùÚ‘"Xœ Kö# äÚ(E}I럞Q\¿$ÚÎ6}×=œëd<»NÖÉ©ksqüš;¿»5ãY¤–: v|c´Om˜KcêBŠ•ƒõírŠó( þ¤r\üÂ,G‹Ø»Œúu\ („U%Mì9+HlUz¢Í×RrdZUÞ®¾pG|ÑÒã¶°­zj[,ä/5 ¥–à¬v HfdùÚÑz}[ÜŒ-uÈ4™mkÎDÝ£.Úî ÿþ¦Ï°®ÿ骠»ï´…nÙ°¯©*fÜ hȱž}n„?spe(>ÍéºØ¯VƒåÖêñ#éï(fQÅ«gn|ÙgÐsÀFš_áÿ­¡è ûPR}lg— øm4<é;Ä*ˆs_j@ÌUxØF줫×ð¼_KŒìOÁ¤ÝݳìÑðsàŽ8žþº.;÷<@Ø™8ÖÃSàÚ›Œ3Wê×z2}höxïéO9½fE# lóè‹´Ù¯M­Eh%ñÚºãÛ„ÁùZN†¡u0ƒYc¶ÃdìBä÷8«®ˆÌ |§ÿ$o¶ö4Ù÷™ú™Î왊ßptG\ §”4,Œ xfãâºñK#[‹œæTÏñ0},Ii gò/â8 ¡ÒU[q¤÷l$»”ÞÕ;=ë³Ìžê-}öÒ8ºŒ–O«Võ–Ý¢@½N/x©1á#…ü4•$k_Eö2÷Î]kt<üüa÷šw}Ãì üC=ÓfŸã(Õ¾£.®Øô@ðÑÂÓ¯û5ª{©'[iAUß1`îžûÌ·gï8,B;á’õ ÞWÊH}ÚbÒvôÜ gŸ’ÁTçº÷ÿ²@øFn©,ûèŠ&M¡ÁJT¸¿ó.ú]X²áP%RpS++ycñwqšPöòžß¿ÂiW³6§%ñÄ-”"%ìZùNÁàƒ“ßS'rªžùÿ€9^¦Ït Ÿõ´ LŠǽ¨['ÈçóÍžÀIÏm?g˜}&|Kð/[5A+ÑÇ™ Õ¿ Oc×Kv­¼PZ€F#¬3ˆ°N©G’í4Zð^PIl#"-UtC'täM¢_¯zá[[…-ºŽ³ìÉò©Ÿ'ËK6ATêiÛ”Ã,` C5ý'gYˆ—-¦FT}R…‚`‹ $™Ç¾³"/Zéæc(®¾Ý˽%®Yøwû ‡®‚Îz‰ž°eÍ¿f)o³Ç8Óå‘Àýn€¶bçOL”L¿N¤Ü©|«lh&4l • §ç+œr×ËjDp4‰Ñ›iØÍ3‘”/g$Ñ %:Ó~°õÎÈ-Î*‡2¡7ðâ¤îàÿaÜPrå§h¤&íëgK»Ç*qa&ÄÜíİÖïúÁ-aúŒ/`S·&¢Of:tãêñGª0è¬<šáé¿%ãÈCYÆšotßpά`’†­›I_SÄ¿&öíâbè¸8e)®ÉÈ¢¢µcîÏ\Hr.I{@tQý¬4öÊx¸Xžh/P—©;]f1!Hºdly³æONÜ”‡‡ûÕY»‰¿9ö I<[­Y¾)s¹.O¡^•˜—=›ÏªÕînŽÍ®Qâ²s½X_âÇ@gŽÚWšEÅù„~Ý/¡U1Òéo|öC˜Q uä×G $$ˆá‚É[s»šËÒ°¼Ó‘DN€…ëI)ÙC6.á¨Ã Uti!ìEça'±WBü Jº…²mð~ç-ºî¾_½M$¢AúÏW”ôdñàõÜüŽÄ0$.b[dSÒ£ý}~·S–¤ìà¢RvC F ’{Q‘h€e¼æ>cÑᆧB{Ê×¢÷Ïw™ä@­0h³ ×û9"&ß§ëf wžq 4àðwÕmäùýº!œàæ³ä¹È÷³[ÅÅ‘Ëp¾AD_!Š…ïøÇÑ`œ£^™ª=!·ãfÍFÏe‡ã-4û Œ0m Iðó¹”d­«žšpücô‘yI—l‚sCüó!‘ŒkÙ@ÑÆ]о¡ÎG—šÂ ¡‰Ñ¥·Óíp©·ƒÞ!Þɿҡ¥ßiDˆV±Q ³ú tQOƒƒtãµ¾“&ï3xµšA„dŠ_m¿ ðœs /Á™©BSEyÌIȤw÷èæ¹»Á¾E«àQìß/@PØuäU,Ö¤ Ñqk„½2]·sf6·™]ĬMPY25 2ÎU³ÙµwcªX ö}w!4Ò¬C¢Ãä²,þŸ½c c‘Ðìgƒ.¿&Ê«B¤8߬—ÊyZ²µ¡jù6šÈQžÚ„ó¼ý‹Ðj¹ýi…±†$ŸÏ(GDu™u9 ’fCîèF>ÉŒø¼èÙ-Qióáü z%œ¼"ÜnHe «6ãQ’+Qûí¦Xº½ â—}`Ÿý¾ÌÄÌùh´v{*§‹æÀýçûªa™š-YðÒkhe¨'I»ÔÜÊqE…ž+刋\¨dcWç¶È12º•€›ë–¤î)¸hô9ŸFUà;b”n„m¹^MÁ—U²»Ac)u¡ç­…&ctŸâ8…¦ô\Šâ¤¡+‰wsá^¤ 0yWVÀOPþ§äeÊÝs,]c}nûÅÆØ©²ý¸Bëä9âÇæZHæÞ.KøŒe5%É}G¯"ÅÒJcµ°’ýæä{ ­m¼+lWiòŸoHSºbšÀh{Üâ¤÷GŠ ÆÝ„¤ëÿ@\1Vh§©[É>>ú—w¢Q… ¦» ‘9$£úbÞSÞ«ïUÂôí;<éVC,Ù§iÏ/->±”ØdúùÂü5k2iðÁ„¢ÁúããevµSÄÄ}üuYz*‘ŒÌ&áÇß÷cóåkÚùðÉM!_8¨e…º†ðíX[&Ö‘Åʨz-b°7¤`x8 ¶eÀ) ¶¾Ø°¨YítýY 5@)ŒE¡༼‹hä„ìðewèìÕà½DbПدåx“/)&ËÙŸq»ç‹ÄÕBžØ§§,›­ôj»2IËÅn[žlOt §¯‹áüõá°XþuÓ ñyd¨Ú䤂[-o "\ݪcd£@z_Ÿ7ÍsÙå xHnìÈ¡‘òȳ'M+>™::;zhpܰTÂ÷¸BfmŽéôØê U€ThµŽáèÏÇ…ýIMÐ zvž/°_£p¦¶2"(äsì«91Û&…³U§©£ÏÞ³×…)¾&Fº°¬òù%Ù0ß×>“ìwS`U>¦ï.>{¯eñ´¯tÖo°wE¦ GãAc`Š·1ç×QÙë ç¹8»ÚoYèYSCvhÅZ2m£ßh»vƆšu¥2Uã~ !39›øs•™•²áu¼u±ñÐ(¡ŠZæ’MÖ×û—u…ã ‹<×hr—æÿ\ Äó+k(º-|£Á2àyî¸Ì¼¶”ýý9SÝÆ…^ ùZÚðïÍ_£{9óÄ”ÝT­Ê TÀןÍpÔ~ál½Õêz…”¡)ãNU ‰øGGô¯QÜÝÚù˜ˆsƒŽ¸êÑù^¤‘㟠’\’õëíd"éD³¶-SKi‹^•@v7 â%ã9o‹ßû‚'õ4®fÿ# aAÏÊ÷¾çÞ’¹ë¢¶Qæo´÷fTߣ»oO%ûȦà‘À`¼¬)I—Õ ‚XœÈ‹íZþËOÅ¥cÂ·Ø k„=q"Ïlxr‡$?mpío8Ù¾+ÛHBÄ’‚ý)n€ÌݨàÊí5F-H°‚bÞŽ³Ù ¹fAhôÁÊ´[ä?‹Óù8s¦t¦Ÿ.ăðû…í„ìºû£]›`aÿÊо=‹Ø0ÝíæhP†Ó ¢ $òL>ÚúØØfâOY:ÁœŒ{?´u%Ì =æ´ñ»e‘Ú²Ÿ̪WòèT·ä£Ã1¦w¬®`Èw¾w»6«Xv¶*_íÂÍRòïp}ü­}B¨ÆþXlòR#r­é°¿³Mט£ ‡ÑæV÷v½T–˜µX¶Šyžg¾Aí@ÀÔ®–ê®B…Ãl }€Gèý˜Ñ7eìïÌJ*e5ÀËñª¡lóQþìÎ;neGˆ€ªÊËÌ;’Ã!QïYì4Ô±$ÄÔˆ®â­AIetN"F«úLŽù”êÙ=H¬á•úþ!Ù-¸ç¡Û¯žÔùÙwXž’x,ÔPzKl€œmáEªáùrŒqý64œàkhQ”AÉ™–/¶… B[GîH(êšá^ð ”iÎtø¨ï öpØ6~èVÞ&fôcâŠ÷šýaÅÞÇ4¦ŸèæßP¥²¡;h¶ä‘!ï_ÿkð(=-3Š$)Z\K"äãйN¯¯N‘„ãízAf…i{\•ÎÃõO†ÃòæjÇ 6 Ì+™@zN§žöhÙÌ´‰Ëƒ^ªE+o€xð9ÉÊCÞ„hD¯÷×#Vrr?}¦ç“YW“øÑ‚êh†­¥Òá{28Ÿ1¹1òò®ÀšÇò ~ÚfmŒ2*W©~NךÕð||½‡‹ðJÓBœ²‹Y¼âªèÁ>ïÈÚ²B­4ôŠ–T´°Öζº6ŠÊ£ïÖ”Öë$^öò{up¢ßišÌ{ =À¹â,Ê94ñADµ8œ…yÏù nŠ E´‡ûª™›…:vÅ–b“êx®+ê•·åcšãæêKq°V¸W…fí{øiµ¡0LÊB -挰ë?®ºƒâ9âdÐü5—!pJ(qc[U™Ã^8­mMkøò Ö–Ôh€ÆícWžÄZ}O¥»ÈSùœ ë§œÒæ>òPÒÓ£º‰ºù÷ L´¬Œþ¿â •bnOˆ‡À5—‡&“°/FŠ) 2´)¦uÖsx„Tš|ÎP(à~(¨VCY˽hšì¸¾2™‡M9Wœ0º°ìà)19'] hÅÃU?´Mï"™½|(xbÛÄ_Q, è‘`½ð…=c“ ^׺½Ö-U~4-èÓ‡ ¹GñH#/ãÄ i€Wn >ÐÎÛV×O¥š3ƒ0kÓ½=‡/›rU°% _x2k¹s|ÁËPÉüкS5ÝS¿)•)˜û[û~B«PÆ%ì ©ä?‡ `“½FqS]±§¨@SE3£ ñöJöѲm¯‘É—e a¶Óö–7ÍÓBâÓPÖ°ŽDùÅI{‘¡¿ 2ÔLãÒ Ã¨Xà˧ÂjCk“Q£s[éìÀå³ ™5ÎC5~ ¬§[¾c»6Ÿ#£é¾ÉÀÙ¿  @EÙhÆ•+qÎÖ,娨%Ý0h÷Ú¯<®³€¶Imbp¶¡´> x¹Â•y2¯Ô;,ºX³ÈÒ¾Íw•aaH•퓜®gÎEçCˆ;,PQ€ø_‹„hÎ?ØëŽre¤÷ÙyÇÁœ7Ëÿ6¶}3鈞Ôö‚©ÿ`½…榥m2KCÚ‚ñë¿Õæ.,ž…ÍÿûNÑX{AIl*PŠ,³ÉB%pLiXȧÇÛWžøc—І¥zPÌÐÊ­ëV> KôT·Â†O¹»¿³™†bä][ZýÖõÂÊ¿±÷ñ:UúŒB,­Ý–ÊM ýlš´ùPÊ|)¤D8½uè¯}å6û’¯y¸`CR÷#ao'ho䉨Û\–gç¯m$q*Ç&¨Îà<ò`¢¥Ôž8Ô=ð£Z™‘šFwi׬q³4¯3`dbºT¯Z’ô‘ë9A7”M’Ù$oÝ$·4 òOrD0KfíŸTmÝ*^L»®Ý’ …ý>¼Áy±6ö‹4]Õy/>tš© aâ!¾Ì‹È–8â Ý·¬w승G+úŸÊx,Ѷ²ˆä¶!®>bz«hÚ`[}P˜`ú‚D‡8Döø½\#±m#¨Úï§‘,I-ˆ—kâÄøûƒöµ–oW»XWв^6ૼ´á '2Od ¯,Õᡊ1,; ÊÔ3Hri:ó¥Á‰T!g”i–ËóGþ{ÍÙ0z NÌÓ ß¼žö¾”ç&(õ2é4O½½ ÿ1Ï„;p›_É×s¯?^ŒÒÆ!`9´ÃÆ J-¾óñˆÍ» £R4 z¾Âh¦e*?êcÔõl• ·6rn¶ÞDè3rLʶ–Èæê0<ÄÇn:è]¹‰ŠxÛzÖn2T’ÆõWKJ÷~3®’æý’>9HÓ©ÛMæ5³ˆmÐ:`Ý’!¬K;z}…4 <¾‚ˆîQ £¯/–:~¯_¿k.áÅ$ˆ! AüÍÅH˜Ü,“Z†×A}¥k/qK©dµf›è(ƒùFÆø5\¡üÐywG2¶ìð°2 ¢n•g»_ …Æ!½*A‘†;ÉkÏQê.UWÜNxA×l¹s( KrµÃ Γ×@ílÚWJúë yKðR‹ÄQÿË£˜·x"k‰èÚ02›Ò*êÊÈÿóçB6…~û_#XESP]a1¦„¡E¦5Ož’­¥ð˜Æ‹4³õù"¸Õ¹«ÓÛŸ¼YíKž&?iëÿºÆIVÕI8‘j#ä’E¨ÒÎÈš¼—7„'ë/E|¯ÌÇ 3ÚœKÈ=g“CÝØ{ɦ¦"*ª)„%‰ËH= ËÙXv\#ƒ~lˆH¶çïôecðƒ)“â‚j¾¯[õº­ÃŸGŸ|Êg‚¼cFÏ#oÖ?û²Öèƒî~K™'9ð誴µJ¿È0„Ùk·ÖöžÅlƒÖ&J·K¢8äI‚"h¼‚3î$X÷D>9M~_×,#¨‘*Åóú8X¥S!«M³™¹³•d…þD“+@·j øÞP›ÒS EGy”ž1ùÙd!)´·VûÍYd*Űä/›mK}ŒÍ„-Ô?ÈóHÇ;L~ƒŽ÷¨Áç‘™"û ":*B•>ÏÿJöŸ‰á1ZD–Ÿ^ü¿O&àülãY‰ v¢!q,î/ê³&mÝ;»úþxYüx×7ûª/èb·}IêZÚˆ°ü,Š37òÀfj|7§Léá⿱SÙVÀH²Ë»ª§(ß8‰R{‹Y¡ÉëûôÑåLwµõÌ fSæpFÑ;±#¨Dbr±%>Îô¶ˆMý× fzy²›®â¿5~¸+'V£ÁÂqŠ˜)Ò«f·8v ÿ.- 0X'IbÀµŽ1µ¨3Ê8âÁM+†Çsv+hØA~`™G-žoà“µâ\u§¦lÇ#™ý„ˆ„O†²ÈÐ?¾b®ñ„µ¯÷R¼ÏEaÊx G°Þj¿§Öü¤£ÉõmáU{4Ów¾„1öÌ0Ãß›$Š4L®Õ•ï^-SÖ媮fía ÖCÑ«R®¹>™?þ®C¹÷Fa³ìÞD3ç:áöÆ’:Ùì#´fòçr´tÅ«oñvAç„ ü‰&`âÍ29‹z“%6Ãô`¼À",$#î˜Ý‰â8×ß-ài[9€ãI{ó5nÉàö‰WOÊÖÝ.¿zü¥{1À \\þæ²Î– ·§ÈS/¢Ûou>BJ;±c<‹-*qûÉpÓƒ-Õ¹GÙIQí¢©Ž®6î.êdÀÜÕ]Ý~aCq$ð{Ç—œ«Ç©à‹ÊC$]üB3{{5|l)ëÀï¿z“d™öêä™m…½EÕžV¡ÈÆ‹Ï{œ©q¬›p·õ"1ѵ Z‚üaÚ3 {îÄ×Ý¡M0’œÂrÀwF½*Dž«Åâr#ÌÀ9)'‡>¼BÏ ¿’AG‘ÞÎa%1MbÄ ß„è¼¯“x³Ì:ªAý†@ÏÂÇ .é:œH°}‘&»cñø4X¶Ðª¤(ýBª)"k¿ÇkµוB—%>ñúlÿùSÖo‚ ä-v8'Œ×o‹b.îáÙ2B<×?‘ÍÙºF1¿­¡Î@˜`e[÷À! –=« #Ô# ù1öíÿ‰‘ïKºVÖN$GK’v3¬j2¸ž@ìùP¬Ë,íV_é=}:/ÑèRÚ'WƒªØ²¤ìDV}X»VNŒÚT%ò¬(ª’²Ó6çOsŸã&tÎŽÅ­@5X×3ÒvåCÉ'—£øcÞ SD_ËhÎÄkÒßÛÏþ<>™0KZ´º¦û¼¬ÿ«ç}¢‚ªúž–´y¾ò8)lïz¶›f®a_÷XšXÙh‰3ˆ_OZ4J|¯Øi2mØ®• ‰çÊg“åé]bô,¨MjüÁªøO€S\zMÅø;ÇOÃ(…§kôD„­ŽKÐÒ÷µ¯¡gÍ aV¡_ÿNdæ;‘*S,Í>L4XfË6o‚Û‘t²ŸØÌÕù˜G]æ%Õ¶°4[»¹íD'Èü5@^æÁýÝÚAùï•RØ·ùYWX39!½Ÿ^5]òž;ËáI¿)¿ªâÊû!ð4®ºcÿ·c±{zŒ5*½Â‘ ±ò5§‹€÷bôt:œHw{Áå?ÂQ„Ï ¬v{àü@—Ç"ž1©‹ÇN[¾*Õ*}éûAöF¼nÌ|oÿ‚öñháÀÙåžTÜ1.ÔÿâÕ…e'wŠë%­o)f¦íòwg\!>%Œç–¨LZ€ŸUY1‘Có–QZÝhß‘Ü)Ãb¾a4AMh‰¯³bNî—0ä"®z³$Él ÐÖæfdJê1Û«HËz¶bwÏ~d?n;ç’׿öIuQ÷hiZòv‹WÛ‚L‡ÔÖb·œÝ`“'¾r`ޝÔ8¤Ç á/ ëhT9É\§j•s2çFòú ¸¶¥^ÞSØèt†cJŒJAÇ ‘5•€¡¨Ý7[”ê?¥Ó¡êŽû¥ÄÛø žš¤¸Ý¹^}ìíìÈôRBtŽ{#<.ÇÍÿ<¹]eíReÆÜóÊŽÔf›)}g1RŒ86Ë[KbÔb˜G:MvÃÀ½LFì›í\¥3³$"LñFì7ú¼vÚ¯rF·ãËv¬‘™¦‘Üxmê\»ÝÇ2Ž mß‹ENÒœ/ß ¥–¹!Â{Ÿ™uÖœ?ÇÖý¾h7èÅgµºl›jlÛý7°¢¯pYA”–äBbÚ½+mànVwÚEdO1û઩‘ym%\Á@£tÎRoˆŸØbÔë!8œA˜æñ,^¯º§–ü™æ”Õϱ­dUÄìÏI“*†.õAˆflÍ7WGC×^Gº ºko³ÝqÏ­I˜:c­½P`ãµKåTÏ?ß„¬•Bß ŽcHÚàNˆxF e»åùjŒ†Ä"ð-cñ™š`È}þ U’‘¾Ûb€uÇÔ_¿‡i¸ ö?[ÑoÅãcy!”­m›ª”ib.µ$fO\®u˜$ŸWyåfd¿äÛ‘kÄYú*‘àQ€zŸ¿AæØ9è:±„óÂÔùT¾®¾5Û³Ç:[pNy¡˜ÄÒ §ÎBǬ¯+‰M¥ù¤Ýë|CE^žbæÉ©Gïc¤M3e990læ“k´'»Îs}½°iÑÜï?‰WªîÞ"žÓ*¿™,¹²6Á|ÁÐ[â2#Wæ®öªL?Å6T̨p¶A|&¾äŠÞPt½®Ïm˜Žµa| IawKa(rZvø.z—©”bU Y(°ò%¹×~Qôiø¥RL@Ûʬqa»n2ªJç8² ßkŪC .ö yžaÌ×ì.ÕÙgœZ¸nº ë9SⓈ5ÔOêE¥^L„Px³ZÝž¸ Bö$ù¡iß‚„‚“º‡wáh¿ðBû~M š´Ëó—µV ¹¯®¾ü1DFê¹ !øèYÊ ×o¿—Hsp<ç±°@öZnネó«¿l¼ž–X±º-½^ã2 ( o;¬³»ûwÉJ:–^ö:M²Ÿ…8A~Yzg­ß–mÌ“£E¬º.ÊGËh÷Öˆƒ6³ó ÀL[µÝìYÅs?$¸Žðƒÿ_§¥dÍm+>‚¾¾­ XOdR%]ršÀm¥XOÒè#R5øé¤yÑ|+ß–O¦?ç!Žßj€ÐÈ9ïÊ6Ñ, />Ï‹9ýzÓý§$‹üfb{¥%)·Å2_úQ Ië£äú@0vâYO¼Ðh[Šõin .QŠöt ùßÖ ‹óQôÖ_7¶Ïž{nۉʻiÆrà1qÎ…×:ž ÐÅüÓ¨F0±T°}¶Ïbÿ“W/õ]œÆDL[ˆîZ Ë„Ø;¥÷£x5²e*oÆmè0¢Ã£eŸ‘BÐ?1§É¦ŒX †":~µ´˜Öe>VdβŸ+4J>I+²Q‚ÚK¹l…ÒÐÔöciJ– ùƒ*Cô»$Ì/f@šó™ &žS2AäOê!r½Å騆™ô+*Õÿ̉“±™±]4ÿ„Vö Š“ºÛYIµºÆéª" Ýƒ€«ž¢k² mî@̵opó„ I -!Ôà×ú–ù'ĵl1h™nԀΠðð+œ†µE64©¸bbAáÀ†9žZë‘ÉȦŸùP[ÝôE«Žø¥¶Jø´0 µBD¤ ÀÝ]7Î$¤ aïÑ}Ñì|ÛàÕ™R$2ëBg?âûƒ1a©us×±(Vh¿©’'L3Öûøc~‚ôÖÞ¦èbú —ÅÜ -PÐ ×U¿ø©J™'¦‹c°jÓÚuázL¥qà “/à:äФ<æ„&Âíá.Ý×&[ù/$$ùÙ@”Äà6"Kë8—A 1¹wH³¢ia¸~øÀ•æÔA¶ã%y. 0–ïq±æ×û’b»Ôñ¢§ r‹Z ÌêƒÃã*%¤¶©Þ„Úúéý/Vƒ Š;÷ª_o …—ðìÊlZfYU9Oö:¿EŽš¶Ì$¦N®V¯÷ƒ‚Ç1 üWG$jÞ=§‡=ÞøgéŽÚ‡õ€£»3÷l8;ÒŸ|E¯×à :¾íì¬] )¦V¦Ruú5÷({AIÛ­Ä>Zwƒ©e1{¢³sÂ.-S4˜ÚijÕµkþÈ#*KϨ[‘u™NŒ%X†ÿ#¹ÛôgÙpˆÙcC UŒ3¶Ñæ¡´Ü’3ïj(÷7([yÑÄû`<°!ÝÉ:¸ò\ÌSÄëÃtæË@Çû:3œ\Õ—–6P {}Aƒ²+j|j–ñ,ʪu‘›){’Í,ÛøÈ¯…,¡{Õ§l¸{)=¨fXÞŠ +â,Sî#DÙÏòÝfW][óvÍó念aúŸZ—'[ð.¦ñ€¸ü:_c¾VnÝM\H«m S'°u9|$”`›mÅuš]©Ë·$ãB'D(‚Ò&J €‰AÀHÃ`©Ø­É«Ú†ACUË 2Ùx_—0Êé,{|~+ÖˆîÊ_ñë4‚ýe¾[\²¯[x€"\Ù>>B¹-÷ù”÷.¾ß©b$Г¾÷s½5—é×@Í¢NÇ%eXâÍ+”§¿ú´¸ì¤fš7éÈý—Áh6¬#ÙÉU çW˜3ñ5{^q´­.› ý7ãa_ù¹ÂLØS”i œÌ0ØiªñzOW6+&ýIílBÆÞË2~š½·1WIú¡øÖ½y 0+øÔ0–Î>s6²¡:3¾(ïÒ&G(…˳¹®§Õ5…5…É7/Tû¨°9LޤUÍ›©ê™EBTC@Å[Kdˆ¥íUÙs-ûìæ3ð&ÍnÀJ²sJ÷ëzV*Oî‘úÃwt1yœ)׋26ß¶ÅvúÉ^·­{¶µ,’9àýaØ™ LšÜ,3ê#ë”!`„ ãkE»‘Ç õðÌ8 ½ÆÖ@Â{›Óm‰sz^^ÌÛƒJÉyd­Tüŧý–'…ÇðÊéÌmVV»Ê"©\ZµK}Ï!³“ay°B`Zé.ù ¼%A8“ïØý_õÇko$§p¼âô¿8!®9T #Zçìèâ{^™2Ñ •5è]Ç ad*±÷ôh¶(e’Ù1°_BqVÑ­ø.¸+ôá+#p6ÆÇV™¬‘oB-ÇÁPÊ€¿e¼zÿ¶ìºH(}^IÍØ#©ñõïRù9AZç¨>¼û¸2ÕqãŒ\¡ŽhÑÍrHÞ¢¦F`h®8DN&ÙŒVŽý¢¿Ãò¾æ,Þ}Eèºv‚6Øx¬Ë¹^žÜOqK ¡è‡rÛçbáyAPø;m…5j‘×Ài`׈³NST¿µzÖ4Ú½v¿ô°ªË½žuîÖyai>‘ÐÎ÷$ý}9"öUëË¢\˜—¾Vþö€­‚+ };!§ ‹^¥ š±æx7q0·ëo¡¯ûu¯ÓÏØ÷Ÿ¯ã)clÝUK†‘ÎQgœl)úUeë…ÊÚ"Êx§J`·¦Tc  •RÝâ0ÂŽ7µÅÚ6.ˆáÄʲÃjY­+Ýȇ0kÎø|`)Ð÷DÎñ¢y5M|þ$8[eV³ §­0Vl%Óó{FÚ½¡p”)T¬_2(«JÃ]{ÕQ?Ÿ%-Á¤×f/žsGÃã—˜=¾tmµf¿Ô|§BX@·AÑw~º• :À]×V™OIêûšW()ѼÜ[1nø”Ḿ¢h$ëÕ€ ˆ¡š/¬³zG£™0~ÿZ%Cîä 8ÙöX¨w„ò¿ÌÁ±½Máòƃ^q¤ A§+:zîiHCa”ÔêU笵ȑuþúʵ…_L˜'•èmïÂnB?TÒŸ—B€ú¶–ˆgMøQDש^Æv©¥%S Û´•F'úÀ—s’œÁÐg!ø±£âìĪӷ¢6#TNi›YÃÿB£¾Åvö7}w?xÄîÌ{·4~0z¡Á¾ªè`WF oÇQed Qß/• ~K'iT {&öT÷q÷Nœ2sÁNŠ`ÏŽß§¬XyÞw{•ÿ)°H™I»|”'\€6ñÂôƒ¨ 9kô‡­j%˜z“èo%%³CÝÂùÍJJRÄ„.xŽîÅÑqjrx³±Ê Å/OŠ=ͼOÁ´Ž8:éÆDÓî6•çéB^zd§8 ×’°IÚ“®ÅD†Ÿç}ŽOÎH‰á5¬a ¶­ù5Eˆ.h8XÉçmÖ7êã˜jðÖ ‰ «ëUáèÜ'™p8Nn;›pþ^t¢9}v¨}—sI§K¶]bWP”ÒC@ìIVq}§ÃŒ‚h*€©†ÜŠƒ‚E,^¯µtM›xCaÕ‹Èðê¨f¡å0^ÈÉUÔ€OóY¾®ø‹D†k¥Ö\ýrýÁÑñ.Fôm²Å[}Ò¶ ¨gÏ|Bq Òà—Z©ÐÒÐrêÃsŒÙ ·¯§¾Ðëv—܆RÄnT \ÈËç wý«Ú$øÙ_¥¹,’ Z9høØj„õ…™Ódá% ÇÏŽÖ÷>E94¬ˆ­îðŽóÎEë2„ ¨€3Òþ>)~›ñùxF¥ÐÍ…´'†ØãVÛMqΔnY~kÂ$“¾8g©®re;£½Ï;ÂS0Ú̦—*Ë”Z¾ß¶ÄZhAÎÄëÕ…ÙÊÑ7Ž[í`“ š‡±\_°ÅÉÆ[z©ÿ0Ö†'ý¬7þ{í~’²Ô˜ç¨Í.=.o¤¿P9*^·ÐÛ0žh˜ÑJÝôVDœŸî§²ò”5ƃ} ?n:¥[ñ.Œdߘ üÉCvù´t¤RĽT¶×H8Á€v±$;)Q;þ¤›'©A”«N““á÷lBJCk6ÔYÒÁã;ëc/6¡´ŽE6@e&©‚ަ>’êTòWe²ã¨5A³É‹Së» ÿöG6¢¢–²È\['· ûcÐÂÕ,Þ¸‘º¾ã©‹ðY S]ð7(hUž“ò€ó44Ëÿ¸€‰ -P@C9{ÂóÙ ˜ ·ŽA¶J‹ PZOÎEBÊäL|ÿÅŒÿ€´YÃCsØÖÓ߯ýí´ósv\9TÚÂÑoä/ƒSRS5jeÚô«Š1VU' ޔLjÌOäMð‚Í?Úu‰¨;Ï Ý$Ã˪™¾”íÑWˆÚ.7^ï_® ê«Ì8ëqZ}gù]N)ŽÉÅ]‹ 6ÜN×±ÄDxx'ÃÑp"É-¹X•T}-íÂ܇ù+º‚A¢n åž (0Aɵôv A §R‘|–‘í^-âñè«nÈR)ÖIIi4È?u׳³æÊ¢Ð)+U.CoDôšÉÑÛ¢ÿˆŒ ®07,ÆZÈΗÁàðWDÙ”˜B©Ý£jº§g®Uµx©.{'yÉWPJN‹GX(æÁ»/Vi¯»!)p»8œ©o>Ò4k§¢C,ÅO@)V×sçÑù#¶WA_†¥Ä7ι@˜#Óº_ 6Ä Gú¦ÜR-÷e”%ʨD†7¾2RQ•JpÐCˆdSÇÔl=p=ð¾˜ÐÀœõ&9vX‰çDz)ÊÈû8æÈ€v~GAå‹Àšæi[Zw* Y{W¥˜þªS/@F’{IqYï‰Ìó&òM-$#\¬±cøÇ>0¢éêäï–st¡ú@–sÙ~`¦HØXn§–5¼M‡ì‰5ðF":Ú#k ±ør½½!À‚ e#zÞ5üÿˆ]‡†Š¼#7ô`HÞ(' ¸n5:0ƒÜ´çDŒi¼Ä=ø²’f| wPߢ-$Œ4y!MCÿ[Fco¢=ýj6T¼N¥Kk?‡q,–è¨a‹bCÒÁ9WÙqúÀ Å÷…xEGc½ÐײУt1¸r\Ì|“hpH<Ï…ª=Œ+ú–„—˜fH5”É2Ûèô²8o7âü J)åÜiÑZ“7Â'†pÒ“S6³âãþ¥ú:‰€‚ñ£R=`Ó}8Іd½«ðÏ2®8*r†G9àX˜¦½>ä±üï?×è±ìw·¸œ–”Œ’Á  .¦FHê™ÎšhÄj=(éŽý<îˆçP ó“­¥ Ÿ´‘fA£•“Ñ0œIÉÞæ¿„Gö̪¹ {%lyP7÷¾q2ª–p¸LŸ¶É$ö¤b÷é—D*÷*WZGÜE_Öwá"(é'|º±ÂVD~°)óp¯·"Ãù)Úû¬‚kÒ¡ Q=r­ñô¾HˠØÞ0%Â4ÅãnQû¹ÉªÃ­¸I" 7¡VÍ ðoþé~–=6¨÷¡ŽÁá*G%ýÍÇÈ÷ÞÑk··éh矦\ LøVy®‹büÒ+Õlzš$9oQ :Ç0fÛ5eÂ…‰¶E‘á¸xv4Qø×G½àáôbÙåBö08@ý‹ÛxZrºž‚$þ|ãDÙÙFiü‚ÉÎõ·¹þ¶,!D4Ã!ßÕ‚$å” +ÆÝGš|jŸK=N~P| ¼W@Rµß½ýuŸ{ éRüá“ZùðÚ#^Ë—12T¿Üù”çD¶åm@@’ù8zèp¹VkðJI nFåêº"¤9g}´þU:,ž¢7ââÖ¤è!ê>xs#EU.¨<ÀÛs¾—tqúDqj&CtõÏB9²Œäù9ÂCa[ÓÚ'BÉ"!,-ÃóÚ¡ú”o‹:*‘˾w®ƒÈ*zoʆ»¿cç1rêÆÑpùØ’#ð"&-°Ç"çã^rÆó…¼±U¹‚P•PäBÓ8úÔ`›Z« HÜ¥#)УÉ_Å÷ÿ1LŽ€ëT÷º7H°‹¿,^}ÕÐy„»úöï×JäP u¦i#⦊¡<éLóÇ("ኀV“IÏâ–[þ‘yù¾œ± ~ÙŠp /{ª]8ΰ63å1suY@‰¼Þ ‡Èú¿ ꀙÝ]7õ®M¶+@€4¬‘=–Ùüì7©Q›†v½A³Û(3ÿÙÒEÎjѾÕÓ ª=ìÒéÀCV6Tñë¢X×v5EôA•Ʋ5ç81YRü ‘æ‘im\õ”h1hNLb+} (DXìÁÍtëü‰<ôмUo>ßQ+q!ýðSTKÌ‘¡s…iœZÙ:Êþî:﹋wÜx™Yk¶ 1gâääšB•ät17o'Ù5BÚ÷'ŠÂ[ÕYG,:‚\Ÿô~’ vZ “"¡A}záAS ÀS GY°8d¾‡ü»4«nßáöîp¨?!¤Eý½ZM/bgõ ?£Y(9ôN8À…!ŽH®Ñ:,;sà´nµLÜÓ¹ ¾ù¸ Ѓs³Éø%õΚ*bÇÁ0/ Ít• ß8•¼ØÓ*8¸¨ÿŒWðfÑVòòª¶8 ¤v¶Ã(½xµS•mz›à‘L‹l2@‡úK{dâ@³„qct[+MÝÁÈ÷Ö—bzLl8-ÐÀ-…ÿAìÀmÀbkÙxMòøºá·¸Ó_¨úrý—õ‚¡â<\§ „ÔeieÒ?ó 4\Ùâß4¥M®»A a½hXI’Mµ²ØÁÁµÊw º‰‚zшUO³2̵‹WFàp–‘€'\goU‡mø,7ÐZw£»®©®O(’-¨Aõô ‡B´êyûÅ;#_lwŒÃµ{™dëiîO¼LÓçÿ¿“ÈZ5·C€äiâˆC­›Å®®wuù¸ÂÄn‚ì©§vŸ\QÉm¹åÂNÿ•ŠÌ¶\ÁÌ”´ Îñô1Þû\´¤'ªXYZu–#æÂwAÓ íǘmãÃwÆÈãZj˜Ui€½^>¦éÞÒÓï³U–†ç}°f«ÓÃ&èòÀùƒóÿ]å´¬Q§ú/ßQE¿OòÊ'cW¸s³Sû÷ P·þ+ËP¿ÈØ®¶t¢¬ó™Å2>–'’Q«ÛóµÕ×ÃìgÉœ\Ø÷ç|–K©–ÑN‡Öš‰va°Ž\¾UJñƒÕ`‰‡œŽ4NÌ(ŠxÝk[^C®ÝÍ0‚ºÁVæS¥ˆÌŽÎe"´úÛŽÉãQ‰^³žÝØ~ÇeÔÍ Rƒháb‘4¡ñ¨:µ²B’—°P¾­ËwËO~{èöŠÛI)Ùð/¶yŒrcï`Ü^Š `Ç–Ôð¿Ò™—`G„®)JÀ3ô¶ÁKÀœ',q/R®y–\y™˹Œ¾LŠTK[l`*…ž8÷`é]ðÊÓGÓùû­ôÍi㋮ŠüŸh?|*ÆæáÕž´ ¥%Yìyx ª†¸VÈ«a‘àx|1g­®*}Ñ{—: ÞÆ@§BûïMLF‘Îz<œ,©ºÌÍ%; #( J€àôóMŠYdÀ°Dß»´ì¡¸Ï¶š%€ø÷ È;G´úôq»±­@3 ”òD^œÀ´Dµæ»Ïhg È['¾]H¹‹;_¡ÑŒ”x¢æ†æ9ª4kä@ ,Yu^ʨðð 2þ‡~^;kò[ø—ô >™õ¡\?¸Î¹ä3ÖAí,÷Yz«éè…”¨ÍG/V²P4"Pé?{ÿ‰Ëz)‹vƒÀ¤Æ5u&?°¨Äf»Àˆ™•8†°2 ‘X~{ŸJ’”9»³Jþ@”ضÀ÷øp¼ypGž[cØ\ Ñ}TY9«ä!—k&Óíg=yP·×°f×h Üß“w(Ëäµ$åzоÆÕYâåx+¹[’‘½qÏÔChU%­ï!ˆ‚=?s^–*ɉ־dE38òèŸ>‰Ëò­ÐBkO~Ö»Íçv•,2žŸf‚Ђ.<à ¾ÝÎósŒI\"HQ\ã)q¬†ù€çn6Z(uq“€N>¾Ä-$«'Â]>D0±ÐÏ _–ðE’¸Á?5þ–()ë5üOû8ÀÏ1-âŸWqÏæ‹ûyßÐ15g™öźa]ð6°‘'ò0ŶýÚ¹l-k)áŒ:ÒHÀ…xm ‰eÿ‡Ø®ä·w{ÁË6Ë´žqGùõºéž~iЊ‚veggvÉ®+ÌëÂ>ðÙMø2ŠTc:eçäcqÙLˆÌ7Ö‰ .ó·¨ÜpñÎ@‰îJ=£“Ÿäˆ{éFÌÌ?Ã2q[9k¬3ßÑn©“Æc‰jú?ð<6KÄ®'È—WÀú©šÑzrk9Rué©3Ã;¯|«¨|u3Ó5¦TrÔj¬˜ 8 f:óÆÖ«²ç‡º¿õ}érï[ â•*´è%øÊÅeò©¨µÕÖ,ùŒ‚3ž²i‡¼Ô»2®·I®‚ByÊÎHe™Vx]ÏRjz3ûU}ÆRØK à4øÓyÈš³ÿ¸kàËí2Tö„I»‚©ÌfOÍ*B…Maù,?NœêPbÐÁÀû4†4Pnêã:ë0”ÜölZä;â ¬Êá ºoÕ˜L,ü„õìã®ðHO»H©7¬6¾îŸü—‰ÙB‚Œ®ë:ç½ ýi12²2+%uqÝD6¢áŒøf´MCŠ&´çKvs]qšNÂFöI¬ˆŠÙ-RÌD,ì0/Ù¿³[Nu ~Z3¾ƒ‡=ÅšŒÞŠ/Læ­‘Ðÿdžüv« €)Õ}&‡ßT¦õˆÃ+qã#¼cdI‹M¶ïžo*Q~EÂä…ïb‡ pǧ¯®yç#›¹&RÿdI1Ӿ X})—Ô1;œXÅc•µ¿NŽ-£)V‡ˆ!«dl¹`·/ËÔÍ:Û§ƒ„lª¿ò{qMܪoM¼¸åiãá:ê‚WYáÀG³HáÀ#‚MÉec6,¼£Å‹+Ò±áˆ+Žg7–¥Ú¶ zsáDÉt‚,fö Þ}9bßÛ» T·xûºëˆËŒVt^À™ü/úY·Ñ<ð=Á§N‰ª#(§Ðl]¬–GT¶¹†ÁËP­;nåF*È \ðô:YÏ.¯ÊmÑ. §w«w¼¬á3‘;åè²Ýã쯨;2’qh‹éDZ7KÁd‘ÂSáŠ+PKí°½•Çv5„I¥=ÇÜMd¦×‘߈ÌÉx?ó° °0rßvCMý@_r u² ½ïըà (‡Žû4a»•/¾Ñr#ðN![_!ނľ]ˆ2}Y„?û6kTæ€gÿ“3âQ/»a…M¿#ï'˜¯Rù®qJ‘"FéBæ©’í/ ôïÔž±j¨é`Ïv'bzï8øæ-¾•…Ä—§QK—y=Vó’Ùãáž>A\ùkR&Èõ&¥¾WÚ¾NDÛžãÅø1ÿ㳆åÑ|ùöêsfµz«õ“B D(”™öy|Ž¢bøÜŽ,Ÿ%ØW2ɮ̾ƒÜ=d!J‚±Â²4ðÕE5 ªÉŒ¾D­¤ €mG¸4>…%"{´ðÒgYñó’âV3ù.7â:މ Ks7ïJr×)ŸÙ÷È!¸mæÈ)Œå›£pökdUÑÄÁbÙ4KWï´máäß›9©nâî¿ÕO…Ìts¼¥pæ “iKÍF¦Ç$!¹.qe*ĉÚTmÃøá& v–¬vÒö: >W¾W^OT¿ÅÔz‘Á‘ħü¤¦8ŠO|€n’½n)7äÓÉÚ¡*s—Ï‹:˧v… ŸÑYâøi…âþcÌ2Cç';sD#Nè%ÿX=ƒsð7âcš+´°ì•¯{™eÓCS[³5‰ß‹ˆfcùBÅq½Õx¨O[=‘Ç\Ñ\»²8-§aÿ™®ä%4Yöô:ûpQØ¡[[âø×Ê Œ§û RàñÖiÊmǧ'“õƒÍ]”ÅEæ‘­½Í@ÍÏÓ ¾/o+ËZùœG²Bl®u¢ÜDWL­r´ŠN´hL˜¢äjFoòtŸþ¼ifÀüÐhÊ‘b ebÏuN³7"%‘¤”©…u`pI$3½SúØ1€Y_ã1E(cЗC¡ï?¾— ÀEÅ×Hº…Í Ë&D…ǢÎJrš*.ÅSÓר`Ðz`ÂФBò®±­·rP#)ëÎ1f%ŽÙ[ó±ü¤øåïúÄS(3ÛÉ£a¤è³Pâ`p‚ìQïåLäöMuª˜î•ÎEÍ|ý }¶€“¬re4ˆÅIÑ¥©pr:¸qÿŽ€!DZ÷‡"ÔÞx«L'ùÖ(%H†6!͠ߌ}ð%’5bÉ}èÓ¢”¸¨J5öúU¨Á<"2ù°ô§GqRÐÜìm¿¬Ô{áB,ðó­)Ûuî2Ò‡:O[Y81ýϺµ{ÝÉû‚AÛiá0›¸&#ÃÎØûâÞÁrÃà’åÄø;R¹m.În’f¡©¥âd9`|peG^k—•øw°Ðâ/( ‰:Hâ Vcî÷ZBU ƒVϯ œõUÐR%Èò—aQÓnEÕ¦yÝ-¡Ú{Èá=zŠËFýê ° Z%‘üÛh<N„hS‰ë¾ÐÆåVè`0ï9ù¿8±(ñEИÀOc«®#xnn3Lq]0«0œFëáMmÿ4ê½ÄÇW² ßÓ0¢NÃÉ!z{+Ûòmž¥ÈÆ]Œþ8t[e˜¬vq&°©§cY·o3wªö Ó¥«Hra„yÚ2iM.—5™YÑ#ѪnA­f|06Ïú>°÷$‚wZžjmg»b¸¤àEˆõˆVpš’ Yù‘E¬ˆ¤éá!=Þ’âê‚O,Ô¯¢ëαà’Â=OÏrwÌx ­ÿ=WŸZ u”Û¨Ée>ßw–·‘C±¿EFËÁK-"–Œò — s»Åé[[jÄ•àcæ]N)£Á©bÇðÔ‰wS«[RJj²´9aoT1éñk¡+ã˜Rz©RdÌ?¸ç–o‚c!Âà¿ùƒBŒ iÅ ÄmLƒÏw\%ègScΫäE½ zK$þ@žð É\YàîuèBò|Ê%5ok"îZp ôÛX±¿XÈ1\Ÿ2dÏ,v†…n#2Ü3Ä€Úq 2vŒþ³ 7²s>KÎÓq}°ÏÇ‚è¿ü–X×£_:u"A …Uÿ©›Žßp»ÕÎ÷`pUPSq–-YÄÁÜСïFø‰9{_Ó9T½½raíºƒu1<øXNªÞâV=ˆ*î} ô6whìŽG9|ÖlŒ(WûÐð.F4VâОÐYR‹Œš™KŽ¢‡£”Æ¿¥6,+KŽ ïš›Â2ÃzŠ ÍWjé'÷+CHèØ”#*ŒR/ øxΚQ×:U—APÞÉþñ4-ƒ\ÞœœmˆÈ¸/q+½ñvi:w¤Öø–˜}¿I;´˜*…`Òd]œPªùxgz±:7i1ù2¯©ßÖ0pÄñ…OÚ|CÞ{ßðÁ”ªúö©¢ŸcŒ†±“¬®z<˜§±Si&ðF‰VÏÖUÊ´-QôŽ+Pò+×ÉÂÌè©'[aÏaŠÁLJc€¤¿Dƒ%s€ë);ä,š“'#o«,IU%¨Ô!W:A_P–*]éjö±WfÇ y¡»üû»ˆ^~ ìë!gôÉÍ >÷¼ø´ë°æÏ¶ŒÕœŸû ]F¼ú»C—ò~ˆL÷yÆé¹qöêãA¥äн@á%ûHËáÖxä¥à‚¨Ó^ýé¢s§ÒÏÈü‹9‹O¢>@رpqœ÷ |ÁK¹ÖÁÖ r9šºë‚R,}}r²·èÇ^Àߘð~ƒÃ г*m Y8­9Ð7PÒí_†®æxuÙQ¢/¯,ñR O³.Wݬ4|É:K¹Á%‰’ÜhQJ‚G6²]_ÿØØ ˜Œet Þÿõ`™š,D´ͽøÇ$U%ÉPtvÙô¯ÉM)—B©T‘ª¿AŽ¥Iév(ŠÁ“ø5:çxâ ®BtÜ)ãÉÝ» ' þdãï#B.K|­Ísþ@ëFÉjnþ³ªvd¿ý׺[}2±8Ë?0âk€Ëýò¯XéÌéìC¯j¥#t%x”“r‰m!k­¾ôáí^©µÆoŸõ+'±VbÌÓ2—dê$ÒYk.–óK°_$VÌ=}c1øÁjBdÙ>,þ^Ç›Éy„ÇË­_æVÓM2ŠûÚQÇoD<Æê •ðé”cÎëʪWÎ)š•>ˆ´A5}£ŒPŸ—üBÊ/¤, YmèøWè~ÁþÞ]‰aL_…¥á|Sø sX_'uÿ;Ùçh˜ÍÚ‚tµY®Y`®Ñz€üló¶Zr¯pæÆ•Wz­Vû#sGó;æ\°š×JÙÎ *s¾ÇNýª‡"êêøºC1Сõ”‡D:UŒÆËX²ïÜTæ¿5; ¬Ñ™KÏ6422ŽÎ%ìâœÙÆ_ì©¶†yF²•‹àô ˆÚé¤ÀÀT4¸r6?*$bÊ‚×ÙŽŒ?.tµðœJ˜u¾iJË9s‘ïìq„† kLõXzƧ“áPŠè2ÈYwÑwÇÓUtp“  úÅZ‰cS˜ø'+d HÂ9Ü@r¢šFØ&hÇ9Ö·Ç@ãó=žÂ!I6kÇI[ý±ú½™—x}(V22©Û”ŠŸ¾Ä4Ôq&~O)Q=¿Áò@ØkDD9¤|OLO§–¹Jvz“hâOi<ÁPÌ"á–Ü”ãŠL»^rúÜßKÝ}éLû“ó5æB!ÙY™Šù¨plW5lê2vŒGµ>>€þȱَ l¹²]®wé¤Ùù-Sac‰ H§g¢÷¬Ø3 hR­‘ãäÆÞÈÈ|+Yí DÒBW¥™÷É õ£Êõ,runÅu!c¢Ds#âÄ¢ 8úTe”Ò˜P𦞠yèÉu1ÖR¸r'>S2Î}R¢€ÄÄwÂòóží2Pše0HÞdb;57(j¯{Ûq–{M,ÞôO"ð³&pe+r·}ÌÔ^ø¼¿r3(´=-%U:jŠúGaü¾q¹‡^:ÆÚsqÔ( ¦‚è}  Àh®¶áéŸÞ’Øà"<ßYº÷—HU°o†¨ç|‚P赘M}›+–UgÝìÍv‚ßâ~¡v^Ìîa’×øëGMï½ psU&ïŸ1Ðâéfô÷1@¡bs•¥V:{­^KáÇ3Î]óŽÁ7»O—’>Fn:>?ï$Ê‚áNÚ¯|†Š2/;稪´'at{7­¸$jœODõ-5cDS›Y_:ðÑíÆïG¤ õy6‚V¯ÎËR0†edW=ƒ‹Ô§I—µ<éæß…)ÄCµ·íæºliÇØ žPû,0í‹«rd£Nà“/]Ü*Âû ˆÇk¨–§¢ *Öi&Ja¾Kª­zê’P¹wXòtMàTnlüÇžìŽ:¾ž¤Î,œ‘wÉÞ&HÎh¿Üœ_íµÇòð] ?©Ú^WxæÛкúõ˜‚ðëm³5™ª_ýI÷²þ¦DlKhø–T‹pµ½•Ÿ»‰LÞJ9Où|9ûâsØ–>R–¬vØ÷óÙip"%¬“¨äëz¿!bØí)c‹<ìHËÆJ#»Úÿ[¢‚°«Ù¢àSÃ9#h8Z:lBk=¤ Ù*Às3I‹–¥2(¤³—ñ`’¯€ˆƒgèúÈ¿«Œ¸&—$;­«Ä‡j§2¡!癉Dy_¯¡«Ø;n-°âò\abD€/Ä©:¬+ó?ª…‰Òbì1œ¶p6¡XAØábÒŽÆlI£üBÈøÉÁ¶Ÿµå0s7&BQ8ÏF{Î6|K&·þÚa=nKiÒïÒ'æé»O\P}šÎí¨U‹cÞ{)úgyyÙ²QÅWQÒÙýyW-/sý_ÃW”¬×—|®ßõ82Õ“·{>¯ bÃëN«{€ˆšØzôK•ý«Ù»ÆÒ ‹ ÕºÙøwF=zvù`š]ƶH¯xAr°=™¡?äL¹ÕÍ­§4ÿã8àèw{cìÌPºuïU«°¾1Âg*œf¿.rúBQxÎT§æµJÎŽ œëáUFO7:ÀâY™%¸ÔM$‘ÉäØó» _LÜÞøÎ> ÇÒ¯U¯8½UµT/>§\0ŸÃi4õ(?7Ú§uèH9®¾â±´9y(½h·WÅ q!ùåNÇC­Å;íYܧ’gÐ>Ü-FÌêd\¨Ìb/RbÙ¢=Óïš²Ê ÆÝÆ_¦&ÎW§¢*ÐbÝÖ„¸Xb°D)Ë>¡æG'ÜôÔ˜(°X¡—z½ùqfÐäÌœŽËÒÔ\÷£PMuìw.œ* ^,ecfr¯ÍI.íПGP«SŸû{šÀ»¼QIMô)U·ZVµœ8¯(%„*MxÍš·±%Ì5î~FÈÓª5À–©àìç®ÌÕ nF$çO ~l† ÀáÊSžò^,šù˜8 ÎÖšíÃ<þú »‘â3ë¯H(˜FžûqT¬ d>æ»ü®/€Ù.±MMú¸ ¡'«Ï‘¼QôÝNZ™ÉïÓÇqôÅ/Š_uq’ï-Za¾ZÔ…_8ñCT-ŸÂá»=ó]Ô׬Ìrö±î½€© m–Äw‚]Y´õ>Å`ÂÎC¹O‹.Èâ€{¿*fn°YÄ’Ï F»ØM²Fp~Çý¹rÿþ_Qêù€ÃÌÛ€DnVÏÕ.z³`÷˜ó‡kÃ^r\u`Õ*ÜF“y6ÜœQ6ئÌóÌ¥‹¤ÌãRÁJ=Æóf õ/l “j/eu¼L¢RÎà΂º{ÿþ. @¥OP$ª¤!AÖÓ÷x;¼]¼ò9;ÏÖŽ'…9UޏÅ•ÎBühŠ“Ï¼v <\æ "¢fÔQØ4ÕãÊk¨„¨µ0t„š2}{oèj’¿þ1£° g/sM½'ݳŽÙZ£µÕHƒÀŸâp=zIgO%ëÈÙnsﮓ­í°ÄÇGýpè¸lG2ùïðS¥ÉI¦s<—NV‚þšêâ&áŒ=7è qÝö;³roY€§„¡!N ÅZÃDä?]9¿ÖWä­T[g¹Ÿ«T9ÚÉË“8Õ /Öfý—#1n¼•ÉZ÷âÝ}‹9¸Yä~j8+~ÞÍMU*c¡{‚H»p÷>xFóïnˆÐV{‡ãç EŠb¢q‘Â1ÁÐ_sFrwÞ¼-Žyf?M6†ó ìÂpÎ:U9“‚ÿôŒa)¤KŒeLÄp2uÔù´©%y-'üËÚßBÀç˜N¾+CBKêRÄâ𯇖ámëÁ>í>qK^ö{¡Óh’=þW膿€‡V-i2¨tƒðÐØ«'ü}`ù°{¿ÏDPÛªÊs¯:*ì³"’À§»t-8„¶–ÈO-)Ìbôɵ¶Ðmvy@:ÍV•ñfÿ½B(ÊÊ Wˆ\/?£”‡d1kór ½¬¸QåΨ>Sˆp®6ÿúÀz.ÀJÛßtƈG;P˜éœÝŸpó2?’ÕFî3ãâÂVlõqRMd„{.‘'À³?É¢˜ä\ˆ[EBR$HÜéç惺‹d¢©‹l+i„ )ÀÈJH>ʧXaþLÈïò½ºSšü“êOy}õ†1{Koʵ+ùfƒ¹¦„ÙÕ Ý»ý÷U½@Wøþ|Å¢?ä±\ê™øÖMwì2‘ƒÙJõ/R×ç4.ŠCªj^Ú>¦@]LCq’×-g^w: @·ƒ*¥uRˆH󎾄v˜mŸG‘0L£™Ê»MwŸo•dC“¸»$fžßbX•b Ä<©õõKÛ—UeOÖù†Õ\Ñö3ñ6óò@ä˜kŒ±QØ¥­Ìµü€ M¢«˜ªvEcƒýÿ4眕úPpd毋 L(s¹NßÙ*L±œå9˜P‹…¥(æƒ,ïÓf×ÅŒdÓŸ¥AdÝ¥ˆËJuý»”Ý–7y¹^½Z2®QNLô5ý{`Cõåñ²S}”ä‰û¨W˜23çï·<0ÿ)˜é˜6ࡎۑK6$ "¸Ó(-€«2gÝÒz žsRl©-v‘ì×|v/“Åo•¾\.ÕðL×;þr~ •½ÃC 2aÓÙöðưP{½EâÛbÏòáDï C³Ñ_Ì«! ö´>‰#¾xCÊP¸Ø;¨ÙZ{ÈWv&ɹ}ýeôV}Ëq’ûü½Álù‚lŒ'}J•Ó„ÚÚ²‡ïô^ëîÎR–´oTP ØÔ=x‰枇]1èÏÿ_Å?˜ôú$éÔµþ¡Ýío¨äÖžYÁö—¦ø«¹åN-í·Xû#à8ñ¶žŠ˜œwâeœ`~THtk†[ZÃÝÁüÚ;ëºÆKñ{›€›KXË\A4­mìÉÞïþ·-'骽äL Æ2ñ¾ Wœ Û]~LBƨ_Ù®–>0å.šùí—Yƒb)ļÿàü(xO[²q Õq’:szÌ9ËþYaÙ÷tŽ eÆ3oÞ[Ìw4ñyR’BÏtnÉKX·¥"›ùk »Ê¿»x#¾áÊ+qk¢Æ'rŠÛWta|^kò”>DYšó:@_ï Ê)~öKÓ‹Ò™³šßQ¢È¢{ýÁkjb!挆ð`Ïj‰ø0#Œ:†MÄÕÀIq "A@ÀØ·ô®£QmÛ~)âNð¸G .ǵ¡qÇN½îÍ¢,Ý-/íª©b1T;"Ûx<½Ç•ÀT‡”IÍê(ø éÜ!¿Õ‘®‹s¥»@±ÔÛšú ¾ÑdqH@|ÚÉ ÆhþAÂ)³!ûc²ƒ=ž@ðˆ%ø"z²¸e½5XùVèÞ=gÞFU•ÓøÅ}Ì0]8kØ]uËÕE¹dÚ ÌâžÝ1|Iåj|£‡‚•b#Z%Ÿ¸ Y¡2,o¯£Â1x“T§Ý‰+ÄXÍìÄŸ¼=³eÿKøB–Ö½ñál ]t„ üCܵ™óÔô”î8ߎϒ=ÏŽYÀ þ«è,FòŒµ¿“®–(\ùÇ|ìüZ˜Â\ùÔ#u ·Ì¾A§74×J§O4öŠà^X˜«ž”¼^+ÔdÕ¬“÷ XÊu}_‰ë\‡YÉŧG¥] sG«„yõáqî+>òæê`ˆRMÀ`‡E(ËBG´°aK¢¤«èË'3Þ…ã;â›|3}»Ùs“V7™›ÿ¤µ›¯ösZ´h>ÞQ[-Ù2Jó ¿¸¼ø(*öºÔJ  ûjp„š =§CLóš ë]ˆÂ˜¦bö $3'.Ÿ9ÐXõ8†Ü8ÎyÞ=J€µ¢õÐÖßljc‰ÙFi²s ™Ëª$Ÿ$y]Ä&ŸÉ_™Ô›Ùî®CÞ$/š‚©r·Ýîf‡™-ß=Ýæ‘²ŸÒ( (\À„#>n°ÃàR_0‘¬sœK§_Ѕ溔]T)³[][mBÃmÒ'þ”‘Çÿ¬Šä”(vßÒ.ŒqûjHCêyB 8;üVk$nÕ…ÙÜû±Õ¢¹l˜† ýÖJ×Ò÷Íg*¤%¾„Ⱥ(7°.ÿ`PA pmBþüqFVö'µ¢ƒ„ª¡™æ”ë5.ü<´œ>hÇÑrÖê¾Xp§‚¯”jvÅù1;ݧK×zU²¹ñè’Òœ¿ÿƒésrð\ï\é˯æÀÅ•HóõÜÝ ü@ùFèñþZÍa7õ¥tÃ!R„#š‰FqÅöF[X€:Á§¥»?/¿X¢ ¯@°ýTiy$»e‰Kçõ>ôG‚ŸoÐI~"B»ÒÉŸÊ-NàÀ3ù\g%î58\O"ˆŸÆŠËWRµ\°F]Y±l‰›|{<“Ý]ù¿P>ìAkµöN*Ä× 0³ ã^?ÄMío*$]Ö­ d‚{‡_%ã.ówê‹;åqg¹¦\§ ý&êvA¹4ú›šm‘ÕžèKé‹MÛsU¹UÄï„&±EÐ,;Í{oiù³²0+z)ifùMÏkfD‰wóÅéÑ‹>€Seô5ðG¤è—&J‹€­¾?’mÝ0U£ñœèiÒ)Ox+}%SˆÉš•Hä9 Ÿq¦ÿ®ã©jÒ’vcïÃ\òÖ·lkJÏJDÞ™èÔI`˜Øµ‘jYùn»#Û‰°!´„ýÂt}½‡™j#Þ½´D±w|Ô*5&µ§M ‚E+äÁ{£WÙ ìôt[‡H+ÏyöèãÛ ˆm!÷%–ѽE¨xgâ‘»=¨!èÔ­“H‚cQý­K5ŒpWµAS+½„çGKƒ[6šJ6Ð9”HÙsšVi&Йùö’v›EI…ݶã9”uhôVø˜Y9ë‰3p|1°ID:H¦‡€]Ρ¦šÖ·´æ‡p¨‚j¡ä¼UY,Ÿ›Ñ·ôõ³¾I$ÅÎá£m’=!73S5ËùîõÌPµˆm„C4¿§ÌOÊr/AÍC²T4«1õ §à•·ŽÕþÏÞýc‚S$t wMHyÊ]®1º‹ð vïIPУ2›Ma€{ïùã‹«)nüÀëÐݶ+I%ÇAˆŠmqü°ŒËLˆ¯ŽêVukè~o®VQÇ}DÏMí=‘zl=ù˜á™ÞLmG©±âáQñÑ{rºokñx€¼ÿo¨Ùf\m2M.<8!5z¨Ä=åC°#¶}üBç¯\dQªõ/.,»õBíkº®Ö5h↜ðÈS»h×yôàïî/7PÔG [³1Öiv"UE15žOÙ9\—óU¸ïs‡òöÒì^g­ç‘iÓÌËYHkJ Ê«´mI ÏÌy ‚¹Ö’kñ} @·ôYî ˆeZÍû}“4•ÁÂɇ t0%ïû8’1M}~ Eµ}0+déÑÃþoO«œÜ-°Y,š3 êqâ'·Ÿy×2kHM˜y,9ÃÄ̘ì°>%ù ùÁtƒT¨¹{ùV# ¿:¨õÆ‘©m‡ÕDïÌ17*3NÄ f¬^ŠÅ*Gžžâ+þÀLÀÖX%[ÉGçtH‰òje×0$A,âFφ¤JU.f@#ÕŠð )iý–ÃQ$ž~pÔL¦fÊÀ",æ_¢WsÂ÷BÑ,±â¯Ž˜Á—DªÓzhÚtªA›`É\¾D+óšlÛ:‰ ØNnòh‘+"(ø:A¼Át H‰`¿ ßD#?LÇ g¯È÷wýÊ Û[òJè.\‰#Ösi5¾}¾àøè‘âwtò°W›(¬;ך²ÄµPDc‘[V‘¾%Œ¿ç•Ü^°÷;ÇVZÖNï‡J™øfâ³r| `hpNIž-÷ÑgO!FáÍfs–sÁzá*âÖ;CÌIS`E¦qtBT]½Àtá :•åa­Älæ…©ªfÓ[¶ª|Ñy:ƒ¡z5¯‚o÷ÃW]cžúÈ=iÙØ©¹èQµ©iÿÀµèkÛ÷K‚RñöÞ´‚Æ·>ˆÓ"ƒÃ~ì È6Ö=k3A·|ÅšÍâmT’QCެØôàöhñ7~O?}i1þÎä »jÕL“ŽW†lï’ÙYYF2Ï„ÙbÝôéþM ÛFpMâѲo"™&-ÌH ‰ú° Æ7ñž¸–@h’¹¨‰T7mr±]Ž›'¬—G–ãV¶+ãƒeþ)7'xÍÌ„cèi“‘ùŽýÔÎPñaÊæežŽØKˆ2ó2‘*´V…ÉSØ„ÈÇ??¿Œ^™=ôün§‹~/ÛÖFø Ø"‡xo§ìçx°]àŠ)YNéþF±Ø8(œÌ­D¿`û-ì J€gÔ¬=YÅÚ„Îq6­kH•K»•üÇé™C Î[9P?\³~„ƒˆsw’þÐf‹—næ%\à±þ‘ít£F$Y³KjÆÊ4%*¯]ç1„ëÛ˜…DåV,j "ƒdì-¸æ¿¡¥÷· Ti<ÜU.É”ž&zÿ—/(Ù”÷þD˜ Î»s)kœùÑH¸—nßЩ’·” ²òGŽü`‘ æÙ!Uà˜¼$-ëy Ñ v2µ¡‚n¥xÙ9âÐq”±¦˜8ÿHLÛ Õˆ?‡”)KQš |˜~»I¹¹€Pea<\ùòÁ«Ó´:á5p)Åv&šNÔ'6Tk‡­bŽ=ÑØØóU#d¥¶­âKÃÐwåK` °/ØÇ÷>m+mì"° ö4зÒ¦ü¥–A¬°‚nÔ¬]XƒG¢0éØ7çÈB¡¦|Fen 6³ê¢=v¼nS†dê¾¢m ÊÏ'‰AÔfKÌÉþ¶ü{ˆ+’ ÿZ•úRY´‚'’„ÙËî«ú8Ÿ•;œ&26Éš_eò¸Û‰v=ûW'dØî¿y‚y‘“1åÅÝKÔg=> BŠ—Ëxä·ðîÊâgŸ‰Q2v³lÝ‹ÜTå²P àäì?Ê ßUlhÁ=¿·üíåj•»’xd¤fQpªú\Ë©³o©U@ˆ%Ȫèôûô†"~¶L -.ágŽ(?=}’ þ è1ä ö£ ¡i^_+ͬÄzÓ¿$µs×Ëg$cý]Ì]ÒkòÝ}í„!?*EVèX/Q¿*8ÅÀ]9ÄÕ\E…/†içÏÛDK&ìõ °I¯er2³-¥ÿåZ4‹a ýCÂuû^ó+©²a+ €ÎWŽŽ çÑ3öìwp¾Ù5ïEÑÎð×Ú˜™k[†R°D‡öÅ®M>AÀÛßU'>9áZ«L ËŠ¼s^™À-¿ Á+áâýù“KÊŒE6|Pv³ÓÊôj?mð|ߪµü,ȸo„«…»K³OîñóPÞS" ò³¨òÁ üjÅÛ¢SÊñUPÏç'Šð€½7Wt@póGß––É€ ¥!ƒžÜ³ê»P¦‹ƒyÜ5KÄÙzÈf~ÜÅ-\Ú¿4m®U©dQ&lvŸo>꾬¨Wgø+5ZF"}#Mš+æö•Á©Dƒ÷Vâ.ùCÍ,S—°‡šWʘ]ë¨RÙôäÆÖYÉ'ä”8Dô{¥L_¸ÔÆ3–ΙR¾‚ý<óÕü !f‰Yýö@ša<&RnM1ÁÆ<î™l¤®ÂÁѲXÌFŸ¢TLÍ…ÿqK’eòx «áÒ'jïL|éiæ‡>.廑<üú56©ž3ß²£û ù†ÕBŒð:Ò]~¬ P÷áe ³ƒ¤P„Š´kùXM_©u•jmøÎIVøSÓÌgiÕé!5Æ ãÌ2͡߃­¦—”×Ù¨‰BZðÛ~ðÔû88 ;WÏ-ÏqO’½qÈ åJš=>-Úš»ie°‰ ߇%¦1ŸcÅÐÇCRºi ߦSg¾ß¾À¾qr3ŒäÌFñ[ß¾E`#BSŸ]ŽI¦¼7p笻ô|Íè¨:«Ä©z&xŲ©ÙVé$ŽÞö+­Z ¶Žg~úOÈËÁ ‚–/÷!€uÐèsÝ@Ñ !»Qã ¥cÿqÄØ ôãÈâT^«ÜÍrásð^ÏkAÅà&?.F;m x1Ëÿü°Œü7¬HSÅŠ™‚‘•ýÀÈB”wÇô~óIj<*N7òpprÈŒØ0"+Kå$õ¦&ÝŸUÕ¬4Ç¢ (günŒi]æ":™GºƒòÓŽpÊÐZñ7¬Z$Ò3ÞóC7ðr?×ÔGè\c8—ºç&8e±)ɺŠ*R—@޽ gÅ‹µð/z *øÑ­„¢ms‹™Ô!È”D#“0a{­ž£Ð†t°–ZêÀc E•*Ó6=‚óúÑ~VޤħÖHJ䵯*™,ì݈}ô½Àá†Ç]>FŽÕc—¾Á†í™Áƒ÷æI=SDŽ_ þ"ž‰JxGC±fUeIïYD`;0ÑÿOÁ­ˆPãŽDç®êuOÑgì”Þ¬x*×Äð¥]M2HÒ–< §‘†÷Žxj"/·í–ÙCÆžäQöÁÂÿMÍ´«8S¼D¶iÂŒU+ê²\ Þè°ð_°–0 ;R69Ó³©tTTŠÝj×j3g öH8ƒ&ÞÖ"«’3 ¿5†—5ß?Žü+sˆ®/)Go¨"%:ê~oIv,{ ÅÖɧ™TØGý4·ÒPõoA}„€88‚h@’¯‰ýËãT”ªZ¦®» ä¬à*úµÈÞ½?[× òÛùâPæd‰IY C!"¤‰î@ª¥Ê'í£¢ßóÂ~ò\ÃiEï³[¤LJQ:ë» B=¼F‰äÅ%gb¯³-#–Òu8p»ýoì,5 ˆyÿ•Un¹ˆä•¹ž«‹Ý+ˆÊ¯7³X3¤¹Ñ,¡6§+Û¿‰ýãgDþ€É¦|÷æõ$Æ›¾ªFñ¾Úó5‘gÒï)€c ·qçiCƒ­£JÒ+Ù%†ÉtžÊAÔF½Øp'/Ûõ„µ‹?5Ò©Ç¢£•ß¼n4ÕXqDàrãX$j˺}ŽËGø‚šzP5gÞ“¥·K˜3pžL£n­ÈÃ. >93ÝIa²29?Ò1mãç‘; k©OB8ÁC~¾²KkaH´9l')ˆ 3"½H 8Â6ÿ¼D—„7‰p9|ˆTþ˜:Œ æÿ‰‹sN_o£—äÄðÅ›h -îm” …î'€„x!B‰ `?DžIÈÛ.µ4͹râ°Á/9È~h^ŒH âÕ¼§O#ËY)¢Î`µ«G2«éY`zËQC!ÞöÁCÏ1YûÄß~6¬#†äÙ•[` Í<¯FÌé’M?ÕÅ:Óåp º1—ww¸kyÖ¸Á/ˆeÕ¦‚Kf<6(6û¡î)¸#N±z¡fý1¥§-BGR\Hµ(Cd%œM#.VåvãÜëèä·3ÊóS½Y!Š0…N””ãv’!Zð¦àžAþù±ú@Ú4v é½ÙrºÞ0ò4¡|PU#(šÒU+X†”¹Ýw(‘rlqMüsªŽÔª‚€ùì䃮ðåÁ—©¼©0Ù\ý¥tt­X¾]¹©éŽND0'Ùg¬;kw?›ã.³© µ»Ò¸eÒ÷ªþóå£À¨œ–ã"å[ëíX¿aü¾ˆÖƒÁ¹ó‡—YÓ¸<çiç «lLÉÿ^ÕÇûéù .-W«|hgAçë6*ë…lØg èòÝw×éåýlMOÔ@¯)„­·ÐP›)ˆxß„&8dZñp R‹ørDâά›[K>ªÖÃ$†T€âä‰5b}mØ¡¹r”N¯y” Ÿ‡ìÓY$P0›*> r"(ÅžkŒZqüêÄüïùúr€e„àÖ^Fž¨ˆi¦¨ñeŠZªÁúût«R>àª7ã.àDÔÍê¥0Õ 2&jg(Œ”Q])¸Ú‹›ÀHôFŠª lI:Jbó{²äw6ªY6tB(Õ(¤F݈Èt€­\øú±†Ð9ž ×ä%‰$§ºi˜wbe/¿03é¤ä›Š`Ÿž¶ =´ú ˆà9½šÔKsPté/Jm ,¥YäGôxqÉÒò¢³ˆê9DÈ$ĸ«éßÖŠ$ŸË"FNžQõÇp}LZ‘x%ØáaÓdp"*·Åµ‹jµÄ¤"¤zN7AK&rWeÌ!y§'2×0 ·ŽÏJIQÆ;¯ ø<=u÷æþpêì&¹¾Vs+êÔFJíôÁ12¤ð–i³+õÃÄ’0 Ý_p%ѦhƒyúÑ$=w ¶{®ÛÞE}sÃ~éÄ{ŽüXtïÌ1($v¯Úuö8/xohšÙ„Yý|ŸÙ0Ljù ‰+5£P5û2]½*ii)Qtè› ‹ˆ†Žˆäíç¹¾Ê2?GÐ6m}N•Pç«H³žÜ»ìqúÕ=¹œ¹:y7x9;8\v…°]M^Ñd AK»ˆì’~2ÊÄcܦ¸~×* ÑÒÀ$†ü(Uò®4kÐȦô¿Î%=l†½ŠVrüIA¿"²¹(hM Ãï–&5Y]³îbÛŸyQqàù>`#3Q?¿Cºmà‘oϾU÷·-ƒˆÚÐ Ý+a0s'GÊÎùmÈñ¸L¥d õ«Ï O|7šÉ]r+> [ܾ¨à9±£–¯RBL“¿½×ÈÃepÀ0ÚD‚C“Ñz•FKØû¨o”•íÑP78ÞO ?V?ɘ…ŸÝ‡øà4èëðSt‰ž(ºXJ¬OWÄIV‘S Iɉ®hn»­ÒWHA¹$y·op/o¯¯´L›¯~ m±ÓoFÛH¸5G³Ë¢ðóÝhm6êÈœ*uœÙÇ—Ó®£ïúÛ«•~uÏBx9É(²›èÇl$?v%«€ü!û$ÙBM<Œ .¤%#wMflè]“×–Î>…c|¼JjÚÊ Åò[€³;H¨=Ó]ëA-\awHߨLpqø¯fgƒÏØ<™Cò3·ÿp èÀY ¥»,Ý:öX%³Š¢î4ž.Cà¹+Xò}«>%Y¬p17Q±¯pˆA2ëX‰3³Â˜„|p­ßÆ|èíiR2Ѳxä™YE¾n²« àßUœÓnàiªìÚ„ÊÙàü¼áó}Þ˜îL…ÃThÁµÜÈ1CGs= ëzׯ¦«ãDð½p„ÓŸ_¶$©£¸HAô³qî T¥W@õQ9(y&”&?àÑôŽìÓ¸û:/ò&§Ò¿vk/°ä&‹kÁkihÑAò÷ÆÚ;²àkgeC¨Ïõ”! ?Üd¤e;ëj®ž‰~§îzÄ¡ìÖÇFÏÄAÆðÍžŽ÷M)¨ ^Y¦–ÇÏÃà›ÛÔôÔÏb±|’ÁR”\xÃÜÖg±DUÞAÇ®‡ϧ5R&•®;ÃßðŠŠ‹õ†I#ÅÂN²Ð\Õ½è6*1„"J5·&\²€Xšfß^Êî^,˜Ð! ̸ZÁë(/†j. { aãû#‚‡&¯0²«n€ëã:Ù1V|`©÷AÜRïgxTLMSaU‰+ÚÐ5yäEHì\‹(1nB+¤ØáÉ@y˜®VaŠÅ'»–B»Yn¸Ý ýߤS‘j]û‰`‡g+‹[aL•Ïètꃬ0dðd¹CÒ¦·Æª÷ЏvSu¿´c]ŽN8T}ùD—×:ÌcuÄoi8ˆ#¨Š*Á ÇÆš×t¨ç0]íç] 6¯MÏô-uN‚òAdÿÖ^})ñT003 |!4°‹AöÿëÛAM%NnÂH©… å«Û­ØCSö.+EÈ6º€â‹¸À¯ò™‚v^…šäÞ¸eì^:Û16Šî‡%6Æ)ãYb’|œ?náSaÕ¢;ôàðŸÝjñ ³HÑÐ ¨ùö)2“®Îéæ;e ×âw.e›‰£°IŠÖ²ÇON÷ÕÁ†s/¨æy*b£#h2¹¡œí ›i 6c Åu«>{?Æas]k»,Güœ?@“Û&ˆâoTõù3;éȯV©p;FwuÒ{´Ÿ8š¼®±£yNôæR B°x>ꯢL³dôD~R~±¦D/¯hæ{v‚9c_ã*ÅEdK†Ô-0JP8#ò”¼UD Ç†Æ÷(ÐÑ.¤±" Ê7ÿ¬£Š×ÈNÅMú@/k>ÖdÊŸAZ]BŒVìq’ŸÈºüý;P &YŠæ¤F"M‘šFƒ Þ|Øêå<›*êœ5Ü:Å•§)´¶zlVPfEÖÙOuÒ¨~¯ö˜½1ÔÓ[ƒ˜PY7; ¶œW'#¹Å¥Šp‰_á>n1zû¢£¾C¯@PáÐ{„¾Ç`vãã( Òbàèûäút:6Mw´ÿŠÄg|y=#%úQà&6>žåÁI®*ª(XVñÊZ¬p~/»û%U£%V$ÎÀÕ>åáe÷ÐU7Ðg~ýÃh˜¿T¶ ›vë Ø~לx½6Î?l’šÞ2·KFF‡œíBÏâÚt|&­«qÁi‰éºB´ÖȺòóís{dབh—0ahHr“e[©D1Ùè‘#z…àc¦ÿsþ/Þíò¦qÌ{˜’œSßûÏ«Z#›3¾—H}¢ DZ6+ŒiÐÍYzññ„(Ž øoñêƒB»¤©/êš^ÿÁÈ$Ë×g›µçìêFñ›çÒrÛ CçÐÜ\˜ýÂ'ì‰â.ÊIö& 58ì‹UèŒ>£Iý=g:’wxÓÂhJRl=µÞgÞŽ¿é ˜2x¨W5;š–ð Ç«hÝõÍÂåŒÃÖ\~×ÿá}ý ùcaÇu/¼å È—TÓ’i©Û¬s„² èu˜w­…#Þ©i¾˜¸‡Äõ°Š)§u!ûÄøš‡Û¶.•2¼Jþ÷ö`5}„âi II5ïðࡉ%_ñ¥Ïò¬Yî~–\åón!Âã /‡6(þòó"ØoþsÜHb¸ŒìÊ$Ž õ¤.}\ýxðE­ÃÝÓ–ö‚¥±Ü·¬3Jû%Ëì–küõ…‚ÛÁlw×Ú‘§áÖ6ÂÒ'ÉÄõ?¬û§*}Åj*p¬Ÿ6°öºÓöU9w[8˦úÜÄ9ƒÏ£­K}®xÉÏË‹ ­ÏÐ/}¿pàÁÌÑ,Xe$(jþ^^–ÿmT£l_#s\#ÖÝÂ|ÖE‰d…:Fê½Rç|ÙK7´%÷ÚáÔ”w}«SÎ>e¶Â}׺ʾÀy­ø·o· óVc@hY ˆGqŸÏ¾0§e¸¨¤ /l Ù^`X²aæù~eôz7« ¥½ƒÁ&`ß«_à^ä f™s±œcÞŠãr7ý&îŒÞê`ŸÄSQÖBÏøŸè’ =õE«ž¸¯õ#sÙ“[U£ØßÚHd>~ YR¥âã žßJØ"²½ q¶JÔ3UGÉòœL8hä/_wæ+V²™æº´…œkÈ4"á2e Öëö‰K‘×PQhj+KÖ~gS€ÌLŠ9ü[$)EVóTÛ$m+Ǧ$Jx¡’;Ì4è–EO/½¡O Ü¡–f›ÖÞ)aµtl®£+âûêE¿°×QðHY¦QäÎüºm®`$ExjO„‡pEüùÓU¡›¼œi»År• €½…BD#fo(‹ªÍ^«—; óE>í‹oW‰ûlß7n3G—”¿6sJ×'Ò˜äüð´¼rcu%:Ê—U‡ ²3éR}MFþF‚ §yœks÷k°(ƒ! «¨RZø$Æ—ßí_äÚT]úÿ;6 7+«Wëîw’⩵ìϹÓUu[‰F\N£:ïV.ÄDÊjç—³Ÿ®7ºçŽâ•~  Wœç@šÎ3ÂÚÒ½_Éë„ó盡±Íë9pzp§©î¬J&/6`øîªÆ ¶ÐÂÇ­…=.Þ§ØË~ø<ïZ\·%) ØðRèü©ñGW>%C×:d>%Âêp•´Ð_ƒäð“Óラ™¤Ü³C³Ô²Ã±îùvï,–Â_ôL‹s_LMþàYï›B4âÄ¥|Â?Y ï.O«¿±ð³ŠyÍåénŽKiâ£P gý}ifK)¨„îÿc8¼R‹±E‘¿sO µDÚ>ÚûÁ¬€±¨ñijE ©_ŸšðU÷%ªû¥¼/Õ(E‰s™¤‹nZœ‚ü)üf!ï"‡BîVwzð&ònx‹1æÇé~yb5Ö4áØeå”Éú –}*Þ½$&2h´-í.[O¦Ó¹ ¶M…/²è¨¼ZÃ*ÞX•¹½Vªït„Œží¦òFI¦JÕ‘†D ôóÐÐùBìÆUMk²3duÞ׌ü^S¬`¨ðô‘†òB“¾{.³¾ó—˜+Íu=æî§ÆbØ'fS8±C¥ û·Ýnam €Ë®jI†(‹},ö–Ggà‰}çäóm½•Qû iL€c·¼Íÿhx:^2”ùòF[þÒ…Öï‰õ0ůÂ|XþòÁáºÔÎ LŠ…¢áÑÜ™FÊ÷~°N^›&@†Õ¶Ä!8|ä ¯üi¢ §@¶@†&æÌñ²|U`ª ˆ&|©‰0¶è¹üàTØL1ªšb-Qñ&kZ\ë71ü\ÒËq4Œ4CÈ”hßÀ£šîî×ó†³R¶,}ܤÒeOKŒè•×g‰ÿ-À­CnUM…|%M¦ ÒÀgã|€ÉsRpðâ²s–s‹Ì½—wá qq-¿'ßÇc‚†T” ‘è Íeèq"(N¦{¾\DµB³P°í+ôƒíˆwz¦‰T§É0¿Jn‡Ç[#?5¹ê ïº_|Œdðžã–{–’’S¥„™íšb¡Ü=ë0¬d3Zn,–OtÓr¾K÷"I±iKìçí±½ïlצ;·«Æ°w>‚ä+• ë4ªMuNûy>-BY癟*®kÅ+âÍ7©@cÄ= ì{ÚÊ'»&ž9(Úœ{p“õ¿êÿhg J‚æì >¥¹kˆ½)ßX B£ã”÷Ü ¡3§ü"Õè(ƒØë¡Ó#F3è†V§®Ç‘yiÀMʈ<í}Iä„«y.tx––ÿ0T&ìmÌHíÓÇ{–Ž_‚^ã#Öüð:9ArµÝ<’x¤Nväæã•”aS ë=&ÿç¨wä÷’{ëðßò뾪áÍ#”â¡°0ÂWz¾qh‰}# ui­v‚¬ ð€y®Ð…b)§å1ü‘¡\Æ‚|] ÔZéêïý½°·ˆ1ösÕD¤ï3 ·”) ÊO0ÿ>ùB«,èl…•U ä™ ~¨Šƒ5&ÀÎ2Õu]e€}\W‘@3¤8¶Œ9Ä…ž1Y&Ò¥…`b5áäz6"+ϰ`1¡÷ÉjÉ” ¼5uqôY©Õgs4sE…¸#†Q0$#ƒ°åG“ñ5 ~'oie{Zqïm–Ø?þ¿å ÂÿFÏ‚ ÏqIN©¾ è<¿EŠCÚ±ôÔW^m&«(÷˜xT_ñÑiyØ|;÷SS…Ž~GzñÁ ÃÂc;[¨iՀ˼.Õ’×*ÎZÑ%™†ñ^N\ä­úbÑ»f«ZÔh¾‘I÷Uk!gm?£›¿}ߊ[\g²Ò±ªGJÓ} Ò/•ãù‘ýMö•—H¿¨Ü HP´Zb1†*%“î“à Ýå±¥Äyeÿܹü$œN¼w=®,AÍýÓ…jŒº–UíwÀô\ÃÑRǧn£6¦W…Ô/×­N!”}¼Èäé™ÁÁÓb)ƒ«§°LTp *²RÚçNŒ÷fbJûMÅ|(€›‰i™#BpZ‚;-çáËSA ïz¡¤[=ݽE ëü_;9Foˆ¢ŠˆÀ—üÎ4!-Cu¢ùcåhÏû»Ò) "0Ê ÔSp·‰‡›L^Û¤Š²Û¶é-p•zï@‚h®¯á"k¿:o1㸠y¡…yÃ2Ô)¥¡V§[vS2î9*6nÙ¢TT4Ì#%·S»iZê¸ jFWÞM×ܘlk`˜ñ—.îW×ikLXVŽåcöIÒ»î¾ó•ü,hKfZªjN¢MÔefç"÷ûe bCq.êÄ™¬ë®í€oy)¿»ÿŒ ÈTï/^Ø‘!Ú¯Aè·` ó¦JµÇ«ê¥]âè&s ’láÁ¿Ý˜€Ç;Ôd“ó 8”šXç¼T 8¼ØÐßR>^O EÐ ¿v(ñÒ0‡ü¾7-ÃaOøß\L0${ÔÖ'Õ^‘þ¿Ñç s]'¶ÿúM¡— Üè*VŸIŸ‹â‡ù¿±îP½Ã~emEŒ1*$½tÄW*Sº4ö…ý©×ÉŽ›b>>;™&÷„Ùß¾†«iCcË ¿ž` Lžš)ÚÚßý( [#©J XsM_ù°M¶1Òû6|ßýíúȱ"½þý®·žüŒî®"ö™Úä®]$žiÒáÔ[ºù ¦BÔ33¤…d¯9§à=áyB#žá°ço¯@!Ç“¹XçIcqJè¿È«ž¥¸+˜ôð„½ú¥S¯„ÙDA¥›²„Zºö‘$Ía$x‹=µ V)Æô35Ô ÇÝmÀ•³?`Jo„çe¤,”^/Coÿ/Ñâ.¦Õf±\,;“Íl7¥vŸî!Œ7äá·KQY¬+dåÀ®°ãF Iøé>¼ßò|ÔêÖóðRÛš‹•Šœ˜™'©aF™^9¹4Õ!Ù ÍRËÜ¢ékëe•ž ô–9]1r‹k†ÿ7Ëi~êÉLÒSÿV¯|Ãáë RÕœ³zßÈPtà uì3Êsè˜Û`šwœ1ˆçtñ`½?3tx˜‰iö¼d—œ­H—“Nëšlì¥nó‘Cûº¬ú÷qYŸÝÎr ¦¼ Ѫ\rž9©'c–¹9Ëííô¨DO]­ÏœÿÝk±Ël…y?°¡.”nó®YŽá3®OÆJG ròÂ&hå­X:bhá$¬²"’–Âr?)w:6¸(jÞß_‡º¨–:nÔ?\´âÌÏIøý¬>~…;Ï2¾NLÝÓÐBY¢è€´¥ë,uÁÕÀ@eÖJßìé(­óüÖûº{Mç–ƒYúLËû.U@È\ËOJIäÕDB¥5N¯g¨1겆‚^gÛ¥«™û·ÏéYÅ“û9ËàE½rª±¸¤?“ÙYô¿¸îÇwME^ÍÐ(¶7´ŒyìAÓÉÉïfXZÀŒAÔ |52êX›pä¯-¦ã<Žh5ªœá4.jª«÷Æú×øãý¸A_ö4¼ÚÈòÄ žã¸ÕÙô±K¤wýœ¿¸í9¤ôµ„:š»BÊûÀ(Œj1Äþ(ï0Õô–ÉGKrUü\Ý î{4ÉJà Ø<µÚ9ɵ`s¸†Ä°È@ŒjÞL»ÒHï7W™‹”,»¦CÈEú=Înö¿>íkX£› âQYAQ#”£|KvZíDÁ¸Ù|Ðj ‚CüŒ'KéÇÅ›ëÅsõj9sôv>Ž©J˜Et7ž õÖ]YûÍo[„ÞEt>š[!Ç6¼Ç“¾à•v€Ž W¹0 æÇ#.áYáGÊ…Îó.`†û;'‚0Ã:8°º2®µ’X¸…übß{WФóºuž–v‡)|Äò»“+ÊxCѯ…R)Æ’šD>ôW¹ Fè$f¹&`Z—ÁfîÐɉò‹Nœ 5ÀB¯èá=+ä}Ý áqÂÀ·—N¤ªVduž,Tý7”)úãð{Ž‹ˆ"3¬x2Þ¾n}T¢Ì»›{3¿”>P¡BCH×!1öÆ/8d à˜A¬ý¾¶Ãù%&yƒäÔ‰f¼ Ö¦>sÙ.ÈA MÑfž*Ï){8×rÛë+jp\K¡bfÿN1ßTtÓ0 5¿ÓûùÔ™°#£¼Ö°ùÀý?£¶Ù‡—lü:ÁH8Ëâ>x©Ú–jtßÖ4uÒŇáN:?‘RÆ8%ò’À¬•¹õ3g ²„¸šÎH ìá]b§ÉnM²³Mê­)oþ•d£ª©øO¥¥Á@–!¢ªá<-¹3WÚ;ÎhÝqýë|WÂ:Q§,½a´äf¸_ÔÕ#£Î|šèJ›wÿîGɖȘ†º²†ìj2\wÜAƒøœä¦:Èí38‚yN5çw<åK¸€üü_nïF,!}%¸$õfR5•jƒìŸMðù8UÞu½/¸#ˆj ÉK›“B¿äºÆÃxk%Mâmµ‡0#â6¾æDI0½‚qÿÕYðMydÓ(5¨ G5Э&e­ð§K¬Ö‰l?îÐÄFÕ#:´b5g 2ocE9ïËz÷{Ý ]VÎè<å£ggVX¼Hô®ŸêƒKÔƒDZ€„Œþ|‹Ò0 Ö ÷¤i Øh©ÁooÕñsLÀù £·4¶é= 2g–¤ƒ¿£áüþ¨Ñ×mæJßÝî‚ê»Î¹dî¼Â5Ž6[ºX¢­®kš×@øP‹ ¦„ƒHp‚cÄç{;%œKJsAÐ6a‘+6ÍᔕK¼µßÿzC%5® ©5Y¥¶–9¸/Ÿñ¬zD/{R­j©ÀˆgóMD1RóØõQœG;™ªÅÁLb,jˆ.®,‰dnžðܹŒ'âVØ¿®<â‘xÔM¾|²'Ù¹{C½ïbV±4\ȃcÛ¹ê66PŸ~š*ãŽ3 ¦—ŸÊÁv,7k@1ä' ÍúÃíµèМۿJ¤r±Ò²´ÄŒHm[ìnVG—½nÙ ¿†Ÿw«d Ëm 6ïPöau¯åǧüß‚fþß ÙÉW‡$3棧Ì=•í^ÿԮĈDhøôë¶`ÿ§Œ’(B%à8o(l–' ÚØöú;æ÷>ó “gpÉÚ*¼XÌIûAS;r‰ýìðô2Zd¿Z}3ÈMd%kðÀ¡Ì:ÐÖ|Ü%K3°w…a^!Ü·8f<ÒV*ំš™e,»Œ×"z…xëÙ5Ék_„29ð)ÓÓ.]!:ÏØ;Äw¯AÔø›*Ûgïõèô¸‹á\ÝÈ™î„rÏ€4i ÅvÛ„–p‘ÖšU¤òv±"V^Yœž5¤!ûñIƒr®A& yá-‰™oÈz"òäÀˆãÖk¨äÑ7¸rjðw*¡ÆB"ãU´l¼ rÓÛÀ3…Þÿ; s»ú¥‚½ètgò-]`ü×°š\÷Ÿ‡É6;†p$šq§Äœû­ŠR&;¯@ L"²5îMÜï& by$}HF&QY&DmKÀ_ÃIZHsœ}Š¡ŠºÞ x<Àðäkä6C¡}éb‘z®½, 5âù¥àçÑ0É›6GÏßÈ\YãôS/Ä=ï¨=2‘™ .úÍjP¨ߦœ<?øÈýÖüÝ ×d— X'Üx%·Dñ‹.ÐÎd,½Åݧ*ª©úô‹…uo›Ì^VŦ'ƒÌ:y(…Xv·ø7NϹï_71¢g›†?%KäÈ<þ6¦†™ÞUù4Bцtb󵻦%w«°rªl^â“庽ñ4ÄŠGüò>BFºµ2Ï|ïcÛù²"«˜X~ÂWÀéh\…Fgbkå¯ç$yä',,›<<äà€˜vg‹+7€áÞ±ˆ{Ù?±àÔÑLåýrníreY¡Â·ÃV«¹è˜1 aôâèâÑ5V¼ â–{©IÊm\.W/)èczø—áâñ_þ}dZºˆæû´¤ø=ùÞªž49‰¶a¿b·Åô²ïNò_VÉÉ ¹þÔ9‘øuP´¦&Ǭ™DàI¦À—%’O&a ¢šõ{ æFµž°ëÑCßÚ©c"[þð.(”nÞªˆå"™ÔeÆÝûíÎ'˜}üj¿ÐZŸ`u$ò@v´PØ>X`#‚3å‚N®".+#î¦Q̤žF/Ȥ\¢¯v‚Ö®nÊ eö®®þ̲—ÁšõL f9~Kt¨Pž‹%v,Y*°iç(uYÈü u/·Ë{êq=Ô;$4›™>5ÃV$*Á€¬#>3é²ß´èŸ”Øs=¹ XVdA¯'©Q•…oI{µOQ•HÙ15òºo‚s®oTÙälNä»Ý¬þ“¤bš§™G~JTšÒév#øÿàR;“bµ]RŸƒAóú“įKÝçÛ{Aœ8[ëû*kÜr|'‘.{„¹§ñ¡¤/àñ™æú¥1M‹Š¹L >ïõ{ùÝUbë®5Œ˜=7œñBSsQ’V÷r´âfh¬…J1iõò’ƒ¢¥”ãG‰Æä¤?pb‰Ñx!p!ÆÅþèÌTµ}´}ÕBóÌæIƒ0@¿¹ ºMܵVƒ5â]¢5ÉÓ |d&‡Ì„ÍÚï*Þ¬$J†K;ð égÁé‹ëi^sV¶t0ÐÜzZEpüÝIîG¾ÿ¨0±$?²S)ò“å[v >w<Ÿù·¥º,œ^™½;£ð¬ñ§¥nK°tÌâÁ¸kŒœl;ˬÆÍÀr0ê'ýä½'î½D]ª“'çH ,A:¤…øûsÂ!ŸävÚåeß‘÷ØÂŠr÷2‚Ù‰êŸq`ïR¶þà›hd x;‡Áײacïà6ñÉüÁ8<à\¤Y EùPïÔLƒÚ)è™hÞ!ë?Agm0Íz¸™+ ’Ÿi2÷`` `+²ÏÇÛi¬@žÕ©â½ô‡g("ÄH%dT0jÇÎÑ*넼0üê¥TÈfá$®NJœpªzhâJåìÂÆ›a3á\|rMÏ\ã¯l…›?¨+b¸pjÔz«”[K]÷CÆ[Ê5Äš«ð+ 7€PF°þ΃L¼Š$#øí£o[¾‚¡¬?ZàÆ¨2NZ_Hž ïNþéw3«Ùý07Ò÷Ë"äX~…ZTÝüžÿš:ýûjW~œÝtiM àØÍn;­BÌ|X®$¦ /S²DЉ†—<â²{6»Öô0`MpÌwä~^6ÜÓm‘Ä‘^{ÌN„µáe‹ÕÊ}vÉ Û1lÚÆ)Ѱºé^iÔ…<ª•§s9ãgãGHÁ5B„„ަj}]tædqt¡)ÉJOŠàšÝ ®%_ø Úâ5ÃÀJ®âŠ&Öžv+õåwÁ2äýYÂŤì-%LuY"ÃVæKy Û€‡ŸäÖ4´ze“ŠIÉ@3ìÐ…’³‰^¤Ûí‹|ßòª™”2ªûÈ*Š¢[s¹Ã!³€à£-nvÊ’ÖFø2ø^ÜQ2ó o“Àl¤3‹t'^æð“B)ŽToö}ÏKÍÃëÖÅË+P-i…‚‡t ®üéX÷”¥‘ŠTŽ|¬&ß` #¦ùˆšŒŒzöÈ0iWße¤Á_blísµ2‚± ­°åDV×Ï-ÈCßc|]<@›&óÈ>:-nò#ÃIMÖõ1R7JGÙwH)w'ÌX×ðFˆ ZF­{ã („ˆL›<9# ÖÆŒÊÄŠXmR\/æTÚæ4[ø+½#lðwX{ عî@P-ÍLÚg!e®î¶L8c˜¾`¡½ÜΓ2'£T1KàéhÛ€E˜8ÉF›kx‡xC“î÷¨Ž0íúR{dΛ“`ªË¥±d¶íD¬g ñ@Ο1x«Uã£4ï›0Q;–üšzŸ5/™d#ÿØÞߤ/8tÅéœ7m<ð´rœÐ Ãß~³–úéú䥙­'TJÎ.Uql¹qÏØoî©Bõ[t9’QL9ÛŠÝ•èC"´îTs£%è$øŹËb½ ÕL߈ûÄ”3 zj«s2˜{ª³Ì—”Nó/ŧ»_‰wÿÔbqXX…ÐÎ!BÒ‚þOE[1!‚Úš>Ó­•€ŠZ?å.»n;aàM°SfÞl̋ٔ*¥æ“†™ùAÕ%gOqjJ£©€™êÓ³†öZH¡DèÅL`Qì#< jv"õõ&2/ÅúB)Z ýQUQE¡ë„Âpy±Å¼ÀÉmØCW¬'ë*÷_˜+Êi³)qM£ðîç£ÉÁ¬i)2Wµl9Ôè¹²ìí‹ ŽZL¢9³OÿÁ?Ù¢àÕÿowDÒÓb1d•âò'¾Ï}šõûÆC '_j; 'ž`÷¯ìâ9µ§µ½¸r-jg÷¾m‚üb/ Àƃ‘£QÎLJ•4²¢»MsøÅö¨öb¦A®ÿé!õ6kéí”CÑ!ÍÜŠK¶`6 »Ÿ /ä¨3­öDë)æú V8ÚEÆËfòÝè UUÚ¨‘žù÷"ñ5xY7áü ¥AÑÀ¤žªL†ûï¿Dx5ÎâÝ‘½á ¢ÓàÈÏxó™Â0'oOˆ ÓÃE‡«j*†­q­MÙ”nI Úœ’Z䣳µ²ùšÜšåãŠÍ…^ %ËÒj6½çL!1 =7:±Þôµ4À𖨳¿{é"3=FÌû¤*¢… +씎Þác*êêýQ“nj¤ªOvT<{rþ«ís},¬ði¦üOT¸ϘsFotŸ%U³Ø¶9¤(d]ú*\‚šŸ‘´©N­i³v®ÿ1D:«ÛQ¼¿õ¢üò4Å’ËÏ{øë†¥7$YÑEÎrN7w=Ê’® @0M»ÂÑ2N_ûz‰oc­Id"ÏÉH 6MRÙ†h)Gdä½P‚¤Q?;u:>°áŠ'¡s>$afdOüaÊExkòÑ,f‡AǺ,VË®E¿ðG•ùøŸv…T¯TÓc ;E«uaÉ”zdÝT”èï%˘d ©;vpÄb{Ëu¾~M¯[+Š»lYö½ôó«*Ø·À<Ä_ÍMYSY.cx5ˆŠe ,ZìÃCŽ…n©û>ûôÑß÷ñ°Ïq12æ›Á‹û›Ö©BÊRgä•Ò‘Ëü¯W‹‰:ôûêÿæk¬ö_£H´X(.OÐx[»ð¶ÖÒ$Ê _”V 'Ðà8f5ÚV‘Ñø†Ï˜ìšC’6G¡é4Ú[ÍÕ³H-3r§£ü•ž]bžƒ­dæ¹»Zóç_eÏÖG™ýqð`3¡Ójò3=!žv0ºV{ë-àò1?=$ðæ*OØ%ó2™*?([Ìv?MÈ\å »·'£|c€?61Y]Ü¥†.—@ü¦ð|ûÝׂù+æë¹ i‘ªWè[ù¸N#ÞÄqynµr'Ec Œyt›R3Ý.ƒc3Õôbÿa\uav¯)orq°›2gŽ̦÷Ÿ4f”4&ãhÏ¢n$ï%ŵö`ËÉhL2÷ú#2ÂE‹X»ÅÏ­| Öo©ZÐ ¨~”`™÷߆! Å8ñˆæÎu||-𵋀 | çÔ}uÿ^Ä@±œa€úÛ¶­–  åâJAú=â«BŒšÃˆ1ÇíÓL^¬öЄ£Ì©!bcìÛAßК·ü^fAûF4‹™Íÿ (•Z“âÁW±ñ!“l/ñK[“ä½…—6¸xÑ#Ã{À™×G±:ÍOoU€ß +ÿýÖC¾¶Ö[ tAüËz«®$^v¤ —°R $ÆÀMèÁ6nÂþÖ”Ì-%Jœù/{ C~”!4× !T>k8òÜ¢ Û+ýF:ø³œcW4vˆDâãs{Bi#`T7™¨Ë ¹ _7Œ\øc\ÍvRžh$#‰ÿêc^ÎÙâL“Mvªû^ùƒöyÆíµMÓ0+Á”J\}³LH8ë¨~ôTï_º,IÝ6Í$É3D½÷ø Ô‚›mániŸE¶ÆÍ Á„.p^ëÄžJ€ö}ÔÈtYY;?Gþ$ žµá§€k¶Gðk½mhì$JƒàÜ^°­PX 6f‡=mQ¶Ê˰éί 9ùך7~ÉÔÔ¦¸6æäâžþHºÉÛOjïñ÷aÿÀ|k 1¢õ-õ9¼òlb0ÈòýÞ”ÂFúHßàÀ[|;Ç‘ !Zc·"§K¼Œ}6)µ³ºZÉ^{ÔÜeÂïÑœ£›Œ n¢ýrŠÌ8AÏ 7ž_ÐŧOpùÇÙôÃÊ?èÝP…÷Ÿv ²{¸Nñ#xZOô«~Þ¬*šÓ“H¹¤"Ì|}ðëõ?/üö5€H™Í_òÀH]K²¢¶ƒðýÜxà… çŒOR¸EN¿¡ ³;‘F”)÷Ê·—‘€F…¤RMvÅ.b6ÀÆdÖ¥¸ykOé…*Tç)b™``\Ὺݥž<ò28Ó“ø ö ‡ÆÇje 0Ü3éPžlÚ’oýÍæìÆþ…f¢¹ Á÷?ßüæU¿[õ ÜÕ9eQNrx0=_¶±…åň4ÔFäΠ hiiêÙaÖëXÒ±`zmÖÓfþBñªXƒMc˜“ùr¶e´I€ÌMõt<4¤hÝ,‰¿îXѲ%á½gìßNè±w®s[?‰VhÎ]õ•`š´Ô(ȶoo9C~&.Ì_Þí…[ålh1ƒ¬Eï ’éÂ6]]c¤_[òÊbˆ†=ZS‡u•"O ¹Ð>Ýä¹r<橾-³ð6íŽ`ö"¼\£=GvËEù®¾xÐDB Ô§‡EqÙëF™,¹WԢ͢"0^v};½•Çõj¾"wmþ?ì…¿ïlôKUU%¬ž8Wvº& fõ^=m=Û¸ÊÆª V(Dà…%—!ILdê“êÞ çÕä‰P°­ñV¬…„ ܶrRcÁ_GÈçËÌ•”ø`ƒÔ2/àW}1xÔ[yoA¿V½öº¿ôÅ, pM½ÉÀË´º£UYTÐ(e [=­2ŒÁF†&Íe–6Ö¡Üt•P ¥·¹Ñd b}Uoo|-%^g¶­^ƒoØ LûcN yS’‰–®ã7uwd/@¹’©Y=éÖªø¤yCtÞ‰~tëÖÕ¤q¥–M.óqèh÷cõi;ÎãG¶³ Å =ÃG³ˆe^µ>¾ûàº&(½è’H²X=†Gç›$°ŒññHDÊ-®Ìýn§Z ƒ<åQ¹XУ4¡ó9›©ý^ˆdžòK1ö˜@4½"³Sè4¾¦Nå¡Ã7Œ¾‹ŽðÑ'z¸ krA·AS‹çK^Ívþ<ÿ}¨ŠÙRµ’]Zè«mÂ~h2ìì÷| :døþóiì‡ü³hœIÑN‚-YÚ£¤a`T”Ø…Þ6(?5b¯¡‚Ï]SŸmoüeÈ ªÈÒ©p>X¸ýº=#szgrש.\Û†´=”°ø{ùÄÞ"®ã?â ÐÁ*žkVÖè¢{ZqÛ a/¿¡ç'P­&©(®³1´îÞšÜÓŽµnUŠå’ÐΛWÔs8XtWf ¸Aù Ô¥Ÿ™l "vPÚݺðæ6gfÿœ« º'Ï]ä@ϨDãºz ð$N¹(J*aÏ™aÛóx×Qò%S(ÑàÞŠ3=Èib½™ò²<Êþœï–Ó¦¢Œqá¦j¡y[4+äÃÀ±+;¶’V¸ýlC"OÒ´yU *yž *Tè·ŽU¯f@ÖãÔ²ç´ù»œ6µl¸Ú¨;ƒa’‘o™<†öd„↣F› þ³Ý ó29)u¦›ØyZî¾ÿ4Úmî,*W7b¯fÚ9æq‡=Uàml–?·i'+ý.ø&ç±H¾Íú¸¿¡”æE¬²þ4 éä;4ç3~Œ–gîÿÑACšB ”1`Û.o"xâ`dÈ5 i/vºÛ5®€‹bí .= ]ª;B)*&:ƒ)“Îà8ÿ ±Ï od§Kó;Ý’Îæ˜69q#$Q—¹¼‹ð‚ó$Ú¡ÊÔ@߯*7½r n.Xõ;_Ã2'BLƒ¿ªofv'•Þzãv)Ø[ˆÇvË0Eh‚Ô÷f&ê«" ¤2J ÙrÅ=4¤‹+ôâÚÔþ”¦ü ÆHË;1ôuÒe€ ƘW™[8C¥N êÝ7Õ0õ›^1wåh llÝj‹_&ðƒ #Nd$÷"’†˜&´¼Ý»Âsðæ©(ÎÌw6}€ª7pèu»p@u‰lšªÄÿ‹¡:Ä4§’üý$²ÒÞjÚ¡ÌÞøÚ#0ÛÞ'p.«W·¨4†®H¡N ÕÕjñ×çâ@?^ 5»ý^[¦ûÑRpÏôGÛªð­À)|¤%Ÿã„u:·ÞÏC&íéÃÛ¡ ç+…¬Fѥ崭Ð硇Ib5«€&`÷­¦ ‘œÿ‹òÍcp*™¤+9o—Q›Ë>õƒhU¢Î›¾†X…Âf·š¤Wò29ÏW|6FûhÒÍ4HEeåä›ÜŽ|5òÇœ¶õ‰UçCž´”Ñð·²ÂЙˆÆÐ"Þd“§Q#ÍxD[N¢i7@¶UÂ;÷®ú®%CÌ—D®=mÊ*ñ;cLˆüø_¤œÅVx àŠ›ç}OiX}iÉ‘±R¸C'¦ ˆÇþcÌôßG &ÞEÃÜ€lx©x4ÑŽÛ Õù¸n¼÷`³¬ý= B5?Ζ¢äMÒðw©ªutÖ°.ëhç¹>8êƒ`pÅ€WU~«ô=gyÕ(Gš™AŸ)1»Ê.Tc@­òd×JçJ×Ó>Êóp U<µ= Š®—ÒKgG•n_Á$ŒÄåB°ÿ©\¹á>N¤[G¡tÚ–¨7°'óß^ôºH®t®¯B&±g‘§6H 6ä±ؤöòÐæPH„£´O°ú³p±cKæIG|´’‘1uX“çš-8È©uPÛ—”€|i5±ï–½«Tñ_’ÁºRkÄ„¦>Y^x¾Ñ‘N ówî*U¨²^" uê  n4GÉ_\½(ß3/ä­LÞH®â9Q iG1 F®ø£”h]ëXü/S_PÛ%ùh×ó'.?¥|ï¯K‰/y©½„»šì#OÎ<¼€Š[<™XÍal¡\~”ó<UȺ6˱§¼-ã(üûð3Ù B÷ÁXIA*‡Åƒo¥ßcIZÈ·µy*ë»`gÜ‘ØJ”ð‘M‘LXáo>ì³#õ­äwÍjqY»¶ ëÀãI!Ë߯Î-õRå¨wÜJW•mQuyKŠ»Sä Ü-M2gEŽ,0W¨¯›B‹·?w%V_ïØ)öŠíeÇ>n›Ïc—0xùÙhšýìÓ×BŒE…vÀ›ÏvW›ßo÷)Ç´‡¥º•æ0þ-–çŠøÅ&šØCâï`™ò÷OîÎ$YHŠj¼ eâeG-TÚ¼c`›–åDÚªôC#æ”å¾tÍ2„X˜;]tÈ‘]ÌÌí÷£Ûw!9dèfµ“˜Îzm+å#¨ÈëžiûºÚç3É›y*¦ÙÈN´Žˆ^xR· H9n)V®V¸è—eÃžÎøQ|÷¸Rטe[ážN[¿%pa‚ô!®Ì}vã‘ †C¶ÁÕ•c~dZ$-G¥LQ+Ç^,`z…¡Y[?Ø$ö@ÜÑüà´O+œœm:†Ñž#=ˆ IlºDdÝý5üÇçHÀœ}î~ñ’a ÒÕ„¾¤y“zå¿ÎÖÊòž9«$ÞmÀU5šÉ# úz7O~Õú1°æó°Y©wò©¶ƒ¸º¼X0÷¨Ã”†öYÇ×j­tœ_Hy ˜”$aA•B@'R®ô'òo‘‡MÐÅKt¸Å"+û„]ÅcßR§qœØJ!ƒÏù´àÑ»/¶î–„ƒÝãÃdðK9à*í8w>튬aTÏ%<'Œ¦à# «%Âb(èÝG.˜".ãòz:š‚ÀZ½´‘*l#Yì±ÊŒõjÜ«xÐwLÙ0€ÙrøîÌ—œA°pÑž–ËŒö[uÙAÞºCúžƒ á>5,Xåîž(T êµõ®sBÖIºä3¢D6O¬¿ãHLæ6`ò~Ÿ““™”µÚ6‘Úr"nóß%²üúƒôAeòÅŒ3¢Í:†w©[)€2èx0Y­×ÕÛ ½“öñXÕKtâE×n xÉè «4×j©t#7^ÇxÅr£6m¬•DN2fãý£ô‡Aðž†Pçùõ(Üî£JÇÀ'ùY?yÇÀ»ñrà.8“š8ìðÄsÅ‘¸Biu1ìæî¸vf¾ªÂkÊÛÿ—HÓ³.–ЋþTûC`0¶$Öj]òóZJÚØy?ô`&nÂõÂÅìq»¡|NÇ¿üå×)±—¦'›ŒRé.ÚW_j4‘‡€Czžéîó rú¿t4Kaøš´ø½–Ô®Ga÷Y|5Ix«Oæ“n~5ÊË =z ŠÄNêVœ¹ùAá¡1”¥»Ø½µæ½(´6ú5%S$¼ŸâöÀ’xÚ“53õRzRJs Ç6ã`k½`RÄÐwÝ-jBœÞ0#ߟçï–À¯u£µ”‰ûØ»g˜{L ˜3MãuåHŒ±g~<ª+!YY ¶Ç±°Oõºs¦ÇÜ¥§ˆÜþäF8’/]„Ñ" o„Ÿcö>Þ'¦R*=ãTl‡µòXúYcXméÄbvbQÒH*74LˆÄéGÇœyª\4ëµáùדaÖ6KèP¼N·Ã›ìLËM3ŠjÿO1¥8d2ÀÕ@¯lb–ºè3ÚS³ ¥¥wãßáï€æ½ž>ÔûÁZߪI¤4•’-®#ðTׄᵀ£å¸¬µÿ—?w…Úüô;ÆEûN[s¿VÎФéëö"f¹‰ƒº3tä/ž8¨›‹žYK ôÈP÷R¼‚ ƸVá µÒ¹¶|Ÿ;ÿ¿”ä±Â¨ õu?`¯uŸ$9pýLâ‚¡‘{f²ô¯ïéëÆ œ6•°ïŸŽ-mrç&"S¹ÿ£Î¯CuøVÄ”¹6€èÀ„ªöB‰ÃŠÎ 9œåt»'>ágRjâª5Ü®E9fX„0¹”¸Êã[cïeŒØ?bØd˵fú¯÷Ño®\üËîá†òÛ,Ž=*.6h`$ï4Üú½Sýþë#¨ªEK‚¢Wä‹@9ñò| þ„?øˆòóÜôåd ˆÂ$lí<Ä{Í{‘(­`VRI&Š/òJT͘¢ª„–*>¿~E×Jí”;™æ NÒ‹ŸÊ$~–Ì ¥æ!=—+{ÑrÈÏ¡`Âãð¥cõä ÛWaªl^ÂJgQRb¼“¼žõ3%+n¼[²£AŸïîi2ñP™'½·Xôií ˆ£ŸY—ÒÓ*ŸŸÃÏäzÍèàD—ǤíUKÏu¥‡YLºY޲u„Kt¶?ÜðPKò0M½kȬôbÔʸ©Xƒdµ€ ÏÃö]¶®6E ù·< %AÄ=â-¸ˆž¶÷–™4$ ,Nû\èÓÙz‚e”…Zh/XËFl0ÅsNa<À vxó¿¼(,×öDg>v àºÅv 4›þ·˜U'úÞ{”º0ékÓŒ.pP‡„W»¬öq}ú5’¡ Ö/ŽAék‘ ×è;tð·k˵}´õ¶¸ž’3¬œ‹Rt:3Z¡þH•ÈÝ]½ n ü‰´þãj#u9FEc3'ê”íÏ<)iÐ.?50ÃÆD–˜Ô_l¢¨9iÁÓUa©ä€P>7N½\÷ì»ÔR8øißâùÔ„ãätã“;rïwÏ2BŒëk#T¹ä{¶¨QðŒ„ýÝc…¼Çs½ˆ›„'«D¾vÕ.aÿÕW–#' Ùî¦%2ŸÜbb iûã«ÍB{ '…’gð¬w0Ð! SQTDtÊòdÍæw=¨¹CçÆ’Hçä]å›ÞµR#Â'Öæ…‹¾åiõqœÕÃuŒ ‰Zq[UꉽÄ׃Ñf3-ÕÆÊš ˆ6ͯmYp!›5ÿžFÆF7à e=µM@”æ@¾‡l Oö‚†4>­§ò¦($¶&ðG[P` {䕵•·_½iÂó7\sD² yºå=þ¸·hÂŽþŽ:E¾mÃEÆC”MBAö¤¹‰Áõ´žOë,ê{–ŒfÑH ZŒÄ$B¼ó´ð'Ø¿¤jÇ+FŒ) k/Âm;Ú2i†Z߹ʰŸ¨í¯nòòIò6¼`Ñ›5ŠÌtæ9ªBÝ· „®u3¤ööߘ û™ÉÂu ؇Û:4M_k|ïR^G"xYÚ0Ηى=—»|N©Â%$ë¡™¹øGI|¨vÃÉ'JÊÉ™-£É1)9x½€ CUõè6¡»ôXŒšÆ*¤wÈ‚'*Á ª‘Ÿw¿ £‘lÀ“Ôfn„ØâíþÞaH' ôqeGåL!‰qAè¬Ôší—áx=Ç7úœ£E÷Ý2ZØBL†Oúö èt¿x*p €µ³zVÕõ—` è:÷ª©¹SŸÕµª¯ýO_ðÍdüyâ×@˜ó`[¢¸šH§:è&¡ªyü—ë !a†Ä q°I œ7ƒ*–7Š®ýiöœ©[_:(€­Réž0F˜8IõbÊ;ðÙpÉ‚eÿY’"|¾Í̆hc„…LÃ;lÝø…#~VMÔ%†V—¥|ŒTU28žßÍ‚R€¥»{÷sû-Øê@ö©ø†ú|L†1ÒÙθ)pñ0§Üª- p¹Óy=$­oìAÞ„ãÀùÀÜYÐ}FôŸ‰ý–ZwŠs…‹Š3ÀrÑ ƒñ€ái"šš_Jeî]DL½Üë<æ·Dj.á‹.óœŒ>œ½º¥/.§V•†/ú$@]^s¤ªŒÜŽEúª§½©‡â0Œœ-ýìÔÿí à\*“ÞÙÖ1ÅW»*yƒ¢‰T²Ù‡'SYF K>ön”üËfyj€`·¹2ò¾Ø¡eïªÃõþôé+–fwÓŒz_ÿ_·‹ÈXu\_‚ h†ð4wŽºÂ‹ú)%³Š†Ý15ë@7ÉÌxª÷ÕH_¥*Àcø‹y¨äõá5mƒÖ¼Ïçÿ§¡l–»9Ó9Ü)^†bÔ¾Ù,õãe\ £]Ÿ"¬)¡5ù‘]^,›§Úvþ /ulA7šÊ³-ø‚øòÔ¤4â3T‰-|±–Á9„pÏý5ÒÒ@‘Æ]ãbp®8ÚSTûñ#£!ò&‹'.ÒàiŸµú«]ù¥/r¡,<Ï^V’í¬®xµ¸{Þ·ù¸°€ä}±ìÝêwÇÛ‰Ù yK¥QÌûÕ’¹‰f8ñWXMÅó¢Ç+õq»}âÕ^Ìc3:L+@u„ty«:t/]`Ü‚$«²‹2ïËÔä®oåŸON‘çW_Óõ2b¹…«JéæàüŒd¸Kú"8Z.W9IÁeg*;©±¹N‘ÊV´WN3G¼ctºœEPáÉ[÷[%!›¤ L°Í’*R}_î0³IA¦q•‹¨1-wÚ› [>V×>E)b>¤  S,ž¢‹–§Ɔ‹!½ˆÄ5ÏÚl[(à4p¹ <È,ÔŒ}Ïm’¹ù ăQøÚ‹ßc–úG·vÂ3IÔ:ÿwì¾vº¬j«\ÊàêT?ó¾n(L>!€{š<)¯=(²ôÌ%ü!]–k´ ýVÁ^/èþ¨Ö*á~;‹©ë¿#ˆÜ8·ûΗ¡ÛùÚ^ý+ìåïÒ3ZÏ ÃÛÐèFËb„z”CyÓ¿r¨Úè:Œ¨¬ é¢(œ¿Õç‡Ô¿_•ŒœüÞãCŸ-žˆ-_úýÓuhœ¹NÌÏűQºéÊžÎãRŽpÓÓŽ´jn€Ö¤¢•»ƒn,Þi·¶‘D[ ^U–ÝoÓÅìðáKÅýÜ@ŸÃsÄÎwÿc‘¤Èaœ†Ž›cÉŽÌ¡µ*·­É£l8!À•Lc5ü)‚ ‹¯fgµB4Û6Æ·i²Ã‹¹],½§Z޵LsvŸ‘%· ˆgYF4¸Rê9çƒùt»¡Ø¸ÁE›‡8#¡x$–(ѦÐø-=óEdëj €Œa!åÖ-5Ï˪N®{Åvý¨HI²™ÊgÆM™ÈæBrEÕbÊ{CÿP‹¤Ü ]p̸`nå°óá¥Þö3I¯á3íŽ1“÷tÎc§3ø9NM-Ц.t†ÖÒg\ñáŠÿÏWÌ~4¿÷ôè` †æÙëS¬€\“›Ë½pôVZ!°2h  šŠ¨§ HõбcûÙÝ*ç®;#K*C ö<šy8²èà𭪢3#MÈËd飼Š0ÕàÿFpöší÷œ\(h¥®9›´cñ„cq`¾ á“.62ºó a%¨ü—@×Ó2X=ë ‚Á±úÂmG§¼›3°·+übÇô_Ïp„™±¤#‚H¢§)ØB_ïC-wÂÿ¾h ª®˜9ø}Ñ™r´ÙÿêJæîæÐ÷…¯ëù>&t¼}_žv¾q«áå2#× v»·À–€½ŒÖ¬—«ˆf»$¡8&wN¬¾#…ÿÎÐ; Øë×w3q·I™4R¥eãÍA÷”£ ÔYKxf| [)É)L몕YîN8 ÙWeÑóš×†ÞEn ù^‰=µXRPÚhËÂ,úp>º¿6–DL^«n–¤&ÀQ¤]hÍÇÆw'x¤c³na߯[8;kqâ:ŒU 9ÏN®­ôVÚÒò?ÇÙ3J)×þ¥ vÇ阀`$æ²×%UH Àsxú+:½R®`ßÚº{©gJŸRÇ3c92üóþ5Wûâãäô!—3·”hüPKn¬¦Ž…BUî»Õ“-qá‰ôƒÏÊÉ*€I¢•{0 §('r]˜|»Ò5D€¾gJ†ÍÓÒHÃ~-¦ARV÷æ3¶!¿DîbÏ}ÿuÕi?A«ä,ŒÌÉ8OmÎÄs:©½üÔ_ÆØ\„€Ú‹ßEeP”®H”Á·³9ŠÁxp& Œ<"™- MQ‘ã;¾Åp:<ïÈ6(yæ7%ù¿‘•„Ù¨Œ…ëàht°Ô³Zð¹ñxV¢–¡L'  rÀM»Òä<"íSÔ/JM]ªbö«íQãªZ8±[ÿ©‘6eUûmF7åw“Ëà^ޱ5Ó£7WHÞ­ñr‰Ï`¾›ÄÿÝm€2,yq5¦ÖJeQ«fr¦"_‹<ƒ6ºhßm‘«2¦ö­¾Ž kÁ!<ǹʛ/$jäÛ»xâÞu´JsOxñiÄZpòl¸¤xn”(É[h"xL¡b¢wûéà«¢¡½qq¯ø¢ñ«_xL$6ߺ&-ć¹wØÇ®nl%’Œh¢DÕñ° Ñ}HûéV²Q¦g¹ŒòÉÙúàjÛgÈ=V@;¿îFÓÇÁÜ °xÐÍå |˜¬D(ÿtD&1ó¢1Á¸3iU«’8'ðU~nn½ÓMÆ’®/l¢\èlîÇ|X†«¸°á¾"GÊ”ùäÔë¾I‰0¥¯¼Àû‰¯óÌ+Ê熵¬3wvrÚd?zemQuU ôde +ü¸Ô“Po¯ñ‘ðrú\0} +M?¿«Ü£ûÉñþ±â»<Àp4øDÀ¢-Ò/cˆ~óáþ‚¯Úmšá: Á ‹ø!xçÏ‚]Jí·Anïa2Çù‡du¿9ÑaAJG£XÔ Ë•o& ¿¼ ðÜg&±0¨ë1òÄŽ-úx`Ù³ÇL‡ËAlºÁ¬°[Ï.ˆGm<ÈûÏ?8¶…+ÐçèwØtuê ΂J@[JšD/’ØC”ý_X,ö*Ýí®]䘃ñ~J‘p)Ye¿*Ïb˜`Í §,ù:Iîo‡3GrV¼È=t£ö@¶âé¸ š¬ÁV¾ä²£Ñî ûÓMÿÊ,QLé5Úߨa…0ñ³9yë¡¿Û[zŽ1eôO…9û&\ëèèk »´—ŠašpV4e XMuŸË“çUçH9Ó÷oÁï±îxÀ r²ŠÆë\Dæ±=œù˜ *P7Vè_â[N2EÐ÷B óá>ìÿèÒp<å%$ÙZMÊó•Mb½ù¨UÜ9x<æNd1ƒÏ™7JŸiø«»›1š&”.yˉ ?ß¾äÃãø•¨áø+†¹  M5+Yê3ôéPöŒý4n4ó~Êu÷åbÐÍŒ"|+Ï–çlvž IšÏçÔ‚QIÉ|§GXIwˆ€MzUAýȇéе~•%¸o«”ÏXç¸é3¤Œ\+ÏayuJéâ¶J)j«ýYB“§;-â½ü‘ús´³[ÙXœˆ?¸²ýwjH»™5ÏúÎrUƒ'É»¿ûž±ùjÐAbKýã‡$w©ÈFK%5mþKá–vEòÁÞnÜ«fÝG/IlO,,ßâA žkÒ‹ì‹a?§ß·Áë@féyÅ&òñ_€xh6Kgjp0úË»³ÒŒ} `T/[ä™ÍÑ;lAÒí¼¬k=—Òû™á³†Á½Æ'ÚqŠ·¨Æ|ÕÐÄä˜lÈq“UROL^SÚÿÓÄW±ÌŽ¿jàÅ=î[Ì¥¢Ý,@éžÍ¬ƒ€kPW:pÞ"&N'wtha½vO°H¦á†  S9ÀÒå'Q3aLÇ£f¥/_JiαíEÌ•©öËPüÉO‹ãÎßÒjCíjŒm•í ²ÀUgQð¤ ÝŽ;˜«„ܘL:/œ“»®çj4z#³P7iXwc[ø6–<í1ÁSuüþ(’²™J d€P®8ÒûÒ_Ó&C(*δ¢ ÅúE¸¼¦ÞŠ»4„¥5Æ`¤ü—…­Ûî7Ãѽ¿—@Wê¿w.éËl²±3ºq™q>äÍÅ5ÚQP½ A\1wKÑé³Á|ÿ1Ì{uvŸAäÃõÒ™¿]ãr4_ûïOÁ^ÉÔ^2íKà ©á)sµâƇÌÌ. NÄþV|‰¿á‹~Ì5âÕµ Ȇ7©Cì%H&_þ.CÖ°ˆ¿vÖÛ3 éWƒ:E—P·°¹zÍ—Ó7·| õ#&`Ù*Ô>sÒ{®f‚¯Õ’1Uwí~€¶¾™O&‡Ø) \Ûi „Kæ‡&ïÄØbS`Ï»+»Dî¼1J«.VWÅïÚ%1ñ£ݯë<&Ü s7¾P_Ouâèÿ4îŠgœ&lrR;üÛ¯/ª¯ÞD€¹zØj?²WIïãÑq·ëÈ+ ÷h¿Éq:œê¬nD˵àe¨ëxµ$#rY;3ç +³Ï`Õ8çH €ÔÒ .>ÇkÚtÐf«b@$ä`X”*öq£óô¨±fŧ#Š—'H\Q¹@Swê'"ºØ\} ·‡&–N0h=iá$ÖIkMüÃ@@:ÁXW’äØúË£.|Ù4ò y2à…?gªbÁM|¯Àä3ÚýÀÎÇŸŸÊ Þ¢+Û%þÉçHAÞí=CH[Ç,pOW˜½J œ)M„?L ÷„‡8>k”OÙE¿QP¶—G›À|"i`ødۖ׳fAéÕÂHðNô¤¯ÃlË‹(ŽR`â¹eÿa{º‘ 4n£ÎÐÁ`©?Då¹IØ¥0˜†eèì­o?Ö„ €‹¤CÕ¿¡-6.¿ÇæOÔMB„y U˜åvF¼šFù~•Ì|7ñj@–}šrÐîgW*ò¾Þ ™ÿI0qö˜\˜ˆ@Ô$ãW$„û0+ÿ%šxØ é3XåÐûºûxÁÄTï½ÔÇ•„Ž¡yØÏ~X*\‚x×BaCíba¹¾Ôßñ1Å×5eN„û{$ “Çúm¨)°y ©M3e t8¾Ž€TÜ ÙØ”±â¨}”ØhûA·!d¹´u^Œ‡½hÙþE äP9Ú•¾Crlž×b»bBqæy©oh£²¼×X—½)PŒŒ4Ä‚ZWž¡ó1v‰"z›u·i¦5@ëùì ¥r'µ21h,?‡U ƒŠ›ŠŽ‰¸B­FÔ@ÆRÒTºÆ«‹È™ƒò ŠÛèC(1UY9• Ö`¡'€¢™`OWEÏ.®ú¡ŒL‹§7OÂy|Ù)󉵯ö´‰]Ðù»‰%\n‹d¹Ãd¦ Ö¦Q¡Öhl&bç ®|V’¶Ÿ‘?äÖc£¶[n¾~´ùÍG*‘EÎܬ¬ÝûKB‡€H˜ÁƒÇ½„j“ðö7-e-tHP“y€6¨æ^‡kš(mü]jvþÌ©]wÆ3B­ÃiEÏãJºCl½"„•Þpª&B³h@[Ì2Wfƒ–Ká®ûbiß–Y?¡åÍDÆžÖôú+÷`½*RÐÕ²êi2i‘޽3jFÜŽÔ34¦wçó!~Ê*"µË0Õ¹ÒpD§ŠÃgS©9Û\Ï®l¥ÙDƹ!ÏVðäÝ£sAîè?¬RæZ/âößÂ+Ô–¨Z,£lÁ'óoáÍ…Fh߯] ùûÏíSÇnÔJµm‡ozD\™ú#ú’0½IÙºÑÆOŠ´Þ1šlÍ]{ëÏõÑl‹;jhË ÂS±¢öétöaùxü—–穸³YÐMcÿ[Ð×xËíü¦ôr‚¦]œÂºQf< ÍÓ¹ê¿0ž2cªuàäÎ6l)é»OÔ/iíXŠTï%¹ty@y2Ð4îç.$ÎØj,=ò”±¥¯2*«¡ ]ù6#ªn¦¿€|Cþ9lú=ÚöL%ù @‡qñáàñ‰kú6!tƒPä@ÁD½ÖG~„_è-ºm¡{ÖȺə¤¡WŽea5A®/HkÁ¯WI–Õ)ˆÿÅô`Ñ(hv]®n¢Qå‘ß?“kARĶYõ §o@ŒÅG¼¥u%²'21b"¥Ô)_?q:ÿ¸Ë|ÊnÂOb­E‡e­/ñ®kú˜z®ÝŠkõ†ì„Ë'_<ü èqt2:învÉ‘ßH°… `›gI©v˜æº*7á5)ke7+ܲ#v°å"R¦Êõ¦!üá°ÓÒÃLiûÐHÞJíJ7sãÃ!WzÝ'ãÞaÜ u§¬<nF}?#ŠØá«×k!;¤íÁ¶nÕpvWAkö佫K[þƒ‹Bô³^‘œšIy1¯c×yà'{²iT‡FGêO ¶CÁÁ ³ ÀŸ ’Ââ÷ºÅê™”@Áe‰ðGZ=Rü£ªx‘vg*—Â@y›%WÕÇKéw$—E7âè:lbf™5á5ú~¶:ÖŠo0ÖnfïC̱‹ö§såFðO¤¦¶Îh”»¦<Á«Œf‘à|@žBÎú¾ÝÃ_¹øÁÓêëÐWá‡éÝ Nÿ™(B…hf;ËKÆZÔ_´áŒÆçŒÃÔu{Õ„É‚VlÿAgs(Ñ Õ“æN;. ßJÄ*ç=“‘°Ù36îÒ¿•Iºi[_=WsÁNfŽ$ÈäÊÉY^Eê^tÇvÀí} œF3ÛHèª-X»””ÖÒ©€=$݉$kccwMµê˜ö`UCá²÷–¹gzõóJ|h4qkÙ~YlF“Z?-É[´¼¬r£î¥[óm%všuÞŒCO~>ËFâ"‚Þ1äÂë­mB©ñè–tš8áËN£ù¨j’„ïý•ÆážbªH:¯Õiz€FÎ1¨Úñ‡Cm¦+1غúÔ¶¹’*«“e¨J¿¯Ç‡õëÔe„°Ö½`ÍqQïä#ƒ/ßÕ~ñÅK|ãwCQ8im¾Uœ_1~…ŽØCäƒ[;¬7€yŒ Öwag7#²|mPãèâX¼$†ë}mô_É›3Xì?ytòd£I\ólÛÁÐ¥@@Ê–ƒƒ9½VÜš:Å„2JKUG#T`ñå„’ù– IŸàr'ñDžRa×;ä\utå)˜œÞvØ ;û®3€p@—mU~ _ºÅ ÈÖ#g“²ÝÝýä*=IÑ4-¿Z‹†'7ø(FƒïÏ/H«R ãvT‹äÑ“êH¾ù®gV5°œf\û¹êô¢ü½|Lxy—  'Ì®pͯ*±È{ÀF̬hÑõ(5»1{Dó@Eœk²5j‰9èžÁ> @™Á/1Ü‚ùimšŸf°@eG ©+ªÝKÚ#³û¶`^‰Œ™Ì)¹¦M ½…:c0[¥^š'K(A°Pß—Ô¢MÜ,b>ßÃ$‹—ÕÐÒ@ŸK›ÛÚéºÕQX±°m˜{1´ëŒZîÎT99°ˆ’r³páæò‘cFâ=5rãðX¢(Ý슘uïEH¾Çƒ²woÆŽhW("þUuÓ…ÄôCçkÏ@BëýÁ—™ Ñ‚ îsƒØvÂÚ¯™<Æ6Dd'wßv|ú*ã›TÉXÒ¹5k–’ã¯9šY+¦Ð{,ú@L“U ß¶¨ÔYÔç02Y¾¼"t:nùá?¬üþAÙLxqÉUÖh-óˆú-gŸo,ÇÑ´"G5#uXûÛ¬·E`¡:N˜„ H ëãQ—ث ÙtÌg+ÙËî¶Ò¦ãòj…#®u81ÏÄ1…\x±ävK»³wY"÷?€Ó¡ÿfðæy;´ê{ø'Ç–ÚM&ïê{k=U”ûÀ°üyîx÷üe†J/Y¼¬H‡Qú÷<¿ÄeO&ª‰¸üÌk¡ºF‹3«õyê•lÈþ*9·B®K_EÝ,Ë«‡[HÇJ.aÖ€Äfê¢Bõ˯ÇE l¹œ‰Ò²âš¨)jÏÞ‰NŒãdƒÂaæ‡@nBC7Þ«–z–!tt.8ùwcù~™½÷ªôˆ›4ߤ^øLv^9È]IÏ^³¢âœÓnkÉsÑ#Hæ½ÅSÑwÙÔê­æð6ik‘Nˆñþî’ÉNô÷NþDñÅöÓ*ƒ á%Îcd Ã8²È®ùÀwGz°„Eñ@Y鶨 mWAKuÌø©îJç]m,šÜLüt1‚›ã áqåÌSD b`¤i¶PìÚÒŸÛh'烯c•ñK5×Ðù\S%r‚QT —a#cy›zªd—w[ýÃú"`”ÓwøroßdþÖ˜¥t‘®Aà3ºùâ¯pÿJ7òa%XY‚Êá ýZÌSa'²´›¥Öˆgòaô”.tLê'DžšÕ]¤¹!ÍfNˆÙhr5åë§ùádâÚ]q8l5µ2¹îysÒoø†i„tˆ®§t„„±˜³‹ðûo% °uðKª|ä°ƒíÛ:‚~1ÈÑÞÏì«;2PébïÓ¹ë gq§r}î#ˆÜP£¸2£»Š¬¡µ›^?É“½/^‚·DØuÄ_CÇ—8q¢¡‰ƒ‡‹€šùy¥ïL¹MУ|êG r˘ ËŸÁLýÕ‚e/”q»Szä,L{‰v†rý‘ô}#z7ò)~èùQW HëÄšU.{moÖl;Ï]ªù ¦îTqŠD~AWþ³É ñ(·¨ùê|éKþ0³™.s=@é¬B&?‡>YÚ½êÁZW8ã&(‹253ñ¹#šŠ—PÇãÌht3ß"å`ü¬ñ>Ðy#ÊÈÈœ¹(BYöI†×bb8"– “³ÁƒÎ%ØXªêkÚºÈ\ÀÒ<Ðõ‘š'ïK§‚~ c­gH5-¿ ºW}W ¨1)_@%õÉŠÇž6GíZ%0ø[ì e-·»K°–¸/ÙJòŒuÉn±ÛM_gçdbþÓÑ8 þ>É}°©ž‰æÞ¶B {;Z=;ád¹†!$ }ßŽÊ ÈŸY,ÛFKðÎwÔÝ¡˜P!#ôÜh¿okwé8/D-¸ÚA£xä–FØÞG!0Bðž3õ%y/îD„ÕãL”®FúŸâA}è>^<?qÝNÿrÀÌË™VO¬o[y`‡^37HÂ'ÎmB ?ñhDDyO»Ìy&1;dêå¤3·j3µEc&µ0GšMÁ)Jo·' -!öðÐUá+“ô•ŠÇ콊EžFü®’Ù«þ—œ¥a‡ãİ_,1íßO“ÿjÒ^Sá¡-5ý=¥gs4ÇCW|Ÿšê{ðh¼>VI+ë¦9no1E·(è8cæï(B3—iÙô3â5<ž}¹dgÏ•,~Œ^ðô|­ ”ú¤ZŽ=ëžÕäl+ arŽXBÏý¿AóìPS9§5T”†J‹†¥Å>£oÍ’ o›Wÿ-5¦c Ø}ÞIrWs¡i…¬P§û‘-; "ôjŸoµ¹ÂÜÒ…lÞ¬¶žÒ…±wvÔ™&ž]e»‡r›¨•Nó"¾¶w’€ÓÝÝÌgÄlÄn-Ð5z "žÃ'œ‹¨©jUØ?ùí±÷sèx蕌åÛçÝݤìëŸ59†äò¬e6É,¦]ªŽ¹oêu¯ô®æ9y¨ÙÊ¡pʦÂê€ËvÚìöì"¸™:Ž7¦€¬ñs5_ÿÊ-µAxÔò™!,ïCÁÊ #D Æ`(écþ//h¶¢rpÁÊåfÆ JMè)‡–ÏÅQî~Îû%hDãùàã ’@“!hQ?†|õÛ!Ö·.¢fZ¸zøº÷·YþÁÂÙX,‘~"‘xçD¥:û èÂŒ„ŠØ^ÄvA ^û5>-Ê:°äãc×@Áê›èè—˜LŸÕÇü^ QÑèëTê9E!´šÀóxû 6³Þ»¾…æ6>ƒæH®MüÉâÑøŽakøÛh›˜âuñØ'ª²À3î"ü&ãyÁ0e`ÁüÿdA*Øî€0Nºr×;º ÊŠ£ròÏ}I÷…4óqÒèèWÐlÐmEͰª.å¸Xeì.˜ë-˜ÿº)L않éј¾rênÒ0&ûÚSRðÔð¨€*:zr>/+xø>j-ø¬&Cú1“F[°HY.<•u¦©À³;'qVU0%%Ìê‹;Ùás¹°´pØ„¬Ï¡fMœÓâ—ðd [_Påùv]Лn¢ r —Ë'ÙḬ̂l1^ê…Íx¹©X´ø´SZüCu¦S󒆑eKS¬ÙӦ¤Að&ós&É¡‰~5ÕøÍŒ+Ú žgˆW9Ó;õ$äØt§5£*´5Ø,Êž˜b½¥±Â¶å˜·RE‡Ì¶ãohFüNí'LJ?6î˜Ä9ÍLi#Æ8c,ÎV4µkD ‰d÷­©ªM-óýGÝ­ °ÆŒEôB( ¿3CHêž…_Õ™[À4©ð«Ã[²´'± UÐsÊÚ쉼„°f‹Ljb\Ô" ØÍ­">þ]¯#l0OÞæÒs0}ÎÉ,gïßÛߨEó}Vùú²fAß?¿WeKo‡®GF÷S$wys0SÞóÐŬ;gÎχ;†q½¼Â“wYCòýÝ (›Ÿ…1ÔãTÚ¢üÁöm–[]ß 0£¶‡+ñG‡CˆÉQÙHßLøb’Œe«éY^1æ¥Áè±Ñ£µø¯¦Êá­ÅÃç¬ú¢sëT™Ù*ã]{‡ÔÂEòÓÔÑ ñ%.¯UË“{庼pÿš#{¨N"9ñÚHoÙ£a}#Ù["n×X>ö¥AÅEÙiŒübÕŽ&A¾I—}ÈQ{ôHüyƒÅ¢ƒá˯ÌYÓïˆܕe”ŸH`‚îgZ¿Òc¦+áÔ|ë®D¯W½‚‘¨5 %†Ë’àŠK™ àM”º^(gjoI jç;•9nÈ~U6l`[Õ…û­1 rdµ¯½F”"Þ9=7*p[9ý„(üQhbÝå ±õÇ'.ý*1YRÉk ây¿¿7¸ÌI\ Ác„§/®^Ÿ'óWíÍ>EÈ•AA䟞i‹ý‡ön½ýâ÷Õ'È+—|T@\#üÞ®ùti~+ÞüCÂ雥Í$#AôÁh2ÆSµ,„7ŠûøìÇWzçí´Ez$_¢t¶®1Ãã³î騯}Ø“iÝB„õãg‡p·H%$æ<²…¾ÄQjPò­‘q’o„I.Ò-sÝ„Èú¡È<ùQ§^ûn—l_÷ä‡kþœ~8¼*ꩾä¨X)¿ Y“®GVA9†«A’ ‚ì!-ˆ=‡VNäOÿw;X»| ò|}Η ÿòb@!(èý‹Ð6Ð.2Áe´bÞ¬”LÕ:à&w•^›®Œe«ÉµiÒi6C½Ù3â(< ´©t¦ûvQy#=½´ˆNÑDðÖoÅy–ñ´Ý$Çc-Ûûñ1øU×5Ô2Âô`äÐ#Úðä¿&*Çà^Ç—1–NH[ØGmݘèx–»“Ã#)¹7;ŸWÐKèõcF†f ˆ.°­ž…sýjdQ½ÿ?/:†æ%2øÂn:ôƒÈ•ÕÃÆ%¸ qŽÔÝê®Q{ L-o5:n.sž‹‚~R<å‹ÒîiîÉ¿<¬wu×#鸔ë]æv¥?ÓùÒâé¹gâ@ ¸¼§Ö¥IÝ2„IÝ‹L;1g•ie/»ô7°Þ¸ c/¡48î¢(Æ/§qäFÈ‚\le>(ض³ËþgÖ^!¸ðþ}—ŒZ¢çNH÷’TK’r¯¸r†IH¯Q¿ÓjnÊY½P3ýõâÄó©ýýÕƒ}VÑ©³¯á\R;¿µšÊ¤ññ6 3¢Ð–é.ÏW¦Q¦üîŒf§÷s;}ýš=Þz+Fh¤Õ)<ŽDã³3üÔ‹N—b"ëôúÊ#¥Œ5ù&Ìñù@Ò×®D½³pRì]þ·Âæ[QÚÕ³óëÜž¶Óm}›.ºšÝÐ]Çðé[#`¿GÞVÿg[LÛ;°}®SýÈ{Ä—\áËÄv°­T¶½v¬õ&Ã(áà51¹÷.”ÝŽ¼±ÉÛF¥câºÔŽü…»º2¡˜ýF©yÆùh*­œº;¤mä4)ÈbKpô]Äõ)˜ Lò?}O'…gÖÔ­ ÏKRsã¡Ty_ˆÂ?£hâ4›«­/)XZ†Go¢ÛŸ•šˆê/8³öHJw£¥ãâc+ÃÊæ*!!‡J€³"Ó‡8 ¬bHN™{ÞX¸ýÊ™úU5—`DàTUžo&Pì–›,éBÍ€—œ¹tr:'/™€:ïf˜&…ØëÒÇu; !·êñ£c¾mˆBjÈÖÙ4A¡¨ËäŒzœÅ’ ¹8¢´=6æGżƬo6$Þ#Gö5I4?‘\©do-×úWúÌ @ß„Û H›Näàª^ïŒv’§±n •`›g(Íí9;ŒüNFlçE¨¢6§ÿMðIJåçj¬rÕLU²þÿÁølô²jÓz‘u¤Qb¦UãO}°òÛqŒ­–±ºÂ½·xM2‚¯à¢Zd¶ ¯-¼ßµ—ϽìÝ™ñ+Ä‹õ±£ y·t²˜t'ÌÑ\ ÓD7¸k‹ùÕ`K?D-MªOD@¥#Üì1qÜ‹{a>¤ð°39XíäÛsi·N]þØ}6BÂ/륛aÖAŠ}©Ä‡¢3ðh¡ SlŒá\G¦7z·™®Q¢6ï9‚›DuÖ»Hõ‡žƒí?MÚòé¢Ò÷̶¤t§âZ gB.h!àvOŽtÛB[·JƲ8æ»h‰’»@ 7üÙð l´·[7}mÑXÔ“™ udÆÉ˜Üʧ yWÉÈKÆ)ý¸á”~õ$ñþ½—ôä=n¥ïÏÁQroP•i,‰ÚpÝ@Ÿâývµk¨»ÔQàû’Æ :K…M'ŽÙ3+Õ9#Fl5Á¥2¨G¯¤¢xK¡Õ¡ÕVNtûGÖWÏËZ´;èzº"¿{€S¯k–NôûïVyA+²9ÞŸýoÛ£%tKW£ÇIÙ®ªp õ™hu½Ì&$¦Ú„¿ý—Žç(ÉRƒEö³Jaæ\„$‘…~r°Ô‚öŽÑ_Þ`N‘S–ËGæi,Eð1ê¿ã,joZóXÉ2ÈX¬•9„9ÍŒnrvi&®‘¢~ŸGiŒòW”Ÿ ›ÀBnŽ&µE1’™^{ÜJ@‘h—ˆœ31uÉöŽ^IÊF™ÿ| eD.TziTu›èÁâãI1«­=Š )q:oÌZ®flè:dŸý¨$ö÷´#C`m9µƒfÞWÂ.W­ì…óà~ݦ\,M¨´¸éî,üä®ï`Xª¶Ñ"´ ØÛÅì’a,"€Z 0k çÊäm=w>ÌLïÎî¾0&Þ~D‡o¿¢S™'u—±CÎ=¿›üÙð×u™Y ¶ÔŸ )–ÏI›7Ò”3ñÉ\{ i·Ñ#ÎöÍ™Ÿ®³­­6L5iª}ïQ¿’3¯˜ réÚnŸ¨BÅ¥äzN}X?Þ^Ä“8kóÞøÞç93N6ŒúýxìÅsÔøµÞ.(£ö˜¶)jHô–dO¨ èm¨¥n§N‰‚s#"{û›8IaI­˜fÖ¦ÛxW†~4Lî­Yä»äȆPÑëzûlоҲ ö©ÉãÄFçÛõŸG‚Ú% >Ã-£æHõ||ñŸÁØÂ°Õ½XK¿CÎÜÏK°ú¢ è´™ÏÒeo  jw¦2Ê›oN} §7Æw6Tš²L>¿ÎÃþ!‰”ö.Ö´4”zÃôRð‡ô¾]ûgà[„¸š“ßlbòh‹îf¿? aØžÙ…/ŸÕæõ%‘¦·Uî5µ§+0ì0Ïý ú݃é3¥zP}‚éU¡­N÷Õlñe+Ô´+e©ežAwœ9"ÊóŽ1ë‰ûk ífnjÊ€°*ì#[7Êcn].æ83ÁH~ûÄ`© Aòùw 04v€.˧ÜiÎ#ÌÙOfªýð®ã_úÓúø%~ðʯ…"¢|ĤIaOÂg£[ÁÕ|ßõ1£(‘nÚ9wÿŠŸy<•&ß+ÒèÌcÌLÎ)É²ÒøLò…JN™ çX>°…>DZ 3kÚÚ\µ()¡¤þn2ºB.aÚ·^T6z"`Ës€YöÈí™ÐÖ%Ý‹mrä—¯%îXÙ¬dyÒ6…ÛåD5•e¤±ëÿ¥ÉpXfO\Öþj 8Zƒïo¼ÒÖ)N×?a~†„™²q¯; ԅÖ 4“¨¸%µ«Þ®IR±¨ÄØ~ST?qiÎt "ÝXyöO!ì&ŸoB/fS`æÚvvh5Aoµ.ßù‘%øCð£Æ -3æâhá7íe|ÆLÁâ'(¿~mˆÒ…Â`Dq=]•F–¦·×0p%.p5ˆ“·.V6ô‡æ#ôÀŠÔ£Å¢Bw¼¥ú0Ü-òa}²ÙXw·¦Û{d’rM«t-ìB9qô Ãâ”ÏÐ\nŸÞ>¶*dO0vw›ªÛÞpªîI:®F­š1n.´Ü©wm0©Ûs|Wì9ø”ÞË&Jw³äÈØôkÏ8$é+ëÄIMÑ…ÄÑžyÏ“JÿØ•Ÿ)ß„pÂø`W™{á{V…¦KB^°¨%­¤ÏÅŽ[Bðo z¢Û¡êZ_®ZŒÊšûóhnÐ3šÑúyõ!P /#Hp?@ò=OiaȵßçÖ¸(ÀføÓ[l|¢ Z2Qt kÌVN‰J´N3ý½Ÿ>èÛ£÷D™ÜÆKä­÷Òä1†{UàÓYïŠ@œT>J¤têç?ù–$ïöÈ‹ÙL¶Æ¡Hþû€SòÊ¥Ñáá24+ªT„ºo-Ø·Å_ô¤®8]s»WP:Cž*¡*üèQ…æHMƒ¦4Gw¢ŠZ³§'¹쬼Xõy¦f¶’}Úˆ41öDä!êÀTíâLZèŽu¾ 5 y!Ï|œ´v-‘@œ5Ó+»×ý-e”°‡—ϲ|è‰ÀlÐqm+­½i§»É¿®;)å³ý¹.* ’#š×Ù—õÊ9ÒYý¤Òþ(3+1¡aS»èB‹é8°µÝ“Ѥ)½•6²àü˜4˜j„ó_ø}|?OÞúy Ù´ Ê4¸vjyüzÑUê߯B~©ý¯ÒlKÄd6š®Hßò!è Q þšþ{c}r«FëdÚ/‰nQ®‚8¬}Ï/âð>ê ÏU宓©pì–˜¨²ƒ*VM²û(F¦b¶û^·«5F¶•Qyã¼5¿r³I7<›î\s²xö-»Õð㣯å/³RŸg…”œT•róüe€ýxÒ‘›È1/¬/+}WBÌ"WEE×]1{O'““»•¶Ìg÷Hª³¶ß•ÿ˜*…ï%"p¦2ýTfXŒ³i]Ë$o^ƒÑ‰rNàV@ô•5W¾îÍ(¢—µ^;9e½™¤"ÔpCì<é‹g%ót½a:7| ÐÖ˜ý‚¤ @Í;”£µµÿ`7È?¾$·Ãç§Ï/ô¡´¯ÃàŒ¼Á çà ¾¯áA²9tš’ì.6tK­*ÚØ”«^{t*7ÓÐxflh—Xtb~kàÁfþ1! #Ýš¥¸}´ƒ‹ÿ_ÁûMí4Ï'‰}ŠèDXÒ¥;fAacsŒ'å!(_Ï·¦óÆ[·ègœ!ÏæP+€†VmiSô¥Ç,áѽ‚Ú÷ šîˆÕlÁ(‡FÕ¦=Qk Òj)-êCûˆ(t55ù ·3$!BdŒ%co+¯‘æY_ý6UÊå†u!ô©èf©^–_(jUð Åô¢kŠÜ«a±KLR™¼–`)×=~6Mêvû%Æ—WÕúùÍŸœ~3ÆV9EÛf¿|“ëõfNןA« sñ8õ]Ž×hâà ·c“d5(=*fÈ^#ÿŒÆÃÕà^ëu …»œT ë…#(?õZÇŸ÷ËöNßUšKþϳƒ$\aW‚wÄæ OÕ-w´VÇœ•«‰>.>tҶæHÈž¼Ýexê¶š³â–7?oœÓgåE‡~ڇܿÐ@¦»üÌI äfÁƒ¢NÂUJ©9ëÅ)Q“¼ú®´•À·x< R%bdd°ás~ü|?C¢"PŠBúñ£'ã.Jµ R×BÓua­ÙK]U¬¬9%qðÔ•I^äÐçˆ>ènÔˆ<¸o¿G+ , iœß—÷“¼á‘²¤¾Ë1‚;M2I|êyéÀ`¨DL¦Ií3nÎÛÒ/ózVóÈÛ¦ w/-ñ)wûr-fWï­Ç¦V¦Óx`+A2²Í (ÃÌ~8V†zqåeF—s¼"÷‹-²ç¸8UÝûKWD2\Ý¢ÇiÅ-/Èú] ç@ŦÌl¤}^â=2àpnïµ…{.…ÕÇ*Ea`æ>ï¢VŠQ¦‘Žô,C›C+áV':z–I ÀdˆY5yŸÙF)¤_%ä3ššÐV“-—©¨@%Uœé ±eåU˜·ÄL‚ì·ØUCå! [8Rì>Ö-L’i› ª€aPõÙ ¶áöbŽÑ 2»³áaÞ¡eÁ…‰€,ÚgÍË ƒ­—~_Á§ò¦™ùt1Æ甚K*éL/ hßñ;ˆc$GC¨s‚žàÖZ½ë‹jà“¾KŸð¹ã  ½:¬)vu%ÑŠâs6iMVÖoÈb¶¼Tÿ#þúœ£§ŸJÅ'ˆÍêkuÂfw6Ì6Ëay°ÈyJˆð–¡í)¦,㪅[±¶x€“7,šS‘ kmŸFè õ×’·ŸªÏPÉ’g¤i™hA°=QŽx/RòšbcÅvM³@/LÑ„Fø÷ˆ×Æw`ˆ6RUq\+<$¬ œLŸ}·ÄëiGŸ¼5¡ï[]™pCÔŸVåR~-V3–LÌ;?ä>·Sæ|˜e¤× =ÂnçUZ§kYÿº áº®|"*5¸ËÒ÷­/$¦õÍQ2:wƒ±ð¥?ö 3ÆR%n+Œ¨Xú½2 ŸWž“kÀiÈGͨøÄðd³Ï„á+¶zÊF„Ù QÔ#ÄòT1ã è+烴=n-A©Ê¡‚ÈOÇQ¼GìG*2µ¾ý“æeÚ<¬M¨mÕ‰e~ÀŒÚœKæ¡5\o¤5±Œ”-b>làBré:?ÐÒ±½Váçg¾ƒ¬.9-¬€ ú÷ŽÁɤïa÷¦„0•;s×ìbpÝœH´#J5¦2£Z#«fÒHW‘¹¡[Þ·¶‡¼¤žô¹lRË=c9^ø¼h ¯x‡f&¬WAƒ‰ÌÝCc¢ŽE'´Û¬-'wJOEjè)  ò2 À—Á¯ŒÊ¤•û ³-g¿WÑ~ò6#œÓ]×l®¬'?–?È a»hºÓ¬×*B‰ˆì‡ò¸GI“#RPèÉ›ÍG¨Üý –!ö*#ŸøYé¹—2‡-ù{ת»W’â† ×Ø;‚rŸËÉ'=ƒ¯uî”ÿH?–ëøIF¿ô‡¢ £«OóæxÝLw”­&³¥¶B^Ì`ö‘¡Ü;ðÎÀ¯ýØ…-5+°ÁÊ>8J·^Õ:Þ^f—”Ò;˜£Ó[úº2ú ^˜;Ó2.` ¼°&… m–mƒöÍOëË¡Uû¨ñX«dh Õ©[¾Ž Çëb4§à¢ÓnL=„¦Úß ö}h•­Žx­Ñ¢EMLØ'¦¿vÍ %&Ì_;ÀëOó¥@.,S:ÄÑùª!ܫ̃¤À´¿ÄêÈñ;,m7Ñ;TÒBšGmSMÕ=ãÜRf”#Y7 •%ácêEíäëÀCÎãã®EÝÊ×5ûr÷á± ëØƒï6ºÈq иð«eˆãLPàÄ&b·Ë ±¨1Ä)½q*LÖ]ZÀ VŸˆºŽ¤îBz»»èZºGíGs°‹‚qgnòS—œ8Œ<ÉWé7¥(ÍWGRáÝ9‡à­‚x˜ÅWð¼à˜_³8 ƒe`ÉìMÍ~”¨)§Do©øSþ\š._#Øswb†@b`SÄs£¹†]Ò®ßVAÁxiÊï³!Ot¾6טãßÝò9‹TD*%5ŒÍ¬Z‚€ihN@bø¦C²,¬%7ô—óH¹Ä °UuÏÏXœö/Õ§Z킼²Žh:Xˆا"_±Ìk'Y)œmƺX£1ü0‚ÏøæÞ†³Ý¹Ó8D[g›Ý†šr‚ýÑCØ$¬ZWsr¤Nrå“`9}Ýo‚Ý®~|ª;œptX…X–FO á_e*|Kô­ì ï’Å!½|ˆ‰¼­0‘Y)M?Õ¿9Í騉ûk4ãÖœ0߀)dd`ý—³ÁÙ&‚!’ /†ömßÔT ¸a>,™ø*d¾c>[êR^¼ˆàÚÄ7¼%¢Ëž.ü‘F ª•Y mÀ„,È‘6[” ’¾ƒìŠ})‘G¼¢:ø{1tìuî´pCô6Á5²`ûM’N¤MZ*FP5Ø•i“‘ÐÝ-%–®*"ñÒ¶‰‹é‘iåt!îR·ïXèR@™°ì b½g23ò¾fÓÊÁÒ/ˆÑK;½Oº“8 z˜î"Ž"ÜK$DÇ—µ™®ú|Á¬¤§6‡²‰ÁšG ]37p.`j"Ä3 ‚ÆßU wì’í¾kG97×­Ó?õ/ç9uûusÜöI„_çºÙž4x`~tVã¹#¹#r€¬ë²O#Á¼XH·Î>_47]£mÉÁÆCë™ëÛO‡YHÇåX³+«5>¹=ÞI§ÔšàªNŠ‹ËѲ¯S…÷¢Ób¤CŸ¡°ãöB7c:Ù¦Îé%2Þ÷ŠžÆÿóU³Úúµs°VÈjG•y9OG—Ç~±ÀÅoJ¶ÇäëQ£ˆ6¹‰M„¶.CÆtw‘‘ÇôÚüš$Úr6Ôögy¡âʯ~{ÀðBAe`ð§,Ö»ù?Ä­ ¡“wGÖXSmØl‰®À–ë ³øØµ’â±lÅàÁ|$†Ö¯Bø„…Œ~$) ¦ˆÀŠŽíM—Ï ¡îƒm}úFnÜæ<à>›.Ý®²Ø˜ P$¸/aY +_·ŸHaLÇžo‘ñfí%R•ì»·OˆÙ²{Ö¤Lx(SèÈlc»Óµ¬ŠM s ª¼e!ÉJš€ÀlHoæ›H·wQ¬;èhjì|u¾ Ëä"à$TZZ°àJ ÍêMS5º¶|ìc¿¡Úó’:šêï †¿Ít‰©3Ù²Ë(õË·tS;d_7™¦¯%íã8ª¨t&Á)ËNÊM8¦O*aÓ:Ò9hßW³Ì1'ðÀG ·ÿsvWp@ùûdÝÎ_÷Eà "O<§ðC? ‘%ÅY÷pžUå¸Z²©ls?:‰Eä)µ¥¼ÈÉÕVb¢GDöŸƒ8«[ %k¦Xö¸)ÖÌ„é$ìˆ{Kw+<=•²ð®øÀ{‡¬ÿÓ°v›Ÿw /áâÑ œjÉqlW©æed‹+±Yü¹›YyxIu‚Ùà—m0·LžÏ¿\0ÉÉö>Ó±B©6Ô¨übÒ eÔƒ›%ÊOî/â ¨]íjòÖü¶ †Ý-)S³å=ŸÝvNvìª3LFªUf9¦ïØ"æEüÈòÿ4xìt¬…q’ä#Œ£Á­ýhéC^|ÍÊa~÷Û¾dÌj™Id)È;2Zåzßqš¡€»,ËŒ1T OYºm^_oB#„<èAM§)ž# 0ñ(´M'ŒÖ‚ƒ¯~ÛvC/¬Ýinƒ‚h`—×½ŸtŒeçÀôj!mÇ­}ªú7÷¯hÃ%*…lOx&ÀBô ú¯ÄÁ‰ÜýQŒž7ωœE¬{:Î`Ä›®¹ÍrÄM\“¶ø7.[Ô¾r7)p\D¹_:6ù{O‡w§ÍkzÈ“ßÌû©$øœ¨ LMÉ”¼y#¸¿ z€62l-N¸}³èÎ-.—è|ºssrnt¡%k_º•fë¦5«’Wyòþ£zSû ;Åîið¦8E¦‘y¶w5}Ý"®Æ ´ñ¯•Êhuw'«J×4þÅe'/æ=i•ã35W:žSHq®BÆ­%tÄÉ\¾'ÖQÑKQGØÃëÀþ»xb¯uî„Ø!¨¬€Àx*»*ùØŒEåö»Ášäzï®Sž‡ÿ¼Œõ„&³r0~‹…§Ž˜i„«÷ ŒÜ5úvé>D²ääýÈ™`ºË ¬NJv<·ó.éx~sxF›_*ENÍ¿"¿))–÷®|~Œ7ÇÎúY äYä`œ‹¤õîŽ9ȳ±{T`h’ø?Í¡I4»D à!+ï@`L?â?O ‰ÊT”¿{î[ÇùŸàÎF=<-ÆÝ¶Q­Õrž| ù f?Ö^·Y¨Á¾9-G™CÅ¢Þ` õÜõò3šFš'›Hlyò|@²›hP" ã¸2“w¤ …\+h‚©ÏÓsMïH䣿þôÁ¹}Æ:êóÿJ†Í¹-JRÅ΃ý ¾MŠu•±òûÕb­ÐŽâz f}H{*øf#^ZÆ‹FV˜„&öxÀk±› ¼z>ÈX­hnĶi*š`³³¶©CÙ,Á“‹f1©JÙ¨6“Š%~0.§§Ü’‘HÚ{ÍY%U½SÙ‰ÛüÈŸ uÌéÞ–9<ÿxNè­ ¥cÕaô¯ $“ÊôRªÒ­™e±À Ec‰ûý?¾O 9K‹eJ5ä²#àÜTE-ËUAt[°«ZOsÍ0’,ácyX§v¹¤,€¯l} ÖR\ào¬AÑÈ™p>=ŠQ÷ÕnfÄzDEª XÉÎé¬m¹My¸+-«Ž UCíÃ¥Òæ%â+ö>©Ζ¢*Pºšn¤:áND;£ ¡žR¿o7Z°œþÈRSŽ GäßåæMxŽöX §ŠuiLŒ²¶Ð° O„Ô¤s‡]n[#À›§Ûk÷, ëp©í¡ñ»»ÛIÓ£ÌyÕåSÐ]T‚M"£ØÅ ÕÜ«ú–6ãnbÊF³ »À¦–üØlÈÕbáôÛ-ÿ¶eÁ“å^>Ž7¾~JŸ®'?å7Ç}DG„î‚dXo=*_¼ßÏJ^c,ìjö+Ê‹úPór_vÈ‘@+K>ð÷Àj³ôßpg«ýŽól9Ä Ôâ‘úƵÑÌù(}ÒžßIå•.ÆGm4ÐùGÈ»N•©ºÿ1‡8B&"ý=K09ªa°Uùºé‹FhGu±Ž ¦†üsº!‰¹épÞ%ãp©ð½\œk±çÎÿfºê YC5Kx;£Noþ­ÖmmHÅ{zˆä%I`q, ©A‘4¾·;¢ºl x£Fbµ• 7¤B±[òN¯3ÿúꟜd*rê\ÀiœÄèv¸àpa—"ŸAÓÊ/ÑünœM´]”¦49”‚щ¥{]^ò»Xpq E›WÛ÷¶œ©[óòtIÍΰ€t~éÛÿÓƒ>m!äsO³—¾H‡~”M o…°RˆG xÝ HAšC¶•ž4·‚¾&²6¡ÇϽjÂI‚‚þòŽô´{iYÞJg==òk]âäú3´Y«£dz$•~ÐN¡ç¸ÛÒÝS÷G½’ܤDMì3VÍ ƒ3JÐb, {!cå«oŸˆ6ǰT@Ð¥·'LcyËLŠ4ðDç¢|ŸÌy%ZÃÏÞ}ÊÓdh|aÆKkü³.7Ãa1Lw¾(õ®.õåÉ‘P;’räË<€×ë:ù»O9ŽTÀ»ªÇ8çRn¢L–J§j:ÆÏ±M§BÆ¢žšL‚G®WØ"û^2ËYê:?Š6XøñB¥‚ ÈXžÁë-‚}‘IÑ‚@ÛfL¼ˆf›ôõ; <¦t±±ÊN ØÎVÄón/î€ @½Ç¿Ð¸PÕ|'9÷·üE¡Þ\–Ò…+%„WSŠ V¯vê"Ep²\­dŸ*£ßpRAZŠ=ˆÏ¬#–‘kº…„ÑÆ“‰ýš‰}[ÕÉÚ6!$šL®$¨n|¢Ù1e°!_~dÌYê`aD•ñ Ñÿwò¨O©œ€T´·VXo¿ˆ/¾|ÊV‡úIÊäÝ Pà T¥z]NÉD»‘)”ȸh#ç«móg?asfÀ€X"š×äfe(pn³×sÎqš>¶¦£ûeŸª½€­ûÑóû‚)4 §Ðý…ÎŒ—¡ ÝÚ*ƒd"Þ„3z^=Õ¥¯iµËèÞj_~†q§æR\~ß@÷×zqwûÌ@E+ ×vO›ÑJóæÇ.Á€OjøwU·ü«Q‚œkŸ8\—PgE«?ý¦Uíxs¿¢BŸ+5Ĭ/ *b'ëâˆdÛÌsÙp;¤uæ6a˲êeC‘L³? ˜µÈõ{#ñä*Hóe·ÌÈXK­—lAÕP2[= ¹2ÏlcÁ"í¬Yg¼§”™†æ!¯Úy:Í:¢z,  QrÊÆZêOþƒ¸¢ÀDòÐ?1‚ñÊzT¹[ á’Ö¶©ä¾ N]ý6‹”Ž×³ïBj”žvÓØgn9ª vµÊ§¿Îk£ý¸ºëÒnÜz¤Q-]ñ™sÝÊJöY¸A"6Ÿ¿Ò®'gT±Mf™ ÖFë“&Lî?5³(æܱ¦ðô¸™j°Ë™úéì÷ùTž¤r=õ ·b´‹oëµkI³Á8¿²«¯~/~'»@IÛ»9+SGrßa&„"s ªÇæ+ü&°ý왹CTWÕÏËù‘¼€PÇJµ½¤¤_Ýîèiêv€KFb¡\ º)èŸâÁOJXy+ f8O·ëᱚ”ËÀÅR&úñ•äôáGL|lAõøºæO—úM¾Eè‹´\¸äâ<„PE1ÎyèÍCGQ4Hý_^÷OVVzͤ™>xo“wO¬ÙF™ó)öñ(BœD±þ…«Ö7j£ha&‰ä‡2Àô˘¦hÇ?¯Ð<?fí+ÌùÁÅ®&‹E$`¾f±j=½b>õ޲fäÔ!úŽ·b¼ÿ¸P(þÈg´ €ä#ÝÉêÕ°ïÕl~^o´k—¨÷‡ x_múžÎüâAç8fzë£e2F ‰ø¨ßù¼–…È‹Üßð©Xâ­Ý­€i(^Zù9uKª±-—¹[½;|²ÞQ¶Ó®Í= S“½Àø-µmã´ ïü˵¥:——²ê<å9ÛDci1ó¾#ÐM& 1ÚŒP-7nRüÈSé Ѓ nöšÉ,+}cœ»¼ð¡†eäÒ’Y­ÎÇ uŠ4 õLÈp9º^ÒÞ«t­žš÷B#7Ѷ3±oÏ{UDøåA»ËU›h½ÄÞT\0@£MÖê=÷—¯ú‚øÀÒ«ãrû`%à3$$ë¹]ØþÝ1ÀðO‡Þ¬BPÝÃ8Ãß=D*Æ?Ü´kÖ™§GäèÜðéÙXaûϰÿq²ù¹d­c¾é£H‰¦–jÐÎû/ "~!ÛéòÕ‡„l÷?´9J:æåT2'…½z|¼NÄÉq®È|´‹Ç •p—w;mÌ‚TÑâ-´Þ›’€Ê“S¸¥ÍÁ£G.g¿™ËÂS|õA ‘þ_*1¾3õüï?:I=ýôúþZ¤/¡x§'†–áÿŠ #45ÎnŽôü¯~K S÷bCmŸ¢© ¨£TÞˆßüžÜç6„ép‚¼lîTÃ~ðžzú ?6 œîr¤õÒDï]ðò)GƒçëëqU§¨åVWSöþBŠÑäëÌðÈR»¤idš½M\ãóù!­¡úÞ²—*Üœ|bÈÈÁ ‰ö5ÂöSœz8A®ä Ÿ$Ö¼ œ&¬3ÜI;ûPl•¹n£zÀéB«dªÆÕ4¼ƒHQáÖÈ2†é[’ ú·¹Úàn)–Á qà]{Áž‰‡o5¶J’ÏÓpÚwRψÔԥȭLƒ›ÐkýnýØ_-]àÎVc}Ãñ]ópB$ä‹ÇÛ47ìÅÉ]^ÝW!ˆí MŽ)3'ÿ˜¿ŸcQ`lõߊ-MȬüTS æ'Ï$‰¥`Ñ8Jˆ8¢m(÷áC¯èŸ³I܃`ʸQ+Ãâà9c;:ÕfÙ/(Œ{—‡øT:ÙƒKã¯/=¬ú!w²Ö5f»–Ml4ªÀÝ£QØ ÇsŠa¿E·²…€†ãx§²lË£Kª‘´ŒNáågî;3t¹V2šn°ïHÎ-äȵ‹Ÿ?Ég'j™OúQ¹“* ðì ʸµšä%±‡h  FœÝ ¾ºÖ¥°fRì¾ÐR8OÐÏX½;ù[M¡FÅ9J>JêñuGxjx|„’˜Ê˜Ÿñ2¼aGÓ5¼Š"TÏåI$¼¶ßÛJg—š#ójª9"žé1´Í¬º–Ó+0™ ß?vQÛ|Lâqânµ–œÒ3eoÅ•QJßjxÄŒV¾ó±~›7R†©’r.›:Z'ä² ²Ðw{èZûªTÕ…ozàd5/ß Çñ—CÒGj4¶laùø|ª×iˆÆÁÂ}!·É$D×Ú•´nîes‰üÐ÷N>s%ë… î8~XQ¸7@u|©ÓÆõ%æÆN¡Ÿ¹{Já½:ú²ªç¹%»ËKfMߨc¦jQ¾ƒ´c †„·ïôÌcŸº*¿Ù8}”ìñ«GTs„ á½­IHøÓ¯Úcãì¾=?‡ØÂá,LìÌè:S²×»ß§q fèGù‚Á=p/0ÐæOù²i{€&ÿ¢¥ºˆ˜=cOÌÉÿ0ð"“gõ™—@É ÿ‘êÆ£l”á–ÈŽöÀ}ÁËÍŒßJ¨©Àxž A›öe÷ ‚Å#\Ó`E4«ÔY¼àè‡c“{Ÿ3U nÑ‹s6F}'‰·þÑØ1SœE¬ûŽñåJ6êPÞr[¿ &Ì¢,Ý·c'³q¹ÀY¯(n¢’7xKH}ŠÑëéó-õ¸¦°Cý”½þ;CcÄIv •EYã5?Vuøï^ŸÜÎ/Á××è•,£7”Óþ:Ëvèô«°$hñäKùÿq#¼ Õ2ÖQ”ÙhQ´HȾü@KY’G·nq8Õÿu´¾¦Ýî+6nÌm6JÆY ÙmbðRX³ÇÂ_ôú=ÌôÍBN²³d¤ß«.Z]÷@}ÑùÊ8ùÔø¹™Lv%dY´8ù Y3Ôû÷c²=¸à£žyG¬SU‡( y³íð]ÃÄÃ@¼«½`ÍY¼d¨9„03;þxcf9Fž%ö9}¸Gaû¹Å6Šþ(Á˜™÷¸·Ï5—lÊ·‡Ð6…ªKÿmWh”N_¯[§JhÈ,G’j²Sb´‚’[Ïy¼Š¶†û|µFDÿ@±Æ ŒšÈgs 4û,™- ; 'x˜ÞNøE±ÕÖ¨Ç|Z¥ãïƒã¥/Ðú“oÉŸ£êÝ¢lŽwÓL’ŠÍôý>Ù0.'Ê ·:êÕq|á={Ú”Àaºê˜zg°Î?mÒ=ʬ•ã¥t‹Mš^‹a‚ëòឪ$ž26‡v®F¸l”a?ðáBqxöÛh×¾´åÜ¿Jnnµ-Ä-Å ºãÊŽ¹ gT2n³»}üN¡OrRÍ}vJºèP„òŠzÔ¸[ÑÄÜÇç×j#×,>ZÎÌ}cØ[â})’—£ ä.jÅŒ‹ÇO{Ö«œÕAE:pÕCß³ œoJvO^ 0ÉŠß¹ôÃ4ù5‚Q,wôA‚e=Vr;$ êa‘òïШunKoF¡°Gb"#_p¬ŽôzÝÒ•ÖØâ§7ðRŒf|Im‚G«Ö×h##B1ž}D$õ œæâ9-Œçh£YŽùá|q¿5Îþ9ô¦?”r1ûô{;4¢ô ø§Xú›¤ê¨ðˆûFîœ%,´¹ÖeSžã97o÷íHiö–B6Fp €Í´ÐEÀÆñÃI}H‡W¾ùYÈE¾bs±¾RÆ‹q fµã5Ê‹lñê« Ñža®èSe­Òî2‚õuÄPsSB2Ï»áÔØá¬ ÓI8¤ûªT$Ôð»y!šÌ>ð`uïßÉ8éÛ9†}õóp©F|é À"‰¤mÞ _ngÖ\ا'í0X›¸fÄü}N×d›ªÑ–=ˆ”¬>?¡¨Ö0…r Ìá‡Çh·- yÀ™ ·K¼¡…ò>+”D=ùÆ3¹Ñ±ÊxõJ…Û ¼ú ŸIf“Q½c°¹½@ÊÛWɾ ©©‰9‘5ÓàË,Fqõ²ŒÍ<"žÄDXâ奸èíÝ ÿï¦dRx~%ÌÈm¨$Ð]lãwŸ‚ªUD’ƒ O*‰rA×]tq3YËŠzà_·F3ªFw/1sÊJgJuþ©«d&rsÀÕC ð•k¾s¢¥<4qPžªØh—­´;æÌäë¥)´êpcºL#ójÛ]1r…»”Úæ†(nÉŠ^žb?o ¿çiJÏ^C§@7=H)8?I55˜yn ²Éví°ÁÖ'tÓÿ’%`­â©N¨v>øý=åÂÔƒAü°6B¡&öÔØeû¸ÅdN¶3”ôôª{Aƒz¯Œ ‰ ‚ÍËu¸[±]Ù= ÂïEÒ^ˆú™Ø¡y(äÊó8›JÊž\Ó¨Îw…êÖÐ/T~j…öÙ\ã”CÝÅî×ÀR®£~Á–'~-)æWŠéʺNð+ë´%½³Æ÷]œ[R`ðxU»ûË~Þˆ\“òCßlÚ÷ÿ´† Cm×*šoQyF‘@S'Ê,ÙsÈxõΨ½ ŠÂ\jæˆ,Œæ ›J–‹ëóó&™{Ô†ñ¹Ó%(üš šmé!ø4êÞ ©/€€f³¾œ$×™w<ÀD(ú"©öwøk¤Ól£æg­Èóý)ÌyS ½œ€LÊÃÀÇzóž\ÕÕ`É”©¿E¬Ú]t ‘˜ÂÐŒÐG‰‘8ÄÝš#ƒ€–à¢Õ®Â)« ›TW%8^TF-´Šåþ£”,úÝó bõaÒD§>è—cê*м Ã…vž²Óœ%D÷’¶>O0ëÐ5LÖ¶ å·“‡‡Ÿdñ^Ïð&jˆ÷Bt£¦‘»% (C±Õé•—Ûœ}Ób¨¸_Ç_¸tU–ªëµTû,ç\—~)ÞÝÞ˜î“í#–¬Ý$â&ÿ^iĊƼâf' ±d“Ýi¶¿7¶¨PâwÞfõú2‚ƈ¦ñäü®‚ühë"T^Wu#E|,tG„FuTÍ¥2¨ —ÍΚcìU%M{v·_-Ú¬k\˜èÊêûÐòeÜÇÎ õé*ð¸f*·$j϶é4‚ª 3%IŠÔdÓž¤ÖùEôÆk]šUéóó1^¹w‡bÁ/O2œUÃGŒØßñŠL…f)sƒ\ËÙ›5U‹ٷ^߯ÐsÕ)@àC24} nR±ª¶‘Òû¿=Ä +l>=íµ,óXŒK«oŠPbyØDJ8¨oB~ÇeÏ6´€›t.Z{/JÞ÷Ü×4?cCS*RXè,ˆè¹álE1‚ë:Iu> €/\p÷Ɔ¹l!¿0Dñ,Á‚YH<¯6!|Ö(À,_Z9UŒaËäñm®)i"ji¹ñ5C«ì“ŸP:\C66€KD¿{(„‡Ý” põy®^ÀC£uÙ“”bKYJĆ˜ÊJ.Ä‹ìÿ"sh35nh•QòµNø·í§ÊÅî¦<¡I’’jF]u.Gº‡V½´åt]Ù½ßë–ºùžÚ–µÓ¤è>eú!A´ 7—!4Fdq†ƒòv£Þôµêü9ÓünÒô¨ÃMÛJ1”™?F·,F椎´/¬pQyJ¤{3w߆N™—ãÙTY$2Gõ=¤Ä K ÄMdPò$Å›/Hgê‘€ÍÆ˜"7¶+På|=Ü{+j¾ÈŨÇñÒò*ÆÜ C¨ç÷aC"G;çÒ©¨³,çyÕ\-€¢â"»šÝ§-.Ê„ôç‚'‰)1èmYNtdùâã;­¹R=·M!F‚o°YÏH6Лm¡xg:Ù’ÆoV9æˆ0ùb£8Ðb‚øgp/Oê‚ÐE¤ûâÞë9Ü@÷î~h!°n­]ß=]÷•+õ­ß µ ‡›Ýù:·AWÁ4™ßîh°C¬úL‰œšÑ>Äú% ï;H’ú™OñàØžÈUH®0cšgêv¨]Úä†ú@v=úÇúÎl²EûŠØ!LâÐÖ¢Nc觤?‹&½ð9 ð•5Ê š6ýC ð”ͱ×R h =§;lÚá<™—ÎB)¦EE®+ØËøƒ–6’€êuÏ  š!n¨NÊ ýCëÂ]͵¸üDŸbik\Jžpâ£:ŽœÌTƈTbt® R|ScÒé ÝP6³ÿ©SLF€—FG¿ê"älЯµ?>ØH|¤ #þÀ€‡–'~“5ßOBwt¹]¢ÚàR壥TŽB¡Å„„YbQyþ#—JÎAT…£ø+Â|©°öŒ‡¢JJêö¼ÂæÂ_q`Umåï[µã±ÐèÒ!/²2pè㛊ٲ¾2áŒ@œU& ·˜ÏÞM¯µ£=Ž6¦Epâ¶8θÃAºŸÊŒÿ®WÔ®tŽ}þoN³÷s× çIùÂ?ˆ¼éªÂN äkøíFæÖ–¡%€C&«æIhâiÒm$wС8µŸ’c®2VÙñ„óê÷røÅ „¼“~È Ãy‹£<óZØfÔâ B| ?¶gÄõïUMì{ZÔƒ•¤‡Ðγ‹ÑÔ»0ÕŸîü¯«]RME³Uúó¥Ï¨!„F•%«Ó)ôÊb°;mF@„IJ˜„rÊÊ~RׯµPo…ylÎ¥»”t§¯ôœ÷®9‚LCäÈôŽºÑÆÃ¡QÑþ®\`Í 3€>6öÔøåæ07j/‡.¼)bŠCÆ~JäF´$f?·R×eÕI’çK¦²ü9'‰Ãó)KØŒ¼ê–˜QZ0ÊIë¸ÏåÐ<÷2 °85ŽYEèâš0÷›逯؋ï`”4ª÷@ ÇÁ$úSx.£ü¸™Öl7§~¡òE>(ÿ2RlxSü®†#]Iåa‘×eê!,« "ºî¥lcâø{EèêÁjQ9Î4~é¡U<Ù/A$²uãsyÃJ…Pt!!üð‚?¤iûׂÝ3–ÕMñâSHÝæg·ç¦¤OA<ùoÅ2†ŸË£ÖÝ ð‰…ªUn™Ÿàc¥!¡FÜ¡:ɼeÁüyh2Lˆ>l¼;–5ýÔžóÛbx¼&ұgmþ ùbÐ+tû#mävy ¥’wZÿµåÝ7aìÃ3«}ŒïЄ›ÆJ‡Dá'¬¤v°'Sìà .€SxI2úûC´Vþ¦¦Ç=í3*QsW2ð¯Eoõ‹½H¢{VTãän_ccO R‰–«ˆE [ÛÈNƒe€jþGó3þ3ÜâÃgƒñŸ·±þ ÝjŠ‘—áb3n¦|¿v¡A<@§ÚLþd7ŒF'‡Ù!‚÷ ©—ÌÕ?ÓÚ–ûƒä¿€ÑXskº‹ãtKÕ•ô åà`ÁËàô-Û¿K¼õä4ÔÐ,<Â$2OIÇ×®É}«2#[û0cŸñg[ÎX÷ͱ›ýB·í0פËì æŸÚ#4ð®¹GÌňìL1ܹ³ |΃£¸Ê Y8ÛVŸZ9Úƒq–^RãCKôÆ{Ùý‹’\íGÞy—n›J—&!Ûí¨žÊ*!HG´e뤡M’òÜr˜ c¤Kš9(šðoúKªÊsš_˜4š N¿_Uš%ùʹ‰ê昛U#‚'Í€MTÑãù­PÊt¾Ãv£Pébñ⡚l©[># m‰‰Ê ô¤T{ÚpÿQ؈`{5g/Ò2[n·HlÑ'’;¨3aƒK=7‚J6îö ë‰<&5¡³¤OÍðßœÐZ×Õ›ˆ÷³ÌœŒŠͰbØâ}q9*ÆkXé¼ãBîϾŠô Ýž#ÀÊKm†™e³ƒèàÍ&¨%\þ¨%<þõ¹j`è_UE0Hw<‰ùÊþÇ$!²¨¾Žî qÛ¿•–Sýæ0#[) PÄã”EÌW›}í숇LCå1“ÿcšŸÅ’Ð ‡…û(;ÕÈÊh…LU“¾$7µÓ¬š¬-Ý„¢{ÎMЙ‰Š„©AŒ»¶ó!LÙ0~E Àúö ¡fg×Ñd^“½Œ §5Eë¬G¤Ù7v“‹-×Ϩå¡Ýeäߤzár®n%ñ<ñÌÁ[9(~„¨™x*qr¦ƒÞJkäûë;o†_/’?µ¶Í7k?` ê³6ðXÿ»Rç˜bÁ…ƒíßõ4DÙ…÷Ju]'B‚õ ëN€Üó'L yQvÝ è¶€ŠM1ñ.ä…™Ñm«¤i¢TFÍ¿ë‘ãQ†ºö&ýZá*½ø¸î£¥d|P¸3A˜·R$Ñd9A} ƒ·S¡úÍ#É7ÓÌ…âœÇÃ{¤E_XôDRÙvN÷e-÷°Nm )qÏ|RÈÔK¤m”àNDx¡xˆ=ÐwñWXÃXU¶r¾ÝËlzy6;0G ¸ ¬Oj]É«»þ8ü€ÖYÞs*G–1ïtSŠçýF1 […¤³¨4Ô#Mé|/¾ÿ Ãñ}ŽguïÄ{r u€¡Lmlˆ8<|y gó²x.¹rz'!½ª„¿žæy^Q‹ÞŒ×r_6ç:j*´ã[Ñp^æ‘X›Îf¶·ÕÂEäa+ °®x´$;ðA5°Li­ˆ›pѦõ?’u|Ñê¯öÕöSœjZl1Ó—ôçë`×j¹dß9,¤áo9%¸IŸº½ßª¤&ºÛ¬Þ˜“Ò"mI;6[–Š: È Ô ˆÅx(ç³(³âF‘¹í~ul+?šÚË$üþºj' '4Gð‹:ŽÅÛ7ËЕ.d8,Ê6òûiEBùLaXœQUØÛøßšÔc&ï3$½"µiHÈMoœ)ƒòFÆI;ÒÎta1*ƒo˜$Q¿”b*û§§d3¢·i4 då,#¿Öœo•Vzº’¾w¿4bˆnk5ä¼{ëû¯…ÅB•E3Ç®Ñ ,ŸDf(3)‰9x¥éõ™7'Ê¿ ã¯,Nn?ë/F£)…n»€h£<µý‚‰ÄP»d8Þ/%Ðij¨Å–u¶šrû¿Ø («ŒeÆ…¹®9Az´úgëNG›rI?Ëj«Bí)9ÌjúòÌd–‹T8š¸Ãy•0‚¨<ª¾’Ú¤·¼>¾ ¿ë]Ì~ë HócÝN¼1¢VÏ£²Ý Â[ÐOï"Êb@›ïhaÄO®<îÑïÐ+­DÝ>Lxs¼exÛ9Ê·!ð}-nȯ']†ó±†{¢øR'KþqŽñ:¿y 1Î>5õ´XãC‡e°æ3¨„\úÝã‰Åd%Ûôö!òîmßÓÜŒeô8äþöÊ„Á–>qkJbL”þ!`­©ñ‚YˆìøS@/€¬XÕz´A,Xÿé,[`ºÃÇ—Ÿˆö4¬:x™~…RÞ1-‡9Êúñ\†ä­—ŠÀÜëÀý`= 9쨀±c… Á,.¯‚m5ÃCIZÝ{/¼–|°>e²ØFÝhßúy,˸æHÿ渥>ÿôAGdŸƒÏ2X¤5âJ€Í¨¬EÛ'&ÅO úÝpbÞ##bË–Dœc?Šòð…mÆ©Òi»sòõÆ4_žú³9êÝ4ŠQÇ“¹ÊÚ€S5 æAi°ž¯ü+YáÁÂ.$4ZPJè6!o?sÁ¤Œ–ã»U‡ò¥›¬B´ÎTƒûàu®úú¾xÃ8fŸ;aå&† 0¦Ñ>•*¢í/kYÍqßèAü0ŸT|£TC•㣞ڕÕÛ.«ÿÑö/Ž ±fÀ¯VöA¸{|=‹I#>>ýÓOÝý*î]Î2¼¼ÏÛŒtì 8ß~5ú[––| îOúŠûô |:uýÌæ.v§QA®¿xº ¿ø2aŸ$9éD‘ê휎ôÜÁ2ÂSí yæoŸÄdA³õÓA¾Ïh ²°WÇ®&¤´8Ü–ˆøZFT¢½>É¥"NƒXÓ5¥L¿’9“ÍÈ–æ…räKS¢€È=l«‚‚‡Î ~׈(…E~åêü+Àf9õ½¯ÛV«:î~£¢éVÝÆê–ÎÓj›,úÆÍ;ÅMsÝ{pîº`6¹8g=7Š;Ô#Ôr\&&ÇÎ a”Äó-Üh {{¥åÊëïŒ%mh¾/”ñ‘ÕZ|7¬ÔÒúvÏúxs1g2'[жw#y‰ã=FÉÒg¥ç‘­É-B>gWi¾ERT÷"„‡²šï±ÐpþX‹ì|.óži#¥ÅæYdvñÇýëþ#ÒÉ”/¿®šYÒS½……0µ……¡a(•ÖWAÎåD‰ËÖÞù€y¥M8Ée3 ½½Ø´<¶½®l ±‚ÔFÒµ8øF¼‡{2Oá=ŸN¿6ã[DöÕìoÕ„ËõjÑÖsõPbºbáq2¿’¦©p=†¾ˆ×_ ‘›½[D@OB-/ %vÌOù³÷X%Íþ†I9s¤ÂbÒÏ›¶õ¥%sÒ?1Tqy~æÒÍäd{›†ÄÎ-òÌzJZZ@$ e´þ¦”}ñ/V€—É=Áð¨[áa(˜¿37>>ù…£šÂeïÐîEô|oêyStÇÚßÏtÉ9¹hx99ÜëH˜.:ž^4d?›™\S©HQhFÑÎW*þHè”Èäq#]gÃô“â2›[Üv4`ôTû(˨ÿózXn¤ÕÆ4ÞRµ>.Ê 6£…’|ZvÓÇ‹|OÑZÖ/C šï éép1ªµÖ5ñŽðŠ®äNã6æ§Ý¡qG¦ ªl:¦c„Ÿ%hV¢"œ³­­"ÌAV6‚‰§^µZëÚ²ðÄ&À÷Y×{®‹»8L6ØáiÖçW:(ÅÏU½:fÕV 8ÍÁ‘äÅ5`pŽ# ›µÇd©÷R6Àd…ÿ· „xÚ«!èø¸¤©‚Š—®’ûäDmVøH‰“{x-%Ÿ†‚‰%Ž$RÅð rn#¡\˜ÎC i¼·CÚçyŒ”[¾Ÿ¼ºz€aQŒ—õÝϪE[£D>—²þŽ7×rOÃÿ†ƒ|Òþûsü9ª‚„h2ZGu©§Ãi¡Z>ßàY;kf£À~‰êR»4jE$\Åi-º$èI³l/dYŽ'SÓÄ.i>iò i¥ÐAù\×l6QÝÏò‡­[&KMRÿ§iP§ï{g³«Šv|ê(ì ˆ¹"üW,úBdì8‚tâÖê×`ÔËéÒ|ç± ,…6&XØ+|÷}fõ×=[Zœ±Vw¯#7Âù7%‰8ò.í£ÂŸ7ùŒ3‰ÖùÙú(²÷-ï¹ Û)tÊ›¯AmÛdÜ@]ø‹(9}žœD%Ÿ©®(KÀéøÈš ïm “æõÿà²?‰Jÿ¶­kPÕ*ù«ŒŠ°tWÜ/ŒLÝ~çºæë?7^Ò¥>H·©tе¿XrMý–¨Cßókð I1e–“X—|¾ÀÎ_9¦gs!&q†E÷BÙvØ e¤‡õ›š³t'«Zhɺ”Aý /lK‚1æZ·q·;Æ™Æ? #Mí,€%Az›2 BéäБÅ,tàÔ£‹K»}Øgç¡gEÙÎ+œÌ¾"rŽŽõŽõ›çjÆ $y¤`_ÈNE²u=W‘å–P^S+ÝeÈ©ðôáæ÷ót(‘ÖŽ~F¾’V‹¤Cú^)qúÎk©«0ºß@M†ÝÃo+Ñ—U©Å–?3C°ývò¤)–&ñà–¼£%*Q»RÛþ?žn•H6:¨¼Öô‚ýUMF¿£ khÍëú[ jJ®b ðŠðº§‚Û.s÷[PûÒ]ý9„–)ÐI¬n]Y/€6Ø€­<—d…âáE l“‰9p>¤ãÕ†×L“˨aàÙ ,G‘ÒÌ*ÏÌÁÓe)ÜŒl‚ü¼Äq]3ަH îôÎÉΓ{˸;¹düXà,Õ‚tîýv¬jð1üâC˜]Ii5SÑ‘°t1¥ÏR ™ãÍ7K¬ÔàUY–e½vû8§TmƧӻ/¢½àÓjš*RýJß>ˆž·#ØEÿA(ûÆ„þy‘=,j‹_Šó‡·ÿ%‡…Dm®æÂâ5G«õS£â>óíf5ã'ƒÊë6©6×<,o­X ôÒª×ßÌFgœŒáQjœ„ÁµZÎ’oÈö „¤EÅœ9Üóz °¨MQO!YOãÅ^¼‰Ø›Ü‚Dñ•(Àµ@ÙÉÜVbÓE¼KRþñ‹5‹¤rTŠªÎF…³J­Óëï}LSe'ÍØ$;ˆ_Nñ3ÆRЬ"ý™2µ—¬ˆ#¯Ì)ŠãÀxô zðé”0¥™íVŸ Ê_Ýp{Gûè¿»L{ßÊ>€cdÛÓˆ1£Ëœu¯©påH †Ñ Ú妰u6T:0îb˜=wçÒu9¢+53_!Üõ²cc»J_ÿ½ï‰4˜ŸðÍf •ˆµO4tÂí!$…çŽ/øHe@qÉT°xl5POXèQ ½_{2:É}+mçªë(?Ñ…vº)Ž–°oêëÌ`Oà`{kždr/ÊT•H÷«°:Èù-²•cµ¯'n³0™×iBÖßpàI-@çn °Ì fø„{nÃÐ yˆsG¡†~àÞÑ‘Ö~®ùi€´¸tBÒúŸSѺۂbÇðB ãðûy[p«5Bs ¼„D9š¨`øŸÿ»5 )ýKPÖç VZŸt._ó>”äêq©ª¢›†2…!X ž¥> Z`M{xѰZí-z+ó<†¸ußt~±„í´ŽNÓ9À¤)§?[*'}‰$z€ãÅDi ëGLç>¥N9ÈÕÚ‹·[ÆoZÈËbsIü;IgéHΉÖèîšbxåÍÔ½û[T”Wi$ëL*s÷«~”ÑüÓ#tÙmÉð3£âÂë~¡ãþF °Ý¬5¸@1}Îû[D…À“[žˆ ÌQŠY‘íáÏ4i+ÒtäÛžì”, ¾.(ŠÝ·s Q˜€Þ` ÆZ& ¶g9fÐkßÜ^ 'Ì ¬6X:±½gìó™\g8’­3+°ë“g9rõõXf-žµM$öõñ î*faJkáé=ÏLl ‘†hßʹ ÷ ¶{íOŽDxNs i¯ÚX^#w'ÃSªE ì#q6Ã%i¡ËrjîFû¸ò¿äìx D’Mï*#îÈ8ÞA¨=L™Š™XŒåJÕ4ìsäAÅqþ% —i¨Žd¢úC·%¤Q1:1pÊÑô{ƒß7^Œ×9ÙÅMŽZW2ªôÛü#دŸý_@WsÆüFZÆA ]RÛ)ÇXbhî‡B3tð4ÏóÓÂ#bSàò’*Ü8(¥x`=“'ç‡ÿ3d,-ŸŒ–ø¦%ì¥àá9‡˵Œ”DsŸm,à !Âaî†ß¡œ}©îf±(")ß7òºÌÀ™z ¯ß&–Vd³l†Õ;àë Í}NÓNzûaŸÜ/0ân²Ã¤IyìMÿT‘¢ã’VŸ(í/à>h•)@áðòÙ=(/ Q”V Mª±ó#åêpG0 ©žŽxÂÊ]°í—ùþ3@4ÒùF!P2›|^F–ŸlÀY²„Qn‰f¼Ž°ª[`Gÿûú’.šÅº»Ádz”ã0Û¢oN¿ mQ-ïêªÛ6g)Sh_7R¯hÛÛ÷ØŽj„J¯ ³à™(-zÒMËädReJIö)Te½\]<þ«ZXõýOÉù ÝÑ}%ä'·7|½›¬Þ;bžÒú†.ºx’³»D0ÕI&Íiíìý€ ùâ l`’$£Ió›G…£çø–п¨~~I2šúÕS_-6Yž“€4Êõõe±ù”D…Sú"Ç¥UöúÊ€rD´P×røOìsèdŸz&™©¾Žˆ*÷³?Á³üÿï|~§kùñÍ«¬.ªJ¸½§êWU5 ^n] S´Ï’1ÎÙȲ« Ú—OOæè zÂi=êÈLc QÝK·9½IG¥îà*1¡XäŽJû£¡!3x›ÿš£0(Ç`Êô…ƒ¤,ÄJ§„Q²wBY±OÀuºú£ì¤ýP<§H»9ò¸¢´ùêê;ûQrHˆœ[õ÷‹(ž©Ž‰ èÀŸÒÏTXÄIá42’¦Š)žüeßÊNK§¿ì:BéqÄ €2‹Ióæ™Â¨UË'¤9¡ÿØ©¡ à:$ÑüÝÝ}Š©*Ï%ý‚‘}…öie[Ý4Ov7›)‚`¬›Z]¢¤ ³DŠcÒðpúµÆ’8èEÁguæ,#oç²µ®´úêׯšU¡vG³F¡# üäk{[Ž|¾óÙøÅõ5~RÇŽ–Æhš¹ƒìûÄŸ F”_Ʀ.ãoî]©¸¼ŽÖdÕ³Ý÷¿ÀuÚ;/k%d÷£Ø^³%u× 1$¨^é·8K·ö>u„þÎÖƒ-ô5‚tš¾1ÖRÙR™¨µ&7ðAÀ ¹=["çlž}Èõ°^dI>ÈRÉx¦»"!ÚzYt$[/Ö¸òѳðtfJwhÞôfΧ åM¡Æ¸6ûP²çb}PCdñÈÞ˜WŠâh7‚í@/¨Qv­''ÿÊtº½Rî‹V9ö <ºÙõ88ªCzH²›ì[QK Õ$å hNw”- €09{ÏÕ ¹£ˆSbya—ßfn¦ä“6àü²t vjÎgyF3THtÄ>Mæ´ßùˆNq&œ1cÁêv¶Ÿœ3C¶<\-lVct±S,¼2ºq¾Ji‚xâ ï#XêT öBüÀcÚ¹`Þ“0‰£q^õÇ’Ùx£«·|4\ÇØvN)€fuX’­ gEäŽMã…ÄÂíUºZÅ'+CÔ ìc±mj9÷ævò3¢&žÕü¯ÉëööEîøK1ÌÆ‰OÕUêzÝ +;S–ÅB´8+oÝOFPïäý¨Œc¶;÷ú­~øŸ³½òÕfASb· ;RoŒªe\’;2kD4áuñ4Ü}ÏâÏXײx,Úêt@ µÏõº·/ecc.°ý³ü×€™yò7—û6 dè@ ÓàONöZ¦Ås-ø>ÎÝVh)/¥ ó”/1BÐBNoC?NÆëú^ï0A*:)†.[[ÖV k ç"8Ý>9h—軓A²73i‚*ÕÎÐö¤f ü’{—cÆ8 ĤµMûé{]wMr Ô(์ÛuÎDB\&Îu²ÏÊý¥TXs—ôD{ú2 rô{¿Ù>×¹–Ìø œäA»Ó3$ÖÝH¯’è‚óžrû±¨ÐpX–k¢~Üsá.ÚܺØÜs(×à4gGaæß_m`¥¬èËÙ1¢øû?èˆ?])@ð6© OiAœÚæl%p®Q[ÙqvgÔܳ{—ô.U©·õf‚Téëï½B}7Üåtë[úÐÀuÙ¯Òÿ3â¿Óƒ©÷¯|¢ñúq`é@fç³k$¼2O a cÞ”{ᢠµú›/%8äò‘uÕ¯B ¨‹p*ô^?_§ž,[…ó¡øØ„7ÿ%~(Ê:uÆ|•™º*7ÊȾVWšLl°j{ŒTúÅFHé®ÕÇç5‰Dx 4:·ûÍqcûÃ,ïÃÇÞŠúzWîÚüôÌæÔE³>ašFýZFާŽè1…ŒNÈaaÍç÷õ\æ£vr=]wM㻑41t»uÓIž-ÓÜ„Ö9¹ïî´)÷sWJu“èaÑEÄcñÂÏÍÊG79šá–6Ógy:ŸX‹Ã,>?'ûÝŸ ª¹žÇ¥Pz¸rMNºP{š´«„4幇 ™™ã¾ôŽ}Þ¬Kkð*)a–!¥%â¡ÉdÛ„*+™Pݘ˜¡vR!W’î7ëV#AÊuå×]S#¨Cž^#¬‰Ÿò`|ÿYqmjú’‚îþÔG_z…èµQ¦§…[œNý¿5±þö´¦`vÖ³O“(ê»éЫzNFë.Ô€¼|íµ3MST·5,ÄÁó’}Ù§?(ÎDP!¿¹˜=jïÖdÉ+Í4â}æ%·¬0߇Eì\×Zª_w„X‹QUrÀÔ•º~@Ê#8C¾? ÓJùšgøïC'-&Á25ùQêÔ!k ÞíÆÐ˃ˆco~³ØóNãmR›*¤°¼¡þ= ø7ž$ø £p3Z,L7vsÐ}üÿ˜R¾ à©_öëÄÙŸðaÌnˆ_á»ä¹ôÂÆÝK ïû;R˯q»9f$»­ë[Е‹xóvrï9šW­Ø›$ CöžÌ ÷WØ Mû³”‰?|¤ï ÖfÊlôBé±¾|ÄöÂøÀçnUAï©ù&\Zï·xx[Nš@…éŽÌâï aû¾\p×HÏ‹­¬¥RP)YI²ýþ ñöái,=¯¿£‘ïõ‚á½})3 SÉ6Ÿ3Xž* ‹MpPR&ø1Ã"‡CVVXÕe«ü,í%!}v£1N@_ˆi·ˆ‰ÉîLçW³¤l4Ÿ>aOãûí{‡.,ù9M4’œ¿@Ô½–@‹Má˜Í²e…GRÇøe„(^Ør~7TŒ€ý˜5XÙ\IÌ2Ôë€vk3•u“Ì'!¶NŵO~'gÌD^n3Eu1EîBp€À}`7©Õbòÿl1²‡le@p&Î 1q}¿í€e¥NjÛLG¬g«>Šðð¥Ü âô™7÷)û[è¾Æ ˜úx(1Ò“u¶ŠæŽì0­WªbUíF c©ã¨cÙ†4k˜O§O~• ›EjL-EQH—Ž0µžt£9×ô\Ó¹Jõe™dfD#ÖÖ›g?j¤[Åü‹îÊ&¥õ¼Û¼w3‚JÔ‰Pö·þ9cì NN6[…6¬EìnYV·TÉ$¸ñC˜Ç’RÉp©]qG¿Zwg(´Óof¨Ìf}–Æu“SJµŠ©q›ÆuÂjîÍ]”wïEMp1„Ï5/í- ÿ µh¯ax6jwègGœ=½øZõÚ¬Lo‡äÊï\šHb¿bÁÒc_ *ÁÜt#›ÇN’Ø@ìލ{[„Ï€Ë6rMãôîb'ã2#£=vÊöÒ×$À<> À\~1í¸4ËPIPÙ …­N¦èèY©Ý$‘?/yß”YTwò…¸f_Î{ëi0ÔwNU¤ÆŒbþóžþ¢¡Ð*ÒÒu™1œæÙÂ÷'¬$3ñ7j«}8fµ”2ë4¢ð#-:9Vd€¹ê`çáË|ÇÉ8’‰£Ö5ð*YÉ™’`ÓÚÖ̃_Çn)ð&ª@ L—îñ&ØG.N&L~8ˆG,ëË®lž{ÙÁ0F{öq »«Ùâ4Q–ü»Ovr} \DŸÛ5u8)ÿpÓÿœJÆSabÒÌ©á} < LÞ{6âFMò˜³‚\ù‚·h+ØeUˆNëë[ñZi0«m„Ã+z¦ßPâļ[9zž'n·Ìâ$Äñ_}à\Æt(T5!\¨Ÿªâ æ¬Ì]üa ÞJç…Ñòlž™¹ýçpñÉ8ßEçDʹýL>lå¨KDžýôÌy¹9þ,|bÒ*:©¿«D3’Ù½ÕŸ_çèm ]$³T>^7CBß3ªÔv^£¼*?òëÕ0Þz³EÞw:ÈÐ?¼þ@rjNgz¬*y¿1è}ص8Rh?˜Âù)u›Tf%Îðýïi?[ЧKÕ^ei\yÐ}̳†ã.©B·:Gãhl¢s…ý[ƒdX"dÒ±®Œ85|ò$‘Ú E©…7îÜ !ŽMsjë*·wJ=jú–1»W ŽP”ËÇ\ÿËÊú.—ºÕ=.Ìfü0)Èf}» †óäJh+ª7~É%88YågÄw¯‚9¬ˆL(@Lÿ‹NªVÎÖ>úSÕšQƒ4oÖÛò¥ámŽÈ|/:»§–­1R 8ÀJ}¹+W44_;.káàˆm¼9ËBwM1zÝàTæG¸ ¯µ³6«ä‚‹+l¡ï\xlÕQõ÷y$´Ì•`£Ð$ú§½væ¿ ¨šêf‰hÏTR8#¦å\+h[|aÒ‚‡í³u >À¿Sµ·‚³¦VHÿÜ#õ¨FôÁôê00Gò÷Oþ¿ƒwK¸Œ<álÕ¤i¶?Ã¥«ÙÝÛ™byüYBðÓ8JhPnᜆ*n~Ÿ'@€uæ.W€£8Ž-pŽÂyä`‰’PÒ{ˆ£Ïœ»˜áHÿ“¿ìÁئ3¥éÓàÃ…º„@Ú‘¸Ív±üKFµI$Œ+ñ Äó àRªûÃ&L8³zeÄFb#Ç}½eþŸ]#ú^…’*Щ_i g ?µàPKÉœ½˜TH?V½X\‹° ¢v˜©¢0{½7-+ÏÜHºÈR€1Aj› o.ëéÂSüçOCPú» ©É 'vö0¡4òÂä€ÞG/ÊnXI©’E½úe jÝÌÜ…±HyÖ«sÕØó¦¯¿XdÐ,cpøÉó«qû×MÅ­ŽéÖïÜ•¤ï*ãÊÒäV÷±×š[iwÔÔéêc7[ƒ(d»ô¤§,9…©€óí¦ÖïDÌw°¹Ñp--|ñ†¬ðûJç £#dµ³c¿’vÄaxwL†R[„7NyÚoÖ;åx¦­u&Pø¦ýÔ7Üõ²5:’‚G4ç_¸ØpŸ÷ô=vÿ²û'ÕM0Å6 —L4ˆVñ¹u sÄ4sØ]VUë}„¶ÉrúµvÉ逨ÆxŒÁ-C maCåµâøø4ŠXf`¾é#Þ€5-¸v&_#´x÷%„ P*8„‘ËŽ·úKË"¦ø:^MÔü¼P$ÁQx d7ЦŠBf˜‹ üTžËo8X=¸—ižÛfL¸–ÖÄ/J$t^»Šwí®ð>µÇuÛ2¹kÄÑ›–}å›a5œ,“ºÌ«f "å{”½óâ %È£Sz ƒ´þ1âáÏ©sÃVá]ÖézAw¬S:WÔW3}v‰ t“(ðÒä ZsFE+:ᎠìL‚"E»"§é2ŠV¹#=$™oÿ¨±ðç2³ƒ˜,&$j,6ÍÀÊ5uTfZúfÌmŽ6'µ±ֵ驪|‘•Bòò&¹Äàå™Ç¾Atw~~Rº®xÔóúˬ8õñÞ’”âYê©ZbϘˆ¦”ãêM‰ÀÿD¥ÝšÕë àh*¢Ó9˜Z¨“œ„Í@Õ™[Ý7¨Í„ú4ù/(ÿGû¼Ëkð2Î)Æ|ìS'Ž:š¼îëíÝÇ¢³X¿ôöcƒØíLõ)§ÙŽà8E[v5üW‰é×ÙŒP c6¨Ý¸žåUûk0?uÓÕ<6‡Ã^M/„¬%ºÓç$ù¥gå磾Uø‹ ¡˜S0ÂÚE, WYLg%Õœ‡Y n(‚]dòU,“nÈÐE}épÖöIá˜ä…Ø@´mÏnþPr+ 㪵ão¯jZqÈ‹âJŽn2^‚q[Í„26$oQwVâ¹fƒæº¥1Þä Î0QÌ s"­ýoßuüxT†+:2U.,›!ÙÂÝOj“Ðàÿ8=8u´K¢Ì”½jqe®)*9—;3TÍ Έ†òe˜(ËÇ:&F9ê»Ð/¢úu‘ÝÂ…ûÜŸ“Ž"ŽiN øRÁÅ‘¤ƒÉFÕ·h?5~•‡³5º¸èntáüÉxz¸Ï^ž«Z ±PôÀ¥ÈAàð‘ÌŒ:ɽ5P3=Ê/?¿&â6¯Xq,W¿^c“äšã èA³Ù[Ö9ïMâ .Í`ʹ‡Ò}”ïA¸VO¹"Mà• W:}Óf˜XŒW­Ò»^URÂN8 N¼XØGœ¿»ðçËS¤TBÊávƒð+Dö†‹4äGÑ5XS7ÁaͲ۱šLte÷¹rÅa7³Ì¯”…ÆÑ M=÷[#d×À9*}ÔÛÝ=–RxêY¤£è×àŒZÅ}KKYj‡Nç“fYƒ©¿^¦Zö‘úmEž‹+y 7H ,í'™ŠÉútZíœRV 9 ƒlÅXûVðà#Ú“‰e­q3§^'_‘<š°Mœäñ~-ÞÚßœm‹ý±ŸÎói}—ï,ìåÝóƒ8/V4»š2gYᎷȾúO~¥¿Y«3¯.Ÿž.sG‡K\˜ä\Fˆ°a±§?!MÐÄ0”’ÓV WÇåM¸µ+¬w¨p¼ù)ub.ڴد¤žiü·ôw2¿½H‚Ÿc¶*Ü´øÝp°F§ƒsÕ'w(£Få«ÍdæÕyQ.xm5]0«6ºšò°µ††ÎŒ#ârkk(E™vdªì½cE$^FÞŒ'_äà].AOƒq/Oœ"Îd°±žx½±!RíB£¬Ìä½"÷f*GådÞïˆÿ5›e±m]Ëáï u`HoAoç^ë/Š=Ì8þ CPD¹BZÞ ™“…ê#–k§ÕHSQ VkŸ–zTé•XØqr-žó¦}´__4šî¢´l(3 Dø¬ñÃhø f\1ÀŽwq'V$£mÿ êèNµr‘Ocj÷- À"I»wEÏXÎ_]øM]‚q|´Ë%¦-§Ç¥–Fl”HÎ@‰]ûc„a&’jz²â—éû9:¢ %MCÒ%£-I ³7* $²ÎÿîÅ2eœzÓÊè3 @ö8j:*˜_²Ž¹Zç¸S-ã MðmbƒW·Î¿©ý|‹ñ2JoÝÓŒXa½‚óÞX¾‚¡ÊEO ÚðsʽaK!íg)dá TÅ7Тwgv»oe±Ñ½ö¨ç“Ÿûô¡üÁTbR˜êºIýÎëX©™Äו䪯ý踗=l(îÖ€ @g ¿ÉÒkn¨ ç}Ù£4Õ²ö0(ù[M¡FÅ9J>JêñuGxjPæ\3¸¶XÒ²5z”­—­¢$ÚïOY~Æ—ü P–?pH 3ÐYßêžÌ).¬40¡}úþXã8yœøÈï®ÌZ ó‡-z$$uÔ™døöQ÷'»[‘ˆ4‹gp”Žì®½~.KÊQ4Ì#07”€î ÂÇ¿*ô¥03b¼Ôi ,»&¸!7–™_^ó¹àÿ!?æLQ®$ïÏ>,O?­Ü£`òÒm@Žé ¥ÐéT«ÕP9‚§[^5¢Ìê">€<®XøžöšŽ43—ºw¢K™É0»4J9ßðÜ+´ËÂâR¿0¦Ú)@_7íîˆóy¤9óM¨ŒÂ’C&ñki¦§”wX¨Bô·º—Ö…OÈ)Þ`bªŽàb•ºf}8 ›ˆ¿jÀ5þJŽT£NßSà í]EÏ,mVLô}”Ÿ§Ù~ÔðuèŒAôÃwž.ÝfÜǪ‰o¥–O,SE4äÈ‚ŒÜ@«¾|`’A…'Ÿ¼£ÜÍ&8[@QÀÈŒ YzÖ–[ˆ*æRÒ‚pïÍ¥Žæ”ùˆ²5O Âí™se—Æ$ƒûÎB<ìa¶øÿ-fµÏɪ³(úÐWhÀ{Õ¶ë_€n1$ôA;…½¼75ê^“&.e¶¾©Î¥ô¾‡$¥)×çäíUæ“e×'½ =cÌ*áü6!aKVDŠèÃ4½ŽD~ÄÖÆ~ÞkZÂjþ®7`3ñ-ÛAæ5‚zÝ„ÉÆê`õHLø*0ê–Ü– í’“»4ì‹Ol7Ô$2×›‡ìèÌkî½µI#ÇO•• EÀÇ€ ^Ž8 wæŒT¥E7å0ÉĬ7-e±+Ñ)”²©úzôÖÛ=D3msn“²`D(Zi—–Ž? 7\Fš/5ÆIG¿á´¬D%µ‹.¤x¿•!ïñ—Ë72$êÚ§ ¦ù?gl:\­R Á¬¨x”÷ð-n6e">¥â Ñ•~[Œø>£s­Köö¾ÿZi|­¸%Ó@÷šÃmrÔÉÅ‚€&Ï=›n™!¬(µ鯬a`àyä]!uÞ*ð;AµòþÖy–ÿlÆ—õÑÐ ½6å“ Z5ëŒ7Áœ] –êøŠqÜÚuÕ –N»Ãƪ»58h¯Ck•`cµ„ŽŒ/DOx,~2ÜëãÈU t·1U¥QE_€"ÎÍMTÂÒWãkŒ–ÀŠ°Êšr:Ó‹®pMº€eÊ¿Ktº —4™,í¦FWûO"zÜ`A¿ ¹¹j|âÓhôÉÚ7a8H â9ÛÛuhAÍ ¹`3¯RŠžë¹–Hèt{âð¸zÊQdOkÆAäjù9uh©úA~­EÓÀšŒ3»M47˜í›{VUáxŽMB&X”8eš äÛ¢fúø3‘¯x.;̆ƒR±´¿D4\àfF+…:!E£ØNñ^꨿jË—÷LüX÷|¯³3FØ´m¥ÇÓRttÒÁ(¾û<7]îA §ÖÌÇwÝ€Ä?~œ‰ì‚þ¢uQH†¹D„ûÐÒ&a¿ÜP¬ºãhÚDÍ@@íÞÝ0Á;ZÂÒD|ºÓJ¡½ÇNå1wBêð6ñÒFv¹.\mõëo¨)þW&'“¥xP%¸Ì¨õÐ.?–*gÿ%“!£a‰HÀ;í9ihÕh˜U1`ë¯ |Ñ+“•sf])ùorA¼dC ãa½4¨¹Ñô³ÃÃffàÝMš ?‚]·«YôØR² X¢Ëܸ0B—“^ P³ñNÐ>hhK–á´HlMŸòh^ßo^¦iÅãd±S_R>G%3ßZC(³»­ÙØ+÷ËÇLøÊjmÁ&äuæ~œö,¯­7ˆ51ÅQaü;„Q]ÿbìßÈnwÛ85†®Qtœîp¿^*¸SAÉR…JXÇ¿¨UèÂÚ… 0[­[9®³yy[û’1"¡Þ*Õ¼3’¢á«#‡K£ßåÅG2TË ›,J—3zÕ $¶üü-R-ýŽ#¬e×ͧ,{c5lx…KèÁá©ÿ·/;]®ûµW' _»žŒ ±j8)$ÆŸîÔ”a¦˜×뼪òþ8.ÈÅߢ%ÑTÐb£ncsš˜(ö¬è4Q¶Ï¨0ï¿‘l¶¾É¿¾z‰ã‡d†›—’[ oõ:…ñÊÄ®ÚÞ¹O¯ëÃd½È¶ðš³èų¯;‚^ìí“;•!/P]„ºd7èóªžõÍó? ×ï Î&ˆ\°Ô*2bû&XxD ©aÐyXú-D2Tj3Jxöº#£ùYã°‚¯Šè‚4ž­>…iyͳ¬ æ7êìò;íªö£ÛC©ô7:¡^ú4SU‡#¿¾Ìiÿ`ønd÷ónƒZ8Vîr¦˜ï}ƒMšÒ™ŒéHúëª)»eò¥èýÕº±`£×žÎŒ‡Í“õífdý@ÅÔ—U {3}­Ò(yìÕ”—Ó“nŽ8˜Ñ^µnf©ƒô0†ððýèa«!¹Æ’Úewè×Ñ€xSÁžó)}²æ@_?‹.3Uë_Üç AYF™kQðç÷Ï»¾z/oa̶–ˆ…lѼÇF2ܶÃêÙx8“j2)ì®âv³id ƒ¹ñ2Ynð 4ÂÚÛpåpV¨ºój 'ÆÎ»´æÈ«à¼ôzDgâø»4#­ëŸµ_¡ü’M™,¿GëûgÃAÕÔ\Úï¤ÓÛÇþ«\Úw’à Ó¦¥§E­]é’¯CÌ:`Ž“sžÌ×¥D-Ž¢y†òt˜‰(wö¿p´ì³©!³]-eš“gðÌ;y¯ƒòöw1)ze, ÍÓmœF¼EU¡gõÓ ëO¾„XŽI Å™tz†‰Ì|Êq𦬒·lÂé.GøjS*yd{1ñó„Dº”êI4^ðÿOßüôî¬mº!M ù’(öËšFSœCâ‡1†ÓÂ[úaé9‡`húK//ŒZ†E×Û>$1oZN‡]éä`V­wïØêÉÖØQ—;]]QEÀÅV“!ªt©µàEw3m´4„Ó¬S¾1„؆Vl}ÿÕߦi¹Q„{µ: îL UgöY@Ô¬JBM¿ÙtÁ*«YOR‰ô!õ1iêÇøÌŠ£iã>w²yÀ|cÆÅta1Çðì$ÄĽ²;d]Óº€£Ôe ¿)ØJŸ%‰˜©µÉƒKúj»÷4’Øê| Aº³´G!óðß?rønÝ\³*Fæ@°‰©1ÍFÝÅs%€òò'>ÎÇÏ–¥Á4.fñ¦&[òèžÄŠ~"®u•kÔåèe:ëaíýk¶¢:D+‡võáiªÂ o%ëU‘úÅc Í›‘ŸzØ¡œöìIUzp\ný[· ^«¿ÁŸò¡ÛèWÖd-»Ë¦ {ÞZð:»{Í3ñlë/5«à®szP3øe,±cèû•!lýªvÆ“o•>–T…ŸMµŽq¾ôô®Ý£ÅÓÁÚÅÿdöZ%ˆ˜ÍŒJ.‚8ä;PN[7X5WÚ†½õI÷Hˆ`ЯŸh¢H^ý“à4€IzÙöˆ²Œ¡lÏGKe›•j¢»E3U‘m\‹ §]Z„{“`ª¾?ÝþË`ÆFYÂsЬ.¹{>Xûý#FƒìÖIe¤<Š‘Vëä]]­ÿúÆ"ŽŒoÖVÕhs•)ˆ×'0(œQïÔ¢@rè6µ,¤¥ÏP½+f?,G Írå¿ÆwX¯Óõ‰üÐ1…ã¯ó>’^$‡¶p[úhß}Ó¬–`«Zº ¡ˆñ˜·5?¹tKŠ¢Ö–§b›'5¢oÑFÍI‰?`<Ï©'œ…{0§=ì²T–4€Ê,vÛ°Áï÷¶ud=ïßËÛI(Öp9æÔØŸ ÜHÖ,Ce5{mdûÔêæèê¹ â¶€x5ÜTêü¬#»æ þ7ÓõóS 2Zæ£P|{Yæ«$ðÐØ‰,«Ö9Í]A&¤°p9@QÙ—DÑX&чú}Í>{! !…qÎÛÖ0óp¹¦£HêÒõàš Ã̼–n½me2ó]¥!¾ðõZPnÃe‰˜çºf×~È×è d­ã‘Òy€‚éµÂh¼5² ªÛZš„]ÙY(hòé2`Ë—Kà ÁmŸ%¶íÑàicg·áìè©VkÏåñZâV\¶¦Ÿeô[-U|´Fxг–šA§æ‡Û®‘-&ù?"KwFýf~Õ™©><œ÷†¢»Þ™À› ³» å¨åM|{=ð»[ڈȨ "0Œ¢ß‡ÃPôrÿù$VP764¥Ím²­Ò¨u©^:~ÉqWEêÆ^ÆŒÔtÜž‚IJ",îóñ϶ܢª{«¼§¢ŸÎ£Ì¶˜ÚŸê‰""ZQçYÜ·@Fï5H:0‡àî=M6ÒÐ6ú˜é,Æ_‹§"[æˆFê"æÅüãözͪ==“Ê@¨Q{®µöµ†òלkzŸ^#Š‹ N”öBBMÉS“š?šßńǼh?ãr¬²žwT^*EÞ­Ù¯YšÐ[dÚˆ¬W¡ MŸ_‰j öœI|«%ËááĨɲƒ«o‹î­<k:%ØÍ.” –{¤d‚áD)Ûéíë‹UØZîãó2XÖŸ¤uÆ„ßÖZtÖ]ÑæŒLˆw oæså‹Ð°ˆÜ#a‰ÔÁ8C?¸nÒ15±ˆ¢õ‘IÉ8üØ*hÈ×¶hêðÍuDÈâö*óéÂND‡þÒfÊÜÿfx7rÎp÷2a†Ãö’‹3ºÞã‘üþ‰°rU~1L÷7‰,#h8‚ Ù4°gÓ¯»µü6¼×§w íV$aÞúŽ»5ާ˜KdÔÄO*Îî¸~_§ Œ˜@îÞúBô‹lÐðÝ#óS¼f;Në |å7ývZR |‹½<*$nkߘc–©«×itªâôÆJP >†ÙË)‰}[JÈéÝ…ÌÇø¯Zg–û`¦£ñþeÝ0\>¾H¥ÏJbãù#ôñkðHÕal„à- Îh-f‚2r×z·¨—Xšýkª¶¸ñþwW.Z¬ ÙëÑàobç<½Ûè\³­ÊðoŒwvÏ1ä¯ ,´äc-6Õ˜ºbgê…Ü=ÂÂ;`E &'T(ÔYóÚ#«G…û›ßéSÙ; (\Ä®ïæ™ +®iŠU'ņÎF,GÿgD6d‘ļëKÝXéq«l‹ûEµåÞ¹5~£Ã­ÕºË]Þ·’“Gì)LRq,XÞ˜ù挫‡šPÁ„v¨ qòd'i‰‰n¨º©Åa n ;Ñ9½xß Z¶Üò"[qjøCÝÓ¯ÎyïR¸ „xÔ»sî%®PÇÁçT-$`ЬÚÑwÒES52pWTåÚðÈC’ôΰˆ5Sé¢G‡—¨ûÅ4ê ¤È]«ú7ÿ¬CåãUh>¬0Ü`–óy1Ó6£Ø3QŽÖ'D[A“Èx%q\çÏ^$}êçpô„Ãæmß4êLÆa¾=툿óhÒRíƒl"ºúhiTל•ˆ1ob“A•|åÐ_»Ÿ·/.úÇ—û‹I3f£1¾YB5ùÐt$p^Ï4_ìë.µ”‚ Q—tCÈj»?N³ K¯ùyÏRðjƺ}) ‡%7ÆŠ‰›Ydè}Lïiˆ +6µ(Àï]åÂh§Ó @§-ÿjæôîf’'›<û¯©ÙƒS™nbÓCo{ì|ð¹= îI sP×Èœñ fƒJ¨Qõ‚5Ó%ϹáaÎ j7Å0"R$©Ï{ ±V©¡ùgíb ßøµŽ‹Øžó6Á?°eoç\Ð<#ó£â9¡èGKZ6ùD­8”ÌÌé?…c&V/#ìÕå-H}ͬfX–_-d~ÁE~V|Ê%i—ä\ É{N«);ç_YµÝüM]ƒÙ4P”YMz·d¡ÂÙ(<ˆ(¢q`Ðj½î ©hSû¬š`ŽÊ¯&å%†æ†ªki£šÂŽÌ¢šð×n5HB$/ìjõ;:F“ž"‰2'w‘›ÉßâÝGzò‡vX_ѽz*ý Ì´Á?Öø°©äÆ—2„ê»ÉjÚHC*…ᕹ^ŸôؚÑBà•”,ç2âƒ3!,M.Á"Ë«cS¹¯.7Ã…ïr4ݰÐ[¥ÞTÞ÷Ó,@¸6¨cö¼S¥”`¨ßýoEcÄ™¦NÖ·%>‘ïUù®‡.›Ý>Ámê½L¡CmÞñÝ£7zã¬në;adØÆú!m±¯ó¹s©aU‰ªÎÄ–qÝÃóbâK“"W`‘½î 4@Ö°ê[›áú!£ãû·Sîø=ÀQÝis œØ±õ(a©˜NÖvEUàDå>[kÐÄ4ïžÂî"Z9a¥,ýúªò>ñ”Ñ‚—›lJÆAÉ9èì#f«†þ9$¬ršœí_“GÑd&ìu׺³Æ¾UHGf{6 ÊlŠÌöiR'Öða¦]¿õ%˜æï!’ËÁ¨°ÑLç&i£Õ×0Ī1¡0Ègd³Õѧ[†Ùë§Ï À3´Œƒâ;JG§¬A3@Êòë?ÈÈúKÆy¨·ßß„ft}­Ö¦ž—H¿³×}©‰‚S„“€ ÒF…iyŒæçMáüC¶ªƒVý_É6¼^R´]¬!d> ÑðŠp8é¼øÉüÓƒƒÊåÕs$ƒE Ïø '…ñ[SïYY<\”;o*€"Eœ´—ÝñlLŸgWŒözaAÙµT·]ûY¡–•ä‘T¡ñ 3§Ø²1û¨Ÿö_},>ÚÇå*5ëÙ‰è|û ñzê˜"ú¬}-üOH‡p~=W”R„Q-YoIš†îq4+ê(lq4“<¥[‘º0ª™ïPQ]«Í!"h;ì+y†ˆ{sÂPª!Ñó:H‘=Eµ$#K‘ˆq ­£ÎccÌqVv&ïR¨ÅÜ´ï?uƃ;ä²’á­t ûõÕ‡>²)Ûìß¡ÕBü(úeì±€îøŒ8­ð‡Èjné½þ6ÒÕ¾T«‚–Þ´úEóÄ–º}&4ßÉݳc' øÞ.÷âÁq -A[%ü—ó3P&±1ó7¾â\ ö÷"´¦¶Z®*„ä–1 H1ªW””pC+³ôÓwgg¶w=sׄRÐÍÐkYOp¯ØþR&}€¯·¦S‹Œ´i]!ñ„¿HvŒ%±„].¸|ïC_8–É·»¤øõgqËž=‡ þ“kjÂ<ÊIÝSê3ÁÁJÉšµ„§ºÕCø%ô躷˜—øý5ªæuM¬¹/÷3NÏÔ[&·Îî؈q;—E{Á0m¬ÀЬ"(tD»®fã,]6ˆÂ[Û¦Å3x¿6©Âü)s5«„Ûw€ìMŒ…³ŠMÙU ò2^ ÞØÿ~SÊ I!-æ’¦¤œ®茨LýÞ„LÈj‘;®ÐT_íÿü-AÓm6Z¹¼ž¬ü“Çmd²2F³nI.j…ðjÔí$@9ÉÔ7 º¨s*j³‘\†£2sï_ÌðÀÀy„g,2­¶¿ÄœŽ3&é† Ò‚½®n6Ö@ÀSµqÈ¥†KsÒV{Ư‡ô¥ÿˆõü„­iÃ/..\P%khhª?*~ì‹àÿ—ÿûóæÑÔœ~vV‚Λ:ɤ2±ÇJF"_ßX5Ý$ìlìmI£ÜÅgnØëÉ2°‰U÷gG{îH¥–äH:±Ä„Û𰄃£«^úJµ°W6×½šß{äQo`¿ž”h-̘(¼Ü&±:¸ïegý1É\ÁáÃôÅÓØCs&ä¼kQ§µ±ÄߨEfjú8™=+” ;`åØŸî ²7n,$QÞlýä[[~ÐÍÆ•„Äéÿf/&™)E÷ï&×°’ÑQø¶'ñ¬¢`¦Õ#ýž÷ØCÉ?G8+ìaBZˆ]d¦4°(Ðà’Ô]"P¤^®j¦»ŸÄéDD^3T§r•x™+ö5“ãÿ·ðp~SeqT¿a5«âÏ“(»“ŸÊÁ \3J¥j”ç0_3—ûÀ±2lò„ ðÊá1‹׸P]wàÔ¡`§€(Á$ÿ½ÓY8lØ«/µA±â„Ná"%ìúlqI\¼¯–Iˆ>hHnÐz!ÆeùžïVa0#AØ’àãË-ož €ó†øh\ª‘†’2ÓĸÏÑ æºRƒtÁ«ÕõZÝÎn*.†°A„L¹nÁ¾O‘ƽ‡a˜ˆ>Ͻû·›Ô©ÖiÆ@¡¯¡Ãð+of^˜µ) =¾ö‘-*„Që 5#dºˆ«ï ÷7uWú_Þ1,‘h©Œ± n…¤Wn—2ܯì”è|ßÑõ`oÞ_îæ*ÂM0šý.ìsNò("ÛWÀ‰w–>Aƒ¨ø@Sψ‡ý{¿¬RMã-á?ÊojÄÓ‹­Ô>Eá+œ9^`yœlr£LW¤ìMÚß›:Hr„é'Ѿk:Pøc>¸Ôõ„2Ѳ´SƒY)àÄ—õÔíœÖvø%²êÌܵýñ1¸Ü!2¶5±C-ÚÞ?¹ïû˜ôÁç°¾ðO ÞEÒ|5mõMŒ‘8on(v!HwDŒ>HTm,Ëâ¸^ÇonõÙAoíä9{­!æý(vwïßQg"Õ…¹ñQ…Œ.²DP›ýû‘E°HF1BqC¢è²ËVPÞ?ýÍÁØÂóÝŽITÆýºÜè#–"ÃÜ •¨JMÎû.„¯g–•#l¥ ¤d©! Û¼-H»æÖÉd ¿=ëu2@è‰>+KË£²î2ï1Li.†ChúÌ“­–s¼ñ…` Ñ¡êS ÌmL7×1€…Ry/’‚Þ±)‹ òB§)ªÈÁ7ôÎ ÷Ä­Ê爵ÕsìN‘iˆšð("ÔBˆŒËÖY@79 ŒÃûvÔ O–Ävã_¨‡ÑÈß«.%Ãö€š.ñÑ*Åf ÈWÜVüÚPÖÓ§p=͉ãuu/ÖjÌ; žd|,ô0®~²»B;@:ï–Ýê*ÿõÛ|ÓI+4ILš ŸãÐ1o9ëÚ9h­j d¦ÒîY€W:LxBzèaÅM–à“S&Ú°·ÀB°ª: Ñî‡[þ3N~fgOᩘMwÚ¡Þ~÷Ðó¨¼Nƒ5ÞWéµ7Jz|\b<ÝUÑŒP mÖ>Çlçx®âÖ³3±[pt$ég]õªFìzHèÏUÌ|MŽ@Zô.²ÉAs¶©Ü˱“PJ¡¯-eÁ‹~N^äp§òÞW*Ø<}`Êkœ–;±U§[‘þ‹]@tn }DzN.w!¿íw90Ü<=c›FÕ%0}>Ýz¨ÎŠoŠ-J¦ú,Ü•àÜz¥éƒö"lÖµû_ŒÍ"¾²ý…pæXÍӻ؆n°ßÚÃwþ`]®qÖ£ÞFºSŠJÑ9Ê‘*»çfeB4”lù`–7ò+ã!xió0\öñL®üúd²š&è ¡ô¹®â'–³ÿ":þÂ:0×á{õºÍÎAÇdƒy7< ˆÉMÇÈ~ Ñ£,MÚ¥pgÿT¼‡¶œméL©{ûb¦—®=ß…µ6Vt¢¶ @´Žb}ÐÕkãA}ÑÓXå*²éz¢Ê G’rÓÒ©öK-SÑ 'Ö|‘bÞÐÓO3é4t ­íð«Åuw=Ž+˜ÚOùw_IG±ùd×ð‹·#òæKDï · (´‚ãÿ¬ØeÙŸRM»×ɧA4í4ËZÂ[{ZÓ‰SÈl›†¤Òµn®eæºgªUL &Ùä*¦R*Qµ ®šÎÀ}ºqdœz®JÜT‚u}MÛU5Gƒ{ÞdÆ¢ˆâ§“\òÆt5ûñºÁ¡ ‹Ó‰[ñ´:uóà«­>½2¦Ç‚)8ª™ø>µî~}sÚÓÐ2¦…¶å7Çzƒ¯TE¼×!Ô³V7B¼69õÇQʽÐ1Ëò92‡°…Âá΂{‹|$O¤À:ïûâX0Kò4jô4|»Éº¬Ì^¦ÆÛ¸Xà°”l§Qá’¸8f ´ûU_m1Ù F²º˜*¬Æµ ¶×«ØVŸ7ƒü].È%Ú²6O¾É³då¨Ïvœó^M¾6I—Á Ò ¼»$¬×sÙ˜c‚XºMÏE]ÔPpî_ò8…MÁYUº¬béÛÖ¥)w*‘¥×é®T[Ÿaוº9q-E[ñì?„?•V™h=Ö¾=r"ÕãµGXKù =¯ÚñüÄfT˜<ÙE»Õ€ó]t4¿8¹ÿvúosÛ” û‚D`ù©³Âdœ7wÞcïbR¼¨_¸: –χa{³±u*_üacQ¢Û¥œµî7_õÎgYƧþÂx8Hÿ…üŠ!‰-ííêËO³àKé“E‚ßlÞsPžþ”EѲî<DZåQ\¸d*˜øq™´o-²V´Rðé˜&W ·Eº#ÿ ¬”®‹¹4¸`o¹!B6²Q¡Aq5ôyëêS-aŸ¹üF׃zÈÚj$Sƒlª{ÑÐÒ–5¾ïŸEþ˜ º„>Qú¬xUþדc.ÞcáðªÜÜßÍÁÕ•‰ê)avçZé`! 18¨±„+Èô¿>d&Ý J²ì*4ñÌêÜ“¹©l^Èë×Ä@BP ØÅ`ÐA ²»% àª'³çÝØ›È ¼¹ÌUA¨‚á(jöá ãÑ0¬}‰“E‚09 êÂwlɨ/€?À‹©÷²AuàÝö÷d£ëä,ØWRí—%Ò*%e’«JÍå!C—[PÉ(Â$Œ=âç¤ßë…Kãζ:Q;,`¸þ ¢ô¾¤ªÞù ’o[_Þ˜9 Á`)¤}¾¥H‚¿i¥ÌÎùËþl¡ÞI¦yRÂrk_%“[°sû¥Æóê€ÎêyÞ6À–±i¯5jÜ9žÏÍË×ö7V•[¾$ÄÕòZbOÙ|9r0~º^™ïQÎ7ŸÆ&Q@šoŽ eg @ÜH ¡QþNïìpÕ7ŠgØ$*÷"Z4³»#Sàìçðª,Éw¼¢Á€Ä#s„li9‚„_7aÜ!÷âÐ>³ˆ5 Um+½¥4³œYÒuže0fI³&iž”Ò=}©ùW"¹¿õsú"ïKdmE&¦ú«Í¼‹²æXlô¯Õ²ÒÍò#«7¡ÿöËVžà癵ÇMÁ³@æÊæôÝ0¢ŠjÃP¢0¾_Bq»sÄÂ;om¾V°ŸE¢"x"Ò> øµÆU+/xJØ$×ç>y‚¸Q"Võ Z&wȵkÌhλÖ²wÌ'ât+öõ½s þl5ìÅ’9)Äœs¼Âͦ ‡½ïÊ‹®ËwœÆÿâŽuà‡þ<ˆô çÝcã0CRGþŒOd›AüÏE ˆéè^%h´ÛiÈ*O.äÒ;H§òýþ4?æíM\gËðÖ+XVÖ», äÉÂPàt'ôÐ,¯–"›‹Eg\« ÷¿ú>suä ê#iwW{¯n—w‡¼û@ È7ð+áËÑmJ6Äa¾˜Fé! ܉îÜÆ6‰SÖô°5¼± Gòª|÷­…`/ÛÓsrßWš­òèxŽ™*9-´Ò5é¶f’̬¾IXæìn‘š1<}ÙËe‚‘Õàµl¯ú³Ç}E:@ò@/îÈPºìü†¿4Ÿµ­WÊö1-˜g97Œê» 3I^ίΙìh[òq”AEI‹á˜ï2âÉÊ{]½¡X˜%ä†ã팕̗[V§ÞCMíûKk6‹=#æ «ÈD¹aØ|4|¯GL8àŽ=ÛX!´–²c¾ë„-lýxg,D}ŽÞé._À¿HAOûXÝð”uII‹‡÷ª£~ôšuxþs§œ FòŽ››—ùs†RIŸõœÖ«-iíõýŽ ‹ ½Y[HP¬»·¶Ð[äÄóm¥rñ¥ÍÓ £8 “ ç$E ò2^œeö‘^½“â D><à‹ÝWúäå&óìtð‚Ñ©ÿïVê…,yÔaoá×(Ÿ3Û"À[Pë³7²kCâ²êh#ØEí8”Aé…&"UdD„­+ˆÑ«¾ú†l°÷MÀ³3OŸœ²)…30Ÿãúç²*V’ßùï‚ÅžPr=•Ù(î "Ü ´6óÐDÛÒsÙžšFïÛ£.;dvòÑíÒ\IâS©Í¹î£ô&Z˜‹®Á˜›wo{d›9tî‡ç4P,vô¿yê8è}”Œ¤¬)'gvÈ7OÀÿ~–‹XÍ£³Ùº õGž† _¹{[{£påÇBA|yG²âø ¼pNÝ䄃3©tðÔž.øâ€ÄãšÞUÉò²eÜÂQ³âoåÛ íËõ/Ž'å7Ã÷”›Ùâß~AL¨M|£&K\¥p\G›„7fïÈËÅ[x‰— Ìÿ$ëG¶¡ðƒ!Jþ"ÖÑã›AÌaŸîâ®mÀ+’½R†»ÚÁñáïu©Õ´êFEq7Ýùú ¸Cd¤N=ȹºœƒ‹{mØé5XRò ÔLµæ”üu¦ßsÅÙ´À>¦Ó·v­9”sÞnÚ…#ÉÂ:Ój?`vNìŽûào FÊjdη6¤Ò½î”°l[›˜E]ƒ·v½¾H&P9¯Óú‚ë7_ÚÓ²¶®Æþ§¶Á‹7KqÝ=ñ{þ˜Úu)pÊ7]©ääY–É ©ùF¬•öÕ2û{M¥R=¼§špƒõš¼UMS¯DJ†7ÈîF æ'Å”æ;g­k¨›%XŽ.Ùmïö¶%Öæ€6ñmv³4 4›ÒZB9²ÂÃñ¥Wd{ã â»è?JejÿÇw«RLu'ÖTS‹\b<¢¦72³{¢øÒpgdÚcÔ…en­Ý z÷!<·ªtJœJü×~R2°ËÐ' 7¶–H=À€|a Ò›;låÕ×2Çp¢¢•“æ'µ ùEAqñð¢W(ÚQÏÇfö¨û­)¹ÞÇ`ÿÏ~]í@Ì_ õ&nñ»‘æXì†?)‡ÿ_%8 ˆUCUwzéUÖ)@Oª¬Žg=ËÁö/½,õéXjžh‡óuLœe@s•Í– ¯èkthQ¸Z¹+i¤TÐÓîŒÆÌÝͺ'ù'ÌL)D¦Š×r ìÝy&N ‘JFÙ¨T,“2MFãñŠŠ[Yä'Ù2V=YÞݯÍÜå:n! ðÕHÑÉmù5”@¶užCºss´k@Ø‘ð*íl©Ge–†… EhêÔ•ÒAf±®ÑõºàÄz; 6zƒ0I%õG ŒWB)£¢gó|w4©Ä‘„A5Ïîëæˆxó¥t”q©\¹„Y–Wd®Cåïí> A ­=QÚ’¡Ï›¼I,Ç…zÝÅC)Ø+¨ñ^Y‘\Q‡ k}oQ8Ÿp·Ïÿ[_xc:qWäÁ©˜ T¼2azIí$·¬©¢-Ÿ·I™.“ұщ§f=N…KªïtM(­]µ˜œQN/“6滆`ã*Jj9šãuÕìͳj#YRÓѱp6OuiÜÐp‘ϧÉwú ‹ð¯H„hÓbnÀ¤Ž«ìZ)å<ß6FÐO™/Bvz5É÷fW­¤ø¶úÙ;¼_בFj âÙK|ýõB”¢50‡õçenÓ†AsúŽPQ¤€•| @„Hø´x]ZgÚèn”#_o[4»àg¥æèÙ*ãÂù/1Œ_ïuÊŸ3ïµØ 5 Ù@R© mÙ땵ò«¦¨7åišá’-!ma‰¼]ÚÔþ®ªFð$ÞŽïò–È·½è ®Õ~æÀ{š*)m°;Þ,m¼Èk¢Z¦éîÏ&ˆàKÇh {i š7zb·Z·L ÄZØ"yÜ -52§³wÀ×UÇÛRÚ³RaÛ±|WR Ÿ«p÷®Ê޵ ¨)ŽZ¤¿JUšöInN4hx_ñ˜Dõ0§o±,p6|ßÓtrÆ´–ÚíùïÕ"ÙÎ^!øˆl‹Ü³Ä÷khHÇþ äI"ÈÂv¦¬¢™³@&ýa¨<—f ÷¯â{ϧ¯JEßVWÜ…ÑÊ@y—Iö+ÖÖRɘáãŠË¯Û¾Š2Ã’PüeÒ4î+¦0¹ëexUmd³®ù"³.ª"~¼WIíÆ'‹á1®oÖ!µÌ%=>U––b‚ÉN!öiE§'»T÷¾o7R¶~ë?YØüúc…ôÇcû` T™LLè”d*,žÝ¬àI†ÑÃb¥Ö&G6½º¼Tù6XfcBwûQ¤ .h9Ý!  #™Ï%¨µˆÉPN,úLJî%ņfD9ïÐzf  FÔ…Ÿ‚ºY8eM²›e:Ó}Ä‹Œ‘%ØöºfÇe!F‹QVS­6ÂT6AÓʈaHVÿÍ;z W({=Ù «oÇîÿQ©‰ðY&6EÁ_`zªÚa­æXrŠÒn˜îÃÄ… ߬hpƇ™÷JÕbcö?è!ù#Eyë“·ìÉ 2£í¬cqÊ"'–åµmý•|u‰§Fü”—\>¼{&«\2ÊÖ*]v{ J¶ìö†ÿMnÿÄE`Ñ‚“Ê¡|U ·O‡Xø|Ák&š<£ãQù´Ü&dÅÅùþ{8"BiÙÇ‘„ä!î$õ-7/*àˆõƒ‡ZÌè„‹ÑXGà:Ѥ:©’ ?Œ£¬ûGîÇ:…}î&3”*¯ÂA™p£õ¡OV¸ªk Ò/Åv7¼ÃÖ÷²-‘u¹ðªŽõœŒÿ.Ùÿ.'%IIˆ±Má`\~{ËÄñ Ý ³Tî_„wžýD§f¤t GÓ`d•EŽp+!UÎsÓáÈÏ `ŸéߊÔÌŽ›š~v9o§ÑM«ŒÿÓ·ÏÂtÆü?½×dÜŸàIÍÀ@Ô£Š1Q¤üt¸²‚8¥d3—K<€Þö=é¾ ™7u–§–û,EРÐÕ¹y¢ü”©‰™Äüνöýü@á,ìt ÿ[_ðvcœvë@u#ù2Ì̤ȴ¯û_Ý„P¶‡‚˜cÛ~¨ìC”¢ØÕŒÖ Áa»jq-_[õouÿÁDà»é€XÎ͸-æ¨I¼RkÝNÎØ¦Ü•õg[†n=À,±+-.±¨2R}1ä®OŠQ]T‹D®Ýåá) èñ±Ÿ=xã²Ï\}˜ÕõuaD°Ð±©ÚÙÍÎG’ðªÕH¹ù·0ãêO2óº†{ŠÝ›ê?º },wiعfˆ’úÒcŠZ›aO°áVí§gÛ!óøé¯/‡™û›´\ß8ôѧò™\UÝËŠv,%ª´wº:Ý1¼%Ç4 Ö¡5[çÒ*\ÄÄ ]ÿ÷|‹ÅI”vöFp&¶üÁÅmäžÝi§ãI8CTpâÇ­6¿Ó¬Wåba‹Y=ÍöÿÈj[ýƬUÏ3yMGÒ+Ú‚ô¼æ¯¯¤T>Úê$]‹@mðìÔÁ”(b»”A~)÷PiCèÁâÇ„ú¢ ‰‘•m¾©W‹ñj²­¡]™ÄT¦~—ǤÅYW¦bƒ Ñm†ør'ìâVÒ™¯x)¬d$œ%™’˜€} ^ 29AâÇà,UH“d\èÝÖ¡l>ˆ¤àMáaôŽ‚­¹ÌT¾r*ËóLðÇþ%ȧè«*M»ÝOˆUÃÛJë!û²'}ŠŠR?„À̽ûäç7÷¤‡çææÝK¿Ï–?Pm™ì"ˆÅŽ#]iŽèN‡äæÆÌ5k/õÛ$ €Vîc ‚ˆu­/ÑJ´ªzç•IæäXü‹/LÄògŒôãr2+OoAüżÑD¢ƒ‰ÆN½Îz.Üüð"Qf4ðm°1Q’F( æÐ÷à©r ¯ŸêäÖN-0¸4*< h¿bA]Ò‰D(5V_e©]\‚âÛ ÝÊðÍ “}ìAÑŠ3Xr>[kæÆJzn~7›ðtyžv]É™Ü<}©cIÌtqÕ”ˆW/XìÒ[hÒ|Ó­eÆ;ä¡°°IİÝ-Àâ × €Ä±A/­újaHÌnÈ&¦ã ŒAtlël®ÈŽ©I±!wÒZ-#ÆYRýÎ ÞgJ¢ƒ¶ˆ™y6S<;Ì—4‰@==0ð)‹½ö°œÚøò¼¨N“àÛ¤…†™ÉøX ëu7$É%‚ÑW}MQx&5æ¿YY`»t°QýÛ C,ˆ‰Ìa5’ÄÅûkÉ ë¸4óJCŸÞLÍŠúR÷GÿTXx]xGÓ ãÈÙÿ±1Qo‹Ïxùà¸0qÝErN›æë篰Ô7]šõ"j…»ïg|R-¥Ù¨…H鱋­45äm#ÌJ»*wÐ>CØì<+J/!ó°›`þz^JÀ2Iá¸n€ßèmJhGþ:uZ³T‰UTlä(SiE–êàUû]› •æ‰@‚ð|¬Vý½SÜÒ‡íðü˜æn,r95®#v­‡ã– V§·XfðÂ¥™„éu…jx2s¼îa¡Sù½‚FùmGëû×#˜M2pÕ bÕX$ ôEìN”òßâkqI îPY¢q®þ^Ü·#`Á2A &ÜÏâßÑÓ—$€v$«³VV\ÞUüKø~ÏÜŽ,bÚ¹wcÛ³g{Lüb®vÏÐwp äï÷W7beŽ¥º'ls˜vÏ Ôð 444!;£N—æJáÀü¸7ÞȺÒq¬Ž¸£ #H·¹D`s5ª–ñ‰”x·¹e0~»oQWÚwËbÞØÜ:ô¾§$LoÝÚ–I¤ÑÉõÉ28Ì2|˜ @n aó·«ÉÖºÞ¦fR¶nR‚BÏüý¶{ Tödöµ¿öÞÝ6N+¸ €!(¾+}ƒÈ´aÞ‰ÁGáF=å'®ú5Û”\-ïèeÄÈçD¯IŠc®ÀLD’­?’L4|ˆ/ÝWÆ£˜Í2<ÿ êrp:Ê|tsDÞôŽú1%.xTb#Ý%˜†{8 )¤Hr¾…'à‰¥5ðt„£WlÝyå/“'"9c åAg®-N÷ë AÇ·iB¶‡1K‘¶©0ëuФåOt%C$¼t¡ƒ\à†v6`\¶® G¹¡myЇ!»ä¤™Ç΀ów#v¡¯AyͲUíõ —±ÿÀbVÜpÎ0QóPw¸&q­ú >窰„ŽÐX‹ð›ÛÝrF%õ°×ýMì‘„É«J~1â[ô;nÃIÆÔ ïaTÙð¿BÖúV«eu~[–Þ"õ. ãc¿cžóøb‹u½Þß´*ÛJµGµ–îŽR]tα¿êIyZ Ì¢³AŠ¢¥¥ôwJ0«€¬g²à»l¢é’µ‹M\Cõ:¦jÎß¡Jç™e>¡_ ‹Áê °ýÉî•DsÁ\*~`Š-»ûŸd„·„9€_ã ËŽ£ÒñNçËçë",Ѐ×ÕÅóûÇ Úä-š+½÷’-K¿¥Ç€xÑ´dS[ä÷*^E¶Ç< ö Gé¼Ì \Mê³$°JÚ»™Ç%fúÑÐøkÎønF:;lÛ¿"8¦ÁœtµìŒê`œ¨šž=Ε6¹©i‹*k™ƒˆ'u }!.„< ³Ív‘®8£6WLÓL¢î»Ó‰n ƒ  Ç ð•ËÌ!Q#%†´É3¦riq/ö°ê’rÖEWÙ¤½îÜl†Kç~¢-H“:˜÷Ù5ßz©´`O…%¹qó:ÅŸ%©K9= — ¢ñFºá3) U[S^hç–«¨~7^Å¿„àEK\×9-iR*^CØ%›«)(“¿\ÀY¿Mn1½˜»gEˆïFˆíê§ÀÈÅðˆ« CÖÖì’s`2 õœ‚ãbT€ m½È-^»Ç]žE¶e wÌat:É[ðî p(rcƒßBËñÐYVc¾~äAn ªd{*u(aˆÚúæ[.3…w*",^ëÕãYÆ ÿF½);¯ÇžÛ‚Ä„é0/ Ý,LšEd|ð£xe·í‹Õ:É<˜-аò(5pWRwõªÿéM‡k“Y QR6¨èƒëNºF/]ðùSî»FNòù㩼TXžV,¯ðŽöŽ…slµY %ñèÂ¥Gw!ÄfT±á]Yÿ&u³[lh¼¤ˆ@ïO©ýÔ¾*bPÙó½Ùý–µ­Á°¢AÿÛ‘|^™_4|=õÝàhsÅOä<ÏÎM_ŽèËþ•i#íG„¾¢ˆ•±4bÎs ¿Á_i=èîówŒÐ9_^§3\«mä9k– \ÎZØcíÀ€bÂíü VƒˆuÖÏ PÞ}«éºWŽZ0kîÎk#³Î¾Q,ïlXIDv(Sgï]â`Þ!µ[O•® ì¬L7~Tÿù3„Sxøõ<åU—¦ìœö-²À/ÿ·=8ˆÀU±'ˆÚIÌt‡a#ƒ›’ßõ“^µà³ØVbp2¹Q!L[aßq¿®Z»czÀë…ª‡”}Û>ÓQ¬¨3B·áßlFhÚ½&ÁÜDn’OlÒKó§Ù~UO¯Ñ£§wu1×…ˆ§ƒ=®¢ÈqVj¦"¢MžÏÁ‹ RЄÃqA¾Ù–y+¬wãQ|Áô¬|‰õöëoÙ*ï™Â}ŸiIm@>®Àቮ9`òäŒ<׋¢ ·û”ö¾¢^ãÜän_…_•vɦ5§\?®ÐS:sö¾CÜ+Ÿïlk¿HÈš|ÔÚ&šø¿-H¤ÍÂEМAÐ$·1h4?‹³«ê’ã£=R^—hr5\îí÷©Ãç}…ŸO½ƒºa3Y^µTUÇ5E% W4qS}m|¥¤¢2£b* ñÛ6£QèŒÖ·ÀŠåk­ƒ†Cî;•ä ÿ_{éã_½Ÿ-…Z*ä"Ïx+´¥Ýÿ°œR"õ¿Œ¡üô¢=¯„ Ë>¨NøuÎèÈÓ¦£E”¸H ÞêgŽÏë®*®ò¼ðú ÁuÝT¶]Û˜›$gËjeë}`R #ƒ&…%hnIÚu—qÜ Òt<@7ý: Þ¸/Øã¾Lkg*ñLÞ^™­ù=Õ5WEƃŸ%ØëI ðIžñJÒ$Tì_ `´Aë°v0U{áõ‹ÐL¸¬ºkë ,Hu(Ä©ùÔ™¥k¡”ÇúUçVrÜÚ€Z\lo^¢(†ø6þSñŦ>wÄ»Œ¨#PÁ½žBîäG|Zz£B·%fC°¬©)àõvº°ÔLqÅ\í¥þúRÔ·žåÅzŠ<³˜îEµÀ„dl´Y5å‡îkXÛ ·^L›Ͷæ¢P^Ç7R{ÄPzï^rÚHô¨Ò»ïá‘[ê§FJ‹ ªcþô¢ì!jY§dK3¦Ì#þ¨óï¶ö®1Ú'׿[rº Š1ÊÛRëËúó U->ï¡0¨€uÀþ[àÛ;½Aº#Œ¤¥;”Ì‚ý L©“ ¦ Ño{;¢k°­ùâÙ©ö>ÎÿðÙ7àç« I¬ÑÃÓÖO / õ(EÀ‚áf§«Â™ýgl;1Fd:Ê5ij(A.¹®}æ©[‹Œy^!üÍøº¿}ÊVêMnpz<ÚÂ3³v{ooÁö¹‰6Ë¡gÇqƒÖK½P¶(˜d ÑÄ6|u5eßšÕ”‡f’3ýP‹£žz Ò-Xf†vÜ8¢ùOHS] _ðYß…Ö² £3‚4ÌØðŸ—Î/©i^â+¶;”è£TÀþ>îV*æzS›« <´¡ÿ oxöš;øD‰®6#nÑh°Cd™-šK=LçØè+‘‘þˆ|#œîv'F…†2ïÂM)Ñêð )ž¼› {/[…¶(•·/ ÷ΘŠt{_òÁj7ËC4"Àñøbîë…°€NeˆÈ›Ö&Ò^ÅCóÕp€…ø”Ƴ“jŸç9ü;õ!C½/ŸÁÜ6áö@"v=*ƒ;°)x°¯7/×ù¥nW®¤ ¢ñÀ.Æ °öÌÊP‰Ô‹:j¿8SYˆ0äíбÁ5±[ÿ¯/P 6¦@fú±ºˆ‚rYb7óúÈörðrÖÔjj1‰ äVí¬äá>}BÅÆH5SˆWq:²ò©`÷{@b«IpÐk£Ë\‹DoŽc›{–Â2êJWäÄ09°ÌL+](ŠG šfüäö`X0ó¼zµY¢IƒOg–mFCÌföf…Õ¨¹`!4­MÖ·:¦øÆMl‹MÐÕgf,¬:ã Qgzú åFrɧ„y© õ—ÇAl-gë#¢N¤_ŽÕà…l ×Á_!Èpæ~hÖ0rÎ7œÒø{ʼnèÛ-®lJbšÂì¿ ´É€…W5ÕJƒ`¾Õ +ºW>¢Œ:€‘,ÿÜ“Ì0µ‹x7ô0ªXŒ‡) Jtôe,‚ôn\XݨKãpÌ”ëp§÷1ìñZ+3IãùŸÌ²þ*càÎÑqÍv vNà\èCÝãÇØ„ë`ÁDËÞ¾bÅPÕR¹ôâéù8+úäÝ5B,U‹h\µ£.VF˜I6rI' ›J´G¦’ø7Ú|t¬É¾©?Ká’ò#†õ*0! 4ŒÍ1“¸Ã£„€]4ùE~b>DhØÂÛ¨ýR2íOq¦8†d7ua³œF3RÜþàø€÷Ñ]x$£†QÖËÌ#·Ž@ebµ$ýïÝkFTô¬8øD ß-¢o5˜çŽÎFŸßÖóµ¦@ê~$Pä ¨gÛ°Ùͪ ìIš—”!×ÞQ‡ÀŸCUd6ùÒSÙvBì‘Ï*®­ÂNþÏP¥Ç¡À˜p`Ï.áùxfd :!ôéþ¸^6 ÷ð’!Ÿ’Ó~âó¿8·Qù ˆ9þ 5ã°²Œ÷çÁ$÷rÉI8j)Ê]‹x89"vŸÚŽá‹>1>m„R^ù^™œ8 ,%†Qè^V ßäà8â’^`x«Ší„ízן5¶ÿXÀI*åå,‡$X©~\ Çqcáxz(É’g˜WÞ{àbH,·ÏrÔ3lƒÞY¶Rä,wŒµ1¤S~¼ è¸üI¶b#aKZÎ)LQÎþQ›k*†ã32º7;Õ•ÀpåbTÐPÜŸÏp±¢ ì»áWœéÆ£eqdâçö„ôî3›•,5ÔPGšÀYœÔRin¬í?ÕÑX¼}ÛZTÏ5›ZëàëŽ%ÃBñFE ûßÿòʈM@Ÿî&ÙÊÚbÊÅT iÔ·&]Íú߉c©¤ ('ex‘“ FɈXŠéTÖ ùzÄ71´^ ×Éœ#$þëþv)0¸®z¿‰ABñƒš¢)A'*ÞxJ<@Ì\„nIZt09W^÷ÆVK¸(AuQâ=õ±Æ?àÀ5ú»ÒÏ«»ÏµPê^kÂßLj"¿yEYï¿?üæÉ±{>G¼Q‰X{æd¦fgç„- âG[tZ¡ Ãß+Q“fÊ"¼øõ΋³îQÞw˜šL ‘±Ñ¤ŠP~~”;‚:f‡Âà—8{¯]èi×çùoÜOÌ ~Ä&Ö2Zp =ÞC¢ögA.)og=™"?„ÂNqܾ n®¦¿ì££®žb½Æx®nòZ£A=»\òyüí@57rÀ"ñš;ddÄíÊ^ÖOsЗÃåÙp:Âî{€„Mç#ñDù%¼èøK&zý Иu uÓ?2:_:C:ਅªuœF6w$PtÞý*_-ú0…ú.©FC\kpÈØ>u­¶¿ñTàu—é9¹gqmx…þAõàdBœu©NÞû§væ”ß8tIˆ%Ãk¶É»C+ÜOÝ „É0Å1²KFÞŒDößæ žÊ/ öpXÝ›ÿì‚Ê@$©b'UUHÑžß:¦ÒRÑò“òÇÏrœ™L˜g@PÛÇšž»+ÎkævšÚ‹ËPrï’sËWb¯ŽG4rb2?‹)¤þÝгó–2›X8îÐ Óo˜¥j¨-§z^æuιªKf¼âœ Ÿ ÿ§Hf1Ϩâg¾(+„dæ*#0⤀5|X½ø¥Åg"R§÷«¸ÀJÜÅ׊ 3ˆ›«ZtUééqraŠ9¶~¯rwÔo¤ DõiŽ /˜,8‹J‘³j»!¬É¶Än Î:[ÝņÏÈ‘9ÌìØ]ÈBóç3ÑG£»¿ýÖ§1ǘ*Ø‘o·Ù~›K¹,~7÷ÌôˈÕA\úCƈ¶¶²Irq;ˆ ‰£„?o¼DÓœµ.ö4^ –ÖØ9àB ÅÙËŠ³2g)+ûƒo%ý¦a;„µqh@åõ)Hì…ˉ}¡#²|Y…fÙ4Ì»GÒm¹JG<åxÈQë 8!G(ëUNxgkÏöx¥±êoŸ 7°§M[{ßÎ3¦ý ¤xèﱸµs˜Ï,ÿsNI÷^ÐÉùwÒ ‰?E ð[“”Æ–Š &¼‘¹5S ²ñɉ–•`%µ×Qž3lûŸ"Èd_(:57d±BW±\f°\»€ÎO1 Ô?.›>¾¸°R(šgˆxFS¡“Ë8™s›¤!ç•'E{Á²ûÔˆVÇÎW0ŠÍõ®|O¹/3ΪíVžÎ|+Šo3ÉÎqq+…·ÆãÄšæL8ìùòS¬aÄ;䌡‘©Ðõb…¯ü=(…"§ž],PéI ïý1_½^Ažûþã%ôBŸ¡o]0So`äEŠˆ l>@æÝÈ™uìñz=í¬ Ž}¼‡Þ»×›¿5ñH³Z`úþ† R”wR¸OþP ì4‡Ý¸Zl¯³Ö$}œÌ©þò-IiߨÉXaÏ)-K[xbXëBáÃ?¬*UA¢ ÔGü53ÃdŒÏ[2r{ÇÇlîæa~z)!=•ò/ÖÏùÜ\…'͆#ªHöð5S¶èµõ./F{Tƒ-. ná§ü ‹¼¤×MTEJ#Ae]ëðheäÏü_`‹?5›ÅAbóB1:1ÛHڙĻI Ž¡†Â¤|ñÚâž‹1Ø·[.”ÊÏükx—8úê÷ýÌPMLeýù  âQú*`xv¾˜Ý…0" ÌѰ"³n±Üw +´eUñ÷ÎwePï_øÒ~ã²xu²ÿøc*lÒk¾L¢°S’âz.IZÑ@Eä2ŠWÍu^%"µ~ ËâŽHþ È4 µŠA›ì6û5VÿLØîç,-`³Qæ!!4ׯXwžÈc_-FµÃá;6 TŒ÷°^§“yÿØiç1×û÷ö‡”᱓Q/»´Oä–ª‘+ŠjûD&úz®3©ëˆiSÛ']Ê_ÛFÃ3¯Z$€ ¼iP¹Š]&Oê°ðÙßÉsÓ_D‘°2utE¯ëœ^ºXíH}ü°†±¾ÍBv¥BÐÚq»×˜Üǹ t,× |m¼ ˜¢iWôèyrž¯åibBüŒ†¾ˆ+\eDÊÐCŽ~†B‰Ó2Ð=ûƒXz6¬/Ä-añøò+''¸ üÐåªÅc‹™ÒeÆPbc¢íÉã÷Pá{~Bƒ¿CùËbò¼Å¢âŽÏad¦¶TxWà?¨Ÿ'‚’6«¡\ ;²Üq»z ø"gÊħ1•Î×~û= ¸ê$ª¥Ç[ı™Í ÁŽ’¨@ùæX¬ââiJ47¨ [QOñ¼Éoj³cF œŠ„ÇãæÄê#øýM¶Uæ‡ÁSUÌÄö½^’±ÈМMéE"¸ÿú/«î*L5O¸×Ö_Æ^VNs°0Bšt%y®XBjÖ @ ]A¨€@~®%Ø«Ý]Õê…Y Qûú¯QÂðÖ6{è‘Am6TéÓùâ0õé>æï')ôµ›àÃtau\=éÙwŽTµT”†ýØÈU9Ùiµ«ýAH`Ì(ºð‚ÌæUA©+Mó9¨4òV7ÃÒˆNDIüæsK`4°ÌÍŸ „kÏu¬Î˜ÏŸÄJ=Ê'Ý]38b‹øKVŸ4½”(,_Î]R/Ÿ„™ø÷SÖSgÛ®‹Ù‹oà˜]2Ûhæ%‹£tbU-Ð* hÛÄ ö4{ÈvèM69•Ç[ç þŸª$p0¦ýþvÃ6ùb²47þGĤ-Xç˜zL÷½ž!e‹+”¤7ì~PÎL7~e3÷>ÌVîsáLŒ÷«'©ŒÆÃóËúu‰#„ÏžXÕ7ÇݲWL@Eý¶" eÇTôŸNÔ^œ´ÉŒÞéÊôR{Kœo[;I$¢M;^)biê¢ pPPÝÜ—UMFa¢æ˜“!n¨™XŒ¨ÿÛ¨¢°Aj·ã£gøZ´3¬¬·l –êqL:(¸ÞךþQµ •–= w)³7‡ÿÁTQGµbì÷ô1rÅ%°Êµk.±²üˆ»"Œ+`Ëÿâg@üS<Ä£ÑÄG/i¦dÓMßß\[†b¨÷ ½v!Å} 1ìŽ[2¨„{ðÆNqt4s õI°×»Å¹êŽ”ÌYùV&̘5Œ¸zœDÛý´ó#þôÒãSe¥í´ìMùï_=$Oðšñ$Ûe`EB‘Û—„)Ë£Ñ] ¤iPÏÈ‘w5ÛtÑÿ\J@¾Öâ$C¼ ²Â+v ¡%)Ù•u š“¸vû½ìÔ!JôœÇ÷ïˆe¤·Ý¯ÄÞð®Üx#8¤NÔRZX­œèøJ@ ¬ìˆ¨+{Tœ`vˆŒªO´¾ õ€´ñ‰©,º–Òü>ýйó|ÂÚü¨˜vàôn!]ðÞí\IVÎý9¨ðµ)K¾â]bÄjDŠ6SÌVzªâ OVö«žëdÎ2 8I¸×f†ä½V8Œo„@óUI 'Ahb«f_qkÞ¥ÿäïü=žì?ÈIàÑú'aEbîhxì\aþ§¯ÓòЍ„Ÿ^L|zNÒÓF\—ôT0°@ šÛ¹²Lã£nŒ°=…W £Tè¬jG;dÜ °A²nVÛB“¹nŽ©~£BÁÓú¢>6t†¼Zõ•É|̀ћD_ƒù¯—ä`ÜáBÚ÷ü쯤ŒÖµBÚF‰#Ãþ ¬Rl,¸F?ÝâQù¿ÕŠJ˺rDøÈ ƒQúœx)þ(V·éú¶æ9á‚ôÎôxáÆL»vˆ&cÆ2w$Sœ›T(©Î’JÊ¡À’Y>§5 ¹,´Æð§Rrȱ¡€—þÖÎæ„x]ÐrôÇl%¿ço AFv«›FêO[bÁW·¼´pW8©Q½µ ‚á%6ùoQ²û¼Š}‘·‚ÆHZžá£Ä+iFøÀ~¼÷$”г»[Á=h¡"¯I9ÚøÓÜ‘ÛËm¥TÄ߀_F^§Í«¦ D1ýx°ÿșȠ¶!æ¾J´Ëd3(ƒþœïÃ/Îït¨ÿ·(NÔ„—$ï»o6ä"H˜‚y§?;Nýfiö®?ŽÎ $Ês=Ƃ׾¯f†dq'G-‚Štõ澄Ðs`Nº›ìÒöÍ“GBôdÛslôþâ²® ¶Û„üÇÂä«¢(Ò§l‚—§`ûÿF³ßlBp.Öœ3+^¤ÆT­™J€·6Uƒ@ßÏ€nSÞ=l°}às–”Z\aêφÉtÊ©”2Ãæ‚™’ôD¦Ds;U^~À½ŽŽÎ™&¢ q­.ù¤ Eîht0«Täàï>¾}b¦4ô,§üžý7Ñ?óŒ@çG5Ѥ¤ì /ÂcxdOÇò+dÿëÒ€õÊ6c‡§ß'ÄÒÇ”åé³"c›£ø/…j„é`$­Jz»®ßç]' e8¢‘Æ0­ˆãÌ®J¸ 49^b¤ÊóW<§‰˜WÇ~Oú°ä‰EÖhŸIGå F*ùo*"ûc¡é䮎Z”ìkn‹Œ`s¨’=|ÛÇäå*XÉo ¾U¹ð„ýô ±›MÅ ¦c%{MúpP¿k®sí—ððÛä$rE8]_ë)œœ}ž¡n¨ Fk#0r™« ”nb: Å‹iòúEÈh,k;Ï”fÒLòR›p”Ô*\èHçkR>¼s¡©³f¨Hè¬m.¡šà5py`#!r ÓŒKÕiišíAIˆˆ´,ìU¸š@;·Èg¸ÁïU >*Î.²·«WÜÚó«áž$’&îílòýÛùçrmίðË aXé˹ê¯zsÕÎ8ÕÕv¹8ý _Þbš N<ƒüОò›Â« Ófkm#®e)÷àû$Í&•ulØÚ sWjˆûkÑdjåJŽþ•ïË`· Kãß±øÕðK˜§3ÖUh.GˆP±¶ ƒ? -ÎóÞ´"ßH™9‚Ç<Ìvã E+Á÷~8¬þ[®,Âãa~«QÕ—ç†Ø0É$æ ”Ôêv÷\=­ŠcÏ6zì¢Ê OÝ[qÝž²Œ£üZ­š ÕeãŠ0{¾ù¹jJô®·¢Tœ8„ä ›ÙÄ›BÀöŠÙ>ifÌzÅŸXì¦QA¼Öí?ÝÇ®æ*hašgñ̆G->õ7x ù¼Þ°Õ™Óçxk/Šøá…ÊT§þ¹²\t;&Ój[üÛ?ç^Kà cª&ÆÛ®Wª”:“I!ÝdJgýý3OY$ö} |Ü>ï® 'Ï®Þ]Ëö¼þ†.°‚†™­¨X&rò[[²â£ÇE¯“©EjÖBÝeÇ–MÙôç•NŠ=ëá:Ý×BŽØãuž¹¬UˆàòÌÿ·LG»¨ š»Àvãr//s¬ÏaË\˜>Ëëá·ÁŸ\Î:Ö׎ü”DÈ,–láeû¢f ¥/†ÊÅÿzô ] )H§‚PIÜ»x_]É9v›3„ÒABIÚÁ›‰?¦·ÔBXhßo¼Á%ÈP^ƒŽFV"kÅ">>Pß÷!]#QøÊþÅs”NËûà ÙC}Ë¥ç¼ìdU> Ú|ÌzÖV‘»ÝÛ'’ÌÝ2Œ>3sø”)”×ì‰=¹¾½«ƒ¶¬#–c2úÙ8Wèn¥NÓD”zŠR–(èÝá>6¿Oé}-öËE³ Ç*¨@7Í“2ØdÓøi1îÅh ÌîÄ#3“¸KEÔ¡+ §GSN.® CºR“.·vBÆ©½ð¦O: ÑÍÝ=žu§ÕYøØ%–BJ`:^†›Ô!7æ;,'×}%?ŸT}³jA O̬¾zý²*V˜»•z ­Sˆ‹"»ÆÀÂn'EÛ©cä&ÕYìTX£]N«,‡—v­k4ŒbÌ} Mây¤ô17‡’­fóg…u{1CtŸ)VPEÅ#'Òßð’$›Îî’¥êÇ8îæ¦<’ÿQ¤ÜÏÏRðü¥©P Å»YÞK¤HÒ-žÉ‚Ry½eÐ0±iÁ/H ¡{ÎÈký$S“þÉ’1øœµ$y¤%JàÅiå`*iüÇËÁlëñTUo{ßú.5› ±=¸Ø²µ÷èÇc>7%I9å¾Yˆø\½Í¼›P; {+Ö翟åðñ©˜Í]VìE”o[UK$W;Í,¤É£–ê{È´´Uí¡µÇ]J*Œü¼)csÒ_#WˆæúpÙ\´5ÞôÍ—G FÛ\0£¡Ì29lUößE›ŒÕ…sâyp¦¦ rÃwÞïçlôÌ„ ²^W».-§&>`c4r¯ùžÍÍ3_í>£¢óv Pš ‡;q¹Íu†,Ë2p÷ÿ‡)2/“@ôøâ±_ç&‚ëî$®§º1Ù)ð®Û_†±áæm¸ !©%GKÈß±ÿ…h˜7½`Ô ®å?kÐÕÆûê.m/¬1²ìž&,fixV„ËåéD8P…Öùñ•ìYò“ôöÈ Î‚‘fS 8zØŒû>^EÎ3Févj³ÎrXN*—bšÞ5ãQ„ÜûŒèQ¦l »¿ ¾Fû».GBsRIsê›Æ¤„_ŠSØúk¨9?,¯”e5Ëûe#RqÉÅÀpóÙÖXÌ6øLÜ´|$-²ÿþ@n$ª åÞ傯¡ýˆlOF1…°¾£‰ÇOÛŠÕ’?y.“_uàY¨õÅ=L’1œjPS$Îï{ÿ‚û÷ÓðGï_z%–Åñ›†FJéGÏád‹Rªè|Œ»ËŒ¢ ¼üCHÛ¿›·æb®4h(Õão‘ŠAdû­¿ª„©.«¾øÈ…ÇÍø’›Œéëpõ²ð³%å®6F;JäIìbjÁ$}zºð8ñ±¤ ú4 7‘€¡Ï+^¨^Ú ÐóV…вJ´ýœu[š9cAEc™ ÄW½A"V·ŽÄÝ>ÔšîçåĀŽ8XAD“4ÝVkŠ¿,$|2Ç™gRºÇÔÈÌg㲜LJÊå =æuœ¿ÛìwÕyÍèK†þ¡î>Q¯{—ϲØå½§T·ì TNYøCE«z{—¬Ä§—Bñ͜˜«1-b¤o0—¿4@oLÂfSÎ䑯%Gý€]öäY³Ç‹U$) €­ý®€ƒÇå .+ϪŸßè‘}¬ Ùãôc{‚²j+~Ö'…}¦pZÏM¢†”]ѸávDûŽÂùÍh#žÒÊÏå~.)°fj3¿Æ'-0…Û´‰ªô—þI$͉ƒ÷8î©HŠ Ýöï‹jÖ~¦‰ÞÆ7ù±ÝÔ´0!#Øõ'FHÓl*Ö- åEê#ηc]CF$ÑÖ˰Ëb"‡)°ÐÂÊŒøföìxg*‚J.Ìc½=㥲g¥é[ñ ÒÇ&¨iKÃ~*¶uky=ГеêÄl¡]R˜¿Â†f 2a¤8âà>â¿“|=pøT'½,.» Ç´¶“ô[´zéCf‰¯8kˆl·ÆoðžÒZ“qÅhIëŸù´®Ã¬ ›Þ¥1OÔD«˜+;Ü "hz‘“áHë˜|r”ƒiyÆ}d…¼îjK@ "9> Zqšõ9ÄÞrw›o‰àCÖ†ZÎÿSé ÇOg·ìˆ¿ lȳ÷JŽiýI,†Ÿ6ôdl : ݇:@o„]UØ"Ïò^$!òá™NäK4ºžQ餓ÖË“*'€ªâK'Ø=ØL‹º~@œïyµs_{W³Q>j“ ï¦%4/…HS‹¼ÿÈ?oSÑ‚A½ê8³:/ø¼)"Uñrå§zï´²ÓÅJýûžqF-³››¨NŠ õ·*3÷›ì¡W–]µ®à#ã7¬»÷øä "©i¸‡Ý'жîp8-˜•¼4í) ؾ³¹ú{»ó8®Ð» ð¾-²a FÂN‡Å¿÷T9ªC´œ7xöÂ{+iævЬ錔Çz›è…# òáL?¬æÊ-U‹ˆl™=FÛÓˆIæ"¥\K*{f±ˆ‚5¸úK`Jļ7¿ã°¿~òaâKæ!® ÁJ 3:³}sb‚ý$RÛ‰‰¡(m„ôÚ°Çs¼’¹ÚÝævTÑ#à2/ö¶ž¡pxAõ©6£W|-ôeáÝqR¨·‘là‡Ìß1ºglï EÍz¯Ûëï̸씼ÛmMŒ±Ê6Ľ[Ïí®8j[ËÒ—©Š20„C”H¹ƒ+‹¶Iîwsè ª‹]ùdµ\¤P”à±i^IÊŸ;‰­-õBî¬$¶P®9Û~¨-4»K™Pù™-T,óªÁißÓY—thUëQ÷s³gF ï/" Õ±b%_›¯¬tB8µŠÇ€±FI•–Ðfý7]敼ÅÊ©-dF&ïåjñƒÝÎ%®÷¤fhŒ6ì†ó#£„vËçR¯ç1æn›?^¡9oø%ñóh ÚqlãJ´Â°ã›ÞT@ŒI¿À¥w1UU8¾€è0YaCjjÎAö°©byzB%Ò`f]hƒcŒ”M¯"ÿ/#O¹ҌYà  ¬[«È€t—H:ì…‘Sþ·Ê ›Å¥kòÜ݇L]}¬ût$PS¨ö‡˜‡W‘›RfÀ÷rÛ#PDˆæ¤‘£l:Våbï¹C”5©§‡'Ák,´À+± v#ý]E+q€Ä›‘ ^ÞÅ=Mõˆ £nÛªu˜’ÔRY’Ô‘TŠ-®aÚ.l—ŠÉHnÎW»Pü8ÚUŠI{-Ie3¥ ÇÈÞ¦ïïA´Ks.\b¦<º …oñ¡SòÅm© c‚MqÖ©ÑúÝñ¸’еµÛ<2&¤ã|CoÊ1Ã*³d6×wëDFê.nµ®bÎNêú~!ýk”ç‘ñ=‹/ƒëŸø8èé‡giig2ÒžxµÈ‰¥§ŸX²î©ñn‚Ð%§úZ³Bs–ŽC²¥´ð©Æ;ˆ¬ÕíATf§lbÎâA” M 2¨`™V`¦Œ Ý}‹aõ²î+¤Ö`͆!ü%I ?ù †²@ZÝËØ^ëö¾rª®#—ô‡no}bÆ j¨3§_ιTÔdŠPj+OȘ‘G1ëûý0†Ú3ÍÑÜÉ•–þ&"€;>ç:…–¿aF«Hû;žæ‘UÐô©oC>’ïCÄÏÙSÞ—² õòÄcLÞ†Ãç%V`ìÿô á•$Å»¸Y¥IË8kD„²nƾš»•cù‘è´JC¼0L‡ßˉý£/LCz ‚¬‚V¹Mçሳ(Qg×1ar„fd‰eÕ_¾F^%|ôO¡¦µÜýM»¸¸Yjž:¨ô>FÍÆŒôg@˜œè«á©õ­„ßî4‡òNó)P®êŽFçw è\žz‹›ç+çZ§S[Ɔ”Þ[è¶Ç›ÂØ ÚüçŽ>ùOæ*ΖíG÷@¥­¸BSG¥u‚*&zÃõ¾°U Œ®°ªaÚ,Bº2í_Fòo`Δ?lz’Ik•ç^å °ÿ; P‚lgO‹¯pÚ¡§ïï—ZP‹€]ÐâÈ®…;mùG@÷W,È}g¨úžÆ4’+!¥t¢­RräêÀe¿ß-UäÁ­&³‹)0Nô V\ðAH;ôÜÀ~…gAí;7‹D½ç†ƒÚ^É${ÓôxgáÙòö6­ âßTkZõÞú#sãdB;Û+hg¢úÏJ•ó¹ûRßË«Å×ýù}ÐØQ9k§]Î=ÅŒæÅÿÒU£ÚËÌ& ?HZ]wl¤–oð¨EÉÑ÷¶œ.Ïü›0£|v¼¿Õhõe¦äE-É‹P®{ò¼–è» ÷[ å]Ëö2†Î9X¨Sz2ûçK5ü9“>ÏL ”Ð#:òT_ž*ÁÏÂãPû ˰ WtÝ¢~ÆÎ˜ãš}ŠÜè½á1µØwK‚;·a³[4B¦Šù9atùr´˜@²«£iÂר«‰™ï9õ8eë–Í{~üwMþš—8æ—ÆÓêëMÄâ\‹ªÇQ ?Ð+ˆYSÄsÅdYÇ4eE,Tá;ô-#6ÛêsDƒ°Ñ% ‘èDáiÛIå^žosHdÎ[{&²Eý$€á—¹Ïˆ6´+$¬sÁ”Ы0Ñ“%–$¯Ã¢Cüëú·–ÜJk}üÒ`ÚBí”IO䥳ç`ãØêc.º‰rjQsƒ݈rNå«8W²%}I¶¯(ŠÿÒír™ó‘‘ sCÏ2ßÉïû°å?J}²Šû*ìŒ×Åe´«B2e“-cÚ÷.Mß݃„ì!_¦ECÝeº’ÒÛI©°ø¦³BÖ—Êç“Ñ·›a}Ƹ¡ûùÕ˃Yˆ0*RPß; ¨Æìžì÷,´žIE‹O §—%ŠhX㯯ŸJØÏ®"éO?Âý~‘Ji"Ëõ ùÍÒ.ð:s{ëš©+ãI¦…×w|ËÌV“tÃÓjmJû¿Áôù:*êÓÏòÀPÁö[o⬇’3%:áBH¯œ0‹#þç£8£ÒÖ¡Îñ}@u­½ú®H§ãý‡ïÄu¡ðPÙÙŸ ðˆcZoª>¿¢…«åÆ1RùÚ¹éŸÍfó«¨ ƒäv—1ˆ-ع5úkÄPä°’:f/ƒˆe=prlô Ÿ®2ÓÂðÔFP¢$zˆ“È@¨Ö¸§Ô;ÅžþºÝ*?Ð):àtˆCV,!=õBšÖ|)ˆüÞ tŒý}NâOUDA®É<ºÀ—äÉAä:€îéàµ:™Éjcè˜s^áúˆ'®~n'4닱÷-ˆ µ³á2ÏÄ(Bd ]Üio4Ð ¡çó—E¼‘«HÇ: 0þLJóB´Lâ&ÆÔJnó¼I lóÂU­8"Á%'Å[‰D ¿@hîêö*ä<CgæºÀuÑßGŽ™¦ó5i9–“ÅSº÷¿¶á¼_SÞ†Yï‘Q°Ñ²˜–gùz÷À õâQPÞ-à_Æ7îÌ0Ô‡Ì×þb†B?A3‚L‰Kßu­×Ãzxà`µé:ã$äŽ"Y=ðݸfJ9¿ƒí”·Šú‹¶‡~˜YW4™ÝKÓ²ïcSC8*Sß¹ ®srx“Ñl yÚLXëàZTW¦ŸŠÌøÕâ,]—UHóÁs„&3Dž‹i©ŒSþŽ‹—Sï@“Uº¢z@4_gW8dÔE¸ÆÚ­¤|R•ÊÔñ°UËŽ¥—1IÅ‚£¼u¦ÿÎCb½ Õ}-;eŒhŠÞ²^Ü…4‡×óŸCi3¦Vî³,÷hzº|s‡Ó¯‘Âú¹·‘ù (ä ¤BK€=1ÉÚÒgÛšf¢ôŽÐ$¤€é¤ýK›Iød ×8ÖÆ‹nH6¶W™ ö× ë#glI¡ØŽ¿ÚEŸpMõP»”…3'çðnï´4IxPÈG-Û¡n>/KŠoÓ˜{ÂÀôÿ¦”ÚKSëlT(Kúò9Y(…ÙAÎå®®vÎÐ YþIØ¿ºÚPcÅ+±ÆáW:÷|„Ís ñÿËp[»v溂-…˜á{‚,ä[Ç•á!“_®|?˜õœÍ®±%œ{8‘»(pp5`ïîù“}é–ª²®'àÄÐû/׿«ú…®-#Ž‚o~Ã_ì`)¦nq •Wi?ø ª²îb'oLvËÑãi‚Ù[m† ’œS¤â4áãñÎÌñ^‘Å#пlˆ%H€¹O â§™bƒú#'ˆ¼7ÿA¤G³…Á–_B⻯# ²I1qšÄÔ5ë€fŒ(jŽšá.yÔ*b¾à{Ñ‘r‹L"vPØÃò^ÍÒ°Þ@šÖ€}ng*Ñ•®Iù¥RÁ¨<ü ÈÛ Î*SPbÊ´»Šþˆƒèj–é0bUü]»8Ë7èoðð»¸z?„¶¤ ðéŒBž2 冨xÄoN‰|’Ff(ÄŽû5ºü_­Õ˜q8.’N­?öp*©Rÿ„ô* —¶ûÇ«[£ŒË§››£‚½k‰µZ s`Cb€íÜæw”~ƒðMW›k_ÜŒ8åŒÇ¾³Jõ‚é«Â¸Îì¥M*¤+r à´Rb.Þ€ÖܬsÅ·˜ 7İ’Uˆ‚$-j6.‰&u‡ç1¼>:lÖlÚkuj‡F8QFÖLæx ®úÆŠ­ú[MzÐ ªÖ îÇåÛY"D?h7¨äþÈ\1 î© ¦§Sözžë&Mmø²éžÖ¹ÈÖ,käCk`äáPÙ`£gŠoß\³Ï%™|&n*Û$ü™K/@º ^ÍXŽÜk— ÷Çê#ç•Ïc¤`7T¿y¥»ðêÒ±¯U=èÕÃØdx¬!}FgûPq%G<¹'š_G1ÊL A7ßžÏ#|©öCíŸê<‰¡MÅÃN0ˆÀbÕ]KCcmj¥n8aXŽ‹ž¦Ù"#–Ô}mó>WcÈÎhQÜ=o¼0ÙWƒ"œöDÀÒ½ä%ÚZê7m¸Ùø‘"Ï$üÙæ6ò9&‹ý·uÜéjÒ°™fC%ÿ©‚@¬íó0‚¬¨Ÿ„ }\?QÁFç9K,€ìC&ÃÛÊ”Žôr&U^$@’ÛémžÕXÀišÎïÞ9èv‹ƒXå_ßU?*ÌF•—t½fõáþõ_`4½á/Ðå( !Mèîô!K„t÷Ñ¢/ZÝ¢Ðs÷:8^ÃÀÑ? W0Ó ”ωµÒA4Ó¹š4•[°íßµÆáö¬„ŽÕo†‚;¿å77Õ¨›ƒúBè¢ÒõgâGÞàá·¥RÍ…²ÿg)¾Cv›Õ"HF'bâHxÁ˜žf¸Ü1œf„šöÆ8„ t‘¹ù™”¾ƒâz äz ”{ïŠ. ú“ö<îæ0]‹Rtöò>>`ÈŸW*@)Æ+ÃÝœÐá[9bÆ^ .ýÃé³7W2ÒÒOØïz&Ç—êܳgæ#úp-­5Í °z­~Ö‡_¼‰ëmþ¸Á9áGoöÓ3Ÿÿ÷ÿĵÈððŒÇ*Å!ŽÜzÀ·æFÞ¡¬WÖ¼K÷·µ{òJ·òÖJ=LpF¬á`æö8dÏI°;R—SÁ2Ƴé´C)Ï™TÐ,vÉêw—ðÍMy ’I{,‚ntÅÙå¦ E’ʰIafíüpܱ³wéD8W§­>g]Cð׉ .ãç Ñ•iœòŠHi4§ Õ!Ḝ) ÜÄFv¦à^tŸ¦X„÷ %AŠNîü¿¨©R‘Üú5£ì‚††š!¡JÍþŸ BåäW–÷Œ8 «:šº·"Ù¤²3+Ê>ˆþ¾ápŠgwôJÁœ–ÿä[‰u ¬3‚ïÎùÅñ@ß¹£·5§yäÜô³à–çëìÙóÃï_à‘„îñIpg‚úþ-´è>þÙ ”®š#Ìnª'AmMœ¿9,B¶xÛèÐ{¤mpÀ Ì i_•e£X€f“µ±‰’}ëôä$eGù–˵¤=×úTjñcü×Ý!±žb ²Ö-‰P(Æëh³|½‰§)—Œ‘Ïv‘žû)‘aR/NElHɖ|§Ó=.JÊWÓ+š_îœõÁµ‡Ñú¢ â€9©;o¹ÏÆ®1>‰eêá÷ù• ´ÙT‰92~ûܨãÕ˜Fe›0ª!>Àk ¦ÐÏŠËþ3Û¦·:lÒ½7èØtà!ή›41sƒ$nS(yƒ¿¹y©‚|TbC·M<¥š9¿êÏK·1{]Üb´ ºf™ÑDñ ÌÙÍùnEõ³±må›8vèÛ£ÜùÄ ²3l´týFm6(^®¾ô^Y#BTÅÖ¬CÐBJ_ÅÛ˜JO®ê€Ua=8P(^3¾*/DÂ'x/h·Ä¤‚ÄË­Q§e‡ôd9Y¶;Àá;¦0>õ4º\ü{ëÅx0hŽPD=!¹Hjž›»~I©]ÌÃ[A:‰_j-x1ï¿kGq¨®ÿøÙ£#à-4HN1A“þ#êÃg`ˆ¸æ˜-PHâ¯Éý8ù*ÛéBZgâÔfMŸ{$¨˜’Þh ¡ÈÎYlUÆbÚã!‡óë0(!‘:Ú©bpÄd’ca£%çhŠ.¦%×^˜N)Éi˜Ãç²0<âJÁ¸ùI^mèÐ «û‹¯£Á*°„~iÉíÎ@³Ðá½=%DÆ#÷P ËĽ_äÉßS¦³›‹«FO=¹Ëf™Î"[Oæ‡EáWNÂÊÍ‚VJ‘ÀŒ§Üé«þ)§°û#$…¡çú¶æje9‘S4›Å¯Uዳ…Wðɾ3‰íysž¸5Œ~B2\w‰›/Qõ‘hŸu"P)ÒÏÃÁй&˜%<„æC•W~ |Bõm“ÝWd2ˆôç:[yù/¡4ì†GÄxgû®[óÈåkή–¤_õqq4ÛXTobèÃȇ¨Qc$.~=+GiÀ]ŸšNP0!ø:—'¯JmA—¸cÞèì%ŠiÆ¢ãßÅ€™«ÃëÄbi ˆÚ¹AÎ%>ÝÍØÌ@ÕJÜÿ=VÌÍ婺±ÙLÏü½ÕÕ3þaªÒcÑ+QEÛ| Ý;¦'w]ù÷A’ícû?¬FM÷;´ïÂäµÌ?_ëIÒŸAI.ÿAº•Ð4»šAlmUŶL:´é½=ä2Ž}² C-}èÇ– ½T±æŸœ¨ÖÖ«*Ý"”¡LAYx]ªæÛ"@k¨ í»EŽ&+Ôß©¼’„PÛ~F¬}ßÏ›™oŒ]´^7‚½º†¾'ë‘·®Å,˜3wÝÔ ŸáƒR·É»J¸àrWpoI3 Þ()"dëÈ&qM°%oûQŽÌbA^5öœj1˜aUe~kª:é^1í6ú;;së]Ò[Ÿ­×@J¶Ïè ° @Xt ]t|oÏÏlò¨Äãy_œÛ•þÇ:R…R÷"ˆÚÌ‚ìcJ¶L¶y‰cD¯àÖ UÄuÞ}D€Âaç®” '¼ <‹6¹ÄGviF”¼ÿËÑ(ݳ¿Àd}©IÚevÇ8e¨:X×¶® ùñDúi]é6êK<Ãf¾Rw3졬¸c’ EÉæ¤,¤¼Rõu5é„Tx“ÁçÏŸ³¥*ådé6Žå ŠÁæBt0vÐᯀ‚Jƒ?I­AÂm§ ¾Î5]ñá%8)Ûä¤.oso±1šÊçH¦Œ"̾mˆø$Q¢Bž¼]µ—GÂÏKâay˸äâ5 GWÕ Jì·ö§Má2¯<—,‚+l«tôc·AÍýf‘”üÌv/+Cð{Ø’ÞzŠÝÌ{Ö«vZh, ›&ünÀÚÃ]öe™¦)­v軲ž^ýª%ÜËÈ_ ïQÊu:ÉbàBÅÌ(6‹gÈJ-næÃ;8ã•"rÍö)1É•]‡æ.óøÒN&¬2ÿ—´›Ù~ÿ“¬½—¿[ˆ43L&ÃÀ±|rÝ6¢ít¶Ûá&œÙ€K*¹ºêµûKhŽŸ)ÂC]êsLœäÝ)ù†hÒ­æ³8&ú”ÕáE}~‚Ÿà o=rªbš<º×HjÔƒ‘)hOq4¤^·®áá”8 Ç÷¥íýܨíñ~»ÒËÁwrXÃga¸²óŸƒxl=±¨‹\°çjsØ/ÞKÓ¸Ú5kíåÖêcÔÉo*Nbfµž¤˜m\qw¥(È…òX|²ëxt±:ªëQLñLXš<´È¹€ˆOÀV΄˜I˜hO2 "hÎ5¦|4¦nä‰áû,±‘±>ñéïIþ:1âSñ"dcÄŒPR£Ò$÷ÏpÑ•·Ü7h¦¥¾C¾¨Y›ù^Ø–œmôÍ Õ”xƒ„ ôB˜=¿ML8>7W1ÍãÃ7h7PˆŽ¢ú¦*4<û?,áƒl}—óËâžÆ*—ë¢t’å= tn§Ù8™º¡xU¥•¿–¼è{äd²¿cû¬i,¢yÏz%.iφ' ú¶Ý¹$®ˆÁRFt¦ïœ<`/àÐ&l4Rñ¡Î (€°„žN+!Ó4°”±ŠQ¶Å…%àÁ©,»#$Ú/ÝDx !£ÀÏû>ÆSª'¼JÌÝå_0ÕÑEáXþP‹\èÅ£OÞNáre‡ÕZ0Zl±lêÇpw®>’u»-;À•³í5˜šG8¯©/¶ -ü^¢·ðŠ»PŸHšu„|ÀsIÍ!Ì zcSky6Ï›ßX3ªQNU!â‘ÖÛ³ý}MøMHQWT—¢ŠinÈ"Ï1jÔǤÂa¤ü:^^@´‘>aLbX® Ó~y­|C\TúLP’9®Ëƹ%ïà£b˜a¬N*ÕûEI©EÒŽ@JH6dÝáµØÍêu( ]9†T^õ<2ïûB™fï}f¿6ÌÂ8ì´¤þ&¤Ì)n  (±Ù€íÆÎ]“œò-£}¼°·MÊõvEvï¹#dPÕ| ©$¹i£¢—½¸–V•,I5‘5ÂZQŽÕ„úÓ£âƒ:]è™>§åã« ÀÎ3q5ÿƒEaP#1¡žÙ—‚sCËÃÒʼ‡"Ð)­Ûg(Û¨V¬Z$@ÿña’†‚l±ƒ›NSŒó¦käSoˆE&iê>24)ÐN·]nNé•ôÀ Û"Z®©6@œƒ3ïjEÚ*§HÌŽòWsµ‚Y í…‘üj”L¤™^½j5e/:Úù¸‡ò ÒºcL ¦Û¶òfU‹°=ìõ-W\|ŸU4'þŸôs/X+MVm3™(Pp)áoŠß²ÑÎiB¢›ÞÜ€Rÿ…E†:«PÓØ~OŽ¡œÐ0C¿8ieJƒáMÙ{iûÈLçm’ŸlÖç3u—…« P‡Uº½xs&î„iÚÂCnX-Ìãm˜¶!hÊaùJL·+wÀù4ãý²ô=5+pç 4üO0Å”ÃÁDD¢ýb(q2&ë&̦G/£’T¢ÿ}óA È¥¶)u)àP·®¤wçX#¢8Çëï¢&¤Ùi4ÚR“ø]äá$)H#'GüXMRì{Òj†V¼Tb „_³ºÆ®ñÕ¬ïˆCKìúbuá [0 U›TíÂÇ]`°IIÝ4……ö ë™ûWóì/.èM?™jÞ­¾i-Ýw¢`ÕmÔúÍHøBSUØÚÓ>Npàò/Ô o”H=gçu[hÁÄ)[m·a4lŒáš™ü‡­A·Þêv9 j;[ +‹©à»ŸU,ŸœG¢‰7nòçÉ*µf­vhŠÆÿ²Z aÒp ·í'£ ‚õÒÔBÐÚVÏ?f&Ý„`[ôŠõ0O¾¹ŠæmB$_O4/@3};1w¯¸Nà €uOØ€»9É"-WÿƒPÏóæ>$n°)›5Åä ræðT¢ÈöäNE:õ5ïXX8U½5ÒUÞÖšÖs#‡¼:G mïgx–)äÅÚŠÖãJjRÄ/Äñqƒœ–Šñ_.oÝyܾÁLƒÓÝØ¡²Ô_ü’ÎÅê’ÒÔ-0ǩaOíVkËWW[‡ho~/­xÜAä\›!—q›{Sú4Fê"§¾4r䯈~JsP&°üÛ—Þœ –v›qAk|íèDf²šWR²/¶Àv¼öÑGd¨Ï· ªñ j4æÑrDØTG<“hÍÈ.JQl­±î ñ÷ö01dŒÇW¿”ä ÅWÉ'ªæ ÑĸÑ*Kñ@Ž[ëÖê2§Ñ#{BÂ"·èMÒ°ÜM0m53ñ—ãd\5 #$ÔØë¿MˆVŸôh[ïá¬mEŸßaÎÞKg_›1§I[#ÀLuž¾¸ÀeóyY×Äî=(œÍàÖ(ÔÐòtÖÂÙ]vö°] Ï¿ïÛ"û˜Ê\•/h±K¬ÙJ¡-»£jð±åVp·AßJFJbGö+ZF%SÜ`$ý¾.‰†Ý×1@ÍÜ-„5 šÁ¯Æ›tsïHZë,ìaí.J²Y‰W@GäÖB X{ºëÀ·º/ÎÙœkò½>D­ü‚27½£ÿË:TO}Ö©õÈõ[®¼e'ßøçr/EÄšms6§Á‡ÊàfÌÊq O>3QõNŸ~¸³Ï@èŽÜÇßPIRPdÜô½ £È„Ù²k ýÂzï9çLØPu¦»1÷ãÜüzQЩ¦5TÏß6æ /†wäPO'*üp5—•„DËxÏÒ”&0£{éîÅ¥J ªü'ÜbÀßúmtª°àdÒB hÑø09¦Æ6­I]&>XØ@W¾òü”ýxOÕ¹ð›Ü¶s‰à 2e¼I@¸êLqº R$¦Kn)qq–ñ6¥ŒÕ0p ÝoHÚÉ/Ñ…Áòp¤2sûÁŒì9ÇCnƒgÈ›ø6² Î’ÒÓ¢‡EÄâç5×i<ù‘·(¥I„eï, Î~® £“ÖSáqx4‘G3ÁÊL–vØÀB4™MØä’q âÝ{ëA6»–ºSB“ ÈDqp—­¸*Ék!?4–Œ[mÛ+"N7C†w=`/¼{ @¸‰—¾€PZɧ¤‰D dqT— ù„ûóGì ½“·"œ¨nÙoNüQ^3mÐãaž?×zSú¥qQGüÜò¡A7>Öøô8ýR) ~†Ëö öHžR°`aÇÀÀwï¾Ê¿ªe§Î- Á⻩ŽÊ¸#§›iœ#ó@ŽëÑ’ÈÞî¾ÌÜÂŽä%¶“£Ó(x!Ì—F¦·X9и—%‡ª–g±[óP‚º·Ûïja+9‘7S ék+—ÂÏ♂HÆ"¬i9Ý Ì@ÞPZE!ÝÞeõQÎ9`ì0!qØÉY]ú½R^KûõdHn½,/pð¡[á0þ¸Çx_¥ŒWñi[» O‡Üͨ?9”êÓm° ±Eˆ9‹­—š»îÄ›y‹“¤N=5'ôp•`EÅkü8Ÿ3·1 ¡càVh^Ó ?&yƒ2Oå–«-¨Ø°´? A- Óx/5,³„D)kö¶œÒÑå1%ôoZÞ?j:«’½Áªe¢Zס26Kª—•#ð¥Õ‹€Íkí$ùŠš¤#âÚúàÀñ«½Ï’›BÅ"‚ ¾Û$Êý/Í•rï—ê{còBýIÜL[kÓ_ñ¾­‚/¼‰þÚVk²Jˆ ²z{'uqgB‰eÑûÚ|‚oåâ} ô¾BÆŽ'ÀÛÛ§}?V=ŽÂ™wœÙ0<¡¡Ø±åE·t,Þša2S†§zxê‘€‡·áÛU*ºò0Suª2¥À|¥äâV©Þè“÷˜þ•?­Î¼Ðý»±Ùa„RQ o£ ¾ÝaÏ]¢šd4xÕž—’Œ?=cà²Ù-c>Â;¨§›‘wGhâºä¤&——ЧBw‘™Õoôqýb˜´6ñ‰|® É×TI¼È&ÛÙˆ¾Ù¶S9´ŸBŽ8ñA…:…šc*44æpXˆoo`ã}^Ú”sZßý`a-}@ßE3^¤ÉÖ1á0úÙò›ÈA59i€,ç>ODãÉvÖÁˆ ®™*<³˜më„áÿùŽg[Aé»F“ÎpJÖ_å#‹9¶á¼$ÎQ\Úç$µ¼€£Ân`Â#fZ2™µÏIÊS»èÙª¼W@Îd¹½!@^XùtôÞ·öœì‡/Ï:î¡lãÌjt¯ºš£úFØý4/Óð'zl(ìáyG°jÈlŸË¤`«÷îÈŒ•u¤‘ }Úúã®'×OOµú®%ÕuŽ W²ëïj3\±ÇÅGø«+ÒKüH;s¢ã•ÓJÀ[]x—x]æºðNÌ¿'GfT—¯,FünÕ¬Lªuñ8Z­7H5Ó¼Q8·„S0ô'ûÎæ€`ÖY‘$õ|*ªŒ¢mŠá?€—ròù’¹Ã-·u ˆ(ùBZE4;4£uœ+ôÅÂíüÂ'?9Sý°VÜ ¹èÍc/kjµH(~uŽ+mAñjs9`Äa7_Làß<™3Y³ï#n ®¾õgƒæõÕòûŒœ ‡™¸ŠBöc­~ÙàO}lBV1eFeV“ñ‹A²÷c)øØ"/´}=ÀDŽN”¸fYçù†5æ^WŒÍÿTÀÏän­ãž(Õ#¥§àFóE'€ ¥ [sú¼û ^õ®{Ä1ææÒóq¿WæS1a |þת(‰f!ýÎ{kMw„¨[vœz£ 5CÞA¨ÒPŠÆçïÏœ¸+WÀ4{r†u€ …ú>QË’9µeäÑR‚Á£ùY[Zÿ4`'‚¢°×£¡éĄʱáÊHç%¹B¥ÌÉÞÃT@ÙÍ"z“èU;½ê%¾y¸ÀI]ç-r‹@• ãU “‘=žIª¥V#q"~Öü vÕÀòôƱŸ€QéLif‰ú@?´0øëN[c²ŽÉ6âcÇÅK#Ϻ’F P¯ø‘Š¡õ#»÷Ò»ƒ+9uEÎíÌ+ˆ‹L8Õâ9_³aMéÍCŠa»dd߀Bëý÷Pÿ£~M gÉxE ö"‡š( g\' 1ÒÃ÷çô/ºÆ"V"+2 í*"ÿh~8édÏÎÌ”þuù¢ð"µ ¬ !1ZÀÅi ›u›§Lê~!Ø—€¾•NsÍY&™øÈÒ(:“„Ðh[ ÀšÉ•ÅIzð]%š­ó?Á/ôM:«™Ôâ=ø/1Y0v°<åKS›ª[a¯z)Ïá_ʺ0Œ‰h;A:Ô8.³¹»ŒEê‹un±¹E Ó棌ßs®xÙKÓÙ1ƒdeÆ¢¯Ú evI:TÚï0í=Þ—Õ‰³Õ±N |hWئ¹DÐÃÃ\š-¦F꣨«y%!*_Žâø«FߟDÚ¥ðïî&SÍ,Œ¼šwóîXW$½+¢6òV°Œ}ØS#ÛLÛ©i~¤hõÓNmÜ×yCçéqmÞCm”?íe!`ú.èzãáBú€UŒЉQ`Ø_BèPæ8)O(¢]59 fD5Ô}T+Bð /·ÛÂ_m žp|Ÿ=âlšzIÖ¸Q¾5JСÎ&¹S´ec„[¯Â!ÐV«$@¥˜¯BÅ}UÂ08ÇïQÝšªÐ›Úí3ooQ­*àÞŒÕ*.Iìz3[QPÉ^H×°îᨠìrw§;ë,¬”W&2ž«ä”©˜#÷Ðàx6 ÎÚT›Å–æµ}s“)/:ûoIbг¡QÃã‰al²éf¨–ˆŽ7ŒDèS›y{ôü'|•ÔàÄn“‘ t* ;TƒÅ5ÈÆ°¼®JG¹èÓïпÜHrXNvÜ`“‘I†ÜöèŠ}ž·€GsvtŨ:®•?xx4H÷ðÉn¼67åk¦úýü!»yð6°¿†„F`“¤Q¸–N m‘Å*=ânj°ÍMþñ”6ΟdºÏÁÉmrÿæmð*vt¤Êêš¶÷@¶E-Hž´hyêh=˜¹i}ÿÿ­˜ZÁ,£ˆt‡zû­I€ÂW•"Tr2ìön'“Õ’v‚{¿qÁj×k2ÉÝóBJdÚÎm²ªtóœ*©¯ñ ”Û ÄÆvÞVc…{kMð2´@âl)hååŒOj4$ñ«e$Þl·§Y’Þ¹“-ÀÖÕNå-UÍ0’÷T\îã"”óîràEu^5攸·^ yaŠùÆùt ™ÚS5šeÎ&¤rBÙÛÔ3rÐЭäu¿æžmãÅÿÜ%Ã܋ȞÀ¢¶Ø±ð¹W bñ™}âx“Uê·t \nq‘!5œñÄ;ÎJï¶© ”¹ØF›?]RÒdWàžƒv¤†Ç zmh@WÉuž>ôP𽌤Ù#ÎoÒ‹HÖOûÑü`)º15 r8vû]Õyâôø¦ïˆÇÞ黸>¸ÀáNNZ®»¸Ùñ"1wJQ£¾ÖAMk›IK0¿ õ"f}LŸ»8`•‘ÄrQ&m7\LüxcW ÉK7FÉÁð+]vÂbù2Õ œ¶œhP³@T•rÃÝŠdíϲ[LãŸ*Â0;%ýÌ{Ê3Í&‘^Pð]þ–[uÐ¥?â¨`^ü³`,χÄi_ l<—€Ñ£¤@ÔB‰m‚{Q¹‚IX&¾§¢Ñj¬Õ\©ý¯Ò›´Ì©äÞ|Œ¡v™W¿MÜE¨GE4ìÔ¢² N‚¦yK쨢±ýáÜäo&†§"é×^4íóðN‘ëw´íSc`åëb@oձŨþ,U”ZìOÂ(h|:aÔŠ÷u²(5½= =<±•–ï®O‚æ£4>hCvK¡/ƒø½SOOu^ôå¤úiêÖñÇt)øO¶ÎÜÌ ñ¥ØñŸyú)q.¯²½Gç°éÛ^G˜ ª³©7˜þölõ|¾¸øÅlÅ Ìê~_®:Ñ$æSÆA@øN˜)¹öî%ºc%鞦nbë;~ ýð¾À¨!Ê©æw£ÁwÑ'J^õ"ÿ¤˜Nˆ&H™mRÍB¶•õéÂÞ£ZžW·ïz2Tòë†.•}¸¹ÔÇ*Ñ8?f³EëÀŸéÅŒÍÎVìîŸìÂY.˜‰‰Ôªb$š·aÉI2?R7kO /ÆQ4à)ªØJÒ\ùh8sPI‡uNxÂhêWÛézµ}¢¸ÇS0 „¥©‘QÍÙ-æWªjÒ™éItÄ éÛö‹7" j™ëUÊõ? ÍÉ,®” =HΗ7¤<>q±[,&}s ÖâÔÞó!üס=¬º›ÃWŽü"_,KÙ²Ž¤«D6Ö7”¹c줈¾®M??RØ%Æ ¢éÝê]Ç`t5¥¾TéHàQ¦l”ùŒhbjêà€EÅt†âü#êI޼÷û°WÊÂÍ­þéÔ±2ÉøFï™/2ƒ¸féfÞa²N¶HªåË7ø15)D2åÛSâ¹ø¤½ß»1õÃ0ÉÚõ,Sc×Äögípåm˜m0ñ4ÓAZ¾ë碛Pc ›óJ}Ï>œ¡ã…â% " Ê:£â9»–R´CO\‰åI ,Lˬð´l—e\óqFcðLð°Xóߎý;}§wF>¹û¤Ì˜„IÃÃ7<þëhrƒZDcS±Ý( T«ÿ÷q³7pDÀ‹‚.Y½Œ?>/xu‹; ©×bFHšv)ðC%˜ï,gmÝZ\€›°þÍš ¢@g Æ{=þ5œ±UàË-44êC]Z©3ž‘Û›^v¬qÿ¢ „¹Á>![4 „•Úùªƒ@Ï»¨µô^Xb¬áU"ôÈ.ã}xõ~Ô!MÊDC]+–‹'•ègµL!Ï÷¨ºá¿_ LL'Z¦Çz’)9ÓJUÄO8§ ߘm Ö®ïúÝT+jYI#}&Y)m‹×϶}õãàAZþÄ&‡ØØ‡–°æýíž%=€£ÔÚÛ± Ë[ì‹lÌ >ê=άXƒ®Ð˜‚Åó8üè'nû…¹ ÚŠf×Áù]shuÚƒÝØ5àófg=@¢š'd±3¨® ^?5”¹"´ÝM±‡z8Ç ~-#òTng%¢¼×ÿºÆ´Ù£ƒý° TÀ—…QÞ—q•ê:wÍYš·gŠZIzŒáš;(„ª®¬)K#Ú,u7ùùôñðàKà'c¦kyžÏ(LþÚ^ 4f^5s;Øá ¨Ð-›bRÖM zcTõ«G8×>vã¢M_é™Ä-'f?敳‚ŽgKµdy}lUºäVþ’Eß(œlù’˜‰û§í„G„÷8$ÃX·þGãWÐ:Z9T­2"ŽOºÎº¶mr{vŒ« @8‡ðÿ>?x¾l?b`Cwé.‰22®ˆk.L¿ö”Y<;£Åþfä¿6g¯†ÛA0AE­ænSý¢¢ŸÖ])õ¡B¤‚ ¡ „#׃Gˆ§,Õ•ä+V¬xRH7Å.ÿñâºxêàÂÒh=hGNŠû¿Ê?ñî›]mÝý¾,;ÈûmzŒ:è?#|îêì´ÇròÌh¹Ö?T{Ä!£»8,2^УT ™ì µ5;MíJ$>’GãaƱëêc†‚nr6²FbtH'gÇŸY®@ñpDb ã×™9È‚¸ÿ >ã\a3JëD A…£‰Š¥zR ±70Üÿg[<Þ Fz¡bÞ+Ó¾kÿMW†ônv@÷=Äøå©·ßȬò‹ú¥E©üæM‡sލmdºíà Fùh¹)ļ «£»B¾±Âxš9H#—š<—+«ÅJða_(­Z’ލúç¼Ý é9}êOƒg_a‡ð eܾY xú9%½P—ï)ÕáÍ»ájäþiëPæh³f%CAôlª5ȲØ9|t|¶‹¦mC^Àƒw,"'©^žÉ;|Û Ë‚h>IÐpjfÑÓ¥Ñäñ°ò\õâUl³DÈ•Ýð³¡ïKÅʲ¢?ÚS›{TŸ¦UéÃçk†Zü&l~ˬK`ÂH\mƒŠcÁìþäŽSãÎo¢¤…½zkPµÞq´2[u3·“ç»–“†·n ë›=.×nOµF³Ú„cˆ¦=±¿d=g°—¨ëN;ØL|w~½Ã}ßáköÜÄúneyû=õØÍêáxÌí”ÕW†$ÍßÄï¬óZ¥Ó+ÃøP|æšhç”=\‚z;Ö;ÁŠ¢õµW¬=få1¾ìh~¯šŒ§×)Úd¿µæKÔ€0ôýþ‰JÕlñþn¡OÌŸ»@Þ(¾3Ú|v+aÈô |JÓiO4ßyØ_´y³cê$wDÚ‰ù-#QÏY.í_Ѷ¯èèsÕ6±—¤8ž¸©µüS4üDan݆ÜA§ª£÷óÿ¡†ö0så›ê(»Æá ÎÝÜÑ1 Ö'Aùç/'YWUj35BÑÕ¾u7˜átF¤í½&×ãKœŒßjÝ⣲Àk1ÚL^Xy¾‰ÌuÎìà*Ðuœ,.Ì |ÇÏÊSWç¤?:’,ùQ%wLÕhxâŒgK ùú_´9þ˙л³¿ñ «dÚ]/2 «X¸É®xt1—üF%M¯>¦šÑ[ê†*ׯ%wVeöN¿÷Çxex÷ž&¶àÎàEiOõ(˜¿C¿lP”•„9¹ po´àMûvÖέøL<‚ðh"ýÄØ8¶ª¦ã½ÄúU™m¬ õÄ6LÏ¿† 4»~d)þºδö¬•HpÒµb4Îoðqä ¨ÊÙÚ—9Çõƒ×û$ÄSðzãÀ£Ý¿ÀT(«ç†€ZŽ ¶O¢ê.œ†ÐT‹Ô©)ùè‡ð4šˆh 0Eù¬qi›åŒØ]¡”BQgŸar Ú%¸<cPÐ;ŸcWBóÜæ- q@žjCäDÀ¯Š‰cRr ±€Gp|·[iò{fEx…pιÀüÀ‚› ’j`ßHi(Q}w§ ·€F‚_=OåJyP#é ˆÿsèMÄ# ý%½/îò‹ø­)¯%WˆÝPcs1ÔÜ̲¡KèÒ"Ûꀮ&óú"i[¤!bKö,Ü/¡ˆ‡›|9i6jSÿiQŸ`w›§Êý~;Vµ‰˜Òåd”º‚7G]ò±¯JÞÂoÉXø P 3poµŒ„° L)¼¤¯Ϋào/õ˜ÚR•`Õ Ú’y¿Ðí@ŠÇâMŠ”c'¼@ë—w=cº7ms£ÈEØ`Ám|Y×ûÊïô)ê àÎÐZ¼·–,J|ÏÜE¼˜¯]1hYÚw0¨˜[ªÓwó®HBÚlÓ¶°ò(¼2‘r‚q¿Ö¥ŸN¢G¤)Â{`!ôŒ@2$èȦ½¾WÁØ€¬Áä™ !qk §®%eãîX£Ü‘n æ‰_óÅ*Q/£"j(Ð êI8ؘ|o€zn¥a¢×²½t4Ë&?wÕyè#æÇ ²•Þš‡ÝøûýøOZj‡3T/°¾%*Ø»¾ºCu°‚”ôá&å¤fë]ê‘ïËh¾øo_@¢†\§Ì‰÷|Ižiöâ÷|š³ÁÔ±±lÎÙQ¾TôN%tÀDÖô×?'Ðß³‹OçÌrçθ®a’¿vßm¤ü”•n= ä oÊC¶XqœÕª$bs÷‚eÄ‹ymÖ*-cÄÞÓyLÕ)à¥É:òM“YÐ5’4,‘¥%¼Ž*(ŸFóÓ‘àÕý×UÒBÀ7oS¹•.[ë¯H;wk u½ìPdt&¾ñÌ|ÞDÌÚ‘Då½máíZCÉük›ÀÇ3  :3>=Ÿá¬OÍæØM‹–ž•¾+E¨Ø÷…î¡ ñïÔC¼ŠzL["g‚Û„ &ù?ˆ4påàBP’½ùòø%M§„àØä3â¨î5ïíÙ5gN³,¸³š† vËOýî¼  ‰=ë¸ïå“Îà!w9a8ʱҫßH¬5ßR7âTg^ÍØ ?À/ô3¯S/Öµ2¥ˆDp†±ÑIð/ ± ÊþW[PLÙ» Éìò´ÁÞø)À5–T ŠÇÆî5–K˜›7_!ÐqµÒÌJ«¼ux<|UZc˜9ë/(óhÊ皃„º¡‡0€90â ¤>½²¦Sj=4Ë‚¤z¿ 7³Y=ÉaåòM3*#9¡zZÐtxlI(ØVút¦è6ïÎVk^9pÞÁ -:3ÀÙŽó·H ÷~³àJPXNü<Q/­¡w‡—eµdIvÿ–ênÜV“­‰v e¿±#ùbë‰F ÌþØ´Îàë}²zæ`m“ {ãT¼ò3¦|³žå †5R4¼Ð{ê{Š R½}OqÖÙ—ûž¶—q„ÔbCØjVœŽîúöîŠêÞT„ãmèLöˆ&ÁxŸÈ&àŽ3—!9¶ÓóNa0ûutŒË±#\â›íd# Ï*|´¼:*Sé%êÐjWÐïÔÙˆ!‚PÊQfÅg§5ª6ê†q¿þÑ£à„°R™a‡‹hÊÆ+ß¼@«H´œìÝà¨JêÈù*˜#ЇÆHÑ sb«l—'(”LôïØ ‡€ À¹XÒÀ&ûQÝ'}uó¢ÜÔ˜TQ¶Jj3žcv¶H^¡étú uÍðèáœÝòâ}þ8¢m´bè1S,ÁK ˜ŠÑ²8r?lËî×{&–ìÚ* n£B±.=3a…‡…qÙñy%Ze{Dy¿Â3?7ÕjáÕ;Çñ)>Ïö9îÒࢾQ¨]po ç¨'1îB]2Ÿ%E<¿.“˸¤ï‘+ø©—àõs å»Î¦´Æ'É)‰C"3­Iò_9f. Ý?›$iOãÞÏÄôÿæÚ}6OÍí7:#ßÙ ÇŸê³ã°ãõFtW «…g<™K\·iòzäú §êºØoÝÌò@ éĆE3L|dËGþ+˜a×ÀD²;› 8À8T˜ ·O|GÿhP1ÒnO<Šá‰¥*9¾–HSf½pëø1U&'èÔ̬õt<8b«fçNedWY_X<@Pvfn(IÀcÔ»ÏðFÙœX¡°*m©„«þÿëä¯i𬔢Ãí_BÊÆþ`)S¼2£C÷À˜´áꬻºÈá¼WyN’£¬‰ M­L¿Ñ†w–è>}°ú&ކö'f“Êýiqq£F½Á„žVÌA(ÐØ=‹¥zÐwÑ ó$¡a4Ÿ=-4|G˜†¯­g`ÙQe­þ WàÝ*&Ëk•ææ„¬#|•‚„ ¥þÖ,€ +¢lìõ«“.¡‚ðxÒŒ»éë*ùÌuv=ŽryhW«8í¦¼TÍGŒÙtuyÌnë†Âó¢ Ó—`Kßóm˜Ù ±ÝÑä´Ç$v—ÆÂÔ~ìúéîŸXJýˆ,Î8ý>\l„ë9ü[­>¹Òc­¨¼âb9ÔMÓ$vÃ¥†­/2н$—}­ÏB²rÔã⯻+O(êqµtwa¹'=©Æ›Ãd–°…AC¸Àš2T0 Ð¥óô¬0&ZFwª‹å›Z³¥ÀÜã•1¥T½ék²ÖkžG!?G´ÊÈâxb¸ì6 îô¦¢”.ÀkÐØ•¢œ€fŠiiP-ð%Z)ªW¦y9`¡\딞)2.d**)•ºjfÉîà„î;/"@b©â¿`ùÞ¢ö Ø“G>´Nó`›|+øÚ —+¦ ç$æÊ5ÀX¥í>ZUIBÛ©e³Cªl]eä­h£—2I7ÕIžÕæõH›Y—ÿÁ'¾.óhü9Cäúö„Á¶lz‚6þ¬™ëõåÝMN »²¡˜'8F¾äÐõpŸ2ö ÄZ…Èóà+-ùöã–bòe©0ßJŸ®?3˜]f*ƒ½Œcäù®–tÑ÷µ¼)fV½fšJц€ßvþ‰Ó˜Øçôª9fvò— þ¶@xœtj-B3U4¹<.ÂþûÃÃÖsŒ<Ñ­¸x_Z²W !ôåLJÿ÷m @þ’Á¶ö¦¾e6¥¥ý ?TÝÂŽÒNÑ~—¯ÁLº¡ˆz . ¨ÑbÓÒî™^X{¹{­¨âžló"f¡ w‹$÷ÉÇ\Ö˜õЇ^” µ Ê F¬\“Ý%²«Õ/Xìÿ½JuJ¶š1;ƒ£ÙÊj]°Ãž×ó*ž|oGbG»n‰vÕ´c¥¼rZ§Xà‘'+±IB¾²Z…äýŽ.Tì†Á’#ö£àÙ64JÀ“Õ릘eÌ&X-£¶9¶÷RL8¥wõUÁ¢A6¦ín†~rXš»aÀN¦ET™óBK·uÜfdeÍü¶ b¢Q®•¿šì'{¼½£xš@É2Œ|°¨ß2·òŸ£Lg©¹¡ Á±(Ñ`]—²´Ì&ê³Ù,(6€­a_ébçqôbU”->+¨\Ý·ŸåZ¹y[kû^º‹;F¥“Ï!ÔœÍpÂe¶é=„(½5¥k;,Ð Ç‹‚¡\·n¸Aœç|°xu*’øùgZŽû_ñ:2zèšü3èì‹«¥úrPH¿Lz¢nÇØ)ËŸatP]`1jqÒ8¼ü!înìh­ŒdÍwñ\Øß-ébâ[^êÔ¼=XLpôÑZcæúˆ¯M`ä™0­xµÒ¥d„û³ã¾.¿xõA@X"µdÒx€J«Crµblªpb¾’«KéÿPûÀ1†õ›ÒÒÙÊGgÙ¯Âæ@¶fQ³Â¡‚ÎéÒ—™›pâ«™·ÿ¨eÑfî¼v$Æ4Jº5Îd¹l=rêzB@2cëHžofUtV‚;>p¶?Ci(Ø{Wþð)oCâm|†ª±±ŽŒÉî ¾Ï6X’o¤¥l™(“Ø$ð­õ†ÜÉ SqÕ¹op IŠX‚‡åÏ98ºù‘Î`d£§Œ_ÉÎX}ò±$n¤ˆóÔ®Œ2ˆxê#xVKRQ¼"f/ ­ÆLw%q’W lÿ=0/\¬N©#ä%ðYñ¯’ó ta ÄL"uÂÆ(r¶,GÝPÝj”­ÚÕÅÌ‘°×|iä·àËðÆMÞ1‚&o:<­à°)êÔÇ&vK¥nzJ«¯f˜&$½–°õׯ)Z1Sø|‡¾uSeþÿwV ‡m6 ¬l–ÏÔ™r™7»yÙ÷¢©›a\ˌĨ>è|†ôHZë Ì¥ÈïNçOMèRÞ7œã¥#3Gæ{T»‘(qGæ ‚bì·3N·‹²z¬ÈªmYåCéù²(—iQt ¶ÆêT³0‘w+kêéi¬ì{ «D¸Aòlr .«“d[vìâТ¢Ò>Õ-6˜\cPÑ1ÌLH°^9 Ÿ(JÈ4òS|>éÞ¨§w'þcÕj\+/I ½kËß4Á¶(÷R&ð .4ÆwXÒúÍtžcOâ._ˆOY‰¥ŠÙ…)òŸÇ‘EJô›,`‘($>©==Üór0åc\„愲—Þä§8 vÍÇy×£¯ÏkEÙ¯•yÞMOyª(O6îw~ïØL’¼ùËW)#É®7-ã8j|ßφ rll o…aêH¯û 1{=1p‰aðЄ§‘jácßÒÕžW²~‹¨b2”q“ÁÐŒs—w[Éó=< ïÍ·gRF¯iˆ<Ö"=Ëý¸\¸†•tÍSâ[cñ·îÏËŽDor4úYh¿S§7³dCÏVvŸ‹å •Z>—n¬=åhs@¤,]–“Õe‡Æëœ\"JP—=‡&Û•_a¢Oœ»uÇ r-•½)¥{”#[‰àŸ„‘Û¯^b„TôqÆÜaÓ1ðVM õ‘ãM«(VK?Zj0£Ùk!ª`G^iiP€EùÆýéˆøÒÌퟀ²·ô0QB~Ô‡˜È1ÖÊÊ€ã5¹"$Ó^#z”Ç>0%õ2K‰xu$)ôüÜÃàð}Rì1Wõw·ÑZqí ™¸.KçÆ«sEѽ2·C‚°®¹„uhý[„®v4”$ ª¬ ÝËhIëîš7(—̨ê( ˜›é~Š 5¹Æ|”"\û¼F¼Ê틆Õx{w¤ô™C ƒø>Ù‡ïRÌão‰‰“ËÞßjÃ4t¢ÿ¨6únŸa_ß®þ¾5fh‹¬tÅng‡Õâ0E‰G¹‡ž?›ÔKp³Éya4 òo®”uDñiëlTâ­¾X ­üGpø¸¡ ³6ÀúéÆlði’j0ÛYMKæ\.¿W8Þ–ô¿±7®æ^fTé0 ³vM»•eû IËšŠjØÐùng^t0xCMÏ/î;&2¥s`±öçÓAQ•LxG;\hÍ ’B%P‹Q /LFÇÜ¡Ãð— üîtz³Kæå>DDpªu·ä‡7^ÝéësoýâßdJ)áðû*{㈨ÏjX%‚*ü·´µz!T>Z;¿[¡©PY¶ÐÞÅÅh“ÅÈlÉÁ:úê1VT¾¥xu^…²e›¿ õú? ŒÖí,kòlmeX¦BÞo• ‹ áj#wŸÝ¡JZpˆý|2®•é+ÌC!ÄÀäàºc†$ÿ !Ù‘ö ÃsÅKèÊ£…ÀUúB’·ÂÇ…„\ˆ€èDÔŽRÄñ&1ÏÚªñ.z~fƒœÇtùê,à–û¶r”ÜŠP]Ø+1I.g©ôj¤V"¤ylÌ ù«aùHo!Ðo“xõdp?5©å@€•u¢êf§|à C£ëQÙJ Ê.Úi™üâ IÃB©Ý¯8ÿ+)~rJƒG¸2ƒâš¼mwÑ8â¸x8¿ëó 8̤Ë^°$¼ í8q:{(êÚÙ!ŒK¤^ùâ=s,[:\U¦°Í+J†DC·.w½¹Þ ð¨Îå#ÌOP:ÈFÈö..Nu‚v½ 8¥Ü;>ƒâÚϬí &8 ëã|iëY0e‰gºÏâYûÕ×z¢°Ã;ñÈO0Xp‰&9'…ü{ÄßLü€ÄaØ>½ˆWN¹xãØ´—q¶žËúÅÐúÁìÚªa©”¬3ÃoÅÂ:IÓq_ô‚à_žµÞY!ÿšÙ”ñ´ÝÝãsƒ–>œh„g¨q¿®Ä:Êß×ᩞâù|3N‰º¹YO¿æiÿ覥×Ë#bTpÈËé3' õñ^¸âö¨_9*5‚ }x¨Ïá›­nÖëÜt,ðÅÖŠì˜R»X¡Z#šhk35›’‰ðMöHC:2Òàc¨Ã#*^ÏàBp¢£ …¢N©ž –T2Z]MBí3X­ÈËM‚©^òtjÿ9R•N§¬ÝÑWƒÄ¶ØKs Íîç .ÿ¿·x°zq‚øñŸ”¬ö!3/wæùäk}Ѿ6 Ürñë&j¾À¦&RªJgM‰ŽæÈ°>#kÛBg7Tnî6H…³W±w‘[–lન ‚GŸäÌ[Îôä%šd˜ºDüÏ 7_ΜÂ] 5ô`+Õ_GÖ‹§ ²åõ£¨òR}®Eéqv¼-…do¨ï‘áF‘n‚ÞÌ#Ø:BGúqé B#Yƒð]Ø]#Ã$LÜ@‚£¡K±V­ ¯šYèB¢Ò÷pÙºmpG*‘3*û¡–&(“cH‰åkP’1¼ß<—\¬ lGK)_îúÚ¤;¾c¯}É·¢踇À kGQÝïG<»®ì¤Ê1¾jycp_&¥Çä{»êÚ.€<©ÁÒ=ïILÚâàÙͰéI1cýÜáø?—Ô:íd§}¨-‘Ñm !QÝXê­Ëæ˜hºÆÒI ¯„bEa ãg*D×FË¿5Ò>$9ï¹R{f¥&¤*ð‹ÒÖ,lP³öŽÁefÄÑ,âM!ÏýÑtÌS–ySFЮzI}]4N¯«‰~ .YKÿâ¶,$˜Ç/1ÛweÆ#‡ðžÒ‡§Ô 6É’“žzV\øåZÔ^ÁP‡T1¥‹i>ϼ¡§Ú—î3„ôÒÁå^÷®o¦ÂEØ ýwCXQýi²¢ºu&|¤äß] ô/7¥!€î¾¿`HÄòhU+è\¹òúOÈÓpÜ’Ð)G³_–öfÈ›ôr=? mü.ìí¿MNŸ@ÉÙ„¸w_kÝLŸ€bœfG· 7‡ÜïPKÕ"%/±ðP„1 „-Œða46Š*ÍYŽm5ûrË£>ÊŒ}Èzp«Ñ ËûÉb#Ò[öâ €aÍÐõøXº+Í©}˜í1´£\ –ôû÷ŸYT'©¯Âç89”ußÝepÌi¯7 ·_ÉýQŠB3]6*o!Ñçêà >bƒ{ºlØXcÞanú†Ñ¦«H%¼Q©ý#ÅáÌ:á•‚*zÝCâ°|Ìdó'çÄÊç§RÃÝŽì ²ÏÍRÓô‘ŠóHwªgqÏ Ô©6+†*Å~fV2vÄ+9ðq—}ç8ád*´@ 1R_ðêƒÞr)¿q‘Ó&ñZZäBɆi†r³¹>éÔ"½N<•u‡¶Ï²R€®m+ ÞëÚäcD‰aqÿ”sµ“êa“â|–œ›óó¼>W0…3XtóÄ6Í8VÅ?dYÝZVñØ9ø(;4¿Ó7MÒjÍk.º¦Ô\(8Pw”QºcL~¾ÇìªÐÙƒ™¾Ïë> rQÁ£š€a‘ÔË“°¬Í{fR“¿õÜÑm.¢iW½ç»îI^+H Íÿ®(.æ÷rŽÀ”ÒP0ùÿTÐÒ`©#®©íç;CºáDzä3±"¡œ‹ã^[ ÖGÉ ƒfÎjÌ99ºCŸ²Úh`Ù$0ýòcBNbøí%??“¢ÖQ)È¿¿v öðL^ëÞ×â}ŽÛ‚·y9$ꮪ+vè¡•f¾y42ñÛià^‘ÓØówÓÚfw5vdÌúeh¤8qÃÙZ|Êì3™;ƒ±ah³¢ts-5ñ6ïD¦º Üëî<,ùÁA+Î˾Wµ !¸^mvÝÙp$»töòœÝùÿeIm-‰â ~ùnþs9r¶&çÞ‘ÄF v¨î°Eð‰ÏßÖ}J—3põøéòDN¾kÂ)Á‰úR¾Ì)—ˬäk–·öþ°qcšPL)q(‹cç7Û;»ô³¶ñe,7e u÷÷¹B+@È™.åës‡Ðf-d w’2…š6ìl*rùµEYðåÂønC]w®ðmi,\@€³Ý”¡ ëˆN›ÐßbîŠáÖDž¬\ªƒ·pál/ëÂÁ—B=³YkêÇ%à“+ ¤þr}Pj¥ÝU{„µ€Éúé?ÎX¿áƉ骒ÒwɸœÃõ"+â6ûi’ 0á!N *ÌA\rãDÖø:f²jDŽÏ"!N¢+‘µ¯͆mÂC±Ê¹te’¦¶Š)àm$OÆmÒëÂKûöc5ÀDV ÇE€n«ºÜäÀGõ:'aAMîÇml=xbÚµû«aº7˜\ÔÌ~™”á$ð$¥æ/³·]t´LÕlAÎ-#mí¹ï¨haï¸b­†åJ d‹<|kÏ–V1³`@ oC}sÅ4ñhn:½'½k+y:¿Må’Ýî •x°q„“½=ÏTK»‡³U&¬¿¿òÌ­ ,Â_°öÝÛÓ¹\û7“”‰ Å‚†k .f÷“,©G’pè¹r®³ÑéôÅà~3‰q99ãê²<&âršpe ýH.Så(RÎ$šÃÚ8n‹sóƒ9¿9–-ìÌ¡1ÞtM<7AÝÆÊrI/AoGŽçòR…»:†n(ô/“—ˆ´_.s/ÔŽÜ4Ë:|M÷á\ý1Å:›@ ZLÿðªûß6š‡€ý•‚|¦fÚo£ŒáÃÖÝÚlt¥èêGðãpñášI¡ûÇy"6ƒ)¢#Ч¸ß‡¥šµ:ÝAávØrWA(}Ö‘‡8P“èRÒ 2½WÎd®¯8¿ò*ñ~Ah¸ìÕ›÷µ ™ªþ«fJ^Œ¼ºSh•æÜ?Éê3?ßGä¬3·æ\6“‹KªXùéæ«+¤/°Q}ÐÅE×DïHlaiDzØåâ°Ä]Ò„õ¢“¨r1 js¢ºÝ,ööÕ)(YÿKäíøR k¨ØC”Œ"å°ÙøƒXn–Ä Ë‘8#‘‹þÅö²Ô^ÈÛŒ4¥˜8µ«¡‰Ý•3X©B³™(йC)ï )TõÐûÇ!Ö:ôåOÃÞ@‹ëÏ-ŽÓúBฆ·*ÛuŸœyÐ@ñ‹¥…8}&uÎA ‘1ƒ¯ª©ã¥ó+&à¼*¹øšèlb2#ÎÖª”‰UþT Ê¢Ú÷.xÅòòœÈ#+¯ErÕk\HÖ¡Ã\LxU0Á$ð´}Ükõ"«Ò%eÆâf¶íQ‘XСóýÓA]A6ϘŠà eäÃ<â+ó@ UKûRºà±ëVÜ›+ëÆhޏŒ7òÃJ¸”äÕ?˜†Õp.±h7³j”Ç•{mdÐ v1ω#fS9¬g HŽ”R„drt¤nPôÚLN®Ê+ö§ ì.–Êuâr=êY¨Æ7²2Ô„?5`ìµ÷Aý0aU™Pš­Ì©2äø :Ïõgšüzð· ¸ ùZŽ3aq]™m©õ3od5!*Üšì«ÐR®ó³|·NÆ/Bµ¡œ^ûQ2¦)Ô.´VVÕ:mÔØÝ<Çž2ó¶]²JC~À “RK‡©ÝÈÕŒSB Êy±Ú”}E‹¾D\?CÙ°:ÜXt­çƒh×ê:§ýBþÞ´›—”H)Ö™Äf bGR{[¸~k}5ØBìÔ£N±iÊÔžl àž˜ oø4ÅD1|g[¿Q0F}ÞU‡rÑì\€‚Ž•aûï¥eßHÉD?œÔ1Î ;øºl ®€È01Çͪ;‚¶Ó*-4,GL˜¬A\`¾*ì¿_iÒô¤T3+׬ÆÏ•MeÞ_¥Ã¡ Qï…à¦!KVùÜ,2娴õ¼µóïk(þŒù“½-ŽŒ³ÚVaÖ÷þ_½«Ô‰Cü$jߥ!ª//è¿ Ë0Kp{ž=–ÒG¡b‹×`¨áÃzÔ¯r‰$Mˆ+¿âˆ€8:gñ/­:Žæ¶ ¬p)¿í¡C¦_¸)‰¼½˜JÐ×@ò‘´“0¦\•œûáûy’Ý]×JAC ob/÷KCN±>éȲMx!$ÓÖYMÊCݦE›sîpY’\•ì¼jÕklCˆ¹ %dˆ/.©lPY°Ö>Ešÿ¹OHÃOô$O!{2(¦YY;PƒÆMúj%¬ô†½aÓF¢†c§@CFã. Bé*éÛZL³‰k[J]qµô…Br<,)[½ù8k¹tƒ«ØC’kþEÁW^¸mû– Í{„q·, „sòièââÏœ ‚wP-¼š™¸Êý;A>Š/ʺô˜¾>•òùJ &¥úq~ Ï²®Ew.MWøµkIfWÚhòHDPâò=%”ó®é5ø6…®Ìž6V¶É}Çm‡Å¿qþ}6ÏÄ ¡SÆg2˜¢„UÐWn¤yš2bþr‰–ŽVÅ”àÝ®e8,»z¢t†WUå(åÕVÿµ;áãȩم|zÅBYÌᛎ”#J;GʽћýWtS³ º[2ËlDßõÀ²¡ùœ¦³ðOËl›” kõó×pŒ!]ÒÈ£„.}kEßäN ê)ªe›ó™ÒrÉàæcÅk1â3+ ŸqöÏC™V¨¥ŠùN„ó.FWتËÑãÌÙN9õîɾGÉ2V¼û^Ê'²ÖŠk€Å›¡ñÞÁè"ÉÆâBàå¬q‚RÒ¹¾€”¨^¤¬nkG¸/P¹I&Þ'EB$A‚"zµïbÝÜñ€‚å÷¾qNX–(¶‘GH`7•5Š¨Ïœ.ŒËw/K‘i±¾“ E[¦%–é¥áÉ'M. eß82+–ü².ËrÁ³3À,Ǥj[*?:{¨Ê*iî”L]yºäÐÌ;bYºépVa~ñF¹•Ø“ZPsÉŽx𣖸¸sŒÂ—,|¶úçu…¾=TŸŒ'ž‡û)”Ö@Zl{MCÖWnVBNišÙwº}GÐ`U{^\—fQ³×ù| X0ý‹Vt\MãI,¶yšš ”c9E(!ñ°L+?ú‚r•ÓíÒö9sg3çAË—vÔ÷‘#>Å}ä}Ö¤›Õ=ÆäG¼¢øOú‹G—@‹P‚QÇ”Ûw¹¸þ‰pá9ØM\v ¼¿H…¥ _ŽY'§9”ù>ªè¿œú™*ˆ£ /g°¾ð$½UYþý~9Ÿ.V3uä-â\à>Œ[8ÍÃ-ÉÞ3eP†œ0ã ½jSABÊ!¥Åÿ•ø†VÇÂþ˾zþTêc†£r`¡ÖVi0žô¶Žè1ì¹H¹#ÐÒEɯÌ"†±ê r F„~Ú¥Š{F£H¾Q„»Ð’÷ì{0pœ݈„ÊÁÖÏgÛasžòeËCÙzß»»d^æH*û˜£FÞ¼ÔÜÏœBI“û™ÂÔº.:–qM6~¿ÚéÇ@³æj«LHŸèÌ…^m4Íh>ß}šPθ’•þ‘³Þã…ûĺaÉIØô¡^ ß­I6OËã0‹¢Ëø-5½øoŒt^×^.¯ÁÈukJõÉŒ+|¡ªÜઠ#íÒFÑaV>Q»IæÝÎ0÷™Ð4˜ˆ-Õx¬ë®¡ƒä»* £·-¦ 7LŒê5×ÎN-¦Ý_¢0†ìrUmÂì2Ï^gâ?Ä–Ñ=~Ö¦¦¦ÃoOLß½ôL×.S‘æ†ÆóܨЃ#˜•»EÇãÎnª}V…ã7ÇκÄé—¼K‘ÿÉ‚h•c0L/á2¡²~ñ}$°{”}1ät’séØHÙØtAÚrön&³õÐ#³±`V^›\œ¯ôú7ðϯ¤Å±4¸‡.þ@.AÙö ãpxŒÓu>E·ME¡yKº®8l³«s —w;s„ñÁw$úYœ“j§²’O¾×‚ Ø…7XœZ( ½¥?F‰2S2–[–ìDšûç¡ëÆ'„Q¯4Â’ uæ_–,ž9MáXãÂE?SÞ<ƒfg’JEëÎÐ5À™Øqo&Bâ;‡Ó¹ª¤ÉÜ­áy’ƒ#€”×^§£cݽâmÞ|ßÝbŠv³õŸU»MÐʼ1 ÈÃ÷¡¢©/ÊÛ·Ñ-p}£‹ ãÁ*YQ³iÂt1¬b=iC‘’ÖD_쓸ò…‰Òiµ¾ùÃ&:buàY†_>˜¿K¶‡Ç)s€—žŸ<~Cg11¶$Š’ ‹É=s±8Ñ ¥Oø¬Øîgì³B78@ô¯BZ!Æ ;é5Ô€êû9¿1àewm‚íŽ5oÿtÍ Üï^Asá3„7Ý£l6,Ýø0· ^@´T–S5]Ñ$÷ô¹ƒæùy?²jÞW¸Åó>Ù)9)ôfœø+á­‡u¦“(Á}`!¿B­Èx—|·Pdý˜mñcþ•$ÚÚ‘>I«FèÎ"Îw~-lò‡¤à8¯Þy¥ DjLJ"C˜WKÐQ/&öe-ej¶ä;Þ ¿Î RÎ[Ó•ü¨|0i.™H(1¬Þ?'âϘll(hõÓ¢Ç}\'Ï¡Œ„¾z—írá.3À¦VwZ÷] _\'u£%EHrò-؃"C5rÞ¾j6‰4ôbÄ=7…ëRzÈ]àЫg5¥WÝ|âtr8!«VÄÜÆh67By –¡5’üä3¨&ἑ t01rª€{}F5ðADf ‡æ'”ØBÛØ:y êq oK¬ð{¹ïïsÒ°Ì• ½.·ˆ±?ƒ[7ÃKѲ—- À^Ø+TP¨MäA–rOìȯ$IÌlí›;¸Ð¸ÞÝ#ëêñ5)FË.>¯l—ñ-™Ñ~oľ3±Ô»…Ó6äí¡UÞI‹&ÜXZ-²ªNôÑ(j×éú7Ã:'™nufîRlû­H.”?¾¤¼ˆ|·ÓüéÌ¥zò>0Ðè4è³hÈÓH˜­¿£Õ×Ë߯4±Aj‚r·gâI°Ö”æÑõQÔ ôæ B òKœÈ"«yì `Ý;òùÏ5Ô»3=__Ñg–šôø@<|åh\ØsxB^™€ÀÌŢi¤úîÞ H||ví±¥­zoìÆK8n±Š‰:ùËˈ³ù|Žô8 Ù^÷gé¿L`'ð¶ õ4^AŽ´k躀ÉÔ®'d°fu´ `ËCSòQÛ½¡ê/õ|í¯¹IŠ“ü®iZŸ¨Ú#‚ù(g?h5‚^(;II(ªÏŒåŸ KãÈÓÜüK_ªq»ó _âlü|(¹Â”Yã©wGœ[êpȃ¾qã@ñö‘Ø& È1–Wˆx«Œi£äS`‹"ÜÝÚ(•lá±mˆ{ ÅOýÇZ;¨:7—ˆ Šö:V£‘¾eOƒëTFNZ®iÓ‚,|ëb˜ÄØ+W‘‡¯bK¸4±€\Új«v±çZ¶ Róé4âDÎ2ÐÁºßÓ¼»óõº5$w r £v¬ºsŸÆ!qR©×ˆ‘Ë Ü(DÞ‚tøæå`òù‡v ñW%ûPä–ý°«¿'ÇOGsKÄUt¥—èVSCR'±›:]_˜KO'!)ÓAI¶ ð‰P•‚A$“¤зàÅ÷QbÊ•!^¶²`p3ûZ³éÚ89+0»Õb×°xw™Žrðh¶9aB÷uÚM(ÈNÏw~ëZëš;}6¦a=!j²àt‡s"¯Ët[O;ñ? [;êɰymÝ÷€æÉ C ÊÛöbå®âqàtX„ÿ†Î#ëU]ΫÝßÞwš…¾+mb†¶mÓ{WÈ ¯Ö%ÆH|Áö+Ý?ˉ/ö¼‰€x'%¶VùÁ¢!Êu²øpæB«A䨌_È[/÷ts.te¥F1ûAÝNûÏ„åð `‘bJÂÜ õÚ¢'®ÃÓšIU tte"–•Bx¼ +xI;E4cö ³„[)]¿>‚|8Ð'Zä{Žk( Àö¾ÀqñêøzC%ZÙ.¢À€”x–䥞vt+2¹„çÃZ0ׯ”â±”`¸ÝæÍƘe \Šv'V{±Ýf7ç©?úwVæçâ8Ã4ŸºU¬IÖ:ûÛ?TRÑØ\0é~2ÓñÓ®':‚¨Øà¨kCgå%XÆÛ9=lv F8o‰j„9À–”šP&]òÛ½ÞÈllJl7Iñݾ­M÷îª0¶úÖà*\$]ÞJMRã3'€d[œnBÍ7Þ5±¹r}MšûÆL•"5>1R&[ÅMìTŽ{ûwUo<Û%Èý¯ëÌ}g£G~º(`§ç¾ú’Ã^ì¹Ýc™HŠˆÿÄN'Tüh±MD“?ovM¶ü=zˆÌ’F¥ãž¢fýhÁ^-ã22íd|ªxnïFOc+7±¢3¸ £&0”÷«ro¼ª‡ÈFÇ(\A¸{d Hlž±|(Ú†ï€&=ûSŒu°Ñb2îÁȯ'èþŒ'üÊÚ+‹’„ÁW¶>–õÉ„¦ª¦ÖÑ‹É܇Þ7\êA¸)öüjSéTäŒó¯÷È[šE°1‚¼j³á–‰=&Áx¦U ƒÐ¯ qòü ÐPü¼G_¢È&„Êâ=Jt7¦èÚ~tæ[º¡%6ü*”pöçJ¦Ï9>¹ê Ò+ (ž (€ûAôÉ6V0—P™{ZšgAò: Yæž?"\˜ú~k§=–WQ}~™ kI<\6þP*d˰ØËùŽ&R|fD¿ÏLÏé…´œ,]dSƽÊfÁ'Z ¬€1Êö¯XÛÞnˆ¡Ë.` áÝù™:öQ­óER4ÂsÍ¢ â6˜¬qÞ®òíS¼ÐÇja-†âkÙÉjª]ª_³Mæ¨Xµܲ€3 x!£¼£÷ ¤'â¾iNÜ Ç|éLvJ×,REâ«Bä+¤HfO÷ª£D?Ú¦ÅkïdÃßG K`_ð¯²ã7ÿMÈæå„Š=Ô Í]ò“|ës™£Ps]1B))¼£c«ïô_.vØÉªGFˆ-ø™ž¨N‚î"ŠUZ7Û®¿âࣩr¹ÿû[>úkÿ³PBœ”$•!Ùb•ñUs¤­q^lpy{Ò½¿t©§S[²J;Wê3NIž?¨qd›APÛ§špx ²ü’z„Žwuío_‚šKc¤ð…ú¿Ô¯^«(­¥ÁWúࢵXæcbnãÜhwh—@±ZÚÙcÂfy,Ҟ¹f«-ùÞŸKáKCµY.Í\ëLGÞ†‡é·TAìñ¹ g‚pTR§ûzˆzÿ.w0®ogÅßx순DÕ8e>æíLÕú¢Ï…Èš1ƒZá\³wóöFXF·Ô6 m·k8ˆ Olºî—Ò+«ÌŽØìƒ\¾ña¦2~ôs»ˆyQ $KÿQ`D‡·Ú=žKÍsv3 “ùñUÅÀ y0^ !©\ˆöÕ¿.¡×mÙ£ie’Ö“ÕÄá}ÖÍóǹÔ<™7íU;Pqjk–hjÑûÙ‚–Aîé²wªS½i¦U Ár7ž«M¡é}^Р<€èþTžg«[)éÒAW³MVJµ÷jNÎj0·;áS°ZBgÙóB˜h?.P“ÜO6ÛS\·èÆðØ^`J6ýâëêÈ;én¸gfÙºþ™¹üÚFTtþEØÃeüaÎ=¨ øX :¤Ü`èþ‹é5!±´§ÈǼäûžâÛ]/g,ˆoãíÜp ³Ä}Ö÷‚¾ùòa´«1ÌÙ9®ÉwËàýfæ™ ó&[eð*6Æ»¨p®á¡]XmxzBd3læ…0o(ÅÙ¢„~Í/¶šr•§U#Ÿ‘YEœÐi›‡ÙÒ• HË¢CÅL¬ »ÏöD•:LÉp̓,.ˆnÒ+Uz2™xú,©Ç+µË·¦ÁÏÃ_¯ÜEgu«ÆÇuÄfRŒ¢ƒ|$+jÎÝxÿú£š”ؤ’#¸af,rÜý‹¹ P‘ÉP×™/»Ø4?æi³õÆ~n>°C¤C{¬ êúÉjœA(@2Áœ)Íw=ú@»èXw~k6*õÅVÄßNvR‘ïÃðyj1&oŸ{-+Ú÷ˆZÍÄŸ-÷ñ¼%âú(X'Ö/¾‹òYü›F U‹ÄH.z0+žì¢ÊäAç.Ù_ÃÝ«éÁ4Ì¿ª†˜¿¢=«>ßÇ`Öw¼s“ÏÖ¡Å» 2¯/ÿ{Ìäs}à‡áDÇ “À(úá7ÁÂÃÿQ+ðs¡m]ÅEqÿS{ã[6µ!¼Ðµp¯wF–»e£ˆL…uBó‚lÅîlS*Ãd«  I)%U ·MƒŽ˜çÁï8)7Ú¢?34ÿ ËÞ°Áñän#LÒo0Ÿuµ"`¥)&µP_¦¢£À¯³V…7Úrúß `«¹ ª¥BnGŠPîæ5r2– yJDGTjãWkø)^0†‰$i!éƒØÄk`.³¥TezŸeÎõ¢¨ 2îÛmÁV •ÿ†Î\u,´œ æT´aÄѼHeœKuϬêV’¤`,9’a À£—³-Kã¹Ézhöyæúq\T“Yè½µ9G±ø§c+‰ÿôÑ 1ãú”ìEÖ’cz*}0yñè”Ý\¢ŠIuEµâí/& ì“Sï€$ƒqûexDƒ ¼IÒN’w«›=&òšKí¢Å¾ †`ÜÓåçèq³Ôc\™a½°èZnAA§«R}kêè'–ÚF"ãüÑÓtØ>Q Wœër¥œ+õÙ(;g„Úôòlš$¶RA€—Ô!ùfc5þw&mI¾>gö»Qk…… ,ÕƒÚ¾eHÔs€˜ØŠn÷ âfnDË¥9dãysaaUK]ç»3*ê"VcL**}`^ ýýNÀé>Íù]´ƒïuŠ´W^F¨;Ûˆ‹¨„®¢¶–ù“1ÜZÂÕa´Ð=kÏ€³ÓÐc!ö³­‡j‰à“4/‘ë°[”ú ~%ä}µõ™²6òÛí0Ÿ÷5k³Vø¼ÅörŸè6šEÖœJ[u§‰ÂhËW¦`ÓC5ÎÓÕ*m¢Pl¨þ j|ý 9÷aYòN†ÓG×e=‡h2fˆOjë–Ó«¸*”&Ì¿7úí%ކØRÖhc~XT~øÐófþ\’>Ù$öCýÌ¥@¹×#ÛBž‹c*;¯“Ô G·¢µPæzèÑ£R–êO‰]=œü}¬x†SF2âeƾ•G« CjMmˆ8¿æßðÉîkÉ6ªv™w×s k¯W3¿ARb'×}N_‚ßÖ #C0È(©¿0”z3x‚'Æ8¿›€"óz:ÜN'á\H¢2ý0.§Od=šõ–è•[ƒûljôju:ºG/µ½ÛZLìw†‘u6mºg èv¦¤æ5RtКú™Æû¸ß p ©ƒfX4'Z!ê¦È4sy‹Q¢0£éÕåÿóZ³Zë£)…*= †½€î© Òƒ}‡‡fäÍ·ñŸxÓŠ/?RRà K¨9 ?3f‰èfd€†A¼1§u/ ‡X[N‡Cx,C1æ(C§Äf†¯+Iü€qÕö ~±U£„eÝa:E€2æ®®Öta D&¤¦¬G¶_ø€ž\wâ›z‡xÙäì÷Z \[7Ð9¸tÊóA#Åë-[ã„*Û>ÅÌÇ·=~1¢îì„5Ë—G3ë4î ŸêªUPí«î îÕØiêTñ5¢*æNr4}GpðCËú˜e}ºW—‹.2ä‹öÍ73øÇã&VíI¥Ò˜K’è©«ÙîÂ~)DuJaªT\¦Ò?ÙŽƒwàÇKhSÛØM[[iU §¶ø×ÄÊ«©ô]cÛ„Y÷™ÖB46fê7 7†%Ü M°~Ó¯CÂï£Ë¡0§{%@s¯ù”A7Öù¥W#A¬ý–l[®C$ç"›1~ðz}7 ëD(IfÛ'ƒu‹¿"#€B–Ë7yÏIж£# JVè{ÈÑï/]älƒípئŽ_þûï=2sZV;ßÕdmP‘þë¨qBìd±° ’Ør©~ãŽã1iùʫĕóþ…—~ NICRK-ÔäL]`eƒÝ­¹“M¨á·«Ø@fJ ”‡Þà:_ «ƒ`¡ò!Ôù+À¹+džT¾Y,½ØÆtÁZO¤R…”•»(Z¾x6øÌggÐ_´7 ‹Jæ‡ýTOoÌz70ÚúÚwü“Ê68?á±’QM;€¥I¶âÿüYeïé€Í‹u‰ý¿\:n@ÑLâ\(‰76~õýüµà"³©®÷Y¿o•Õ=m5V%ÑzG8™w‰ÿй¦ Yx$¢ ÒF@£ÄÐ ÎŒáGdKGè}w¤¢wx|MÎYOŠï°Iœ1ølØÓtÅHÛá O )|Ã÷†¸vkG\‚œLNg¹%—ߟ›ÿD¾&@VZ4ŠØ}¥,¾ê·Š%7™:jÌäÂùAÈŒ öU}Gs¥!Sî¿j”IƸ\…ÂþH¶ãê†÷À¤–ã9¸ãÍïJU;þ’ßèÛawòÖ`ÔîyàËtpý†g_©[”äÌê\Óþ8áÁÙ''L(“ç½ÎÞ9ò„‰Léh„Í[~ùFµÇ‡1Äûû*>NSŠE¢ á35 ¦H vCîÒçþ ©,@Ž cÍ!ÓŲ¥‡¤yh@ú²xËQ} J¶BYYÞRH»L\#…oEI¯÷ÙÆãm‰C.1V|PÓ5„ÑÙm(žVâ_C¦”jW¾’v&KÈþÙÏÔYoôˆV3sé_F%–‡4ÎFW„RíðŸ FÙØH5=zÆ!8ô¢l'cqTôãp¨Ó3ñP¦7—g<%ü$×G¡§Øô®ä§] æmJŸþ,QwWWÁ¡Ø‘±ïÞëˆN—Ðam~›;R5ÿo3Ÿ /KQõC¾Bʘï”a”V´ü´*±YlÖ¯À™&¯ŒR'¯£‹gmœKîpG«ìšo­¢|:ä¹:óRuwf}õÔÂkÕµˆÄi'¯~¡1‹a•u8S̘ޢQ+]úãL(…­Þ‹7åŽõ½¸^%´ýJósËì‰ù§}ëë@=¢iÅ’«ž@ú¢:_¹ïrˆ#K¥i³ÒWcü4C …1á;€J_OEj«×½±Z¶Ä†8ÞÞ†>BcüvÀ8¤RP^Ùt¹&ð]¼rIhÕýò•ÖªŽ;àÜ»Nó‹ô»ÀxX&Q㟮Ү ^ì ¡ï¢1“ñÕ†ƒCéÂ.t.Û¥þCÌhÿÿ³*µÿÙDxefA$-#åO®]¿ÿHäªaæSQ#íw-¸˜²‡ËfAÿWË ‰\ܶGª9ÒäòL@œÔ‹ÞªvÕç‘ôÙ“Yˆ+Ë/ÁAé™$Ã{Ü*„—È WÊ]»‘«f”·ÌY°¥/Êg¦ÈD•.ÒÁ„¨'¬WèÇÿ¥¦¢ó94_-X‡×µÜ†AÌj¬›ö» ~¨ùýBpj‚WÇÅéÀuÍ»vp³0%aU›tÞU]¢ã>rœŽí^ÇUY2#“8 AkøéçaeÈ,(=—õ­j¤Ù;ìS!BÙLsd:nk––`žê•*¥÷×ϨjÇŒ ¶v'Ë…ö<û’gC”A+ï P¬çeE$Ñï{.X5[{Åu|ÁNßLö‘O}¥f‡ŠvÊ^ößà³ °¨6íP¹µØó•|€&b*ŽìØRD»z@ÝäÓcôÎ1ÂhÒ$³}©Gf´Q]fyànÅÁå³6û†¨å¬4F9”Ì~˜~in@Õ~‹À½mïÕìÌÿQ®„›ÑYÁË£rûßuˆÛýq“?‘y–Á¶,bÆÿ(-\ŸÛó«ø…||å`Àu±¨a'°”‹aZ±V¶+LpýDÆ Ž|[ÝÜûƒ8¶aGÝ]ÄÝh†f¸ ²’A¿kÛ Ž€ s*4B¥x¯Ý•üsqÛbʨö3µ/Ø€vŸì”fœzYÝÔmÖŽ>c®ìàƒ¼ŒËL×9d±Ûü“ë©TIQu‰f u‘¤WFk°>“8Í-õ%9CId£ßPÞps?–ú—˜Óƒm ¥Ù¨“´Yœžc~jú9ÿs?0 WibYùQrI_º(ù„eö~㚘÷‹Ï?' † ^úö€I-bÀtáZÙßܨ„^í̃ Oòžþ½Å°> Wüƒ¾EDR)¦\–(‘#ñ%ýÚ”›"›ª1ŒDÖ Ž‘š—© dzOÇaø/Ø-òŸýhœ9úíe~Ù×e>Siä8N2ו’–$Sœ'úþ]ÒjäÑxݶª|ðº„Ôê޾5¼ßÍ´•Å{YLž­³N²r# ­Á‰µí¥©<Ã`àü$ë{¯MB³G[[š\+:$ÅLp_! ÉŒ)Ó¡4ÖRå³KÒX }øra.+Ù*ð™%ÖHøWÑÇÙ½º6ëÜÜÕÃnvík©ÑI£ë)QÃi4 œ8‰:óŸ NQIÏ…ÙꪊùFó±¨<¤ªæ@ÞÓº¸qjÛ¢-ä¦ç¯at}ôé‚g‡¦‹ÿš½óM8 Pª€Œ9$!×q;à ̫e•U(ð¨¢ÙkÕ(]8~ix°/"æ_[ÃĘšWþÄœþKíÕ Y÷×~V,©JbÈ9Ç£\úâ_úÝZ C,8­pÖbðà77œ‘ú'üÓæÄÂ'y-aVZgÙóaõ–e?fåÛpúûáliuV¯<Ÿ­•ÓÈ1«üÅ"ä³z½ÔhP¢BðƬ8w›b&üpQþP‹<÷KKž¥¶%ç5­‚µ§›µ› MØF·Äª;ªñð…ßSéŠ6 µÊõ[„‚Äâvü·ìì%Ãk·Òâc©D³¯¹!߀—¥³«#/¯öIx“àæ…¥(®Ó+„â,óq"?‘(*åÉ_=ΖޛŸ[ M¯n )p‚æÞ`"õ[u pÑŽã@vÉ=M/ãDþõ'»‹Ú$ñ‡xP¦“:F;5 €ë6µd¾ÊfXH<\x¾®¤£Ï:†\\Œ­¶ “dÔqÎÏx7ü˜Ô§Žµo% ×'›ƒ¹À8âS ž¶Ù¸2ÿuWÁ€ÁÛŽÑã>ŽlVDôŠðûê²}ý¥Tn'=êj`³–ä&aÜr¦ìÙð0Ì…@8ÇBßôß:ùÆ4ÉF!°W´$ν²‚3ƒæ¼ïGÀC€Àÿ™'=.cã5ûCn÷1q[3!¤›ª§PÇH3YPœCt Ê-‰^ž2‡r~ o½2l±Å0zö‹0ˆ³dónV¾Rë³ÒÊj|ì:““ûf!É i*£ÏgÒ¾5a¶zoH¸)ï|°‹2ð*Û}ñ—í^ Ûd´IV'gõÀžÀ¸ÿµ'¦/Ùd]"UåQ°j KÏX`"Iß !"n ³¿T„¬²Ð÷Ý ©Ú$Êò-OÍÀç+ÚÑ“º~”&ü6L7âwhYm!ÂÕߘ—ìÃo2xN8Q^‚e@ XòÔ¶^ÊÛ!…>¥ÙiÖF..þë¾ º+á¹r.6¦È4•tmuDz€!ÿІÀÕÒÕ27ë¯Ô–Œ'Brù?ˆÜJ_êá6&+~"ñZ4ª æ“g.¾æ"ÍðìaPƒ>ìdšÈ[‰@æþ+ßµ[ñAŠ«ÂåJ°çóöރ…Äùáá*@F¹ž™•̶^’Ÿ¸G‹ª?w¼:3I±Å¢ÝOâ- ŸÃ$#:à©lñ¼“ì o^_`gð0Ü\T°×=Òb.-–ˆ´zÒ×èXhHØbY ®!šÚ=xÿÊb½¿ºV6Ÿ£ÄÁ²«„ ªRZ(óºhzQê´1yw¡ "ó’D;yÜŽwLly ÜiGiã+0bLgÎOè€ÈM!eS  Ž(ÎlÛ½)´¸_¨á"HÎvÚÊ_ßr›Ù_ž$ôÔgVë19F²j¡ÀÓÛÌÄ„¦¡üêë°íÌdÊXÆSŽÔÈ&3ç—ð+¬Ë_¡Ñàì’„fűåfƒ ½º×és±1,ÿå &ÕÓ‰~™ÂtXP""K{:DUÜ*^¾Ù6ge7F<šîª9ŒE­ôUšÌ’‹¤Ü9¯OXøŒÿ¡}3܈«ºÊýÍÛ´Õ0~¹œÁ§¡I³–\GÆ,CJŸPq8O·ôý§ÙãšXƯ;¾‹­=¡†äPZh³ [Q#>hÌ6äO@ì¢sÿ"`n†~¢.^•8cÀE©rßVüÖQ} BGï®›9‡G¸ÖŒ/Òºc´.•µ ûz\#¤„Q7“£GÆ!ònB™S°rqh¼Ó¶9Èi‰=º÷…XmA/‹˜¯NÖïÌwïO|±Atµ<“nã2R)Û.;Š÷ í,U{Vf%º12-6æÝò±Ì¢]W¯QNyGIôô‰ëÏ)(XðEi¥¸v/@%\õ(æ+DIE^öe%»Š«‹¦ÁŽtª}úîRMÿ[LЄB”,µäÙÎÁ]2&Î{Àâï©"ÿëêmÇkípÎÁ¼ÖÅúÀ½ûƒ(ÚéHÉ›Œº8˜ÅÐÆýI ¬Å8§=ë„£íü9t­ð ¯rT`%ß~.ÔÅß#о‡ZóÙMÑTî¬iø/£HÞ<ý ”lè=šöl×I-6'Õ€ f”B¼:}|€µµ,yŽ\Æ ¾»Iå;äG#«–”(;´p @ÈBÖÅ`d7 Þìg õ=”|ñ«ÙTK]¤®Z!@{›Ä¶ï éö(‚U1Xet!im'&óÅ<1zõ„ž"ܱö‚6僃T\]ׇ){VãàJÇF× eäîºLK ïh- $wÆk¶kídôQdG‰ ;»Ð«ËÌh4ä””¢âÒ!Æ‹‡O×` éÙ÷¥¼AGþEvàž6ФhN£ƒC½fÄèãšJÐk=FQ K®Þ&­‹«Käí'À¶ÚÞ—0®ˆÊtÅ$ËeWL#îhó›²0L þ¡DB9r¼Ø-¶«ã·{ðÜ×\ÞîB¾0È1È?©Öžj´C3”(!QW¨§ñ«V  h­{+Ýe¡´â|®ŽÔ¡À™…^¬a÷øH[ )qêCU}SÔ/)_LHëOª2…èî žžo/ ÿ3GbƒM)¦çe{YY°G7Œ£%¶áQ8J6ê´‡/CÜ8Áæöo]ëÐÒ cׂ%V¤Ê*çcÁ3‚G Ûø2«yó„.qÃ× µ?h ÎÐAUÛæ:´hF‘ÒçjCŠØ25ËöŽƒÛª¬K¨¯}5† ÁêvXäÕYv™Q[,'0Ee"GÀÔ:¯¾@IeëÐWWb½ŸìŽ‹˜[d“øuœ&Cî€ÿ¶lûZäÛFȮԙõkZã%ø`n—¹ÉFÙb>ÜôpvÜZ]Ÿ‚šÌFõýª(èrá÷:ƒËÜŸ Ïï½™ŒP9)¬è•SÑ-Ñï-ý{g7àN×< 1PŽKFq |ä"ÒÛ!q®þ8Q çÈ UmÒ:ÐLÃ18Y~êúÌ5¶ð}¯ÙSòW›ÿàtÜ<0²§™ Tf9áu‚FŒz$ò}ÓÓD£èj‹ËÇ"&]©ì`x;Tl¾æàóK0B:;ú¯ùÍîÆ"Ýee÷3y¬\‰ÈÕ4œ¥!CYZˆÛþÓFȤZ°W´CaFõ$X)éVž vE:™!, 6Òß‚ú!7»©„ÿ¥b´è~&“à³U ÷;<ódˆÙƒâ-Kš¢†rûøG^ØÈÄh§ÿ 2zKæíÅÈm,^Œ¤«ÕâPãS®¼ N^«FV°duÞ§~Ž.8¸†Žù cM„Q«hŸ#þ¿•­Ø÷Ü¿²¡Ôe8ƒiÅÏï9\½ØâysT‰Ø÷¢v@œé¼ÏñÁmtÇÓ>«õ0½O’‹ó ÀïEoèÜówþÂSþ)|×$ù‹1NúDX"Úƒ$¸S³eÆ`Ãr1ä®Çzü&å¾™nÉ@™ßÁ­Œöu7-p(­Ä |»$Ü›ä¥ú¡¥BÜTäöw~÷!ßRÞ«gž§Õ1›¤”ι«ÔÃüá|—bÏjáiws§ožH BŠqaHS(KšlAY1ßfÍ{­ò¸Å"””1Þº=N¸êLâi ¹³ç"‡­+öË‹nÞôsôÔóóf«™ÌX:Çë_žaöÛÓìú•#«ækœÊ+ìˆN…”!/I\3¨ºDÊ+ÍÄÁ:΂ÎK=xÆ0èv’ÜPS# 8è _¾0â­N”ΙâM°SŒ$ŠÍ&I÷±Ã~ç³ê~`‚ÑòZ®ào— 8AùËÁ@Âp>)Äë¦êÌ“è¤bWÛ’.—!‹Ï(ò™`\z`}?Aë|&o;¯ø‘ Ö2À­´˜ÆwŒ/ê4W˜Œø™ŸÎ·ôé&ÔÁ„`ªW‚ØaZ¼³Ñ{ÿm?P¬Ü'\yOBÔVjUw‰£ÁVÅŒ¤V½ƒÊƒ±Ò#KgÇû÷†n!<›êkÙåä`ÉCcüU#Ž´Æ5FÏcʱ[à"iÖ‘ÈO™N,ñ6yvØè½b±Žø½&b •ÈDkuØõÂy‚_%›2üäÆ*Ñ8í[­ b#øÛtÞ5KTc?‚‚;ûã":ˉnÑÕçhARù b‚Z°íp4ÈŒô˜b-瘾VÓàìÃSZÍÔÁ`W–¤ í¾ôØ…)Týæ ‰[‡ã:];Ž”üY Qg÷@Á|o´³R§˜Š©­ËšM—šl±r{ ßþ«ÂÌ…Å›ãÒc¿ˆ˜#¥€f.’BÌ»:)ð‰Sç´áÿŽg2Î9ç'šîs¢²¨–©ÏÛ®mËN5ß«ØîåhaC·@à5†i.œ‡Ì8d€5—ô=ôd·‹ºUK`_$bl-†ä+=œf²Ž&ŒÝiÌœ¢J~ÁpiµÍþÏÞ'×S>ºÁôžq‰á£rœÑà ެÝÞ>C±‚`‚H +±ÐzéO¸iAPÑLñ‡¥hq üAÿã_!øI.…Þõõ<èzÁÓ°Å€³6ùÚió>Í\žïBö±¦œ‹…CÝgkÁ'‘´§~*¾Âš±aJÕ«­—pÕ¼½êûf k¶yµ%LÐYé˜×U’Ü&ÿw/„k#ý(]~=8¬_—þ žÐ¾Ò@3#z,O9>‡í®eŒ„b8ÛæÕý·©DE·m] h¶…Å¢í#áñk–m t/¦I‚‘ÐÅYø-Ñ*ª‰b}Œ8X6ù}œáÜÅ~™ê¢ªŠê᥆T6%‡åoÍ%¹…iÂ^¼LØÇK¬oïzNj‚èfñ‚M¾ Ú&õù~ Z É%¬ðÔÉÚ™¾¿©ªcí§i„ü >ihÍqûXÔãî=L52ֺ˩ã!p&“"´&ÖÁ¿ÄÚ2ãCSA£EÀ0µÃd<}p6Þž­zéýbÀcb04ÆäØ¢—,óŒ¿Ûã<à3‘ç²Vª>n¨£EÙ«Ÿ«¸d.ù›`â;Z£éèß‹+£ÑE²&æÜÇ}ÆÆTh8u¶¯1n#ÝA¦*_5.Ç6п¾’u;£€¶ØO¾Ùœ¿ÒïGÄ …Ñræ.c«ž=¯# cyù7×¢Úy# §™âKæðÍhkx”gaax6T`â¾øÉA÷2V[ª•Xl‚¶1:ÎÏêåg!Ÿ=»‹grþ ¨I^š¹-{eŠ‹7ØáúîJ®Çý“¢0ÿ‚#:âOt”½~,G·¸Îõæ£Paç%fÀaßIE2Xªna\™B5„ÿ»zf<È‚Á*ó x‚T‡Y‘56ò‘yŒ”AlÔUG…’;§ÃkAÀŒ|>‡-Œ°x­—â§õE°­™4ûÍ×B}9oÆÜÍ=à™ZÏ #O§æ° ·íqHþ.3͈N3#nYµƒC IÝ C…Ñ;…•‰‘Õà ¥íMbÊ’ž0ËrÅ^>x=µþÐh­È–¢¯ªRJ6þ? € ±Î ÏKZ§9¢G†9#ßr)|f=RþSmŠ;«ºN´‚O^3z{$×WD aP"<û!žDþú•rÄ{Ö¹¯é[†NGʧኻ’#* Mð`ÐRƒ‘¼!?nR9ĈµLÓÓúý8B |Ù `Ïox(ý= 2Üêžkk»¡æ0ÃdUnbmܲžŽˆ"×ôkÓ×5A÷i&"Iȼ?2t†ý|<Äu|•.î+¾Ïc¯q£²• zÍ9 €_fªTÞvn»Æ§`«ˆJ [Ö–*ì4~>‚VØÊh˜0bË2ÿo7®#;vÛ¼Ô èñ†&#À¤´–^Ì?çU¢n<ß[ù˜1„ZLQ…†iٟߦޠaé1ou•åR¾ rôðõ-7\t(åˆopGIwJº–"¶ì…êîr—Íy¶×*°ÉÁ‘ÄÏÝ}£lêšáX qé(„ÿžx´'ƒ;ÕÎt¿CØ"˜Húµ³×ÅùˆGj/Jœk³§É£‘Ú”~ñÒ@°ð÷ç*¢:F‚†'ÇüZ­Dç“Ìi¢K@¦Å™ä1# îΟ ‘¨âŽÈL<Іd!¯¦âz©Û׊qŒRpV6Ì·K·™ÇQç}ú±¥_ m55lÅ¢upòù±ïÚH{0´Þ?£ÂèÐämZÜ0‹(û gt…å&Ep –³³Ð©ápZ#ìYô­z¥JÁ„F"Cz쳜˜“NPԚݣCˆ0üÃÚ\Gw‘)noºû²Ä„Ö" |½òöB·Ùd™"Œ3âdœTÀep÷-lóhz³C‡ôÍËSËG>Êg¶ˆa7%~aɤø.CX…‘c'kŒ5*è ¨«ä#­ÄajüýÏ 9ñãaIÌF\ õnZä_ŠZZ͆F¯=\ï|oAÝÏDÄík—K¬Ã!?º'£üü dÍ´¤ €%ãüÊX=³÷ LDðé†GÚƒ,€ SжÀËz~­÷ãƒYì¡F×kÞð’ ±DØ_–Þ=®Êy|wè÷ò™z5ŸŒºH²‡ÔˆMÅbâg-òWBHæòâuÙ ~†w©à=ÌÆ‚²77€V ¬šà㤳™ýÙóüj îW±¬ÞùSÊÞoôÚ8nôŽ6ÊwkAà¸2ÖQtâŠÅV¼>'ÿUtcà:­¿)ÿدÐÊRÿÅËÿÏ©{ݼ]<´ŸiêÔëLÁhA}Aìþ{Y…Ý4qÎÕ­öÜñ& Hª]ì6ûX{Ѓ§ØÑæã—æót ‘ôƒº½·|vLB68Õâ­Þ¦ëµ%'j8ºÀ­«é› )þ‚Ïõ)ª*OÒÊB./j2d|\$ý„?K –dʦø&IleN$ùyÀÏ~›9e-C„û`¦žtëÎ1IrŽYʧ[“êòÌ(n~Æ`Í`Qb€¤›pØ|:¬?ëRÌ€~¾C‡›ë Ü€,ê¾PäY$ž…1ŠÃ|¦2½ Ï_=Ñ—î)1ÄñôÌTg¦ºr'lúüØÄzÖw“ôl¾|"mtô »¡µYxo…~ymµKî\@Èÿlíш½»Ïa©VH )²tÃå„F'M°úëó|f yþØM·=¼ì^¬(‘ µhؾ‘*Þâ. èÊÑtÃú¹b}(Ö›±$éuÁD òPܤèi¢‹\G!F7Ÿ ¶Å–9ƒûn{¯ëT f\=>Õ *d1ŠsrjXa^^Svláî3l¢Ÿ Ú¿Vi¾© ©ØÚ>ÝÇyöú,d¡pRðÒ«©Ø%Ó%@Ǻ;=#¬þ|èUÔ‚Lýf’s¼BÝñDœÍÇÔ¥w K¯°RíK´SÁwÁ2¾¾Â^éÈ¿–q®;TÉpÏòcÓ™Õû!ðG?˪ûÎRm‡“cš\ðÎ"À¼òéJU3Bõt„«CýJC íîJþ·b–#l õt<úU_â·}3¬Gr¥?EðΡ%žÍY‰‚äuÕ â'ìd{»²ÄrpÞ¢Ý*1~Œ ïaæÃß’Áï)œÂÏÜa xñ]G_4'M ¤§úûËT¿ e¢æ?ÜoÏ«rŸÞsÚÖ›Z¨ؤ|yR*ˆøG47P)SöW†/I#]Ù‚ƒk#ÓúKžù¢:òÊäY·Q,Ž:¹ÁÔQqBÞ}=!¯£?u[Áô­W;þƒ5?/ï‡w±96©fÝÝŸÎx,,'“õÈÛÿQ®;‹ý†Ú)È_Š$,ßï3—5© @©Ü‡lÓ^m›o'¿H>]µq,e?Å™g2Æ>qp;6Wÿ0Ä”#"p–ú`¥ø»¦·Òvgu *fþ‰ W„iì°¡Ÿ"‹‚ NõgHH¡;Órå+gƒCc¹G”y3£ÀàÒméà:qáÉ–S!Ú™9¢\…E\nnˆ¾ÅŠ6&Q3íJ¥ßa´ò%Wô¸ßÊ®#Q´=âÖî¦LëJ.è;hÀVw!!ìN*"]ZñDp9"i¯yªöD‡ÎpâÉþ;ö©l„­OÃNnÑ´Ijô­'æäÌÝô$ÑWÛõØ?í/3OOX‡(#•b¢¸NJ‡þþÜC^VHˆžÌ'NU`¡ º7Ð7ÕÚ:q‚ºk'Uq𨗬ɲ÷õ[ö¥¹ð/¦ºø±ÝÖ¾¶ÒH,= !i5¦ט[¹·4‰sjíÖË—²M镼~ÇY¶Š‰ƒ¯î5{e‰ž‘N5#ar^_Ð%‘yÞ…"3Üf )ÛaE#V*€¿Òƒ.ÈøB£¶'fš& „âKÇÐqó_váÅn®A‘ò ajOëÅñš$¸tÖrnû"7$&ø­-ùPˆúôº ±öœÏRs7$IŽfU±Ë€”ð¡PëP<¬vGÞÿõ÷ÓÍt½¹Ç€Kxš!èHÏì!O8„)™Ü"‚òMäv¯ŠÅbÈrûÃäÜ{ó÷²½}'ÒóY8FŠ}È:2êP2Hûjè0˜3éÀI›{Q€P-Op‚*Cñ‘¨àòÁ„´|Àˆé§ZäVÔÚÒ;Á}`"ÄÝ [k œHåßà• ß*·æ5@C÷N×w#ŒîÖ *÷˜ìþ…S ƒaG8ÜÈñ#SÙÓkÖÝEGäìïîtó—d¿O7»£E·ëC{Ìz`È™åB­œoØ—/‡4r#Ù¹opIw<¸Ì" Þ¹/A ­’ûqáo tá–N¨Œ¥p{–Ž Ú×x -/X“=:úfè•‹{#Û+<É#ZÃcýÿ”æ°Í)³‰(mn@= Ÿ^zا™šÙ¶›¥ãh2 Ñ„Ë:õV Œ ŸRˆO蟗›«¢Íü±¢âª+#b¦{pÕ@¦…=1’F·wàæq¬Áú/[¢¾n& /åûð$ÙjtéàòÝQ“z=¦ìY!Ôy€ðéĽ¥JV˜½aÛ1ìÿüansÔ˜cÀH¹xƒäÕŽ=³nºÓ²yxP¦A=c#¦èäšâUuOé7+±Ðô>Ié/ÖÞ ~Ò§®>RÝjF¡ú#U KãQT£Žêþ¨Éku¯R¿*§æõÞ˜IE²¬ÿ¥ûºÓE ¡ +k=îØ°ì «}v0ñÏ´¦ÝÝí^fº‚jjáûØdÒ²*¥Ž>ZJ‡_BägKìT,îÜúêçÏܱOu.@)ö=§”$üœÍÌ'Ä5àBåàªD':âsb¥Í22ð. Lø4u´à‰ñ+Cr¯ŽÓžÊM­3ž×ÆlpÞØ´mt ÒïÌÃôe$w­~ GuÛXQñÁIÚS¡AèåÏĶxªÆjånÁ>„. ?Õ"Ž“lš´Å¶v¬á»-;®RKß ” Š(€QºMªÕns›ýdfQ6‰wèøY@$_D6åei**KŒ–P‘ôȩ̈)µâ;ÂVb{àˆmŠDUBó¿ów ±Q í]‡^mÖöÜÏmZ©hB_&ˆ µ.ÄèìÚIÔÓë ÄŽˆ„p2ö²ÓÒüÃY–âÈäYTÌß²V ä°¨KaõDŠ™÷Uùס•‚ïxÇÝjø‡›»©]å3*ñöÄ>»2ÊH(¬XßJ¢BRzôß+_Eó$sÄùñ¥]~„ƱMr'½³¬öè–¾4-¹–@Ŧ“vlúMíH³ f6yšø)ëL+š”ñ+ÙŠ Àc—À?† i“BÉp‡'óŸcUùª†~¢»o&Q7X KõŽ©?•͇F-Y$Ùhim màõ_8ec3Õë½b3&Ì‘ÅñG5øû ÂRŽ ]Ì»(‘¤:ÜVþ“·^É{ûÑLЄ®!2ÙTw¢P7«¯Š|Ît]|jîb¼)Gbîó ^híÑY Ö9Ð<ÿ^JñÁ¥6“Õ¿h/j·€ï9 ÕSëK´¼Nÿ EPD}ãöË4X9bÅBäÕݤ¾Wp¢¢ìáP‘4Wòü¥"4†­9©œô¼“ìi!iy8è:™›[ÀƒQ/JäÀÐÁ'-ûÓ4vç»ý$¾ø…9cä‚ðp“ ’|õtÅÉ™*é6H›‰ÒÊw$uTÆ‘‹»4(M`Ð¥žñ¼d4å§ÒàÆumbÖÿrÝÜ}ð*F`ÒsÛ|_'•æm ¾ h r <¾!yö–˜î/ÚñFâÕj¨ þ@¼=Úñ¦:øß*EEc•¦KÏÔ=€ˆ[þÙHg5EsÃ*ÊWô'¾™iÅD9,4BOM¡­§øc>æ²uBZ|Ÿþ‚ÂIú?Ù™œÉŒˆÃè䥾ÚÈã½™æcõ¤³ä±©z>.ÐÑŽ°Ë@gâë”hŠÓ%/úUf1íK@ÞR¹½äæë¹!WêXÉÿlŽ]z$®ÆÄau^@œsîV< ¶ mõÐϼ|v°ü£zúØA%ݳsΘì¶nQßÚ$„““[7´" %Z-‘¦‘‘À2{C1°hnÚH&©ûŠ·º•ìݯÇ=®`ìWG;¡åÏáÄÜE¬ÇO2s7cûŽzÊùBNmÌJ7 ©º×zb„r_&6ˆwÊ‘¸åÎSÑ}}ü+ ’Õc¯bÙŽD 1õ1;Góu !FÐ]ŠRЭˆP;Ú­mY?çz?0¯pއþŠý†ë­¤ãæ3ƒ1öò6%:kÅæŸtPÇK¢Ô HÙù4çòð†V*ç©ü—Q°[QzÜ1š6'ðIÃá±@Ãæ.cþEÈ_­z)ã_á4¶.¶²Úš—ýQ{Bÿ†Ž à!Dè¬(=É-›´\¡Å(Õ Õ»Ác0ǃ&zíï4Œæn£Ï«\BăùÛ¥õ ÕY˜À‡§þšÛó^˜¬rÒR©ñ䬭Ä%ð'¢Þ "\@¯q8£…B&ÀmW>½pÏ8Óð>ÃËÛÁñv>Oü‘"óÙÎàJ”Á±”ÝŸ#l*MRÜYøfçFèJ>cL‹÷ÉSÞ‰©ä¿M-€)0«@’,©_BÅfzæ×NÖrr¹…ÑöŠ-þ×öˆ¨À˜€nÑ\¹¡æIþ¹Ð¯ˆ.< ™ Þ*'4Þ=åaœ»­“ÈÓ?CMñù†úÚ>9âQwñ>`?M»HÑ»ˆ¯6‚íM4oAK­uÐ’hïÆGG]³¯x%ÇAÏŽ¥áKÆ"Ÿ±Š*èrŽ¿Ù˜3ñÍü¹Z/×,)ídî´ÃØw2©ÜPÖÉ{«e^PXõa³åH˜gål9™¶W+p&,ùËé§KL­(mLÛ@sn¾‘¦2^ÔIa­[CÁn6œï·ã­¯mÝ“ÛôðeRlqüýnîÉXX©8²ÿ× ËT/¦ÝFC¾÷«Íä›wŠ|­k¨ŠjoñDÔÀN$lílLŒ \ðööŒ8ýúdН'É*ç*W¶Õ`s€9„;å,ÿùõ™ZÏ©Õί”(ýÈ3|ƒŠ%Ðoå{Îý¸¡†G¢~MÌœzXe三ø/­Îòµ´dŠ××~è,ôΩ\gCÜ+z¶œÁÔÁ öM”팼·í…‰Á¥L[‹ΣÄSŠ¡r¼–h·!ÑÅœQõÁñù²¸WN' ’˜åí“(7v[‚¡#¨²Íuƒ¯Õ ªóAD¿þ: zS, ùEÔ_Êò@T}˖ࣰí8zаÎò1šë 265&9=<ÕíÌÉØ¯>ô¦ûÛ[…,íz((W’‰”¾”õ*‰Ð{^1¼ëxU‚S¼ÛCÒ>$d†?É*•e­%[טï†=Óöaâv'ߨæ¹³’ª¾Ž6çšUSÜ|=b8z>Žò\EÈÔ Öñ* $b&JœÙÿmÑKK´”űD‹`·’^¤J1´¬ŠtJ !´ñ•pXÜmWš= N¬sJi °±Œù9á4¿*2ƒ]÷aV&ýzéÙ¼ŸK‡gþZ™_ B:¢)™>±±d`ûñ=©ú€è ÄÓÕª£>ñÒ­<åFåw‡Ô´¡»WŠ*Gú½¾ÕÊÛ#]-)ò&ŒöY€3­áÀ‹Ñ„“s •8t÷ìKÑe£Sšãω…JWÞDzoo\­¹^ücvsGò”Æ’Õon¸=²;üÉ•¿ ëöjB+o”óã¢>t—bm€ ÿPŽܦXò :r¢ÁP4±«Zˆ»s;à]"GÎ#y¦¸iüº6<þ†Qr¶†÷Ÿ1S‰|µ°$2|ÿ ¯ttOçd©]!o]€;€ˆ¹(£&Ï4²Em æ÷Ó Kà©Êçf9ÌÃp¥$„R¡ù*qå딌ØyßÏ ÿ„8h¹ªÙ7Ô&÷]:]8°~ñÚÜ9HÄnÁ'žÖwCÖåEi—7jx©ËØ-bo…½fÑI` >™"T°r›ˆ” èš—^ûÏ0L†@Ö™3lÌF©#¼ 9´, (z}²YYD€Ÿ&csúÜ…rÔ¢îÛÊS³øœ¿üƒÿDlé’Z³‰‡¢€îˆzŸB°ulEå‘Ò»42îœ]ºØþŠ?®ÇÚì:®BÉ|×-_bÏl`±Íkô¾Hja¬¬ãÙåóL.óC‘iJ'}h'ák«¼u»Q¼’ð­¢ËÛ/%‚ÞGÜhôj¤Æ G½e(€ìÑã’gWU•‚à ¸´•—[eZ6H6þD&[^3Çbù뾊Þ«ætE]ÅðDúÄöD þ± …„ùü Ï1ã¼WAdŸ_/ÈÛÄ„cf¬tÏ$ÚB­.g®¸NesŽiÈ|Ô²CkûÔk÷Ãë„ÿ0ÌNãm]Ãi=| øãÈüÿm¨{~©ÌÀØ=Y»L%O$îjí+«—cjPWŒôÑbŒ*Æž!~Ri¶8ehG1Þ̽¥/ssÜr$v -FHåÅék;«¼BL7…hêxÅ £viº˜ ÔšýeH0.á&¯=ûÜe½ý®Ø>pÛ]æzmRaê»GlÞû ¨¬ÿ«OR7¸&Ká3s-4g”ùP³Ók!Æÿ$šÑ#)EQÂ#¬é¦º¿BH$6–À¿e–'¿*h;"é¨óŠ#¼Åz:†ìš~ƒ*ô2JÏiGS4÷;µé1Í©T‡ø»Ãh·ž=+mB°¬t+܈Ïj¥’dûyß™‡{yYR%…÷É—ty!´ß|Š‘gí 4‹¯§K>ÝœIá?Ø*|öÉ[à' tqf›¸_{“¡”dB†ßs»ð‚ßvß›žÑ!ä-Uì]h¼T—¦ÐÇÃî:Ýwz@ÿ\{–:D6P¤¢çÚjd’PeR– õšQx¼Â:Q¥s=Zn¿Ää\Œ¡A‘owCVM &4"°˜­€§ —,¡ç¹ lT{ÍCµ·%xõ‰ñó&Î}æ~HÛÔÕ¯¤¹]J˜ëNa´=þz-¾­ª 0ÉùtÉèiùAG2èXË&E¹ƒ!îѼ‹¸ ÉZØð¾S^øj NŒW«‰ßUØJYþüÄÆÞxÏðm‰Å¶P•qÚ@|FK7Ç/‘ª1 ¡º¤Ä¸ã敯H"GJTu8^8ŠLáL| ·‚1g¬Ã œn¨ý‰‡ólêÀÐ3͆J·.ngü÷n£c@kí…>fN%â)†eý²‰«)ìÇãddZr³üüPæM˜ççæ¦ xPg@…NR!n²˜;¼ŸÓª.TÆèݶ~ùÙ Bðâ׾¢5©Ðø"µì]ÉS¥i´?wÑ »ýfÛs“×wÍf£´&ÿjQ’e-þZ¨ã3 ÎÒdicÒEC‚1†Ökp›ñ;÷­S±>¨ß" tí ¾…ðá7ó1  ÐÞfÙ¯°$T­i¾%ÓgÛj m›=„wÑÚͶMŸØ9¢º¢Þ¡üiœ$ÜvψçÃÛØY]ô²)éZt'þ†E8œžb*Ô{ôÏ™ä(ɆjÊúHÚûoˆ¿ÚòЩ—¸«X!Øß„Ôˆ?€D¤”â'À°®kÁŠ b§ˆbû±ìs­MÒlýRÀ ë¹2WµŒpçåhx±!ê$-]'_„YA5p™> >Û•‚< ¿÷ÿyî¡æ_îŽÇò‚SÞ¢í¹K`šIœÞ<¯DÙGÓN4œ¶È÷­G6ëd¥ìàÖ—1««œU- ¬¨Fšˆ»Î€¼A éà˜G„†doÕSD.þLÇ'ÑàÀÁ]"5'ÚÆèØBN àõmÙ±#)gV|.dÀ:Ý'„÷a–¸K¾faîͤ›^(eP^šQ ãQI°Í«ô¡¬ÇT±éšÐw>öËØ±ª4VÙ&š=ðӸݛ®ÞIñƒl‚ƒ¢m³®zë.ÂÔˆøŒq/©ÝÌ Ï™èÐé³Ifcå3WÔ@R# §0WjŠž5±ºÙo2‹ˆˆ§ÇR¢DŸ[Jsáˆ_×Tö©y 'L„:ëªa°˜F€þ×èúÚ‚µC'!cý»ŠZö“ÖÊ۲ϘZ½FÁ7·¤¾›€õ÷˜–ô3ÒÚô®R±‚q0²DL/FѤ֔Æ=ú™Ÿ_OªDî¼õÎ-zAàrLƤxßÇy8¾¹DÁ*´o´ùŒc$_“3~ÎãéGšðF€”K¥ @àt¥x éçaÕjÀEïr"®Œî·:\ë-ÈQ%üb/Æ_V±n2²®)õ6»gxÈæ6òKû½"Ñ1¹•Ó@ó~žÕ³4ïU¹A TÊ­ß–çàVßwËfC+VT™³ëïSÑCöÈ($SªÔrb4p×Þó²™lÔöSê¯vläŸÞ•îòB>ƒã³D“t؇ ºðÎNÜeŠaåÊ5cUGû7úIÖãEÝz¾îøð—uΛ,¹=©vKNCÌôyÚày^o°ÐÝ„»ÒÇøl©´úÏÔœ’Ê~¾<i>c>(Дi4².ô‡Îp?›µ‘µVЈ0á0Z,¼EÛ{ÄçD.ð4ŒÝÊÊ Ô4Íká«nbîÑI9EºwV‹Áß‘_ë#õcÚ¼§ðÞb)MÙ´ÂX£ˆÇI†¦úù%¬yDv”‘O³+ï2ø¬B®VÜÒ ãùªÈW«¿ãögPÖIjVíØáO¨å]{MJh ÚðÛé ÞOÅ£'Xí×"D”t<×µ³ù””5 !ŸH3æí(Íó/¥}j¿½ Ð`±ª‹âB{#&V•ñ¦!šê¿1Éô–© Çߥá£ÚÞŽÛà—Ô4»-S¡G*ÙÆ­™íÎŽ†sS€èã[ÍļчštIÐbüM¨\äËQJ¬ ¸ô{áh”ž@3+õš?¾‘þç_Åüþ:p8•òÅý æ6¬ Á-:ù¯of’7ÿ·±Ñ’MtÁ`sJÚÚ·fâÇ EÝu½±ñy&Ђšˆ˜Å» —‰-sN±1_{gòòxúר4 ª- -eå3H̯SSöárlç產AÙ^ºV—ÙN9Xn¦ë­bðrÈôÈP>Ô£LÒªBC-Ò+-(fÝ8;äCã öM{‹+À„®1^öåΓ/Ëò„+ ©ûu¤/ty€Y~å±Zïe¥ÏO,˜ä¹v–!²}§º¢ïã œ¡Ž$B5ëB` r½°‘Qnö_([-ÜèE]ÍI˲€qÞ¤£ë âZgC!‚6ò¸cFVPÈW/:¡ìOyaLÙÖmZZ]"‡£²ýk”HMö#N„²´x…B)ï 5¤K¸d¿|Á®A£æWàOà:/2ðômùóLk¨páuéÝ_ÿ¾ˆ³* y`å6žžáØþ§[)Nàü8CìU²NÆñÈŒº]È‚£¶¿ ’ ÉOGú¶¬ÿøl‡e­¬mܼ® !|IIµÝ5SÇGÊì§f7âE¥‹¹œ½äzòOï§ Uåò>¤úA TZ©¿Gö¦Ën]i—yñ;@³/îa¿wix .S7±¡üpkóÁoJ1È”=…ÁÊÑ+7ŽÌŠíàëcmË<ª¿_0™œU µ]m?[V.%ØøAšŽ¸GU,š4£ß™½ù9˜/¼Æµ£H)2»óí,÷2át½€gV‡Prè™S(îh«µ 0S)(T¥«=M´ ¸ÉÜ@OöG‚Z³¬ZÑTV®òô__Rµß¹pÚâ‘@ß@ÇW/åj7¯NáðN æ‹1ª¬€/1OÂ%¹7>Ñ&èŽZ2c£ ì Ɇ\ØÑì|3½)•B1!ë%¦énÓôíœÜܲ£=}WGGì“HI-SÌ þKkâw ø[:2Òr°c†ì˜+wFÃjX†XM—3ì.‚»Dod\¤{nƒ‹ò™U'P¥aQ?§„ ¾Ð*r©CZ~T˜²¦´äŸVP cñ ›±&qmBnï¾Xœšð‘Qj'öçv%ûópä`t5]´Vtr œ°ŠiKyÌÁÄû‰·½Ú2’"¬t¬®‹§º÷}Ž)×M¬öPœ‰ž ŽE ¡ûã ¦£Ø4"º#‘u^•ÐÈã`{pË Œ’Az>þžo1&ø±Ë>µ±Þ÷I}ä­3ú—íH^ƒ3Ö‰ØØÕ—µ>ïm@ƒuÆr¿¢g'ªFãš½¤þœ6?ºÕkL>‹ˆÜ"]8uÌá‚ú°«TnWHÈÊ;cvž¢?4A*\0¶|÷Êá4RYžo/ï ¶ðÝ€wY°Å÷Ùípà{ÕÇ¡¼q©Ž|˜Ù"Ÿ¶ÿÐx*nD{ †ìô¡Ai”Uà55˜[!9¸\²·k,°ïâO"K‚ìŸ[zîG eÍŒ^ l!^bå÷Xjo†’Åkþènß½sßà,3Œ¸%ˆÄ%Œ38O¡f¯$Û©ÎjV§Ž[¹”_wÎ75•ã‘ ÉÊöVâ¯+z5NÔüá>ûV€g}‡!)žx.ýí· ~œ83k0—¨òB[Ýùš°JQ(w†«…ÌEYžb3VWL‡8© D˜&\(ͤèÓ®ÿ‡n½v8Ÿ«©k ÎUú G?~D* ‰ªü:~ìžõ®ÿžÉî%øÞÓ°vsÚ£B~Žïò,±c7âŒÀ\bimÜ’z~t~¨}rÑX’B†ðZ’øÊ3×´Ùdz¸ùŽºÀ#gò Œ²"¥&¨CØí/XÐA`‡zƒ¡h˧&%ߢPbPÕo¥3 ã8Oî¾ê·ø…*x;%ÉVC XU¥eªÛ®À§rÛŽ«“<–ê‡Õ¾µÚâCð=þ)7§™ÅGAµo„ ±ó$i¥ÇÓ°s­xĺ1î»rݱ=ûb¹µ2Þ:ÒpYñDñ<v8ô;ÍžÐâö„DJ÷“¿Þ—ØÿÙ‘«ýëÀ:ð{'-wwÎß.W¯ŽôìÕúÍT¼”«zÏ-Ö&Äð+ÞÖæ?í/+÷ä3%5nZ%½¤q–SÒŒ?ÎþS‰Cþ­þ(£ÅqÎŒ¡n ñZŒ3ɱGZÿ8Á¡]?¼‘ž=ÐcuÒËbvÏÏÑÑ@-Ɔ2r Ñèe·ÖrhT¾±F˽‡ÕFaÛ BÑQüô>"5†ô‚ë´+ˆgÏfêþ±Zq¹ÿãzN:ê®K][áéÏ9ÓËÞžF¹‚&û2˜…fÑVü†oàcßãþäô§nªß§ü |%Û.ÒËæs$ÍiW¯ÖjÈ2Âåÿ³á»"awhfÍ¢éV–ð¡8`VS#£ov‡tÄNòdÓˆJÔ q@dzŒÜÓtÂÞq+|ˆK°³¦¾Ê#ÒôØú¦D•¾ç`µc6ƒ^%üíH¶JÑâ“À ÖÀc)\Éõ)½«0ù qÄ…ºGS†!ãékÔ¾)=CïÔ!‰è9ϯ¢šéI'ªžÉÔ¦NË|æ‡ÊFþÆAoƒÖ<£ UÖå`â/¦Q¶”=ïè÷4µ„e_IœúØ‘Ìno¼J9áz"ÝÊÿL#‘¸2+%ötm…šZiâ)s¬Lƶ ±-ôªým§Í”nXõ"xÅ:Y!!PGr¦•9>ÛU¼ÉdgÂÎÚd×®õòœ_uþêàšŸZóéz€f®ýhÃwr&ë| üyŒÄéJJÝC\$qoQÃN 3˜ãko6¨jiq —µø%BáÌ÷¡Å¸b/gámߎ«ß¡+Zh’µ\ÆÏϽ8' ­MvDî ™˜à—ÄQ+¦ˆnì2k êqó¶]µ“|Ò|lgvâïL»9·Vý¿@ïo)paTꯑÑ÷c‡”6Þä¤×Ÿˆ‹‰ÍºkNµKë¿ËT%Öð­-éÔqÎýÎuŽ• É^³X¬Õ>–oÄ—*‚Ä¡ìÌ0d~@rç¥DôˆªzM챘Wf£í‡,›\B.æò»ï„“}d!ûEÎv÷´êãAÀ?Rnüæu» ¬,ä¼(­ °v8r•û?lþC+ƒ‡HYýp]'Pþ&6‚ˆ¸xXVA%±;Òì!XôSIû3Ò܃òôjž+÷Ã{DÕÊ•Ë^piFoÏ1xc¦bàJøªë1-ö.⢈JoÛãrÚ7Œ§¼Y»çlP¢ \ÚRAIéº躗X äþ;+Mh0âQBnÈ‹c#Áò*¯Ý—X“í4@«ÞväSºä«£Dn몴·“„sÑÂw)q0Œû8h¸<€&¼µî;®8¾ |Í@.@]”‰ß­H%)²Þ¨H‰ú ZëÈûZv›’AuÜ  ÂtJ³ hl{·ÜztW3“/±:§t—=Ž‘÷ÿV2ÚPÿ¦5ïÖ-øKî*¢ª(úZÑ[VU}‚ä*lÈñrÖQ 'È´¼eÝa8xjͨ©9L@Y`+<*kÆá1ÌÓ‰1Ö¼+‹2u•p®]ÙïËb„êžÙ‘aa±'Eì©kŸW­ÛÉuÐò„À¨èø´AÔ.šh%ÃHý_¹Ik4?ÅÁÿÓyé„T9íJÆZÕ‡Ê)åàÍ™j¡CJº\()˾;—¾ÔF)O¦2VJÂŽÑ¢ä†gÈô]Ö7/EJÉ‹u .ÒÝ —š<¡ZJá#sçŒ:¸‘·±umé¾”âĤpÔ9ZÀÈš9ÚôU‰£c~t×ã¼€VgÊGl«¬³5>3¶! ã5¸u¼‚Àxpž­K½lžñ)\éu$´Åîþ¶ÖŸwÒªƒõœzð€1Â(Xz–,ëC„Þ07ŸjŒ çrs>U¥ÈËžh'Ejx‚Wn“â•–H® ‚&ÖšŸ”@ìDÐ ~îê=ÿpB@Ê«­I*Ø%5[q âO”›{]¶ÏûwbÛ‘ºUQŒ¯™Ìñ]$Äb‡zºv7MnÉýxé–¿ èYJÈdœãMRœþ…|ŒË‘VN‘–žá_F‘‡]B»Ÿgâ§Nˆ\øHšÆ¶~V1Œ¸Q®óÈM§ZŽ Áã÷-¶Òð裛d2–é;ʧ'ÓìuTX^"2ju#”+—ñt`ÂX·œãÚJ’O‹6÷_Õš»ö/ÍéMýÇ8 W@Þú&|5áä­Ë Õw7à…5'—KlZÂû"ôh:òš÷ ª¼ÿrÔWW£^sÀg¶^eqÅ”_ËH!©l±XX¾b>:÷Å0,&ÝÏ39øýŸ/‰VÁw\5Ô+¯éüÑÀÖ ;¢|ÔAëùÞ] *=-o… UâPo»®n0›Îà¾uD¯jêâ•'sUá!£Î‚׸Gq5ó‹½K¥ý²¥½|¥šLÇ”Ó÷5ÐÊÃycЭ<ŒÙýËøÍ!WBp1Y vp^joCQ6Vɸ<7ôÌñL´@ädáå,– t‹öÝÜäÒDÒ4wè•Þ”ˆÈœ•Ém4/ˆ1Êæ4OšÀ•”D·ƒíM¼”W/â{QŽ©¼þ˜¡J­Ê/ŽËu•õæö,¬;Ôn<¨@4™ºÙ—O=ÄÑ5ô?¾}…“3RýÞZ¾¥sëi衳›Ñ‚×I‘q'U÷Bæ æ¯üÚÌÑeQæ·¤ ¿šãtØÉP}ëW…BZ.†?—{yˆR>íj_)3Ø*40p«TR ¼ÿ¸ŒÌ=vÙΤ‚S.¸sª¥N˜Ü¥§•E¥ Æ´T—ˆa5ñ“äñÇê«õ¨šðâ\£Ê»ƒn¢± ÔK”¨ÒŠVݬ1…äànîˤãa/â.ÿä|s¶iq;0šÍÕˆ¼ƒÏ£#Id`ªè¡×ñbçwö¸suXÀ/´€ºŒ©8íæÖ¤ÄëÆÌÅ7š¾o”¹êø{¯8¬wûü \ïQD'yË HO¼¥ú¹6!óIü" 5ºa_íÎÿ‹Ÿ¹3mx ï¹Ñax•ÜYb©1CÃûlf\c4á+‹ÌÙ.kØÄ &Û KéE×÷´"$h.6WLÊ)K­—ŒÁŽ9ÇdP«OaifR¿Z%B¾ 8Él÷f_ö+ý ¬e7˜÷P#\Uìqºx)™|5 îP ñ‹¼8ƒÆÛtªŽ1zb–ób#[xË×”ZðO­ÏpýŽBzéj[ÁZzÚ-*N 8(çp-þ#òãùÓ q©D(»eÓèß2ø®Wrö*@ ìv%T%.F|Ò1Œi”Ë_’ö.õ)ì²=â‡3Ó²üÅq¬Ͱ¼úÍ ZNZ§_͛ײyÞÝXH©™ìÍyÜxE· ¾Þ”IüCx„Ž‘ÙfØ6Ñ¡ìû’ xÿq›#Wc©Hšy@?¹¦d”mÇ­ñÈ%í¿½¦àoî=Ñ®åD¿:»2ð<Ÿ‡<‘Á¬0Ãp¥3 “ûö]œ6ÁÚcã…††¦ݹäÆIP‰döæá6¨£¥¡þšÄwGKðâÒ yß^阯ê×¾éäÊÒ?( }ªÆšA S܉_<´¤wb ¨´Ÿúˆ6+"L‚T ó» ýo®Ïþf°U†Å^iñJü÷™åg¼¯©p°EFš¥úˆ¤✠ Èq“ºú ¨5º¼Ÿýhï‘éHI_ta$NF(^¶~.ÿ(®®€uñ6|ãW)º&è©!ÓÔ· zRxíÿ8›o1¸ü]yƒNË'”¶JÿY=4ùª¬³Fbb¤ÿšÎéÊ“²Ip%9;⨮+~µLâÓžúV£×ÔÌ®¦ +7ššoû[w¹!þ¾K£à€päXšùçhœŸÁ;ÇÿƉ°ÑWg|©¬F9½Ëà;‡äôÁ½ÇÔåwcB .A.ÿBnʼnÎ;WÎÀ¯šÊYt ´R2ÊRä^Êéö˜ ˜Ã|¶®n˜Þ>}K‰´IAœï½À0‚µXç¤ôÔ;¬Õ°_â!lÖ;¡²Z"¨%ñI1t3$¤ƒ*‹K¾¹zïñ©®›hØn½Û jCÒ9dõ£8Z ޵ÛKj‚<ÎKâé5Íî^õ–pEÜqWX®*Ùj÷RF爔¾"Âôßâ§)Br~ô<¤ B„_e’ÉÁo‚z£/åœ×?„\Y<‰ýeܸzç«ðÓæú±Ç> ÝÖhd¾‰EÚ%L‹ý­+½àna}„{X'¤sTa‰ÙTà‹4žfŠ–G‰|»¦ÔôĨûZn%\S?í0+s2÷­wÅZÿ|­ŽO‚77€NOfJ«÷¥#LyìΰŸ…r]¸G-“±¯›!Ü!—š¸‹úñã`Ú¦ßØŽÊ~0 û@à1›úÿEö¼wé}ê3íü«gK×ì`ažº´ªœºáÆîb3ó’c“žiû/›ÉÀ†Ý–¾j(C¤çŠH;ÛñËmwG¢¢üAN,YpÝÈìvïå‚Eý/ã†Ã¹¾ÚòR3«»L¤¦`œEßÎ’ÛPyE#&ât`\¶é‚Uþ‡/V“‚˵|ß½6-:—<*ÐÀå•j\¬»¢­3;5É;v«§ϹÇË{’Tä6kã~¶}•uº£]6 QŠvÏ"IWðؤeµßÙ¦7µÝÚß ›Ö°¸ºT…úÃl5#õ&EÛKu(>P2À&ú™d¥ å‰*ÐÌZš›ùÌ*ÒRÂ+ÂY}Qjp@s]_FVJ××o£on!ÉPGͶ·26ÆÖ¯âtÆŒkeæ7ŒB¸w:’Õ[Îà’vb$FhZ1þºù¦9èu!ï‚Þ 1œÃÁsü±ô*ˆŒ½ª™ë¬Z24:S¤2¹ä呪£ÅmñqûM ŠÆ5±Íé—0Õ (3.P"ýúpǯ€.+Ë¢Õqa“iªaHy½_ú CáZ¾•†lÛ§t;uë´œœû¢ÝfÔà\=ä)¿ý"q s»<ÐÆŠÐãè õÌŸSl‘ÂnÇ"Öÿv‚ÔN#‚ i·xwê±›Ùòi"ÿ#&¬â»ëø[´7`Yª×½¸Ó\|ŸT¹&ý_qïÇ@{3®Å2ò®pCHû\^úÅε´ @Ñ€…7‰åf±I>¾˜c‰Ú¡×ßxK‚.àk8 އß×ÈîãöE:ØÄ‰¹’ÿckÈU65Ö& ĆÁZ¹¤¶HàG.qbÙaù’Ë{¬’#‹‘µ“Å{{í—M€”nh°°Íû´'^ÞËÐ’TÁ|ö€H:»nx^Ò¹C34ÀÊD %ÄãE*Bõ8‹ƒø›uZ‚úGÆÖ*¹`öWð‡ó.ö®l<þ7¼Zm3¹eæy׆ä"w<·‹¶ITa7÷4¸º•ä9‹Á<Á"Ôý|.QÈå×}‚ŽËGïŒˆÆ "”Íä5Ú nú 5Ý 8  çáµ"ÙÉ©CœOn6[Q4—êgþhèqËŠ5—´ßs—T7áæ" Ú­àÖ·—[Æ _O!À~ø_·B­HyøkpùÝÎ ¿Ã²ÒTúcF5p4îÝ”YÌ儳«Ò5º^gzùô“¦š˜×ÉÇC½Î¯¨0w{¥è³;‹b}ýê þ†uâÀýÏôë4þo„’”3|€?K¢fœÒ4ok¬½x!kïèµ$ížeì8Kr»´UäÎ8Éõ·\Egz°ý '-:{ÏLŽYÍ!K nwµØÃ~º&ÏœÓïέ:ž|ÈSÑß/À*Û˜»cŒ3B‚¬ðl™èn865Xö³šÏb\Yþ?l€š+%6QtûÎq‹ 9®*7zaÝŠB÷½ù=!&²4´0‹Xx Àl0¬“baOwÝ} œbkíaË‚p&¨>p§mÜ{phÌûþï~ÚKìºX©>mÆøešÀÞ“çªú\â‹âE Ožb}œ%³ªoHý’[W°K©Ì-9 ¡¤~À?‰:Üë  ˆÔ‘èvÍþØS(÷s9ÿ…Í —UHè‹›½ê¼²AýH~’PÓ¦'ݧžš­4žËv „ÖÖ‡ØÄS½*wÜÉXÞËо·¤˜¸$»âï¬ y:žÑY©JñdŠÿIL,“©óÉ u+_ù}¬.B“2÷ïÇ‘Š5j§¼… g¢ª¾EœòV#³ŒBØ<¯Øu„°ÄkÛ@xš_ïM½f‡(çn´´ßfë‚ÞK}.~² ý(_?`Bl´÷¢­Œ,õSt2;ÞÌ ¨+EØãƒ†Ý‡¡ íõº¼d´Þ¼Fu¤Tù1äðï$Μ{9TdqÎç|~½[ZŠ{ïÃKCüöÍ71.c¦%%Û‡mu•Ûø UTÕ²6éHôåÌŒŽ¸RÀ¥+¶ÎAlZÇ;ÇÀäáy—ænÊœ ‰uè’ÌUEê ›=†k{-~|~÷ô¬­øœ@A<ªr«C2{´Òyrxs ¯P?Mù4JVðî#­LûS`¥Ì´8®‰")A¾X‹W¡[¥ös&$´q$"-nô¸P4þÖwl¼a9ä¹´*5¤0ŽZ&©{pzD ßq´Ã˜=>^è-Ðàã?Hx*äšœ¸p¶¥Î¶Éç¥õÈ5Ðz⥉ .©<á!ÙgçœD!==ïÜ÷‚ÿhüäJÖÇïq@¶üàdáD®ž#·g;ΰfóšòm”ËNú\#.B\ŠiÕ Ú(¬eÄõjù¤ŠÑü~Ÿ|íI+å×ñK¯%‹ m ¡mt3´1pCyÎ윞 =,±½!rÄ|÷­YÖ4ÜNÁÖqˆxþYR} { 4ö ¬fbÑ»»­dêÿnÔÌHp¼‰³"K@Ç@ºÑn¥-3£[°@eÉÄÙ仈‹”îi'ŽbÉ1)b»>]y]plÈ·h½ q"&ùÑô- 4#…)jÙÐî £Ï"cà†G{ÝV!rbÑÒÁþÁžäý½ÞõÓÔöÊjPo.E*3cÙ˜ž±Ý›ôå€!š¯Aîh’ëM°õÝkí1ŠÂ#ÿ(ÈOÖ<|ßE›M­Ûˆi¨ÜÁn‹:‚ æ¿ òÒVÐg]ã¸ß0;t3Ü«%@§“d¼ùÒ³b¨iŒªÃáËóÿ«šaj¤§]`˜%_;!¦«­¼,‡Â˜žΣ€r³˜’w”ÊɪÎ9Öh s ëDó¥Qd4ÇëŸ%1!3Þ׳¼©©Þ`ƒûä­O»…i„®™3 /žŸ1ø#©(dEî°¥Sº*#]¼«ê9U¡DâþÔ£ç÷îý¨DŠña{ãsÞj>è_&æÎÉs¾,ÅÒM!¾¾'YïŸþÒQ’ÔTÑnEQá ÞßÿøØbì@yç Ï ôªZ‰9±{?œ4ÀÏÍ4”pa±9¢"¿!¨Gío“âã2\¸Ê4@˜ìf¸æ5±ä0ÃH% oùà%@§¢’ä)¤5/ÜùÜì‘ô‡‡%nÇ ë˜p=³äg‘††Ë¥ý0i§Q­-#*8“ÆÜ÷FB¶OCV/ VeOo2<“RʵœÉ}x;_cÇßj= ZWuѲ@Õ{ Á©\ÕnX†I›¢Âwx4Ö£·¾X¸è+×z>:sEäÒßcLºæÊ`5*#ªQ¨5|HJÛþ»UÓR}‹-KN–Ñм_²ƒc¢ƒQ\#7hlf½~£ù¸økû:cXí¾»~}ZÐZå-l¦»Qg&ï¡ßÏ\±µà*¥H¢jq­¶)ïs7!°sÏ éG‹õÖå+.2|R*J2®L?ߢS¬YzÈÙ KÉæT¶ãày1ù:Õ fªd¶= _‚ë €í—áἜ2mvÒ€àS²½ôC.z•|>Þ/Ƴd~wr_ {îZû~ì·&öSŸõÜÝÌÓ3èô©q£ãõ)jµÜõ&Rõì;ì4%h’àǃ™ÅÝïLλ+\5晴[)³z’â^bI´é¤¤dÑ/ŽÝîaÕ‰f8ÚàtäÖ˜äe6…ibçe(…&ÙÕ^bš*UŸ–ý[ÓªVJªïϾŒiˆp÷«lÖ#ŽÛ QÖ”î躛q1X×5Ï·Œ(E¥ä…"”ŠIvÚDp¤Â4¿ãò€àÞåÊn¨0CÇÜa5§¿6#Ñ Ú³ÆP´Æ æÉBšs?±+ÓË+}™žü2µˆ¿qñÐ:²V@è;Í3Ç$.Ißs>0ÉÝ\K°övHc+v¶ÂÂÛ¬všÍ'±õ”Bð ÈÎÑý‚äåuÉNÈÈ÷×EžWÄ 7èhvIwLÑ(ÑeÏKxĵ~|a¨ÌÏ‚£„ÚKÔ\±€«GB¾˜Ý²„¿ŒV¬# ¦©ô*‚fqé)£é»/ú[èèȬx.…sm­¾åíxSo0hÓ¶³„±™“,ëüCSÃfË´lëÙ;Ív?‚Ïv6Ǭ³‘ÆRck{RÁ–(Pg5ƒ@¯ïxvÕתÃÝ]Yy¨T7yõbLý½.‘ HÒj™ŸÓóŒ½B<¸».t3,&ù$Nÿ¸`KÛš‡Í³mrRY™ùHýQËýÞ³ë@þ4<)7²YòK†¹µ¥>~¯E•öÛ xH{=«à måáPÊniå)<ÁwW¡Ýõ³W-ádöUûÜ4â8×È'ò!cnvè7e4¹“’C.ÿshbÎcÙùL V®¿TF/¿ƒ†=!ÊþÝå°:Òz²™w!*6+Ü!N»%–ÛÁ´oކ®¢ZJ•ž”&‡[ÚæWþÏmpŒ¨±×;ÝiP.'ñÍC I·¤%*ÿe?øûÅ=å¯t›°‡Ÿ ^1Ê|$ûÓ½;n1L* È÷ŒuÞV¿Y€·•nÎ(_¾&EŒŠtumŒÇ²=;£)Oè~]z¼q9i$£ûd–jÓØ9<Ã>HFrŸ#+ˆ*R?72%RàÛ»< YŒl?Ó>Û Øz2¼r¼®"ëX“ј„ªÚÄû0ÓÙ³ùÐ}µ!X±•‹þjêÕÒmÇ\êìGCDÜA®»^<Þ 0´TT¯U*÷Ûa²K‚Úð­]ʃ¶üãž]õbašD·ªÖÃoñ8„Ue(ÉE7" Ρ¾r¡žÃ•dÔUý—õÏ8 »m‘×ôSIö¦|œs¬cV‹×NŒÐ]ÿŽqpz‡Ðš¯BKþ4Vãö8/ÀÒÆ&šÛ¢Ðé(÷W; M»•OÁ›o^Tw©?¸œèHÈ¢×›è 4c÷á$J£1üÄᧈáï1©¼ñE²þÎée´Y“.Ô¥Þ’剳eÇ£¨©NäßœˆÏ@I9ÕnmpnuİíY-Ÿý(°XŠˆm;˜% @‹“ùg¶q¶…² …8<óÜ aFÿ; ð£>k‰¥Ö´~57Ò‘ P‹#€·fÖw¥xïš~£ôD a´½Lûºš‹q·þkù›¾"Nxã`›KÛ6…3|Ü{æôi,Ç ß5kž“•/Òߌ¨UÀóþàÎŒaó+uàœÁX] ¡ŒDÏ™ÈEÙ|xâÇŸ‹-øØi ÙHÊŒ|ëú?UýÝç&Ñ9¾®¿Q6a(²\ùNÑЪžx1Ýèo< IõÔ·º<òƒ†F¨¸:2gâÕ ­6ÑPp•ЗY`JšS[õ2hWn%ϼîX)Â2æÖÓ<€ŽÝË모ۻ¨ÕWƘ\Øñ×K%œÏØ×ƒÑè6èìDÀ^<ü}8ʧä *¤²ßšx ŸA?Ø?Õ xpºZ»C2g%<ŽÌp1i¦GgòøC' .XgeÍ gßOFwÿ&q³ìP$²Ìݧ‹[»X·DýàÚd¿Ü}„#ª#ëç]~¦gèî”O”ÅŠO¯/߇"Ÿ‹F‰ï™qqN`Sýv±\›-ov­õ=†ÁØ|»n÷õ(÷ç¦åµ?„+zí™kd£½2RIå¢ÁD·©ÖJS~z3 ]‹÷cZ£Ì¿X¢–Ò´^ év;=¬Å«§ì-‚!0ÀÃO"[¹ÖC, Ä/«¡º«4ߥþR­g9 mêÏUt:°ô„åЈi‰iÄR&ݹ>FñAõ_pr)‘§š&fúù¸3÷êßdáRqº+¦Ë̵HHqi{ ƒSœéT«ª^~;¯¿K`M]gJty²¾ÏƒIÝ@åŽQË¢²gÉ×bÖv<î¯5x_H… šÀ¨1å/M϶:˜Ú‹oXøZ3ºÏ¯/¸ß…ž ¡t·7C›FÛT–B'B¾OÔ›Öb±¾ìúü«+¡WÌÞ-gFÜU·kvx€^*ÙÝœD*.d‘ªeïõV2×JnVŒ´j¸€(¹ ¥à¬KRS}÷ù÷~)rÛ”| _’8]Â|8…ºwfÈfŒ‹ŽS\)_Å‘¼ØØºö7Â>Ý*-{ºXMS£xSA +-$¿¨$Ùä˜b"â¥McJÌ3ö¸xhœ@h[&ïÂÒ ×?†Y·DÊØ$8gÈ2ëÐ6oX­eŠ›Éíá°Ó17—2O¡®dy;Rð2˜XÒù $ÊVÜ]€\#ñíæ (I»ü¯u;f‚:[’îÅŠlþÙ-ûŸ6Ã2·ELú·íô1´cDZªŠ×n!‘L¿Eèp¨ÇY£a%˜„­XÀš¬>ðŠÓTÊ•l®M×B3a6à8#ppŠÙœ7)´ÝæâØ1èó(è$sé×å‰óÆŽ©r­æ>7åÿà¡ z`R]‰}yœoh ³žsT+†>1M’(^PjÔ¿¨)c [9&¹[þ8ÇËtLÅ™$±‘Lf¶e=¶1e)]º\bºuHÕ´åU[„KÙe«rÇøMµ‚4¡nvÞå9 DÌ“ìè)yK”(‹âÐP0‰v@:ª¹Úžl²ÜÞçOúˆ7!L!w±gjÛY¨°M-æT˜ªJ¼µéqæÿ2™ü1¬¹D< Ös™L liœ(a9þa»T-ïx J}­¹%ƒ™Ë¥ó}âhÌO„Ù]ɧ.]/Id‰­À °TæÄæœcFÇG•aã ²+bÙÌù1:QÓ÷µÕ·Ü·ÅÉć+Sî·ëôŒæç¤?kSC’K£®Ò+ÙT?ZÐ$]Ó´ˆ=ú'Ð]‹˜¼ýÉq>’©³==\' z´‹LBÒeO­Au‡=v=^ =ÈÞ0£<ûj§¥q‹Öeü4‘(z<40TÑã@m>9ëJd£À¯ôŠÅ"ɤ؇igËwP1Ö’-þ(ÙÝÔ*7’ÂØ9SZåáër$Ò6JTM¬š¨?{|[ñvfF—çêXσÁ/{戬ö|…u:<ûà3 >¯cr+g¿rg³`©{ûQè곟\bˆk˜UCõ™a%ŸßtK5Q[ˆÙ'Š·ŽQô;WD©¦–Œ›¬ÖXˆ~e5´¥‰q쯭^{µ‹¶y 鲃4 à9pݲy'jÈ6p¥öÌÀÎæ±§ŸÒ}Õ sÔ›»í¤r®~&àk•[¥µœè2]£Z“ýGqƈЗê8¿òK*MVSÓ1áÆ¸Ctñ‡/3¡q¸³Ð”åç3}G$Ìa “N¨6Õ)Oœú_ÓtaÞ’I«ÚQ4»þ˜ ¼h¤Ò$C–±ÿ„®!‚WQ?ù`±ÄØ@2sþ<.¨¦B”>xÔ=Ÿ‰Šå]aÖ.”07zÜ#ûÒ#Âð¥G´…úàƒ`©îš?8h˜µ/Î|ÓÕHÓ´ÅaöëŽZj¤†Xp.Wsâ62‹µ=À=ûq |yOfVß’g`.c4+„aK¨ºnö@!ùäªV6px´ý©HKPótÓYü‰±Ý?`Ç&§X6]”Às]úÉCQ6@#X"gÈòˆIÓÒHOê1¨~™È2œËKˆFJÞ‚ñ(Ö)C´ÿŸ@ —¸IÞ%B?èQê’dg¯–ÊBz!¸ ’[ÖØÎ”5É…º142³œ“éohIÅw÷ŒQc–â€Q[Ï* ÁAÑ&+úKÝ¿Ïzk/‡h'É¥Çã¾¢V…°wîRãØò vì_}AæìG&«Ýl¦ÕkØÍ”U\ì}°Œ]×Gᆶ€ÁRHð,D0ù é}TN1S™Ã±ýÆaë %Ç= ,CMeÏóëã5 ÙϵÞ7p´Þ ¹Àa®ÞÃí ³‚þb¿8 ?mEØ3=êýÍoiraféR‚vU`Då®§x»î&—ÎÕK´ËÿB“‚T]Ú¶qú¦%²Rj¢‹=‡A‰ó(p%£ª*¢¿Z\ß}äÇúå­¤¡ÓüÉ{øïÈû6©{Žúr+—»Î:¬‘g¸4‚çN¨@1V½$ÈU Öd^ß)kp1fN&»ï;7‚0ÁÂæÚü]äÃabNö°‡[œ!>²(§9¬Zw&SŠ·Š’ 3IU<ÙéÒ1Õ¾-¨¶F|Õ–Þ,]~>‰úJ]CŠ}éæýÙ4¾"X‚{ûqêÐ)–·xn8sq¨ÛX€O?{?•c5ó1€€¥z8ùy,€^­Ñ¼=‘}çÓ¯Ý4Œ5ª©nk£y9ó>¬ÞfwÕ®lª±ýÃ/7ꜫ ÀÎĨ|*F_Uªú/ê89•WêB2£äSóþ§‡ŽÇ˜â²¡¥&„÷MÌEÈ‘…\2¦òá¶¾uº˜ÁOˆ¨„åˆUà¨ÔÅÆ‰ÂÃÙ‰IÔ¾TÙ{As+)Rxþ€0'Oˆˆë7q«ãÇ è Ÿð;“^ÃT”Ç.ÍÙêGf95±µø¤ÅVŸÖ6׆¥QÏÓô]ý3©"A‘¶Þú4¬î³½Þ²‰ñ˽Nô:CÙ3ŸÓy[K²ús¸vVÜw€ó½óiµü×íß¼ ¬¬¥–Šfhàk;"éý}ÁuÙ @9$y0qÔÑI Pxb¯PÙøåç€!i¤eZ*#TˆÉÇ`ãž³ríJ¦b‘Âê¿ìxm±&Vgûr8úÿ Ñz t¹¿ºJrIº±Š2õ´V/‡“¤ÉúcæÏŒ$»Jøï±u¨‘üªÝ“E@åuÎÐí„âc+n“T÷Èþ™èÈ¿!“´a!Ë\¼•5LXx¹ù;«HctàÕhᲯnª³¥üÞá îÛ9#"üÉ!&¾^á~gÜÆÚ;®"îýëÐeV  Ý,‘ÿ}m§ ƒ³ü5øDª'Í’´1wE‘KH@[½ 3ó‘Ðc7=ñ šh tÇ.p{ŸÐÛeÂ#e Êy„ÊÃS#_K¦úwKŸó÷|J½#ÁWë0ÏbVˆÜ3•ŸœóÄIt\—Q¡ññj ‹M˜Ó·Ë­ÃlÓsúÅøsíÆ6„ÕÔ+ɰx’†q·xÀ§Ag¬¯ÎÌ}õ ‘j_ÜðF´$ ö¤Š‘ª $}‡'%8UpakaÇó(8¤Ê(ÒpðŠÖ+Tt]tó)EK즜µžüïé5,…ÉqȈ ¯eìQÍÞÛÛÁx1!-=ˆ(p÷Ù\aÈÏ;K¨Bív™—€<˹”œ‡%p[áç ‡“$>ãH’cŠ ª8vsÖèØíùÇùܛÄJ½ÍðëXx 8·µ½'Ú#ç+Cç9ï+ɰÆZËt$¹™‘§¡eÈ>Xs}/’xbü§9Z¾I ‘fH©¬ç»úå›–[ kÄ­†.q¨o·Ôz¦>(ÏVÇ Á  ò±++Œ Y MßQ/Øž²«nªŽu _^"ùùÏvS5‚Ÿ£»XÈ×Hn8;Ú°ËiËÏ8/ÅË|Î.|} n@,%×U$G˜`©—À™óÕ,lE~&p³àëM DÍËboZy„†¿¢AÝé 5EÔ•}»Néi]å¶Ù /nm„ 4I“pò( å^€¡/P©'|†4Þ^~ü-RÛŠÔ6·VÂLŽÿÉÿµ„‚@0ÈqK`OÓçóú ¬$,3‡¶ÍÿÈèÃØ¶?^Pê?Hf†™*«…›poåÍ„Ñasð÷7ÁY`fëÁv¸úÎ’̲Š×fæàþZ£À³Rеo³ÄqÒ2Je%vQêÔ™™ƒH â—Á–Óâ½R?Ô‚ŽÌ{¯Z¶]!Ñ»õ/éF-ѹw'xˆ‚Õ'’­ç%Éãîü‚p$¯Iu¼ì‚[_ -*uá)IZ±•.­<9‚¦m"!\jgŸ`Hܤj„×ÅÏáÆEq(S°B6;4apèe=ûŽš¤p¡>umû<.AÆêýüG6¸|íº"ý?Ö“Ð_T2röWÝöGÌ™k¼`Oþ~¾€2¬têºÍn¿ :æ9çµ!•ô@%„5¢E𽤼¤j®r1+ÆÕ\ä¯xDæhˆHàòsnUä«àÝ5X0¾ß.9—(\ýTp C¹ŒS‰³³^ð›ê]ì9õª°ü)‹a4ªt9F ݠߤç»úµf};5ÞQcĵ¸ˆ½ÊL8¿’8&ø+ † .Wÿ®sµ0ÁßÃ#Ä¥Í^ ×¢K7²_ð7†qp¹EÉJXû‘]ÀòÉ ZCMÊC6’‡ÆVâÛëJ»LIÜÖÐæã©d¿zk,øšþ§þ*½Êvg“c4ÃëµÚT¦‡Øû6Mu‘1Üu¥V R—b—b%E·næBN'[Å(¿Âa&×·#4¢ñN­0¤•ŸôYà·‘cä¶O­ßηÛEõ“Ôqâý÷бÑ6$BÂÜÞ&VÆ]%ˆÕ Å²ì¶Ý]« .h“Âõ›Ò+¥h1~È~˜ªÎÇJÑÅŸ»ÀÑš´²SÓ&Kº‡÷ÎÌö(î]+áõˆcí0jéØ1€c“¹cÚ•v¼ÈQ¦\ŸjãÞ¾“ߊ‘9Iú|2BYÄàñnþ}æô:ßdhvþX žüp~\¨Äê<P´’°œ¨b|öÐÊàÔ¾!*}uõ: O/48î]®¼TÔƒ›z n<îí_3¹q¾FZ‹úoR$.ó³ôaOõÔ+n>ÞkLAÛº 3ø/F±:ÒÑ;ØnéMS9ÕòÂò%a!bÜ2×ùd׎É[Ÿwîų+ˆÂEj­êå9nF¿×ÍæÊÓ2?`T²û¨v¼Q(Röº˜®à3XÉ-P˜V8Îó*ÀcõKI‹MBì“'»µÒl#Š×XßIPk«ø!µß—lcÚ7~ÝåQéxÞ >ÖÏóÒ¨QHä ŽE󋮨­7!ŸTÌ€ÐZôª«scŒê ý‡±6¾˜F΃\C{¾×$å=•@£5 Î×adær‹¨^¾ÛB²¢Û.±„&š¶uúÒðtà™ê‘ºŽ»m¦ƒæyûÓªŒIíF\Û9ÝúŒsŒ—J˜XU ñúíÀ¤{ vDE*íåhcü­:s­¤ÔmcÿŠoÖ¥#¬×­{¸LcTÖÒ`®fïyæúlÝ3ŒÉÇgþ€˜üPñ€ÓTW‡½2k‘ŸÏÁ¯Uð&—‡ $§ å-‚0s]÷€ ŸôÊì:aÖÂŽ†–¼–<“¯Í…šq \¹ð\`;:ð.¿Cqèg]B­`i¹ï¡_B*Ýï"P¨Ïmù×¼qÍO•Éc” qû㛽Æ!”û ›óÿÛzäï¼H=/;¬ÒÞ(CWO9v¸!ô p"p;“(™ÿ9-£¿*hÄÊ–åêY…ö$ ->i‚éó`í‹ìTð‹H½sÒ`V52ÜÞv¢¾<–y±Áøom¶þ³"ÜÃM<€ÌçAX+ZBá¬ë4l1£ )ꉹ8¸ßŠ[EüDŸ‘rL7À5–¯¬µ|ÿÿòXWvÆÐº5©ÒÄt‡ÞÜJ–àã«íÄ"KîÉÂz0ºkN×[ c¨öºuNLNYGmm­ìé/Ä”ÓõÆAªžÍ™-u>z\˜Ã¸ˆ‡íJin‹Œ³Ý,ù5$ÎÅŒ=ábÛtH"‡Z"Ê@ ?ñuÒÊtê‚,¬/3*ßÀîƒQm]„dXɤÃÏ-® Î}ƒÆ·m­ESFÒ-ñ³°Ù»×$A3d›bá]­!šN¶$ ÿ iùW| -1Ö™\d]s"2?Pȳ£¤MHÕ‘·"ܘJF^†é)™c’þ \÷aàV‰:Ðr,mNÒ6¡óJþN/«÷jÊ+ã(Ç¢Û¤qɲº1@éioÿ‹³ Ž»ËÂF›×mXùÌ ÈÐ#)kÚ~NEéBddÎ3åð}…ƈ”ÝÖµ(Wº¢–çÞpÐŽÁ½w×cjec$ ð0CŽ¿`YÆdªÖÅ„*_âsÖav5,‰dX‘üÉl¡d\£{¶Þ»¥Å†¯,²—ù–Á·âR¦v–¾”*¯Â•¡qÊpÎP CH‡&—ì à7ºÙ ê âÛÒ™‰à"0 cKëQv¯|rÖ)®e‚æ¾ïäÃÉ)U9þÿjºõCŽŠA˜¶àEñ–£ñ•@Âì¬+ÞÕ™bùöV·×žL@tÞŠkˆÈV‘¯ý,;Udr^hfâ*|QI'¾ub-Æ¢äcbXOl#§2;"ŠtvÂ_ò¢ØvT›\j9k—ä‹.˨Ëgœœ¦ëè“J»ì—¨‹³á»Çé $ÎÒÿi= }µ-¿÷¡¬+õ¦¼iìú3)'fôG³1¿(Ä$ìqÅûÚ(\ÁÆ}×­|Ö¶·ñù¢iÇOZ–AÉ ìV€  ·«ãàs|<ûrePŽBÎÜß·öîâ„ ­-íöMŠ\8véÌUxýޝ½5z¶bjˆ%Ql*‚[·=e¼ ²»s þ¡ÚØÌ´ó$éçÓte ÚÒJKÁp¬{”KUTæ¾BùB|[êD㸬|ûÈQWv®HáÎN“Ggft x†r–nÐñ(¡l{±Éß•4Ù)ØÎû¿`ØRaA¼ðØœ!µm>%¡nùé8Øì4=H ÈŽ¢m_ã>„0‘jà±ß2ZÙŒ2C"2®²Åõx£ ¦Âl IO"d€ç N®*šQB.ËL+€{&­\æ÷F¨1@ÏJ2½¤÷H–RÀƒý¨ÂˆÙ?N0pÏO˜ÄvRjfiœ@–,v8Ãë`t›ÏÆx:ØÂâ7Q]N\Ó¬pðO.Nè³¹³ÎŸšVêJÜeg)fKÓÓ|,5g·Hu|¯ÛI‹7ÝÆúëk|à0±Ú)ÆÅN‚=Çåçì/²+zÓ£{Yˆl°q¨ÎÀ"H¡ó»`Q sTI­F4˜¶#¨eÖl8¯™èu:Û nÛè§?‡zŸ‚ïãè-ó¹Ô …„@zž… ÷urSb ïrpHå#m¸MJi` ' •èißµR(]\ÔÜØ¥ð°2<û¦ZÜÁ¼ GÓJŽV<ñn¿WÐ/8¾>WPÌ“ÇIVlF—wÙá?[à pª—H¼þth W½"Ñ>}vaÕ±±sS ¯ § BÚóþîXWCæ¥Ãy2Žò¡>MÜÙ@­_ÅH`D[fOXi#¾ B‚¤7´˜¸m¸ÀµÑN&Þî(Ç-‡€Y=§aÇãèl#à"„×H¬­ÊU£"b¤·¯M„Óÿt+6Íf)ÛFýäý’¦†`}¨E¶ŸZÜäáÙÞ°BaØe1ªúz1Ê;fª’“ÈòàÔŸ²=ZÁâU&™²¸•3ÊW;÷ çÁ@I±?DcÿHPÍSÔ9ß×[}}dr ¶U;¥–Oü¤;ŠeԥÞl¥n$A @ÿ} kcGEÜï/‚ü³‚'ÉžÁV…šèÈÿOÞ±³%ê•6öÿÊ>·Kv.Ë=}–PÕÆ€Ù0žÉHïÔƒŸÉ‚uv…×þ+µ|F$Y—Ü—墡¿Üšû¹–£Ímþ¯£³z…k?7ó.¼%œŽZ éé}Âh³°DŸþH„›G+9+x#t=U™ÁÅìŒù»£àt°N¡0vmôÃv ~]ZN]³”›ú{ïéù xÍäÔëÿÕ@û|ø”ì¨ïʈ¸R‹ÉÊ`Õhñ5(ÇMžoiÓÄFÁ¸A½":ÿþàΘ|9KÈx 4NŠåŸ…pä—0¾Jh(úã¼OBx¬Ï˜280i\þ­çé(SOz®WðC‘¥J²z`ï]©¬lëä#¦ó˜¿À®³Ç–Ðúîi“ô‹hÏO#¯_¶ì–g‡¯ sÒ'ŸO ·N”6±ÒA’s4ªZ…D’®ª=Š|ÉnÕB‰Êà§Ñn‘òq³x )`Œš×ꀞ´¢„"Œ|ìØ-SIzLO“_³\y¦ }väbâàt+ija¡Qäb¼ºÃr!­Óh¦Æ=ZÔ<‘úP‡5jø¢òù`s„†ò/*qëLžðdYCº¸¦§W ÄÎÕbÛƒÖ2ka¡yHœ*Œ­áÒâ½1Ø3L ©L]€upPœv§ƒ= ^+w„&‚éT%=§i7Þâæ“Ãì•5KãRf3pkœ¸¹/Va¥F¬÷Cz§Å^`ôòŸ’:ƒ½z1ÃG”«­úܼåÛ—‹Å±æ91ÜÑòØj/U‰íÚiíÂã -¼¹CU~ÆVþ€€ÜªS9€ *s…µŸÍû$ãÇ’Náð/Ç•jˆÂ—y(MµÅ!”Šfø> -3p>:§%Äãé*JýDÑßD$;€ËöRì Ë–ò~M¼Zs«ÄЇøoãÔp¼4Wzke›»Þ¶¬+ =ÙŒ¼ìÇÚ*Y7ÍM×ת¸h60*`ZmW®_ŽmÐWÛh^`ÿ‡“&q`Zõ)ÄH[hGg)z>EÁöÀC¯tÍØ>$’‡eoU.AªoÏÚ+¬ŠZ–#v£ `mõñ~o’+ÝeÝÛ=žì¼•³ã‰A«v´oúèm$.9žû;­fõ…¿àß-Ì›ok3¿zsQŸš×”DHÓ0| wiÉMz²ýØXëG÷ÎcS¾ ¾¤®X:´“x1ÐYVÃ]\ú„é>÷òK‹âõÇ\Âu® Ê'ÂÊ] OÒŸ9êÿI§vUÀW’ªÓuãÙÞУޒêôx¸½5>â‡>Ö™D“%_6†žK,¡e_b±f©ç:±übèX0ŠóùŒ·MQ>Ãwn nX†Y©îºAÀü?)‹S17ˆÏvñ›U}Äo¤¥BqW3LÞԙд°Àó"Éâúµû$£7RGcCRñP‘šh ž°¢¢¨þ†@»@Õ¡Ï÷ ü‰¦QôòríàåëV^Æ8Ü.ø‹Bü¬‘¡¢«WAâ€Õ±1V›°¡R»“Í x™Ì ’Ç"É$¾¨ÿզᡮ”p¦GÉfÿ`G®ñçÔH…¡'®|ýåw2Áã¸Äuþè)´‹3ÀþMÖ“m‘î‹ÓѰäÊÂîÞ­|=^a¹lKÚÁßøšÛ¬‡k[rËÈ«0jÇÝíä½ ÎW-.ˆ©ÂùÔ­¾‚«ìyÐ`á÷=6&@D)%c›÷}™¥ªd Û\ϲ:{Ùâ ¿»ÕóZJ.0¸°%eɨ n«ów1WÒÃɶIT»)š±»()Éýÿl.â(JäaÆæ¡%œd³Aú”6<ô-Dpw[ Kë4ôŸgue5l.ø’öƒ.‡€tWzk­~>1/ªó“v¨ÛבÆ\jn ã–‡>æ"¬°L䬓¨Aš®[¬Áæ…Ü+?VZÏ+ì×ÄŠ?üq9ŸŒÿ(œë¼yƒQIܘ$¼ëŸ~·È5v¼²¬‡m*u¯¾–]í‹Ùˆ€ûV~x ö¬4–×;9„aAºTp:r¶±sñïΕX!3pð‹Ï:Unzk""< ƒ”Ž5i¾“?çÞ-„Ÿl{[[—Õ{áü *—ôí ÌAç^fË¥8w˜j¡Éüf¡ÞzP¾rè<]“¹36ÈV‡CÛPÒá.ÕW"/Èd» =tp‰¶Ï{5“là­ ›÷JSK†ºÞÞ/HCž¹Mñø ŽóT1'cµE#Ͷh†Q. B$¦\ñ \5ïê;¯sÕáÔKûÑöûØÔ½CHÏ- †-ü`õLÿÅ3ÛZ(Ó®º#Ë|ÉôkºòíPPwN¥gæíĤÇ&éF Q|äJ½ï(†Ë›±Ä+ä´ÇÁhÔ(·3o³nU†Œ=Ú.`­ˆÏž Ûã½ï<ð5Mɤÿs/k/ó¹^y»ûz›á‡Ç¹Ø{G!ýc5š’6 %)=¤d $ñ§¤ò¬áœ…Ôy§Ü'Ó—Ž7þýý_€äÒAÁ‹öª*,¼O§Éλ'uMå :v+‡_•× ùlÓ6s˜A–Ùö;¹h°Î %ï²BXÆèßkdæ¤ ‰‘ßâ4ö­ê[Ø"ªÁeŽàŽTÐJÆÜ&«”¡V*lŸFŽ$fÉä€îu®=â Zõ Ô÷ÐÈ=ÂKI ¡-ÏóòPáˆS›ál1]0E>_£0 ¯ÆûçBý°å|RN·ö¦?¤façi°ƒÝv*´ÌcïТoùÐB©Æ0? cÖ l' ûmØn‘¾DÛFòI‹‹‚O58{o$Qå¶ f¶;0)3>‹Ä°*~¦Çz™¤M¤°§ì©™Gr/dó €3tX¡ƒ8Ï‹-CWꕇúØ÷xq­ƒ¿ô–Äj k.&Ùà›ç; Ž˜·›dÝû@[lÕf´x¹ ÜÍⲫ²|KD|ö¯/ñPðfe—8;).òº‡a1¤‡ób!ÑGÉ.3Ù—ŽWÝb!³w©½6=e3x3šãX-éNÐ{ŒÎuÓtPa½zÌ7ùý4KÊ0ÞÛª\d˜%½Vi6{]ÿ2ò_¥%'M„ÞU0i˧ŸRN…bñ°;w„ߣW†"¾Â‹­Ï…ü€½¹ÚRÏ,çuJ‚]¾ŒÜ¿6‰Äò pƒÍVONó‰ÿI1‰[1B†VÛFXfí:É4¦>…òBÒ ª0…ËT‡³R‚Á.DºpÎ.%ªÖdGv¤Ÿ¡²Ë¾Ž¯„ñ:ôÑt« Þ!<£½©ªã ®kÙÁc–CbCÚ~û?Ãý½ÓnTKwq~ñ Õ0Ã"r^‹'S ¼uö!ô4æš }5¥ ó‰”õóÍWðyÄ=žî„F¶nM¼#z¬ëÅgOøŸ O¶>oº%£ kE‚ȳB`8˜\RÈÝÁÿ“üF‘üéz#32Û¬Ï>k!‰­Ý‚8Žà#´Ní˜bpÉPB5–í»ó¡Qö«©c~ܰñƒ@€™Y÷ßœ÷ ‰Ä? ÁwÈ‚&=šœ·QøÝ‚ÏW~aMËü‹öŽýëñC{ÑôyJ”™…›“{ª¯FÇ?›ñÆá_nu/Ø#ç°òá¿á·]‹ tÁÓâ¢õŸ "Ý¿˜ûvWŪè; ç«®‹8̈˜Qà3¢öhäRžËÀÚ¬¤.Øë’c¼½k´!ô˜þÇÙlPß©°œ{Æ9O$úyÑûÈc“o»ïÓÐmEõîó ™ø+Èu=ײ¯Ì«6ÐLÚ(rJ%dyf4¾'.²+÷+l¾Ñ¡Jt÷ûå ŒŸö%Spog$Ì-Îp« !´d_`˜ád‹³ñþÖTñù–±ÿi&§ã¸(8MTQå@ÆÁ¢haB·ò5ÄVw§“݇«÷ËûԯŠW ¿‘!øß–¨ì:@\å&ôІK¸´l(ÒiqéÛT–ºk7¿ú³ò¹—ÄÑ“%Î^Ü÷]ïÕÓ—ïyÍõU—ûEˆåšEµéÛý€((Æmœð1G¬»Q³‘æQF“Y¤UãÌoka¨Ø&oüÍ“¼û½Þ}“h"}îe´¡€…,®¸*ÖÑ­Ì#ÃÇý¹›}m÷ûwåcÏ[`ň%é¥=Fâ5£ Fƒu1ÖgA©OÓÖÂÈGXÎ໇êIªEpÙŠÐZÕE úJ|¢öÐh× ¿ë™tvN7Nµ'. ´]Zؼm V='ÖÒˆ˜é¹DS÷*ƒÔþÃwË3‚ôk¨ÐtÌFR=}‡ÛN—•27™ÎKùÎ#4)Åyl,í|¯¦PÂ÷BÃâ •ÞªŽA‰>é”]½9UºþG?2×ÑqeDp¨[Ž®—£ì—Ú‘¦.ãú#"±¦k*{ß!r½CZøÂ-ˆ»3²]yúŽU¬ÝÝez¯åÜ­êÝÜF©ù·íÏðLÖà“–6%R×á[¸'(d˪écTÖ‰cúªR EÄI1‹/qy©¢¶´Ãѳ˜úho@`ÇÕ½í:(˜û8S<ÇB­ƒüz qÝÝ€ùë÷t!Àþ“^1;€•|?JÎ’ùñä:<æß«¡'ìÏ%DÜ–pØp%?>期M¤17-ÿ¢íÎ RËs¨LQŒFÏÄׯ÷c+7®àó bÚIñ`Ißh5:íõðoõR—,ú…v™ÍÒe’,Ièh.qÈC@°NVYP›àϺ+äÁ¨·ð­¯ 3~#A%Su:›;Ó?I¾HÑ(S ʉÙÄ&Qª¸Lܪ`úóQ-µË·=ihg¿ ×|Þ'—¤—2P¿Ñ–<ÃS_˜Qþ'›"çØ*êF=:2lÞ¿y˜¬ùðæ…ðÓ¤Éá~:8y*ÓÌ¥jD êÖØ‰ª;"[cxr6 Ô=î›èPªUb¼´H¿%ca’‡\ë è×ÄàŽÍ¹<0³ã¶#LYîoQeXî{àՙϟTô+dËt¿0©²øµ¬Ðt"»b}_ÊÝ ÍÀ¼¯°­ª®SxÛwâ–@WnÓÙÐh­÷ZëLô—Ÿ?ÅÌ×è?]OõÇýGÈ¥z5QCÝref\¬ÿqë{«Žn‚Þ™ð2O›ß·¦Ü6öô‘"LGÔeÄ1œä{X\ÔÜì’½ç¸âõ5sTßÂ˜Ž•`ïžÓÙ’åµJ3§×nÙÔü?BSÁ`ªÍž½u*”»*ñ­„޳F ;Î)Ÿ( ÂÙX$¹‡§ÛkNYø— :X6H$¬rúÇÎi±Ó»óœ§#D/_s¨›z•EAP¸:?n´ò1zŸf¥ð”%$éÛ%‡Þm.ÀV¡aGÕ9øèñ ÓûCe¨ ‘òpE;ŠhÑ;—…ª;'9Jì‰Í<;Zuï¦Nú%yäó¬.–2»µ JtÖ•^¦éÖ¥‰ÕÏhüñ§k"a?öêó‚Áv¥óàÕÀ­o€£µãÙœâœüå ÑÅ¥z/JÃxOŒYÝú6•zò&ûžÜùã¢ßO«ªä=l€*Ž5ç;ûŠû#ýõCA—”»œ.a0F>¡s`ÈÈ6o*.°MüB¢Ë¡ƒé:Euqý‡$hÌx¸ìFšŸ5¼£ìò»Ýg‰þC“±*Lªc´½kÇ6– Û­ ú™…ø<äfÜkH‡rj+·®ª¦òÊPêÚ«AÕkÿÂþeÒ½/žQêaÌj(»5ë| ãóg0Ú8S.À¨<Úæä¼ÁpêâýІ4kˆzLÖ³¿ ëͬáRðe{ßâˆhU] Èd' 5ì"=£Ö– úNŠÂE75Èç¼–&ÁL™¢¨ âewä”Å[Rßsdó“ˆiæñçåÎÒ]{Þ^V-JìàBºÚL/Ýòd‚ÝÍ*¨Â¤A¤Ç>=æBÃ[ãáHÑÝ*#Á¸KÒ¸#¾Å® íЃv/¨Õ÷Ýpª3ýQ¯N}Ÿ©Oi쎦—6‚”äŠ%ðÖ<ÿ¨Í· P"É~ù¡­½81–½è{²µs»Okô¦wålž¡ð¼&ðÛ'Ö£<‰0­‡^P)ãå¾|šÝVò+VÝÉQ°¼Óa½5Õ 1èç턯Ëiù$ Ê©Š·õNìpyéý“ôÈPÖq‰Œ‚<;˜TÙf 0¾ÝàËA xbØÎ|1G FŒª-µ$““GºJÅn º¾déšüc\«%"Štš­G]I[EÃbÊÄÕ[†ßC!Òv0ÛÈZÎZHp ÊxpS>…P{ý0à]ôd0Ü­”~7±„´àgAŠØ ØíÍÓ¬…4ïŠéù ´ÔgTô@³ÚÙOE:_\ò1L⇀¿ç.¢Yo¡6Ò7•¯MCêíGé« êTë ™=zl3ë)r}GšŠ”¦H~qUíš2šüB“ŸwNˆéK*•“1)œ¨;_'gÔââ»ùö9’1¢‡L;Wó067Ý÷PǪßÒ§}[+MÒÑc[úØKÍžWtºÍx ë4—;.äIkùv¨÷w.GÒv”v÷ÈסŠ¹Ý’"­™‰QÇY”†/ò^w‰ýK_Î(ÐÈ„pÍÕ°LàvRÛÕ‡¶Dø™,ÀçÓȉo)@çb¦KÀêôÛ*,«uÇ=¯Ìãß•€a}±—ô—Zâ!Oô1ŽÖ¿I%h³}}BpûïA£ƒÃ^r/^Þ àP:fx?JÈí{ŒÆ)Ha³ûeV%â Sµñ¸O1ø^ˆÝÕmm“¨ Å£¿ˆHU ˜&Yòe¡/ä‘bÜŽÚÒæy¡æ‰sPU,€ íº’<…uOÃÿxGFÖ²¡ŠëZ³cGw襑—ßÎÜ®ZØ üè1*®Âˆ—–Óç⃄8ÌÖBáâGf|tŒµ>ç*?¸ÞØ™¬h£Ã…TGÕÓ8Us°6ôÃGÀçñ98ñ8£µTÈhUÆ-#h& 1…·‡>h/Ùß‘WÇ=žæN:{Ü!!Tf \–¶½e™{,Éü°Zl¹ žºOÅ+qâ‘,ɰ2Mö|yƒv‘_H&SÈAÄ#âzM¾ˆç¼7ËšËÐ_ÛVÊhä4Ÿ>Ë1Ë£î“V›qùñCƒìžNÊ ý‹š‚µEêå?éH%8gò+ìeõYtc¨—®ïœŠáÚ î¡f’°²ZRSQ7£Û ö[AØsûEÛ˜ÑýÂWoù>à$ñŠvßœ”V«M/t¼öî’T rš$§Ý‡Î°knš+ És<]±¼º'$-ëÃ/™·ë%.Ûš®è)ä.´—×x{~€#ñ@Άcø w”h*]U6=ª;‹3¹]’–zƒk>žY·ÛÙϨ*ÔaÐú‡ø‡l2ŽTÊ/Åœ Ò<Ò… å–öê¢ðc&m„ŒÁ@”óÚ;é…å“•‘L£›H:Q£²{ -ÿjþÔNä8œæ±i¹Ghy2×5þ„¸Î\³Ø‘£•Ns\Ãd!’ª& ß„Ø X+vïãnËãëD’Τèå &úŠÞ ÑK¡.¡TVž£X UGåîoËÂ\Ò¯9Ng½Ç2AŠ… Q~’,¾3­¡‡¨|¬•ƒ3e€)›VUÃáê…L3FÓ¯Ò6t^¯íWù_®Mœj)úÍìöcIв¢,JÝ#9†(È{¿eˆÇòưŒ?Ú¿âneR¤OÊó9EâÏÀÈBøyÄáúýŽ.8x #®ä5£G4µ–§*À]2·7¢ÚÂ@‰€ªC‹Ï@¼~+ Õ!›W=)Añ2·ž|EÒô¶x»ár‚,Ñ#)Ĉ֧«ä¿þs„Ä|õç^•Gðqp7©ÐÕ̲Œœv³Á6‡v¦×ºMøwå<¤Î”gŽÇCˆ@Z‚’LŒåƒÏÎrÙôţϣh!zú/_Ù&»åûKRZõñoœh«jKfƒÎTt¿@¢çh·ÐÊD_û¨¼bÄp—ÇÄÁ—앵Ð×V´oŸ¹¾ÍïÈ6—4gWch]Ô0‘\ ø^~qFíil=…æJs®ÒâB¦¢Ù‰mOÿ·0ûÉãÙ䆭bâ·)†j}REbð<½,ó~‚±Í€òæád¹%/ÃsíÓÿ¿µ-”:]y^ÎxMÕÉâ¸é;ˆïBcü¥‰H¾–YÀ6Ã…P¨ŠÉ?`”ó ¨L&Øɱ4Tå`ЮJe½2EÕõûl(,GSëz€ŒÕÞ¶5øïü2¶À1· âŲlåcy<ÇZ1J@éqH"„*õ%{ÕWÖ]÷bõ{o«íÅk¼ÇvÒ²C«8²måH¦ õ=qÚïc‚^Ê )-ˆÑåè5EÖ¿þ>ʪjÆœfË¿€ÿøÑ¬õ…ƒ w'SÙò‹ŸlHÆçh‚Ÿ0 ìBU¤I¾l;ñ5•Áoß'Ý Œ\.¥+÷ŸZx ~Üýú\/¯{O!q0¦‘"+"O¡ìoÿsr*„ßMž‘íÞØMœÊø†Ï1`ÉŸ*3\6AŽùåÁIÎmêØtµzÌw ‘Cú Î ¡8R‹(º6äžÝŸ»`ꀳÈt'غ…'¸ ¶Ðn #Å.t$`WlËïP7—Ș¿8WuBp‘þÛüfÛ%ãàŒ8·…smÁ|‘¼ix×ïo ¢ßGWñª„kÙ‹dî¼…«*D¦õ>ßćö1M Ý/Lï$Í—Ño0¯ïhAß‹çù!iË€b{í£¢œÃ†%7SbrßD¿I¹?mï||ůðöº©r‘ÛW¼b•ÞzR!ƒÌ\’UòK}Ïðß`'†õqùž9?};ê%9þúÇX€ZȬ”]ýêt‰/µK¥Ó$Ò±"忉Êaשð;¯\?X²[„`-£'f(àsP0&nYq­#ëÞŽ÷̆[‘§[TJ:G6[,]ÍBZLÌêÅ}Á=h(¤ÍzÆqÝŒ׎ðõ_ñgfYº1?5€öÖ¦¢mÇb»,ÏÔöx§ö€OæÝš(FÝÉdç|mZžx„Ü…,^2*Y`,½ÄTfÜjÕÈ’ZBv@ôŒÌkñsÑ`AßgFì kíÖ´8XmkbØa‚<3JRlÝ;¾²á_ýZÚ99ß ;æ§¿m”•.²e" täÐUù/f!Öÿwæèz¸‡¯KkµÓÃúÚØ@t²Ìú÷¹Å 7Ê ÖŒinÏ eZ¼ üD-4ïø)„rüЧAœ¤ëÀß•Œª>ÒGx·b½zÁã(:þSÐm²Û||˜ûßU­)®Ló›Ï/áÜ5㹈E‘Tÿ ôFöªÕËqÃ%`€¯ôµÐc&öQ¯( c‡Ö¨æµ ‹…ļ²uv½ŽÔÇvt@Ó~{ˆî9æl=d5WÇW¯Ä±ý˜fcùŒS²Ò—$¸„ÒÆC·äl¨®uÍ 8мÀàUÓ‰„Ф ×{GZÑ»I†Ç<§˜@ˆ,ÆÑ3D*ƒÖˆS1’—?LÚ]ˆB:W/ZJ %°È‰)qê°&úÅ 46•[w7×-{¨Ó'ê×ܪW¸KZmô[}?}h®ÌÐÂây(à—úœWÚ§œJòÓÉ\1]é!ûþ¬Ý•š©ˆ²ì*ÐË „´ôÕ½qÜÙ$RØ ¾„‰z•|‚Èkë¼&$—íŠãŽÃÉ¢H8)ÁHH#j«£Ò¯Í«"œzù’?á¾õz¼öußs€É3+àådÖ.ó›ºÍYž=v?¢MìíP÷Ð[‚ïqn~UÓ¦áÿœÞ©‹Öà¬vʽ’9µËb ;îZA7v¨¡²W F[fo)æÊ¦¿^"¬ß:EåÉÓåØòŽë­ƒÇBÍþ¿E%® ²Îñ'U,Ú¤Â7Äþ<üг‰hto‹l,u;À½mתf&]òàFTºÂìÑÌ4GHOÇPäÓ)á$;¿9­ ŸFäì;<hu¶|›Tz`øc‡F0ß+½ÛóEøå»nÖ`Åü•<;G¼¢l§ËþÓ@ƒ~­&^ðY?Hp*TÏ-ÊŽMo'^g ½m{³Âóö ª„Ê<ð8… tëÞh﯃ŒceNî¯Y»m•ºFF¥V¡8׫;T=2c2z%UIÂqä²¥¶·¹œl¤|gF öI¾\' ÐÎ,5.mˆqƪ$Š«ÔçÑj²xs£§ûÄÇ+?–$©¬Dbðvs3×VƒõËú&Õ[|öðºÃ*|Fó"inÚ÷qdKO9­%7sI0çgSæImêW«“Îa·–Vc£ÖEW¸â)xEÑ]t‹¶z>©½™ÇXRá9ZÆE¯˜îÂR³ùœp@žê°ðMëuî#gæ†Ö¤ºÒãüø’Jñ,.Àa–.´aAD…ëoV`ÛÍ$ŸOÊ+†«ö‘¥ƒ¡ìò ž=¦tF^:˜g0èpŒb(·ýéɺʨh²UH¼Tj`jÎñ¿ßŠëWŽiíãFý3æYÙÁ`/b¢TçÅg£ÈZ‡÷ÇG⬠ÊÐþeÐ!é3UÿMIÏ/úè„«€lÔÞõæ›ÊíÝCá¡ßV˜Óãì'¶.ØÚ¢]Ï!œ`j˜ãÃBÀù[¡KtU{µ@ó†l{€ì:à5º;DÝxUÞE¸;Î06¡l˦´lhqöT¬õ(=P—%¢“ã÷üê±…y`cÈ\Ô­i[l•‹‹ÃP%g×f3»çýúýáºîšäb˜°’[~ê6©$/Þb(? =ý¯B3T™ô¤›\úJ娀µlƒ~Ô®ˆ6Ì;›Ù1{¬QV_²×ŒoÐX€öF7Zª9Äß-\õð¾(\@5 {­™÷÷›Ù=ÀD;"¬F>¦‹÷W›†Gköy–V÷äH9ÃàWÅ~yÂ8écKº-e™uöÅóuS)É_Ä{pÁíòÇÎ>U÷ÈLlˆ&d’žC´0Ò¿üÉÓ‚6†ÏU-ó}×ñÓ²Ä^Óè5$B^€Vu߃ 0BP<­6¾²ÈQ˜”v^“ÎÌ/ß@5x*Ã=·Ï퓼ÙçÁiú%À¾˜ÿ¢¾ η;é_~œ‚ý:3Qý]*ך·O¯1žnò@¸álwSœrÿ(Îë÷«5¨à|xÈËŒ£C®Í®LwG¢¹µ„e¯Í„¡ðo`˜n¼ðþXe<¼¤ŸjÉð»úü% b®É·ÇµKAñ]¡„±RSSî~¾ÍÔÓåziúÚqÎ8ÐUOgT·£Ô*%R-E]Žd°ºÃùêN¾Ib=òR1_vÖWõíÑ+ÂhCRÇ¥Ïç<žÐs†{ßgÆŠE¦ †ÿò›Ôs;9ÆÖÒÛ@î…‚¶ú Пgf˜éÒàÐŒ÷9›+0î]ëÛ¬=J*³œC&—í2þyä%ñLÓk˜.µ{õ< ‚PØŽÚ'™£ê.'ZŸ($¼9f?®‚ÒANÎâcŸ(is«ò…¼ú_ϵûIÉi'b)U åƒorJi #ûg€Omç "äýœ†£Qa@1F8£*S‡è2"õ›Æƒ¤B-tZ¢×41*ØÙa©ôÔ C ÀYw&ÚlzÅ}‹öUu§Ú© ïÃ|URúbï•CU½ª½*U7!v!‡†·Sšz—Ü{÷r–Jëd‘Až¨nçQ±–iK<ÑÖÞf/äk®~Ë GRn^¡+ i†R-Á¥m.¥œÚ¥ ?ϳùÃX8 ñ}<ŒÁK¡ÀU±qŸA> îÅ {€;ÄnIô¾jïªÎ2’ŸTbôá_±n™z¥Ì¸~ó¬ ¢@þ. :#ç»zÙ”´öJKpÍR—YÞï/ªißOÙ-‹Ÿx©š¹“çîbfÏä&Ý.©‘¿FÕ®j[¼YÍ x lHvI¿Ñ°x±n“DàªïûÏ3?Œþ÷q ÆÇ%ðãÎAºRîœ~±¾ÚŽÛ…ÏÊ3¥ÀlE®æ¥[d0Œ¡VRBÚõžÓç¯†RùsKGXN«G"6ß=” ys€¯;Ó¸î¨å/ ÙÓš­¾Íç<þåB8þë^ä ~ ŠsT!TáwkÞ¶1 OØ=ìr¨t{pMLáL‹wñ—2’úJôÙðÃOœh:3AD¤S0ãÊO“4ŠH·Ã¹ê.¿Ä•2ÄxâF–’ å7;IGùä,èÁ|ZÈ åº=ŽåÏ÷þI3üP4«ÒÒki¶Ïz’Ê#¦¸ G.zx䯡yw Fðëϱ9Õ2+ Å…wÂ?Ö=æòY€¼­ˆ°“žÃ›"ŒËˆ|ÝËyžüËÖõ4饦-´ÕMÌêrb;à On0÷Šø¾Â.`ÊÛâªa.0CRœboWrYs?}ÿK.nn”¸èÔ=£ÙàI°•Bçƒ ÿ ¶dÉ)ÄpCˆ´7¼Iøüþƒ“ÈB튑¯LÃÜÿØ— Iw9@. Ç_9œØ‚Ř*x̧$c} |…;­£úoº!T‰¡ Ço¯“½Îó­¤…OÅ$ZºPa reþØ`È 4¡ ¿ \±Áe÷î7+(L)—(æ±Á¶Õ(:ùG-޾ªs–hÒdZóÕ;+¹!¿µG¿ú–g0F?ÞEÅ„Iñ+,•Çž‰„9Idü†ë½åY²Š<ÇC2sŽÓžq1us[ ‡Ù—/Eá˜ÇÜPQTÃï3žuÞ}fîŠAVç@†WnR×X²Þ¼z3,ÏP_A ¸¯«~ž¹­nóå®à£®>«ùÓná¢Â2wU[+£è"}Ô£`’±xJÐiÏæ"úHì­"2×üŸ†ý=©O‰„ ,ê±s=äÀqèo¶’ÍŒ—Ç ï6nû'¾ZÔ8¯ÿ/Á÷3šŸ-Á$8Pj03Ík¶ò:Ms¯ÇNwF‰ÔË´ ÔlyÔ¡ÊvX‰YM„†! ­ž¨ #dQ;:ÊÎø{zÃ6v= ˜Lµôœ¦Ñ*Px¹Sæ%†y|«ƒÊ©Œ/n*bÅ¥yÕëón\u|àÆç þÒL£‘2 ná±qÓ M©bµMŽ=9äØ*èÞhbÁy;ƒ<™Zj½%1ϤJY‡ÌÆ+KÐOlâ̼ætû+¦rï$¥ñoúõøðèVô7žZ‹±;¤ñ¢†r·¡ ú‚ÑœÿŸp–xfÍðAæ{{’E|^=á@ÊŒ¦¨Ó±p–¶ÙE¾‰ã6†*úØe2ñ„3Æ¡Z.Às\½·Y¼·1’-Ì—‡¿%|qù•öa`ÊÏSJJ˜öÊ/仔ȗY!Þ†KÀ™ùóé^L|ÒmÜ%éêÊååóW?á’p¹€={ư§YÕ{5ÈÂ÷ú¶äòÙ‡»Dî+æÓ¸áîj |‹;ñ¸µKüþH‰„‡¾ïpâÊâ3¼D9¤‘‰bcR¸ ðÅ €_ß iQMfUy)¼q„1¨š5fÿkL‡ä¤%×”ÔC¥ ¶ŽŠ9.h§Ñ@Dz'ÁÕŽ.Z©Ñžm ¢u÷ȹðrÄ…ÇiQú­öåRïVòµulK k#¿÷g`‚âM]Ð`þ>R„‡*XryAL&>†ÑþW¹&ÎsµfAÃÀŽ_ƒPP8…¢…äFTeÏÌ·*<& @Ïz#»7¬šVáðå[ÜßI™¯¼çcÏ_àQhÆ®’s˜rŠ{"ª€h@³çtÙØ%â$?¢,ÞKú!ø}ø›ëë›h6AÛk‘Ÿ¾õ ì+ÝOù »VâÅDÝ2§.Hˆò~ÏPÀ“u+ƒ>ȧóâ¶0à<"üðØVZè§›þ—ËÁ@‡¬ÿùt ß$ÄQ{Â÷‚ѬetøþqÖ/×®çºÌØ(Sÿàm¶b"^v†•…ˆ<Ùq‘|Rû{}XzbV¹9rãUSî¸aWcEï**Cèm„ÊyZ­€ö©8¨°-ù‚Õêº7“Äê„õ×#ÛM„_e&D½;/J9vmR—f3बFÓ…tgBz{×]³FPò†°|µhwÛ{’¹î¼`òþ¤î(D+f¸j"tP¿¦æB¿‘Zj2ŽÉ÷Ôµ€K5VªxÑò£P½.P=EèÇ f׌ý½y“¡:HÝ#ÑW’³*t)Äs¨U‰§ô”´½èö×î»2iµ\*ß¿ÅïH†poEÉûrœ)ãN­ülù£HŽG:<èð±¬ùŸÉ¬?äƒÙèÚv¸A1ÙiÜm¾m_ !U‚N©Ð0B˜F¤Ã¦üUq±U 0Cü¯mi¢¼ :âö}1뛼?á,‚l¸àŠ¥Î`ÌҖЈ4Ys 0Cŧ[ÑXuˆfØFÏ*t¦H. åýœÓõ뺹“Eˆ•嬨éôç_ÛkØ}}²î€tÚÀŠZxѨ3ûŸ/¾5aÔ ©ížV­îòÞ€N´gq“HÅc¡«‚ލM#qŸI2mŸÇio0Û·§Èߎ|f}knDÍœ<¾sê¤\!Šc‘ª&IÒr&@–RÅÇÃ>^”‚1¢!ÿy$©ÐXé@ º$â,?æÓT|˜~ÇÀ#ñ㫱ŽÏiÉìJKk}ºWë!x‡?ާDú?wÑ$;ëJ^€gÖØ'óˆo¡jÍæ†§=2E={ È·0Õ©‰üŒ£#,D:æçw¬轉›læ"×Z-/%mN´ýyã‚:9[y̽WÏTKÛ'ü´Ç h)bt¯CÕ "Ï¥…ªí jxI>mw–¦¢°$MÇœëÖ‚H¦ù6Ϩ˜œÆ1†üÒ¡–A¾,Õèë÷/<šA^Æ!È«0õ1bÍ"Ÿÿ–Û‘¢îü£6ìD…ý.‡ ·×´9„¸B$d€Þv{d€¦‹y4^äwc‚ \fƒüSФ’ .´tÄŸbq_Ñ6ò&è­‘Õ¨qmYýœÎ¿õ¿ñJU#„0ÝèÑo}ˆ±Ìr¿F«¡Dè‡Å¥‰(Dy¡nr¹ªÀâQJKmBn®?EÉ{Š1ÒÏÀ0¶‰—B2Â- ÍAÐ9Î/VŒ!6PòOå¾ëЖ ä̑ʅ#å°þs‰ía?åa¢µþZØoÛMuŒTƒ.ÏÒÿ]ËQJÍìî7š¹"ç,œ]bq¾Ì¦æ>ƒ7Â&ü¯Ÿ ya?4&è(è- ‘øèihš<óo~;ÚÍW³ñ€¥÷?*±¼S¿ûÕªŸÇ•¢œÆ;Oh‘>;”œ ¼ž&y ‡"ÕNt…]`Õ³8) wËãMt„¸ÝÝÑ® î—7<0V×ÿõ@>do&Á(6¬Ðú)Y8ôE@ìd‡pþfPÖ⃱¼WO^ÏH6›5=#æ,ý¾Ê3,ðIaÔ‘“z¤¢Æ$Œk/]Kg"«<¿M ÿ@žÈ˜Ç¤ÄIƒBr±Îî\Z+À…×U£r-è‡÷=nß]0.êþÞ"|7u_€ ªfØÐ™¾´!)"ULOþÁa®2µ¦<“…|(øùsMšT;©‡¥Gd"vüÄÀìÀ}a3×dÁ^ïIŒ#òGE¤Š¡þŽDÙ”Îìî¥_Fp ’kX •¨ —zÚf,Ã)ààG顎mng9KRᙣéGR í~Í)Š'Ž¡Iªê.UzjÒl ªkoÈtQ– Å}ÉÊR¨ ½žî·Þǂܼ=ï5‹ E„;b0‡ŽWîcisóuLt¡<wN†‡huôÕdž u]ö%ëû&ÊUŸMêì Èp2¯8NpÞ“ûAv^K¡£`iø0ÀøóËBJ7Gp”i( ª"dþ}Íèø8Ñ4’%—Ñ@v&Jú“—räÌ`‰·5/–WT2+Ï*õjûº†2ÚYµjô¿–o¸“ÌïîÔÍ7®Fip0Bëãª:þkìzøí0äçÃB¾kH²:‘äÔSíÚúŠŽÜÃH†¦Áÿú¾®°Æ†ù>Ž}D¿AÝoû®Ž›IyÌkô×¾@Øö89tšQWü#ÐÍ\¢Ã£qgœH¯†§½Ø'«$cc”W?‹*dãîÁП8’€þ‚ô˜ÌU‘yî– —ô¬¡îßÖ04hÞt¨ñÔÙí ÆZýÒ$ãŽ_;Ç^F`Su~U\aÂk×Úx2n¸ZQXéÜqËŠ ¤…Ê:06\ƒsWOÃP¹§ý;>©'Ö0­UÈ'©š¾s1ukœZ|éP'TK×çF±ðTT±¥W@ùæœV™«2ë SËÔìg“‰¿ÓLE ‡´ŽˆÚŸÙ•JÀê >³mݘŸtö}õ7c‚ò!9E0)Ö€ )8ÿzˆh¶q Š þ{¦¨îP'qlâ8›ª(.‡áNûxd7!z7‰c¤€"óuEhó.˜g¹Géæ}¹/¸ª`‡øE¬ëÁÑIËû˜ŒŽC…(–Z…\'µµø¶Û’Œ‡!ási¸rV‚°Å!ï¡´Û!÷-ûËaÒŸÜý„.̵[§  º¤Ò†ùUÙß‘Éåp¯O—g†”l-cÅ0o¥˜c"ïž>c&Ãã»M„ª¯.¼X»@óùÃö^‚ Ÿ)vÐ#«Qh»á]÷wšö/æŒjôðN8q8Œ”8z£`tíð†µiûmøA‘übWl* [ÏÎ-ÖœžØBÑÈï°ž¿y,™÷׳“—3¢ÑÅÌ›º°7Óp¡ŽqÁרåàW qïkY]{†×›®e„»R¶_œ³ Ò`u°Òðªó6LìI#[…/rÈ2ôŒgÏô þ#O!vqÜã>¹FÌñÉxÎõ 7z­ÞŠ×™?ö–¼L äËèP¥üㄺeô?ì3`ëDí84eÝRT˜-f?r Ùµác¶_m8‰b¬×^€ÇÌ!0½nÓP¾Ý„§Ú'Ìâé'8@M‡M2qùÄ”_€ªÔ¡ ãĸvýU™vFÎ$ñ‚&&¡mEµ3¬ã·H«F–ðIÒÿW'Ùgº-Ls }#ÓÞ®ÇV˜§äC%c–/ áœê¥üÕ‡Äç(d8vóz'ኧ}•¦T~/GÅ;+Ìï'X3Öe·3?8 Ù•Eá¶}#ü‹€ÏÑ«ôqvßjˆÈZ…)î p×ò·k¦Ug ì†\~ð7°ñK±Ä †ÁÐ%-;uቺ—ÕüJþSÂFЂ>Ó:÷w®F˜Hõ¡oßQoø¦ì‹&§>OF­Ã|& 6O÷€÷aBU`‡–éj$ ëÓ£ ƒgДá/H7![Æ‹™üiƒÞÑ>Ô‹€¾'nR#ígÜ[†~=ô õ =‰.4a†§‚êNO&‰Øu •É^üöi_{{;$;:ÛAY4•Ä=eErgí¨I&²œdIkÉ:Ñ•ïYuóãQm=I°ÞK"Gƒ?:AKÞ†AoZÙz…R½u,oi¨†wTùp”°¯%à:²ðÇ–x˜g˜ K«0dROÿEÒk.IK§K£ŸzXÍ’*7|ØÌ»ï »À nÿ$kâA|ëˆG8¹ÄTâ¥ÐׂLƒ`ºŽÑ­qÕÑX{ƒ«r÷Ü¢>¦‹ b9ÃÍãe¤sgêðï¢T@ǯpa{€9gíŠ.BØ¿5œ—ôº± †<!õ½ñäë†VØCÝ÷³(wwŸ¢¡m VE^öUURôšnàS~Þ™6«Ë4*»+¶Ñ`µ´åÅÃM¸cT ÐÈ8 U]Ô~2MWªŠØŽ2ktµžÀÊÌ*gµÈ*»o“¹ND@LSJÿáÓˆ<ÞH°ê³ÂhUBsiïùš®¾1­Âë~©T=bç±õƒÎ1V))äZÕªè+ðevè]Iyœ)fïïÌŒ ˆܡ¼¯9d YòŽWqKÁþ½5ÅÖr8veDœ¸ÊzmF‘ƒïÈçš—»ê;¯ê&‚õ ¡>xøŽFÁ­†èŒ4m¬HÐFâë*_HVLT„LÈ#:B3²îHË;zÄ=:Œi¤4Ñಋ÷Ú˜À×pµêhÝd{Àï´ñ÷ÉopÉ3ã?(@~h=}‹¿Â2—-¦Ç·µ>Úˆ&N˜Ÿt} óla;¹ ½© \Å)R´×|‡9ykº&›Oo ,jÕ4ƒžr2!oµ=þ2¬[|ÇšËê°èæèáŒK‘vÂ}UPëV†…¦cÌb³í€Àº˜lj-ÝÖ]¥LèHÍb[&AWùz¿±Õ 5ŒY‰ ãó¦ÉPdZò¶³ºIÔq*tÝБ=“}¿û ÏAæB®1zÖ=EeùŸ•…ÐÂÝ ~ÞKi¢‘ZúDY挚ýŠÿÔªØú»ó–fIQéì”zδل¥ì~”+4d$XU'â¢STPE. =kïýÿ”RÙ ;±ÚêЬ!G”Íý¤2ϰa1ò“9<ËÉÿ#ÿE.ˆÞ+kdMŽåµ>›7g.¨°ˆIìÀy¿£ï%|v"CŽÁײ,im~wA 6Í1Ë~|$l×oj÷Wi<«“l}z-M’¼øc¹®]Y7LGÒôZ™7†›B“?ÈÌh1™tKb¹Ëã|Š"Ž}XZëJZ. HúãÌXŒ³aT½/®Ê~éºIïäE›Û=S~w¨†$)ìtð»šõkd¤qiÛkz·œµî\u‡S²/Þ9)¦ÌŽÆýkðœ–9ü4#™¾á€“œ@¬óÈ{6ðõ‰uy }lö¡Õ|{z~j1 z¸H°{ªÇàÔëÐ`òƒ¨áb×ï®[ i•ì®§ì'8ûÀ~"|>dNwön”)ÿ" 3?3wÜ‚WÇ«¥P àW¤wô{@P`ð;°A‹ŽTÈ q!Ë“¤ì ­ð­UŠË]j¶ÜÉ—I ¿o§Î]HÍtÉ‘*“,ìù½BÑÿã㤜ç5¢’ÄðF$E‘ !5Ò<ô$ÓôLGe<¾¥M‰Uƒqée˜TØf/ì‚“±(&LºÚgÏÊØ-"h¡7-²¬ñ6#ü‡’>mo¨¨æ—ä‹ç…mпfž ÏӷܾöU>šÄEƒ¹½ýíqi¿XR/£’a‚Qañ×Y|ËZŒY³@_YZ™3Ë·,®Fµb° 1 ‘±²Ú»`»v/ÌKu>(‰í˜ˆûÐb(Çd¬+ hº¯Ú)Å¡@àµ4aðþë­®K=ÍN9Ï@:|Zè3*á×%¯ƒþ,T '_”ŸÕÝÓ*UÇy’Ð.§°Ô(„vÜ33M¯ø»¤'©œ’3ä,@ÊXχM^2:º(ÌÛY¬sÖ3¤½7€†„ÕhÜ4µoŸØ>(µæ·¸+(çÚCmëÄ Š Õ ½:¼PJb ÷›?V3é[ësú‚­I .¢ãžoìÞBмPz÷&Ük7~ZR«É@ìïÕâ˘Þ<}÷~"¹!1!XÝ’0wr’EÏÓe‡Ÿ‘id¨_WWðÊä Kö°¿¥À€àâv厔£’*% =e4îUã×[8£•)eý¿.žâ¦‰˜ÜG˜À”Óv@yüÏg”ênÝ×ì$B1—“ËgˆÏÜ<Ú:¾šxÝb7wF¥yT'×8ã¤?”Ä*ÀçÐ'3¹Éè¶‘V að6ÁgƒÍú\~Ý^ýI©&w °ž¸É±¡qm£Ù>ÜŽ mQñJhdášEÀŒ1øRZ"¶¸¢÷>öö¢ë9êPøßWl¤e.ýŽqמˆæroÿüéw’NõÃg+g˳~1©ùÏ FS?õÞÔ·Œ5³Ñm¡ò>gCJœ¬–©ÃFÁSúAáNóàÛ²GYtUp ˆÈ0¼ÚçFüÀ‚;û@hâp5A{]6ê”+÷ý›BÌ\Q1á¶Ytì2ŵ›Â˜ ý·´"Åרu>œV¯û¡- ãÔ .:{&(YúÝ|™…¡ 0Y!/ß°ÌÎM >­žR½”ç+’Là„9è=Ìc¾ÉlHóߺŠõHŽšNø†Ï=šT˜[suCÍASíyEÍ×eÌ âæªÝÚÙe(¦e„‰„A2ûÕF´x¥¾úÍx ‚‘ÔÆbã¶zœ!BÒÙÏ\wù¶ÃwŒ¢Jz8Ü̺WV^b0úol,„ÝÉÔ$϶Ìjέ±›g+Ænð=ú¶­TücÆýxx xs7€`{½ûQu쇥æid(TŸ˜X<¿í͹¥í”ÛÁ ›G©ŽaSPZ:u„ò®;Ñ«zb–4^vdͦŽE˜Ù; ÷‚æz{©\þůLhÑÓ”‡­ËLƒô6E`B¬A1 qî5Mü¸®¤z©qŒ~vãg»šýÊã5m×'Ҡņ|!;¹[Ó¡¤ü¦OñîvžÖ(’å,Åÿ§øÎÚçbƒî;^DÂ5XÙÃa˜n±­Ñçàü| ÖhæR$¡oÌ\>k£âÉε%€÷ÀµùrlÏëZîÑó§¯ÿÔÕrTê³Ó)Ô'2¼Ô˜ŸÈW½âT)Ã{KxŒ#ð5íýÒP}Bô½­´.kÒñëÌÕ1E«*‹ANƒJd¦åÚsßCØ'Šê¼ÊÚQøúÛÖžÞ>zÕ{ ‘hó ¸xZL:"?½iâÌA­Væ^R¡Ét7–¢~hßïļ: üJ/òµqð~¯|ÌâÓ‘ÌÞ&x|¨~IFvrM¼7Ť»ûÑѰ É|nú,wZàR Uá”Ãéî¥1„/ŸÐ…Öw  #ƒ S? }ùuN‹c-¥í‚“t—ü¤ï“ãm«£þ‘TÔÐM[=}îØ“{¦›&ý$tû.sJfè3mÉïnÀ‡_·&ü2_SbMÚ“á)‰à†‹íä¹DßÔ˜ý-œf‘<&¦…F!»0qE÷¨ÐðÕû(˜Ì¾Šó{Hà?}æÐˆô”6ʼ°KØ[I›Ì>[ø´Â(?•ƒ ÞL8äò•`v€¨œt“aªVy"›üœ¥¯`yV â¨\Ÿœ–ýè ®•Á¨<μ?ã°²ÀN &è½&¦àÁ#QïŒè ·Ö`\L»féTŠg±æW^ÞùrጽàÑž`Jƒ=¸èDݵæºý1Á¬?) çDá×rPà7çä¸ëhŒšGH4 Ý ñ÷ –b儸qÃþÊÞËÐÖÁ–•iÕ¬‡æð^¡ÔCû¸(ä¢è;šô¹4ÀdÒÄ#x [êeyKª ³³j}ËæaÆ$Yλ^ž½Y;{Y¥YgqË̶7&{®a/ÖßòD>üܧ ¸oEé»Î2þ|÷¯…À¨àC–C<œæ-ÝHN]søÊX¾$‘ªR‚õâ<»מäìDÏÃ¥oò:€sjlÓi¡¤Ú7SúùºS†19ÛÂfÆ‚6ÀÇoõTZD²˜B9B‚Æ)Õ~ëÊÉwl+‚˜.ï·@´aÀŒëœÔHG~BüB̳°G•×ÕôÄÔ¾‚b%Èâ¨;ªÒL¨ìH×ÃRk“ódªß2€fí[» JŸà|kÅënœ”Û’•­\?ƒÕãÙzÃîR”^à 6œÓ- ÝÚ‚ XZKó&ŒRøJu8v3kÖ³H{‹ãSW!Ô Î(1øG¾sto{ZH†Ÿìõ&ß™² ô£½žÆÚyYH¹ËE.É)mv§€4;qÈ<>x\;W[u´†™Íåî¤ê{sæQ²h«–ýµDm¯¨ûo„ 1ùúóÁøùVÌš»tÍ“c³×HÆŽºM±ÔИ ¯Ê¶–ciCú¥Ÿ°ùåz9õp$ŠxÜË.]Û¼ænýœ<|ºÉ7[Ê»·$¹žì3’»«xÔ‹cŠZoJ#Åy%÷·MO$âoš»5òšûz™Éa݉v®/Eèv?dQ(™|ïËjè“k=R>±a*° ‚ì3&D£] †~œ¸"¹þˆ”ùùídÒ“êw>>qïó—•ö‰- ;äø¼»ý™É¢»DÉi}O‚¾È¥\þ:&SvD$‹)î*#奴ÖýÕˆ]·+ž‡á‰WŸ¹êDX˜Ü–ÛãÓ—Æ É†©T>–#e’ÅÖ ÆC‹ª ³§ôz7xur`óùü¼Ÿ†CèU˜ã±çü+¦D[ÔÕZî÷þB4ÐTÌ™8Ëq¯j;¾ú­Æ»*w•k³¦ *“|J ‘ÁéyÓºva­,üà¯q›è¿>wâVS¼ÿQÖRè-a’¿=yõÑ¡0bH2Ësh˜èT¶jø”ËìMÖ¸³¹Ý¿2šOØJ¤~XÄøqñ1NX!’§.)©q"Ë}æÑÞ„kz-Ó–^P±O=¡ŽþÑákÃâ$É•!ý§ìÝWÊn5¸Jº5üâôØZæñàê„LJ¬õùtúTHKÏsÞDLsª'wD¤ÐWüj ž÷9 (úÏæä¾Í@F¶µQ…m?Hfw7jXÎ5Å]7@¹—T¨Ù¯¿«—'Ɇ}:Éà9·¡Åò)ÆÄ€pÞ?¢Ü¿&ºRÿYH•\ö&6J Ð+î ӀÎíY$Ù¤g^èÿŸ#¹"s«Ck(•;¡I-©¡¨?^Q’ ­²‡çv&•˜Hô|Õ'Tà éV·}Æ»6æ'û2¤%õÞ":-FþÍ¿Co5ñ¹‘*y?îmd¬ÓHªE]ߢ†ÿM_=ù”@ð¯ècs¡\}'Çÿ<ÜrD=Ḯ¯½]Nî>ãÍÅ!Ï1Ø7%ª#tØ·vsU``‰™Hàz¥^…996NÜ¢(+%GîÑ´BùX|þú×Ló¯n­\ Ãé˜S¬o¤R¬Èy¥€Ó~N«Hg  µ2¼U&§óì%§²§7#Kýâ÷õ@7æBú~› Q1aW³š-·‹§èMú£ÒeÂv;ò$&®(Àn›k$Ér±à’L³ôÛG¸ÅÆ«žúÒEWô[~»Ð8è9pΚ/ YV•)§ºÝˆ]nÝY¸ª]ˆ­zð"ÅXRCæxý"÷Òšê‰Ý¹zYé°U5Óø<ƒ¤BþOüÜ<Ih…bn^‡ôú¹áý|Hnpe_=ÉuûvúÐ,«Ö··bãï Œ ØZ²1H°‰®o·dê_¢K -Sœ¼vz¶Ëê´§Bü달±ÃÑÞ[ts7‰ù·‡bꕳ–E5LØ•'©†,!vrEVj0‚ëz×®û–iwÍÞ# šr®/ë¨*uæ­äÇ\O“ V®CÁ¿DÑòÿ Öö‘?«yü€³É’‡“7¹e&¶m¶­¶’_ƒLÄP,ù\3X×5•åϑ϶š]GÁIÁ»«Æ–,ÛÞÅã†za9r•ŒÿãõQñ¯OÇ>KtžÊü¤1Ò˜à/­V>øq϶¼V0à³¶•Q&IÆÈ’WR ìê)±ÂM0GN{öÎók ô¤òägúÈó ½ ”Ä\l ELŽ™Írws³¢Øì_.´üôÅ™”6eߥ‘Ryƒñ ®¶3*£/2½9^â®@B™Á÷Çy|ùô@‰\QçÕh¸ïp,jºµéàÔèu²xp'äÞö£èÿŒöÉÇËyÝvc‹*Qî–»®io´v¨xa©énA”$«ÖIOJϤŸwf%O1Ì¥óþót–åÒ½!€ëGî¬ÿ/,¾ä„ÆÐA ÓoŒÝs vHœOݲ:R´Hepí®:gC§Bc~:É[1wcÌ7mËŒ‹Üm-jm8=è¶í(q -Pü5ë>F›{Ày¾Œ{ ;îÚKH R…¹«^c{ Éõ¼×8$dá%kÕ"ß{ä‘!U 'w}s5”FäêÎ"ä~ºÏhý%§½!a¡š%;¿¥‘ÜRìá@E®ùBÊú2âúnœÑM î.Q7ÇiZ»åâ"v-k6ú]HSr'gáÂ[ b­ð*ŠfMß3Hä»Êá"Ñ?ØJÔ:J¨-›J^µKк1B×9H!Öàâ«E–K;{œ(ÐGJ!ý˜~%¦3¼±bRÿÂÆµP·ÄYÝ ýàZ—8è"œâþ*‰¡9ý¤×„¡9ÉšÂï:é/úf%ÐÿßgcF ˆy4¯pâwÏÖ…;¦¿iú 4`UÏsŽÓñbÖ± ÌÇ&Ò—>S Ã.ÉØÒ1} œWƧÛúmζî(D†@|´A™vÓ ç8ÿ}ý‚ÝðWw¯Ñ‰»6ôáJ?½ozYÇû}‹¼eGÜ çôâk&ÙOÐAxzØî6MH«qãÓ£ÁVº;ÀB­D‡UŠÝÏñÐç5`-ì…ÍV-ÖÒÙ×$R ýNHnÇWœÙ$+QŽ—c!JPäK¢¨z~7GÞ¶Ú¼$\®®hæ÷,·fúÑ¿¥ïpÁ)Fg!'ëK× ™ÆÜòýD±’òÕ싘…›ÖÑ©^QŒ'ï×ÍÄÊ”ëžb’ü%ƒ°‘"»VöÏñ‚gá6Ræ$2èü4yHXðÏÀ\™Ó £ã‹èêá\À²›‡Ãƒ;Zh€oY©³ ?<’Äâ–rZ¼ŽËfd¿¨ÛÔÁÀÏAH±Òò¦Ã<ssMF`ÅúÔa{1Ï4{š‚·ÙŽ!ºòÙ¸}šŠ‡IXcܯsýbŒŽÅ~ì·t=f¬_"3½Hœ˜²hôxeR¨ÝÑФÕEÊ`_¯ÉN·ÝI·sRIp»_Žä"ûå´€;‘Z¥…@(Jµ«…+çLä*Œ³^|6-ìQŒ_Aª[ynëõ½AWýt²ýÉ.n&CǨÜk‹M¹® úÔW6ñ¼]ú"Pû„Fp¯G°,7Þ›š´ª-kѧ$ïNbï°n¿ßÐÆ¯6×£R+Ýõ, Е?YAmÙçžéîØb+Ûí¨iã†ÀÀÇñÀ›0œ••—ðÚø:+,àͼ|º â?À 8ª»ßÁ Ó6!O2†ÔÀÖq¯F§Ò¹Á¼˜c yŠeQR´4‘3])¨=UÇåndþ¤ØIkòµûLÂä0Oeéï?ëöÁk Ï$*[5(>“ï½õG¢ò¬2ó ¦øš*‹žÄT ˜² æ: GwÐWÝV>!ÝëR?€ÆuœàUq°lž?<ë4)ÀºPU[xÕƒº9W'©¼ø¹û¾ˆ0Bü«Î7"›€’ LFY2oÉæ~©€Hÿ+/bøû7ìˆìD¿@‚…_ÿC•ùDøL(”´ð#Ж–wH´¯ |* ¦— ¡ZÏÄ7.2¸Uõ«éIÖÌ{ àPÎÏH#Y^°“oÒQ£Ã!13Š ^/:\ÛÍûÎo£8zQ(Ç‚-’¶¡(Æ‚‹Üˆ›64Žço³ÆB¦|n¬äFX_,æû1·oí@ˆe97„ñ 3ÌÿÏT_ÙLó×ÜT«lëÔ(áˆU4oó¢žÍ4?}Ýbã—v¾O†)EÇÍÇí®æZp…ÖT— >¸{¿Ú¶n> pÄ~›÷Y¸üúvE%"›:Mgúj*¾µñï‡&H U–‘Ú4šQRÃD_)E/&ú-j‰ÿ䯨FNùaWhÁ”÷#DC£«@@3…@sÄ{B'QÏR‡ï4¾bÏbó†âŸ0²áÕ Ržlžý#˹ßk–5Ôß"\`ñ}€Rr<””º@JÁ´X°g¼»ÂuƒN‡ð»BTÊÖoaµ/úÓb_FøÅ„£5|dk¥÷|nEˆ(q Ö'e7•…RÕ.HF`".4@UÉîs‚`oŠ5¸¶@l–Î`0BIÐ"^܃º̇Tû¬Ý§1—·ÙœT»™]žÛå»ãôè$“ÇåרcÖ/²AñáX|"“íp;“ŠÃØ/ãªS‚YÔÖùŠŒz!%`õ=òņ®R˜7¾•ÿL;”!|Ôœ92|ÛÉwOÎeí7½“ V=ü‡„}ÀbzqhdÅíŒ]ÓH²Ò"–.Ì2ÊT8#‘šò_oh‰—cÎ~ŒÚ¹è•W·ƒçKëE¤bêý1Y‡ðC2ùMëèq=õS|?4€ló¤#I&-èß6 }ªh2»¤†S “ýñW—ÈžF’SMÎäÀµË÷%‚±N  Ó²}†~KS­…%E:ò9ôÞý|/Úäs™„•¾ètšÁ‘~‚'S)î6*H_†bæÔ˺$.Çè[Vc{P¥9î®,xd&¼(§ÑcS…Ài0œ©¥'p*ÈF€Û”º>DܶçÆC–Á¶T$}lª>Eýg·|ÿ´NYXÔŠmL/¿/ùiE6zó ó̽ßs.×È’ÏÐ;yLT…¶F©úLH»H±úH=#€¨œ¡½/Šp`þ½¾ÕÊQä…{î›Ï0‹ãhs'ä”Eu”J—„, dâÕ V•Î0b ñemýŠ{/¨Pkä 3g¶A)x‡ˆØ§çžHs"¡d_¢&Ç:‚—ŽWî¡ÃJ{âp‰„º1rl…ºÄ’U(•,ʺ¥VwÑs†»/¸O¾1æ"ëžž×ø°“4 g<\U¨Æ¡õgÛ–¤™òò1b„UñÏ»&Iãbãr¹÷:zŠú3ö+‹·ÜH'‰—ˆÓåKÀ¾Þ&½Ï?ì ¾@ÓÄ­f ¹hß©øGO2`E‡bv€|g³k©¢²¼?E@‘ZÚ]ªx™yL`ÇÒ~(_ƒZØàx_6 ™‚òDæïDy¯CÎ.W¡(Y«3Ë 3`ŽCW_Á@ F˜WÞÛeÚBu½€jèÕRQmK¯¹'è4‰£°q;ÀúŸ¾õÞhÒì/ëCw¡¡Ê|kü#HÄ8ü:Â…N'­”ˆ©Ÿ«×£C‚…Ѧ¥iëá’—+,§{}#É«miv*ÍÍÍÚÁ¹Q8 Z )•ßv}PQn6Î ÌÈ't|µ<“x™šAÒÑ æ¡…¹†ò©ƒSbÒ^}ìž×^ZIú·±ÞÝOx™Ç 1’¡'thºF„|’Ûnõl͹-[¦.õyÈŸz¡Òánsú̆¦Àž$ýØvÅTÜ8ªd7ÊøÑðM«Æp<ˆ£Nêû0ã÷l“U¤ ‘v‘ ë\0Ô¹Ÿ¥ì¾xÀPþ,½ B9¸­†ó‰‘TÙø‚ u–_,Å©™]J‚2B^ÒÌQж™eϬÕÌBSŽä–åƒ0Zô©÷&¹R`ú« ®”  m¡Pd=\NÍÎsže¬_†ˆDž{Û¬]Ô²rc"fð7XTcó®€dr«¶D™uÞÄ#t79˲…C±óUp 'ÒByB¢ÊVûO¥dç¤cNkå„¡ì2^Œ”¡.ë§’ƒ›vm¡=ÖOv3nñ#¦å#_$ œ¨ëåÑú˜kh.Ñ(Mmylke^I±Ijªµ"ª=×ǫĦۋçß…i3{²ˆÉÊ’ŸäÉ g¥f©{‘'q"KË”™kºõ•ìÜ3¬Š^n£ôÃøîÙ¾?fúš¿“{»ÛæÒ5 Ô©Ú\ñ¦ïêÒ£³Vÿ68Þ*;ûßM[´œ «¡§°œY~—/ÈHßæég‹D–À¤“Rt›:µM-áXà ÂÏ‚¶&?H'=mCM`X:€Ü6ýÕyéaˆ¿q’»Ü¦&‹;/FOú%­+_OE Jú@WK@ðÁ½OÉÙ$uïÍ=}— .[›Ó耯ĨlXI>î/˜òâK™¬ÛóÕ‡ê1ç>PÕ¬”Ðo0RF›$8œÕÜÿÔY!+Ï]é[½ºPÚß‚€¢²[ߨTÆr¦Â":gPÙ…Î]«‘È<òòÞò‚‘ÑðêÕ|¡štÑLEÀ0ýš Ä¥ÎÚZˆ·`e/ܘ\xE÷—Záxgèr)-|Æ Ð—_Yô~Mâ‹•…£©8—zµÏc§–SºÀÁÿ&?â]ç°/¾‘Ù›¿§Ü|+ÒpPÖùÁÑÆÎÍ7ŸM­-íÁKÔe%“À†ó›ŸS*Û}긚·•Ú„“U‹-´Ð阯õ J^F íú›OÄàô ®Þ^àᆢ,}l!wYÐI|2´M÷ºÕ1é´FÉÛ j÷3/ŸžÓ¤Šö²c…¬d³øk8{’²ß?¢‡¯FKÛþq±¸Æ"’Ûâu˜§Ÿ&D&¸öϲLhAjµÔUF2{ý,½Ä|¾BoÅ ’„=¸•yuÊÌ­T* ¥›;Áµ«Tåt®èÅ´è&ÃHŸ4 ’ã4JÄNeXãv9Ö7ÙÓÎçàÐ܋װ‹,¦Sð䀿.7w››ÜÃ7‚æêžÿÙÓ =k¿e5ÊåÉSˆŠÕ%¡–ò;kp¶~cŸQãÝl.ª<[5Áw{+îØ†€"'êø¼õó ƒ@ 5Ì‘üK›¸R´3–ž¯)×…¦Zæ#ï?’åY“\ñÖJ©¯n‘¸îhOªŒ†ká阺= Õ,)†Í¥ôòÅ>mtvD!J°Û™+®Äm着ùó·„Äïë ¿ŒdrØAb`°°Mñ™—±„_'•nfï>Œ‘Ŭ¦¢Ä3œÃoDò¿uÒ° ²i¬WÑs"ayö®Ï ‚K ¶vÓoŽžfJŠÔæ}Ûœ.Z kÑæL]Ë+y\Ô‰‚±E¤e?$6(eæJ¹Dz˜‚²ÈÁœþ ja+B¤~ ìYtãbñç¸ü€&™e+·SøHÝW1ÛÎxèwêžYßxYHïûêKŸ±;µ•xOmï$-D³¯Ø@¸‡15“Çð­~Ü\¼£„Åddûï³Yå“|6_ÒSöjM>8–[šœkøi®6Í_â4ÀwkÛ•ò„3Úñûçê#9Zsæ›ì|4Ú•V <Ÿ#˯³²¡Ðeò®›bêBbM~ „G 5¿Šb7ÍgŸaæryJ÷£sÞTý8Tf±a(ÀIU›/§ŽÊ”˜ËET‡Ÿ{œHuÁÒ €]èÛFý`³â]þxü]ã8#Y¢Õ”ê‹ l´ dÝçCY'qˆWÒQ›øL˜²eD”­qW‰Èlàÿ.~Ñy<ÃuI• lõ÷³ñˆ ù˜ÐGR‰Æ´0díëV0W%qÎê M”´_m@ÿ)öØœéx·0ÅOp PéAÎD#¼`pã{mP¥ \liËW?‚—f¢l3:¥½£ ª`‹ylïÛ0ZÕϰÖ_Úš´Ã·ò•±êê¿ïŠxƒêkFÌyá3dmÈ69\K-Áç†g:Þby¹#èà´"ú“ªT·l€c×·ûr¼¦Ðͯ Å&ÆÑ>°@›Ì›U~—XZ;R×òŠSŒíRíß±ó1½—Ž7 ž7=µAŠÝZBܹú€9“—!áæ½cà«uÐOšÌP:Ï„ª61಻üX·×øuI†Éu?RèFeþο±˜D Ž÷«*“⧉’LÀe ãvQóÝ}ùb,Iñ lŸZ{ø³!Ç6}_¨øH· "HéÌTOžE—º½Ú™áUD39ø(Xï€ „¹Õí¬yÐD¡«‰è÷åö¼ƒXØõ¿µv=¹)Póæ¸ÿ;¸¦Fº0W\tƒï×^ñðî GZœU›#¾…¶’¿ü6(Îa¾‚‘¿ëtŒaVP"÷ZŽ—sÖƒ®qŒÉ¬[’õôíÙôp)w"rÊ×aý ¶äÎÇp\`§¹ /8OÄ ™Ž7`Ö–adGÔûf3û‡¹Å3¨Œ_³[ÎÚKEp@FäbØ­uÏáN•Ê(Æ{(&Œ­?óTìsÍX Uw¿á×—2“JœîC ¯ó•DˆùBOèÅ’cØì„g$îëüÌyDoвØ6cõp¡·–8¬ÒuêJcÝÁÞg§oÿÝ»s’ºm&­ú 飈y|šÖ#42þ|QçŸ7¢‘ÞÀg¹l=ð_€,Z¯ë+¹7Þè·⸺ûÉÖ‰‡Éªó ųeeƈé¾ô–º¬¶÷m.²ÁŸqõ±nm MðW'å_HuÂèmXÈÊ8ž«3Çöê.4ÁÀbÊâø. ¢¥irÿ¢]ÝUœbî½m\x$\ÐÛ à)ÏaEr˜JíMs*•LSˆ‡M4;ÎsÒVSí´ 6ÛÓ™JYE·q :Ý+!à;Õæª_6ÓPƒÈ@…˜°Êeaò¡ˆ¡Œ6»Ps£®¿³Ô·Ž¡åö\vü $d]êI”¶¿¼(/›Ð˜9/‡°/ó¤à¨á¦êM ©Ýòéã‘N rùoVK,íB¢™nFù?>ˆrÉç¦ÚÆá*NÛí>%£¨íf¨‡{Q¸'§åô8›í'Qy+ÿNõýH?ÄNÏ# šn!ö!'¾°g¥qÉÈ: ^õï8g_?tÞ)ºBul3tQdÇ“¬‰È˨– ±zIû|EaEÙ€<¦c;ð7ÚUZÄŽ¸¤Ûh(ªÄ˜Š‘™Ä¯ÉÛ¬ú™škãÂá x —÷jó9<Ä×ÓaÒ>N9»XlïõÆj°Æ+µZcÄ%´„é1y݉º‰ €Í’ ‹™KÆuîs°vŒjr;nb“%ÈEjÏ ‘Lí.±…éA"þܱ¾b<êFlR?Vš‡êÜ’Z› ëÕ¨Ë9ƒS’\w4ûl^°¸ÙË'uM€Ûû”íŒÞþë0œýüÃÏù»;+ÄÇ8‰ïC£osˈˆóƒlŠ˜ø,o–./ƒ¶·± rw))g^Búë©Û¤p0Ð6—3½ª™d0}…FG>Öo~é4¸{¼T¢d€E7°ë‰ÿF¢$OGJZ—gi*Ýã&.¥ÃV3>É@#W†ËqŠÜéâ°·A(Qk4ƒGÈ»œ×lÔ´ˆžLœ;2­æV£„KÏ.íÂ-nAÌÞ2¨G¹¹nˆ›É¬ÉwÍÃ{ƒ°ñ:Kºœ/®{öY±EбáJŒ&¼rÖ¦³Ã±è‘p ÚžÎ1t’íê…Ú8R%‘§“Ú’ÛåÞÒ‘Å*Œ §=(7:*ŽXó×Á&ÄÌ '¶ïåÖhLº‰ÁußšŽöN¿ ¯Ö+Vi§§AãUB:•¤^_®ª…œúÿ>“°kâV>ür/t ïÉÿÝŽÈKíaêRn^Ã`¿9ŠÏŠU×S‹Å(Þ ·6¾(ô„éšH¨ÚÄ"×è-ã÷L¼NÊ w§I•‡Ò‘T‹Šã#®¾‹ƒÏò ÇÂqßlĈVë@åü·¬àÓ£@h· \¸#‹è:T¦ïû-M’èæµÖX/"÷cËÕ~‘±G–¼qúxÈcô¸wIþý#g©>È}Þºyý#ÚÜý%¾–Óx™™ªãÆuMÂõ3¿útcSFþ1;z9Ý6ÇÔÓ—ó‹ó¸ZJHTÃc¹Ì…P_hiƒòè’Q”>û·u,½¶‹m áòGd×ÛÝσÕ»ÖpìÙ22í_´§ETNÁìa.dÏÍÞ–›@rÁîä±õ¹Crj«êó±ÏÝ ‚ç8’¹&Dî†îÄNåIpT²R/w¬£yæã"âÜÏ€·»TÞ9ñx*IN°RŸ'Ø ',²MM?~w5Rˆ7zq”ÿmDUÖ¤ßÀ¾¦[žI…{ö‹& Çœ ^¿Ÿ_<¨‘2÷VʽëøÊ1\AIœóLå´w[´%ÝÝíJåü‡bÄå.ôÒ9M'5˜«Äæ«#%zí¶þ/¬”ûZçF¤âE6£žÎtà¬M7 6ñßïPCpMërÅoeؤØz«>ÁöÐaÚ|¬R´~t±Ã’§"Ý¥ìµøø¢ù¿SÓ¾ûY;—{E™OÕfÊPnU=Žy©½ä Î[@›"JÊ«aËoâ3Ü äÇ /·Ù$ d*Ñ„u\eŒ=ú¿üÙ?jü}%‚N¸XÖc%[Ç‚<,2VçòÇ뜒æ—!ŽÀô¾pÂ,ø7KÕ'Þeó š–4õ)IÓÈËæV3Ž/¢Ù9P¤Ãp»à3å ÉÚ×vÁßóSæÙìB`P>¯žFθLjîÉ„¹Å‡Í r[LR™á®( à¶…ò«!üÁˆ›©Pí'ˆx/q¹§´§Å4¾—¹h%Nﯩ9JíÒ QÜoÇýk• í§€äyk%ÆP–wÈǨæˆáÙu¹Oœ_Mý¶àt¥—ÎYy5ÖØ ƒ¦åŒ¿†ƒÿ7r÷)Lÿ0ú{x³¢N ö#Ô¤¥J„ !@å&MãáA´9uþP†Š¹L úÔá›Z8±’Ðúy\ãöðü}oEEêboÖ>°€;ï®â—òhj XS‹& n71Äî¬lr©$Éh«V­ð¸«®ÕÝ¡beÁ© ¡º“TrxX„~›OBI)šÛt#6³R ½E™Vtÿ…Ploc]ሲÍIÓ–»,ìšÈtÜ&-ùØ þo2j›->.Ä\ (‡òWŒ>%/pö!åÔÞ5»D63x*Ǽ¹^Hì~0®8ãrt¥àªõñUœB¦dôyÂB€ì/8hé/œk]›u¡®œbœ„f§ŒÜ‘ýúp;_“®éò6¶ØžgçI=ùQGCüÄRÛR/kÓµ'A@ið[€|¿ä0Û7 ï³ ¾M)¹)~HgÂô;ˆÁ,ì-@±2RY+$üPe›T3§ý‹ïˆíÚLm>Ë&CZ*£`Ćâå@ÑÑ›*^kRÿp‡øpž»À…f*Ulc8@Ý#&Pæ:˜‘‰aΣAœÏ«­)nÉ*wS¯«ÕÓØ‰2{{ò(zõðŽü]ÖHN´izì£0ÈÀçådíÒÜV¢¼Ãš*…Ãýˆéµ;§¤i‹à þæw3$³€ïíìYÜvÌ/² 5æÜšf [™3^š~ˆ‰üd8¿ ,ñôIôËÙ’g˜L,Cz¡¨‰s÷hl)sÅ£Ž: b±¢m«ÊOS ö·x)ôJs˜§I] ·t¬â;'²T~¿­´p}»‰X…#Ü?tw½¨Øx]IDð1 ½•ŠüB»Ü0Ô%‘ßÕ7e…pq0¯U6:JÇÎ Û9Ë\ 9¬]ðÝg ´ßmTx¬jùŽduœESo?¹åki¹Pr©àö£ÖžÂ86¨a;bÒ±Fæóù›}¡‘uýfoùŸÕF57eõ¾tܽæÄÔ2kÕ®6±MãOißç>@Z‰’’}Ã6šÆk3}ˆëÔ}\ùÀñ©?y9,÷hr5̳ÞÄ*¼E\o8)Öìqa¿MÇ1du¡9&}\IãAå5dêSßÙ#Ý·²í]-Œ «DýÖŠ+xZß÷AÁUC/ØOºÅeWŠq¡XbØ;Þųö怮&¶zK ŽÚœI{ôÌ‚å±ÇëeM“ Œã”³Šf—î[É“Ïâ£éÒÛBõ„hr¸FÕÙ›$Ô‹Ö¬–ìay<¯‡Ý<<8Tq»Õ[©ùÜžM`nDÛuzÍ¥téN5 } ›ÐÒ”y~hJµ*l¡äj]!1W(UîLÑik)ž ªH_³ÚRÔÓeGçR{:±~n>œXïj`r8ˆÏýÆßf[! û+ßvÎŒ W{ÌÇ­ Ëq~âpÇ?â_¡rëÓ˜m±œàcÙE«·eãÇ—^e4¼j߂ۅ/ª—;A ¥ç,5ö“úÆÍtMÇŸº{—´G˜º©"/Tý%l]óƒPE½k¿‚9¶O™â\¸Àÿ-Äâ†Z@ØÎ$ïedd­qø0=w.J´‘ræ M>è]±k[HàuŠx §ë#D†¤*¼ÏæT>¿rq6 ¤¥~©(¤øØfa¢ï¹Eßcoá„e'çG¤2ÿêq¢™Ò`eòÕ³ñÐO§š¦ßîz?œáB9¢úÇV4Ü:æÂ0ŠÝ¡pþ–1Û2p'<Íc£óðZŒºÓö0´µ"ñîV@L’ú´Þ’ 0m4½¾êY"¬¬Ù26×EЇ­ÃŒò'-œâ… l‹sç¬ÍŸ ×±NIFlº|6(MáÀx寮ÆF}3»`6zèðÉ5fþçPÀ›—õý‚?ÔÏþ–ö.–Ïmå’éAW„˜Ò8õw¨ySýBc¡¹'± .ÀuJ<7­/…‡HyºÅ^ä´MþøÙÓ_ 5´mÕ£ú­íÿ¶rúãA“¶¬Z®²H–­3ÁIK¾‘&ñ§¸|»‚é3â­´Í~k­åèpaJŠáM~¦+ާ¼Ÿ_ȵê$.mÅK=&„` BÉaŒF%åëFâß+ýtªÖ–®~„K^ƒ9e–ìWŒÚEÁìqj°ƒEy2äôÜà¾#zððÅ'@·‰úhè¡< b(~\ è„˔蹔å5oòïâî,Jä~j áˆJªU ýO”VÓK”?jlÒ 95Ï-R“Äv-Ìa$½øÅySʦI¹y¡Þ’¦"p²©ßÉζtiÛ‡w§Vœ|Éå/¬÷h¯ù4‚‘äjœgä(pœ%4""'1Ô°¸ ˜fޝê0œìûÌ !Ôyõ÷û+Õã÷ÑVZ€§n×ÞD·£G—ñ7…6Ú*$iÄ•¡Óì£ÚH•Fâ½ *²~Ä;Xˆ…áyÙš8áý×ùDÜ]pýÓ˜ê ‚LXç›îµÑ«â:]‰9+^^Ê/&’)©¢qÆ€¨o!Ê ÂËú³|oq" Æ©ïõæ›(µ~3†•™³ÕÖ.7çÝô,›ƒg–ÕM»„Ž1ZCË̵ Zòý´±Cr|Ý©ÁãÁ˜rŠòåe2td]j檓=UÛYT´Ä:x¡\ø‡¼xô®‡R#±qw• $µp¬}&žÃ]ö(Ó¸ðع<öaòӔ鯹ëAÄwLt7Ç ÑE‚æAÚc{*T+Ý-) íao׊MöåV®áâèø¨Ç›Ûõc×¾A»\ƒ¦ÚtÒ‹yeK\NUÛ,@3Ü{üžn8TH ­¡;úEì¿ë_\@V5|ϦÐÙà©7B„ažèOá2{1Ÿ9«~|äÁ (\ûU” 3ïÊú`Öî”Å'æÂ¸Ù„‚m|äOۢɗú¢à ”yM1žv_ºˆ+à.ƒL²M¢‰3Ù6c»XwñPbšsFDW¼f‰X©Â— k|’ÊÓTì±sJ¹¤-D#_~=Òà “Ò‘ §¨"×óJÊÌ"øë0±Æ'änöÌž¤Š&þhðÔPªúÆE•ËåUœôœ#‡Î@猫( •©j§‡d;ÝS´ÌJ÷µç+µ¯p&…ÄCæüü8y"Ë/£Î ÂÓ‚Ÿé\À+†rOÜà{tT·Y@Ù± wî`Ó´.ÖŒ¼p.¦¡qªÊj¸ß’†»d*®y"vîÊ¢@ªgóž•6£i•ÍpÏš!c½±¾ÇѬuZm>ÁI~%Ðàsœ<Ôùšd螃,Š6ó,ÐöÕ&M|š9ðª»ÛL´†•:ΜPx¾`³ZC3RÓ¥ —ßãN$?¦a£,—ÇŠÖiZ x¯6•sgϵò€Áÿ#(W–Ùmó¡÷ ¢qƒÃWÐ:‹/úàxôksXQ?$ê pUÞHX,rD:ÇãÉ1šxry{èLð‹û˜¹xi+“ Ï>™óRl NjÖzÄÆMhžÄ ¿^ZVAuVÊTi€Ô®ö§ Æ‘,µÔdÀ4“¬ZÁûWù+tò×ùr”=½ RŠ-ŠÞwÖ­8e u ѯŸ…½‚`Í_²WAÂe¦ô%(.ù¹+ý¬I{™%UîÂÇÖ@eŸFZ`G©¨Z“ÆJªÕó a‰Úß ìñcHñ¢NÁСO‘cÿ°û‡¢“~j¡€–\%ã jô4e!ÅUìn@«ªÅ)Þg­U¬£éœæ¨Bjú[Ö|wÜ»ë.j\@þ?Ÿ9úV×öØ/ƒ¤ IÆ[éQß{¿Ç­ÈhççÃV5䌂öôÂÅá)¥bû×F@nr7ª]±`¨×¶5úŒ³ Ü)-vy}@dƒšå²Y*©shê_TA(€xgºŸåºcU'“DýFé3ê©t()É1Åâ_¥®Ár‹Uó©ë ™Ÿå,–²À›zŽæ\Ó rÊζbwÖ8;ÓÜ¡R!´w¹ò¥é•¾Îh´ü`£šÏC#håÜõ£¹[‡¡O¹oû~KALŒ+‚ö]†ÂK†×­ÊÒèäbú ”µÚ€€„Òâ„)f*ûINÏÌÆ¬Ð§Q”·hïìáfq$, €6{ ‘2;NªìÒ¸DèàPà;Ù³[hñr%+£`J‹ƒH;–÷c¹ÏÇûf»Ãkßé/QÔªç|9vPW÷šSÜg‰8ÚÄc;¤Íç—јŒsçæ–êDÔü¶zèDŒnÄhÍd »Fõô«[ QÍ-‘uV°“ýW‹ŸÛìv „`obËèq¯Ûïtü`°‹ !«¼û×¹ðyÅn­º—cõܤ²¬{9µçÙ„øå}(Â:7Gð ¨À·Ù•»}¾§Í'´R¥MÜýóð#­­ŒCɘ‡÷YLJþÈ#Ý¿EIôJ¬Ú¡&Ñ4}ŽSªašfžÓ;ª::p×Â|=à.Ìp*¸¥Fïvp*@Nx޸˜³$­3¡ì¾¸Ì£'ñÀ-§z0BÞZn mÁƒ'bëG>qt|Ø)òÌ|ölG$‘JÐ>ë6 nIÈx&ªÑqô‘£ÀVCYWO,½hâ4ÕjÌÆ¯IËXwÑz@@ ­ã €PÙ‹'q·ß¡Íìð2ˆ5GÝf÷¢„µ± ÅWÕ3þ’ ;­Öá€ÈÌZì Âïßt%%ûU-€òÉ(`‚bªC£Zðlÿ²æÐI[“2òVo‘UË>žr´qxú*ÆØyKC<[6? µÝn¸§UÒÓƒ¼B•ทмâœÅQdòè Ô¸ÚáH”É–´³/iÌ^pp|ZzEÛù΄ó| T]™J¯Ê^­!šñ×$N·s©…UÇìq„øÔÔB²/¥x‰‚­yr'%fî=þ£.‘eiûTsíÝ”‚–jf»>+ yeѼyu“¹zÌÉÒz&%Ýç°Ö¶¤Y“; PÊ*¿d泇ò-ÓÕxív××Út½ˆ&w#KÀÂÁtGæ^¿1=œ¾upÚ¢_[;“ÓÚ¯¯£¯YÌ£®:+D‡„™¼[‘Áâ|Pô7 »îk¨Ÿê깊)¹¯šòcÓ´–O“lM¨íÙÈO8D¯Tÿˆ'#—{¼yš!ὄ÷<ù~©§1'jT©g…OM¾4M+Î(WÆJÎ Eñ†xûLø)i[oö¬L=“AÇW“‚Së#vȧ^Tp@Ú8" C·øOz0üƒ [B®‚@ÍÝÉ×´"ÎðÉ_°acO™SÌ¿{˜ƒL@0 æ­:¥|\àhõBAËóí¼"B Ñ>õ³ XVé•òSÖxÑZ$©ü h¬q;Ä™0ÁPjM8O‚Ÿ¹Â0i;åï#¦²™¡³¡ð#޼­›žß]0ú1^b eöå¦ÐQn¥C£_xÜ{ =„nôÿ àáåC«qöÌ,2Ô75%ºÊµùlçóÏ… ÁVƒn~ôí·ª¶yØ£Èû·°¤]MØ«@Ôð‘1¾¢4‹O¼…¿}V%&ïm»Ë„kâ(¨ÒŒaŽŽWlœ¶¤©øk*áµë§žÁù„plŸ¢q^‰¿Ó%Ä¡0Å"|¾z–À_ã߃Î÷Xqž c²u½NÍöL¸Ì×5N¡ì”‡!Íà÷®ó(yˆnˆˆ—œCëp(­}µ1¤þJcxpÏà…xzßNc`ÝÇ7f£*KÍZfÿ¡±FHX›©Û¦€ã…îF¼4g£‡ˆúÚÇ …tV|ñX¶Ä}?y©K&棵>¼)¹Iš½™Yµ-\i $&˜~D8•\Ó.è\«æt?¥†—±óè!K/»+#‰¾¸f«L÷¨][Ûêѹ® /Õ¡æ.JˆÁ )×XnÿçˆöçlFñcòÊž]ïyГW+“BNt5«<6—~<Ï~b˜:” CÝöM– i ºÚš•ìÄÑ“øÕÉWçæëŽ£Ãûw3"Ðò>/®¼¶k‡^fô½Æ5ƒÓ<¾¦Lçýüš[®-JÝXÃ4<áaw:€þívqH ºh;ðhÒH4Qæ2`2iÃ×ô œ?¶ªM¿ýHè µÀl3 [M0ý›ŒÌŽ<…™S§¥¿SþràBí-øqM5^ˆþ@¥(ŠˆzÏ˵HÐ…¹a¶®´a‹=^À¼;&³àûm¨¢ªsO @œVºa^ ¢iIÝÊà÷f_ÝÌŠ ¿[z2,×_ã)žDÞ£ã~# Dš“röDR>´ “¹øü þ­ÿgÁ2Ž´z.­èÇáõU^½ÐíhÐÁc9&UŸs3¾ Óy,—]SÂò#¼'ezU.˜Ó.ïH/‘å¿ä°Ð’þ;±ø™´H7Júi Ç´àˤ¶¨)æ± AÉF…x‘…LÖãAx£29ÛA¸Ý’Ú…¤‰Ð#<1ÖÓÌXeÞjjH¦$PÀ €êðxúð¶s Ç7Æ”wlÍ™O¢tYåíe tÐ|ª €7Ð2á›Ä ®uS–yÛ^y6¥ ˆpöm!qÜ&U>[b¾BÀ+ÙŒ+ý5î…­äþªá (Ò $gïw‰±~ú½Æïí#­ånA>pN3¢gÞÔ̤öcÔ¹pHü è·N¦›P«@´+,©Ë¥~·/â$3Í’pQ÷‹v|µ[V³ôécMlµ{ŸZ]3,¥û§®J&Gxkæ:ì9ìBêm7 X䀨)™~ýÕæŠ*´4!ZRÄ»qOÊèƒ<=m|Fw$6” è…üWEƒ÷¦»¨¤:Ü×i¹È"/iÕ=eÂÖàð¼Sñ sNš6OØbê#ê/kìß Ç}•«2 -=sêk[>š0ÞýÅóËÌõÙ›éžçA·HFIµ8&ÉäÇüƒ’‹iÕÀw=Ä^èÏ.´´W ™› Ù1È[%÷v$k]Ä-ã-Uf‘±/»fÎ1³Ôøü `S™kÁïu—ñŒäº†^":‰l7öüºíâ/ÖLu:©ÿ^žg%†)§òåù˜‹ Æç™Úº¤s˜» Þb¼ÉÌÞþuíO´ùZsqwHÿ)@½—äÂ'ÊqGå_‡!÷¾úð8ªNäÁVI(fÝälÚ¹J_ÿ5"·”¤kçG™–ö]¾'1P®yßÙÅî•’ÿ4âf:„µÁÁ<”(‚’òüÓˆ*̃dìã€BÔ§9åüù‹r;ggJíŸ4ÈM®9n&ñ®lå4SPØð§è›qHç“>Ô%‡€³1¼L#ÀwâXPغ¥heù^%Üùg =£FT#­H6(º•#=>Ë$3Õ0Îîûêžx®ZHˆA¨²põaøÚ¹Õ)uÑ0Ì[‘KvQQ¸x–;ê§Šx].—¼v?uàåϙ©ØðëS2KSËðÚiàóî†Ï§t¥dIÙ¦E›@Cï—ž+P¯¤rÕÁ•‘àVæHvI¼,Òù§Õ/½“ÒiÒdgþ༦ž™jpa4óœëkNyãýn-†€iñ˜à¸à­÷P¤wJ·ÛĘ`¸r  % zkßÏýŽvƒ†ÎˆC#EƒÐÄq ?îr¥'"Êà$–÷ìE¥ßÝõoÏ%ì §«$^án¿Š'â¾DÏšè+ÓÔSoûaæb€çŒpr¸°ç»(©H`‰ûš]ŸýÑiÅ^µÓ½”QƒÐðGaWH<ý›Hú‚'­KL¿æ/õ»ü’ÁÇD V%œmô7oöÉᮺÎ`ƒÆ=y ©·áÇæmjWÏÄ]M5©PÊÌeô©7ï” ë ÅšeX[Ú!9‰A¿µçu—|ÆãE*®¥5ÞÆ·©‘LWf×úyžÕÂD=WÝ-ãX÷٠ͽûöþ“C³ÏW…üeíÇ–íòî È;X@œÛZõeZnòríoWϤ*ë€Átºƒ™'¸+ŒpMäôåYÃmÆJ0D­hìd#ŒÎ³VeCè"ëNôò3; oÇH¶Ûï² ÷*^8{k-·Œô†ß+„DÅ z…I߇¨Gõ¬]—àŽîû6¬ Ç‹&tµ:ºÿQχd«Áù Œì˜(—Äï†vRæBî_bv¾2ºû7ÿ‘*œ2|£nèé¶J  «}óo…ÏÐ9þAèŒF¿“ÞÔÑ_¯ŽäoWÅcoËJÌ”5:ùÑ€}Ùþ·â8B³†–´ïÂ^KÞ8F– )écM¨÷öPóÛ¶=ŸÓz(2¿Œ—Zõ•# ÿ»øújo’íAÇ9§ó³³?Ìj©–Bn»jþK2Ó¦ ”žNœŒÆ’=\éºüøÛp1:õ|»à)Ë.XÉÍà ¡…˜b< ¹wÑq›×ÿ¢Z÷dÓ‡dàìôm\¬þ;ÖŒ¼|XwÇ/šEÇ{WEñõi`'&„˜:©õÚ»ðÈaŒtÃÁ°;ñ%÷´yÁñ–ÎÈ JgMÒF¬«‹ÛßT£Õ$SÔ’)—tÄœ¬ .¨èå*×OstÉ£ë*pߪǜnE²¾†93 úóÚ,^ÆÛù/J¯Þ°òŸ<&ž‡:O‡›ŽTý%ÀͺØj²vDÙ;TŒã¡VO»ˆ£Ÿó§Í·6ÑI=;¶(€ú"ê I¿•!{@Ðl>'¯Ÿ:»°šNýoŒx©ÃBÐÞ{äZSþ0N¯‚š²“îáRÍÇrô"Ù$ÚS×È׈¨c˽ø…¼Þ”\ù6–—‚‰§œ/ð³¿ÌÒQC“À“'?Åëã}MûpU(IÓÛîWEA‡¤ô8ê:L¹ìØŒ^|Íò;–Âiñr!jÂö©*ÖÌõ7¼,¦1œƒ!‘ÁüdÊ OOÄXÚÔI·»ª¯XZ¼±A=‡WAÚù6.Ì^Üîúò×T&Õ´Wˆ°¸, )ž×nÑ…ëv S"ý.¦‘EIþá!£ÝîÉlyÂF¥ocÏ’^RïhÏÑsa}²è™Xƒ?oª¾Ú÷ý4Ô;XÖ0d²m.Ôórz4ïIýeŽk¡|Ÿòò£ìœ¥ùNþžè–¢ Æk nÒÄ. ü™à¸“„=~G;šÌÿ*Ê>tS@žò‘Âw¨QUàÊFæÎ$Œë†³N‰¹ÿ§„»áÙ.0€_¸éçìßQÜî~ç‡f©c,»ãcêåaKÈ eæüZ|¹÷x‹ŽÇî<¦úù› aLÊxÔþ,À³Ò¸ú-ÚÑ­nLëFˆìnÝ¡‚‰zv×»P»*¸ TØÀÖ$õA…d¼[T>æ&&B»4=$œYÿpÈàæ#‚5ôPsjGMÌÀ±6ŽsRZ)³Ÿrâgáø:º$R›ŒDô%â”s¹Oç`AšK[ür¦ì}¤#£y"Ë<@9jü¨d–^xå#?sÏ2P¾)yÄ,âUF ­”º½ê%—½žGËÂãôo1K¡ …"îG:„t¯ Sxeµ¨3AmªŸ.ôvÞQø—‰ly믲µÖ"¹„I8ì’æ»³ç<¯Å ‘ܲeäŸ@™(é[—Ù}BÈ7ðÒÒÈ|ãÅtYßð>9ÙvØœóUŽûľf¯yÇõÈÐæ ·cÛ¯‹Èå'uwÑÞL;ÇW%+ΪäE /á:(Ã!ÝÄL¦gòX™âYN¥\Z˜‡ìU³dŒè¾}6ÔL™6Ê÷gf¥xM':ŠÖÙqOƒx—8…V|xÓìn¸–mêÛ:¦>i t[À³Ÿ´¥)‰5â—ëxâ|?Ü'>ë:@ù“FåuïôvÌ‘1áÿßCúË_#•51õð}cÓÕq(¥‡&â/9|ÕI3±Bá÷Ç?óØg´-†º÷§Rœ: '„ûÏ;gÈ:¶=Cä!ÿpIµ•óöWÏ‹m¹¨O©öëô–òR ‘: ”›FÈ„Ì gë»sÈ!®Ò÷›ËÏîתçMz&Ò㸡„‡”k¡šéÅÁP7§ÒÆsŸzT;¬¬+„¯Òj®fkUbåº1IgL@Ïí­Cä­Þ‘53¿†$”Rs¿æ²º‡ÊÓûh þ0&¼FEºÐàÁ™xâ„û©‹ç8„e¯"éÄÿövË‘W´½}±nGùcqç!ˆÇSc–Üš‡îÐ.ä¸ AîŒù‚ü Ñ7 ±…å£,=þ‚6ÖšhMØlVgHH fS/ðaï‰|b@¤~šÌi)qáúÅ–¥yVšQêÈ®…Ñs£K÷j?'MÊ–ÝÍù¨>¼V«oñ`S¥:s„ҨÒœ'JŸ€šB+±ž}‡K+»£.+²ö»|tÕnž‚ÉšŒFjVÎgDt bo˜8§#Ðuï²ÓÔú7u=³Gžvk¦øâù¯/«:ÇtC’{ty&a€gƒ—ŒpTäĽ9.O媓¼S´RV?àhX¯·Åê[éšû*9šE_ñü÷.àŸmJ•ÿ¶/ÃÛB|6 ]\ Ipb"ÿ:Ðeÿ.OráÂ"N-ƒ´{äÿ5Pm{²g (t™†wWú €n©Ðañ}ÅÜŽ–¹¸(CÛ;cÙÈñÙÉ –‰rÏ(pIá¢ÑnYÞ8ˆ;€NF)ÒÛ.ĬDˆÇÇ¢g¸”(R¯éoAÒ¶º%€0O4´ø©a§ÒDZ<’» wÙHn‰KF7ƒêŠ .8V)B¨˜Ïö¡Â|Hpc£ôÑyClž™‚ip¯J cgfí9c¦å¬T°Ê+flPÞ.ÆÏ\Y”ß§´ö¬î™¿;Ùñá}ÿ$ëjØ+YPÁ&\x‹Cƒ#Ñøqµð%ØÌ’nÍ{ø¡Tîeã¶_Xб“$Û{vÍþÎ<¼cÌËAm}!n¤ m®å£+Ùǰ7Ïc@à}ú#ŸGïâ„tÐLGI囋R9žôÊëÝéñwØ×€Ð θáýxR¥lwJ¿_Xc)2ÝÕGõ"ªm‘ã’gíï¾3¯Ë[>#¨'Ûµ¿Üë³uN[¹Ž\osÉ J³°íc§Ñ¾_Φ-þn0Ι.yÕ¶M —ãÕˆ ¿Ûâ heç!r-1ÄÜø®Œ óJûzmÁ}ãänpŸq ç²ñRÔb‹á1Ëén|™B+Ë”¿>Ëþ0ÊÖ¡åÏÄ?ºth T[•Õ§²ÔœK—ôæØD²l}ÊÒ(~˜}4€ã&äu;ïƒýê=B|{zvPP" îåÑÒ™B¨ZëØO)5Ós‹TšÌº—‚F)øZó€ÈÚ~•7ª°! J­˜÷êIQp³÷ø©¿:õÙ¥o'>„=ïö_´Ç9ÞÊ)ü²x^òCÜw„Ä•`=‚àëŒýÇì&78ew ØtxîV©lq”{Fî·Sü»¼ï«I¿ßñìÌD£¡èࢠ);*Ë¢há®›Œç^ã 9 ‰×X „ômº¾•ÓƒïB0±;â®É©È¬^~Ë ˆ®"Ĭ2ŽóßDëN…¬Ie0Öª:$Í[üõkAòkø™a^x¦Fñ2d:äÏH¸ð¿fŒÓ~3úa…}ø‘·ÑíW¨ª‡U7±7¶‰¯ÕFûw¦Ã”ô¥52Ì}qšE Ö¸ÖÁoîyH“Ø5 L¸VBu=þѺ籎àO™ü֯䴗²æ'æÓ#4ųØý“Ùt†&)¶(B¼†“ìúÏÑ6âu©§Qâû#(ðò¶pÖ<éUœÈÓnÞ¯M[QÔ8˜ßÌ7”0ÞIa½ Ï[¨vAÿD¾Îñ>ù"RîJ¨¢ ,ׇ¹ð\¯Ú¹À]È”2[5k¬6ÕN©Ã™"“Õ’Øî±7mjK[=»?åb’Ç·4sŒù¾õ}ì wE½Äš²ˆ8>î ³˜ßʇHí/±3´ùhì%ΦäpÝYÖ{T‰“ZîöÀ2•žÔ*0¸~RVPe1I‹OÝ5;ô·2à”½ºz±Ô•á2J±fg½€2Ž'´¶‚I}S}å4Ýu±Uk&ª¤ i”nlŸ)ÝT æ+^΄ÂrqªD­dA /}²ÉJÂaƒ¦¢qÔÚÕö‹[TÀܹ¢a°xÿ­VÀ§|umríIûËÂÙ³ÍNÁ6~"‡1ùzH|yT'±¨5ÙÏ™ÂCŒ:=(Š¥,áÏ«Ã&©lt DÞ3ìiËðš3ÃÏÕ8Ì}¶Ìm´ÑÞÙr1ôâÚ@Ò8 uñ¤píeóŒvN¢ù¼Å™w¾òÿ%; ¦(d^-‘V‡ìš¸îÆ€¤Å‰8Þ ü9©†íí`»Ç-öZ®éë ]¿×4;iiÀSôŽ8Òl9L=V¸ï-˜K:“¦‹U´GÏèÝIMê:´¾ÕñZƒ;w©~ÜXž¡Ë ­y¤ Ù&h»¿¿µq•ƒo2¯çd‘̧&7IUƒtºg >îºñ Ñ`x‡$Ì ÎäÁ#ûi™ä;yGoS†Œ¼@2!¨ácÙ{ÅÊlj©âNù %™‚ Á IRàZÎ5Xr¾qòŠtLûÓÄw6ÍÈÉҾęF ëûIoåê‹ÀÕAÅ‹·”;%Ù4¤_²§ýÃu+ó£üj²²kÖ3c‘vQºâ…™C+˜Äê;«€–rVÑeèE`upÜÌÑou„TKoÛàqY°vÕGþÃK'€¢rcž…èFçr€îx*žšI7»H³g웨uÙiñ„—4=âç3HØaÿßû}òàxÐ{ƒÇ\‘k ]äs”X;:ÔŸ<ÚÓ\'¹J¾™âU#÷h*ƒK‡×@Tz—ò°~5 #»ìàbѧ%ò€fÛgõ÷æaÜ*‰\‘Ô’¯^“Éâ3Çb[ßô<ùZ~eÛS(h—…a#yÇo5LFê‡Ãî?¾ÙŽÔ²šö¢e±;Rׯ åÆõ)ÇJlÏúç9f„«Tà‚6I¸RÎ/¸¤s›bá×ðzüŽ‚^D¤‹D` í`{?ät¶Ó£úô‡Äˆ;Ážf'€üi8üve;‚»°&ÎhàùoåH¾Ënd°ãøÆ,i0ö%¢bI²Vó>œEçŽË VÏ]œRú¼ø B”=åç«7»_í 3'n¡þTgIëõ0ü¸Æô.@ ÄÈÒ’Ê'À4`7‰ZÐ c!ˆÎÿ´3°dÍöMwÔÝñÊÃívpù®bÇ“Ö~T»je6¶L½ t¶~bÇÑQ,Gÿ›Ïºé½js¬öíc´ÿ„†ÇhÕ7»'Ñ€,z 6Âr,cŒ¢ò€,ë©ä2JEMH&Õªé†[.eö]"~âÅßaݱc 0rØÖH¸f_‹Çº_ÑÖ }üHƒ³Ãõ¿]©ql€µŽ³úß‹EBŸ|Zµ{žá±ªŠö1TÔKŽùµd!ÆÉG€û‘;M¡úÛŸ„¾}GDJ_¢íŠàwwçgÄbçþéè0rd¸gýzJÂµŽºg&Dyl9jÝ6v5–äk³œD$•T9iWP,uµƒýD>)6r°K„\ ÏRF¦„’ت v¢qƒ¯À; ÖANøÆ]­vGõ¸Þf, ß­$€n.ûJg•aÖ"á7ºœ(hžÚª»Ä Û¿5ªh pÞŒê€5ÎŒ?ÞýàƒgØG« _2ì½mºG‚wàÁšŽ`ö?º_vD‚ðZËù먤¶ØGßüÞ¼_+!·‚¿ aŠ9 ·ÀªÕSà?’LM¢ZÂØàÞ3Ç×@ªãÕ6º[ò•„ip"™m5‡{M2¸ùG4ó#b'3³_s©9zìõéþGbA¦pƒˆEtR1p3¾ñc!©áç† ã‹Mɸ€Ôâ±/~yêæ’ôV~n|f ù}e´ØœWb²mü$‡j˜þq£sÐâ `y }oó#qÜÂ×φ¶Æ­·ã¬¡/Ÿeö†œ¤“,EŸåEyô¾âýQÝÐÏ ”»,Èé¦ ðB›:¬\i´CΙÊâÐ=¾S‡xŸ¤›Ìî®郧—GÀœs ‹˜9bOŽ©’ÍΡ¢±}Œp¼ÚÖÐM~íRXçæA¡·\"­¬pøÖ–­›ÌÙ9‚Ö¸T>€½ò]ÐÒCÛQ”22 ïºC¨~âœéucÈpß;eÍE—K–‚ˆñóÀé4®ykSÒã!ªËœÝÛÒaª§`Šò„¾ìèèt9y?F+†Ø÷}! Tf·ÿ]•¿iŽsjÚõ}ôJl6{­žIÕ%CX”Û6¢?+ó Ú+”\ecÜ:£z’Fé.( û”(Þ×mxk®›?ÓAaæ©gôYÖ†èê’ Ê…¸!€wGåOèÈ8c %:ÈÑž œ1d5CÖ{k—ü4¸œ+£1ÿLlNí¹?å©”fª´D€ºš++µ'=‚Âä"@y‚€C}ã©G‚–ôQÒ¥‰Cçß^JR4pXšr'«öSgŠ7NΩæ÷Â{yÌ› å±óÞ8§ , 6…ôOs"g/Ýåߥޔ·tÌ’óæ? rœ%™6o¥„ ™ÉC¡)ܵìGbqÆÚ:H‡ï'líGhdj°“ŒTÁHí{¾¨ògƒr*Xª>óÅâíZ&Ì:З ŠïñkOö`1|’n4ñÙ0_ðv¹{YOUŒUëS9L¾P‘?0’ƒŽŽ½YG4< ÓÝ éÐí}Øp¦·Æžhxæ'%IùiFvïÅÞ.ízψ :¤°°¬Ý” ßYBØ_•Y½·¶Ðuˆxçˆ1ª³ñ =S7€… uQ—Åû*1J‰†Ï]VÈ¢a1ôŠ"h„9{.Àpº·Œ[Öˆ5Ûï¬ ç…2߬܌ë\¤Wkž“RÂ$lôH>Eªb³kB1 Èz˜ŒÒÄ0#“;ÂëîŠ{âpã‡+[ÈgÂ1À]Ìʪc<’h¤§XîÕ9Ú¥½¿¦lOVª(·ï×—[¶¡¦šÈž»’;w›õ¬üã¡÷ÕìÁ;ŸTú¿ÖþHÌ%[™ôý£ †'Ü9 åbág0uù˜Ë þÿ~Jç©%÷gö,lB@}Õ4\î<ØûÏ[Ó³ÜÁBbáPnþæëТܘÒ­nl´;šµjäèF6¶!%7Ç$·»{(J † ;‘´’jj¶@±¸`3'Îðò0'®6µüO“S gp?[±´ï!7 =ñKx­áåã˜Áð÷Ì*`ÀP¦*ÑŒÚ@Žyà`%ø àãš@ð«:ÅÔàºvðQÚ'%_”õå÷í³‚ëS—¡³E¼Q7ˆkL°”Ÿf'Š4 IýèY«¥Åæ,âÖÕu¬Jði÷ø÷9ù7S}i¸½º9úW·¢ã2ã2Gl¦­Jx ¢ÿö¸Zø­Qu#2Ö°yòšò"Kփ̥ɓƒÕE›ÙùÀ.‚KîŠ)ñg’ ÔÙ#Š#Œ°‘R¹2SûU–‚Â%þÿ€§6®{@``O'ÏܦËvè_V7½nŸjéaUÍ É0qP¬¢×nð­<9¶•ý¬ƒ´Úߊ;øÏÍ;ï%Ì@GZw¥ö&;¦k)zM/༎úxc׃ҺÞ@˜E(7âÞZ¨à|€T0" ¾mD(±Ç©ƒÓ2ñĦŒžàn]£n¢n(éÂ…sp àsbòŒîæ[í È“°›ÕìÙ’O©»xÒógl–œL  pvO˜8aë™_ç߯Ùz% ¨#ßájÈE»{à'Å |v—V›÷ƒ¤ì€¾GÒ_®!$3mcšäN¶w¦»‹%ÂU”òø„ÿÕI Ú úÙÐ!Ï©q « ÝEr©÷õœÁY`+M"b7Q=‘œ®˜8ÇžÌ(yd÷÷!–×ÄQ8™]GøÉFIl4Sáa±òÐngQGuâ<«ÑÛ"ÿ{eh(‹QƒÎ”ÃýA%—¾³Cú‰ ØrÝ—ù62X¸þ&=yƒB Ù>›øëý„êZ™(#«ƒ¸œéðk`ÂM&ë­EÞ4~ºdbÈ#œØ€ºÎef‰°"ë^yÙ Äa®»8œÓsO¨K#¸{™•R’EËÏG‰¢ºÔ©dz€ ÷Ô #·æ÷¶¢c¼p) ¹BòTlƒPI6„Ïi²óYRˆò@‚LÂhP¸&aj›6}e[]fùfÊÚÚÜZ­òIøßc×>Á»åÿ¹ogY_&¤óö]óð+j"Ü?}^êuO(çÿöµâKöÇ{éÀ–ZEjx>tºÞ{z÷ä¾-7Û†|¬} aN"<ÿñì»Òôv¤®Ï4p{PPÕsýöªÈ¡òªÏN]È#&ÑÜÄ/¾T<ä¥+Áܤ!ªÊpn Î&Y§Lõ¨x†¢LD@ÌýwÿŸ<„¬ÆúB4Çq»—4*r¡@Q\]ïq5Ó@¶ ˽Bu‹¨f­ª^ ä«žóggÐlz3#ä¯ÓFTƒóðp+̃qÒ&êZŸû§=ÛIR‚.Ay÷„4Ƶ]ÛåålöÁtQ}ñaÏ-Ôz à– úþ¹ñ÷‹l?nvä÷ç yo1Oùüa›J|Êy‘ y`\U´Šc)”êÃÆNú6ÒW¤^ò‘TRÍôGAðŽð¬ ýÕ £Ð¼U"{vWÐÌ\Jﻢ¿°:†À-1÷G>J^*Õ»«ÈZþ?ÖáäÒ‰óGêt7–Q¿¢oÆ |p«áÀr7 plÒÄg ¬A¬µí ñâJhË_ª.v¹æ.-¸éœLñ[*Ó¤ŠÅŸ!ÿÖÖvôÑw“©W͵¸>Wm鯎}»«)k*Ф‹Z½NËböO^®í£æ 0º¨îÓç8:‡l¸C "4·_Ô•Ò~Dö§Û­G!{ÙkW’ë=Æ”Rk`%"ÑÞLF²¼y‘Ë‘ èҲÚö·E7 É…d§€™tŸfß[o®øøN¿Ë_©Š èÁ÷gL÷ˆ¹¥Q¾ò4}/BϵAR·'5Ìþ7ý´&.YöCOXSÁs¯’ñ;½ ƒxî¥÷ôŸíš=âªÈùêghpÀ9­Þy‡ÄÁ˜_ɂآ[Ó€F½X#?ïgÕv¡Ne™ûñ©ÄJð¨*qÕ `ÄïéQ?_‡èô5º“%CºÑˆÒÅcqå*¢ è•Æ)h:›aL™wLMf{ÝÃêMÜ6ýê×,’#ù îË{¹Ágc 8O°‰vœb›ÑA|¹~Rz²ÅêÅ,ÓYUØ‚F, æ4ñ•Èykò{±wb â°5w<íp„÷Ùò°­vé`Ö&bq+bóédLOðO:¥UÕeÒúÂÕÓÁjž8òù‡7 c9]ûG” ŸÊðlp§2?!3‰¿èÖFVD¼~u²¶ü­é™3Èkà[HÝ©ldx"@¬Vwèÿ;6Å{!tî)m’ùJAw~ÿ”]îþOÊÐo6鹈Hqþà2-ß{ðæ*ЏÙUÖ'D^Xmp‘ÂùÊ,4 iß š ɲð5dm>çB°vÍO]êQÆ}Q™vȵ±f½;i‡3\»ùÉ<™ã¥ÆF&ÅF3ÞpüÈydzq\S“§øÁSÔ£hÝLÀD¿ d¬kÞDƒ}Qå,P‚C¦_!^ÕPVÌùDèÎ6Y¨¹SÍ[ÜlÓ8¨Jƒ7A.¾äÒqf duA s…økÒê“%ÑrIW8¤O:‚2; LëèÁX}EjY‡ÚšuTà ŸÍË=WÁÀiÖµi‡6íµ¥×L*Š ²ÕEÿêæ·’¢ÓÚжiâ<¹Ø‡}9Ž]Š5Íhxý ¯v Ü€iµS¼Jyic3>dPàÆÁ$¶G@+rÞ¾„mÝ…{æçÓ€úrtÇø‹GSïÚ{I«ƒûIæ“Õ©‡|â{‘œÎ{ÕªàÁÅ«3§|J‡è.Ñ ¬=G-®¸b²FJGm^O€Ø¦Jýcú­0x³\*¼ ¨o¿Ï•âSº:%ÙÖxq´I9<>èÜMès…MüNö¹ÈÃ`äâW‡ˆÔÜ•Íj©ræÞü»Ú;#B"ŠsDþ­Ä¹[jÄã\·Æé_éd a öû,]ç‰÷oüRœ¦téqÅJ#¡èóÄYWÏÀr5‰Y ÏAºñ»¬6ÄÙ¸áLnÈÚ¼#ˆ‰(Vûß~ œÕðÎlêæŽã‚Voªs“c­\VÞ„H‘fã’Lßq>B¹C¡w‡Ö‰5{½Q¿éÏoyž¿(Ž®]ÐÔ‘Ôt¡·Þ„DR4øÑ¨JôwP ýoüÊàP-4›ÇǶ󈓉JÑKG! u<ÑÔ¯¾™#Øöz(£5eØÓGzí èZdj)¸] "‰¦Õý>‘ C+Ž{÷}éqòç\U"房ö2ó¯Ðxjöƒ[¬àY‚y]¡§rÅLNHG&Òw¹õPk„ +é™s)H!86V^§Ø…žõÄ–P*6§ñç\†5`£Öï‹0µ±ò†{s°jˆTJöyŒetUî îÔ.›‰óy°`ïÊÃ!ÒAnôÚyQ†¶ãêk&t/b%ÝÛé;‹#ÞîÄ”OʹB‡˜ô×TÜ9×Âîú¢W2u{¶sT—A8kË­{|s¡°ª¡ ƒDdw}¾`•ë¹§ÑnSxû 0ý¾¬]÷Ð/am<=ȱCê<=2¨¶×ñ4h¦¢žgÌ Ó|ç‚ÿ!¾«25—9¡nßLY¿¤>°‘¶Ìõ&ÃNø®mòP ®l¨ìÌ BF(*£JƒZ‚Ug,´ŒÚñ #“Õ²Åíñ/®æiy/g×;J`ßm“Ñ„ß4éê7cN8XÖÜTW- É®>à«Ö€~£Ì%`Kݲ3Uz%)Ï8ì€Ô7Uw×”ðèp×avâ§)y LwÃë2uÅ}qpþ…U³þˆ~aXTo¯<éYW.Hì„¿Ö7ƒ¬DØ™X^ŽgL7°°=ò¬ÁáV˜výë±Q¹‘¹ÈÒf£bL¯ÑÃ!8NìÓ~ˆ#96õž {Md‚í×H…Šf †r$«eîØ3¿‡e%¦ú}Ú¶Z¶."¹ondþ‚½Ž2tÍ‘ýêÃ-4T=Ö“"ȦWú¯µ¦?šG“ø¹ö'˜ç[}‡~ûSH{Ÿá¤£ÄeÃs"4ú'*#•t–"~*ŪÆÏu24¯©›ÎõKÙç©­9Ï¿xÈ£)Ó¤ÚÄtë8“Û Äý$·,YW2í±«8E!›Ôhr{¥&Ê÷‡'hÄó8µ97|åb>šKèÝøzÿ㘆Öï‡~ƒÀÕã «L¿þe?÷¸;ü’›™LÅI 1o(ƒXŸM†pˆ%Ç‚•5}G´i iSžÑ'SÆŒJºaQzš6W€œÕ°ð†h$d×§÷WpuÜ&¼m/Xͦ«/aYzu›çzå² ¼þÔTe%z¦&D;×!—oõèÄ!;Ä8n©×Õ+xv1‘ÕUý˼H ¾£ ŒOx‰O™Ü¹Ygõš²Üá-Šú¿„°[täŽè0¼ùÂì$9(âV*Ä́ؿÛý×ñp™wÂ$@¾Ò­Qy™Ç"Ü÷Ôƒk—¯«ê¿]Ìæ<ıä$´Å\¤ÊcÓ!æÐ–%WøÒšƒ EW†Ï ëª«Ý òÁã>²Ž$bæv|*#‰BÀYºÙâAŸ „Ì@íTHM11Íû¥|‰õöëoÙ*ï™Â}Ÿ¢[fñ0<\z¨Ûk-åítJ‚3ë²SšÈŒÝ }PcØÁp±š¦¤=Jª­§zŠôÃj‡ù…Þ¥1“&Tcªx¾é¸…ËudtXÍ(ò§ý7ª…°ŽðÅ&¨Sôf8,“˹„ãýn9wšÏrM§ÈnÖôü~Aè¾Ûüè8qt6¹u,› ì³ þ6ucšmlOJ.ËùM÷¡£‚'e*!~ ýf¼kL*T›Á³âEëÉ}²)TâG³Dª’Ä[¤ä=$§I)_ÜÅŠG¬(/„¯‚÷k©_h³GAk‰Þ/ð' ŽQlð¼!z›¹¹!Ïû_R%ÄFîëpX±rÉâ(NDPêÔupqÌPþy$¿rðÁN ÄLúÙšáAT¬³¾o  Ì?IeM+]DE²q“JS®°ŒM“Ý•»…QèŸéDcwG-t 0³K]Õ™V²g. '‹,8ãûÌ vwDò ªù×V`ƒ¤¿G˜‰àïÃ8KŒ­&z}eunŸêaÆë„'žÌv+–o§Gÿ$»\†ÙÛ~ µ “¹”‚Xëz}‘y·éÔ—\ b¾bë[L¤ïAùrÿF ž ‹ç¯å­,V>Ùšv«&[ÓΜìP…Ÿ ï8©ŸêÖõÙìÆø9ˆÌhY'Ã!}Ñ<³RvÚ˜ëïƒD\…"Ü⸲žÈ¼„+ÙµùV²© BoÆ~Œaƒ’ýÐrD°7bš¾®Á‚˜¯Œ¨rRWe¬9\'B™ëˆ =¿‰É!ªZ°q Ưz) O%¬öÐæÁšA ßaÌWC,r3¤Ÿ`<™èv5 pñ¸@; ÷°LŸ'U¶ù甽1éŒðˆ;HàÄ!@'Žös…‡r`ݲ­KÚèsAÄ3¾‰PÇ:¸uš7Ê®-o°·‚ÛÏ´÷áÚa5¨y2sß·Äý4C£ßÆÿb—¨-·":¬7&ä½&Él|OÌÇäZ2ÔF¿Èc3¦B¼v£¯gôkkK•켄*¥Å¿fM,áZÃ,}3Б•DêýSà럗¼Njï!ŒÁ-o”b <&‘çÌèè*Ö‚÷㜺4&÷x½çi¦{ÊZäh.„öGëÄ(ˆüÊóõä´Ä.œùÜús—-óK}5ŸáÈ+µÖûÛèÊZ-c)ئ”-ŽW²Üd1¯ÄX€hx®ÐÚ‹üpN€ç³‘ðM)1Þc¥xJ'Y†º'ŒÀ×î⯆"eð$tp9æ(1œ´ßrŸgA½s£u¼ÇN›àåÿZ¼ÌŸ•¨lq± Þ«wרñ†$†Í52‹Û² @MH)¿!¥Œc;[’EËŽÞúPН#ʈ²±îÐ1¥Öt¤ÃÍ_¼Vµ¡GN^ÑGb8Tv*(ÏFÀ¬´sCůªÑ]óìÙjt„p$"ô$19·Ÿ6ÈOgáG™Ýþ¶PN™"¿ä#·éñü… šôKçš‹½Q÷©TêúÓ×(ÀªA¸kõêfÈÍIâw5m2íÏ]D|"dFéFÀUN‚…Ó‡ö{HýüYJô°¬Y]œ5Æ:†m»'”­Žé€xé«ðH»úk«}³¥ž~ •k˜õœ&i”.Ru+8oe_“YEVÄ)#Lg 6vº‡íù÷hÙ!ç+àŒ&^ä‡]ÇarÅp– +°.0jxâ}3†š|ãam u¦Yêýû¹ýˆ($>†µtÔÈÉëÏÌOs©ûà2õ¤±þŽ­é^Wƒmh§[ ù¯y\(‘ ƒJˆ¢ãËj¸s°ÅÖ—³y!Fh‚³v:‚¾ÈåLa‡{b:[dº¨åÆÓļËÓáÀ=Ú ¿Ãýƽ¢ Ý´t§ª¬úi…Ë_ÜÈžmÊ<ܤpÜ­×q37:ªjø,Ì:ÑŽ½:ªj._ؼ.µ„U‘rùOö¸°1uµÍ{W]–kˆ]Rß “h8ÿÙ‹‰ePÁ¨ÉgOZò}¤:Ùååeª7hÉVeau= a6Ss¦$±› É#ey?×µJy·ù™‡”0ÇžVÆ!T€StÙº õб_EQâB0ê„E¨_½;ã•„8 Ç'™sá[Áú¼÷`¤û!Ïd$;rBlÓ‰‚.©§-ôõnmDx†•¼Þh ñ3Eµ¾¢«”þì‹.컩a“Š-ÏêUY®¡wj/SÀ£yÃSǰ…—mM,Ù­‰¯ÉåCØß**€qã«L“p!t-fùÁ‡QýrÙgp.QØym5ËëΠ˜ïôK†È'½Ä€æ[r½@ûU¤ê-8 žXA}Ü ˜oª\’úð« º ¦ùSÖ]õÛ”›)8x[[úó¤ÚácgiT!T#é5qÜžÉ^®Þâ©qHuzT´KÒ_ ó×7Ä¿Iª>bëðxf¯æ™sUôüÙá…O¦ln—>X+A*òÎXÙ¥ÀR`‚ZqÌKÒv´Ãˆ“õ´òl ‘àxMdž;n!¬uÞ2¾Ùvˆ¬Ü®Mh×!–jTš¡!²¾ÉÏþeÉßír Ïiˆ2Ôö¼œ5ÔPÝ›¹Û—K•HÔÄ3+H¿Ê¦8*‹@ÇN0ú½»©!ˆeï@.– sûkŽùÃJô¸Ô9øÓ+ ÎQà [ùÁýÏãöpº*¶žúäU¦ à Ž,‚10cÒFÄH½p1ãx[Y Zfû"x‡˜¾W:ØÖNŸ—ÀãT3™¼ýúÊ iQýƒ Ȳq÷P¡<Qu/c‹ Õ}»NÝí"@Ø]\>hŽäºoéŽâH…>ç†1gâ q2UÎðáííœk‰$a½¹À·ð‘³"q^ªæ,ÈDs´z¼|ÊìTÿü£os]ÛÅ}YÑ¡œ.‚Ö¹F²Šac»+ðjäv2ðœÜáÂ3h^+î!ˆÈž5Ø×"ZXõ圦ÓL¦ÅÛ==$ðia+ŸÆô%Næ,”<*ùæ(l­; ¦c—&±{¤s|=nböÞ¹'¦ç£0o—5nÞ¡Še¦ÚÄjEuäVËG®½É_¸éÒp÷,±ß—M7¢&'@¼Ñl²ÜÓ‡t³€#þ3¢5ªR[fÓ„Íf 60lòÈ4ÀÙ¿kïSÒ:U™ý©xD_:?!—ó!òïRV9ÍëòvkÞ>kp“æn¨ 3ø¯êˆHÅ 2Hô„a´¡qÒ2A¼¯ðvÛ;Ù/Áñϳê¥'‘p‘ ¢^ܯptmUéÜDÚ›*wK~C½dxŒ}dK}–õü³Øoš8¸Õ ¡Û¬PB¹ËÂ÷Õù£ÕR¡ÜÄ 2; ïh<£Ä¦[MøË{ÁŠc+†zÿiäàè»EѳCGéKåÍ7ïPÖ·ù+Êd…W”f†}¾Ó¡™o«¡£L6Ì•n½±ÂÛ|ÀE!7zDý!lR6‘¶zã1‘5¹ÄI¶…ëRaNâŒØìÔ5|àNµ¿1áËÕ²•õÞK!¯„ldC¹7íX¦gkÛ_h — XG6!Íç}/¨xËw^ÝG:_¤¬eÎ_¿j}8Z=©FªgúYœNµ–JÐhƈœ¼x(• ¾µîÒ'ÅBFs˜RªK¼u¸ç¨5¸\ÚE‘ƒÆ¥ L»æý2BV¯¢W•6R¡“LÀÊg3«scÄå|OyàHbùZÈ¢#mN«‡qSäÄB»ùÀÀI{H#sÉ ß\ž@ƒ.û 8ïí(?lÀ0‘µ¥Ïl¤oÇZpüV.¿­Üm²…Š‹kÓÂ8ßÁF¹ûcn8kë"ø:WKÝ}8}KÂ>žPØYsÿ­õhW=¦ïNÝMMŸ T–è«. ,e”ÔÙᲟãÞ­Â tɃÂG4TNºG˺*ÿTÄ ¥ò#û 2wPh ‚~d‰))˜h,£Ì)ßa¬¹ÊÐÉʧ{"~bo°;5ol©i¦Gú†JÆRÓ`R$%\ß5Erއ"|fëœ[8˜ýk„:µè[gØGôÕPu&1¥Ç¿È¹Å)DRÎÈzQ%Ï¿ÌF)ÊA¯µ²øB_ý,3¹Ây Œ$ëÚW‹R¤,¡´G`ó]ãj5^mêAù— 礸eÛž›‡NÆå—¯¥öJ„Ô?ØÞëË!k›u€·ÇRÞö½Wç·NÞúŸuq?€ÍZ;;Ü 1‘Dõl<÷‹q è|A'k±†YÞN– kaËqàU1ºàJ…`ƒ|ƒXxž)ãþ7Ó» Šóxo˜ÞZB#÷ž‡Sæ—}¿ÁdÑ_ïêñÉ›,µì⯜"eœD fÓé[q'Åþeu¿Ã*ø7¨ð 4h¶AüãÜ´¾«]9ŒÜÎ?ÝðÓ;>O5í˜ýÍrÜÔÜT:*‘Zc3[¤"~ìÓážÖ~Q!RúÁ‰\F²1áØ¿]qâ„ÈR zb4ËQ²Œ¶øúTíP0=ÊÑKáÅÆd¤oïF:™îxM½Ó?¾Gf´.µÛlSïZZŠñY+ÜjD^DLáÕŠÁåvxõ9O93@S«SFb·]nŽTìîaý¯¯Ê­`k­ 2†÷YKý»<3=hƒþìÕ*£Ìþé—Ÿª—4ª„“𧬳ÂÛ aTG¦Œ \›éì¼È÷˜%ªÞ­û#W&%êºèól>¿KûÙ…Ó‡üNúžGæ@Õ´×§™ôŠ"ª'î)ç¤Gö>7?þq_¤ÄhªŸ¿Ò¿uÎäÏì¼'ü†uV¢¨ì.;8ŠÕ:†ÉGK=ŒYÛ*,©Å·»Û¿£æ°tß0l¿©P½•X=¬ü5Ê!ñ†+*Ë%ÛŸ/,Ú [ý]òmOÿœAþõ¦Á©­?¯ãØÕb”\Œò¥µËz%é ¢ß1St©èÃZ/’„Ú¤Ãt^Ê© ȪÅЙÙu/ÚPf0+>ëf*¼s^îd -ð#Ûé#àb§Y‰ßs&1kç[1·Qx ÚT©Û”…$€áÌÊ“G:ý-næ'î­¦hnþ?>BÔÝ+–®—7˜]`nt¡.`Ø<7êØƒ¢UqT›}AEãŸ/y2þ‹ãmAÊÚÖ¯ $Ó=:×d6&îðÓ¨Ž')çôAІ¬qZˆ8Ôê[.øû½yëœ!½DòŠª“­_ô#eø¹æ9­õ‡á.“ÿtˆ˜™‘ÅKÏR„O)¸ 7º,¢pM zâÛt «õ>¯ RÂ!‰¿Kð"kNs‰5²5±B ì¾öQ¢K“á„pòNk¿Vßä¾ì\2ÒÀ©‡é­FÏí/G i¿¡òR“}ÑëÔ}ëx¨Aß"=¦¤–óð‚D¢ÜÈ$Lî³Â\IæÀRê’õ75+ì´µ{4‚ œj¿ð|X±¨ ~IV”¿ü€¤ß.éþ”½ù2úa±6»À8¹ÌuÀ*rg¬¾®\„ƒ 1Û¼„ՙϸaLJ,QÛ¸%úØçðp›Y€Ÿ§ÛúhÜÑ^N »%„·¬._Äýë· ôýCt×ZZ ¯cô^G2™K÷L_¦-y²’çãKí%+q@¸›¸Qh— nÙÏoƒè`¯ˆ¢"f‚Ï•¬Ùãy7°u#µÉ÷ 6Üû=°Iâø©Îùâ ëjµ­²0S¶Qé°Í#…/¢?´( ‰–©žŠµŒ— ª5¬Bô¡’ßHS†:g_(ùœÒ«÷)LÁR4+x0w˜¥ñ^ïg/:õï‰ÄFg¼´[ô ]J«pð!¿„ñÞ!'›ù¥vë$Œ6á C”[ “:¶ Ã}øðûïc]EuÓÐX Æí¶o¿xP“, ø€˜ð÷ņ ÛÍcŸñIõznj ´Ã°!©b¾QO4ËÍSâü€¦×wóªo°}¼§b1S™–·YÞ>@Æþ «…H_œb#çC>*OåTå]ËñŽÔ?ã Ø@Cúͽ­Ôzmß Fj»Ýï¹U¢nEšº®D %fõxÅÂŽ#Š^yÆË é¶ßå&5Â`þÊsáÆ[ø+ΕÏ.!6N ÿŽ«¥ÁVÀu'tabR'ßÁ„¬f>cûT¸æŒ1å©r¸Kf$Ø­žlàF (‰™@Cd˜Ìw'A »Ø|¬™¨Gœ*¹•BXtörù³6dm¨nÒö!ÜD£¯×ýM Ý«PýôMábÖ¾#¯žø cf-L‰ó䇉ôùB˜'š•K[ÜÐûCå=íEž8CWE-œ&DË'T¶dÝðAõ‹W|ðîX(ÔˆU-MÍœøï5è5#¿ôÁ™ò¯Šh=ñúÛ‡¯Ô«ëêfâ ±ÓìOfÜŠº7%BðH<¦Íã”èMµÖOý¦ÑdŠm˜K:Š,K‚¤U 6›ð4m~U?*œVïà)£i:˪gc8òž!¤‰ÇÝ¢,¯“DÕ‚5l3W7м­©DAŽë«‹É0õS¡#ÄYT|¬ë2Õš !qÀ—&µHú^å 1¹÷‹Ô‡–“'ªã®öýÛÀýR9p‘noÕòwˆÍ¼cJ•jƒËA\šdHuÈl°Â@ÆÀOÍÈp1³*pî–_)SSDΰjñMn„Ý•Êð5“¢![[çy4áa¹Ô‹òvnö¯*ì’ýËCxD/,^—jH¨HcL‚¿ëü†ÃÙÂìÔþ °Lf…‰õ{B©u?ësÙk„—ÄaAéŠ}ýÛ•Œíí¾ÄfÂÜYþR6ñˆ2I?[·=Iö“r5ÿ^ÛgA0¥·\*ÀÈfðUZí& ¸¤_Ø©ì}£ÿHŸ3ÙŒ|д‡Õa7ù J<:Z%Ï­ˆåv@çU$V äž1¾àW °@fe,~ì ÷ úWì´ã°ðË[xÀ»ŸP©$Ÿ9­†Dr(s›m°GÕÆ0ü‚Ñ£÷Ä ExuD??ìýlqa”­š^l$¶›>ÿÍ×ÇšGšÀÙ¿ñµfçjႲܦ0¾P¾”FS´¥c„Kñì1%V´R"¤åa¤¨Eñ<|vH¹Wt‡å8‚E¨žJY7Xƒ9ƒ\-ýj/Ûe6õÑï\øbB?àã$›k‰yˆÍˆÑ3Éå÷ çÖ€Ñó§ úµÊ(—ÞnKº`ÄõsàP‘@ò—·gàØ‰>[8ÓªTŸR…D4äš?:×lIÊê×ÃÛ'ïµ@yܵŒG? pÉ0ú(ôv2Çy’­Ä`f ™iØAŸ}Rà}uW4´ÿ!¿ÉBJó}s™ÿk¡4ú踦d)väõ9[Oä©^ŸSk;Ť"âÍ6Õrš¸q{MP+Ê\I=áR*X ¥Q¸LL|ᆜ>Ì6.ûO‘̬–àqˆ“›SJÿ×(p5êªfƒy ( Ù[ÔœÙèíþcƒKù¯þðC诈{åÂáÖZ«Y$ÛŸIFãÆö½ÂG§k 4žšXbxÆ&•FZ®þ `ó'dNÁº>ÛÙÿM,“Ø–÷‘nËaSy ^v‡µó ­”¬7¢à&r}*מã²* Lwãò;µ²å#è}×\™€c·'¸„ñLwEÃ1ÂùD”E‡¤öËï1 -Á'Bvl_ðÆÂû0v‚®ÎFÈÞˆ,·ÆTL)ùÓYVÃ|ÛŸ8´ÔEcæäËMÞ>®C;aò0Þ¢¢Ü’‹ƒVþõáLï¤Kç÷õ¸7Ç­ýFZ1Z?:/`HQë¾säí6=†ØÎjÝøç-g ²dv9¨…ZYApäŒGGé_hx@g[•YªjÚ%˜¤ðòÈ¥´6 €0[+×ñO”(¡9Ì ;ä73Èâ(§_¤‹Æ‚!@¯cÒ ®dV‚tJïxWï ÅeòaŸHiî9óÿ ©‡¬d.˜â-ÈMœ¥¯ÏóøÚô[:Sr¦pÑFVš)ªîËïŽK/³[áЪ¦ ³ØÕ¨nÃA2HT„ñš…¹7d|Íâ•Ãÿ =ã¾àCo =²bïís¦c‚Ü_.T¤Ã"ƒ°Ó]6®½ÊÚýd9'&¦9.)"hE&q5íj_O˜ aý=IñöÖ=M#Ðçá-ªcÂk_Š.b¾ú\j{Qá©°°•cò ±~DÁ#?8× Ü–.ex&Õ¬冤Ð->ý#isj}{Ü`»>~´0ד̓½¿ Õ·ÇyÅjzp1*—Ÿ6þ¾{¡ø¢hxãHî¸ ¤oçÀaâÇpŒ;‡Ø·6L:DN]Ž3Î5Ag¯²šµ©ïÊ^J°GDL}txê¦Ô«G{¤nOk•ƒ}‘+áe+saoDT uDÙ€‹>Û¡¼cÑáðŽX¹N… ²ÿ؈[ÏzeZa^õø"i*Ã>_:|2†`ó‚ñùéÔÉšž;ƒ0VÀ Z9 É9Ái9”-p¿¹íZy«ž©B°Z?–&J0ý 'í}‹{˜HpŒi{;*¢ù¢èö PsÚú#A悦p’Ø•¹œiÇá# Ø£1O4·xDæþ$;¶U]å¨8&½°lIäL¹ƒï' Â&FTßP=-&VSБ ¢Á¼ Žú `ŸÑnÃmê'Ó„˜½8c\ïR3ô\Eq²ÍEÒø/ìa¬‡ê‰£*Óî~饂åçMÄ~IA‘ÎJÖ¤55!j!R….H­í¤¸è®F6¸śêe)çDÀ"sBšÚÔ­¬B‡ðxåãfY² »Íe==™Â4ÓP»P˜×b!רƒà'gLÉ- ,-¬ØK¡µÄ C3cÿÒ{¨¶³·0™OH ÆyèÓƒYŒsŸOpï\0w}¦©"·‡›‰™í÷ãú;;ü‡ìÅK’*ÔïRÇ ¡}M¦¬EüvÍ®)œ;aP¯Ü®U(«âsµË¿!7ø×/Ð/°}m$Ùçl/ê~2Ó•®îYâÍúÓÍÔùJ èêÃô9ä[U§G@$Ï•åöé7ù¸ùdQüdÅ4mìæU†¼iæK>u׋k`®ØN“îÞž3.Ô{>R¸Ék‰ˆg(e¬Ð¥SãÇÔµ5ØëǺˆž§ü§{’϶øoñMº Á•J•¬BØ-Ÿ£ÝíøHÎÀœR¥Bâf½¯%|ë$ ¦ž€ç€ä(èŽR6†äÍÐÜxæÀlò†åb ¤OªlØßÅ–wÁñ*€ƒVi–:—Øm?ˆë:Ɖ˜-ìiÔƒ]’DoY.“NAn°zbc•ÄOB¯?|^$e5Y2ñö{ð æ´uÄø†œÉ{vv΢!ÙôŽWrYØE@½©I$Qÿâ­ QŒ¨% RÁ©nQ©µ`‰ÇŠrÍìZåƒ&#¥]7æˆÆim˜PQ€è°Tö ™;+EݯÂÁºtÂÄ¥x‰ó´râŠû9NÂdmú†_Ì=wÊ…Bì@<íím°Š3å¯.ÎPvVz®´»Ÿþ¼½ƒØú©ºkB+ÈлµöZ½ o°ŸUP$ •Vâ é©ÕLŠjÈôß_«ø³ìOäÙHÀâQH–ÕSôÈ¢×–ý¥R®èNÀBÓäñ´k0»gðxz4BÐyÍãŸZjÊ—ÒJ¦‚—r”À"DM‡S ÁuÎsfNÌzv÷ªïWnžþt9*î>¯]N ¡å‚ÞIóû\IóÀp¹Mqî¯â(DOYTšlg¨ŠèbØgLB¯j8ˆ}E†á™WU§(Û6!{Sƒfr‹ú­¶´¼#["ü£E³9@Ô9f£zxiºÕ£éu1³Å¦ß–‹™kÓÌ wÅ΢Läv`"³ƒIi™µ[®ôò°ÎŠ•ÛWŒ>˜O®] óI”aë¤W.Æ’˜±Ša›ÆŠ¯¶LÓa»ô $k×7¹ïEFýþxòirðÛR’4R#œæV)ý;8YŒoY86ÇD:uºoš›îWq7n-½þ6Ö[c,dIbàš2»®)`çZ¥s¡¼€tE>Ø¥öÖ"D`Â7íUêà>IÏ·MŸÁ?(r1DœñöÉW÷pº#ã³°ƒSd8vòåo¢l“ýì4ŒÜÝ«ô¹n<Þx½kÛ‹k=±ê{þ7.Üq£LhV;´¿çoìg¦ƒŸÿF?h±²c\[[Œ8ÆÚ#Òü ²™  òÁ¿ÁD°qìx9í\ZÐY<&üçT­¸´ÕæRãWá®#å-¬‰OôQ Ü'hˆÊ5ÕKÿ‚ìØÖÕÕù(G‡þ‘½Úñò´JkR2evƒËÚ¤ã(t|-Rž÷#´ž[¡Íçanô;â†ÔÔ*00z(ð˜_ËØ·^ƒ^ ‰Kìšr3Eþ¤h}½¶"‘ È~PEB[ ¼"¡κÄN÷^÷AÈs-ŒPåJ1¦ê{Æ"DßÌ!`(¬°GŸxeŒ¡äƒáú‚|Ó„ ‹G/>K~8³6@“¿ï‰RÊGL(!xí~`ß‚ä†\ÇøÙþÿ{WÌ}Ñk~¡•Çát»Œ F>Á1Q)'q1µÊÖ± ØžãYß”Åidjà-:c8¶¬É¡í!ýèlYƒÏîbV›ž‘òn[x¼º–úœ£ÅvM2Øé!èÞ¹ptx@ß/Q£„®Ròw­(½Jõ£7‰}E™²©s9Ì÷-°ú.sP.æ¯É)ÀÖïYP·r»Á¤\¿ÿ¶ÒÖ¥jp(q›š÷½Ef»©< ¶_aràå‡ ë YuüU¡1Ú<0‚à‡Ø(.Z5@Á˜Ó(7#wꃠæÖֻʔ‰h‹­ÞV„á¢öymV­è«ñ 3¶z¿/Vx²” ¥Ý£ÓþmUÑP’ p̰Å5¥zbH…Ó²Y7’7]U“)r=äßdÁšî]íªù×x¸7Avs¤ÊRŽ(ë'÷b`* žóà`怤ê5Ò³öè6‡?ëÎ.îl|Y÷KvTÛ.Ê¥š±¨²5°ÛËBÉ\4N$|™$Å §k1ú:HØã‘d'8K$lÆSì¾:à ÓþÙž8Îú{ŽÎÜôýÌ`°M,}x ­Ôæ78b0WÐ~þ.ý3P¨‚¿.S ºLô‘Æèßž]´ªÁôëÜÒø6 zÙ‘–„ãzx@¶@±%8ƒ lkÂN…T‘yc3\Õ_ ¥íi®¿®¯ë¦¸›¥˜65Ýé©~탹Âz_¢pQôFå‡ÀV߆r9⽈Ê/`úM[)øË&¿,î™µîž ÿ9¡žøÅy)^iƒ@CV£ê¦~B w[û‚Å©b¾N2içÞÈDFÑRè?Ëñ×ZO¦ ¥úét]ŽZŒ)µYRˆ¬ ®wYu½Â¸Ø‹¼ºÜ½h[¬Àe<HÎ&m¾(E ê@ï½±½74:I|\ƒé…œæ{Â?çÐÁe[q„°NJ‚éÓNTçVŽX¯¤M7×;Yeò2g&|A˺”v(®<ÃŒÇcUav$Ú~`ž]KæcHË€c†"}Šè¹º±x˜“ØÕëÞê°#å……ÇXŸ:h¦òFÁQ3J0`Dð]¼[ʶ¬òŸPÕxœª¬ùô‰° ½žÅ.à°Ä@O,)ô•½J%Ë_Æ>À1ØCáŠcÒFÔO„á{—  ¿_dcíôeÈþúùo‘kN$×&u¨Ÿ½)Iœ(x'ïÒ«q^Þ•Á“…MÄ92f)\¡Ì>)¨îÞ-”Hpçu¬¸# ¥ý²éWáÒ9‘¥5kyÖR¢È<ð»r}çlfä”vÃúªŸzã=ÜÓ–ÊÆé/]}Û}ºÄß_ ¸çqÍi˜ÿë*áFºvhG\ÒõNSäÅ€Wï]ø \ ïÀÞŒ¥”ƒèK¦Õ®);²·ü6b€L‰Çv% ) @*f#:°tJCâ…ºØüIÈpþë'Õ}†=ŽlfÊ“jsEV¹{E!•¾“ o;aŒô ¥Õ¹¥Yï¥$p :ƒßº¸¥tŽ©PE+™Q/(ŸÙÁøûíòè-Yw3êX(ÒÊÌñÏ!“Xÿõì³Ì×ÓfÒJ¯\‚£yxܯj°­ùb›]ó§9 &÷9€R.„]™ñV÷¤¥¸«™èŒyÇ9D$Õäñ’¥î'x܃i³~ífJìÑBLaßèçÏ¥nÛ5ÐEô‰ ±ø-Ñ!–ò0æõ4LA>|­SÌ€ÙªszÄ $€{.úå¨ÐWp¦Œ\)Pze8  ‡*×G×\òeAkТþFè]”þhÄ­W/Ë‘uõ$7Y`•Ú¬f0?¸~Ó CÅ×r}އʗ³œƒ×Šp\°!GÊí{ v[¬W¾sVÄÀÞC°Ó9ënÙóAA;¸uN LR—~jÎ?ߤΠµúÔ™5 fh¤-q©ÿ—ÇãpPÃÛh\Õk[¼¼3;vÃWq0uU4úh­¤³YJ¸º•ì!œ1œw²mF=² L#QÝœ©'ìY4ÄhøHRÇ) æ>Ýb·ÏXS;ßÅr’]’½ïZ ”¹)¦°É ÷}3ás'Á™í»þKž eˆÚleÏ“Hýrw!Y¬J£ÆÊeÖª×hKsMKï)IÈh¶ŸÍÚ6½ñš²K ×:p̪¸¸/Ëâ ­¾f'<€š!ïåJ9èÀaÄ PKßNÿjîë¨aÀ]®já´Ì„ª5Qw‘†uÓDßWOCHü†R.vô"Ápæs¼§_Ò—6ÇÏù~¤—°çí¼[+ýæYàôîј¹5{ãÄ’Ý‚t—ÏÁñ„Ó¹`ºÌ zŸNP è½W⟃#wŸó±ËcKʈg}qˆÍ¯¦“Ìšò¿,-$añ5¶A2Ä#RFÖzõOk­ôçËðyQ–¡×´DÉ-…`´±)qÚ®vg7bže¶Ã¥TY “á®5"n®MþˆºÅq˜T>•Îi ±Á*.Yi^r^kLDª1Ùò¡ÔÍ‚ã¨|µù›ÑV%Ò…ö,$ ^»-ÎHkÅÁñ®š óµ±@GY¸´e;æs‰&Go¸)Ø/9íRÛ&Iméá%ŠGq"H]áñ/aG ˆ; Ç_JFgøÜ,ôïÕ¡×ào» ¬2½‚Z؆·ãŸÉzCôžß7S˜âÁ®‡ÚœnÈ-Ⱦ^wBÄ&6LO‚ì8±   #GsÊÀé³Ü%÷a†wbÖæ²8¢Ÿ`¼)ùÀF{üF94§)4·ãÇVNKKS:©ßÂä8«àx?³Þj!•ªA=î_ŽÒ‰:üÉmè â%u°8Þ Ca‚°HqîÚøE1H°ˆtÅhUŒÇ1²ßÐsNX^búµâ O l‰€–ia~ÞG)sй}[¸Œ7¸Ñ¡aG@KŠç2‰$¾Ø¢3¥ýͱaT"ä%‘§¬¿¶Xä6&¿MÕ’ÂHY5Îâi<mmN hd£Q*^×2;ŠO•‡ðªüßÁ %’l GMy ôŠ$¯¢ a‡(Ž´ë¼7âg_y¼úpXóîä‰&ÛyFi0|lT΀_Cãðíl»ÀƒèÓ™c& éºzUõÝÆònSÓn]ô/š×cNÓÞ3>.2‘×|CåΗlÕÒ"-°çG°«²1îò@ñIá³Û«@6viml* …©@Š.ò⢎èþÿñÎÖ—Iz¥ÐÎTi¾åÛž?ykꃣ&ï=mª>yº~B­÷­ê¤l'AÈxF]Lì}'¥½ßVS> ÞœŠ‹€5MåFÛ¼­@ÏkÝItys¼¸¤:uɬ.{GçÚM_óÜe$_@®¸:¦0µÃçÒàïKf[ˆo³•ƒÿý‡6X¶eócÊõÒ†®G{†÷\¯Ôq¥ =º!?]·&»Ÿï{³*¿·e8°Ë2çÕ¾<Ñ5*Üä¢À=¢v$Y†´ˆ¥é›æXßëæ÷r‘‚‡?äk F~úrèêf!Hyu¿\WÍÁô*ŠvÜW{®¦oÜ+§OÅŸÚ+ýmÚöÅ­œñ‰H³-ÔGB'yôO¬Q*ŽÙ“B‰F˜[=O…ÈTíÞÔ}ûüGÕ<\$FÉÓÔ)ÏßñªŸÒHuãš)à$ß)u'µ¶+¯t=Nª.-˜†|+`N|PÓ蛕®ä íºN× ‘Áj DÂ!9ƒŸ:˜UBª=ó‚Ø0ÿ‚× bÔxLÑ(M Þ¡?ĘÌdË k(üùÞ8ëJ IäºîH§ÀtW4cÁ´¤e4…j=Õ0?N iã$Ši¤^)ï¡ aot\$¾tEŒc¹w¦ÏÍuÝe1ZþëDšcK@‹ZM.FÝš. ² Øñ^ÉŎ˘¸LmUÀ‘’ƒ˜)®]0»>()è¿Ié¸èú@àGÅO|;¤Cî&ÂÒOçÏãoogo6…ÙZ¤¦á’£f“šV8k ;1;Îws´Ô;uÝ1íç^Ä—•·O•óBÁä*DŒ ¼ºÚ¿!&Ï›­i̦‡RΊ>‰C¨]Ÿûýa±-KÒ Mì|R›%³$a:–dÖJNæž¶2Ç¢SéLü|ñýQ*Î…]– ŸF£÷³„‘Y.Ÿ5kv“‘/§é[—uáp;—˜îï[Ä“rc«±Iš6_fu‰¬yî’™ÂÒ¯f/û™Btœ]1…@‚­‚ƒÍ¯¦Z¿Wîì  U‰eÓ­@”ÆB9€kƒè„l¢pa^&w‚/Êò‹S±+ô{–5³ ç8ÁqH:88”ÆzxŸÈã±9ˆ*†ý°† «ðêÞüu?Ód-åbŽkKI‰7xîúúK«R\½m -_ò'x\6=¢Ì,;šgB“uÕI[9ß Ò”"¶Zü• :𞤽žy>éx–¼Ç¬)PÇ–0ëÌœµ—J*â¸_òcô“3¨•Ìë~ÏŽI;7žoÁý–H.(¨” 7ûn°Ò¼ÊªˆFƤذoÛÅ)½c^á’ßAݘÏ|ÑK¦hüϳõ9êMN"lëIÌ<æ|‘!Úã\YÙk¸TÐaCTV]ä™ßùÓ©)DL«ØxÃ'=6ÜSƒDÙâLjµ¯¹{!Š8ÞsÏ•ï©eÙ9ìw®ÈdØÕÑ÷õÖ÷k³½t—׋PšÞi~ÊL nÙoæÆçö©çqiÒÛ.奕më0%µKÐøvÕq·E9K‹xC~ÍJ-Õ£æï>0.s_m ˜_0$:òLÙ&³F|ÕöœBJª?,  JÔääÎ9æ(Û^íêȺÊÕN/¶+ïéõ+z]H³uÛKÝ€³¿ßHªÇÚæÅsÛÍò1¶p ¼Ý¡ËH9'Êë>Ù[Qì¤}I‚Ò­)(Xî7𦫑”NŒaòcù[kåOêw|â0ž † ÅÌÞtüPŒIJ^¶.gàžT€ÎoÑîOÝñµ˜J€2æè¿üçð*¶²YÞã¿”¬ßÑ0å€Mba@õu:Ù|‹@kc?¢_ ´x@•GÖr-ü±ªmM˜Aìè±\6“€!?X|»”@~™EnŠ.+n÷kw .‚W•V$ůĉ±ÜÎÂß õ8t÷™ó–öx¡«RÄbüˆ^tÄ¢_M*‚u¦•¥êkv`—Õܽ0¹H&ßÿ9¶p¥zfv¡Î'¹í÷x:ªº1ìƒc”[ \ªá¬ÐwS'ùGk™‘…?‘ ¼*T7^©âoÏpÊSްµíAÒüËÓ¸C%€½‚}%Ö g»¶žowSŽÛÒþó‹dõÉÙÜ“¥…u³D¾œ€MgÁ'°³ë†ÅQºÐå;ø¬ zFm ɼ«ž‚'7k&ø…`~¬PüÄ«;ˆÞÆÄïôøMÁYî‡ØÁšxÏ JóµJîÎÛi rg&¨¦Q¦Å t&„‚jø¸±òÿ.ª]£°/Ž3§ÏÁóªNfJЉªiq!ë3Ï2¸7šaÔ9½ôA¾¹‚Ónò3Ò)áÞ’ïh¼ß|h ’í[Ý`î´¥±ÿ¶ï7, ûz…+J¦'-"™)'†£©hæí$4¶–{RSôÊÖÆ[^ K­fÉZ_¦ ïì2ñÎUã— Ð` Cíð “»­Þ¾Òä[LÕ’Ä•ýÛî’_X*äà˜ðcA,V笃lÈùJ1Ÿ•ß뀓žâíüruçë&ꜗàV(žVaQ%Úá5·Ì×Ú¦ beÀl<ÿîýbÛ‹«˜s¸èóŒÌA»K~Þ\ ñz¸†§Éký=¾~ÃV»Ä©u'Fض)óª·Îä&Ý4IÕ u²ˆÐZ–çkü¥ÆYá+§ÌÈ}˜órïoäJuAƒýÊÊ‹Ô r}˜ Ý*oy>wÏ1Â#v(5]ð:Î:{¤5wOCÀt ‰êÿs+1©Ÿ[åŒßÊÅ¡@ª|¯“v¶È"%ëýû^ÞÐêïf>‹v½eG)ýÄàt<<"ü!ÑÕ›M`øŠEa®q"Åû؃ÅO17¸\RyÒG: O‰QáÇí!-ñ`ÞÕåÕ`-[ƒ3LÉbq™(×+4‚Þ¯¬@k…—9'’„…ML=ém¯YZb&X¢¦éšùªñi $‹µbWðbd6M—ß’ï qâÈ%΂‚)ÊÇ¢´ÅÎÀÏ¿3±‡ûñ²Œx‡\=¬›²ÿ ¤S¶[tè–‚ã”_æ|b§AØ@yoÊ2£%ùIì:ÙÒbKž[w¿š\ŽaìN$ÂæD"AgŒÃ–(ê­ ¹òjµçd•håxPús)´Ï˜…³l\”8Äžaá}ü‘u“–ØóÍ]Ͳ9ÞiÕ~I‹$ù[7(ŒA×8k2S¨Ò¹‰‹¨û™eÈNŽ õŽ–¬Ì›8üœù;k¼à_”ÂON½ìŠšXƒI ¾%œP¨dÇÚêŸF>´".ÀAÝP…$UuÕ;PgÙÜõ@Ô(²#Ó<þãÂ^ ÍÿuiNü˜JJŠÉwÛÐ iåÚ³¶PóΤ»gW7R(t Y ºn oFÓê9}ÈKËràgaWÅ ÷ W4XYè ×å ³¿þz¼ST³ÙõG€hìþ¦ŽMD÷Uú§#%ß±OÅÔëáÇ×áÜÌ^ËÿäC=¯!óP@¼§¬))7Þb°*3‰R,bêæyZ„•ác=©9¶TQØ1¬„ž]© (ç¶\.>å†Ôst?Ì>[6Zk欜¼gãdþß«Ó-vtÛ‡Öo^ ßŒäcÜ».´/Ä—â³^š&MˈdFŒƒ1 ôtðƽM$Âf®uû®(JV/p”Ìò×ý Šv:‰¯ S'w#\×Nchw*øéóà]Ê¡Kñb³ÑÕI¹iEœ!‘a£Í”í?¡ñ*¨¡ 9±l›ŸEQÎнٚ02w$ÔZIÄ7~´­ •—å¿è¸e»þ´÷·îL‚¶)GÐ{vOÙ@º±{LzX8°¤Ëˆ…5úçq²ðn­:²àT2òš.` ÁÛ†=A8·¿-=6œ‚îéAnšk¸ÕQR>÷ ¼ž…uHÚ™U%÷$ù£\ º¸¼u=„Ïlü³ãÕˆl— oÑ(f¸ñ½Ê¶Â–ÊXµ¡9ñº¨îu¼ÍH%š²ÞòUî½Ãð¯„uà $²’hyän[k£=££ƒí“ÇE4šëÏÓ@nk ¬¨ûÁ®­ ¡Éâ¹g*7Rà»^u»˜ÉeÍ·Qzlu¨R8šFÎLÙº À£Í¥Ä’„Íy9? Ö’Zaõè_>›·î—ö˪a?’2³Î•yà4"¾E–™F^B$¨Ñ~I´¸< %FfË1Þ¢6â2JôlE¡ø-ûÊoÕX äÇëj@BHº$Os!޲¬"ÎkóÙæùMp±BýsÇ`ÚÉ„Eø¼Us§A¹IX¤°¨½‹aòÒÝxàCÌA‘•¹éï ó5ï{!î°>Ì-•ŽzÊiUÂÚëêF˜ bt6£–ä{)?¨ì¼3ê¿1+äÚóêõ"Ëù" pÓå—{)Šp 2]ìe\™Œ–MF¡³’Ï[‰ò`›9hLÏ!Óôñù¹Û¶ÿE"%Yÿ°uAY|«N,×Ñ·çÓƒ(Ý FpJW°Þ®_SÀÊ!!zɰw«;`MbcgWÛÞAêHARý ´g[LÖª‹W’Šåã-1ÌÜêø üïÿàѰí¸9Y±ŠÝ¢¢TÃÉNÔá ®fÊM“ý6t•ûhô­èåZÁõõ¼@ð›Sé“,ñR#únø`78áÇ‚ä_`Áúk†X¢Ô§ÐW%‚¼^ºLûP-Mc†$¡™… ÉèïAmÛ–ÈÈgCJBœÿÈîÊLrE{Bƒ2ìwû´W™ÄX‘(Ûýnnf8Ø/éH˜'ÖÛ͉ĺà¢zÓÅ:ó¹tÐés¿k®õX‹ÐŽWŽñ®Á×µWóž&ØSbjJ#Ìöî0¥9¤.؆m k×Eð} | BrëJy lÒ‡Ð3ŠÚ?\ÿ-k*ÊîÓNг×¹za:vÍV9p —RêÓuj}SH.,kN)GYðN/S ÂÁ¶µlL£†ëcãŠÁÊŠ-¯Çì ’,h š`ÁŽáD¥Î.­`ðS<Ë€b3ZÄÈÚ¹ì0Úžé@&«rš<âÔS{u±=ÆæÜ™ -›€ýßÄS.9µ7P³õtx$´ý*²c[°&V_ͼeG‰¼nc,ðg '”Nf;öÿªÌ‰@èÃ}HTÇò„Ƣ栘ãÖpÀ¨A¼.—ò—VB|+—u]}ûmRÈÛøl×ÿgrK:6)¢å  6ì÷üÏ)>fd¥"Ú}™°ÃË¶Š¼¤ô¼ÖKˆ &ŒÆòGTñ7¡&j¬xjÀUÒm7ýü„'ìgá~…ýæ—¿®ÆŠÐ¶mú%ˆ?{S™_zæŸØš÷ÖàƒÔ›9¥´<ür¾¥Þ{7²„î8ß v‚pÓ ¸Ën"üÚæH ÂÍfÉÎô­<2Y•v (»=bo?ì“tÁS~ö‡ó 8ˆš9!§Är¤ˆP¿=…ø:@®Á»su.§`J¿¾…ðx"(•é*AÇtᦈ,A%õÔéäìö¶‘¯MBIt>ÅÖ±¬Þ“ûKòµz0QñàZbåÌRâ †4Z´egSˆ#ñ¼"|EìqØF;#íOúw[Ï»gælÑ^KP®ëcðSZ8Á€/¡r{—n$CÜv©“ï}ZÆ4ï9#­@Ÿw'Pƒ%v8ÇsÒ—*)Ë•:¾î^Õ]KÛоuÍóaU6ìö+Abªtà„ŸöWŽÔ’¼ :GÊVlÎÅ…2zÕBâ<ˆüÞ^RݲQ³-õü­w-hàPÁô=km犸΅¯ÇŽ3ã/ÖH"[JˆÂ*N-ÕmŸú&%ÛþŒs‘ ‹âéЫ¡uhMæ  ¤è“ðá ;!‹¡r õ±©ù›‘6Ô»7AŒ’}·˜&šy)ÉЄr„7Xcq…‚1`Wª!ÌC·°E3xè`Ï.´§,èz•Â^Í9;¿Ö Ø#ä…¯¢6Ìw ,ž~éöÐåVÇ…¤*¦VܾB¦ß½ç9ê=ó<,qÈþ݆hÐ'ÌÃØÒ;ЉÍÞpŽÒ”fÍ Ë‰Œ ¥Aá[ ÁËH%Q7Êˆêˆ w—½ªWºjÅ”6-Ì@kàï}f¤Œ( ß¿‡&M_Ú +åǸ Lâ̶¯÷¸©ÃçÚð‰&Ö9ól#®nŠç£ÂŸí¾_‚kîÎé½Ú*¸óƒÉÀöò-9 I|ÀwÛ>•÷ö<ŽüÖ™ú°Ï-… æ'}òÆhÿ¯ýï~R›à„_¾[)yœ\t47>åwh¸EW½ËæêžS NJ¨_Ð0¦Žfž„áNaš£­I÷D¢¾¡/Që¡Dɘr²€¢òñïB“›ûÊ( mPP×%æ€Âu$4Ódç˜XF€G:2Æx@§F‘£ó°ŽÒòäkÙŸ(¤ÂœGÛdIçm±/3”ù,šå²×óÙ®R¿Íß ëÐÆ+?ßÿxæŸcŽßΜ“ôBŒºö¶@MCò “²¡i _K½¤&ç»S0_<>bcŽcÆøv€bÉn3NŸº5eÏò%³ãâ–%}—=þ-²¾¤g¿\Ô·ºÓÛÕ›Þ[骧£¨†>»òiJ¶Z£ýÙ ŸÝŽ÷ã…ãàÁ ƒ|­"õß^P‘¾Z0ÇHùâyƒˆDåý1‹Ë¹VÝ­¯|†sÛ6=g^íS-ò3P D®º¼ð§\µ¡€ê©¯]Ü›©âøpéŸRŒØ‚_#?¦?#ÿ©£Þ© •vœÅ@à¹K]¾H­ ³Më`i’v:Và`&HbøÄJî ç3öÕæä°Ô×ÿTnÐê‹R»v¬¢›˜¼çd¥ >H©‘ÿRâ.†ä¡€âòí(”»]"…©a½ e~P:L£*rF–?Ÿ“Ù4ñ^@RÃSêÓùå…×ê7`¯“ñ7…ÏÛ60bA"“N¥?{¸ÌÀ9_½)3´‘.GŠp€¥8œ Þù}æ ŠÊo'¹ù|—!”ÖO]Žóp‘$¤”Ïu†z¨¨)æ.”EõœÂ‚Z¹QW8ê¹aðpkÕU™ÑÇVó“FzKS¢ÎÂiôÖâþ3ŸÅ>Ó•ÁÜùãÇþÚ¤µ±‹“!^0ZÚёӾÑ_ad“ÓDBéڸƊ'®} CBª¦ë$5#[­u w˜kú„s]y¤Å ñÂÜg‹üçôß}¯$A¦kxméÏ6€t›{+/уK¿­^×]×Î!™¤›G­è # öªÖ–À_eŽ¿4‚2]ä÷ûnî2«ê­$"LÍ¿ "Àå:“Ä)‰¦P°¨A¾D A¾Ìž›i .Oš{EŠÍx{Ī­{ÚÕþîç¤ÐB¼€úª=x‡oå¶H•8*iµ|ÄXbƹâº1HcÐhø8ìãØÊYH¬nuíÚ,à>EÍÜŒ¦{ÞTNÖtà0¼Zc¹qae3&$'L—Åá4x/kL¢ã ö+®>%øçÑ ò×´$A”¬™w-h16N’™Ò# ˆÌ>#­åf…êážáùˆmýÚN(íøƒtÚ–‹P¨úãÿ¡«R-%¢^¼9X˜0[D‰^P2>Aùœ–"sUHD‰œ² |xð9„Ù:j*RU:ÞðFýžè›o¨ïÊפT[~:]”S€£™ñ:iSô…bûP ôŒ–·|º[’Å’úãô$ñ,—Á®Îu[–p︬á•5ÀÓum|óŽ)¾Øk‘j´ð‹D+¶1†Þ)ïó@Ñêtô²JúhM½W@ ? ­_jê¸d d §b a>YÏáftú¸¸{floÅ5¤Ÿ1ô× ¥|ÅP0þQX--½qíó „Fggn‚³…´ŸzË[A Ï~ob„ÛÙ“ˆmƒçÛN²¦ „'¢¶£†Jì*•Á,ᡜ¯O«Ò-Í+sñÞ‹¨.ËSÜÎ ë®þšÅìry+µ&’¯?©Áù;Ô2@2Ñê7,¾u1®íÆxqƒü)§BðM$eHÙ[¶x$tßB,íQ2ýj°Øª¶*ãzäè/ð :Ñ¡Aûö<Õå£ %*̽=Z&TmÌ€¾ë¥Õ†€õ6îÀ{Xd™È!’T÷ΡOMÍu#¾œÃZMˆjCÇ)ÅExÇ›š; ·ž}hzyż47Ô˜÷¨÷cl#ýÏâ7³3’—±>tåêˆ ì¤²MŒ„ÌÙtê¨Ø$þ˧U9±>…³T}bÑœÁÉUå˜XÂÅŒN!½„E â/•$­¿py‡€7 îûànõ~Œzlꨅ °Ý¸ZJ¨–c·¥AqrI‘¤³òÞŒYÊ„n„&+tú»¦ˆ«%c¹œ:§ t@ófyBpéŸLûi±Û³ 6¦îzçö²&ÔÆÿ³‰"ô9¯‡,·p´ø"×Uœ9À¼-Sœ¸•¥‹|€ TD>qàÊÁ¶”mÂÎv3¯2ÿ¸…s9Æ£yï´ÖóHœY™v¾³^°ò’ ìZ Q#ëR<V” G«é]Ôò óò–åÂ=žŸN·dHÃOdÁ¨vǵQïôâž(ªõjñLšA %ß¡”myaŸFÄj¨Ì !qø6‘ pêpÙ‚«¦\ríDE!.àŸJ×TÛ;{£{iJÉ)«ZéÅ®%ËX0÷×â·¯¹ùdC¯“œÊÛè³Þ¥‹²í íyÁî îó€ÛtÓ¸òœäL*©» X 3LGÕ™I ÿV7CnJÇSÀnþ[Š2=¡Öd l±±ØiÀ I³AÒñe«û0]=E•²³ÀØuq®œ= ß,5+—YU™«+W‰„eä ¸aV$|4åŽwx—3”@ks&/÷tD¹¤>sÝ6‰¼ÅsbªÄ’ '¯Ã¯´¯}˜ú×[ðÏ!8Afì…}æÏË(©k§ÿ@ßZÉùé•Zr YËŸâ¤pà·d­:ûóT €Ñ¨âù>Yv]äÒÀñ×Ioànªðò_|¬È›m!Fg–Ç#È©žµÊç0Æ¡dÆs¤sO‹ýü$ZV!b%)%ÖiÇe¨¡ïX‚âMå]€¹ñú+¸ØUœW!9÷MlÉCùà1A뀣¸âÍa4’ß^j.— þòí0Õ>?÷ÝÀü‡›lÏ¿óSW°0Ùù†¥–¬d÷ä­ë/ÌŠêJ›Á˜ñhðÞ?Ü‚]±Ä’ùP?¡¸a. éiÃ¥ú˜Ötá)¹ŠP³~T¤øaæÇûòïêtjw Al)RÐÅ:£‘ÀÙÁû÷vYmY›Ø]0øÏB¶L LÈàsáív7ð3ž3ÝèI?)ÍœÅÔY¢KÅ îû’¼©˜g©¦õ3'ùÀlñtäÂæ‹úÆbhp‚À48§’ИˆW€VÃ0A jTçÂRnkÉùvfIýL•å›ù"” ªø'Ö:ý¥–éq{ö/UBÔ­ùc@müúoÀÙ' •Nñ9ž´&äaØïÇ_Ï^ &*ù[’BÜ÷^K®Î›í¿³ªÜ‰‡Êí¡ró¸.žîCv9­Ãàm$£, cY²e.úÓ<&hXÎA|Ønj¿tèµüP]5ÂW ææ4\Wnõ¬ë‘KäÞBÏðV&F±œð÷Êi†bRÕ&W'­»s¼ÿÀº‚±§¯€*Ýì°»W@%±°Ž3¦R,ŒJ±Ì3[ØÂ´”kMŠä€gÅâ'œ€vãR»}¾hŒþ;Ô³4§ÝN1 ѦÎZÝ`œÖ Õ7ºmq Љš/Kê¶ç°®öèLWÙu7[1èðypÛsSªŽ^GRiÝÇé.„ec©Uñ§ì‡bPYœnÜ;i$æ°…Ÿ¦æù{ìL[Ç_¯ÇµkºYcMmÑ…‚X8ýïœh‰b6ôÑJrç0Ó'Xžg5åÒe™bÐVçhìœØB©èR´|¨ÜÏ*ßk|<Éo1 ªÊ£ÞAÛ6vòî5ÈëÞNT½ÄÏ]_…KçäbÌ›ƒ^b®Ùr°pЉÅ&YŠÓw‘ËãÓr{8,l±?ÐWí­n’UÂàèž‹DMÚ>¾ìñ‘tŒ†FX ]ˆ(ªUk¸R—½heX¯uü”sÉ{P3ÈI†ï¿5%¶Œ0hÑa;çìXØzYp)ü„ÊõÂf=Mc“Tªéí=ñR^&eú 8Ûtϱ¼/ænAŸÑèÌÃFP ×´bõ<óä̵½Yo…U'VBÁ¡ÉãQT¯¬õî˜nÑGè)Q3=FÚk1"…}çÙ.6´A¾žEˆ.›L5Ø)Ñè°=×»g’UàV@¤õ9uñÀ#xX~¤½nìê.e¸$/BàцҠŽÅÈû¥¸ÛS¾½¤n RÉ”L/LÎñÌüÙÝjøY?CIÊç¡Òàüªv“Ÿ¼ŠÁCh q &ž¤Ã¥W͵`’ Ž˜‹Øz.©'Z¥“ÂjFÓu´ðboláße³X?•ãÖ¸#ìöˆLB^×^G™”ã{‘~¼ËxÚxIxÐ5ÀÌÀ ¼ÂÖ‰z@žœÞt809z(ȾÅEwí/Ä¢,Õ_¥;Ÿ•">TàÈAÄŒ­"Ö¸—l²Ö³žx+è” nËÆqMž$ôsk‡éÓÚ‚4¥z·1QI™šO ™§‰^<¶•»µíãìQE¥!è·3ÒÏþþƒögžŠÔS+DU¶ù)¬_ÉZSvV¡~ˆ+#ŸÊœGuÉé]C¨EG¶Ìºò†Z1  IÁ]%çŒë_i4‹Ñ‘ f P7Ý›¯¹}Þc¦ê2J¾™YkÒóU65g2ÕÉ®H¶°í¨¼O´ÃjQ£‘*¶¥ É¥]c؃`„$J¤ƒºÏ³¼-Q³1vŸœ°xªUv‘¤{É÷âö+k³„XÔ^cE:ãÖ§x1Óôw&.ÙûÃÿ?÷ß]¿†T«ïÉ¥ßÐø™Ñ.äšaܹ/ÐCÔí5_½Š}°Þ`„2½uk`àUs;“Õ>T“øWó¢]üHÅ: ÝÀ¥À²¥´wË.µ¢×ýŠv+d gÈWLÝ¢CàS¶GH s3Ò ÷|ä¯Z/øSvò(¨FÈróÅ9y£¥uy ±×Kå2—b?YZ{·c˜:þ¢eǾç-MtÅæ=v\j_6ûcñɱûåžá]™Z ç˜.£o˜l·2ýQóøtóÝEœd¼RËMâX,#LûwI‡UhZÇi‚!-ö–ßyUˆ>g^ñ,﹉É+Àõå±ìÞܬ Æaa²=50 ÷-Äv´’K+¨ŸwFón!O‹>(zÐXr E €Þè,§°ä[l¡_˜ȈøL=L By¿†6!&ŽÈQLfUs¡Å•‹ñûí ¢Æ¤ìÛ«¤Íu¢ —ÏpQvÌøJq¦ûðt–¯éMY,Æ¡äuæí÷®_%w‹‚TvA§ i>Z,*rŸ_Œ]ä¸íktõ‹×Di3ˆ¡)ㆭIªàpŽïò ô1+¢n¾‡¬~! ëDAš!\]´›JÁJtyYVSì¼ðca‡òa1*ÛÕÃ/¯•éÊ‚Rß–oòI,Md”H<œm#‰­ †’)ÈA"j~ÿñõÀͽ÷|Ë-fÌ`›$‚¿=· Z÷V´][ALþÈ«:ì†wõsÙÙÒV†;«ç¤7û†yËÖUÜTó¹íÄ”ô"˜~éaP`÷EÛž/ÿ¿)Öíöÿ0z(ÅþYN4KµY ¿u3÷‰ñgxÓi©9—?æCÝ à~Ùÿš`“-±‡xx(Dv/) ɵ!f í·1îVĪ?áÇa‡ë‡à\hQqƒòP+¶Kòžã¶Õf}°¡†Qüs8ðŽK€P‡‚mR‘æ…$ùԊÖ÷”?gr“ô “¡Ï^ž{'wšÃróY¿/ò Ïcxmb0”¶£Î ´4º¶5RWsãI”/}³-ç}Bíß”îÐ\~°–B Ã*Ä$³¿£èÒ#Í÷Ä¢eh#æSÀz„ïÎ"–ƒ¶ø´•F¼¬yCÖ¾åÖ''¨¿w±š€ó[RÊÝwê?tÇ$¨ò™µ8‡ŘÖ_#i¡­Ÿ¢Ú¾[j#cfapŠˆ Ö ãµ³ÞÃí9ü# XR/Ô“ÎZeW±W†SèÕç'0j·ñ/f)}K+y˜øÓ sž¹ŽYûÀx˜ÙÙt ¥ÄNYuÿS$¦‡DÉ¿BØ^Ø£RÇà‹R4žüÚs£übÜPrã¥22ƒˆ{ƧìFª4qÓ¿åÑ¿õGÍ>¨IÁ55]2ÁÅ£±q[ØÇÝ!f721ÁÎ…ß™7"Û|ÔÑ‚4yhM½'`_ËÏU"ˆ¥™Bb!›á×3Ã'9¬I¾›ýcÓ=@ÙhÐlæf@IJ`­!ñ„g{²–\Ú9Ö'åñVæKÖÔ¹H®è¿Ù6ãsH3³ì/þXÄ2sÐb âxó?jÁ@¿Ò#­ˆÒ"𿺳:¹‡ÍKE%5×[±ÏAcHx°è1†À76OÚá/<‡ô½Þ7o]ñ º ……b|Î{ù:(-_1©ëªÂOÊ$—ÇÓ“íþçɳs:Vôü é>&²ý¯°AÃS2HØ¡œ3è!îÒL¶§1/-0>Fq}íršõõm$CÎló?;ÜP¦Sf†Fë¶‚ î쎳ðnT œð»âÈV©]ôvG`ÖÈÊQ˜ÀÓ<ì[=&5+Ȱqwnå·X1¥_E‰)µÖèë;‘ÑÛfµªQû¢ˆíIÍ‘fnꌋgY=WÅãØ)ðv+$~H§°¨_®éÅ0d0ÊBÃ^B:s‹b?f¬<¸,@ õñ¾¯Ã/ÕŠsy·Ü¾ŸqF‚N<Ñ2..wÝ%Ê•îÐð И§Ò•ùé‘`9QE1çf°CG1LÆîy° hûÖú;Ô£ÂMÏ~ÚìÛ̉øudgÉ)ìir8Ⱦé1¯N¤’Ãò9njMÃow7z—ª*DÿdÙ¼*•âR…Á4EÏè êuKÏ… W©”åï°öÆ–z#¢&ñ¶(PŒ5|ä#Ü\ ¤)xa¤¡™yBzJ;#@ùÉGÿøõL.fí±ža˜üÀpY”#fo1õû)ƒJêE”_'}ŒçfÂb[úŽ–áä70Wï¶f(0¦`®Té•©U³I°­•Ò³<‰é þéA©fÛ”O€›¼Žr•׵Ϩ|ýçBßRó(Žãñ<>lÚj…µø±U¤î6¨ìg„ƒ‘†zö’Þb…¥³»±íuûÂëx}kXãïÉθ?óߦ~Ü¢IÍ Jc³tt/Ùü t&©¨‡-YYˆ]ãó™ ‰«•0«x_ÌáÞ8 Çÿò5æö ¹‹˜RŒ Á ±Í·ã© <³º§Ÿn+jµw^Œ­šaã\ ; 25<=Ac‰ój.4ŽF¶›’ö4}Æüz>Ù.‡\ªJãª[ óübÑ$Zý¤Lx„U6Œ{s7ŒÔxBH>‹h`?¬½lSäDÉ/âðX.Qð8ëô.kÞ·@¢Q[pذ8cQ˜½<ÊqDsW„´5ÖiæáM‰M$æóÆTSþ5ƒ]õ©§š qìAú“]»^‡B¢Š-Ôoœý8kv±BUâØ—lDÒ‚é“NÎÖÙ–ÝÚײ<âÌiàø}AýŒ\ÖA(L¥kþüߟb§ŽŠ·¨”ŒxçVÐæ)T —3ñžóJ×rç ¢¦nŠJWí½7pàüOÊL?Ç»ÞHh³§;;§I-Û¸]·}À#I9™ e=4ƒ ç“ǺÕV챕Û2Oé±çÖõ#ñ$<†¦…ò;/²Sí£ébVQøFl]LmUÔ?­•ã%Ö‹ºÚMÿæ©¥ž;.4Àæ“{\šá9þ¸IE^äûdè}ß÷üö ­Î!Iî¬3:¸^<^sUºËp5*‘½*{^û`8U]Ãl!- ~jrMKD§Gr²C¦Ì"•Õé:ÝѨÅLùA¤Œˆþ;›ŠfÓÉ›P‹ò/…ú×·bs]"GMlcñe8xbÉ—¤ÈÇU•Õðñï=¶U乆 7 nkŸ Ű[¦è#uʤ°¾^wN¿›Ž  ³½”BšiyÒü¤ñ‡Ìp¾¯·s~u§ñ€oum J+1 1Q8~N­ó—ZÙò‰Ó€ Õ˜bÅ€‡ÍØ*$ØD?N;"‹¬íŠêì`1㈃÷3ܪ2#lŠza- "×Á¶Ù¹ª¹X'*âWn¡ð¬5>âÏhóu¿~xiŽ69á¸XŠM‚ƒB~b,ïߟ9Cai†µ°OÊɵ!=¨sÇQå;Ö6ymw+63©xsæ^;òwè?øsÛ—¦©‡P/„Q°'ÁãMœz©§áR$#àYÒÕb 5_@ð×+Ó’±›àDߩԴšˆ))Ž6Ez§tkŸ0Q…¯w}¼ÖØc¬…ÌÙßÇ$ª\Øè™›ÒLÇ•ųµ:™Uµ4ÑZxÙ\È GÚ±­"r&dy—Ey‘TÒ µÖ>hlŒH;!/ØŒ÷ZØ>\áó…!$΂ r×—ÃnIá%{ e¥þ•>)ú-+-¼43Œ4˜ËRO©¼GBê;B®·E…QÉ&„ÒAGÁh2ƒ‡¤7c÷5ÍŠ⼚<ê&q ´Ò>×y±›y ì]NPN.]°ÃV5È:H¢¨¬°t5ò´-cd&…HŽ?š¾ct²xQbŠÖÂU Œþºç«ý8G QÒ¦kPÛžPœÀ(jáåY Ëñ˜á.¦ IQ]×ù­K[¢ª<#ÕÜOD=ŠÕªÑsbP/É´9³ XwôœL×À¨Æ6.sßP¯X@ Üg(©a§1Ь³g Dª’ÿLpÔ›ç³ì¬þÐÒ‘Ý3ŒJãþ-wpd£=ê_ÉT‘J*pØ…V“òzK§f™§/š…ã¡•Ñ7–Šw¹ô‹[Œœõ]ªÐþÎʵ`DÐΆåy*¿Lý‡©‹'=ñWß–3¹ÉÔ¿ÞO“÷âK ¿¯ît_Ž¢/YŸÈ±-zŸ ;ó|ëƒbtc…¥{?¦Yšo©´“¦e©^ûª§×í5’uI@^[áuƒ´¼.‚MF¼ôS@À¡\lï/o ÉßÍÌ‚¯£Ja×q5úùÈØ¬pÞX¢^$'ðcÍsGÀ¤í³;|‡1Ì“ú_gÅ j6ñ‚*ŸTegø°3›4m~Õœ|ŸLÆŒò¯ò“ýMG¦Ø'À¿˜P†D+ß±#³?Ž€á²|º®)Œ“Êæ ò/V½Ý·‹ÇpŠl*°ÆÁ:í?¶ã¸Qß+´Y­!3ïa>OÙ¬ó¯ªçÛ ³± [G EÕá «À|V ®!Ö_Ñ+Á *QN©ÓuÇÙ¸Þˆ£Üc©nÙ& xÐ]NšµÜŒÇÀ7}Ûô2ôÍEþˆ-¼YÅÀöK.õUVr­ý¡ˆ’ã°mÞ= HÛ§´ü“¡ßSâĶÊé ̳è[òDÃ&íPR?€–¸Fæ€úŒ? Ad÷oIˆÇ^¬ü¨þÀïTë §Ðê¡d"Þs¬Ó”ð¤\=빉.~m´:Éx¿—sc‹kÜ ܾ|]²Ê‰Á¸ÕY°CÔê½vS\ªC૊kV­TGþŠ·‡\t~ªû}Q­˜¤Ki2Hxy;ë†ø¾¥J¸áž«„¦¦ØBüØÝ o¹@’l'!7ÒÝìs/ÄW5­àøYÊ%ý²´Á]^1sJ§Ô ĹoT3¿SA§y³ø(ð9|%LÀ íqI¢Ë¡«ä > ´QëðX,žZ)ì÷¦Þò4Ê)W0 ˆ®vç}ùéK%0µî@üTÕó7¶SMÑi]Z”™ü*´ =twŠ‹È5·u'õªÌ?íGþ¥îH!ŒíR&Èl·x¶JŦT@_¨&«ç©QQµýj˾™ñ‰ŽgXçfQ?Úo.öå˜Ë—Þ•t^ ¾É;s¯‹>\=k÷£‹ƒ+¯&eÜ&Šq,R‹Aõ3[ã…Hp‚Áñôw¢\|ŒÿYÝQ ¢‘F{àæßz ì ×§@˜´œ(=ö°ì.¤nO’\9ξQ~¨w°Ò„ä‰=#~ivÓéàŒØ³Mëí‘¿ÈM]íé|-ðÜô×”fít,Pp¤Ú€e:‚7žü ‘'u¼<«¯¨é1-”â¤ç­ßXËXh)¿RÓBïP²+=N󟰻W>Q.KVQ÷䵌[ú¤û.Ðß!M¢bë™ ]åi{÷]ÎùÿÏum:(×Óׄ´ÊHñq #Y,@ž /b´zº€j¿uª]x¶Ñç“w­I^è Ž=E$E…ÌÂz5‚)'4v öhøz^ÿ‹ÑûZøX™¬¨ˆW8ÖÜ Íò&ÝRìJâÄo•[(Úb°O‚vU”—_÷å›¶ „·C)¼J4éT,ÇøËl&(rhªÈ‰æÍL»"âVMòËÖ_‰îD„0rÔÊmvò<>bZÞÙ욥Ÿâ Q>£?Ü /¨è³çWœˆWu"k“&oîÚi`¾ Ð1DÉyIA¶mÄ;»ñé… Ÿâõ ¯WjÔì½ÀØa!wÞa“Z ¬ilôú('ivóßf¾¨~OQðÞ,ð –ÀœÌL5-ø#é4óÖagÈXɰ»O4VLþmz |;lë1âÁ~kD&”UZÔv‰Ê£ëºï‹ü[nˆ Æq›‰¨Í9æk¿Í$©Äw˜ŠŠ^£É—&\Gm/±t.8AñÍ…²Š aBµÊ@ÌÏí­zwÜ«#Úcçôúj1ÂhÛý„÷Cžm†ÓÏj³VþE­¬*؇a¹cyRpÔ}è‹çÝ–½rǬÚq{,`˜Ÿ@¬ûs{E©a_4C øbßL…$ˆìâ%'èž~9’‡ØôÝé#L„Ž[Èt…À|:}Ÿ.E.PvÊ£ºÏe>åe-]£ QŽ¢S£EkWn<ˆÏQèŸÁ„ǟ ä&´2ï®Í[rÑ¡^]'>Y[– >ŒrAµ†æfyÊæßØ JoAòÅ‘|Q¨Œ?µÐò áM@] lüBQÛ˜©¥n´¸óœ8ÝS%F9˜ÿj-MeÕð”õDMí¦¼Ú¼fB_]ú¼J‚Ô$ÿøÕ¤iÝa{n¡q›ÄõðFÕdÈvw ·äpÊvâ¢÷åKO¦¥‹r•Ðî\jÆ}K‘>Aúr 'li ¸­•iš¢ùh¥Vï=Û¢Í5/`«ÛXL-¾xfrKÝš餔¥†){ØöQÝYP¹Sö:½`…ꜿ‚úo>¦~{£¾@4çA®eì*ÍŸ’âõ•põ„ÂÂÛó†~Å ¦ZbÔÿCFÛK*<[-ÓGÔ/âB ƒ:ö5ÅØ`×a­öù÷Ñ!œÝO½:%DøcTŽðÑye !¢z¬¶§°ñRDkBìÛ‘‹c¾Õ/-ôã.oÝ0LrÛf¾N`!º]]ÂÆsF΃ É±_[f™&+öþ©°ÇøôjžÅA&³˜ƒ¯]d]u÷ïKùáX3AôzÑ…K÷C°„'ŽÆmݚ͈[0<èðoCKsŸ‹þˆ©2læ¦FX>üîá}Þ§Xí6!ý¡eÇ;<º¢‡·ÂPÕS\Ã^{š¯¸¿¦¶BJ7ðî' ×…¸OÅ:µÔg('*UåòÁé·bÂô‘åœh’(˜ yUK²WF‡<ëd ”Èðí§ý*ïÖP’ÿוP üÑ¡©ž©n׫Ó[V@e¸ÝÁ(Mn/ý­5º(]ݹí(e–—æÄ‘‰}x]ÇÃHRµ:Ÿn<]¸JqµˆW%oOD‘a‰E-äúG$ˆª. ûCÔ¯±3|9½\}¯í«Ó\PƒÒ]]SM7à#´—½gÔó‡#¸òövø³BáMJiXA³øH^âM§€¬íGìþí}Õøšl­õOåFeU ð‹Âv¼õ®@#*멦¿P—ŒFA”–:Îþ³“n=Ø<Èÿ¾çÓGÁËL³»Þ!1->›+pf§^,0T˵2¯ÜK:_¾òõªÆNQv®òðnk«oCôeƒ ý«£khÜûãœÖ8›²Fñ?26DþtÎ[ç$bt¾ÊgvˆÂó,ÞRéOg¼ÀŸ’D0‘[G’ÍÝ÷£Ý3ÚEþ¯+Ov¨óy•¹¾¯‘uØ‚¨:€?u.•ŸÇh^ƒà™—F–à –º:UOyþÏWDâ·ÃgW™ 'š(sÀ+}_Ú‡<^‡§¥mlq¡Ëì¶¾6àÙáÍÔTꜽùo'©ÏÔi—2õ]V~z)Ù–ÄM°˜iK<´:tÔ£"øçJÜ‹=ì‘–I¶>“0Ÿäç ¯Ï,®âqÖïyï,tÐ?)¯'Jøö«ºe]½dãòXHM(Y2Ëc/E4!äOï\Í¥ïE$ÙɅؽ@Ú螀5á…¥Àªg ǽ™ñUo¨M2Z‡>""Ô×1õ°2-nºU2"ühvÊðrM™»]AÅÜ̯ŒéKÉGNr¸’óôU\ħT¶ì Ë(wÏÜ ¶‚d„™$"âä;ÝéðDz-~ÅtÒ’5\ZúÜ!‰ø€ôfÅ]÷©cz‰¸Ç›ÔZ—%æ%°Jëä>Ù¼äbÔ.*Õ[± ÔÙ¢GÀ©ôÔ§±g©“!½ ÇLãN¶±t!Ôz Bÿ¼—ØôT‚rШ‰S‘“§E§},ßlpÓ\#£Í6ßVB|Ñ0'Šm¾6£KhÌØR×킃ˆÙÜEp 5†¦ÛkÓ*†ù"Æ¥¨kàݾÚó^º4_/­Åâmv‰ap½Q A ÔØådícÃ)x-•ó¡–ÐÑsñ¦bp¥ºÕ+þ‘³9,üv‘­â^!Œ˜AàcšÄ1È˲)¶ PÉ&¦IfÛ1éÈÊh82¬jVî)‡ aÒß’Ô(øµ'·ÜçùYá%™'åÃQD°jŽÜ™ò®¨Þg“‰½ìÌ^ƒ,eÒn>¥™j¼ô®ËLJ80&¢Î!ÚÔ‰Ú_7<:ýÞ}®ì ømÉ&µKíª‘Š4¨-$í ´ý*PôpkQÉ©ïtd„”9§HL°åÚÒjÔc!·V™pêy!BYÈ›¿7à¤ký£6Qñº0Ü»ÇyY¶¤¤æŸòtàŸç*:•^Ç&€'2sX“†®)¿}QŸ¸¹6ÿàôûb8µ‡»Mxì„\°äBça1&:bÚzeÁežž”k,”:,¼OÛ_;“±ë²/¶_/d{(“€EÝãŽrX‚ËØ½˜%…î##Ž\U× 6Uú²­§ì¬±¤ì%€‰uÉ?öx¿üë‚÷zföïõW(¶…_­ÍްT0¯oÜ68¦Þ¿­¯-ÃŽ¥Âö`Ò­oØØ¾QÃ"{a`*hÀâB¨Ò¼,;ÿNœM Ó#OøÍ=Tuø—VÙU`¦§®G>c [ä`7&¦†íL¤QÛ$Å,žޱ>ƒ³Þú5ÞPÇJ¨ñrÓ0˜šY—gâàf=ÿÜ‘ÿèòFPÞÙóÅŸ••ßRš¨1Ýì=›m¯6¹°v®fyÐ ýs™0\„î¼î}®¸MQkŠmOøU! ÿýLBx¼Ýwy'Ö˜ÅÒEy²§ :äïë{‘Uï"Å_êµË6e1¨,†\fyЛ˜¾a½"°ãøçÿâ`ùÓH×,ŒöÌImbÞÂöæØ’î¬²y°AüÅÀ±êX\à.}êQŸ Qg*êÆç#ñ2~f@f¯‡§ýax,†ÄÿBôë í$™…}^²îÓà÷a4eÏ[ÛÉÇgŠ*Ãöûà)Ö€¹) BõIì67Ú«Tr?éüBHyÏ Î"Ž™QïÆJˆ‘ÏYªn~«f“)wòšuqn«ÿ˜JWIuÓ1¼“ãZà×LŽJŽTÐA?ï {@áÚm$7L^µ„­t²)PªWÖvˆ³ÖÆ/´f…ÐBœR¸aXv6vÆwt“ü`¹ˆ`¦¶7Ÿµ\£¾ä¦[çÝ–”?wcЇÎé•Ì!< 8FBÒ¼¿8£!q8Þ!çQñM—¡—ÍËú¨o™Lª“ÞQo'póªY»F¾f0’Ò¥¥®‡5¾‰2¬ï›¹¬£ ®  &f#}ZÙ<Ûô’²Øökãõ€­Ý!ƒ0TjPù«ÔigÙÖ‘S5ƒÈ8!¼…¯Lêê-åۦμÌWÔ(lF‰ˆN¨wÀû0z¢U¡I’¤QÏ ‚y7´.£ Búäªcr;fè_ÓÊã ¤ †þ¨óQ÷÷™›Î‹¡ÞŠ‘w+±b”ˆ›ýYQuFu—¨®“°yçμ=S pûn/òO/TÜŒðT'fÄ‹ÒdGAŒÁrN”©÷ÕªöoÇ[Âßd”εJ'Ïbv&ê¸'½“ÈybЭ/Ñn¼¥ö‘8š9Ð<ÛÓ=ZËúëe‡(ÊÎB5Þ~æÛãžÐ&‰Í0CwQä5ÎuÒ¼M{û»Žqonï·Ã×Âo«Ätqxy­úH=¥XÈþãèºaÕ.LBœÜn[¥îx[ÂáÄ^7ÂÀÜej2HÄÜ¢Û9Å@ÕsLÌ:¶\ùp?´± &ý)Ôaž!ãÈßõÆB¼æ®t‚;ÈU%û$¿»O¥Ù¦9Ý¢B¸Aî©eË_a§dWT¬–Jþ+Á6HÅÎâÕ?Á–p-ÒåŠ×ÑT°JqÇÐôqÒÚ ô’šÄ%&¡Æ°²šÚ§tòØ…¥Áõ 5üp‘ú;c4 ?J½jâ6?f£^дÌ,zÛŠL’ºõíT! “uÞŠºë3Íb«ö÷ šþ"u0]M°A8™q¾†m-&¼ ƾ9Èc@C\¢Y=¼: ؼÜëpùèó¸5~«hD9 'Iñ‚Ê‘+â"»Å~t8É’ ‚ò?ÄdS¦Û;ÈîzA_¹ó# ‰ÔìŽ)‡LÙ%¸æ"Ío• òiå=CsÇÙߢ±ã·Ea"¼6&·ÞÆ5å_Ü2 2Þ½±äöóåÿ9iRÿNímš#u3Š¡©«ñ¾“ZY¤èùÓži6(EH§‹ž;ÌRø-ç-?—£«@>[Ô4²¬½“,7ƒéßô¸ …A_ŒJ“¿—ÄZ—8$BAË2]V\„û.ÕæÌÔÅq”çeþŽ~6\G2íZÕ¢m1M!c<‹¦ÚîRånskâ¢tZ+KºX"ÑWŒÿO>ÿ?îL €K™J<ñUi›Õæe—7C8Õwü*¡dI(¿ÑíÎôfÒ¤n6÷Fï€}Q€åFj$*åGL†è“@ýŸu•ñIžr:ñÎ)…±òçÈŽË>ª–Ïí¸Æk&«Õ™¶7ÛÔª!Æ©êÊA ß7JÂ,²—&—!tQ¬DP Rœ@fW`¨U®Dd_zY¼òŠž£?Úô,ÛúõGîûDžGŸ´±þ/£Š ¾´ãß§ãûÌ‚¤M‹+±¹ñÙpåu—'ÒPTº"Ë_ºƒ:²r‡EGƒº±‹ú\|ÌV4œ? ´¿(zÆ‚OFþÀ’vwªvV¢ì$,ÏÖà®ð:Ä X "ħ'N;õ¾Ï”ï„OB¾6éÔ ã05ÄLÀÅ”ÆV¿‘Ü\šëüŒìAx¤{î‚72± ÏÂB¹C– Ÿ=&+„·äÉØÙ€ÿÖQ#®ùß´1ÔSD7oì±Ô’£.}èjxõ@ö óL7¶]]b"©:O¢4±„ȪŒàúê_BD$ã_Gù&.>³§oéú2ãðâ9 K)6xû3mÌsIéèãxçOäè([õ…vÁÓ®Ý=¤¥2'‡m)œpË‹#©^%dî{¦wìqꟾ~ðkÚ…aÃkþ8=qDaó-Ý3cÙB‡Î²w+z[ÈW`°Ä ©ž>ªJ{÷4 )]Fþ^÷¯LéÁÄ'ò6J$B'1 !iE—¥ð¢ø5.À#=ÍkLŒ-­pžl¼Ä¶‚¨¶ËÄ‘û°ÅÆ‘+9¨¾s ÉÐ`‡;/~I°éxiY ¤ºt+R¸ &éw¡%uBX8% ¹™ÞâîÚ¸øJJ²G€Ù͹ïœWD°bT¬ÙíÝÊA×0b`rÞ/©:¿V¸‘*irWö!"¤Ý0ÁÃHk±„¸;Ÿ²³þL>ó˜‰oG·bé‡[it çäH½£‡C¶þ÷6ÆwØ-^ÙİLYä˜Á=ïRÿº·¬bÞ JïL»˜ÊEAVm¸˜D¶H>qT9“l¨;&Ò–p ¼3ÛeøcG1÷#›ªùúhÉ6ÂX3­ŸíÂÊÀÉàÀ¥Ë¨S•*öÜuÖËÆùøÔ&TkÀþ‘™‹9“lb£ “çîÐ8ŸÑð¥+DEHU 4æÂC NZ5”K½Õ*Mß²Õ.Ó5½JzÚ ž°0—q)MwÚž0ø™”!ç[ü‚] QœmS­—Ò&Ä3›{TI’?­Ÿ}xç+P©&«0vß²V§wÝ×YM­£rfË‹Ä-Ÿ"ÙNbWð‡Z{Á©«²oýíz'scmðú‘IÀ~ªx¹E#¤wlâ]¹>FyxËÒ'° Í?pÈë Â&Æt`ÓšÉ Ó§(—ˆ“Q{«ÃQ~BO;ñeÌ<Ø|÷cü´„°QrIöÚ#} ZQ™u{Ìr]JÔQWŒ”`*÷"WÖnçJ/NCjZsÿLP{tjp·WOnŒ« EÞÀ–ìä‡K¿ËCŽŽ¢ ,¿Õ9À´fàtÕ)'c.ž¾|ûù?½×ĉä¶þ ú(;„:ÚÖm59ÇOŒQôqÒÁ\p°ínŒYsÛ(6,ø]ü÷Íšá£:åQ€{s0ùû<;;·P«áK¡®š@fÅ“:¾¦_F€‡ò^ëÑætë5ãpœ€·®vvÓ¹§LS´HïÓ.UâÑÁžÇQLÅËÖ-׎PeÅ Pm”öÞaä3çÁݨ󰾯HÊue3‡‚X z(|z¢ò#ò ÷évÄ&@¸ ‹÷ªœUºË¶—Z°ãc µ?/=]­^•3þVI Í å&8«Œ^[±Ï< ž‹×Û*®çRSRU•AÿH2£¢§·`°çÂÇŸÎØ«ôÈÅ }Ì5*õ$™ÔT€6»f^¡È…ø&-‚œGër@ b£¤eéÅ£cy©a1ßœaüE¥J‚Î6PÃmdHˆ»xM© ßÕ^–6¶W|¹®ÐÂY¶aÛΘà´B_§Á£ðeW‰UOÀ«;0eÓYŸ +_¤uêš7Ð ^Š‚dq­ßr®ª šòb͉êýÃHþÙàwü|qïVâ†cmüÁÛŸ¥÷Pu^>ÕÄ‘I©ap’#ž[R uÄsA/…äíÿ{)…"vôÿ!Ýã ŽÀƒð^pͱT¡§"©…M¾Ö›W ÛN¸ü?É]½{Jqî"ÒϥǧÚ_fdR°\§N…¨ÂžA†/c*½eœÁÉn.…,‘ϗĘ~ã™FôP•kç¡sû6ÿ½µ`×]­~õôhGI{Ó|0o†VAOÀUøÄÝƹ^J_uN_Z„W?yªÐ­2VâéæFùß&N35åòRÞ°¬£¢ƒ»7è2Ô €þ+¥£%NÖgÆœ›{²ÊÒNéÇÅ==JN)GðЙKöÅRÀEh‚ ÉfM|d»èËoï{ ®®#Y2 øíØ™H»¬GÊ™„^´…ؤ.‚ÞÅøÁ»ÑŠ@ÙôS’ä‘y$…¯ÿY5:£ú™ö¾jŠ5º“¡: /Nݧû¥€ÏìÏÔ~“äño¯ôˆ¦Yb ¦‚Ì$»›[ß'â35 útö„š^°‘ô 냤²ÛX©¤ôAnÓÑ^¢a×_Q‚-j<ˆÙ0kF¦>\{læ í=ýfâ&ìjt§}‚¶ho?U†Ò©m‹‡•¶ëH|Eiþ© ^üZP#TNµí’ôÒÁ€ðïJà¯fóø'®؈þ6™ó4Ž£O-#KÜi– ¬1*¹Z‰Ž¢Õr‘ª" ìGõÕˆ„x‰¿Ÿû&ú:hÀúˆ©t³û) ³J®±“ìK†.ËŠ?$oNGP–ï|?$ô­±‚8Á@”SGÙ§5GDú—Mû߯.r{5ümx¾¯‰úÚŽ)sO+6}@iÇé·üWˆžþ±pøìóíž4çæ ¢ý]ˆSÏìïD6 TÒ?:³qæŠÒì„-J¬Ã~i£ð_Ì=Ir>ŒæÑ¤q©™Òd¼Kx¤ÀØeJdrƉ¡Ñ\ õf­_ìàœ‘ÑâEWç%tÙ×ÁGÞú>ïç{¤oG‹”[×Έ Š^¸ûÇïcá-©~²ª ôs½ÕÏ£vÅ!Á™­ÇVõP‹~÷ROcíl9ž;nÈD¾Ê*É™š¥~…K³Aòz «æ¦²_~z„ÙUÑw&ôMÁXrÏ/€°â]Ƹ7 Åxš/¸ÌI¤=9¼1«\²‘ê‰;³ã”÷ç´Œ¾kĘûŽS,ùC±X) V™F|ˆµ¤%á³6—_§Ÿ6±VI'©›Tc‘±½D¯4š‘´Hù$—|&½ß>NÝÍmß%b¾õ¼¢Z\ý£ «,$Qs(.º>F3T©éȪkÔ6Á¢îF#ìk?9ãN¹ü œo˜X‡Ý˜0"e«ý3߯3¬P¡pt»^›“Èß(Lvø²lšn¶0@jršù8 }ûäã:ñŒéÖØ]•Åû¯5£Ñ¯/Ô 6g¸An£eÃSgÏïv•mŽoÖRDûšÃLhÛ6y•ˆ¡ é&–söBR¤†•¦Ü¹W€»„š99(2 ¶Ôùop!‰à̺Êú`ç^ö¬#`­(Àì:}ümÈû3ü1éáˆ5ÕµnéY¤Ö>3°²Å\¦—©öûÀbÚ¶½{ˆ$ÕœH®:…Iß°fÎ Rñ"µ¦xHæÊßM3#ƒ4¨¬Ê6aÿ¤‹×½ùqë®x ( BÞU#:ãû>úÿVlÌÿ”ù|¹rã5 ‰sO>e·zñÊ‹Mæ7ÖHÀsÔ{SŠŒdLUŸ9iF.۱ܢ‹rcü|[(Êê&Ù k:™2Iç¸~£ùކB;G?zEy&C~ÆVÉ;C`&ƹ‚Œp¾ï'7Y&ƒ“§Ž[R_ᇩ]6³ 4„*@Ì%@äÜYëÜÒVÆ0œÍ§¦°Ý g8…Èvöò€À|e—DÈ~|è’n@B¸´(äS<=4ô\E/:úB1"í\ªÿ–h8°T9 fx‰ ¤á©Ic\i¢}ëÅÀšGA÷tï0lÝJ2“ˆn¿·;± ÌìxaÏÝjÈ HÞŸ7H­‰:¼×£0‡JM‰^ôî¦Bå†YÎÐdjwÖ`,¼8%ÇÖMþ^ ]wÿç‡8Rž\CƒÓqI®úØVI祎Õ.l?I>‚RÔø}N v¯£àsKz§^ËËÌ«Ów˜ÿºsÀe·q¡ÊnVN=”fˆæ,K!`Þf==“ƒaÕ+ì£àôóñ†ëC &IJl<މ jɈü®™Pi3„Ò6œ[UE|h¤¢RÅüï æHôj÷Ïg5qu¤Eë`e{ªÒÄ• ôk1žÑ3uàb˜¥„üûýe¹|sͽZ ¢*»fŒ ëh!ù sļ¾´ÀØxÄ¡ÜT>•„áÚài„òÎJ&y”.{-^¾lœ¾ÒjgóQÌI¬§õß¿<÷‘»âݾ _NÌú¼·³®‘y[ðÜ-íÀ¿Ñ‚v7÷Õwô!Æb±ù…¹‡yvêqy¹8 û‹æB§;§GÉŸs0Óœ„·`°2´Dîq'’(ŠÀèXo^½xÑ”Yðx‰™(ÇΤm’YŸ•*E`0·SÐ>"xl9í»µ;mÍ[pJºÍsttµí @b‰ d—Ç‚M z4žt›ð‡ àgS,KÏåÏÛSØ@|*ÿ~[Ë'œÆ‚aë&Ôñh9-_NÇ” ¾Põ8C‰ôeàó“p â,¬“\Q ’·ZΙ£;@Bå £#›J½Ó ̇½ÓK$Ú¨™òþ¡¡’Ç•WZsz,ø¯MfÜÍÑ~8gÌì]ü3±•]:àä,——Ó¯L“Eê&¿Æ¿t -Ñ)<•5&Fw8{.?•†œ<•ò–%óRËÞ}7í½&ÈS O5|( Bæð/¶àJÆ€ó!!ŽÄ§­Ÿ°ÁÔf7¶H‘a•®nqÒ”ÇèË·+ °1:ÃL-Ö}KÕ§\ŸtÇú²ÑzmfY~Ôæw é\õ3YÅàŽû¼k ¥€cK}?_OÞq{(9å2SÈ“¸P¨2«Y!ýEóÒóX. ½]öµ¥vbîØ†}—œt‚÷ȇ„ŽÿE ÉUCŸvô°ŸOn”)=?ÜÑJËÁ×9·ä~6R´@ß°š…FÇÀ%"eø„_{`<+¶‘Þí=/%¼ÙŒîÕÁ© & çJCŒ¥ë&'[[S;*¬)Ï8Öò6¯_Æ3uLýà+pÈn®òUE_®II7X±;ÜJØ—¨îzU[²|ƒöC¼­hp.(ÅÄ$oñ¦·Nk4(NÀ‚%ð ÀܱrNC{²¯R]™t‚bœŸì›¿§3¡V×Ï&±©ÿ]ôúfˆwdŽxì°ÞÍÇhøh Ž“•é°}YjSÑ„ ì¾QGu:æ1LÝÇž`'8ÈŠ;C´$dðØRK캥P"Á£)ì…È34`³q:µÔ¯Ý?©^¨K³4…w6s¯ï3G¹ÿ¬55íI–ÜJYs9R}ÅÙex¤‡¶e‰¾e/)¥ÔT4WþÓøß2VÑ¥‡·t¥fÜ]¸¼D÷ô¥Í¾s²-ç ®L"e©ÍMõºÄ5Òòƒ5ÕàY~÷¢9Þ5'h<¹Ì.Üfly§ÀSvÎÉË÷7D]‹¼Re¯[,[°úÉ?çóc®à§JÒ/‡jž™£>Xœé7Z²×®àðD’³ó³þìÞ¿GK71Ÿå:9ŸÎ…РîW©þ†ô)ÑôuËD;$ð1‡jS¢­y5rüI%è<ç .Bé’°§ŽsÇd”¿YøYœØÕ–’Ü‘-X9C°Ÿx²Ñí=áñ¸l›]ãõº¯€˜Ö)šŸ@êÍ/„h…'`{–}E¤(™}à Rê7Ûß1:ÚBr„•ä  ¶[òx!-2WdV7ms£* oC§çj¬ÈJÿŒþ}AdOîo³ª÷Z`Íò)Ÿ[ˆàÄÔp‡_~R–l‹dÊæó‚õ× §G9‰œ!h{Oƒi Íexl.[‹ÇÈJÀ”¹¯ûÎË…)›,äú†oftÑáV”DW}óÅ()ÿGçõJv6•ð Z›SÒÆóR ÊnkÞ#‹›À\™7…¬Õ zGd‰i®ÁÚ½~ ü}w^á‚3 «ð¸ã/?9‰Ù…m@»³‡Ò¶-Åd?ǵ~Þ™n¬-^ÛF$i„¯Ñ¤Œu˜œ­šœ ÛÍå¬b38Vx4©ÊÏ/7mÉ­¡á_aWöÙAAÊ~q(É#¢SÆ™ÀÌ$dY…æ][vq¶u]QžRKŠà@ÈDú„78 ñÁe’J*S,¤gÖ4â`Û‹b»7Š î¼ñZýÊzŒ¡8‰.QHTJR-šù|On=æt½ …ì²E«!ž…`“n?ÔˆfDziÇ2iÙáÎUÏot3ðd Ý·†¸^ò”î_ÛÐâ(a£9[(yêk†À½LA2fB+öáhÔ$âS69 õÚ©ºZŒPwŒ;/ý;b—Eó%ùK¥¾i‹±œŸbA#ТÔB±6-$š’oËÝ`¯Ï„1"±LwGZ3T˜Àû}^OÛäpNBiADþ«˜°£«"ÄÉdqÝuêñ•…´ž61ÍÍÉ[L£ØÝß%Ææ/Syvñæi»«nE×® JÚòæâl°†Îçµûw¥¡ò— ¼4!ver60ãò^ð.åÅ;˜™üÞ›wÎS]ƒS{AÎj€ÑêE¨gþäiåËÂáL ßÜW÷JÃSÇ›ˆ,1 ›»Ÿ|Ðæ1û·ZçÑsÊ&»9¤¸4ghú)Yx‘øšðW¯­×S‚DÑôLCvíÚDánãí¡š.K“M("âìéD>ÚûÞ2üË_s=ÈGNq¤ìrš3#ŽŸÊg¸á Û?y“3ƒÝõ‚´‘;’—Ëÿ‹õ€»e\rîŠæŸ˜%K?EÒå$½ MíÂÈsbi^Çô¾f‡z£;1%‚X ©£ZOy`poÔ ëz®é Ÿ$—›œ%Ðõ˜[Ô!î„Ôˆ¶mgGk††îø:kNP²Bw¢F:5ì#&mç¾Üü›¾E½ö‘žü¾g¼£2+áïI¡ou”.ÐO?OÇ$¢šÚò5T¯j>õ°ÏüÔ»DêP½¸†m²éQÜ5Ÿ¢œw¢µÄwb¶ÏÔ‚æ%wúµu´!‰ @#äái¶,¶‘Ä ûæÇTi]Н¶oC-kœïÄ”< q+|“êN(òç ñÆ؆.«hè8ªâ•r×Z gÉ'À@l !4Yüm‘øa (îí7N¤»éùUÚ¼¡4õx¿“{¥ŸÙÝÞ˜Ža–¢ÿþ¿~æº üš.¯¡d÷È`OgqàêB@‡7 |°žŸli»R>xò¤e]‘’ÄU4m /âàôc_ɽHÆMaeÌCNËozÀ¶F ^ÿ&ô{Vù¦ÝE½ÃŽ$?a{†…è!ím£@¶"£H% ͘4©Üâj÷f~´#÷Œ„“K1 +Ç\Â}3h)ðյ߅ôü/—:³<·³×I¹Kþš<Ög¸p\éûUVñì]Ø»3d΂J·îŒôž2ZÉìpßè»ÿµY²Ää×4{E ¢cª4ÌYy“Uqb@ûÍ)5ãÒÍîó€9õÚêdØÀ–ÛØžœµpÏšÚ—àÙøŽöå׉p“©ü•½§$záhs…Î…ÀîeÈ5;B”&üÜú9Öêö&’ð&¶1­5W$’ðæãõÍ=Ó¦¤žõ.ùÍŽ•¼mº:S€TZ üj¡ÃYtýÍYû|î߀É.D ‹fÍÿÅ8 ΂kû—`èϵÑÆ‘©]NSc>¡p™Ó€x‚°ÉU).Jz¿ ¢¤Ï*Ú‘ÕHe”"ùÉj3¬ ³º”8aÄǤIj¨O#¿Ó/ôÑŸç÷u®Ú{‚ký~äÀØ…¸!Üt`ñR£Å]O+Í&Uš?áUœoyJý0ÃÏ©÷&ªí]i dP…A’Q7b¯Wë‰Ý¨oÿZ‹=Ña“Mÿe¯ÂB^m¾ujJ0C!â Ã…THƒ+‘ áÓAŒ„Lu%ÒýÏj:i¢â2šQö†÷†áÏ<ÁpQ|G/ePBj¢ÿP<ÍåÆ œWýóQdÔ²]wÞSv›ù—¿3hKN~“ã52Á[Uk¨É-G`3pQ<í1Ó/ÂÒƒ£Z@×hï¦ù ¨“ÀyÔdñvÞa¿ç %O]§°åª\0Àõ8¶JÛ:Wék÷0¼K½pçkŽ=ž0!65¸ ¶åIŠé„˜/•|ž†q®¡ú¼Z±¿k3>˜ÆÛecó+Öô°—#ƒö•àvHrüµhfmݵAêBß)öyêíì3t6ßÈš”Ñ/ü{?t·/K…hk. ñÔ»r‹zœ;Wù·sgHºÉK‰ž[ª}uöÑþÓøsL+¦ o)ÔB›ñ²ÖmÞ8´ì$œO¥û&0¦â¬¯Dõ€°%“ì*‡AY=¸î³»\ÔIyã>®Auî§uìx‘ñö4I•$Ç×µ¯Ré>f-Í!Bô™±Ú!éAc,Í8y|o¶úoo¥az›Jv­:~Ërm|üèߨãJKàç–†$@³æ ½Tê{‚Y¡ì.'Ÿï`ÏÖáàN§ñ>0¢‹|Æa-´e?ô”%ëÓ}Âã»ô,jé‘Ê1ªóB[«»À"f  £b/8žv$u\8 <± P#-ŠDÉ {ÔŽùšI8*Óv.+£K¿°/x—šN3R©$xÅÒ{áÎ×Q¹&oy{½oÀ7øÔaõÄ~=ÌUqôK´lÜT$ÉQâOßÿô\( ȉTê¾iÿ§kõÚYr»›únN‘¯ÍyóeÕ¢Àn,p÷¶Ò‚„œ²» Ÿ²>–³Â–ÿ„û·^WnÁœ§3©\aZܰöo]2Wý¬)+6Wl5iaM¼œ¬«:Ñ #ßO'שÏņñó¦õª®ˆ£¬‰ õy˜½™„§ ìyÓPójuÑp¶Á-©ßBÜ0Ãwk~UäÌøßGa¢ZúÞOÅ!¤{=Pá×SÕ†ßí+ÚÜM‹  Íu‚á|³"Y[–œ'¢Ñ.>¿QVÜ™nÁ­ÛÄM?“/7–ý<Ù.Ä>]Œ öv7[ZqþÄù¶Šè2aË`‚®zû±øWHWž çqe¯ÄU·•I¯L[üð]öpÍ“baSüŽÿÅ×ÒÎ-þS[¼]˜]øÝdð»ç®h±ÑŒh’“#%!?ñåÀE+F¨Éqžý-[ú§—šT>ÊÛ†Úˆy+€Î´•špPÈîáA?;p‡_ˆqÀ„ЄÞÉ[Ûµ´àø~yL3¾ìÝi'œÄÑ )ºG ©ÌÊÆsôÛaÖ«¡è.S†kNÁóN ìÔó±ûu)Ÿšrë®W%°¯†ù<“)Zî¸ƒë¦ÆTÀÚòÄ“hëTTšâ!O—l+ýÎÇ7 ‚Ä(­‡¿è8‰ÑL–CK`öWÌÞOÝê£3Î,GŽh“û¬êÜ*Ò¤’Õ¯#¦ìY¢™€($vyÚ7{ÀPRÒåòÎe{Ð,û=+Û[)m‹d”ðWð¶÷ÞvlÛð]ÆœíŸ ='a&‹Râ®[–عñbDÏZŒ"è)ä9»j{éè¡È‚І;œ ¼¾ÆH‰~å{sM¼Oµ¯ô|½@@fä¶‘[p¨®dCÈ3¯™&¾ö PS€þGµ«ÌuÆsb£ë/»§@‚&X‡Î¨ÀX7Wå¿“?×1úÿì» QCû2¾Ê؈=;•j³¨‚ÿ~Í¡iùÔWÁ0 T…«·ãû-ëÎé ^?¯×˜tŠC‡bh1D.yÝô_,•³«+œœ ;Ö‹Y›ºÂµ÷þSö~š¬IŽ¡=Ðø žŸ ™H*Wðóå¦rUj CÌŽ6Õ›JE[¢ð|v©«ñø_ÆBß{N66«2·ñ·­ Ý8&áÒ>öhL‹ØZ xïÜ:´gßeaúÈUïmû%j½™ÜWng…HÀðö%$(`ü©ûu1\‚öÎêÈQûØÛ ÐÒnó(Û´Ó=BNü_£ñ¦.4‹Û4HâHLHšTè tøó¥,q£àW^ÊÉTÔ]¡KÞ"Ü _¯ —jîòñôÌÿˆ Î&mYÌíïsKz2yDÖ »/¹QdF!6ôį ÷b†ƒ<ÛI’\‡ðÛ\ j" ìÚŸQiY€–Û¡Þ»xùa§Å³qzlõ;5(?Ÿ”´Úî~7YBG%C?t¬«Í’°u9´´ñoœ }h°™Žç›X;în‹M߃;øÓ‚ùò^žñ¸É0άÞBÿø;Åo“ÞÒÕPM€ ûD§Ÿxy˜”Ë Íð² µAP0±Àh€—KŸÞý³2`ºÓâv˜ZxR"à(vËì²3|ÆôÔ(oÏŒ…\7Ø[GPú. ±Ó(@%B€DÛéMñ¨û›ÕŸèk_`ìŽo;ãÞS–@Ç1Í*Ðÿa™’aÏ“îü¤*ÝÇwÍ'¼ˆèH·éâýÓÄÞ†74m‚ìî§ 'RQ÷˜ÎçWnËæ¾:xb[ÉnúpÑjPøsÚ² ë ”R!Õ]sBë\ƒB¤ónè7ä´bÄ' ôéáèt¥ÌsšÞ#î @ÿ0ñåêp¦ÛmN锚 ï"!ÅÃ6µoUÙÇŽ’Ë&X¹rË Æ>…FœO,þ® Ì<$fj§@­Fš~„—–Òÿuø]kQ–÷I{|Ū“=0!­ÁWâ±õ÷¨YN† ¾„¦þw5OŒLu Ÿ:s®60ÀëÔÍ'G Té;lô.Y¬U~ÈOùëPÅ'Tkî?æ*YæÞ%ǃ3ë®Y’´öêvj?+_ç,lr eÿ™FLÅT?~ ´¾he³ýŒ®ƒ¿ÃÀüÐÕnS Ž’Ã“z¸bø#ñ€4xÓ |Wî¿,â¹r·‘.¥Bð¼A¬‹+9ýn jµ^—!\íZJýDtŠ)§좈êf~ï©öÌ£7.Ú#¨Œ*N]Ç'D}(‘ᡤ_kÀ(à`#‰Sá×TÞª]bû“b£° åâF¹ÝíÑjLŒDh0w ¤¸ËÐàÑë˜Éœ¸¸Ë}ƒgÚˆkôv Z=î‰_xØ`–x-% „› Õõevt@ÞšJK©è 0r$Ã{–‹q%åv¸±–ddã¥ëý䔄ò\·ÀsÕï¾g€ý%àÓŸvߨNBCÍ€øõá?ÑC>L lEÉ­LvK2MÖ_ÐŒ°(§tëXï[±zа_ħü¢”“G ¦‡V¼×D:{gDRÝ„ô)î:ôÏ-Ð!ZÍÚ%Ú5%lm$VAö€ÌŒC…8ŸÞü‡Ö©[æÁÛÁ-šÊ ÔÕÿ-ø„¸ç® ½fr?¸Ž£$] ðÓ,bÑæ­»FJ¶.óŠ~‘Þ.ŒPþÂhâÝO‡¨$Z)ŸúÞöIÊ‘RK%ÕeÙÐ=ç·Áj^ dòF:êïÖóíg«06é[«ñÙQVâعõî•i±aÃäcǨ·ì)½d–Ûý’d…èEYØ?–ë¢ôÚ™™s6˜ýùü Ôœí‰Ìü™O°!š®ÓOé:ÜÎJycÛQ5Ê£E::nÛšr-‘Yµ9>qŠ0‘wšöý­ˆk|ª=Œæ>8ý yæg½/ZS¤ÓÖÛ·é-MS-vœ!n#Â$%œ)Pñníàç[ÄCɼý•k77äL?/"“1çî•kqŒ‘“Q&¼’'ìé²6Œô¼ )éE4LXäçæE¬á"Àû×Túûy^Mš?âDHÖ©c|ÝL¬‰Rñ©Uįy³5Œ¦*6[˜Noÿî +Ofã!&/QË™_#¹ªð­•7éïú[DëêQNúdÌÌÊñü{CƒÚC¼1Uh ‰_Ÿ±ÈÑûóV]ƒØ¡NÞb§Úin,,M3g±ƒU¾äZQJArLT(01ÄøE¿^ òó€³K˜³Üa³×774r@ @’4ëE”ú‰æÁ!es§CRɦì±"Šs0¿½hY"ÏôE÷öà±Ýp¬ÌÁfP¾ eŽ=¥––˜ ~ã†:ïNˆ2“îͦ ‘’‡Ùôwcy^_Y/ß:ÝØÜÊK/PiŸÃ²¢H9m¸µ‡Þ÷Õ]zI q‚îA¼Y½Ø©Ð"t¸…u n ¬6%³”îâ%ˆ]¶¿¨ßêüAù¢ùãK$‚-¦-²Ô}¢j› xãuÙ^mÓ²áGÕ¨4ƒœ•8úq`¹¼;«¾âdîä~qŸÄ¿“RèO¥._äÁ‘¯½Öðô¿†¾i4™}ÖÜ}à%9k2_ŸG*sfk¨¶¾LèÔɾ¡;‰û¬Ÿ@~+–3Ÿr^ÿÿ¾}§} Sʾ¹Fqs;`¥àè‘ͼê¢ï0Š@ U2˜wa*LÒßzÃ’4}ö˜JàÌMÜ£qŠÇ÷°ÈëÜ¢çèy¿ß­~Ý6–•ÓÜ꣟lúR¸Û“ÐŒÿ[EÐWê­&~1ã@U ìÏ®.üšEÕ÷%ÍÐ¥íô^d ÿôŒ>àØI¢Ã'ûTÀÙÂ:«g†hó=±ÚkMǰhãÊ“O5ÔÛàSd*é‡Y{—ðe€jÊ  $Ü‹æãÓ_ZëîûªúCa´ºªÌ½mB¯çÙÏ‘„mè°¸@9X4†®ôjbºãº´-’‹TÖâ-6)¼0‚sÐEœ½…BæÃê3Ãi¨£ØÕUdkDz;ô섬)¿‡Ö{`·šßѯŽËkbyqC¢ù0÷Œ¸rcRÝÚZi›±Ò¸¼”9a;ÏN°†Ú+ÆA Yà Snì®^ÁuÖZ·N¯Ã(Ìñå&úü%Œ'£uDua˜jýÁ•RF9»o‰œ,á$ÎK5÷íô€’Ï•Ìa§Ê ^4âý ³ïߢ_§\§%„2©7$ÁI”ú†'ÞB‹‡^»283;2=Ø;_z¹‹i¢64Œ=læ1 -`ôãóI#øKÁa‡æ2ÚXê$@è]y=<Æ|õ±’ëãB»Ìj/é SȲñL]‚ 'î1Éøþáe BÇ<¬(»îµSAº²ûä£ÿKXõÕy/G±ehrÍ'ߺHFÀ©T©ã·’]¦ð·_ÄßÉæÀ5æS9ƒXÍ¡‹g|Á.ÿ™_^ࡪ²Íç«û]×7ÍR>¿Ê+NjªÀX|»Ò¦¿g„JþŒ³ßƒA¿ o÷K÷<‰ ö¾’€h`‰úŽ#–QóÔù#`æê[e \àÞ^ö¬qʈ»dŬ52B¦á£èGèNÊd­Z^¹‰»`’tÔå—G=Š©ÒDa*¤)Tç.Håë6_3c#ÅoáâD•ù,ûÉÿ ü^*W%J€÷÷˜€Sä+NçTÉ+›`@˜äñú´ÆÁ>9'µRN7C Ê[gäY9•õÕ£V¼b|yø[þµ…PóÌãÆ÷lÁ¯¡m Ñ1éqêÙÛ”}ð ŒQT(Éç{ð?¸âe=!E|¢èÆüž¡WÛ1Äß<ÉÎ,¿ ìqÚãD2dþa°öS”³ó˜ÉfDåXãJ´º“CÐGLŒ¸ÛòÁ(_yûc÷Ô¥¾`ó D@Ýø(QqÇeæN`I hÊ~ëFò„üG‡8ª¡‰Çt§ÜãbkÙ½ Ä휇øVU~3êQgÎ]K÷œq Ü`ÁÀÊþlÈ/ôŸñŸ.48¥aɧòàœµ°UJ&EFAV Ùy§¢LšdÁ …l‡šOtñÊö-U<2Ú UÑÏç6—TÍP†õÜÑRJq Qªl~+†þbxgpÿF*ÕðÍyÜxw~ýâ›5»+æ™óÖöøÊ¬Ë`Ö*?y†Öæ^z•Å`…Âeèa¤^‰Âþ@• ¼‰‹øÍx¨3@4NÃÔ‰J¹Dé'‘ˆÑlxÝ*g¿€°ðö¨5‰z»œæ!‚õÎäâ&ÛY?ª—©–”Öç 1/ʱÓådœÏG“eGt¥''z—« W¾4Å >ÛBóÅÆJ‚=Z¸W‡W (³öLn™²öÂ^ëÚ=N×-ãÃÔ>¿DPüÂJ šT[\“ªZs Ã";½¬‰ •[¼¤+ñõî*¨¢úˤ‘¤5•£0q‡#7ZÍ#s«²l2‹`)eîp’̾ÙòDã´'ƒãCyWjkÍ$ ŠPÆ„û'i÷·NÄ ö¤E ð NHÃ…»ÃPb k*áÛwsŒo?1ŽÙå°´ÃÙâZ“‘/ÏÊ6h2àÿ Í·…bWå¸?çpÓuU¶ršJâød\wFK W¬6leMVBÖÁ•m£‰T¦¼uh8©—»‡çiIV+tLí´ôê©¿¡]³Ñë¬œÎøü2êŸÀ‹ª¡ƒœ[Ž«˜„2G#O‹c²~' EÙaewKšçmÚÛÔ¥ ¥•v™óG}ëœTc›¾4Hš˜ª:q¡â‡?®ý=r®Fä‘DAß: Ó —|½Ä”Š,ö€Ì¿¿Å $K’–è8Âó°}s÷÷>d¼…Ö‡9©¶JòÏ<\˪5=½½™ñ9Y°X¡7Dù)Ý6ó·9¼ü'5Γ (Hkg‚Œ?1:î,AJC\,׉7!¢Í±(k—,÷S×0-)ôDmDÏ”<•¼Á:gìdZØ,²Ï$²4ÐÛ»º¼´Œ&søyUð¨¥8»aLõpã˜Ó¼OüJ R94  L2^[Zxza5ñ‹‹˜„XVœ; ,ãß ñA”^¹^oéú ¼ä¥Bc¿æ4tÐ_‚94"ÂêQJýCéÕrô–þP†ÇpzÕrzš«ÿúdN "/Íáú]…ÖHç“üT ¬>ø)­@¯êw_Ym xYgÓ^Î r€¡Ž"÷,¢UKøí:±ÃtÝ'ç a×~^¤Y&3ŽÇcòöÓƒG¡»‚nIëëke©ûU1¡,©ºÓ-AèçlÃùåx›^ð›IKÿ±ªŽ`®ÎzhB ®Ûû´žÞñAÔŸfÙefûÒ 2Åú[C»æy—Ýä“èHÓƒ¹W¯ <Àò%EgØtVP̨ýÖ# p1¥¹=Ø µ§ švŒ¬€¶zTåjn9ì›4í}»ü^>ÛS©ÐN7œì& ýp º5oL»›¸ƒ¿owëU.ˆä¤¾¸ö©†£qަ…æ¤Ò&(¢^×JÚÅ*¾­kÔCúÔÐ9V W§%?ÑdªŸç-lϳ4çü¼87˜)˜Ó™[‰aFoìÐ^gA#ætå ²ó¢à—Þ¿5L_4€u8Æc'Œ,fO¯°.Cþsk]ö÷ôÔùBi•‰^RÃÝc¨ +L7$ö„Æû}¾X÷. üɽgÅ»%±€ë9>ÐEœmÒ{‡: ÝÌmw{ßd•EðYoO@.A5“λӥŠp=³f@n½o "æC¯§†g4ôüm$—H–½ÎMè8ìL&ôITô0ˆ”xpNôù¿l(Á7Ø•-úÝ£*s"@’… ;²)°(XRÉquõèøLÔRM3zÍÄÈÊæ’kÏxùY‹vÖ¦¸VXʲQ-{£VÅWù…¡5åà¯Þ±6ªÒðó@Øq óKÇü6žSð:ÔP¶ ‖áQú’±°}#_&âàäË{%GÊsèÜ~î ž¨ZΕõ‡£•šNÿ¡)'/ì|Ïq*®$>LYvÜc ­*Ûç“[›hS¡½„ÏQI«j}^YákhtÕ8ÎÝå:ËÁÿs¹ƒ-å½íÑj£MÝä:½×±™|ócn*¨K*ÿº{êÐ/ùfÍûh§Ó g9–…½jÁµ3ã'ò7ˆoŒsÌû˜Óy_À>Ží]-ï°ßàRÉÀº‚Y {>a[Êô†°i†Ú¤=™5Õp_j“•§-ÖËjõ{-;½0¥Ÿ_? 6—[ºri™À+_¼6|y¦µ5ÔÜõmH‘Ck‘°Ç h0.ÄçÉFªcƒÔ”²°æ@Ô©Wfw3¾½âÞ;y(qÒHi‰ÿÅWµÛ¹@±.…€bëE6ð°Q™j§Špr‚y|V™¿‹²ŽqI³®5…2ÿ^åÃÛqÅäÆŸl¶(ñf®ÆÆy{— £äÀfwövÙ> qïW[d3S«3å^J¤>|Ñ@¼±j?ïÞc4­nùfR­wvoxbo-1.8.5~svn1246/brainBrowser/synonym.h000066400000000000000000000137571153177201300204650ustar00rootroot00000000000000 // synonym.h // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /*********************************************************************************************** * synonymRec class definition: hold brain region synonym information. * It may seem to make more sense to use primary ID to replace "primary" and "name_space". * But the combination of "priomary" and "name_space" fields will speed up search functionality * on the interface. If region ID is used, when a certain string is searched, region name table * will have to be opened to get namespace information, which makes brain region real time search * very slow (takes about 55 seconds to launch the QT interface of "brainRegion"). ************************************************************************************************/ using namespace std; #include #include #include class synonymRec { public: synonymRec() { clear(); } synonymRec(void *buffer) { char *buf = (char *) buffer; ID = *((long *) buf); bufLen = sizeof(long); name = buf + bufLen; bufLen += name.size() + 1; primary = buf + bufLen; bufLen += primary.size() + 1; name_space = buf + bufLen; bufLen += name_space.size() + 1; sourceID = *((long *)(buf + bufLen)); bufLen += sizeof(long); qualifier = buf + bufLen; bufLen += qualifier.size() + 1; creator = buf + bufLen; bufLen += creator.size() + 1; addDate = *((long *)(buf + bufLen)); bufLen += sizeof(long); modifier = buf + bufLen; bufLen += modifier.size() + 1; modDate = *((long *)(buf + bufLen)); bufLen += sizeof(long); comments = buf + bufLen; bufLen += comments.size() + 1; } /* Initialize data members. */ void clear() { ID = 0; name = ""; primary = name_space = ""; sourceID = 0; qualifier = ""; creator = modifier = ""; addDate = modDate = 0; comments = ""; } /* Return combined data members as a single contiguous memory location. */ char * getBuffer() { memset(databuf, 0, 1000); bufLen = 0; int longLen = sizeof(long); memcpy(databuf, &ID, longLen); bufLen += longLen; packString(databuf, name); packString(databuf, primary); packString(databuf, name_space); memcpy(databuf + bufLen, &sourceID, longLen); bufLen += longLen; packString(databuf, qualifier); packString(databuf, creator); memcpy(databuf + bufLen, &addDate, longLen); bufLen += longLen; packString(databuf, modifier); memcpy(databuf + bufLen, &modDate, longLen); bufLen += longLen; packString(databuf, comments); return databuf; } /* Return the size of the buffer. */ inline int getBufferSize() { return bufLen; } void show() { printf("Synonym ID: %ld\n", ID); printf("Synonym name: %s\n", name.c_str()); printf("Primary structure: %s\n", primary.c_str()); printf("Namespace: %s\n", name_space.c_str()); if (sourceID) printf("ID in source file: %ld\n", sourceID); else printf("ID in source file:\n"); printf("Qualifier: %s\n", qualifier.c_str()); printf("Added by: %s\n", creator.c_str()); if (addDate) printf("Added on: %s", ctime(&addDate)); else printf("Added on:\n"); printf("Modified by: %s\n", modifier.c_str()); if (modDate) printf("Last modified on: %s", ctime(&modDate)); else printf("Last modified on:\n"); printf("Comments: %s\n", comments.c_str()); } inline void setID(long inputVal) { ID = inputVal; } inline void setName(string inputStr) { name = inputStr; } inline void setPrimary(string inputStr) { primary = inputStr; } inline void setNameSpace(string inputStr) { name_space = inputStr; } inline void setSourceID(long inputVal) { sourceID = inputVal; } inline void setQualifier(string inputStr) { qualifier = inputStr; } inline void setCreator(string inputStr) { creator = inputStr; } inline void setAddDate(long inputVal) { addDate = inputVal; } inline void setModifier(string inputStr) { modifier = inputStr; } inline void setModDate(long inputVal) { modDate = inputVal; } inline void setComments(string inputStr) { comments = inputStr; } inline long getID() { return ID; } inline string getName() { return name; } inline string getPrimary() { return primary; } inline string getNameSpace() { return name_space; } inline long getSourceID() { return sourceID; } inline string getQualifier() { return qualifier; } inline string getCreator() { return creator; } inline long getAddDate() { return addDate; } inline string getModifier() { return modifier; } inline long getModDate() { return modDate; } inline string getComments() { return comments; } private: /* Utility function that appends a char * to the end of the buffer. */ void packString(char *buffer, string &theString) { int string_size = theString.size() + 1; memcpy(buffer + bufLen, theString.c_str(), string_size); bufLen += string_size; } long ID, sourceID; string name, primary, name_space; string qualifier; string creator, modifier; long addDate, modDate; string comments; int bufLen; char databuf[1000]; }; voxbo-1.8.5~svn1246/brainBrowser/ui_browseRegion.h000066400000000000000000000265101153177201300221020ustar00rootroot00000000000000/******************************************************************************** ** Form generated from reading ui file 'browseRegion.ui' ** ** Created: Thu Oct 7 12:03:25 2010 ** by: Qt User Interface Compiler version 4.5.3 ** ** WARNING! All changes made in this file will be lost when recompiling ui file! ********************************************************************************/ #ifndef UI_BROWSEREGION_H #define UI_BROWSEREGION_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class Ui_brainBrowser { public: QAction *aboutAct; QWidget *centralwidget; QLabel *label_6; QLabel *label_2; QLabel *label_5; QPushButton *closeButt; QLabel *label_3; QLabel *name_title; QListWidget *synList; QLabel *label_4; QLabel *label_9; QLineEdit *linkEdit; QListWidget *relationList; QListWidget *parent; QLineEdit *srcEdit; QLabel *label_8; QLineEdit *nameEdit; QLabel *label; QLabel *main_title; QListWidget *child; QComboBox *name_space; QListWidget *searchList; QPushButton *resetButt; QMenuBar *menubar; QMenu *menuHelp; QStatusBar *statusbar; void setupUi(QMainWindow *brainBrowser) { if (brainBrowser->objectName().isEmpty()) brainBrowser->setObjectName(QString::fromUtf8("brainBrowser")); brainBrowser->resize(620, 604); aboutAct = new QAction(brainBrowser); aboutAct->setObjectName(QString::fromUtf8("aboutAct")); QFont font; font.setStyleStrategy(QFont::PreferAntialias); aboutAct->setFont(font); centralwidget = new QWidget(brainBrowser); centralwidget->setObjectName(QString::fromUtf8("centralwidget")); label_6 = new QLabel(centralwidget); label_6->setObjectName(QString::fromUtf8("label_6")); label_6->setGeometry(QRect(60, 346, 0, 17)); label_6->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); label_2 = new QLabel(centralwidget); label_2->setObjectName(QString::fromUtf8("label_2")); label_2->setGeometry(QRect(80, 454, 101, 20)); label_2->setFont(font); label_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); label_5 = new QLabel(centralwidget); label_5->setObjectName(QString::fromUtf8("label_5")); label_5->setGeometry(QRect(39, 186, 141, 20)); label_5->setFont(font); label_5->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); closeButt = new QPushButton(centralwidget); closeButt->setObjectName(QString::fromUtf8("closeButt")); closeButt->setGeometry(QRect(360, 530, 91, 28)); closeButt->setFont(font); label_3 = new QLabel(centralwidget); label_3->setObjectName(QString::fromUtf8("label_3")); label_3->setGeometry(QRect(90, 286, 91, 20)); label_3->setFont(font); label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); name_title = new QLabel(centralwidget); name_title->setObjectName(QString::fromUtf8("name_title")); name_title->setGeometry(QRect(10, 57, 171, 20)); QFont font1; font1.setFamily(QString::fromUtf8("Helvetica")); font1.setStyleStrategy(QFont::PreferAntialias); name_title->setFont(font1); name_title->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); synList = new QListWidget(centralwidget); synList->setObjectName(QString::fromUtf8("synList")); synList->setGeometry(QRect(190, 246, 381, 91)); label_4 = new QLabel(centralwidget); label_4->setObjectName(QString::fromUtf8("label_4")); label_4->setGeometry(QRect(50, 120, 131, 20)); label_4->setFont(font); label_4->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); label_9 = new QLabel(centralwidget); label_9->setObjectName(QString::fromUtf8("label_9")); label_9->setGeometry(QRect(130, 383, 51, 20)); label_9->setFont(font); label_9->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); linkEdit = new QLineEdit(centralwidget); linkEdit->setObjectName(QString::fromUtf8("linkEdit")); linkEdit->setGeometry(QRect(190, 380, 381, 27)); linkEdit->setFont(font); linkEdit->setReadOnly(true); relationList = new QListWidget(centralwidget); relationList->setObjectName(QString::fromUtf8("relationList")); relationList->setGeometry(QRect(190, 415, 381, 101)); relationList->setFont(font); parent = new QListWidget(centralwidget); parent->setObjectName(QString::fromUtf8("parent")); parent->setGeometry(QRect(190, 116, 381, 25)); parent->setFont(font); parent->setFrameShape(QFrame::StyledPanel); parent->setFrameShadow(QFrame::Sunken); parent->setLineWidth(1); srcEdit = new QLineEdit(centralwidget); srcEdit->setObjectName(QString::fromUtf8("srcEdit")); srcEdit->setGeometry(QRect(190, 345, 381, 27)); srcEdit->setFont(font); srcEdit->setReadOnly(true); label_8 = new QLabel(centralwidget); label_8->setObjectName(QString::fromUtf8("label_8")); label_8->setGeometry(QRect(110, 350, 71, 20)); label_8->setFont(font); label_8->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); nameEdit = new QLineEdit(centralwidget); nameEdit->setObjectName(QString::fromUtf8("nameEdit")); nameEdit->setGeometry(QRect(190, 50, 381, 29)); nameEdit->setFont(font); label = new QLabel(centralwidget); label->setObjectName(QString::fromUtf8("label")); label->setGeometry(QRect(100, 90, 81, 20)); label->setFont(font); label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); main_title = new QLabel(centralwidget); main_title->setObjectName(QString::fromUtf8("main_title")); main_title->setGeometry(QRect(210, 10, 221, 21)); QFont font2; font2.setPointSize(12); font2.setBold(true); font2.setWeight(75); font2.setStyleStrategy(QFont::PreferAntialias); main_title->setFont(font2); main_title->setAlignment(Qt::AlignCenter); child = new QListWidget(centralwidget); child->setObjectName(QString::fromUtf8("child")); child->setGeometry(QRect(190, 147, 381, 91)); child->setFont(font); name_space = new QComboBox(centralwidget); name_space->setObjectName(QString::fromUtf8("name_space")); name_space->setGeometry(QRect(190, 83, 141, 28)); name_space->setFont(font); searchList = new QListWidget(centralwidget); searchList->setObjectName(QString::fromUtf8("searchList")); searchList->setEnabled(true); searchList->setGeometry(QRect(190, 77, 381, 6)); searchList->setFont(font); resetButt = new QPushButton(centralwidget); resetButt->setObjectName(QString::fromUtf8("resetButt")); resetButt->setGeometry(QRect(220, 530, 91, 28)); resetButt->setFont(font); brainBrowser->setCentralWidget(centralwidget); menubar = new QMenuBar(brainBrowser); menubar->setObjectName(QString::fromUtf8("menubar")); menubar->setGeometry(QRect(0, 0, 620, 23)); menuHelp = new QMenu(menubar); menuHelp->setObjectName(QString::fromUtf8("menuHelp")); brainBrowser->setMenuBar(menubar); statusbar = new QStatusBar(brainBrowser); statusbar->setObjectName(QString::fromUtf8("statusbar")); brainBrowser->setStatusBar(statusbar); QWidget::setTabOrder(nameEdit, searchList); QWidget::setTabOrder(searchList, name_space); QWidget::setTabOrder(name_space, parent); QWidget::setTabOrder(parent, child); QWidget::setTabOrder(child, synList); QWidget::setTabOrder(synList, srcEdit); QWidget::setTabOrder(srcEdit, linkEdit); QWidget::setTabOrder(linkEdit, relationList); QWidget::setTabOrder(relationList, closeButt); menubar->addAction(menuHelp->menuAction()); menuHelp->addAction(aboutAct); retranslateUi(brainBrowser); QMetaObject::connectSlotsByName(brainBrowser); } // setupUi void retranslateUi(QMainWindow *brainBrowser) { brainBrowser->setWindowTitle(QApplication::translate("brainBrowser", "Brain Region Browser", 0, QApplication::UnicodeUTF8)); aboutAct->setText(QApplication::translate("brainBrowser", "&About", 0, QApplication::UnicodeUTF8)); label_6->setText(QApplication::translate("brainBrowser", "Added on:", 0, QApplication::UnicodeUTF8)); label_2->setText(QApplication::translate("brainBrowser", "Relationship:", 0, QApplication::UnicodeUTF8)); label_5->setText(QApplication::translate("brainBrowser", "Child Structure(s):", 0, QApplication::UnicodeUTF8)); closeButt->setText(QApplication::translate("brainBrowser", "Close", 0, QApplication::UnicodeUTF8)); label_3->setText(QApplication::translate("brainBrowser", "Synonyms:", 0, QApplication::UnicodeUTF8)); name_title->setText(QApplication::translate("brainBrowser", "Search Region Name:", 0, QApplication::UnicodeUTF8)); label_4->setText(QApplication::translate("brainBrowser", "Parent Structure:", 0, QApplication::UnicodeUTF8)); label_9->setText(QApplication::translate("brainBrowser", "Link:", 0, QApplication::UnicodeUTF8)); label_8->setText(QApplication::translate("brainBrowser", "Source:", 0, QApplication::UnicodeUTF8)); label->setText(QApplication::translate("brainBrowser", "Located in:", 0, QApplication::UnicodeUTF8)); main_title->setText(QApplication::translate("brainBrowser", "\n" "

Brain Region Browser

", 0, QApplication::UnicodeUTF8)); name_space->clear(); name_space->insertItems(0, QStringList() << QApplication::translate("brainBrowser", "All namespaces", 0, QApplication::UnicodeUTF8) << QApplication::translate("brainBrowser", "NN2002", 0, QApplication::UnicodeUTF8) << QApplication::translate("brainBrowser", "AAL", 0, QApplication::UnicodeUTF8) << QApplication::translate("brainBrowser", "Brodmann", 0, QApplication::UnicodeUTF8) ); resetButt->setText(QApplication::translate("brainBrowser", "Reset", 0, QApplication::UnicodeUTF8)); menuHelp->setTitle(QApplication::translate("brainBrowser", "&Help", 0, QApplication::UnicodeUTF8)); } // retranslateUi }; namespace Ui { class brainBrowser: public Ui_brainBrowser {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_BROWSEREGION_H voxbo-1.8.5~svn1246/client/000077500000000000000000000000001153177201300154025ustar00rootroot00000000000000voxbo-1.8.5~svn1246/client/Makefile000066400000000000000000000063051153177201300170460ustar00rootroot00000000000000 # Makefile for database client -include ../make_vars.txt include ../make_stuff.txt CXXFLAGS += -DQT3_SUPPORT $(QTINCDIRS) -I../vbview VBVIEW_OBJECTS=../vbview/vbview.o ../vbview/vbview_ts.o ../vbview/vbview_layers.o ../vbview/vbview_render.o ../vbview/vbview_io.o ../vbview/vbqt_masker.o ../vbview/vbqt_canvas.o ../vbview/vbqt_glmselect.o ../vbview/vbqt_scalewidget.o XLIBS=$(LDFLAGS) $(LIBDIRS) $(QTLIBDIRS) $(VBVIEW_OBJECTS) $(QTLIBS) -lvbglm -lvbprefs -lvbio -lvbutil -lz -lm -lpng -ldl -lgnutls-extra -lgnutls -lgcrypt -lgpg-error -ldbutil -lgsl -lgslcblas -ldb_cxx NOXLIBS=$(LDFLAGS) $(LIBDIRS) -lvbglm -lvbprefs -lvbio -lvbutil -lz -lm -lpng -ldl -lgnutls-extra -lgnutls -lgcrypt -lgpg-error -ldbutil -lgsl -lgslcblas -ldb_cxx -lpthread W_OBJECTS=dbqscorebox.o dbqlineedit.o dbqimage.o dbqcombo.o dbqtimedate.o dbqtextedit.o dbqstub.o dbview.o dbclient.o dbqbrain.o dbdialogs.o dbmainwindow.o ALLBINS=client dbtool ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else ifeq ($(VB_TARGET),db) BINS=$(ALLBINS) else BINS= endif ifdef VB_NOX BINS= endif all: $(BINS) install: echo "Not yet!" clean: rm -rf $(CLEANME) $(ALLBINS) dbfiles.h # executables client : $(W_OBJECTS) client.cpp rsrc.cpp dbclient.h $(VBLIBSDB) $(CXX) $(CXXFLAGS) client.cpp rsrc.cpp $(W_OBJECTS) -o client $(XLIBS) dbtool : dbtool.cpp dbclient.o dbfiles.h $(VBLIBSDB) $(CXX) $(CXXFLAGS) dbtool.cpp dbclient.o -o dbtool $(NOXLIBS) -lreadline -ltermcap test : $(W_OBJECTS) test.cpp rsrc.cpp $(VBLIBSDB) $(CXX) $(CXXFLAGS) test.cpp rsrc.cpp $(W_OBJECTS) -o test $(XLIBS) # all my pattern rules %.moc.h : %.h $(MOC) $< -o $@ rsrc.cpp : client.qrc $(RCC) client.qrc -o rsrc.cpp dbfiles.h : default_scorenames.txt default_types.txt default_views.txt\ test_scorenames.txt test_types.txt test_views.txt $(VBRC) dbfiles.h def_sn default_scorenames.txt def_ty default_types.txt def_vi default_views.txt\ test_sn test_scorenames.txt test_ty test_types.txt test_vi test_views.txt dbmainwindow.o : dbmainwindow.cpp dbmainwindow.moc.h $(CXX) -c $< $(CXXFLAGS) dbdialogs.o : dbdialogs.cpp dbdialogs.moc.h $(CXX) -c $< $(CXXFLAGS) dbqlineedit.o : dbqlineedit.cpp dbqlineedit.moc.h dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbqimage.o : dbqimage.cpp dbqimage.moc.h dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbqbrain.o : dbqbrain.cpp dbqbrain.moc.h dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbqtextedit.o : dbqtextedit.cpp dbqtextedit.moc.h dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbqcombo.o : dbqcombo.cpp dbqcombo.moc.h dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbqscorebox.o : dbqscorebox.cpp dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbqstub.o : dbqstub.cpp dbqstub.moc.h dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbqtimedate.o : dbqtimedate.cpp dbqtimedate.moc.h dbqscorebox.moc.h $(CXX) -c $< $(CXXFLAGS) dbview.o : dbview.cpp dbview.moc.h $(CXX) -c $< $(CXXFLAGS) moc_searchPatient.cpp: searchPatient.h $(MOC) $(DEFINES) $(INCPATH) searchPatient.h -o moc_searchPatient.cpp searchPatient.o: searchPatient.cpp searchPatient.h $(CXX) -c $< $(CXXFLAGS) dbclient.o: dbclient.cpp dbclient.h $(CXX) -c $< $(CXXFLAGS) moc_searchPatient.o: moc_searchPatient.cpp $(CXX) -c $< $(CXXFLAGS) #connx2srv.o: connx2srv.cpp # $(CXX) -c $< $(CXXFLAGS) voxbo-1.8.5~svn1246/client/client.cpp000066400000000000000000000034031153177201300173640ustar00rootroot00000000000000 // client.cpp // Copyright (c) 2009-2010 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "dbmainwindow.h" // This should be made conditional -- only works with static Qt // (maybe trigger by VB_SHARED ?) //Q_IMPORT_PLUGIN(qjpeg) //Q_IMPORT_PLUGIN(qgif) //Q_IMPORT_PLUGIN(qtiff) int main(int argc, char **argv) { // Qt application QApplication app(argc,argv); app.setWindowIcon(QIcon(QPixmap(":/icons/windowlogo.png"))); // parse arguments (none so far) tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; isetCentralWidget(dbmw); // DBmainwindow mw; dbmw->show(); return app.exec(); } voxbo-1.8.5~svn1246/client/client.qrc000066400000000000000000000012571153177201300173740ustar00rootroot00000000000000 icons/icon_bold.png icons/icon_ital.png icons/icon_line.png icons/icon_black.png icons/icon_red.png icons/icon_green.png icons/icon_blue.png icons/icon_up.png icons/icon_down.png icons/icon_noimage.png icons/windowlogo.png icons/a_open.png icons/a_connect.png icons/a_create.png icons/a_search.png icons/a_logo.png voxbo-1.8.5~svn1246/client/connx2srv.cpp000066400000000000000000000147121153177201300200550ustar00rootroot00000000000000using namespace std; #include "dbclient.h" #include #include int main(int argc, char* argv[]) { if (argc != 2) { cout << "Usage: connnx2srv local | rmt" << endl; exit(1); } string mode = argv[1]; if (mode != "local" && mode != "rmt" && mode != "remote") { cout << "Usage: connnx2srv local | rmt | remote" << endl; exit(1); } /**************************************** * User login (local or remote) ****************************************/ string username("dhu"); string passwd("dhu"); DBclient* dbcp = 0; if (mode == "local") { string envHome("../env"); dbcp = new localClient(username, passwd, envHome); } else { string serverName("ajax"); uint32 serverPort = 5556; dbcp = new remoteClient(username, passwd, serverName, serverPort); } if (dbcp->login()) { cout << dbcp->getErrMsg() << endl; delete dbcp; exit(1); } /**************************************** * New ID request test ****************************************/ // int32 foo = dbcp->reqID(1); // if (foo <= 0) { // cout << dbcp->getErrMsg() << endl; // delete dbcp; // exit(1); // } // DBscorename newScore; // newScore.id = foo; // vector snlist; // snlist.push_back(newScore); // if (dbcp->putNewScoreName(snlist)) // cout << dbcp->getErrMsg() << endl; /**************************************** * Print out global map data ****************************************/ // cout << "types #: " << dbcp->dbs.typemap.size() << endl; // cout << "score name #: " << dbcp->dbs.scorenames.size() << endl; // cout << "Region name #: " << dbcp->dbs.regionNameMap.size() << endl; // cout << "Synonym #: " << dbcp->dbs.synonymMap.size() << endl; // cout << "Region relationship #: " << dbcp->dbs.regionRelationMap.size() << endl; //showTypeMap(dbcp->typemap); //showScoreNames(dbcp->scorenames); //showRegionNameMap(dbcp->regionNameMap); //showRelationMap(dbcp->regionRelationMap); /**************************************** * Add new database user account ****************************************/ // userGUI uiData; // string str1("admin2"); // string str2("admin"); // string str3("DB Administrator"); // string str4("admin@cfn.upenn.edu"); // uiData.setAccount(str1); // uiData.setPasswd(str2); // uiData.setName(str3); // uiData.setEmail(str4); // if (dbcp->putNewUser(uiData)) // cout << dbcp->getErrMsg() << endl; /**************************************** * Add new sessions and score values ****************************************/ // int32 newID = dbcp->reqID(7); // if (newID <= 0) { // cout << dbcp->getErrMsg() << endl; // delete dbcp; // exit(1); // } // // one new patient record // DBpatient pRec; // pRec.patientID = newID++; // // two new DBsession objects // vector sList; // for (int i = 0; i < 2; i++) { // DBsession newSession; // newSession.id = newID++; // newSession.patient = pRec.patientID; // newSession.examiner = "dhu"; // sList.push_back(newSession); // } // pRec.setSessionMap(sList); // // four DBscorevalue objects // set id_set; // for (int i = 0; i < 4; i++) { // DBscorevalue newSV; // newSV.id = newID++; // newSV.patient = pRec.patientID; // newSV.scorename = "fake scorename " + num2str(i + 1); // string tmpSV = "dhu scorevalue " + num2str(i + 1); // newSV.v_string = tmpSV; // newSV.setby = "dhu"; // pRec.scores.insert(map::value_type(newSV.id, newSV)); // if (newSV.id % 2 == 0) // id_set.insert(newSV.id); // } // if (dbcp->putScoreValues(id_set, pRec.scores)) // cout << dbcp->getErrMsg() << endl; // //if (dbcp->putNewPatient(pRec)) // // cout << dbcp->getErrMsg() << endl; /**************************************** * Test of time request ****************************************/ // int32 t_stamp = dbcp->reqTime(); // if (t_stamp <= 0) // cout << dbcp->getErrMsg() << endl; /**************************************** * patient list test ****************************************/ //for (unsigned i = 0; i < dbcp->pList.size(); i++) // dbcp->pList[i].show(); // DBpatientlist tmpRec; // tmpRec.id = 2901; // tmpRec.ownerID = 2351; // tmpRec.name = "rmt client test"; // tmpRec.search_strategy = "case_sensitive any include 215"; // tmpRec.notes = "rmt client notes"; // tmpRec.runDate.setUnixTime(t_stamp); // tmpRec.patientIDs.insert(2217); // tmpRec.patientIDs.insert(2258); // //vector vec; // //vec.push_back(tmpRec); // if (dbcp->putPatientList(tmpRec, true)) // cout << dbcp->getErrMsg() << endl; /**************************************** * patient search test ****************************************/ // vector pMatches; // patientSearchTags searchTag; // searchTag.init(); // searchTag.case_sensitive = true; // searchTag.scoreName = ""; // searchTag.relationship = "include"; // searchTag.searchStr = "215"; // if (dbcp->reqSearchPatient(searchTag, pMatches)) { // for (uint i = 0; i < pMatches.size(); i++) { // cout << "--------------------------------" << endl; // pMatches[i].show(); // } // } // else // cout << dbcp->getErrMsg() << endl; /**************************************** * patient score value request test ****************************************/ DBpatient pRec; if (dbcp->reqOnePatient(2258, pRec)) cout << dbcp->getErrMsg() << endl; //cout << "# of sessions: " << pRec.sessions.size() << endl; //cout << "# of scores: " << pRec.scores.size() << endl; // for (map::iterator iter = pRec.scores.begin(); // iter != pRec.scores.end(); ++iter) { // cout << "-------------------------------" << endl; // cout << iter->first << endl; // iter->second.show(); // cout << endl; // } pRec.scores[2627].v_string = "dhu new fake value"; set id_set; id_set.insert(2627); if (dbcp->putScoreValues(id_set, pRec.scores)) cout << dbcp->getErrMsg() << endl; // DBscorevalue newSV; // newSV.id = 2627; // newSV.patient = 2258; // newSV.scorename = "fake scorename " + num2str(i + 1); // string tmpSV = "dhu scorevalue " + num2str(i + 1); // newSV.v_string = tmpSV; // newSV.setby = "dhu"; // pRec.scores.insert(map::value_type(newSV.id, newSV)); // id_set.insert(newSV.id); delete dbcp; return 0; } voxbo-1.8.5~svn1246/client/dbclient.cpp000066400000000000000000001117021153177201300176740ustar00rootroot00000000000000/* Define member functions of DBclient and its two derived classes. */ using namespace std; #include #include #include #include #include "dbclient.h" /* Default constructor, do nothing right now. */ DBclient::DBclient() : online(false) { } /* Another DBclient ctor that sets username and passwd. */ DBclient::DBclient(const string &username,const string &password) : username(username), passwd(password), online(false) { } /* dtor for DBclient does nothing so far. */ DBclient::~DBclient() { } /* Default localClient ctor. */ localClient::localClient() { } /* Destructor closes db and env. */ localClient::~localClient() { exit(); } /* Ctor of localClient. */ localClient::localClient(const string& username, const string& password, const string& inputDir) : DBclient(username, password) { dbs.dirname = inputDir; } /* Function that handles local login. * Successful login is also followed by these steps: * (1) Open enviroment and db files. * (2) Read local score type file and build the type map. * (3) Build scorenames, testmap and scorenamechildren maps. * (4) Set user ID and user-specific permissions. * Returns 0 for successful login; * returns 1 if client has already logged in; * returns 2 if username is blank; * returns 3 if passwd is blank; * returns 4 if local server env is not set; * returns -1 if db env can not be opened. * returns -2 if user permission records can not be loaded. * returns -3 if patient list can not be loaded. */ int localClient::login() { if (online) { errMsg = "Client already logged in."; return 1; } if (username.empty()) { errMsg = "Username not set"; return 2; } if (passwd.empty()) { errMsg = "Password not set"; return 3; } if (dbs.dirname.empty()) { errMsg = "Local db directory not set"; return 4; } if (dbs.open()) { dbs.close(); errMsg = dbs.errMsg; return -1; } int32 status = chkPasswd(dbs.userDB, NULL, username, passwd); if (status == 0) { errMsg = "Account " + username + " does not exist."; dbs.close(); return -1; } if (status == -1 || status == -2) { errMsg = "Failed to retrive db records"; dbs.close(); return -1; } if (status == -3) { errMsg = "make_verifier error"; dbs.close(); return -1; } if (status == -4) { errMsg = "Wrong password for " + username; dbs.close(); return -1; } // Both user name and passwd are correct, log into the main interface online = true; userID = status; int foo = getPerm(dbs.userDB, dbs.permDB, NULL, userID, permissions); if (foo) { errMsg = "Failed to load user permissions."; dbs.close(); return -2; } if (getPatientList(dbs.userDB, dbs.patientListDB, NULL, userID, pList)) { errMsg = "Failed to load user's patient list."; dbs.close(); return -3; } return 0; } /* This function requests a certain number of unique IDs. * Returns the new ID if everything is ok; * or returns 0 if new ID can not be retrieved from server.*/ int32 localClient::reqID(uint32 id_num) { DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int32 startID = getSysID(dbs.sysDB, txn, id_num); if (startID <= 0) { txn->abort(); return 0; } txn->commit(0); dbs.sysDB.getDb().sync(0); // write data on disk now return startID; } /* This function returns current time stamp on server side. */ int32 localClient::reqTime() { return time(NULL); } /* Add a new user account to local db. * Returns 0 if everything is ok; * returns -1 if account already exists; * returns -2 if user table can not be updated; * returns -3 if time stamp can not be updated. */ int localClient::putNewUser(const userGUI& uiData) { int32 size = uiData.getSize(); char buff[size]; uiData.serialize(buff); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int stat = addUser(dbs.userDB, dbs.sysDB, txn, buff); if (stat == 1) { errMsg = "Account already exists."; txn->commit(0); return -1; } if (stat < 0) { errMsg = "DB error when adding new user account"; txn->abort(); return -2; } if (setSysUpdate(dbs.sysDB, txn, errMsg)) { txn->abort(); return -3; } txn->commit(0); dbs.sysDB.getDb().sync(0); dbs.userDB.getDb().sync(0); // write data on disk now return 0; } /* Add new score names to local db. * Returns 0 if everything is ok; * returns -1 if socre name table ca not be updated; * returns -2 if time stamp can not be updated in system table. */ int localClient::putNewScoreName(const vector& snList) { DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); // Add new patient score values (test results) if (addScoreName(dbs.scoreNameDB, txn, snList)) { errMsg = "DB error when adding new score name record"; txn->abort(); return -1; } if (setSysUpdate(dbs.sysDB, txn, errMsg)) { txn->abort(); return -2; } txn->commit(0); dbs.scoreNameDB.getDb().sync(0); dbs.sysDB.getDb().sync(0); // Update map for local client for (uint i = 0; i < snList.size(); ++i) { dbs.add_scorename(snList[i]); } return 0; } /* Add new patient, new session and new score values into local db files. * Returns 0 if operation is successful; * returns -1 if new patient record can not be updated in db; * returns -2 if new session record can not be updated in db; * returns -3 if new score value record can not be updated in db; * returns -4 if time stamp can not be updated in db. */ int localClient::putNewPatient(DBpatient& patient_in) { time_t t_stamp = time(NULL); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); // Add new patient patientRec newPatient; newPatient.setID(patient_in.patientID); if (addPatient(dbs.patientDB, txn, newPatient)) { errMsg = "DB error when adding new patient record"; txn->abort(); return -1; } // Add new patient sessions map::iterator sess_it; for (sess_it = patient_in.sessions.begin(); sess_it != patient_in.sessions.end(); ++sess_it) { if (sess_it->second.id<=0) continue; sess_it->second.date.setUnixTime(t_stamp); if (addSession(dbs.sessionDB, txn, sess_it->second)) { errMsg = "DB error when adding new session record"; txn->abort(); return -2; } } // Add new patient score values map::iterator sv_it; for (sv_it = patient_in.scores.begin(); sv_it != patient_in.scores.end(); ++sv_it) { if (sv_it->second.id<=0) continue; sv_it->second.whenset.setUnixTime(t_stamp); if (addScoreValue(dbs.scoreValueDB, txn, sv_it->second)) { errMsg = "DB error when adding new score value record"; txn->abort(); return -3; } } if (setSysUpdate(dbs.sysDB, txn, t_stamp, errMsg)) { txn->abort(); return -4; } txn->commit(0); dbs.patientDB.getDb().sync(0); dbs.sessionDB.getDb().sync(0); dbs.scoreValueDB.getDb().sync(0); dbs.sysDB.getDb().sync(0); return 0; } /* Add new session data into local db file. * Returns 0 if everything is ok, * returns -1 if new session record can not be updated in db; * returns -2 if time stamp can not be updated in db. */ int localClient::putNewSession(vector& sList) { time_t t_stamp = time(NULL); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); if (addSession(dbs.sessionDB, txn, sList, t_stamp)) { errMsg = "DB error when adding new session record"; txn->abort(); return -1; } if (setSysUpdate(dbs.sysDB, txn, t_stamp, errMsg)) { txn->abort(); return -2; } txn->commit(0); dbs.sessionDB.getDb().sync(0); // write data on disk now dbs.sysDB.getDb().sync(0); return 0; } /* Add score values (test results) into local db. * Returns 0 if everything is ok; * returns -1 if ID in input set is not found in input map; * returns -2 if score value record can not be updated in db; * returns -3 if time stamp can not be updated in db. */ int localClient::putScoreValues(set svID, map& svMap) { time_t t_stamp = time(NULL); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); set::const_iterator it; for (it = svID.begin(); it != svID.end(); ++it) { int32 tmpID = *it; map::iterator map_it = svMap.find(tmpID); if (map_it == svMap.end()) { errMsg = "Invalid score value ID in DBscorevalue map: " + num2str(tmpID); txn->abort(); return -1; } map_it->second.whenset.setUnixTime(t_stamp); if (addScoreValue(dbs.scoreValueDB, txn, map_it->second)) { errMsg = "DB error when adding new score value record"; txn->abort(); return -2; } } if (setSysUpdate(dbs.sysDB, txn, t_stamp, errMsg)) { txn->abort(); return -2; } txn->commit(0); dbs.scoreValueDB.getDb().sync(0); // write data on disk now dbs.sysDB.getDb().sync(0); return 0; } /* Add score values (test results) into local db. * Returns 0 if everything is ok; * returns -1 if patient list record can not be updated in db; * returns -2 if time stamp can not be updated in db. */ int localClient::putPatientList(DBpatientlist& inputRec, bool isNew) { time_t t_stamp = time(NULL); if (isNew) inputRec.runDate.setUnixTime(t_stamp); else inputRec.modDate.setUnixTime(t_stamp); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); if (addPatientList(dbs.patientListDB, txn, inputRec)) { errMsg = "DB error when adding new score value record"; txn->abort(); return -1; } if (setSysUpdate(dbs.sysDB, txn, errMsg)) { txn->abort(); return -2; } txn->commit(0); dbs.patientListDB.getDb().sync(0); // write data on disk now dbs.sysDB.getDb().sync(0); return 0; } /* Local client searching a certain user by account name. * Returns 0 if user is found on local server; * returns -1 if user is not found. * returns -2 for db errors. */ int localClient::reqUser(const string& inputUser, userRec& rec_out) { DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int stat = getUser(dbs.userDB, txn, inputUser, rec_out); if (stat == 1) { txn->commit(0); return 0; } if (stat == 0) { errMsg = "User not found"; txn->commit(0); return -1; } errMsg = "DB error " + num2str(stat); txn->abort(); return -2; } /* Local client requests a patient search on local server. * Returns 0 if any patient that matches search criterion is found; * returns -1 if permission is denied; * returns -2 for db error; * returns -3 if no patient is found. */ int localClient::reqSearchPatient(const patientSearchTags& tags, vector& matchList) { if (!permissions.size()) { errMsg = "Permission denied"; return -1; } DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int foo = searchPatients(dbs.scoreValueDB, txn, tags, permissions, matchList); if (foo) { txn->abort(); errMsg = "DB error"; return -2; } txn->commit(0); if (matchList.empty()) { errMsg = "Patient not found"; return -3; } return 0; } /* Local client requests all score values of a certain patient. * Retunrs 0 if score values are found succesfully; * returns -1 if permission is denied; * returns -2 for db search error. */ int localClient::reqOnePatient(int32 pID, DBpatient& myPatient) { if (!permissions.size()) { errMsg = "Permission denied"; return -1; } DbTxn * txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int stat = getOnePatient(dbs.scoreValueDB, dbs.sessionDB, txn, pID, permissions, myPatient); if (stat) { cout << "FIXME getonepatient error " << stat << endl; txn->abort(); return -2; } txn->commit(0); return 0; } /* Close local database. * returns 0 if everything is ok; * returns -1 for db close error. */ int localClient::exit() { errMsg = ""; if (dbs.close()) { errMsg = "Failed to close local database"; return -1; } online = false; return 0; } /********************************************************** * Member function definition of remoteClient class. *********************************************************/ /* Default ctor for remoteClient. */ remoteClient::remoteClient() : init_flag(false) { } /* Destrucotr closes client connection. */ remoteClient::~remoteClient() { exit(); } /* Ctor for remote client. */ remoteClient::remoteClient(const string& inputUser, const string& inputPwd, const string& inputSrv, uint32 inputPort) : DBclient(inputUser, inputPwd), serverName(inputSrv), serverPort(inputPort), init_flag(false) { } /* Function that handles remote login. * Returns 0 if everything is ok; * returns 1 if client has already logged in; * returns 2 if username is not set; * returns 3 if passwd is not set; * returns 4 if server name is not set; * returns 5 if server port number is invalid; * retunrs -1 if server not available; * returns -2 if handshake between server and client fails; * returns -3 if maps not received successfully from server. */ int remoteClient::login() { if (online) { errMsg = "Client already logged in."; return 1; } if (username.empty()) { errMsg = "Username not set"; return 2; } if (passwd.empty()) { errMsg = "Password not set"; return 3; } if (serverName.empty()) { errMsg = "Server name not set"; return 4; } if (serverPort <= 0) { errMsg = "Invalid server port number: " + num2str(serverPort); return 4; } // Check server availability if (chkServer()) { return -1; } // User authentification if (chkHandshake()) { exit(); return -2; } online = true; // Make sure maps are received successfully if (recvMaps()) { exit(); return -3; } return 0; } /* Check server availability. * returns 0 if server is ok; * returns -1 if host is not found; * returns -2 if connection fails. */ int remoteClient::chkServer() { struct hostent *hp; struct sockaddr_in addr; memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(serverPort); hp = gethostbyname(serverName.c_str()); if (!hp) { errMsg = "Couldn't find host: "; errMsg.append(serverName); return -1; } memcpy(&addr.sin_addr, hp->h_addr_list[0], hp->h_length); c_stat = safe_connect(&addr, 10); if (c_stat < 0) { errMsg = "Couldn't connect to " + serverName; return -2; } fcntl(c_stat, F_SETFL, 0); return 0; } /* Test handshake using gnutls * Returns 0 if handshake succeeds; * returns -1 if handshake fails. */ int remoteClient::chkHandshake() { // INIT GNUTLS gnutls_global_init(); gnutls_global_init_extra(); gnutls_srp_allocate_client_credentials(&srpcred); gnutls_srp_set_client_credentials(srpcred, username.c_str(), passwd.c_str()); init_flag = true; // MORE GNUTLS SETUP and handshake gnutls_init(&g_session, GNUTLS_CLIENT); gnutls_priority_set_direct(g_session, "NORMAL:+SRP", NULL); gnutls_credentials_set(g_session, GNUTLS_CRD_SRP, srpcred); gnutls_transport_set_ptr(g_session, (gnutls_transport_ptr_t) c_stat); int ret = gnutls_handshake(g_session); if (ret < 0) { errMsg = "Client error: Handshake failed"; gnutls_perror(ret); return -1; // FIXME need to be more elegant about this } return 0; } /* This function parses the server message that has buffer size information. * The real data buffer will be followed. * Returns the size of data buffer that is going to follow this message; * returns -1 if server message is not received; * returns -2 if no patient list is available; * returns -3 if no score value is available; * returns -4 if no valid session available (all patient score values are static); * returns -5 if server sends a scorevalue message; * returns 0 if the message doesn't have size info or is not understandable. */ int32 remoteClient::parseServerMsg() { errMsg = ""; char msg_recv[MSG_SIZE + 1]; if (recvMessage(g_session, msg_recv)) { errMsg = "Server message not received"; return -1; } s_tokens.clear(); s_tokens.SetSeparator(" "); s_tokens.ParseLine(msg_recv); if (s_tokens[0] == "no_data:") { string tmpStr(msg_recv); int i = tmpStr.find(" "); errMsg = tmpStr.substr(i + 1, tmpStr.size() - i - 1); return 0; } if (s_tokens[0] == "no_patientlist") return -2; if (s_tokens[0] == "no_scorevalue") return -3; if (s_tokens[0] == "no_session") return -4; if (s_tokens[0] == "scorevalue:" && s_tokens.size() == 3) return -5; if (s_tokens.size() != 2 || s_tokens[0] != "server_data_size:") { errMsg = (string) "Server message not understandable: " + msg_recv;; return 0; } int32 dat_size = atoi(s_tokens(1)); if (dat_size <= 0) { errMsg = (string) "Unknown data size: " + s_tokens[1]; return 0; } return dat_size; } /* Receive global map data from server. * Returns 0 if everything is ok; * returns -1 if score type data are not received correctly; * returns -2 if score name data are not received correctly; * returns -3 if brain region name data are not received correctly; * returns -4 if brain region synonym data are not received correctly; * returns -5 if brain region relationship data are not received correctly; * returns -6 if patient list data are not received correctly. */ int remoteClient::recvMaps() { if (recvTypes()) return -1; if (recvScoreNames()) return -2; if (recvRegionNames()) return -3; if (recvSynonyms()) return -4; if (recvRegionRelations()) return -5; if (recvPatientList()) return -6; return 0; } /* Receive typemap info from server. * Returns 0 if type data are received correctly; * returns -1 if type data size is invalid; * returns -2 if type data buffer is not received correctly. */ int remoteClient::recvTypes() { int32 dat_size = parseServerMsg(); if (dat_size <= 0) { errMsg = "Invalid size of score type data buffer: " + num2str(dat_size); return -1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { errMsg = "Failed to receive score types data from server"; return -2; } vector type_vec; deserialize(dat_size, buffer, type_vec); // set local type map for (uint i = 0; i < type_vec.size(); i++) { string tname = type_vec[i].name; dbs.typemap[tname] = type_vec[i]; } return 0; } /* Receive score names map from server. * Returns 0 if score name data are received correctly; * returns -1 if score name data size is invalid; * returns -2 if score name data buffer is not received correctly. */ int remoteClient::recvScoreNames() { int32 dat_size = parseServerMsg(); if (dat_size <= 0) { errMsg = "Invalid size of score name data buffer: " + num2str(dat_size); return -1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { errMsg = "Failed to receive score name data from server"; return -2; } vector sn_vec; // set local score name maps deserialize(dat_size, buffer, sn_vec); for (uint i = 0; i < sn_vec.size(); ++i) { dbs.scorenames[sn_vec[i].name] = sn_vec[i]; string parentStr = scoreparent(sn_vec[i].name); dbs.scorenamechildren.insert(pair(parentStr, sn_vec[i].name)); } return 0; } /* Receive region names map from server. * Returns 0 if region name data are received correctly; * returns -1 if region name data size is invalid; * returns -2 if region name data buffer is not received correctly. */ int remoteClient::recvRegionNames() { int32 dat_size = parseServerMsg(); if (dat_size <= 0) { errMsg = "Invalid size of brain region name data buffer: " + num2str(dat_size); return -1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { errMsg = "Failed to receive brain region name data from server"; return -2; } vector vec; deserialize(dat_size, buffer, vec); // set local region name map for (uint i = 0; i < vec.size(); ++i) dbs.regionNameMap[vec[i].getID()] = vec[i]; return 0; } /* Receive synonym map from server. * Returns 0 if synonym data are received correctly; * returns -1 if synonym data size is invalid; * returns -2 if synonym data buffer is not received correctly. */ int remoteClient::recvSynonyms() { int32 dat_size = parseServerMsg(); if (dat_size <= 0) { errMsg = "Invalid size of brain region synonym data buffer: " + num2str(dat_size); return -1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { errMsg = "Failed to receive brain region synonym data from server"; return -2; } vector vec; deserialize(dat_size, buffer, vec); // set local synonym map for (uint i = 0; i < vec.size(); ++i) dbs.synonymMap[vec[i].getID()] = vec[i]; return 0; } /* Receive brain region relationship map from server * Returns 0 if region relationship data are received correctly; * returns -1 if region relationship data size is invalid; * returns -2 if region relationship data buffer is not received correctly. */ int remoteClient::recvRegionRelations() { int32 dat_size = parseServerMsg(); if (dat_size <= 0) { errMsg = "Invalid size of brain region relationship data buffer: " + num2str(dat_size); return -1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { errMsg = "Failed to receive brain region relationship data from server"; return -2; } vector vec; deserialize(dat_size, buffer, vec); // set local region relationship map for (uint i = 0; i < vec.size(); ++i) dbs.regionRelationMap[vec[i].getID()] = vec[i]; return 0; } /* Receive patient list data from server. * Returns 0 if patient list data are received correctly (or no patient list is available); * returns -1 if patient list data size is invalid; * returns -2 if patient list data buffer is not received correctly. */ int remoteClient::recvPatientList() { int32 dat_size = parseServerMsg(); if (dat_size == -2) // This user doesn't have patient list return 0; if (dat_size <= 0) { errMsg = "Invalid size of patient list data buffer: " + num2str(dat_size); return -1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { errMsg = "Failed to receive patient list data from server"; return -2; } deserialize(dat_size, buffer, pList); return 0; } /* This function requests a certain number of unique IDs. * Returns the new ID if everything is ok; * or returns 0 if new ID can not be retrieved from server. * returns -1 if cleint message fails to be sent out. */ int32 remoteClient::reqID(uint32 id_num) { string msg2srv("req_id: "); msg2srv.append(num2str(id_num)); if (sendMessage(g_session, msg2srv)) { errMsg = "Client request not sent out"; return -1; } int32 dat_size = parseServerMsg(); if (dat_size <= 0) return 0; int32 startID = 0; if (gnutls_record_recv(g_session, &startID, sizeof(int32)) != sizeof(int32)) { errMsg = "New ID not received successully from server"; return 0; } if ((ntohs(1) == 1)) swap(&startID); if (startID <= 0) { errMsg = "Invalid ID from server: " + num2str(startID); return 0; } return startID; } /* This function sends a request of current time stamp to server. * Returns -1 if client message not sent successfully; * returns 0 if the time stamp from server is non-positive; * returns the time stamp integer if everything is ok. */ int32 remoteClient::reqTime() { string msg2srv("req_time"); if (sendMessage(g_session, msg2srv)) { errMsg = "Client request not sent out"; return -1; } int32 t_stamp = 0; if (gnutls_record_recv(g_session, &t_stamp, sizeof(int32)) != sizeof(int32)) { errMsg = "Time stamp not received successully from server"; return 0; } if ((ntohs(1) == 1)) swap(&t_stamp); if (t_stamp <= 0) { errMsg = "Invalid time stamp from server: " + num2str(t_stamp); return 0; } return t_stamp; } /* Add a new user account to remote db. * Returns 0 if everything is ok; * returns -1 if put message can not be sent out to server; * returns -2 if data of new user can not be sent out to server; * returns -3 if server confirmation message is not received; * returns -4 if server confirmation message is invalid. */ int remoteClient::putNewUser(const userGUI& uiData) { int32 dat_size = uiData.getSize(); char buff[dat_size]; uiData.serialize(buff); string msg2srv("put_new_user: "); msg2srv.append(num2str(dat_size)); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } if (sendBuffer(g_session, dat_size, buff)) { errMsg = "Failed to send new user data to server"; return -2; } char msg_recv[MSG_SIZE + 1]; if (recvMessage(g_session, msg_recv)) { errMsg = "Server feedback not received"; return -3; } if (strcmp(msg_recv, "success")) { errMsg = msg_recv; return -4; } return 0; } /* Add new score name records into remote db. * Returns 0 if everything is ok; * returns -1 if put message can not be sent out to server; * returns -2 if data of new score name(s) can not be sent out to server; * returns -3 if server confirmation message is not received; * returns -4 if server confirmation message is invalid. */ int remoteClient::putNewScoreName(const vector& snList) { int32 dat_size = getSize(snList); char buff[dat_size]; serialize(snList, buff); string msg2srv("put_scorename: "); msg2srv.append(num2str(dat_size)); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } if (sendBuffer(g_session, dat_size, buff)) { errMsg = "Failed to send score name data to server"; return -2; } char msg_recv[MSG_SIZE + 1]; if (recvMessage(g_session, msg_recv)) { errMsg = "Server feedback not received"; return -3; } if (strcmp(msg_recv, "success")) { errMsg = msg_recv; return -4; } // update score name maps on client side for (uint i = 0; i < snList.size(); ++i) { dbs.add_scorename(snList[i]); } return 0; } /* Add new patient, test sessions and score values into remote db. * Returns 0 if everything is ok; * returns -1 if put message can not be sent out to server; * returns -2 if new patient and sessions data can not be sent out to server; * returns -3 if data size of a certain score value can not be sent out to server; * returns -4 if a certain score value data can not be sent out to server; * returns -5 if server confirmation message is not received or it is invalid. */ int remoteClient::putNewPatient(DBpatient& patient_in) { patientRec newPatient; newPatient.setID(patient_in.patientID); uint32 p_size = newPatient.getSize(); uint32 s_size = patient_in.getSessionSize(); uint32 v_num = patient_in.scores.size(); string msg2srv("put_patient: "); msg2srv += num2str(p_size) + " " + num2str(s_size) + " " + num2str(v_num); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } char buff[p_size + s_size]; newPatient.serialize(buff); patient_in.serializeSessions(buff + p_size); if (sendBuffer(g_session, p_size + s_size, buff)) { errMsg = "Failed to send new patient and session data to server"; return -2; } // Send patient score values to server, one by one map::iterator sv_it; for (sv_it = patient_in.scores.begin(); sv_it != patient_in.scores.end(); ++sv_it) { if (sv_it->second.id<=0) continue; uint32 sv_size = sv_it->second.getSize(); uint32 size_net = sv_size; if (ntohs(1) == 1) swap(&size_net); //if (sendBuffer(g_session, sizeof(uint32), (char*) (&size_net))) { if (gnutls_record_send(g_session, &size_net, sizeof(uint32)) != sizeof(uint32)) { errMsg = "Failed to send size of score value " + sv_it->second.scorename + " to server"; return -3; } char* sv_dat = new char[sv_size]; sv_it->second.serialize(sv_dat); if (sendBuffer(g_session, sv_size, sv_dat)) { errMsg = "Failed to send score value " + sv_it->second.scorename + " to server"; return -4; } } uint32 t_stamp = recvTimeMsg(); if (t_stamp == 0) return -5; patient_in.updateTime(t_stamp); return 0; } /* This function parses an input string. * If it is in a format of "updated:xxx", converts xxx into a uint32 and returns it; * returns 0 if one of the following errors happens: *( if message can not be received from server; * returns -2 if the format is not correct; * returns -3 if it is in correct format but xxx can not be converted to valid uint32. */ uint32 remoteClient::recvTimeMsg() { char msg_recv[MSG_SIZE + 1]; if (recvMessage(g_session, msg_recv)) { errMsg = "Server feedback not received"; return 0; } string tmpStr(msg_recv); if (tmpStr.size() <= 8 || tmpStr.substr(0, 8) != "updated:") { errMsg = msg_recv; return 0; } uint32 time_int = 0; string t_str = tmpStr.substr(8, tmpStr.size() - 8); if (!str2num(t_str, time_int) || time_int <= 0) { errMsg = "Invalid update time stamp from server: " + t_str; return 0; } return time_int; } /* Only add new sessions into remote database. * Returns 0 if everything is ok; * returns -1 if put message can not be sent out to server; * returns -2 if session data can not be sent out to server; * returns -3 if server confirmation message is not received; * returns -4 if server conformation message is invalid. */ int remoteClient::putNewSession(vector& sList) { int32 dat_size = getSize(sList); char buff[dat_size]; serialize(sList, buff); string msg2srv("put_session: "); msg2srv.append(num2str(dat_size)); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } if (sendBuffer(g_session, dat_size, buff)) { errMsg = "Failed to send session data to server"; return -2; } char msg_recv[MSG_SIZE + 1]; if (recvMessage(g_session, msg_recv)) { errMsg = "Server feedback not received"; return -3; } if (strcmp(msg_recv, "success")) { errMsg = msg_recv; return -4; } return 0; } /* Add score values (test results) into remote db. * Returns 0 if everything is ok; * returns -1 if put message can not be sent out to server; * returns -2 if score value ID in input set is not found in input map; * returns -3 if score value header data can not be sent out to server; * returns -4 if any score value data can not be sent out to server; * returns -5 if time stamp from server is not received correctly. */ int remoteClient::putScoreValues(set svID, map& svMap) { int32 sv_num = svID.size();; string msg2srv("put_scorevalue: "); msg2srv.append(num2str(sv_num)); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } set::iterator id_it; for (id_it = svID.begin(); id_it != svID.end(); ++id_it) { int32 tmpID = *id_it; map::iterator map_it = svMap.find(tmpID); if (map_it == svMap.end()) { errMsg = "Invalid score value ID in DBscorevalue map: " + num2str(tmpID); return -2; } uint32 sv_size = svMap[tmpID].getSize(); uint32 size_net = sv_size; if (ntohs(1) == 1) swap(&size_net); if (gnutls_record_send(g_session, &size_net, sizeof(uint32)) != sizeof(uint32)) { errMsg = "Failed to send size of score value of " + map_it->second.scorename + " to server"; return -3; } char* sv_dat = new char[sv_size]; map_it->second.serialize(sv_dat); if (sendBuffer(g_session, sv_size, sv_dat)) { errMsg = "Failed to send score value of " + map_it->second.scorename + " to server"; delete [] sv_dat; return -4; } delete [] sv_dat; } uint32 t_stamp = recvTimeMsg(); if (t_stamp == 0) return -5; // Update score value time stamps on client side for (id_it = svID.begin(); id_it != svID.end(); ++id_it) { int32 tmpID = *id_it; svMap[tmpID].whenset.setUnixTime(t_stamp); } return 0; } /* Add score values (test results) into remote db. * Returns 0 if everything is ok; * returns -1 if put message can not be sent out to server; * returns -2 if patient list data can not be sent out to server; * returns -3 if server confirmation message is not received; * returns -4 if server confirmation message is invalid. */ int remoteClient::putPatientList(DBpatientlist& inputRec, bool isNew) { int32 dat_size = inputRec.getSize(); char buff[dat_size]; inputRec.serialize(buff); string msg2srv; if (isNew) msg2srv = "put_patientlist: "; else msg2srv = "mod_patientlist: "; msg2srv.append(num2str(dat_size)); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } if (sendBuffer(g_session, dat_size, buff)) { errMsg = "Failed to send patient list data to server"; return -2; } char msg_recv[MSG_SIZE + 1]; if (recvMessage(g_session, msg_recv)) { errMsg = "Server feedback not received"; return -3; } uint32 t_stamp = recvTimeMsg(); if (t_stamp == 0) return -4; if (isNew) inputRec.runDate.setUnixTime(t_stamp); else inputRec.modDate.setUnixTime(t_stamp); return 0; } /* This function accepts a user name and loads that user's information into outInfo. * Returns 0 if everything is ok; * returns -1 if request message can not be sent to server; * returns -2 if size of data from server is invalid; * returns -3 if data from server can not be received. */ int remoteClient::reqUser(const string& usrname, userRec& outInfo) { string msg2srv("req_usr_info: "); msg2srv.append(usrname); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send request to server"; return -1; } int32 dat_size = parseServerMsg(); if (!dat_size) return -2; char dat_buff[dat_size]; if (recvBuffer(g_session, dat_size, dat_buff)) { errMsg = "Failed to receive user data from server"; return -3; } outInfo.deserialize(dat_buff); return 0; } /* This function sends client's patient search requests to server * and parses the data buffer from server. * Returns 0 if everything is ok; * returns -1 if request message can not be sent out to server; * returns -2 if size of data from server is invalid; * returns -3 if data from server can not be received. */ int remoteClient::reqSearchPatient(const patientSearchTags& tag_in, vector& pMatches) { string msg2srv = tag_in.getStr(); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } int32 dat_size = parseServerMsg(); if (!dat_size) return -2; char dat_buff[dat_size]; if (recvBuffer(g_session, dat_size, dat_buff)) { errMsg = "Failed to receive patient data from server"; return -3; } deserialize(dat_size, dat_buff, pMatches); return 0; } /* This function sends server request of getting all score values * of a certain patient and parses the data buffer from server. * Returns 0 if everything is ok; * returns -1 if request message can not be sent out to server; * returns -2 if not score value is available for this patient; * returns -3 for unknown message form server; * returns -4 if size of score value is invalid; * returns -5 if score value data is invalid; * returns -6 if size of session data is invalid; * returns -7 if session data are invalid. */ int remoteClient::reqOnePatient(int32 pID, DBpatient& patient_out) { string msg2srv("req_patient: "); msg2srv.append(num2str(pID)); if (sendMessage(g_session, msg2srv)) { errMsg = "Failed to send message to server"; return -1; } // Receive score values from server int32 srvStat = parseServerMsg(); if (srvStat == -3) { errMsg = "No score value for this patient"; return -2; } if (srvStat != -5) return -3; while (srvStat == -5) { int32 dat_size = atoi(s_tokens(1)); if (dat_size <= 0) { errMsg = "Invalid data size of score value: " + s_tokens[1]; return -4; } string newPerm = s_tokens[2]; char* sv_buff= new char[dat_size]; if (recvBuffer(g_session, dat_size, sv_buff)) { errMsg = "Failed to receive patient score value data from server"; delete [] sv_buff; return -5; } DBscorevalue tmpRec; tmpRec.deserializeHdr(sv_buff); patient_out.scores[tmpRec.id] = tmpRec; patient_out.scores[tmpRec.id].deserialize(sv_buff); patient_out.scores[tmpRec.id].permission = newPerm; delete [] sv_buff; srvStat = parseServerMsg(); } if (srvStat == -4) return 0; // no session available from server if (srvStat <= 0) return -6; vector sessList; char sess_buff[srvStat]; if (recvBuffer(g_session, srvStat, sess_buff)) { errMsg = "Failed to receive test session data from server"; return -7; } deserialize(srvStat, sess_buff, sessList); patient_out.setSessionMap(sessList); patient_out.resetMaps(); return 0; } // Close client connection cleanly int remoteClient::exit() { if (!init_flag) return 0; if (online) gnutls_bye(g_session, GNUTLS_SHUT_RDWR); close(c_stat); gnutls_deinit(g_session); gnutls_srp_free_client_credentials(srpcred); gnutls_global_deinit(); online = false; return 0; } voxbo-1.8.5~svn1246/client/dbclient.h000066400000000000000000000111261153177201300173400ustar00rootroot00000000000000 // dbclient.h // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu #ifndef DBCLIENT_H #define DBCLIENT_H #include #include #include #include "typedefs.h" #include "db_util.h" #include "dbdata.h" #include "tokenlist.h" /* DBclient is an abstract base class. */ class DBclient { friend class DBview; public: DBclient(); DBclient(const string &username, const string &pwd); virtual ~DBclient(); void setUserName(const string& inputStr) { username = inputStr; } void setPasswd(const string& inputStr) { passwd = inputStr; } string getErrMsg() { return errMsg; } virtual int login() = 0; virtual int putNewUser(const userGUI&) = 0; virtual int putNewScoreName(const vector&) = 0; virtual int putNewPatient(DBpatient&) = 0; virtual int putNewSession(vector&) = 0; virtual int putScoreValues(set, map&) = 0; virtual int putPatientList(DBpatientlist&, bool) = 0; virtual int32 reqID(uint32) = 0; virtual int32 reqTime() = 0; virtual int reqUser(const string&, userRec&) = 0; virtual int reqSearchPatient(const patientSearchTags&, vector&) = 0; virtual int reqOnePatient(int32, DBpatient&) = 0; virtual int exit() = 0; operator bool() {return online;} DBdata dbs; vector pList; protected: string username, passwd, errMsg; bool online; }; /* Local client, inherited from DBclient. */ class localClient : public DBclient { public: localClient(); localClient(const string& username, const string& pwd, const string& filename); ~localClient(); void setEnvHome(const string& inputDir) { dbs.dirname = inputDir; } virtual int login(); virtual int putNewUser(const userGUI&); virtual int putNewScoreName(const vector&); virtual int putNewPatient(DBpatient&); virtual int putNewSession(vector&); virtual int putScoreValues(set, map&); virtual int putPatientList(DBpatientlist&, bool); virtual int32 reqID(uint32); virtual int32 reqTime(); virtual int reqUser(const string&, userRec &); virtual int reqSearchPatient(const patientSearchTags&, vector&); virtual int reqOnePatient(int32, DBpatient&); virtual int exit(); private: int32 userID; map permissions; }; /* Remote client, inherited from DBclient. */ class remoteClient : public DBclient { public: remoteClient(); remoteClient(const string&, const string&, const string&, uint32); ~remoteClient(); void setServerName(const string& inputStr) { serverName = inputStr; } void setServerPort(uint32 inputVal) { serverPort = inputVal; } virtual int login(); virtual int putNewUser(const userGUI&); virtual int putNewScoreName(const vector&); virtual int putNewPatient(DBpatient&); virtual int putNewSession(vector&); virtual int putScoreValues(set, map&); virtual int putPatientList(DBpatientlist&, bool); virtual int32 reqID(uint32); virtual int32 reqTime(); virtual int reqUser(const string&, userRec&); virtual int reqSearchPatient(const patientSearchTags&, vector&); virtual int reqOnePatient(int32, DBpatient&); virtual int exit(); private: int chkServer(); int chkHandshake(); int32 parseServerMsg(); int32 parseTimeMsg(char*); int recvMaps(); int recvTypes(); int recvScoreNames(); int recvRegionNames(); int recvSynonyms(); int recvRegionRelations(); int recvPatientList(); uint32 recvTimeMsg(); string serverName; uint32 serverPort; int32 c_stat; tokenlist s_tokens; gnutls_session_t g_session; gnutls_srp_client_credentials_t srpcred; bool init_flag; //const int BUFSIZE; }; #endif voxbo-1.8.5~svn1246/client/dbdialogs.cpp000066400000000000000000000220101153177201300200310ustar00rootroot00000000000000 #include #include #include #include "dbdialogs.moc.h" #include "myboxes.h" using namespace std; DBnewsession::DBnewsession(QWidget *parent) : QDialog(parent) { QHBox *hb; QPushButton *button; QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); this->setLayout(layout); hb=new QHBox; layout->addWidget(hb); hb->addLabel("Name:"); w_name=new QLineEdit(); hb->addWidget(w_name); hb=new QHBox; layout->addWidget(hb); hb->addLabel("Date:"); w_date=new QDateTimeEdit(); w_date->setCalendarPopup(1); w_date->setDisplayFormat("d-MMM-yyyy h:mmap"); hb->addWidget(w_date); hb=new QHBox; layout->addWidget(hb); hb->addLabel("Location:"); w_location=new QLineEdit(); hb->addWidget(w_location); hb=new QHBox; layout->addWidget(hb); hb->addLabel("Examiner:"); w_examiner=new QLineEdit(); hb->addWidget(w_examiner); hb=new QHBox; layout->addWidget(hb); hb->addLabel("Notes:"); w_notes=new QLineEdit(); hb->addWidget(w_notes); layout->insertSpacing(-1,40); hb=new QHBox(); layout->addWidget(hb); button=new QPushButton("Done"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Cancel"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); setMinimumSize(320,1); setWindowTitle("mydialog"); } DBpicksession::DBpicksession(QWidget *parent,DBpatient *p) : QDialog(parent) { QHBox *hb; QPushButton *button; QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); this->setLayout(layout); w_tree=new QTreeWidget(); layout->addWidget(w_tree); w_tree->setColumnCount(3); QStringList hh; hh<<"Session ID"<<"date"<<"examiner"; w_tree->setHeaderLabels(hh); w_tree->setAllColumnsShowFocus(1); w_tree->setRootIsDecorated(0); w_tree->setUniformRowHeights(1); pair s; int f_first=1; vbforeach(s,p->sessions) { QTreeWidgetItem *it=new QTreeWidgetItem(w_tree); if (f_first) { w_tree->setCurrentItem(it); f_first=0; } it->setText(0,strnum(s.second.id).c_str()); it->setText(1,s.second.date.getDateStr()); it->setText(2,s.second.examiner.c_str()); it->setData(0,0,QVariant(s.second.id)); w_tree->addTopLevelItem(it); } layout->insertSpacing(-1,40); hb=new QHBox(); layout->addWidget(hb); button=new QPushButton("Done"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Cancel"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); setMinimumSize(320,1); setWindowTitle("mydialog"); } int32 DBpicksession::selectedsession() { return w_tree->currentItem()->data(0,0).toUInt(); } DBpicktest::DBpicktest(QWidget *parent,DBclient *c) : QDialog(parent) { QHBox *hb; QPushButton *button; QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); this->setLayout(layout); w_tree=new QTreeWidget(); layout->addWidget(w_tree); w_tree->setColumnCount(3); QStringList hh; hh<<"Test ID"<<"name"<<"that's it?"; w_tree->setHeaderLabels(hh); w_tree->setAllColumnsShowFocus(1); w_tree->setRootIsDecorated(0); w_tree->setUniformRowHeights(1); int f_first=1; vector testlist=getchildren(c->dbs.scorenamechildren,""); vbforeach(string &s,testlist) { QTreeWidgetItem *it=new QTreeWidgetItem(w_tree); if (f_first) { w_tree->setCurrentItem(it); f_first=0; } it->setText(0,s.c_str()); it->setText(1,s.c_str()); it->setText(2,"nomore"); it->setData(0,0,QVariant(s.c_str())); w_tree->addTopLevelItem(it); } layout->insertSpacing(-1,40); hb=new QHBox(); layout->addWidget(hb); button=new QPushButton("Done"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Cancel"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); setMinimumSize(320,1); setWindowTitle("mydialog"); } DBplist::DBplist(QWidget *parent,DBpatientlist &) : QDialog(parent) { QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); this->setLayout(layout); // FIXME actually we need a place to edit the name, patients, and // notes w_tree=new QTreeWidget(); layout->addWidget(w_tree); w_tree->setColumnCount(3); QStringList hh; hh<<"Test ID"<<"name"<<"that's it?"; w_tree->setHeaderLabels(hh); w_tree->setAllColumnsShowFocus(1); w_tree->setRootIsDecorated(0); w_tree->setUniformRowHeights(1); layout->insertSpacing(-1,40); QHBox *hb=new QHBox(); layout->addWidget(hb); QPushButton *button=new QPushButton("Done"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Cancel"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); setMinimumSize(320,1); setWindowTitle("choose a patient list"); } string DBpicktest::selectedtest() { return w_tree->currentItem()->data(0,0).toString().toStdString(); } DBlocallogin::DBlocallogin(QWidget *parent) : QDialog(parent) { QHBox *hb; QPushButton *button; QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(0); layout->setMargin(0); this->setLayout(layout); QFormLayout *myform=new QFormLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); layout->addLayout(myform); w_username=new QLineEdit(); w_password=new QLineEdit(); w_password->setEchoMode(QLineEdit::Password); w_dirname=new QLineEdit(); myform->addRow("username:",w_username); myform->addRow("password:",w_password); myform->addRow("directory:",w_dirname); w_message=new QLabel(); QPalette plt; plt.setColor(QPalette::WindowText,Qt::red); w_message->setPalette(plt); layout->addWidget(w_message); layout->insertSpacing(-1,25); hb=new QHBox(); layout->addWidget(hb); button=new QPushButton("Done"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Cancel"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); setMinimumSize(320,1); setWindowTitle("mydialog"); } DBremotelogin::DBremotelogin(QWidget *parent) : QDialog(parent) { QHBox *hb; QPushButton *button; QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(0); layout->setMargin(0); this->setLayout(layout); QFormLayout *myform=new QFormLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); layout->addLayout(myform); w_username=new QLineEdit(); w_password=new QLineEdit(); w_password->setEchoMode(QLineEdit::Password); w_servername=new QLineEdit(); w_serverport=new QLineEdit(); w_serverport->setText("6010"); myform->addRow("username:",w_username); myform->addRow("password:",w_password); myform->addRow("server:",w_servername); myform->addRow("port:",w_serverport); w_message=new QLabel(); QPalette plt; plt.setColor(QPalette::WindowText,Qt::red); w_message->setPalette(plt); layout->addWidget(w_message); layout->insertSpacing(-1,25); hb=new QHBox(); layout->addWidget(hb); button=new QPushButton("Done"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Cancel"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); setMinimumSize(320,1); setWindowTitle("mydialog"); } DBuserinfo::DBuserinfo(QWidget *parent) : QDialog(parent) { QHBox *hb; QPushButton *button; QVBoxLayout *layout=new QVBoxLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(4); this->setLayout(layout); QFormLayout *myform=new QFormLayout(); layout->setAlignment(Qt::AlignTop); layout->setSpacing(2); layout->setMargin(3); layout->addLayout(myform); w_username=new QLineEdit(); w_password=new QLineEdit(); w_name=new QLineEdit(); w_phone=new QLineEdit(); w_email=new QLineEdit(); w_address=new QLineEdit(); w_password->setEchoMode(QLineEdit::Password); myform->addRow("username:",w_username); myform->addRow("password:",w_password); myform->addRow("name:",w_name); myform->addRow("phone:",w_phone); myform->addRow("email:",w_email); myform->addRow("address:",w_address); layout->insertSpacing(-1,40); hb=new QHBox(); layout->addWidget(hb); button=new QPushButton("Done"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(accept())); button=new QPushButton("Cancel"); hb->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(reject())); setMinimumSize(320,1); setWindowTitle("User data"); } voxbo-1.8.5~svn1246/client/dbdialogs.h000066400000000000000000000117131153177201300175060ustar00rootroot00000000000000 // dbdialogs.h // simple dialogs for database // Copyright (c) 2009 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include "mydefs.h" #include "dbclient.h" using namespace std; class DBnewsession : public QDialog { Q_OBJECT public: DBnewsession(QWidget *parent); DBdate date() {return DBdate(w_date->date().month(),w_date->date().day(), w_date->date().year(),w_date->time().hour(), w_date->time().minute(),w_date->time().second());} string location() {return w_location->text().toStdString();} string examiner() {return w_examiner->text().toStdString();} string notes() {return w_notes->text().toStdString();} public slots: private: QLineEdit *w_name; QDateTimeEdit *w_date; QLineEdit *w_location; QLineEdit *w_examiner; QLineEdit *w_notes; signals: }; class DBpicksession : public QDialog { Q_OBJECT public: DBpicksession(QWidget *parent,DBpatient *p); int32 selectedsession(); public slots: private: QTreeWidget *w_tree; signals: }; class DBpicktest : public QDialog { Q_OBJECT public: DBpicktest(QWidget *parent,DBclient *c); string selectedtest(); public slots: private: QTreeWidget *w_tree; signals: }; class DBplist : public QDialog { Q_OBJECT public: DBplist(QWidget *parent,DBpatientlist &plist); public slots: private: QTreeWidget *w_tree; signals: }; class DBuserinfo : public QDialog { Q_OBJECT public: DBuserinfo(QWidget *parent); // username, password, contact info, group memberships string username() {return w_username->text().toStdString();} string password() {return w_password->text().toStdString();} string name() {return w_name->text().toStdString();} string phone() {return w_phone->text().toStdString();} string email() {return w_email->text().toStdString();} string address() {return w_address->text().toStdString();} void setusername(string s) {w_username->setText(s.c_str());} void setpassword(string s) {w_password->setText(s.c_str());} void setname(string s) {w_name->setText(s.c_str());} void setphone(string s) {w_phone->setText(s.c_str());} void setemail(string s) {w_email->setText(s.c_str());} void setaddress(string s) {w_address->setText(s.c_str());} public slots: private: QLineEdit *w_username; QLineEdit *w_password; QLineEdit *w_name; QLineEdit *w_phone; QLineEdit *w_email; QLineEdit *w_address; signals: }; class DBlocallogin : public QDialog { Q_OBJECT public: DBlocallogin(QWidget *parent); string username() {return w_username->text().toStdString();} string password() {return w_password->text().toStdString();} string dirname() {return w_dirname->text().toStdString();} string message() {return w_message->text().toStdString();} void setusername(string s) {w_username->setText(s.c_str());} void setpassword(string s) {w_password->setText(s.c_str());} void setdirname(string s) {w_dirname->setText(s.c_str());} void setmessage(string s) {w_message->setText(s.c_str());} public slots: private: QLineEdit *w_username; QLineEdit *w_password; QLineEdit *w_dirname; QLabel *w_message; signals: }; class DBremotelogin : public QDialog { Q_OBJECT public: DBremotelogin(QWidget *parent); string username() {return w_username->text().toStdString();} string password() {return w_password->text().toStdString();} string servername() {return w_servername->text().toStdString();} uint16 serverport() {return strtol(w_serverport->text().toStdString());} string message() {return w_message->text().toStdString();} void setusername(string s) {w_username->setText(s.c_str());} void setpassword(string s) {w_password->setText(s.c_str());} void setservername(string s) {w_servername->setText(s.c_str());} void setserverport(uint16 p) {w_serverport->setText(strnum(p).c_str());} void setmessage(string s) {w_message->setText(s.c_str());} public slots: private: QLineEdit *w_username; QLineEdit *w_password; QLineEdit *w_servername; QLineEdit *w_serverport; QLabel *w_message; signals: }; voxbo-1.8.5~svn1246/client/dbmainwindow.cpp000066400000000000000000000403601153177201300205730ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include #include "dbclient.h" #include "dbview.h" #include "searchPatient.h" #include "dbdialogs.h" #include "dbmainwindow.moc.h" // internal enums for event handling enum {AL_NONE,AL_IMPORTANT,AL_MESSAGES,AL_LISTS,AL_USERINFO,AL_DBINFO, AL_FORMS,AL_RESULTS,AL_CONTACTS}; const string headerstyle1="color:red;"; DBmainwindow::DBmainwindow() { setGeometry(150,150,800,600); myframe=new QFrame; setCentralWidget(myframe); a_open=new QAction("&Open local database",this); a_connect=new QAction("&Connect to remote database",this); a_close=new QAction("&Close/Disconnect",this); a_create=new QAction("Create &new database",this); a_search=new QAction("&Search database",this); a_test=new QAction("tes&t",this); a_newuser=new QAction("new user",this); a_newpatient=new QAction("new patient",this); a_online=new QAction("take database offline",this); QObject::connect(a_open,SIGNAL(triggered()),this,SLOT(open())); QObject::connect(a_connect,SIGNAL(triggered()),this,SLOT(connect())); QObject::connect(a_create,SIGNAL(triggered()),this,SLOT(create())); QObject::connect(a_search,SIGNAL(triggered()),this,SLOT(search())); QObject::connect(a_test,SIGNAL(triggered()),this,SLOT(test())); QObject::connect(a_close,SIGNAL(triggered()),this,SLOT(close())); QObject::connect(a_newuser,SIGNAL(triggered()),this,SLOT(newuser())); QObject::connect(a_newpatient,SIGNAL(triggered()),this,SLOT(newpatient())); QObject::connect(a_online,SIGNAL(triggered()),this,SLOT(online())); client=NULL; w_menubar=menuBar(); setMenuBar(w_menubar); filemenu=w_menubar->addMenu("File"); filemenu->addAction(a_open); filemenu->addAction(a_connect); filemenu->addAction(a_create); filemenu->addAction(a_close); secondmenu=w_menubar->addMenu("More Stuff"); secondmenu->addAction(a_search); secondmenu->addAction(a_test); adminmenu=w_menubar->addMenu("Admin"); adminmenu->addAction(a_newuser); adminmenu->addAction(a_newpatient); adminmenu->addAction(a_online); //w_statusbar=statusBar(); //w_statusbar->showMessage("hahahaha"); w_menubar->show(); filemenu->show(); currentpanel=AL_NONE; setup(); updatevisiblewidgets(); arrangeChildren(); } void DBmainwindow::resizeEvent(QResizeEvent *re) { QMainWindow::resizeEvent(re); if (client) { arrangeChildren(); } } void DBmainwindow::open() { DBlocallogin ll(this); // FIXME bad defaults! ll.setusername("admin"); ll.setpassword("test"); ll.setdirname("test"); while (1) { int ret=ll.exec(); if (ret!=QDialog::Accepted) return; client=new localClient(ll.username(),ll.password(),ll.dirname()); if (!(client->login())) break; delete client; client=NULL; ll.setmessage("nice try!"); // FIXME should probably say something else } populate(); w_arealist->setCurrentItem(al_aboutitem,QItemSelectionModel::Select); currentpanel=AL_DBINFO; updatevisiblewidgets(); arrangeChildren(); } void DBmainwindow::connect() { DBremotelogin ll(this); // FIXME bad defaults! ll.setusername("kimberg"); ll.setpassword("kimberg"); ll.setservername("rage.uphs.upenn.edu"); ll.setserverport(6010); int ret=ll.exec(); if (ret!=QDialog::Accepted) return; client=new remoteClient(ll.username(),ll.password(),ll.servername(),ll.serverport()); if (client->login()) { delete client; client=NULL; // FIXME should probably say something here return; } populate(); w_arealist->setCurrentItem(al_aboutitem,QItemSelectionModel::Select); currentpanel=AL_DBINFO; updatevisiblewidgets(); arrangeChildren(); } void DBmainwindow::create() { cout << "create not yet implemented, but let's open a window" << endl; DBmainwindow *tmpw=new DBmainwindow; tmpw->show(); } // FIXME obsolete this? or use it as an alternative to the quick // search? void DBmainwindow::search() { // if (!client) return; // SearchPatient *sp_form = new SearchPatient(client); // sp_form->show(); } void DBmainwindow::test() { DBnewsession t1(this); t1.exec(); DBpatient pp; DBpicksession t2(this,&pp); t2.exec(); if (client) { DBpicktest t3(this,client); t3.exec(); } } void DBmainwindow::close() { if (!client) return; client->exit(); client=NULL; arrangeChildren(); updatevisiblewidgets(); } void DBmainwindow::newuser() { if (!client) return; DBuserinfo uu(this); uu.setusername(""); if (uu.exec()==QDialog::Rejected) return; userGUI ug; ug.setAccount(uu.username()); ug.setPasswd(uu.password()); ug.setName(uu.name()); ug.setPhone(uu.phone()); ug.setEmail(uu.email()); ug.setAddress(uu.address()); int err; if ((err=client->putNewUser(ug))==0) QMessageBox::critical(0, "Yes!", "Your new user has been created."); else { QMessageBox::critical(0, "Error", "Your new user has not been created."); cout << err << endl; } } void DBmainwindow::newpatient() { DBpatient pp; pp.patientID=-1; DBview *dd=new DBview(client,pp); dd->layout_view("newpatient"); dd->show(); } void DBmainwindow::online() { cout << "FIXME coming soon" << endl; } void DBmainwindow::handleAreaList() { QList selections=w_arealist->selectedItems(); if (selections.size()!=1) return; QListWidgetItem *it=selections[0]; if (it->type()==currentpanel) { // FIXME refresh certain panels? return; } // otherwise hide, then show w_messages->hide(); w_lists->hide(); w_userinfo->hide(); w_dbinfo->hide(); w_resultsbox->hide(); currentpanel=it->type(); switch (currentpanel) { case AL_NONE: return; case AL_MESSAGES: w_messages->show(); return; case AL_LISTS: w_lists->show(); return; case AL_USERINFO: w_userinfo->show(); return; case AL_DBINFO: w_dbinfo->show(); return; case AL_RESULTS: w_resultsbox->show(); return; } } void DBmainwindow::handleSearch() { if (s_searchline->text().isEmpty()) { // FIXME QMessageBox::critical(0, "Error", "You didn't enter anything to search for"); return; } // if (searchPart->isChecked() && !currentPatients.size()) { // QMessageBox::critical(0, "Error", "Search aborted: no patients found yet."); // return; // } //if (searchPart->isChecked()) //tags_out.patientIDs = currentPatients; // put search info into proper form for server patientSearchTags s_tags; // FIXME s_tags should be the right scorename when needed // int field_index = s_field->currentIndex(); s_tags.scoreName=""; s_tags.relationship = s_relation->currentText().toStdString(); s_tags.searchStr = s_searchline->text().toStdString(); s_tags.case_sensitive = false; // if (insensButt->isChecked()) // tags_out.case_sensitive = false; // else // tags_out.case_sensitive = true; // execute the search vector pmList; client->reqSearchPatient(s_tags,pmList); // FIXME right now reqSearchPatient() returns nonzero both on error // and if the search doesn't turn anything up. the latter should // really return 0 with an empty vector of patientMatch // vector results; w_searchresults->clear(); for (size_t i=0; isetData(Qt::UserRole,QVariant(pmList[i].patientID)); w_searchresults->addItem(tmp); } w_arealist->clearSelection(); w_arealist->setCurrentItem(al_resultsitem,QItemSelectionModel::Select); } void DBmainwindow::handleSaveResults() { cout << "FIXME: nothing doing" << endl; } void DBmainwindow::handleSearchResultClicked(QListWidgetItem *it) { uint32 patientid=it->data(Qt::UserRole).toInt(); cout << patientid << endl; DBview *pview = new DBview(client,patientid); if (pview && *pview) { pview->layout_view("patient"); pview->show(); } else { // FIXME shouldn't happen warning cout << "shouldnt happen" << endl; cout << pview->patient.patientID << endl; delete pview; } } // setup() creates all the widgets and calls arrangeChildren() to set // their geometries void DBmainwindow::setup() { // LOGO w_logo=new QLabel(myframe); w_logo->setPixmap(QPixmap(":/icons/a_logo.png")); w_logo->show(); // DB BANNER w_banner=new QLabel(myframe); w_banner->setText("Welcome to the database"); w_banner->hide(); // MOTD w_motd=new QLabel(myframe); w_motd->setText("Watch out for falling pianos!"); w_motd->hide(); // AREAS w_arealist=new QListWidget(myframe); al_aboutitem=new QListWidgetItem("About this database",w_arealist,AL_DBINFO); al_resultsitem=new QListWidgetItem("Your Search Results",w_arealist,AL_RESULTS); w_arealist->addItem(al_aboutitem); w_arealist->addItem(new QListWidgetItem("Your Messages",w_arealist,AL_MESSAGES)); w_arealist->addItem(new QListWidgetItem("Your Patient Lists",w_arealist,AL_LISTS)); w_arealist->addItem(new QListWidgetItem("Your Account",w_arealist,AL_USERINFO)); w_arealist->addItem(new QListWidgetItem("Your Forms",w_arealist,AL_FORMS)); w_arealist->addItem(al_resultsitem); w_arealist->addItem(new QListWidgetItem("Your Contact Records",w_arealist,AL_CONTACTS)); w_arealist->addItem(new QListWidgetItem("Other Stuff",w_arealist,AL_IMPORTANT)); QObject::connect(w_arealist,SIGNAL(itemSelectionChanged()),this,SLOT(handleAreaList())); w_arealist->setSelectionMode(QAbstractItemView::SingleSelection); w_arealist->hide(); // LISTS, USERINFO, DBINFO, SEARCHRESULTS w_lists=makeplistbox(); w_dbinfo=makedbinfobox(); w_userinfo=makeuserinfobox(); w_resultsbox=makeresultsbox(); w_lists->hide(); w_dbinfo->hide(); w_userinfo->hide(); w_resultsbox->hide(); // MESSAGES w_messages=new QFrame(myframe); w_messages->setFrameStyle(QFrame::Box|QFrame::Plain); w_messages->hide(); // SEARCHBOX w_searchbox=makesearchbox(); w_searchbox->hide(); } // populate interface using stuff in the client record void DBmainwindow::populate() { // search results should be cleared w_searchresults->clear(); // searchable fields in search box, plus other args searchScoreIDs.clear(); map::const_iterator iter; for (iter = client->dbs.scorenames.begin(); iter != client->dbs.scorenames.end(); ++iter) { if ((iter->second).flags.count("searchable")) { string tmpStr = (iter->second).screen_name; s_field->addItem(QString::fromStdString(tmpStr)); searchScoreIDs.push_back((iter->second).name); } } s_field->setCurrentIndex(0); s_relation->setCurrentIndex(0); s_searchline->clear(); // patient lists w_plisttree->clear(); if (client->pList.size()) { QListitems; QStringList sl; vbforeach(DBpatientlist &pl,client->pList) { sl << pl.name.c_str() << pl.search_strategy.c_str() << pl.notes.c_str(); items.append(new QTreeWidgetItem((QTreeWidget *)0,sl)); } w_plisttree->insertTopLevelItems(0,items); } // FIXME populate the forms // when we logged on, we should have requested patient(userid) // find all the scorenames that are children of the node "forms" // and all the instances of those children // each such child should have certain fields, including a brief // description, requester, due date // e.g., forms:posttest:duedate // clicking a form opens it up in a special dbview // that special dbview has a button for submitting the form, that // makes it read-only // FIXME populate most recent contacts // button to load up all contacts (in groups of 100 at least) } void DBmainwindow::updatevisiblewidgets() { w_logo->show(); bool f_client; if (client) f_client=1; else f_client=0; w_banner->setVisible(f_client); w_motd->setVisible(f_client); w_arealist->setVisible(f_client); w_dbinfo->setVisible(f_client); w_searchbox->setVisible(f_client); w_messages->setVisible(0); w_lists->setVisible(0); w_userinfo->setVisible(0); w_resultsbox->setVisible(0); } QHBox * DBmainwindow::makesearchbox() { QHBox *hb=new QHBox(myframe); QPushButton *tmpb=new QPushButton("Search"); hb->addWidget(tmpb); QObject::connect(tmpb,SIGNAL(clicked()),this,SLOT(handleSearch())); s_field = new QComboBox; s_field->addItem("Any Field"); hb->addWidget(s_field); s_relation = new QComboBox; s_relation->addItem("include"); s_relation->addItem("equal"); s_relation->addItem("wildcard"); hb->addWidget(s_relation); s_searchline=new QLineEdit; hb->addWidget(s_searchline); return hb; } QVBox * DBmainwindow::makeplistbox() { // treewidget with searches w_lists=new QVBox(myframe); QLabel *tmps=new QLabel("Your Patient Lists"); tmps->setStyleSheet(headerstyle1.c_str()); w_lists->addWidget(tmps); w_plisttree=new QTreeWidget; w_lists->addWidget(w_plisttree); w_plisttree->setColumnCount(3); QStringList tmpl; tmpl<<"Name"<<"Strategy"<<"Num"; w_plisttree->setHeaderLabels(tmpl); w_plisttree->setRootIsDecorated(0); w_plisttree->setAllColumnsShowFocus(1); // button area at the bottom QHBox *hb=new QHBox; w_lists->addWidget(hb); QPushButton *button; button=new QPushButton("update"); hb->addWidget(button); button=new QPushButton("open"); hb->addWidget(button); return w_lists; } QVBox * DBmainwindow::makeresultsbox() { // listwidget with search results w_resultsbox=new QVBox(myframe); QLabel *tmps=new QLabel("Your Search Results"); tmps->setStyleSheet(headerstyle1.c_str()); w_resultsbox->addWidget(tmps); w_searchresults=new QListWidget; QObject::connect(w_searchresults,SIGNAL(itemDoubleClicked(QListWidgetItem *)),this, SLOT(handleSearchResultClicked(QListWidgetItem *))); w_resultsbox->addWidget(w_searchresults); // button area at the bottom QHBox *hb=new QHBox; w_resultsbox->addWidget(hb); QPushButton *button; button=new QPushButton("save as list"); QObject::connect(button,SIGNAL(clicked()),this,SLOT(handleSaveResults())); hb->addWidget(button); return w_resultsbox; } QVBox * DBmainwindow::makeuserinfobox() { // treewidget with searches w_userinfo=new QVBox(myframe); QLabel *tmps=new QLabel("Your User Info"); tmps->setStyleSheet(headerstyle1.c_str()); w_userinfo->addWidget(tmps); // FIXME user info here // button area at the bottom QHBox *hb=new QHBox; w_userinfo->addWidget(hb); QPushButton *button; button=new QPushButton("update"); hb->addWidget(button); button=new QPushButton("revert"); hb->addWidget(button); return w_userinfo; } QVBox * DBmainwindow::makedbinfobox() { // treewidget with searches w_dbinfo=new QVBox(myframe); QLabel *tmps=new QLabel("Database Info"); tmps->setStyleSheet(headerstyle1.c_str()); w_dbinfo->addWidget(tmps); // FIXME db info here QFrame *foo=new QFrame(); w_dbinfo->addWidget(foo); foo->setFixedHeight(120); foo->setFrameStyle(QFrame::Box|QFrame::Sunken); return w_dbinfo; } void DBmainwindow::arrangeChildren() { int pos=0; const int SPACING=20; // LOGO AT TOP LEFT w_logo->adjustSize(); w_logo->setGeometry(10,pos+10,w_logo->width(),w_logo->height()); w_logo->show(); // BANNER AT TOP RIGHT w_banner->adjustSize(); w_banner->setGeometry(myframe->width()-w_banner->width()-10,pos+10,w_banner->width(),w_banner->height()); pos=w_logo->geometry().bottom(); if (w_banner->geometry().bottom()>pos) pos=w_logo->geometry().bottom(); // MOTD IF NEEDED if (v_motd.size()) { w_motd->setFixedWidth(myframe->width()*2/3); w_motd->adjustSize(); w_motd->setGeometry(myframe->width()/6,pos+SPACING,w_motd->width(),w_motd->height()); pos=w_motd->geometry().bottom(); w_motd->show(); } else w_motd->hide(); pos+=SPACING; int wtmp=(myframe->width()-30)/3; int htmp=myframe->height()-pos-SPACING-SPACING-40; // 40 is for search stuff // AREALIST BOTTOM LEFT w_arealist->setGeometry(10,pos,wtmp,htmp); // LISTS AND MESSAGES BOTTOM RIGHT w_lists->setGeometry(myframe->width()-10-wtmp*2,pos,wtmp*2,htmp); w_messages->setGeometry(myframe->width()-10-wtmp*2,pos,wtmp*2,htmp); w_userinfo->setGeometry(myframe->width()-10-wtmp*2,pos,wtmp*2,htmp); w_dbinfo->setGeometry(myframe->width()-10-wtmp*2,pos,wtmp*2,htmp); w_resultsbox->setGeometry(myframe->width()-10-wtmp*2,pos,wtmp*2,htmp); pos+=htmp+SPACING; // SEARCH HBOX ON THE VERY BOTTOM w_searchbox->setGeometry(10,pos+SPACING,myframe->width()-SPACING-SPACING,40); } voxbo-1.8.5~svn1246/client/dbmainwindow.h000066400000000000000000000055231153177201300202420ustar00rootroot00000000000000 // dbmainwindow.h // // Copyright (c) 2009 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include // #include #include #include #include #include "myboxes.h" #include "dbclient.h" class DBmainwindow : public QMainWindow { Q_OBJECT public: DBmainwindow(); void resizeEvent(QResizeEvent *re); string v_motd; private slots: void open(); void connect(); void create(); void search(); void test(); void close(); void newuser(); void newpatient(); void online(); void handleAreaList(); void handleSearch(); void handleSaveResults(); void handleSearchResultClicked(QListWidgetItem *it); private: DBclient *client; int currentpanel; void setup(); void populate(); void updatevisiblewidgets(); void arrangeChildren(); // actions for everyone QAction *a_open,*a_connect,*a_create,*a_search,*a_test,*a_close; // actions for admins QAction *a_newuser,*a_online,*a_newpatient; // central widget QFrame *myframe; QMenuBar *w_menubar; // QStatusBar *w_statusbar; // stuff inside central widget QLabel *w_logo; QLabel *w_banner; QLabel *w_motd; QFrame *w_messages; // the "arealist" and selected items therein QListWidgetItem *al_aboutitem,*al_resultsitem; QListWidget *w_arealist; // menus QMenu *filemenu; QMenu *adminmenu; QMenu *secondmenu; // user info QVBox *w_userinfo; // db info QVBox *w_dbinfo; // patient lists QVBox *w_lists; QTreeWidget *w_plisttree; // search box and search results QHBox *w_searchbox; QComboBox *s_field; QComboBox *s_relation; QLineEdit *s_searchline; vector searchScoreIDs; QVBox *w_resultsbox; QListWidget *w_searchresults; // widget building QHBox *makesearchbox(); QVBox *makeplistbox(); QVBox *makedbinfobox(); QVBox *makeuserinfobox(); QVBox *makeresultsbox(); }; voxbo-1.8.5~svn1246/client/dbqbool.cpp000066400000000000000000000050371153177201300175350ustar00rootroot00000000000000 #include "dbqbool.moc.h" using namespace std; DBQBool::DBQBool(QWidget *parent) : DBQScoreBox(parent) { otherindex=-1; layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(1); // layout->setAlignment(Qt::AlignLeft); this->setLayout(layout); // cb=new QCheckBox(); // cb->setTristate(1); // cb->setCheckState(Qt::PartiallyChecked); // layout->addWidget(cb); cb=new QComboBox(); cb->addItem(""); cb->addItem("no"); cb->addItem("yes"); layout->insertStretch(-1,0); button_new=new QPushButton("new",this); layout->addWidget(button_new); button_revert=new QPushButton("revert",this); layout->addWidget(button_revert); button_delete=new QPushButton("delete",this); layout->addWidget(button_delete); originalvalue=""; QObject::connect(button_revert,SIGNAL(clicked()),this,SLOT(revertclicked())); QObject::connect(button_new,SIGNAL(clicked()),this,SLOT(newclicked())); QObject::connect(button_delete,SIGNAL(clicked()),this,SLOT(deleteclicked())); QObject::connect(cb,SIGNAL(stateChanged(int)),this,SLOT(changed(int))); } void DBQBool::changed(int s) { f_dirty=1; updateAppearance(); } void DBQBool::setEditable(bool e) { f_editable=e; updateAppearance(); } void DBQBool::updateAppearance() { if (getValue()==originalvalue) f_dirty=0; else f_dirty=1; DBQScoreBox::updateAppearance(); if (f_editable && !f_deleted) { button_new->show(); button_revert->show(); button_delete->show(); cb->setCheckable(1); } else { button_new->hide(); button_revert->hide(); button_delete->hide(); cb->setCheckable(0); } } void DBQBool::setLabel(const string &lab) { cb->setText(lab.c_str()); } void DBQBool::setValue(const DBscorevalue &val) { if (val.v_string=="yes") { cb->setCheckState(Qt::Checked); originalvalue="yes"; } else if (val.v_string=="no") { cb->setCheckState(Qt::Unchecked); originalvalue="no"; } else { cb->setCheckState(Qt::PartiallyChecked); originalvalue=""; } f_dirty=0; updateAppearance(); } void DBQBool::newclicked() { } void DBQBool::revertclicked() { f_deleted=0; f_dirty=0; setValue(originalvalue); } void DBQBool::deleteclicked() { if (f_deleted) f_deleted=0; else f_deleted=1; updateAppearance(); } string DBQBool::getValue() { return (cb->currentText().toStdString()); // if (cb->currentText()=="yes") // return "yes"; // if (cb->checkState()==Qt::Unchecked) // return "no"; // if (cb->checkState()==Qt::Checked) // return "yes"; // return ""; } voxbo-1.8.5~svn1246/client/dbqbool.h000066400000000000000000000033511153177201300171770ustar00rootroot00000000000000XOXOXO DONT COMPILE ME // dbqbool.h // // Copyright (c) 2008 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include #include "mydefs.h" #include "dbqscorebox.h" using namespace std; class DBQBool : public DBQScoreBox { Q_OBJECT public: DBQBool(QWidget *parent=NULL); string originalvalue; string getValue(); void updateAppearance(); void allowOther(); public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void setEditable(bool c); // handle signals void newclicked(); void revertclicked(); void deleteclicked(); void changed(int s); private: QComboBox *cb; QPushButton *button_new,*button_delete,*button_revert; int otherindex; signals: }; voxbo-1.8.5~svn1246/client/dbqbrain.cpp000066400000000000000000000046121153177201300176730ustar00rootroot00000000000000 #include "dbqbrain.moc.h" #include #include #include using namespace std; DBQBrain::DBQBrain(QWidget *parent) : DBQScoreBox(parent) { layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(0); // layout->setAlignment(Qt::AlignLeft); this->setLayout(layout); iview=new VBView; iview->setMinimal(1); layout->addWidget(iview); layout->setStretchFactor(iview,20); iview->show(); // unsetlabel=new QLabel; // unsetlabel->setPixmap(QPixmap(":/icons/icon_noimage.png")); // layout->addWidget(unsetlabel); button_load=new QPushButton("load"); layout->addWidget(button_load); layout->insertStretch(-1,0); button_delete=new QPushButton("set",this); layout->addWidget(button_delete); button_revert=new QPushButton("revert",this); layout->addWidget(button_revert); // buttons aligned to top layout->setAlignment(button_delete,Qt::AlignTop); layout->setAlignment(button_revert,Qt::AlignTop); QObject::connect(button_load,SIGNAL(clicked()),this,SLOT(loadclicked())); QObject::connect(button_revert,SIGNAL(clicked()),this,SLOT(revertclicked())); QObject::connect(button_delete,SIGNAL(clicked()),this,SLOT(deleteclicked())); } void DBQBrain::setValue(const DBscorevalue &val) // const Cube &newcube) { cb=val.v_cube; f_originallyset=1; f_set=1; updateAppearance(); } void DBQBrain::setEditable(bool e) { f_editable=e; updateAppearance(); } void DBQBrain::updateAppearance() { DBQScoreBox::updateAppearance(); if (f_editable && f_set) { button_load->show(); } else { button_load->hide(); } if (f_set) { iview->show(); //unsetlabel->hide(); } else { iview->hide(); //unsetlabel->show(); } } void DBQBrain::loadclicked() { if (iview->LoadImage()) return; f_dirty=1; f_set=1; updateAppearance(); return; QString fn=QFileDialog::getOpenFileName(); if (fn.size()==0) return; if (cb.ReadFile(fn.toStdString())) { QMessageBox::warning(0,"Error",QString("Couldn't open file ")+fn); return; } f_dirty=1; f_set=1; updateAppearance(); } void DBQBrain::revertclicked() { f_dirty=0; f_set=f_originallyset; cb=originalvalue; updateAppearance(); } void DBQBrain::deleteclicked() { if (f_set) f_set=0; else f_set=1; updateAppearance(); } void DBQBrain::getValue(DBscorevalue &val) { val.v_cube=cb; val.scorename=scorename; return; } voxbo-1.8.5~svn1246/client/dbqbrain.h000066400000000000000000000032711153177201300173400ustar00rootroot00000000000000 // dbqimage.h // // Copyright (c) 2009 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include #include "mydefs.h" #include "dbqscorebox.h" #include "vbio.h" #include "vbview.h" using namespace std; class DBQBrain : public DBQScoreBox { Q_OBJECT public: DBQBrain(QWidget *parent=NULL); public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void setEditable(bool e); void updateAppearance(); // handle signals void deleteclicked(); void revertclicked(); void loadclicked(); private: VBView *iview; Cube cb,originalvalue; QPushButton *button_load; QLabel *unsetlabel; signals: }; voxbo-1.8.5~svn1246/client/dbqcombo.cpp000066400000000000000000000100651153177201300176760ustar00rootroot00000000000000 #include "dbqcombo.moc.h" using namespace std; DBQCombo::DBQCombo(QWidget *parent) : DBQScoreBox(parent) { otherindex=-1; currentvalue=originalvalue=""; f_set=0; f_originallyset=0; layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(1); // layout->setAlignment(Qt::AlignLeft); this->setLayout(layout); cb=new QComboBox(); cb->setEditable(0); // cb->setEditText(""); // cb->setSizeAdjustPolicy(QComboBox::AdjustToContents); // cb->addItem(""); //originalindex=0; layout->addWidget(cb); layout->setStretchFactor(cb,2); ee=new QLineEdit(); ee->setText(""); layout->addWidget(ee); layout->setStretchFactor(ee,2); ee->hide(); valueline=new QLineEdit(); valueline->setText(""); valueline->setFrame(0); valueline->setReadOnly(1); layout->addWidget(valueline); layout->setStretchFactor(valueline,2); valueline->hide(); layout->insertStretch(-1,0); button_delete=new QPushButton("set",this); layout->addWidget(button_delete); button_revert=new QPushButton("revert",this); layout->addWidget(button_revert); //originalindex=0; originalvalue=""; QObject::connect(button_revert,SIGNAL(clicked()),this,SLOT(revertclicked())); QObject::connect(button_delete,SIGNAL(clicked()),this,SLOT(deleteclicked())); QObject::connect(ee,SIGNAL(textEdited(const QString &)),this,SLOT(textedited())); // QObject::connect(cb,SIGNAL(currentIndexChanged(int)),this,SLOT(indexchanged())); QObject::connect(cb,SIGNAL(activated(int)),this,SLOT(indexchanged())); } void DBQCombo::clearValues() { while (cb->count()) cb->removeItem(0); f_dirty=0; otherindex=-1; updateAppearance(); } void DBQCombo::addValue(const string &value) { cb->addItem(value.c_str()); if ((int)value.size()>cb->minimumContentsLength()) cb->setMinimumContentsLength(value.size()); if (cb->count()==1) { originalvalue=currentvalue=value; valueline->setText(value.c_str()); cb->setCurrentIndex(0); } // updateAppearance(); } void DBQCombo::allowOther() { cb->addItem("other..."); otherindex=cb->count()-1; } void DBQCombo::setEditable(bool e) { f_editable=e; updateAppearance(); } void DBQCombo::updateAppearance() { if (f_set != f_originallyset) f_dirty=1; else if (!f_set) f_dirty=0; else if (currentvalue==originalvalue) f_dirty=0; else f_dirty=1; valueline->setText(currentvalue.c_str()); DBQScoreBox::updateAppearance(); int ind=-1; if ((ind=cb->findText(QString(currentvalue.c_str())))!=-1) { cb->setCurrentIndex(ind); } else if (otherindex>-1) { ee->setText(currentvalue.c_str()); cb->setCurrentIndex(otherindex); } // shouldn't happen! else { cout << "shouldn't happen!" << endl; cb->addItem(currentvalue.c_str()); cb->setCurrentIndex(cb->count()-1); } if (f_editable && f_set) { cb->show(); if (otherindex==cb->currentIndex()) { ee->show(); ee->setEnabled(1); } else { ee->hide(); ee->setEnabled(0); } } else { cb->hide(); ee->hide(); } } void DBQCombo::setValue(const DBscorevalue &val) { originalvalue=currentvalue=val.v_string; f_set=f_originallyset=1; // if there's no "other" option and this item is not in the list, add it if (otherindex==-1 && cb->findText(currentvalue.c_str())==-1) cb->addItem(currentvalue.c_str()); updateAppearance(); } void DBQCombo::deleteclicked() { f_set=!f_set; updateAppearance(); if (f_set) cb->setFocus(Qt::OtherFocusReason); } void DBQCombo::revertclicked() { f_set=f_originallyset; if (f_originallyset) currentvalue=originalvalue; updateAppearance(); if (f_set) cb->setFocus(Qt::OtherFocusReason); } void DBQCombo::indexchanged() { f_set=1; if (cb->currentIndex()==otherindex) currentvalue=ee->text().toStdString(); else currentvalue=cb->currentText().toStdString(); updateAppearance(); } void DBQCombo::textedited() { currentvalue=ee->text().toStdString(); updateAppearance(); } void DBQCombo::getValue(DBscorevalue &val) { val.v_string=valueline->text().toStdString(); val.scorename=scorename; } voxbo-1.8.5~svn1246/client/dbqcombo.h000066400000000000000000000033421153177201300173430ustar00rootroot00000000000000 // dbqcombo.h // // Copyright (c) 2008 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include #include "mydefs.h" #include "dbqscorebox.h" using namespace std; class DBQCombo : public DBQScoreBox { Q_OBJECT public: DBQCombo(QWidget *parent=NULL); string originalvalue,currentvalue; void updateAppearance(); void allowOther(); public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void clearValues(); void addValue(const string &value); void setEditable(bool c); // handle signals void deleteclicked(); void revertclicked(); void textedited(); void indexchanged(); private: QComboBox *cb; QLineEdit *ee; int otherindex; signals: }; voxbo-1.8.5~svn1246/client/dbqimage.cpp000066400000000000000000000055421153177201300176650ustar00rootroot00000000000000 #include "dbqimage.moc.h" #include #include #include #include using namespace std; DBQImage::DBQImage(QWidget *parent) : DBQScoreBox(parent) { layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(0); // layout->setAlignment(Qt::AlignLeft); this->setLayout(layout); iscene=new QGraphicsScene; iview=new QGraphicsView(iscene); iview->scale(0.5,0.5); iview->setAlignment(Qt::AlignLeft | Qt::AlignTop); QPixmap tmpp("aaa.png"); ipix=iscene->addPixmap(tmpp); tmpp.save("foo.jpg"); ipix->setVisible(1); layout->addWidget(iview); layout->setStretchFactor(iview,20); iview->show(); // unsetlabel=new QLabel; // unsetlabel->setPixmap(QPixmap(":/icons/icon_noimage.png")); // layout->addWidget(unsetlabel); button_load=new QPushButton("load"); layout->addWidget(button_load); layout->insertStretch(-1,0); button_delete=new QPushButton("set",this); layout->addWidget(button_delete); button_revert=new QPushButton("revert",this); layout->addWidget(button_revert); // buttons aligned to top layout->setAlignment(button_delete,Qt::AlignTop); layout->setAlignment(button_revert,Qt::AlignTop); QObject::connect(button_load,SIGNAL(clicked()),this,SLOT(loadclicked())); QObject::connect(button_revert,SIGNAL(clicked()),this,SLOT(revertclicked())); QObject::connect(button_delete,SIGNAL(clicked()),this,SLOT(deleteclicked())); } void DBQImage::setValue(const DBscorevalue &val) // dblock &block) { pm.loadFromData(val.v_pixmap.data,val.v_pixmap.size); originalvalue=pm; ipix->setPixmap(pm); f_originallyset=1; f_set=1; updateAppearance(); } void DBQImage::setEditable(bool e) { f_editable=e; updateAppearance(); } void DBQImage::updateAppearance() { DBQScoreBox::updateAppearance(); if (f_editable && f_set) { button_load->show(); } else { button_load->hide(); } if (f_set) { iview->show(); //unsetlabel->hide(); } else { iview->hide(); //unsetlabel->show(); } } void DBQImage::loadclicked() { QString fn=QFileDialog::getOpenFileName(); QPixmap tmpp; if (fn.size()==0) return; if (!tmpp.load(fn)) { // FIXME put up some kind of error dialog QMessageBox::warning(0,"Error",QString("Couldn't open file ")+fn); return; } f_dirty=1; f_set=1; ipix->setPixmap(tmpp); updateAppearance(); } void DBQImage::revertclicked() { f_dirty=0; f_set=f_originallyset; ipix->setPixmap(originalvalue); updateAppearance(); } void DBQImage::deleteclicked() { if (f_set) f_set=0; else f_set=1; updateAppearance(); } void DBQImage::getValue(DBscorevalue &val) { QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pm.save(&buffer, "PNG"); // writes pixmap into bytes in PNG format val.v_pixmap.init((uint8 *)(bytes.data()),bytes.size()); val.scorename=scorename; } voxbo-1.8.5~svn1246/client/dbqimage.h000066400000000000000000000033761153177201300173350ustar00rootroot00000000000000 // dbqimage.h // // Copyright (c) 2009 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include #include "mydefs.h" #include "dbqscorebox.h" using namespace std; class DBQImage : public DBQScoreBox { Q_OBJECT public: DBQImage(QWidget *parent=NULL); QPixmap originalvalue; // last value set explicitly public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void setEditable(bool e); void updateAppearance(); // handle signals void deleteclicked(); void revertclicked(); void loadclicked(); private: QGraphicsScene *iscene; QGraphicsView *iview; QGraphicsPixmapItem *ipix; QPixmap pm; QPushButton *button_load; QLabel *unsetlabel; signals: }; voxbo-1.8.5~svn1246/client/dbqlineedit.cpp000066400000000000000000000046421153177201300204000ustar00rootroot00000000000000 #include "dbqlineedit.moc.h" #include using namespace std; DBQLineEdit::DBQLineEdit(QWidget *parent) : DBQScoreBox(parent) { originalvalue=""; layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(0); // layout->setAlignment(Qt::AlignLeft); this->setLayout(layout); ee=new QLineEdit(); layout->addWidget(ee); layout->setStretchFactor(ee,20); ee->setFrame(0); ee->setReadOnly(0); ee->setText(originalvalue.c_str()); // ee->selectAll(); layout->insertStretch(-1,0); button_delete=new QPushButton("delete",this); layout->addWidget(button_delete); button_revert=new QPushButton("revert",this); layout->addWidget(button_revert); QObject::connect(button_revert,SIGNAL(clicked()),this,SLOT(revertclicked())); QObject::connect(button_delete,SIGNAL(clicked()),this,SLOT(deleteclicked())); QObject::connect(ee,SIGNAL(textEdited(const QString &)),this,SLOT(textedited(const QString &))); } void DBQLineEdit::setValue(const DBscorevalue &val) { originalvalue=val.v_string; ee->setText(originalvalue.c_str()); ee->selectAll(); f_originallyset=1; f_set=1; updateAppearance(); } void DBQLineEdit::setEditable(bool e) { f_editable=e; updateAppearance(); } void DBQLineEdit::setIntValidator(int32 min,int32 max) { QValidator *vv=new QIntValidator(min,max,this); ee->setValidator(vv); } void DBQLineEdit::setDoubleValidator(double min,double max,int decimals) { QDoubleValidator *vv=new QDoubleValidator(min,max,decimals,this); vv->setNotation(QDoubleValidator::StandardNotation); ee->setValidator(vv); } void DBQLineEdit::updateAppearance() { if (f_set != f_originallyset || (f_set && (ee->text().toStdString()==originalvalue))) f_dirty=1; else f_dirty=0; DBQScoreBox::updateAppearance(); if (f_editable) ee->setReadOnly(0); else ee->setReadOnly(1); if (f_set) ee->show(); else ee->hide(); } void DBQLineEdit::revertclicked() { f_set=f_originallyset; if (f_originallyset) ee->setText(originalvalue.c_str()); updateAppearance(); if (f_set) ee->setFocus(Qt::OtherFocusReason); } void DBQLineEdit::deleteclicked() { f_set=!f_set; updateAppearance(); if (f_set) ee->setFocus(Qt::OtherFocusReason); } void DBQLineEdit::textedited(const QString &) { updateAppearance(); } void DBQLineEdit::getValue(DBscorevalue &val) { val.v_string=ee->text().toStdString(); val.scorename=scorename; return; } voxbo-1.8.5~svn1246/client/dbqlineedit.h000066400000000000000000000033141153177201300200400ustar00rootroot00000000000000 // dbqlineedit.h // // Copyright (c) 2008-2010 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include "mydefs.h" #include "dbqscorebox.h" using namespace std; class DBQLineEdit : public DBQScoreBox { Q_OBJECT public: DBQLineEdit(QWidget *parent=NULL); string originalvalue; // last value set explicitly public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void setEditable(bool e); void setIntValidator(int32 min,int32 max); void setDoubleValidator(double min,double max,int decimals); void updateAppearance(); // handle signals void deleteclicked(); void revertclicked(); void textedited(const QString &qs); private: QLineEdit *ee; signals: }; voxbo-1.8.5~svn1246/client/dbqscorebox.cpp000066400000000000000000000032721153177201300204250ustar00rootroot00000000000000 #include "dbqscorebox.moc.h" #include using namespace std; DBQScoreBox::DBQScoreBox(QWidget *parent) : QFrame(parent) { f_editable=0; f_dirty=0; f_set=0; f_originallyset=0; layout=NULL; childlayout=NULL; label=NULL; button_delete=NULL; button_revert=NULL; // valueline=NULL; // scorenameid and scorevalueid should be set explicitly, but... scorename=""; scorevalueid=0; setAutoFillBackground(1); style_clean=""; style_dirty=""; style_deleted="*{margin:0;padding:0;text-decoration:line-through;}"; style_deleted="QLineEdit {text-decoration:line-through;}"; style_labelclean="QLabel {color:darkblue;font-weight:bold;text-align:right;margin:2;}"; style_labeldirty="QLabel {color:darkred;font-weight:bold;text-align:right;margin:2;}"; style_labeldeleted="QLabel {color:darkred;font-weight:bold;text-align:right;margin:2;text-decoration:line-through;}"; } void DBQScoreBox::updateAppearance() { if (f_editable) { button_delete->show(); button_revert->show(); } else { button_delete->hide(); button_revert->hide(); } if (f_set==1) button_delete->setText("delete"); else button_delete->setText("set"); // if (f_set==1 && f_originallyset==0) // f_dirty=1; // if (f_set==0 && f_originallyset==0) { // f_dirty=0; // } if (f_set==0 && f_originallyset==1) { setStyleSheet(style_deleted.c_str()); if (label) label->setStyleSheet(style_labeldeleted.c_str()); } else if (f_dirty) { setStyleSheet(style_dirty.c_str()); if (label) label->setStyleSheet(style_labeldirty.c_str()); } else { setStyleSheet(style_clean.c_str()); if (label) label->setStyleSheet(style_labelclean.c_str()); } } voxbo-1.8.5~svn1246/client/dbqscorebox.h000066400000000000000000000055361153177201300200770ustar00rootroot00000000000000 // dbqscorebox.h // // Copyright (c) 2008-2010 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #ifndef SCOREBOX_H #define SCOREBOX_H using namespace std; #include #include #include #include #include #include #include #include #include #include "mydefs.h" class DBQScoreBox : public QFrame { Q_OBJECT public: DBQScoreBox(QWidget *parent); bool f_dirty; // has the underlying data been modified? bool f_editable; // is the data editable, independently of f_deleted bool f_set; // is it set to a meaningful value right now? bool f_originallyset; // was it originally SetValue()'ed string scorename; // pointer to the name in the global structure int32 scorevalueid; // pointer to the associated value in the patient's record DBscorevalue newvalue; // when the above scorevalueid is <0, the value is here // virtual string getValue()=0; // get string representation of underlying data virtual void setEditable(bool)=0; // make the thing editable (or not) virtual void revertclicked()=0; // revert this item virtual void setValue(const DBscorevalue &val)=0; // get the data from scorevalue virtual void getValue(DBscorevalue &val)=0; // pull the data up into scorevalue QHBoxLayout *layout; // horiz layout for this widget's info and controls QFormLayout *childlayout; // grid for children for widgets that have them QLabel *label; // pointer to label created externally for this widget string style_dirty,style_clean,style_deleted; string style_labeldirty,style_labelclean,style_labeldeleted; void updateAppearance(); // children can call this to update styles based on the flags public slots: protected: QPushButton *button_delete,*button_revert; QLineEdit *valueline; private: }; #endif // SCOREBOX_H voxbo-1.8.5~svn1246/client/dbqstub.cpp000066400000000000000000000031421153177201300175520ustar00rootroot00000000000000 #include "dbqstub.moc.h" using namespace std; DBQStub::DBQStub(QWidget *parent) : DBQScoreBox(parent) { f_set=1; setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Preferred); layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(1); layout->setAlignment(Qt::AlignLeft|Qt::AlignTop); this->setLayout(layout); button_new=new QPushButton("new",this); layout->addWidget(button_new); button_new->hide(); QFrame *frame=new QFrame(); frame->setFrameStyle(QFrame::StyledPanel); // frame->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Preferred); layout->addWidget(frame,1000); childlayout=new QFormLayout; childlayout->setMargin(0); childlayout->setSpacing(0); childlayout->setAlignment(Qt::AlignTop); // childlayout->setColumnStretch(0,0); // childlayout->setColumnStretch(1,1000); frame->setLayout(childlayout); QObject::connect(button_new,SIGNAL(clicked()),this,SLOT(handle_newclicked())); } void DBQStub::setValue(const DBscorevalue &val) { if ((string)"yes"==val.v_string) f_set=1; else f_set=0; } void DBQStub::getValue(DBscorevalue &val) { val.scorename=scorename; } void DBQStub::handle_newclicked() { emit newclicked(this); } void DBQStub::revertclicked() { // this is a null instantiation of the pure virtual method in // DBQScoreBox. we don't need to do anything visible to revert // stubs. } void DBQStub::setEditable(bool e) { if (e) { button_new->hide(); } else { // button_new->show(); } } void DBQStub::addChild(DBQScoreBox *) { // childlayout->addWidget(sb); // children.push_back(sb); } voxbo-1.8.5~svn1246/client/dbqstub.h000066400000000000000000000031011153177201300172120ustar00rootroot00000000000000 // dbqstub.h // // Copyright (c) 2008 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include "mydefs.h" #include "dbqscorebox.h" using namespace std; class DBQStub : public DBQScoreBox { Q_OBJECT public: DBQStub(QWidget *parent=0); bool f_set; public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void setEditable(bool e); void revertclicked(); void handle_newclicked(); private: QPushButton *button_new; vector children; void addChild(DBQScoreBox *sb); signals: void newclicked(DBQScoreBox *); }; voxbo-1.8.5~svn1246/client/dbqtextedit.cpp000066400000000000000000000141011153177201300204240ustar00rootroot00000000000000 #include "dbqtextedit.moc.h" using namespace std; DBQTextEdit::DBQTextEdit(QWidget *parent) : DBQScoreBox(parent) { originalvalue=""; layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(0); this->setLayout(layout); ee=new QTextBrowser(); layout->addWidget(ee); layout->setStretchFactor(ee,20); ee->setReadOnly(0); ee->setUndoRedoEnabled(1); ee->setText(originalvalue.c_str()); buttonarea=new QWidget(); QVBoxLayout *blayout=new QVBoxLayout(); blayout->setSpacing(1); blayout->setContentsMargins(0,0,0,0); blayout->setAlignment(Qt::AlignTop); layout->addWidget(buttonarea); buttonarea->setLayout(blayout); button_bold=new QToolButton(); button_bold->setIcon(QIcon(":/icons/icon_bold.png")); button_bold->setCheckable(1); button_ital=new QToolButton(); button_ital->setIcon(QIcon(":/icons/icon_ital.png")); button_ital->setCheckable(1); button_line=new QToolButton(); button_line->setIcon(QIcon(":/icons/icon_line.png")); button_line->setCheckable(1); button_black=new QToolButton(); button_black->setIcon(QIcon(":/icons/icon_black.png")); button_black->setCheckable(1); button_red=new QToolButton(); button_red->setIcon(QIcon(":/icons/icon_red.png")); button_red->setCheckable(1); button_blue=new QToolButton(); button_blue->setIcon(QIcon(":/icons/icon_blue.png")); button_blue->setCheckable(1); button_green=new QToolButton(); button_green->setIcon(QIcon(":/icons/icon_green.png")); button_green->setCheckable(1); blayout->addWidget(button_bold); blayout->addWidget(button_ital); blayout->addWidget(button_line); blayout->addWidget(button_black); blayout->addWidget(button_red); blayout->addWidget(button_blue); blayout->addWidget(button_green); // valueline=new QLineEdit(); // valueline->setFrame(0); // valueline->setReadOnly(1); // valueline->setText(""); // layout->addWidget(valueline); // layout->setStretchFactor(valueline,2); // valueline->hide(); layout->insertStretch(-1,0); button_delete=new QPushButton("set",this); layout->addWidget(button_delete); button_revert=new QPushButton("revert",this); layout->addWidget(button_revert); // buttons aligned to top layout->setAlignment(button_delete,Qt::AlignTop); layout->setAlignment(button_revert,Qt::AlignTop); QObject::connect(ee,SIGNAL(currentCharFormatChanged(const QTextCharFormat &)),this,SLOT(update_format(const QTextCharFormat &))); QObject::connect(button_revert,SIGNAL(clicked()),this,SLOT(revertclicked())); QObject::connect(button_delete,SIGNAL(clicked()),this,SLOT(deleteclicked())); QObject::connect(ee,SIGNAL(textChanged()),this,SLOT(textedited())); QObject::connect(button_bold,SIGNAL(clicked(bool)),this,SLOT(toggle_bold(bool))); QObject::connect(button_ital,SIGNAL(clicked(bool)),this,SLOT(toggle_ital(bool))); QObject::connect(button_line,SIGNAL(clicked(bool)),this,SLOT(toggle_line(bool))); QObject::connect(button_black,SIGNAL(clicked(bool)),this,SLOT(toggle_black(bool))); QObject::connect(button_red,SIGNAL(clicked(bool)),this,SLOT(toggle_red(bool))); QObject::connect(button_blue,SIGNAL(clicked(bool)),this,SLOT(toggle_blue(bool))); QObject::connect(button_green,SIGNAL(clicked(bool)),this,SLOT(toggle_green(bool))); } void DBQTextEdit::update_format(const QTextCharFormat &f) { if (f.fontWeight()==QFont::Bold) button_bold->setChecked(1); else button_bold->setChecked(0); if (f.fontItalic()) button_ital->setChecked(1); else button_ital->setChecked(0); if (f.fontUnderline()) button_line->setChecked(1); else button_line->setChecked(0); QColor cc=f.foreground().color(); if (cc==Qt::black) button_black->setChecked(1); else button_black->setChecked(0); if (cc==Qt::red) button_red->setChecked(1); else button_red->setChecked(0); if (cc==Qt::darkGreen) button_green->setChecked(1); else button_green->setChecked(0); if (cc==Qt::blue) button_blue->setChecked(1); else button_blue->setChecked(0); } void DBQTextEdit::toggle_bold(bool t) { if (t) ee->setFontWeight(QFont::Bold); else ee->setFontWeight(QFont::Normal); ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::toggle_ital(bool t) { ee->setFontItalic(t); ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::toggle_line(bool t) { ee->setFontUnderline(t); ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::toggle_red(bool) { ee->setTextColor(Qt::red); ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::toggle_blue(bool) { ee->setTextColor(Qt::blue); ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::toggle_green(bool) { ee->setTextColor(Qt::darkGreen); ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::toggle_black(bool) { ee->setTextColor(Qt::black); ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::setValue(const DBscorevalue &val) { originalvalue=val.v_string; ee->setHtml(originalvalue.c_str()); f_originallyset=1; f_set=1; updateAppearance(); } void DBQTextEdit::setEditable(bool e) { f_editable=e; updateAppearance(); } void DBQTextEdit::updateAppearance() { if (f_set!=f_originallyset) f_dirty=1; else if (f_set && (string)ee->toHtml().toStdString()!=originalvalue) f_dirty=1; else f_dirty=0; DBQScoreBox::updateAppearance(); if (f_editable && f_set) { ee->setReadOnly(0); buttonarea->show(); } else { ee->setReadOnly(1); buttonarea->hide(); } if (f_set) { //valueline->hide(); // buttonarea->show(); ee->show(); } else { //valueline->show(); // buttonarea->hide(); ee->hide(); } } void DBQTextEdit::revertclicked() { f_set=f_originallyset; if (f_originallyset) ee->setHtml(originalvalue.c_str()); updateAppearance(); if (f_set) ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::deleteclicked() { f_set=!f_set; updateAppearance(); if (f_set) ee->setFocus(Qt::OtherFocusReason); } void DBQTextEdit::textedited() { f_dirty=1; updateAppearance(); } void DBQTextEdit::getValue(DBscorevalue &val) { val.v_string=(string)ee->toHtml().toStdString(); val.scorename=scorename; } voxbo-1.8.5~svn1246/client/dbqtextedit.h000066400000000000000000000037311153177201300201000ustar00rootroot00000000000000 // dbqtextedit.h // // Copyright (c) 2008-2009 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include "mydefs.h" #include "dbqscorebox.h" using namespace std; class DBQTextEdit : public DBQScoreBox { Q_OBJECT public: DBQTextEdit(QWidget *parent=NULL); string originalvalue; // last value set explicitly public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void setEditable(bool e); void updateAppearance(); // handle signals void deleteclicked(); void revertclicked(); void textedited(); void toggle_bold(bool t); void toggle_ital(bool t); void toggle_line(bool t); void toggle_black(bool t); void toggle_red(bool t); void toggle_green(bool t); void toggle_blue(bool t); void update_format(const QTextCharFormat &f); private: QTextBrowser *ee; QWidget *buttonarea; QToolButton *button_bold,*button_ital,*button_line; QToolButton *button_black,*button_red,*button_green,*button_blue; signals: }; voxbo-1.8.5~svn1246/client/dbqtimedate.cpp000066400000000000000000000110001153177201300203610ustar00rootroot00000000000000 #include "dbqtimedate.moc.h" using namespace std; DBQTimeDate::DBQTimeDate(QWidget *parent) : DBQScoreBox(parent) { // DBdate original auto-sets to current time/date in its constructor layout=new QHBoxLayout(); layout->setSpacing(4); layout->setMargin(1); layout->setAlignment(Qt::AlignLeft); this->setLayout(layout); f_date=1,f_time=0; dt=new QDateTimeEdit(); dt->setCalendarPopup(1); dt->setMinimumDate(QDate(1900,1,1)); dt->setMaximumDate(QDate(2100,1,1)); dt->setDisplayFormat("d-MMM-yyyy h:mmap"); dt->setTime(QTime(12,0,0)); dt->setDate(QDate(1900,1,1)); o_year=dt->date().year(); o_month=dt->date().month(); o_day=dt->date().day(); o_hour=dt->time().hour(); o_minute=dt->time().minute(); o_second=dt->time().second(); layout->addWidget(dt); valueline=new QLineEdit(); valueline->setFrame(0); valueline->setReadOnly(1); valueline->setText(""); layout->addWidget(valueline); layout->setStretchFactor(valueline,2); valueline->hide(); layout->insertStretch(-1,0); button_delete=new QPushButton("set",this); layout->addWidget(button_delete); button_revert=new QPushButton("revert",this); layout->addWidget(button_revert); QObject::connect(button_delete,SIGNAL(clicked()),this,SLOT(deleteclicked())); QObject::connect(button_revert,SIGNAL(clicked()),this,SLOT(revertclicked())); QObject::connect(dt,SIGNAL(dateTimeChanged(QDateTime)),this,SLOT(changed())); } void DBQTimeDate::setValue(const DBscorevalue &val) { DBdate date=val.v_date; f_originallyset=1; f_set=1; dt->setDate(QDate(date.getYear(),date.getMonth(),date.getDay())); dt->setTime(QTime(date.getHour(),date.getMinute(),date.getSecond())); o_year=date.getYear(); o_month=date.getMonth(); o_day=date.getDay(); o_hour=date.getHour(); o_minute=date.getMinute(); o_second=date.getSecond(); setvalueline(); f_dirty=0; updateAppearance(); } void DBQTimeDate::setTime(uint16 hours,uint16 minutes,uint16 seconds) { dt->setTime(QTime(hours,minutes,seconds)); setvalueline(); f_dirty=0; updateAppearance(); } void DBQTimeDate::setDate(uint16 year,uint16 month,uint16 day) { dt->setDate(QDate(year,month,day)); setvalueline(); f_dirty=0; updateAppearance(); } void DBQTimeDate::setFormat(bool time,bool date) { if (time) f_time=1; else f_time=0; if (date || !time) f_date=1; else f_date=0; if (time & date) dt->setDisplayFormat("d-MMM-yyyy h:mmap"); else if (time & !date) dt->setDisplayFormat("h:mmap"); else dt->setDisplayFormat("d-MMM-yyyy"); setvalueline(); } void DBQTimeDate::setEditable(bool e) { f_editable=e; updateAppearance(); } void DBQTimeDate::updateAppearance() { if (f_set!=f_originallyset) f_dirty=1; else if (!f_set) f_dirty=0; else if (f_date && (dt->date().year()!=o_year || dt->date().month()!=o_month || dt->date().day()!=o_day)) f_dirty=1; else if (f_time && (dt->time().hour()!=o_hour || dt->time().minute()!=o_minute || dt->time().second()!=o_second)) f_dirty=1; else f_dirty=0; DBQScoreBox::updateAppearance(); setvalueline(); if (f_editable && f_set) dt->show(); else dt->hide(); } void DBQTimeDate::changed() { setvalueline(); updateAppearance(); } void DBQTimeDate::setvalueline() { if (!f_set) return; // if (!f_set) { // valueline->setText(""); // return; // } string val; if (f_date) val+=dt->date().toString("d-MMM-yyyy ").toStdString(); if (f_time) val+=dt->time().toString("h:mmap").toStdString(); valueline->setText(val.c_str()); } void DBQTimeDate::revertclicked() { // reset date and/or time if we originally had one if (f_date && f_originallyset) dt->setDate(QDate(o_year,o_month,o_day)); if (f_time && f_originallyset) dt->setTime(QTime(o_hour,o_minute,o_second)); // restore original set status f_set=f_originallyset; updateAppearance(); } void DBQTimeDate::deleteclicked() { f_set=!f_set; updateAppearance(); } void DBQTimeDate::getValue(DBscorevalue &val) { val.v_date.setDate(dt->date().month(),dt->date().day(),dt->date().year()); val.v_date.setTime(dt->time().hour(),dt->time().minute(),dt->time().second()); val.scorename=scorename; // boost::format fmter("%d %d %d %d %d %d"); // fmter % // (f_date ? dt->date().year() : 0) % // (f_date ? dt->date().month() : 0) % // (f_date ? dt->date().day() : 0) % // (f_time ? dt->time().hour() : 0) % // (f_time ? dt->time().minute() : 0) % // (f_time ? dt->time().second() : 0); // return fmter.str(); } voxbo-1.8.5~svn1246/client/dbqtimedate.h000066400000000000000000000036601153177201300200430ustar00rootroot00000000000000 // dbqtimedate.h // // Copyright (c) 2008 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include // #include #include #include #include #include "mydefs.h" #include "vbutil.h" #include "tokenlist.h" #include "boost/format.hpp" #include "dbqscorebox.h" using namespace std; class DBQTimeDate : public DBQScoreBox { Q_OBJECT public: DBQTimeDate(QWidget *parent=NULL); int16 o_year,o_month,o_day,o_hour,o_minute,o_second; void updateAppearance(); public slots: void getValue(DBscorevalue &val); void setValue(const DBscorevalue &val); void setTime(uint16 hours,uint16 minutes,uint16 seconds); void setDate(uint16 month,uint16 day,uint16 year); void setFormat(bool time,bool date); void setEditable(bool e); void changed(); // handle signals void deleteclicked(); void revertclicked(); // void textedited(const QString &qs); private: bool f_date,f_time; QDateTimeEdit *dt; void setvalueline(); signals: }; voxbo-1.8.5~svn1246/client/dbtool.cpp000066400000000000000000000212441153177201300173740ustar00rootroot00000000000000 // dbtool.cpp // text client for creating/examining a local database // Copyright (c) 2009-2010 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "dbclient.h" #include #include #include "dbfiles.h" class DBtool { public: DBtool(int argc,char **argv); private: localClient client; void create(tokenlist &args); void dump(tokenlist &args); void dump_types(); void dump_scorenames(); void dump_allscores(); void dump_views(); void dump_patients(); void help(tokenlist &args); void nextid(tokenlist &args); void open(tokenlist &args); void close(tokenlist &args); string ask(string prompt); int err; // just so i don't have to keep declaring it }; int main(int argc,char **argv) { DBtool dbt(argc,argv); } DBtool::DBtool(int argc,char **argv) { char *ret; string cmd; tokenlist args; // special usage dbtool maketest makes test db if (argc==2 && (string)"maketest"==argv[1]) { args.Add("create"); args.Add("test"); args.Add("test"); this->create(args); exit(0); } if (argc==2) { args.Add("open"); args.Add(argv[1]); this->open(args); } while (1) { ret=readline("dbtool> "); if (ret==NULL) { if (client) client.exit(); cout << endl; break; } add_history(ret); args.ParseLine(ret); if (args[0]=="create") this->create(args); else if (args[0]=="dump") this->dump(args); else if (args[0]=="help") this->help(args); else if (args[0]=="nextid") this->nextid(args); else if (args[0]=="open") this->open(args); else if (args[0]=="close") this->close(args); else if (args[0].size()) { cout << "unrecognized command " << args[0] << endl; } } } void DBtool::create(tokenlist &args) { if (args.size()<2) { cout << "[E] dbtool: create takes at least one argument\n"; return; } DBdata dbd; int err; if ((err=dbd.initDB(args[1],"test"))) { cout << "*** error " << err << " creating DB " << args[1] << endl; return; } else cout << "DB " << args[1] << " created successfully\n"; if (args.size()==3 && args[2]=="test") { FILE *fp; err=0; fp=fopen((args[1]+"/scorenames.txt").c_str(),"w"); if (fp) { if (fwrite(test_sn,1,sizeof(test_sn)-1,fp) != sizeof(test_sn)-1) err++; fclose(fp); } else err++; fp=fopen((args[1]+"/views.txt").c_str(),"w"); if (fp) { if (fwrite(test_vi,1,sizeof(test_vi)-1,fp) != sizeof(test_vi)-1) err++; fclose(fp); } else err++; fp=fopen((args[1]+"/types.txt").c_str(),"w"); if (fp) { if (fwrite(test_ty,1,sizeof(test_ty)-1,fp) != sizeof(test_ty)-1) err++; fclose(fp); } else err++; } } void DBtool::dump(tokenlist &args) { string mode,ret; if (args.size()==1) { ret=ask("dump [t]ypes, score[n]ames, [s]cores, [v]iews, [p]atients, or [a]ll? "); cout << endl; ret=vb_tolower(ret); if (ret=="t") mode="types"; else if (ret=="n") mode="scorenames"; else if (ret=="s") mode="scores"; else if (ret=="v") mode="views"; else if (ret=="p") mode="patients"; else if (ret=="a") mode="all"; } else mode=vb_tolower(args[1]); if (mode=="patients" || mode=="p" || mode=="all") dump_patients(); if (mode=="scorenames" || mode=="sn" || mode=="s" || mode=="all") dump_scorenames(); if (mode=="views" || mode=="v" || mode=="all") dump_views(); if (mode=="allscores" || mode=="scores" || mode=="all") dump_allscores(); if (mode=="types" || mode=="t" || mode=="all") dump_types(); } void DBtool::dump_patients() { // FIXME the only way to get all patients is to search for * patientSearchTags s_tags; s_tags.scoreName=""; s_tags.relationship="wildcard"; s_tags.searchStr="*"; s_tags.case_sensitive=0; vector pmList; err=client.reqSearchPatient(s_tags,pmList); cout << "found " << pmList.size() << " patients in db\n"; vbforeach(patientMatch pm,pmList) { DBpatient p; err=client.reqOnePatient(pm.patientID,p); if (err) { cout << format("[E] dbtool: error %d requesting patient %d\n")%err%pm.patientID; continue; } cout << format("Patient %d:\n")%p.patientID; cout << format(" sessions: %d\n")%p.sessions.size(); pair sv; vbforeach(sv,p.scores) { cout << format(" %05d %05d %s=%s sid=%05d idx=%d dt=%s setby %s")% sv.second.id%sv.second.parentid%sv.second.scorename%sv.second.v_string% sv.second.sessionid%sv.second.index%sv.second.datatype%sv.second.setby; if (sv.second.deleted) cout << " (DELETED)"; cout << endl; } } } void DBtool::dump_allscores() { cout << "\nALL SCORES:\n"; client.dbs.dumpscorevalues(); } void DBtool::dump_views() { cout << "views coming soon\n"; } void DBtool::dump_types() { cout << "types coming soon\n"; } void DBtool::dump_scorenames() { cout << format("[I] dbtool: found %d scorenames:\n")%client.dbs.scorenames.size(); deque snq; snq.push_front(""); uint32 count=0; string item; while (snq.size()) { count++; item=snq.front(); snq.pop_front(); if (item!="") cout << " " << item << endl; vector tmp=getchildren(client.dbs.scorenamechildren,item); vbforeach(string ss,tmp) snq.push_front(ss); } if (count-1 != client.dbs.scorenames.size()) { cout << format("[E] dbtool: internal error -- %d types in scorenamechildren map, %d in scorenames map\n") %(count-1)%client.dbs.scorenames.size(); } } void DBtool::help(tokenlist &) { cout << "create " << endl; cout << "dump" << endl; cout << "help" << endl; cout << "open " << endl; } void DBtool::nextid(tokenlist &) { DbTxn* txn = NULL; client.dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int32 startID = getSysID(client.dbs.sysDB, txn,1); if (startID <= 0) { cout << "argh!" << endl; txn->abort(); return; } txn->commit(0); client.dbs.sysDB.getDb().sync(0); // write data on disk now cout << startID << endl; } void DBtool::close(tokenlist &) { if (client) client.exit(); else cout << "dbtool: not connected to any database right now\n"; } void DBtool::open(tokenlist &args) { string dbdir,username,password; char *ret; // get and check dir if (args.size()>1) dbdir=args[1]; else { ret=readline("db directory: "); if (ret==NULL) return; dbdir=ret; } if (!vb_direxists(args[1])) { cout << "no such directory\n"; return; } // get and check username if (args.size()>2) username=args[2]; else { ret=readline("username: "); if (ret==NULL) return; username=ret; } // get and check password if (args.size()>3) password=args[3]; else { ret=readline("password: "); if (ret==NULL) return; password=ret; } client.setUserName(username); client.setPasswd(password); client.setEnvHome(dbdir); if (client.login()) { cout << "error opening db: " << client.getErrMsg() << endl; return; } cout << "DB opened" << endl; cout << format(" directory: %s\n")%client.dbs.dirname; cout << format(" typefname: %s\n")%client.dbs.typeFilename; cout << format(" scorenamefname: %s\n")%client.dbs.scoreNameFilename; cout << format(" viewfname: %s\n")%client.dbs.viewFilename; cout << format(" total types: %d\n")%client.dbs.typemap.size(); cout << format("total scorenames: %d\n")%client.dbs.scorenames.size(); cout << format(" total views: %d\n")%client.dbs.viewspecs.size(); } string DBtool::ask(string prompt) { termios tsave,tnew; tcgetattr(0,&tsave); tcgetattr(0,&tnew); tnew.c_lflag&=~(ICANON|ECHO); tcsetattr(0,TCSADRAIN,&tnew); string str; cout << prompt << flush; str=cin.get(); tcsetattr(0,TCSADRAIN,&tsave); return str; } voxbo-1.8.5~svn1246/client/dbview.cpp000066400000000000000000000734221153177201300173760ustar00rootroot00000000000000 // dbview.cpp // // Copyright (c) 2008-2010 by The VoxBo Development Team // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License, // version 3, as published by the Free Software Foundation. // // 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; see the file named COPYING. If not, write // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // Boston, MA 02111-1307 USA // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mydefs.h" #include "tokenlist.h" #include "vbutil.h" #include "dbqscorebox.h" #include "dbqcombo.h" #include "dbqlineedit.h" #include "dbqtextedit.h" #include "dbqtimedate.h" #include "dbqimage.h" #include "dbqstub.h" #include "dbqbrain.h" #include "dbdialogs.h" #include "dbview.moc.h" #include "boost/format.hpp" using namespace std; using boost::format; DBview::DBview(DBclient *c,int32 patientid) { // FIXME hourglass while requesting patient? int err=c->reqOnePatient(patientid,patient); if (err) return; // app's responsibility to test this dbview client=c; init(); } // the below constructor is mostly for testing DBview::DBview(DBclient *c,DBpatient &p) { patient=p; client=c; init(); } void DBview::init() { nextid=-2; // fake id for values created in the interface // styles //style_main+="*{background-color:white;}"; style_main+="QPushButton {margin:0;padding:1;border:1px solid black;background-color:green;}"; style_main+="QPushButton:pressed {background-color:red;}"; style_main+="QFrame {margin:1;padding:0;margin-left:0;xbackground-color:white;}"; style_scorelabel+="QLabel {color:darkblue;font-weight:bold;text-align:right;margin:2;}"; style_addscore+="DBnewbutton {color:darkred;border:0px;border-radius:22px;margin:0;padding:0;text-align:left;}"; style_sessionbanner="padding:2px;margin:2px;border:1px solid black;" "color:darkgreen;background-color:lightgray;"; // main tab widget resize(600,1200); tabwidget=new QTabWidget; tabwidget->setTabsClosable(1); QObject::connect(tabwidget,SIGNAL(tabCloseRequested(int)),this,SLOT(handleTabClose(int))); setCentralWidget(tabwidget); // toolbar toolbar=new QToolBar; addToolBar(toolbar); QComboBox *cb=new QComboBox; cb->addItem("default view"); cb->addItem("view all"); cb->addItem("view changed"); // FIXME only display if some fields will be editable cb->addItem("hide all"); // FIXME patently bizarre entry for testing only! toolbar->addWidget(cb); QObject::connect(cb,SIGNAL(currentIndexChanged(int)),this,SLOT(handleViewSelect(int))); // buttons QPushButton *button; button=new QPushButton("Submit"); toolbar->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(handleSubmit())); button=new QPushButton("Revert All"); toolbar->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(handleRevertAll())); button=new QPushButton("New Session"); toolbar->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(handleNewSession())); button=new QPushButton("New Test"); toolbar->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(handleNewTest())); button=new QPushButton("Edit"); toolbar->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(handleEdit())); button=new QPushButton("Dump (DEBUG)"); toolbar->addWidget(button); QObject::connect(button,SIGNAL(clicked()),this,SLOT(handleDump())); // status bar statusbar=new QStatusBar; setStatusBar(statusbar); statusbar->setSizeGripEnabled(0); statusbar->showMessage("Welcome!"); show(); } void DBview::handleSubmit() { // FIXME should we ask for confirmation? maybe not if we allow reverting // FIXME! int32 thisid,oldid; // set ids; map newids; int32 f_newpatient=0; set newsessions; set newscorevalues; set dirtyscorevalues; set updatescorevalues; // make a list of all the new ids we need: patientid, sessionids, // and scorevalueids, in that order. if (patient.patientID<0) f_newpatient=patient.patientID; pair spair; vbforeach (spair,patient.sessions) { if (spair.second.id<0) newsessions.insert(spair.second.id); } for (size_t i=0; iscorevalueid; if (scoreboxlist[i]->f_dirty) { DBscorevalue sv; scoreboxlist[i]->getValue(sv); sv.id=thisid; patient.scores[thisid]=sv; if (thisid<0) { newscorevalues.insert(thisid); updatescorevalues.insert(thisid); } else { dirtyscorevalues.insert(thisid); updatescorevalues.insert(thisid); } } } // request all the new ids we need int newidcnt=newsessions.size()+newscorevalues.size()+(f_newpatient ? 1 : 0); int32 firstid=client->reqID(newidcnt); if (firstid<1) { // FIXME put up an error message QMessageBox::information(this,"id problem","id problem"); return; } // remap patient id if (patient.patientID<0) { newids[patient.patientID]=firstid; patient.patientID=firstid; firstid++; } // renumber the sessions in the dbpatient.sessions map vbforeach(int32 ns,newsessions) { DBsession ss=patient.sessions[ns]; patient.sessions.erase(ns); oldid=ss.id; ss.id=firstid++; newids[oldid]=ss.id; patient.sessions[ss.id]=ss; } // renumber the scorevalues in the dbpatient.scores map vbforeach(int32 ns,newscorevalues) { DBscorevalue sv=patient.scores[ns]; patient.scores.erase(ns); oldid=sv.id; sv.id=firstid++; sv.patient=patient.patientID; newids[oldid]=sv.id; patient.scores[sv.id]=sv; cout << format("NEW VALUE: old %d new %d string value %s\n") % oldid % sv.id % sv.v_string; } // remap the ids is updatescorevalues set newusv; vbforeach(int32 id,updatescorevalues) newusv.insert(newids[id]); updatescorevalues=newusv; // spew out some info about fields to be updated vbforeach(int32 ns,updatescorevalues) { DBscorevalue sv=patient.scores[ns]; cout << format("UPDATE VALUE %d: string value %s (for %d)\n") % sv.id % sv.v_string % sv.patient; } // for (set::iterator si=ids.begin(); si!=ids.end(); si++) { // newvalues.insert(firstid); // patient.scores[*si].id=firstid++; // } int ret; // if it's a new patient, we have a function to push it all at once if (f_newpatient) { patient.print(); ret=client->putNewPatient(patient); if (ret) QMessageBox::information(this,"error committing new patient","error committing new patient"); else QMessageBox::information(this,"new patient committed","new patient committed"); } // otherwise push the new sessions and updated scores else { vector stmp; vbforeach (int32 s,newsessions) stmp.push_back(patient.sessions[s]); if (stmp.size()) ret=client->putNewSession(stmp); ret=client->putScoreValues(updatescorevalues,patient.scores); cout << "putscorevalues ret " << ret << " " << client->errMsg << endl; } // FIXME handle bad return codes! // FIXME also handle good return codes, committed fields are no longer dirty } void DBview::handleRevertAll() { // FIXME DBnewsession ppp(this); ppp.exec(); DBpicksession qqq(this,&patient); qqq.exec(); DBpicktest rrr(this,client); rrr.exec(); DBlocallogin lll(this); lll.exec(); // FIXME if there are no changes, just return // FIXME ask for verification if there are actual changes // make a list of all the negative ids for (size_t i=0; if_dirty || (s->f_set != s->f_originallyset)) { s->revertclicked(); } } } void DBview::handleNewSession() { DBnewsession d(this); d.exec(); cout << "FIXME not yet" << endl; // FIXME pop up confirmation } void DBview::handleNewTest() { // FIXME does this work well enough? DBpicktest d(this,client); d.exec(); DBviewspec vs; vs.name="Your newly added test (FIXME)"; vs.entries.push_back((string)"test "+d.selectedtest()); client->dbs.viewspecs["dynamic-generated"]=vs; layout_view("dynamic-generated"); } void DBview::handleDump() { // FIXME debug method for dumping stuff to cout format scoreformat("score %d, child of %d : %s (%s) : %s\n"); pair score; vbforeach (score,patient.scores) { cout << scoreformat % score.second.id % score.second.parentid % score.second.scorename % score.second.datatype % score.second.printable(); } } void DBview::handleEdit() { // FIXME switch to edit mode // FIXME first get write lock, remember to give it up when we commit or close for (size_t i=0; isetEditable(1); } void DBview::handleTabClose(int index) { // FIXME do we want to make sure nothing important is in that tab??? tabwidget->removeTab(index); } void DBview::handleViewSelect(int index) { if (index==0) { for (size_t i=0; if_set) { scoreboxlist[i]->show(); scoreboxlist[i]->label->show(); } else { scoreboxlist[i]->hide(); scoreboxlist[i]->label->hide(); } } } else if (index==1) { for (size_t i=0; ishow(); scoreboxlist[i]->label->show(); } } else if (index==2) { for (size_t i=0; if_dirty) { scoreboxlist[i]->show(); scoreboxlist[i]->label->show(); } else if (scoreboxlist[i]->f_set != scoreboxlist[i]->f_originallyset) { scoreboxlist[i]->show(); scoreboxlist[i]->label->show(); } else { scoreboxlist[i]->hide(); scoreboxlist[i]->label->hide(); } } } else if (index==3) { for (size_t i=0; ihide(); scoreboxlist[i]->label->hide(); } } } void DBview::layout_view(string viewname) { DBviewspec vs=client->dbs.viewspecs[viewname]; QFrame *myframe; QVBoxLayout *layout=NULL; for (size_t i=0; iaddTab(myframe,vs.name.c_str()); layout=new QVBoxLayout; layout->setSpacing(0); layout->setMargin(0); layout->setAlignment(Qt::AlignTop); myframe->setLayout(layout); } if (toks.size()==0) continue; if (toks[0][0]=='#') continue; if (toks[0][0]=='$') continue; if (toks[0][0]=='!') continue; if (toks[0][0]==';') continue; if (toks[0]=="newtab") { myframe=new QFrame; tabwidget->addTab(myframe,(toks.size()==1 ? "" : toks.Tail(1).c_str())); layout=new QVBoxLayout; layout->setSpacing(0); layout->setMargin(0); layout->setAlignment(Qt::AlignTop); myframe->setLayout(layout); } else if (toks[0]=="banner") layout_banner(layout,toks); else if (toks[0]=="test") layout_test(layout,toks); else if (toks[0]=="sessionlist") layout_sessionlist(layout); else if (toks[0]=="testlist") layout_testlist(layout); else if (toks[0]=="session") layout_session(layout,strtol(toks[1])); else { cout << format("unrecognized view directive: %s\n") % toks[0]; // FIXME } } } void DBview::layout_banner(QVBoxLayout *layout,tokenlist &toks) { QFrame *fm=new QFrame; fm->setFrameStyle(QFrame::Panel||QFrame::Raised); layout->addWidget(fm); QHBoxLayout *hb=new QHBoxLayout; QLabel *lab; fm->setLayout(hb); // FIXME set spacing etc. for (size_t i=1; isetSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred); hb->addWidget(lab); } else if (toks[i]=="username") { lab=new QLabel("your username here"); lab->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred); hb->addWidget(lab); } else if (toks[i]=="string" && isetSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred); hb->addWidget(lab); } else if (toks[i]=="space") { hb->addSpacing(25); hb->addStretch(100); } else if (toks[i]=="score" && i children=getchildren(patient.names,toks[i+1]); // FIXME just use last one if (children.size()) { // FIXME the following line creates an entry in patent->scores if it doesn't exist! DBscorevalue sv=patient.scores[children[children.size()-1]]; lab=new QLabel(sv.v_string.c_str()); lab->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred); hb->addWidget(lab); } i++; } else { } } // FIXME logo // FIXME patient rec # // FIXME update button // FIXME date/time // FIXME show/hide missing scores } void DBview::layout_test(QVBoxLayout *layout,tokenlist &toks) { QScrollArea *myscrollarea=new QScrollArea; QFrame *myframe=new QFrame; QFormLayout *mylayout=new QFormLayout; layout->addWidget(myscrollarea); myframe->setLayout(mylayout); myscrollarea->setWidget(myframe); myscrollarea->setWidgetResizable(1); mylayout->setSpacing(0); mylayout->setMargin(0); mylayout->setAlignment(Qt::AlignTop); //mylayout->setColumnStretch(0,0); //mylayout->setColumnStretch(1,10); // myframe->setAutoFillBackground(1); // mylayout->addWidget(new QLabel("name"),0,0); // mylayout->addWidget(new QLabel("value"),0,1); // parse flags bool f_mostrecent=0; bool f_sessioninfo=0; for (size_t i=2; i instances=getchildren(patient.names,scorename); // if the mostrecent flag is set, only show matching scores with the // most recent session date // FIXME if the field is repeating, we need to group all values with the same sid together if (f_mostrecent) { vector mostrecentids; int32 mostrecentid=instances[0]; mostrecentids.push_back(mostrecentid); int32 tmpsid=patient.scores[mostrecentid].sessionid; DBdate mostrecentdate=patient.sessions[tmpsid].date; for (size_t i=1; imostrecentdate) { mostrecentids.clear(); mostrecentids.push_back(instances[i]); mostrecentdate=thisdate; } if (thisdate==mostrecentdate) { mostrecentids.push_back(instances[i]); } } } for (size_t i=0; i"+strnum(tmpsid)+" ("+ ss->date.getDateStr()+"), examined by "+ss->examiner; lab->setText(stext.c_str()); lab->setSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Preferred); lab->setStyleSheet(style_sessionbanner.c_str()); // mylayout->addWidget(lab,mylayout->rowCount(),0,1,2,Qt::AlignLeft); mylayout->addRow(lab); QObject::connect(lab,SIGNAL(linkActivated(QString)),this,SLOT(handleSessionLink(QString))); } layout_node(mylayout,scorename,instances[i],NULL); } // even if there are no instances, we still lay out some nodes if (instances.size()==0) { layout_node(mylayout,scorename,-1,NULL); } } void DBview::layout_testlist(QVBoxLayout *layout) { // all root tests, regardless of session, maybe alphabetically? chronologically? vector testids=getchildren(patient.children,0); if (testids.size()==0) { // FIXME put something informative up in a qlabel maybe return; } QTableWidget *tw=new QTableWidget; tw->setRowCount(testids.size()); tw->setColumnCount(3); QStringList headers; headers << "testname" << "date" << "info"; tw->setHorizontalHeaderLabels(headers); tw->verticalHeader()->hide(); tw->setAlternatingRowColors(1); tw->setShowGrid(0); tw->setFocusPolicy(Qt::NoFocus); tw->setSelectionMode(QAbstractItemView::SingleSelection); tw->setSelectionBehavior(QAbstractItemView::SelectRows); tw->setSortingEnabled(1); QObject::connect(tw,SIGNAL(itemDoubleClicked(QTableWidgetItem *)),this,SLOT(handleitemclick(QTableWidgetItem *))); // if (client->dbs.scorenames.count(nameid)==0) int thisrow=0; vbforeach(int32 i,testids) { string tname=patient.scores[i].scorename; // cout << *i << " " << client->dbs.scorenames[i].name << endl; QTableWidgetItem *it1=new QTableWidgetItem(tname.c_str()); it1->setData(role_link,QVariant(QString("test ")+QString(strnum(i).c_str()))); QTableWidgetItem *it2=new QTableWidgetItem("foobar"); QTableWidgetItem *it3=new QTableWidgetItem("more info here!"); it1->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); it2->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); it3->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); tw->setItem(thisrow,0,it1); tw->setItem(thisrow,1,it2); tw->setItem(thisrow,2,it3); thisrow++; } tw->resizeColumnsToContents(); layout->addWidget(tw,0,Qt::AlignTop); } void DBview::layout_session(QVBoxLayout *layout,int32 sessionid) { // FIXME details at top // use patient.sessiontests to find all tests for this session vector testids=getchildren(patient.sessiontests,sessionid); if (testids.size()==0) { // FIXME put something informative up in a qlabel maybe return; } QScrollArea *myscrollarea=new QScrollArea; QFrame *myframe=new QFrame; QFormLayout *mylayout=new QFormLayout; layout->addWidget(myscrollarea); myframe->setLayout(mylayout); myscrollarea->setWidget(myframe); myscrollarea->setWidgetResizable(1); mylayout->setSpacing(0); mylayout->setMargin(0); mylayout->setAlignment(Qt::AlignTop); // mylayout->setColumnStretch(0,0); // mylayout->setColumnStretch(1,10); for (size_t i=0; idata(role_link).toString().toStdString(); DBviewspec vs; tokenlist toks; toks.ParseLine(link); // cout << "link: " << link << endl; if (toks[0]=="session") { vs.name=(string)"Session "+toks[1]; vs.entries.push_back((string)"session "+toks[1]); client->dbs.viewspecs["dynamic-generated"]=vs; layout_view("dynamic-generated"); } else if (toks[0]=="test") { vs.name=(string)"Test "+toks[1]; vs.entries.push_back((string)"test "+toks[1]); client->dbs.viewspecs["dynamic-generated"]=vs; layout_view("dynamic-generated"); } else cout << "FIXME unknown link type" << endl; } void DBview::layout_sessionlist(QVBoxLayout *layout) { // layout->setMargin(10); QTableWidget *tw=new QTableWidget; tw->setRowCount(patient.sessions.size()+1); // +1 for the 0 session (no session) tw->setColumnCount(3); QStringList headers; headers << "sessionid" << "date" << "info"; tw->setHorizontalHeaderLabels(headers); tw->verticalHeader()->hide(); tw->setAlternatingRowColors(1); tw->setSelectionMode(QAbstractItemView::SingleSelection); tw->setSortingEnabled(1); QObject::connect(tw,SIGNAL(itemDoubleClicked(QTableWidgetItem *)),this,SLOT(handleitemclick(QTableWidgetItem *))); map::iterator si; int thisrow=0; // fixed "nosession" session // string slink=""+strnum(0)+""; QTableWidgetItem *it1=new QTableWidgetItem(strnum(0).c_str()); it1->setData(role_link,QVariant(QString("session ")+QString(strnum(0).c_str()))); QTableWidgetItem *it2=new QTableWidgetItem(QString("no session")); QTableWidgetItem *it3=new QTableWidgetItem("no session"); it1->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); it2->setFlags(Qt::ItemIsEnabled); it3->setFlags(Qt::ItemIsEnabled); tw->setItem(thisrow,0,it1); tw->setItem(thisrow,1,it2); tw->setItem(thisrow,2,it3); thisrow++; for (si=patient.sessions.begin(); si!=patient.sessions.end(); si++) { // slink="first)+"\">"+strnum(si->first)+""; it1=new QTableWidgetItem(strnum(si->first).c_str()); it1->setData(role_link,QVariant(QString("session ")+QString(strnum(si->first).c_str()))); it2=new QTableWidgetItem((si->second.date.getDateStr())); it3=new QTableWidgetItem("more info here!"); it1->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEnabled); it2->setFlags(Qt::ItemIsEnabled); it3->setFlags(Qt::ItemIsEnabled); tw->setItem(thisrow,0,it1); tw->setItem(thisrow,1,it2); tw->setItem(thisrow,2,it3); thisrow++; } tw->resizeColumnsToContents(); layout->addWidget(tw,0,Qt::AlignTop); } void DBview::handleSessionLink(QString name) { // FIXME cout << name.toStdString() << endl; } DBQScoreBox * DBview::layout_node(QFormLayout *layout,const string &scorename,int32 valueid,DBQScoreBox *parent,int row) { if (client->dbs.scorenames.count(scorename)==0) return NULL; // FIXME shouldn't happen DBscorename &sn=client->dbs.scorenames[scorename]; DBQScoreBox *sb=NULL; vector namechildren; vector valuechildren; // if it's a leaf, lay it out, plus if non-existing, lay out new node link if (sn.flags.count("leaf")) { sb=layout_single_score(layout,scorename,valueid,parent,row); // now put up a "new xxx" link when appropriate if (sn.flags.count("repeating") && valueid<0) layout_new_node_link(layout,scorename,parent); return sb; } // if it's a stub, lay out the stub, then each child, then the stub repeater else if (!sn.flags.count("repeating")) { // layout stub sb=layout_stub(layout,sn,valueid,row); // if it's a NEW stub, mark it dirty if (valueid<0) sb->f_dirty=1; // find all children of this scorename namechildren=getchildren(client->dbs.scorenamechildren,scorename); if (valueid>-1) valuechildren=getchildren(patient.children,valueid); else valuechildren.clear(); for (size_t i=0; ichildlayout,namechildren[i],valuechildren[j],sb); foundone=1; } } if (!foundone) layout_node(sb->childlayout,namechildren[i],nextid--,sb); // if it's repeating and we have edit privileges, put up a "new xxx" link // DBscorename *tmpc=&(client->dbs.scorenames[namechildren[i]]); // if (tmpc->f_repeating) { // layout_new_node_link(sb->childlayout,namechildren[i],sb); // } } return sb; } // FIXME non-leaf repeating else { cout << "shouldn't happen yet!" << endl; // sb=layout_stub(layout,si); //layout_subtree(layout,si); return sb; // should never happen } } void DBview::layout_new_node_link(QFormLayout *layout,const string &scorename,DBQScoreBox *parent) { if (parent) { string perm=patient.scores[parent->scorevalueid].permission; if (perm!="rw") return; } // int newrow=layout->rowCount(); DBscorename *sn=&(client->dbs.scorenames[scorename]); string linktext=(string)"add new "+sn->name+"..."; DBnewbutton *mybutton=new DBnewbutton(linktext); mybutton->setStyleSheet(style_addscore.c_str()); mybutton->layout=layout; mybutton->scorename=sn; mybutton->parent=parent; layout->addRow("",mybutton); QObject::connect(mybutton,SIGNAL(clicked(QFormLayout *,DBscorename *,DBQScoreBox *,int)), this,SLOT(handle_new_node_link(QFormLayout *,DBscorename *,DBQScoreBox *,int))); // FIXME probably need a custom widget, so that we can associate the needed info } void DBview::handle_new_node_link(QFormLayout *layout,DBscorename *sn,DBQScoreBox *parent,int row) { // don't need return value? DBQScoreBox *tmp=layout_node(layout,sn->name,nextid--,parent,row); layout_node(layout,sn->name,nextid--,parent,row); // FIXME add it to any lists? // layout->insertRow(row,"hereitis",tmp); } DBQScoreBox * DBview::layout_stub(QFormLayout *layout,DBscorename &sn,int32 valueid,int row) { DBscorevalue *sv; // if the stub doesn't already exist, create it if (valueid<0) { DBscorevalue vv; vv.id=nextid--; valueid=vv.id; vv.scorename=sn.name; vv.datatype="stub"; vv.patient=patient.patientID; if (sn.flags.count("default")) { string dv=sn.flags["default"]; vv.deserialize((uint8 *)dv.c_str(),dv.size()+1); } vv.sessionid=-1; // FIXME why no parents for stubs??? //if (parent) //vv.parentid=parent->scorevalueid; vv.index=0; // if (parent) { // string perm=patient.scores[parent->scorevalueid].permission; // vv.permission=perm; // } patient.scores[vv.id]=vv; } sv=&(patient.scores[valueid]); QLabel *label=new QLabel((scorebasename(sn.name)+":").c_str()); label->setStyleSheet(style_scorelabel.c_str()); DBQStub *stub=new DBQStub(NULL); stub->setEditable(0); stub->scorename=sn.name; stub->scorevalueid=sv->id; layout->insertRow(row,label,stub); int f_writable=0; // if (sv->permission=="rw") f_writable=0; stub->setEditable(f_writable); scoreboxlist.push_back(stub); stub->label=label; return stub; } DBQScoreBox * DBview::layout_single_score(QFormLayout *layout,const string &scorename,int32 valueid,DBQScoreBox *parent,int row) { // first figure out what we're talking about DBscorename &sn=client->dbs.scorenames[scorename]; DBscorevalue *sv; DBQScoreBox *ret=NULL; // if the value doesn't already exist, create it if (valueid<0) { DBscorevalue vv; vv.id=nextid--; valueid=vv.id; vv.scorename=scorename; vv.datatype=sn.datatype; vv.patient=patient.patientID; if (sn.flags.count("default")) { string dv=sn.flags["default"]; vv.deserialize((uint8 *)dv.c_str(),dv.size()+1); } vv.sessionid=-1; if (parent) vv.parentid=parent->scorevalueid; vv.index=0; if (parent) { string perm=patient.scores[parent->scorevalueid].permission; vv.permission=perm; } patient.scores[vv.id]=vv; } if (patient.scores.count(valueid)==0) exit(0); // should never happen absent corruption sv=&(patient.scores[valueid]); // next make sure we have a DBQScoreBox structure to work with if (sn.datatype=="shortstring" || sn.datatype=="string") { DBQLineEdit *le=new DBQLineEdit; ret=le; } else if (sn.datatype=="datetime" || sn.datatype=="timedate" || sn.datatype=="time" || sn.datatype=="date") { DBQTimeDate *td=new DBQTimeDate; if (sn.datatype=="time") { td->setFormat(1,0); } else if (sn.datatype=="date") { td->setFormat(0,1); } else if (sn.datatype=="datetime" || sn.datatype=="timedate") { td->setFormat(1,1); } ret=td; } else if (sn.datatype=="integer") { DBQLineEdit *le=new DBQLineEdit; le->setIntValidator(-999999999,999999999); ret=le; } else if (sn.datatype=="float") { DBQLineEdit *le=new DBQLineEdit; le->setDoubleValidator(-9e+99,9e+99,4); ret=le; } else if (sn.datatype=="text") { DBQTextEdit *le=new DBQTextEdit; ret=le; } else if (sn.datatype=="image") { DBQImage *le=new DBQImage; ret=le; } else if (sn.datatype=="brainimage") { DBQBrain *le=new DBQBrain; ret=le; } else if (sn.datatype=="bool") { DBQCombo *cb=new DBQCombo; cb->addValue("no"); cb->addValue("yes"); ret=cb; } else if (client->dbs.typemap.count(sn.datatype)) { DBtype tp=client->dbs.typemap[sn.datatype]; DBQCombo *cb=new DBQCombo; for (size_t i=0; iaddValue(tp.values[i]); if (sn.flags.count("customizable")) cb->allowOther(); ret=cb; } else { cout << "FIXME shouldn't happen" << endl; DBQLineEdit *le=new DBQLineEdit; ret=le; } if (valueid>=0) ret->setValue(*sv); // now do all the generic stuff ret->scorename=sn.name; ret->scorevalueid=sv->id; int f_writable=0; // if (sv->permission=="rw") f_writable=0; ret->setEditable(f_writable); scoreboxlist.push_back(ret); QLabel *label=new QLabel((scorebasename(sn.name)+":").c_str()); label->setStyleSheet(style_scorelabel.c_str()); ret->label=label; if (layout) layout->insertRow(row,label,ret); return ret; } DBnewbutton::DBnewbutton(string txt) { setText(txt.c_str()); QObject::connect(this,SIGNAL(clicked()),this,SLOT(heardclick())); } void DBnewbutton::heardclick() { int row; QFormLayout::ItemRole rr; layout->getWidgetPosition(this,&row,&rr); emit(clicked(layout,scorename,parent,row)); } voxbo-1.8.5~svn1246/client/dbview.h000066400000000000000000000065261153177201300170440ustar00rootroot00000000000000 // dbview.h // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include "mydefs.h" #include "dbclient.h" #include "tokenlist.h" #include "vbutil.h" #include "dbqscorebox.h" // locally used Qt Roles const int role_link=Qt::UserRole; class DBview : public QMainWindow { Q_OBJECT public: DBview(DBclient *c,DBpatient &p); DBview(DBclient *c,int32 patientid); void init(); QTabWidget *tabwidget; QToolBar *toolbar; QStatusBar *statusbar; DBpatient patient; DBclient *client; // string name; int32 nextid; // fake id for values created in the interface vector scoreboxlist; string style_main; string style_scorelabel; // style for the label next to each score string style_sessionbanner; // style for the session info banner/separator string style_addscore; // style for the little "add xxx..." link // layout methods DBQScoreBox *layout_node(QFormLayout *layout,const string &scorename,int32 valueid,DBQScoreBox *parent,int row=-1); DBQScoreBox *layout_stub(QFormLayout *layout,DBscorename &sn,int32 valueid,int row=-1); DBQScoreBox *layout_single_score(QFormLayout *layout,const string &scorename,int32 valueid,DBQScoreBox *parent,int row=-1); void layout_view(string viewname); void layout_banner(QVBoxLayout *layout,tokenlist &toks); void layout_test(QVBoxLayout *layout,tokenlist &toks); void layout_sessionlist(QVBoxLayout *layout); void layout_testlist(QVBoxLayout *layout); void layout_session(QVBoxLayout *layout,int32 sessionid); void layout_new_node_link(QFormLayout *layout,const string &scorename,DBQScoreBox *parent); operator bool() {return (bool)patient;} public slots: void handleViewSelect(int index); void handleTabClose(int index); void handleSubmit(); void handleRevertAll(); void handleNewSession(); void handleNewTest(); void handleEdit(); void handleDump(); void handleSessionLink(QString name); void handle_new_node_link(QFormLayout *layout,DBscorename *sn,DBQScoreBox *parent,int row); void handleitemclick(QTableWidgetItem *twi); }; class DBnewbutton : public QPushButton { Q_OBJECT public: DBnewbutton(string txt); QFormLayout *layout; DBscorename *scorename; DBQScoreBox *parent; public slots: void heardclick(); signals: void clicked(QFormLayout *,DBscorename *,DBQScoreBox *,int row); }; voxbo-1.8.5~svn1246/client/default_scorenames.txt000066400000000000000000000030711153177201300220070ustar00rootroot00000000000000 # this is a test scorenames.txt file scan stub scan:type scan_type scan:date date scan:tech string scan:nicescan bool #scan:notes shortstring #scan:foobar stub #scan:foobar:xxx scan_type #scan:foobar:yyy scan_type #scan:foobar:zzz stub #scan:foobar:zzz:a shortstring #scan:foobar:zzz:b shortstring #scan:foobar:zzz:c shortstring scan:lesion stub scan:lesion:size integer scan:lesion:side side_type scan:lesion:location lesion_location demographics stub demographics:firstname shortstring demographics:lastname shortstring demographics:DOB date demographics:adefault shortstring default "your a default here" demographics:bdefault shortstring default "some b stuff" demographics:nodefault shortstring demographics:phonenumber shortstring demographics:sampletime time demographics:sampledate date demographics:sampledatetime datetime simpletest stub simpletest:datetime datetime repeating simpletest:combo scan_type simpletest:string string repeating simpletest:text text repeating simpletest:integer integer simpletest:float float simpletest:image image simpletest:brainimage brainimage forms stub forms forms:posttest repeating forms:posttest:notes_from_coordinator text default "please fill this out" forms:posttest:deadline date forms:posttest:experimenter string default "your name here" forms:posttest:date date forms:posttest:payment stub repeating forms:posttest:payment:for string forms:posttest:payment:amount string default "enter amount paid here" forms:posttest:tests test_type customizable repeating forms:posttest:payment_for_that string default "enter amount paid here" voxbo-1.8.5~svn1246/client/default_types.txt000066400000000000000000000005411153177201300210130ustar00rootroot00000000000000 scan_type description type of the scan scan_type MRI scan_type MRA scan_type CT scan_type flatbed scan_type once-over scan_type expensive side_type description side of the injury side_type left side_type right side_type middle lesion_location description location of the lesion lesion_location here lesion_location there lesion_location everywhere voxbo-1.8.5~svn1246/client/default_views.txt000066400000000000000000000011511153177201300210020ustar00rootroot00000000000000 # this is a sample views.txt file # here is an existing patient view patient newtab Patient Summary patient banner todaysdate space username patient sessionlist patient testlist # here is a new patient view newpatient banner todaysdate space username newpatient test demographics # here is my simple four-tab test view test newtab bssd test banner todaysdate space username test test scan test test scan:type test test demographics test newtab sdata test session 10101 test session 10102 test newtab simple test test simpletest test newtab all sessions test sessionlist test newtab all tests test testlist voxbo-1.8.5~svn1246/client/icons/000077500000000000000000000000001153177201300165155ustar00rootroot00000000000000voxbo-1.8.5~svn1246/client/icons/a_connect.png000066400000000000000000000162771153177201300211710ustar00rootroot00000000000000‰PNG  IHDRx<"ÏéÿsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ *^»3ç?IDATxÚÍ\i”]U•þö¹÷õjL*©Je*BHH‚!ƒŒ& ¸„ 4ƒh7´cÛšèRh×ê^ Ävè@+Ú(j·m·ôjéV@E A@•„@’TæT¥†TÕ«7Þ³ûÇï«’E ÞY•wÏ=÷Ü}ö¼¿}hK‚0ôÅê!‰$IB‚˜„„`’H²úCH3Lý!$„$Á iÇ›1nˆH"I‚!"Ìf€ 5Æ=Â$$“to$‰€…Ð3H¨u’zÖ¬M¯YB0Q„€‰Ìòƒ" Š X ÐSL1½T÷!$ÉLb?ÞgÚÏ7c4qH0kº*23ÀŠÞĵ bû/@ 0›'@꛽b"f€Àj¤ž›ØÞ%VƒÕ/1ë1zIdƳÀ`ºÇëz‘pãAl>Ê<¬Ö¬W‚A½Zýhž%5œ'Úo“yœÌl†xl¾‹ô"…û(wÓûRõvÝì(‘þ0ðI"Kf5)[ê@¯,-ˆÙLN¬âÍÊì3Ù &€AR‹$ÁŽ1+d6t!'° Öëb0ňBn½¤VÊ Vu ¶Dq* ¾`2¼¨ßHB3ˆcÒœí¨¤‰¦x\ý×gFýÙú–fiQ321ƒ˜È­ÉÞ `Í zcÌ„¬&a0ÃpImõ®³–0©)å3q±"«¹˜!Ô·K_ÈÈÈ"9…Ê0tWr ÇXÁò‰n¥ÅÑÌn§¡˜Òf³Ãz¬NP|dåÎÒÑ) iWÀfÛܶnÕÔt@+‘'³ûšœ1%š}Ø×0–3ˆ´Œ}“ùC󤥑ú—ÍTV¤!ÜpCö]·œ¡•“âhÿÝš¿˜ý-ÒŸªd–ô»Hkñ˜öóvÊ)V#yìKšÙ µ7dt (f/œá°Û£iÊÒ’Ií®Q%ìT!±ÇeÖŠ°k6ØãzA€ß(°›gië–ÈV()Ô<cµ†P?ÅV€Ý8cý¬}3¤g'Vl ©(N†¨S[m$¤EeTäòîêP ÊRšÂGU–LBTÁ Gd)¤`0Ê ˆ€‚33ÓRS&‡­ATïe&&kñ¼ÒÜKÒÞ²@¨;ŠiN¥Žb —´`©íd»=zÛÍ3ò¦~Qwz#‰B£:.KøÓ_²Âå#ÅîWóÛN‡õÉ0gÖ¯£M8_SÅ´"©?ÍÞfŒ`ý»Ža?_³°`! çlèý^¢`U@q_:<zvÖ+ƒ~7 7…VJk ãÞêW=;Âò±òñ_roîÅNJ݇ ]uaS:l”ôI¬É$ OhöÒ¼åÑÚq˜6H&d×äÖ çí÷ˆ}]°Š„±Å–­5Õi²ÂJ–ðÌZGœÄZˆA`m¹÷ÞÒÁ2$Þ¢«, ‡ ¯”d¡!59dšK™¤a@Øq,±»<‹6¸T7WOàÏ㊸r`dû¾áÍYÔTµYÖ£š¶~ĆÖJFMÜBñÔ$ˆ¬7sW U"ÔºöAɵa•ïÚXŽk"æ¸ÃÇ„ç+Ã/üÙ@EçwŒVlö^h¯b}/¤c’œ>µ¹5/fñ"g@*íJ:7S/ §Y“(æ:µàI ÛÔ¥ÍûK§©·FCø3»ò•þÁò!Ö.³—é5Þ–ÊöYÏJù³ìg'm¦Œ¼x„È$aŒZ°¹*“, œu0ªµ×DCT>J…®`hSØ·6YêQæ‘$•;Mz¡Lxï«]53lÞ†Mïþ£>~r+:ÚÐ1#y$“(—HFp02P)Ý{,‘•¹¢¬0°¯|8bùƘº0ZT^óOÝXs·Z óùLïñæ}ÝÛ¶Ï]÷ôÛ{ûZtjI›5xâK;Öžä +ÕÄàpî}³Öl¸ø½z¤˜Õ©¨-a0–еtpü7©=«ë‹GC)ÈÖ"‚`ïyuwÍ#«ïÄÍ«Çùlºxßv Ÿ'£5¯–´}MçÚ;—öäe~ šß]Ú_”•ÑP@áp4ÒÐÞ·ÿ¢è¥õ™-—Ñr¹$ñÀS7ãKñûÇ/¸ëGê雨ŠJ’\ñˆ!^\{Ù©g8ØÓ~ýW¾ÿR÷éRÚgŠ ?AG¿® 0IÔSr:ê–Ê–•°™TÄ‹ŸlØ”b[R%%"EècërÛok“‚Ž•ägvîïë%ÛîyâèìNìvÒº;æëP" d®Ò0µ0õìãsßu0ÓX0z"uÏçÞµwK»-V©ºQ‰£[þÁ†Íxäᦟ?X."yª—¦ƒÆy®˜Öp®=ðôM6o˜ÿã^Ç I‚drŶö¾ º–/ßÔÐ0àÄPý?Üòù-/Γ’TµL×í^|ô2ëž;çöÿ´$]ñJ§J3;^÷®‡–/Úà`oûù«Ì—³¡ÛÀaw™RD$oÇî{¿’òéÒ´ ‰fyÖO6½·u´;ð¼:ç{T†ÅPWZ‚6W‡ Ñ82Þ6]S7wά£J#áñÝ ^Pðó´õÁYß~Î…ß±üÛ³¥oí]7\Ó{ ÉY,P‚m“pÕ L ÛJë/?^îÙ4¸®§t˜_ÃmoJMiLNñM>ŸÙ·gŠ.f1ÄÖmÁÃ,¿óû¹þ¯~ûÑÿ¢±aø;«ÿéC«¾Õ}¸Ã‰"lÊ#ùº—»;ýÂéó¯,¸ÿ‰+¾yÓ7þú²_Mm=rͲ5?}ìZqMû1ÚŒJ´ÿ;ÙW¾æxÎ7N°_1ªI-1zeõÁrOTSÚs›šÒ(Rñß(žŸBµ<ñ¯ ýµ ¤ê*W}é/D5/HŠääÔô '®˜YwfB$Ǿ±1ÙÖ‘[˜M´Œ­Ö±©…ªR'Åbò?þëºÕw¬P—ýÂßý›+€Ç+w&ÁoýE€»îû˜º}ö/ÂÔ4ÇPÍ$£¥©½7Ó÷û€– Kõó*dg¤8¥ˆz¹<$«§¦ò¤ {V²•)¶Çìb—i¤ç˜½ëÉéN?÷Pûœ~öó¾jgADM‰IKš/ßpAK²=)ÒêΔ6œ·°qvÓEí¹³Â «ý„س—´s»þÛ‡ßùôú¥ÎY¼uÎé{Má­¦Rc*„®&:ØÛ®îæÒ VœeùliŠMâà³jP늂¯Ø"E¯§+ƒã¥5&uI k*©.M̺˜`ç™{æ« .ÙãJËq!ƱÍsÎ=¿õê%Vœ7ý‚[ÿ_ÿ"Þéìöº ÊXÌ#“Â1<ô?÷]©~ºdÙz›å¸ð¢hÈ´M8¦þ8ÒßJ®Âbv†L:ÔÆH¦Eƒ›RÑ(YnZ\fãIŽU‡ÇKÑå(±,55Ia\ÿØÊMÀÛl-uon+&’ÙÊÌ…ÇltåJ‘&6â$¥›E¶)9壟ð’«àÖO¿=d¤+®‹šWÛÈÀ« Œ¶Ï-¤³™âÂy/¹©áh v€>ûþ»Õݵ›.b“ø÷“÷ f¦@‡¡ä{ŽïJ4,,g;+älì ‰ú¨Ò™ïÚž?5¡Ejr˜Q”JÀ¶"n+ëRôìišº wÂôìװ͕ɕÛg‡‚³…ÉhÒ´ ¯Øú¶óº<µfñK[;¸Ôj‚€'6 w“+§Æ½FLãib±øåÝ—HgJ^ºÅÖ<ã uéIƒ q*A ;gÐ}°ƒ=Ð%Çì©Aiù‰bIwül%€ºôè5Ë׈1•M,Ó¯ñ?M甃,|>e (Ö ëWÇ#õ¾ÁÒÑ(šòÀ…±D»IÆÏ\|,™©èÞÖæÃ×âT& hrž8¸·MÛ†YGœ×êûþ5^&Å€‹îȤ‹¶îœëÑ‘NåÁé=ev˜¥mõÌ—E\?ûŽwŒ šö·#ê?ÇÎz˜‚Ø[S'±®ñŒpQ>S<A2‹8¥Lb×aa9÷ܦ†mûý,ƒú“î38)‹äT¼&tš)#›a÷ ±ÿŰdÖ)¸á}¿Q?>úÔ;l¦”=ÄÞIt$™Â@GÈaP±÷Å‚ 4!€Ú?0:ñ’"€ãO¦‡^NY_ÊìÕ,ãd\ëŠ6•ŽH’<Ör,xQ÷—\õÊÜeû¼üìôïNðñ¼¹€HJYÆfÍ? F?Öì°ä:äÁì‚ð+W<¶ì¼MžÙ´¤ko§†$l&âh‡ñ4 \2w»Î—ö¶‡qt¥-Å3HèjOš§jdÆ#ªÃbç­4Òú’½¦‰L–‚QŽN‰»àGFwgEjNjrmYÒwr˜Â´|ÇǶ¾ó[G’¿¼m™ÎrE£ñˆ52Fk¶t¦têßiÏäÙù~)ÏO`ÕuL”L–?xý¯?þ¡ûŒä³«¿÷)‡ðð¸Î!#œE ʦ‹_þðwÔG6^ì– 3s¤„I4pr*7,­N¸¼œh‘*ýÂ'Z ÝÊË mØ#‘“‹O 7ìOí=5_÷ËÂoó»@¢\A2T}eÒéC &"d}µ±ctêÂÞy—îÏ6äÓwnEÿ¡F&fôÑ”Ù\©cV¯„¯Ê6gÍ?té5&µ÷xjíâ®—fxöJ?X—ÙyHuBˆ™ºBû”Þó».Z¶¡©qÀà‰†›n¹åàávpƒ®«¯ËŸÑ¹Ç¥$И^4gÇG®¸wÆäCîÿÃ{^èZàÿ§’÷*Ž=˜íúçÆBO´œ‹@êÙŵ];ÔÈÁ¸ûgøòíÈCj¡Ä—¾P¹îJÌ>íµÙ?[×ÌúÝwÏ<žÓ½*ä·¢Ð6~sÜ驵‹ïZ}}¹’”R¨ÒAð»u+Ç)œGÁ#/ûî?r¬¢í|qu­¹xÜWß÷‡÷Þxç×JÕdMÀâ([¢ò± ßžØìy4Sì ¥ÃRúàþ˜îhjÄû®ÄÚ'ñÈããˆ0Ê•›WãæÕøÌÇqí{pÑ «¢8’êÉöìiÞ»¹mç3‡rÒÚXr 5ÔøXñXa4uühó+/ÎøÃš¥»¶ŸÆ$Ø/xÓI¼£j5Èç³½Ç[övO}aÛü'ž=¿·¿Y¡´ôÀZ¦×@Š‘ÑìÞ)›vý³Ç®ÚøÒÙ:£±% $ÝêD±3ÝK¦7 ®­Š)Öt%IHÕVEBB¼TùIaßQYx]•ÓE™™ 3³f&Û"½˜À+\©™I¶Vé5lÕ4]™*F‘צ?0P‹g¿¨ž±¯0Å&³ =yà‡$S`kC‘FÐé>6"çk+E%°p:‹*³05°|Ž#ĬO™‚:‘ˆ@;_'¨ãhupKaï@”O‹TcXï^A '”òµà6öh#h†NGcgqŽ wK&¡{X„Á¹9Ä¢°È.C• whàs ÏÅqû¡MàJ ¢ð! º`VÓngk Z Gƒ3ƒt„uyDÝÑÈëE«l-¼z"!%Ò AzK² D •“Th)K><““ˆhØ\-zÑí–˚Ǖk1v~§ µŽ†5„ l_ézùÈàá5Ò°Ž'âE6›dQëÓÞwá»S‡¢ÑW«CŒ×}m-tm+쮲)‘ÊŠl@A.¨¯ rSÓÓsAc&l°€p¿¥C­Š˜ØG·Ä ÏÌÖa'øýy>–Y#“™D É€ [<œ×È‹C6:Þ«NÅJkm„â|FOÁ™šˆ¢Âd‘¹6Óùߣ]G¢Ñ×Oj0x(Ê#Êý–lÙüvÑ”h©p5%2® #Ž #D!¥J²™²,$ƒºˆ«‰ —¹úTGCzz:Ñu^¯™íþsÖÕöU°+ Ÿ|C ¯qÏ«|µBªÄ¿Šst_¦ôÇ’Edz@b]˜6:0ïÖ™×9аášìi¿Ý{4Êÿà9å Gï÷ÙtØÐ˜š1¹~QkÝÙAXg‹ 6Iâ…K6È´”1ÍÂ6FsImE*ÁµõÄš_ÁÊ ` ÄÑ×^jص ‘kPã­¦Ž™G,šEfb¥Á7îÿZWU–ò•žÑJ_d2ɉDI@Hm ẞt Þ"7´Œ7 h›/UÖÞ³Lþ±¦VŸ¡žWX<£€o1´¡Øi;ãîy,ˆî숂– Û™håê—˽…ä.GCåRÓ“a£ó—¼Ï æ@[]!˜X·Ä2VG­;;™†ŠA”{çÜj‡=§MÄ|×.è¸Îݶ=Ú &"ˆ¥f$š¦„ý² ·Ü’+uɶ\zàw)Ç•ž›«HI°Þ—ôû*q„i˦Ÿ%žN%„ì5ê´»N,ßK¯Þ¯ÐëRäXáÑÕy‰FJ/Lf;Âæ~YÜX:p¨:tä­@O*}Åj¿Íü¹.AÃ`b ÑwEÓK Òt ›u1.ŠêæŒcFÈu‡^ŽUÄ wl‡d° BÛ_†=ÂÕË­1Ñ %Ö x× %È4u3“bw¥oc±{kqÿ›On—< ¯3ßþ•yd/éc%¶Jüvç’­µ…Š@&‹+¸æä¥\õ‹Yi³™„XƒœKK=T“wÉŠÓ’“f$ÛÎLu<3Úu rüÍ!q&1!Np¬HC^ÇUô Ä$ ë8ýËÜïÙR—E'ømñº Î~†¨¦¯8ž£¦ùÌKO›šhÝR<°£Ô}ä 7ÕŽ{Õ§¦Õ§§»/uâë…9lb õÀr¶¥Šjª*S̃¶~´Žù¬Íñ³d(Ö‚ë-ÅJ™õáÉDŒ~ÕÅœ[àµÐÄŒ2êÃìÒìì9éi»ËGv©ôU9’‚޹úÔÔÖÜٙĆˆXýPÐ’‹(ÒÄ5jÇï)âÚ¢%tj“Êî¤×îZ\ù¾‹6#J¬ˆ =t› ÆWâ±:À”‰¤H5'šçgÎùƒåžÞêàp4ZáJ…£¡h8â¨øÚ›SacczƤܢÖúEBdeMW¾Ö‡[ðE¬yÇvÖë^ƒy*S FÕêh«‰4lжý{‚ᇰDJÁ©Z5¼jÙ`‡“³ç¡8ÇÆ×0j¹é 9Y¤[­6GZŸùþʉ¥ýEYª%D²$K© S‘&'«¨†”*ÉѤȖe1d#Ž’A]"ÈåRSÒ3Ó‰‰Bd¥­ÑØž(q ×ïD ÖEd¶GÀÄ ^íj`ãqBõFÉÂGS¨#bE_VKióu€ïxÖ;ùI18IÀWmÈ`}•XÁÍâïô®4Í aËôÌ, Í—Îs×烙SÅ—;VQ+SD~Ö±ô™§RÇÔõµ­#Á~¢Êa´‰tâ5Æg¤Æ0RLƒj„±ÎŽq×Ì»mMÚK xçN±Å×¢Ààs„Ç&ŽÓaíüœ;»íKü´Ž‡é!"òÀå¶bßE6¥Á:EgàÎ"ó yµhh©Î8ñ€^ˆ¦[”À‡l+'ùçúxXUôF1€>Å]N"OJjO:S¯¨ÅØ9®¯±(ìŽVr%ZgÜ=,ÓBæä5 Ö'ZùÇÏØ>_õ”~ùˆtuKX¤«=ò‰Í.™cxŒ™µÙnÇìBÃ1èT Š5ˆ 'æÞÙb5'µ09[d1©÷ÔŠ gÐØ;§ þ«½(†dô1CD±H$Lk<9 ¼ý b’'Õ»^ä"Æby /!rV‹Ø˜J“ wÕ/›´õN©!¥§…Ôr³_¬ñ¶Ù¡è8†Ä°È1‹óT­Eôø-Üñ6ÿþnäÁ`(.Ç Ñ”(@µØ&£˜0¶Œòø¥RÂÌ75·IEND®B`‚voxbo-1.8.5~svn1246/client/icons/a_create.png000066400000000000000000000164101153177201300207700ustar00rootroot00000000000000‰PNG  IHDRx<"ÏéÿsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ * ¾nÚùˆIDATxÚÍ|y˜\ÕuçïÜ÷êUuUõ&µZ½¨¥ÖBKH  Ù˜EØØŸcˆˆáçKðä3Ø8xÎd™ÆŽã8ùf<ØŒf'Ã|cŒ1^bÙ VƒX„ -HH­¥÷­ºªk{ïžùãÝ­º[Ý(vÞúZU·î»÷ÜsÏú;‡vû>A=ÿ#$‘„'IH“LBIŽÿB‹ÿB’`4ãõ;Äð$‘$Á f=@F<Æþ„IH&ißH !¡fˆ×IñoõÚÔš%Eð˜H/O0(‚¢‚ãj*‰""†§–j7B’ô$f›p¶i¶¯Ç(â`VtÉÌÇô&&Ä "6ÿ2ijþ(þŠõY13@àx¤š›Ø|KŽ?ˆ˜ˆYQK"=† èÅ€ƒâï`5@-v<ˆõ¦ôã5«•ƒ Aˆ_¨Kñp²œhö&ýsÒ³iâ±Þ©E »)û¥³ÓxfÝl)‘ÚxŽ‘!s<)ê@­ -ˆYON¬âÌÊì2™&€AR]I‚£WȬéBöÂ2X­‹ÁTC²ë¥x¥Ìà˜ vÁ†(VÔž˜4/ª7’P bÙ‡g[*)¢Å<ÿ×eFµmõ•bi~ÏÈÄD b"»&MP83€ƒ¨ƒÑr< ƒšƒH:l«NÕ “ŠR.ã°¾.æÊ*.fˆxïÒ½d¤ï"YÊÐtïc.–Kts A€oIeOÖY½¥&11 X‘ …Œ~®žÑ+ÑtrP†u$ ,›EB@¬ô2‹DªË˦Eï»æVEM}®êÝvK¤Á\íx'¬OѲ’CJEP%ÉåBý€r8™¯Ž”‰R8Î É! É¡©j”÷½úHƒ`©ÙLö‚DrY"hg̤›æucˆD»=Ï¡'>0âŸI=i=ë:f!IDD¯Ëê³Qñça®Â\™!Dœ'I^š¼¿qKÐÚå54x)û–X½M輎!bÕÄÐúЬ4úG2±’•®+q9æGªƒù0ÇD¿¹1Ù‘öy"à "‚(TÇ áÄñ©]ùêÐDé͘²§ùM‹®ªo¼,™^Ï$"­9=ë^O‚h·ïi^×B@T£:%¼˜(LñæÅ0ó ²üíêx‰9:5‰g?uä¯òz‹{-Í^:E“ˆ\se¦ÆéN’hË–e–ò'Ôé7ô&—6Ç>›û™PÙHK|C‰!ÉaˆÁÄ‚‰Q·¢nmYVvO<^••3¥W]°ÔiÏË0K&»àuS…½‘œOÿKYÒž7Ù˯–È·ªŽ ÄÌDDÒ ™˜N?G;dyA2{ 'Û/e(ˆ]ç Pd>&§_ '_¨ŒŒJkÆ5‰T—ߨ´mH¶')!-#+vV¤¯±à„Dǃ@ ©-Ñ@¤º3ëû¦÷–Žœ–ÇáeS~óŠÅW×§VÁRã=Çñq ªFÅýGî(–ŽÎ3 GkP° 2ë`¡ ÝžwÞ‰™Ôã*¢U¨xÐ˽èþ"(ùDåo……ù@ßÇ—þ·A²J•Iâ@]ßöEo<´´Rô%Dr˜ËǨ,K¢ë¿zhãtw¡I_ô¨*ÊùÄÔPÝðáÆ¾—[÷=¶<7šQÁ~ò$ # ^ìs}çÝsÝb¯«»ÿûÙ[¾8°ÿ¦°é|üé­Ø°ËÚüB¡nx¤ùÈÑÎW_[÷Ô/· .bòªÑôÐÄc'‡¿+ç½ú-üèÿ¢&&¦öY½íùw÷‘kò¥t¼`Úí{ç_€M9ÂÈ¿$÷óx´Pžä– ðн蘥Šò'“Ü´aüPV*‡ž˜< ñÙ½?_àÕ’^Û¶ò߸hb({Þ*œ¤Ss:~ŽÃê- ðò‡?€ÿó {̵¢@<úØ%wýýG÷~µä‡Õpbþ©Þs}°æ“ãCíÿâß½~tGO=N¥VŸD=Ë‘¹H.ºªê7s¥Š ®Àþy}׆4ÝÞÞöÎæ,Ø“D"ÅÙîÊÊkGÛ/PèO>xõE•r‚YH¡.fLè#¿l}êkâ@< ²Õ†eÅeŒ¬{ßñºÆ2€éÉä}·½ïÍÝí&Ye"M_ßù ¿Ú±ò¡»ß@B‚©¨µkü’ß~åã|èWæ[óÖwÔ¯[t;3$ òP—-µµööܺõņ†|¥Š~T÷Ù?Kå ã ÊŸÎW¬ÛtS*Yîî<~ÝûÞzáóŽ·¿ëÓ?)TҖГ?¡¾Ïèô D¤Ãc”¢Ž[ÊÅ/z? ó:ƒ¬ôn>§‘š ^ zç_½yÎõCžþ‹ž}µK1;KÐîý9€ýÛ:þÏ[œ  ‰$_ú{·~ê5\.$¾yõÃÇšØÆH= Š ýÒ#ë¾ý…›“dÅò‡ÿÇŽWæó[[‚Þ¦¿õDV’IQz$¹Ë¯øA®´ýÿ=ˆÑñÓÒ¢ ­kèüœ *ý·ÿô•OüÖ|îë_þçí¿#jÝ-µÑDeê»+ýÄ©p!ëùºKMð¡3 *PñÚ?tª°Yo62[Ö““È Š÷øÿÚøã/_ ™©~ä¿<ý&32SÎèl±+ïåΟÍã“Õ©ò 9‰SÕhúÄðËÿóOÞóOÞiR9™éM5\'ÙøÍïRñ_Ïèœ&fÑZÅ:¤ö·?Eåy-¥ú,.Xå;Y1íIN&•rÏDʆ‰³sTsÆÖ1!b›ž¤]?:gߓˬyç‰öµcŠÊ*ßæ¸Û,thɘWê\Àø ùdî¹PD‹•á©çö¿ëÈàwrÓ¯‡Ñé:À‰är/ÙæØøt|¸=þ*›*B¥²jsª¬“†* à ¢ñJ߃xrÇ|+/‡ƒ¹ò•¹âáPžq°lUwýtâ&/h—p¢ [¯¿7ð‹¯`Àw%«ð3yŠ/tÄ2]L˜ãikEº9jè)³J…H"Ó]YuÍHçåÞøÉÒ]l"÷4¡ÀJÀ&#n2ëR nZÖ;¼xù$»9lcg+í«G ’2äQk×ø¥W¿²nóÁ—Žá—/PòFF²ÒŸ{¦z†\ @\Ø‹[nZñ½íõoƹ· ¨vw¿î½_¹ùY<ö¡{7׈‹ Z,Ö1b rþ·æ¦°tkþý[ç0¦ò'’»ïY¾ï¡v+þ µù3' L˜tj4 Û\t8f† ï:¼á]sØžÃýÍràBÏE˜Ï`z TpÉ|ùϱõâ=7^÷û³¿=6ØñµïÝôÏ|4^ãl>µð’`jXˆ£5Ÿò«lgyÃïì¼dÂ$ÉÔä4Ëâ`ªøXýLaÅàù2–<ÒgŽgIûø ŸÜÓ” Îz)Y·æŽÛqñæSèZzòæß÷î wÄDô]¶²ìF䄪 ¸Ð¦ò{¸qÇu<{”h’‹z§×ߨßqÉľõêãºþÀÏ:˜$˜kßlód¤ntßOF±o­!aVíØùȹßúµ¹ÀéÆr÷úþü‡gÎ{ÇçmÄö§ÏbÜ\É®Åm7n½ä A?yå~õ/u☄‡††üùç¼~ó5÷]qᎾôé›ÿûßþàÉ«kÌ;&pÄ YC ä-’ƈ©ä±¤âhpü©æmÐ{äѸüKûëšËEµ<«‚±:vNZ„(S¯~ñ4€üXÏezÃb¦â엛̾²£çonû/>Ù›LžM"gë/në¼-]¿%HÌÌõ€(’Þèdóö—]ç=ïx¯ ùõ[ÿkKãX­@pMP°µ « qt¹¢r×΋U8ŒÝ÷,HG«®ŠƒÝ<Ë×pìB}“4$Òó¸uÕ8€á¾&«M*;„L&‰˜ÅC÷^ÙÕy–ÄEª»sÙçÛ:oMezA‰¹!‹ÇÔQš¯Ý3€LjúÚ­Ûü™‘”Dê‚áˆpš‘~í9F®òY&eâ!‹×æ]ô›“kW¢Då«Ê +7 u!€£¯¶øÚ,*“Åªì ˜püͶuçÃó½½ìÛúµíåèóAº‡5Do¦—+÷ ˆAûŽ­Vºº{¿¨•Ï–@3` Šß·Ì© 6!ykÝ_§QYÔRJá_a±0œ{Ùï¾{õÑÕJÍáÀ¥BF?½ç2´¶¼]vÞÿÆHÿÉ{¦r;ªÕ17Û=‡,@ I&ßSQ ß …+àj—`(Ѷ?ŒŽº^æní\·nÌ)ÙŸRYš‘®¶ dv –6äÀºËûìvùÉC‹]<¯CnÍ:_ 1fZ½áXwþÛDÕéé×N|sxàÛ•Òi§|¢¨OŠÍë^SñÒávQ‹®4Ù8]KÌ ¯ø£üÊK)9†ã#RÔ –òÓÑ–Û”‘{ô‰%H‡f¦%¾`&?)¯üôË¿sÇÓJùà¡¿¹\cÅI¡ÖgÆbÇÒÈx¤êÊ7|úgmèYsV¤4‡Õ‘Üøöc_Í?:2¦Qüše4›@”N•îü½»âÏþ»íA{ \·VJ ŸD˸á¢pñ*‰E2ûg 3&ðèÞÊ–žb\6Á öD¢)\|^~ÝÇê—•üiÛàž°­”L}µuM."ÁD$Ô‡ÓË6¯o_º© 0‘º÷¶«ÆN4²ÉÓ“ãµél¹sõpœˆa J7”Vo8ñÞkŸom0<˜ògÉôàrñ‘“ÿ•»ð¹O!›.ô¬ö9àÔ9ŸYÙYßŽíªŽs£²ì ‘ ?!¼¸:‘I@WúÅàký‰J¾0 f‚ ©¨t |tûä³¹è”z¬M^]GÝj[ADjf„'RƒÓ{‹á|‰©tryGˇê3ç–+Ãa4%¹r&ÔžK‡ÃÂ^/ÕMÉ@ÌÉ>u1!ÙZ>ÍPÆ’@Šéý~ö…ha|ÿ„¬LhD‚D¦”HS¢I¤BÈE^:E‰õA[“È4ùYè²§ØL’ª „¯O÷=—ß3.œ³«hˆPlð[˜‰§ òy!'V’Aû²ö'§v=\©Žð™¶T ¯æûþ:½â ^vó t¿¯P„䤠jJ†õˆäJ‘Ü/Kgðn–\ž@ùdÌ•Õ1;Ë' hó$àÁ !òH„Ì>yQaZ– §ý–©p55£lpoÚ #^vŒ•—Œ}œTБX´4“Ý8ž{ftl[æpÚpèx°ðæu+¿â×orvÊê`Vu™Dd“oäFåˆê@—ú™¾j¥ÈòíXEyY0U>+6V½ßdo±v2¶¶ëÉ…„^±

yDùõ×K’$~³TîN¯½ éòúD³«[}N3 ˨1µ|A}X,“n `æ$‘Ÿm\üáÖe·'’]tšLf…|[V¦L?[Ç ÙÒh ¡  pq¢á¸¬<N”ßžb|‹É‘:7»éœú¯©&®m’¼5‘^€ ZšR«ŠÕÑùXZ;nÇÕ©&´)¼lºñ²¥©î©‰í¹¡ûy^»È¯ßâ†ô½›„¯Ô4û,Ú&€:¿'!´žŒKþD ^·Ÿ8Çá¯Ä Jôd7liz÷šloÒËByÛjÁïE9/5ž‹  äp(¿{>½ê/Z²è*íµ Ýõ@H2{ÂoNf7%³›*Å}òÔf~²ã³^zÓÞM"ÁzA R 5n•r…òc*ÇZ‚¼y˼Ô*/#DžÃSÞ$VÖ­ÙÔpñÚìy‰E‚ÚIºâS(—G-]º3 _¤&ËGK§ ŽïeZš®¬Ïœg¶L:ÊȪZ[è/D²Ý¯;',‹æ -×-××`'7± ¹×ö’!“ «é¢Â Í4z©•^v< +£\í“ÅaYîŠ9®–8ªœB9õ¤{V§{–¦º”%$ %=™b¤æŒî"FŸ3!vˆÙ÷²­ÙMÅC§pX²õÙóŒAD‘"ލ/ŠAfcS÷_NõÿCTé¯L½d$†Hv&ÛoAMJØ×HF۩ƺUºæ‰geš’K€( /ATï¥Ö@¼ƒ(bQ€‘•#QþxTÈs5/«ˆòR{+§ùøäoÊn\U·¦%Ù®zW€¤‘ªn<†§Z0•ãÄ(@ÕÓé¥ [ÊÑÔѱm3ozbIWë ™Ôê _˜¶$n6U¿Ý Ú3í7…•?ûR|“¼†wˆ C$;g`Þè…DZ*A!"Ý)ŠAyÙˆå¬P§í3A‚ug©¸•tšØ1#QiT–öV†Š\“Ó%Ê\±LˆDEVü†¤H®Ju×ûõ~£Å–;l³ƒ¸ì&RKUi¾‚DÅ078õÒDqÿÈÔ. ¿¡¥ñ²LÝÚÆúÍu5í ˆ$Ûn³ÛtT¼©²±°rŠêô|" èZäÙ%䮨 "1‰ˆã"bx¦N"®L‰”€34D»áÈ]44ÂÞmƒböFz¬ÆØ:›Îš²ž!G|ö`ŠTºD•+¡,•£¡&Koãⶈ“mÖNoƦd5G dsÃ4LºXQGˆÈ§:O¤‰{!(n§Ï$ hBµL" ÏÔV¯[If&kÚ^Q&(\'Êöc0rëàk{YÍ£å8ÁÅÍÄh.9šÙé,~…ÄLŒ,ʸæÜÄMÑΦˆ´Škk)® Àª£;PvE¹éÞ¤‘9 ®„Aºš–O¬Ï]j:rY“ÉU5A/ULi˃ÍaV˜'k˜ào†OïÖ:¨öt.Ý¥rÍ´Ž-DÆ1j\'et—R`!&¶ªÌPÈÁŒ(–¾0ÓÀì´G36§y¹¨£¹aö!X7Jƒ zÁÔ=°>GÅŽ¥Ôd¿,Š3öš[%>³S a[˜»2¤0ë š£tÊðÙtÐÖ´1ÈÖésM'C›GÓ ¡Kã8H‡Ý´De’sÊ]G€MrësÜšÃGú"*)fø”t¹Š6í¢¹¶žélÇÎMw*¢Üc¶O®i›cc3¦H¡~j3Ÿº‚¼&×glrÒtTN×ô4Ñ6²À>û¹™ÍÊ&ÌN£üÀ‹ <Œ!CIEND®B`‚voxbo-1.8.5~svn1246/client/icons/a_logo.png000066400000000000000000000132531153177201300204670ustar00rootroot00000000000000‰PNG  IHDR 2ÛaÐesBIT|dˆ pHYsOO÷‘8tEXtSoftwarewww.inkscape.org›î<(IDATxœí]iT”Gº~šUÅqÑJ” :jtÜE¯&ÌDÄ%q’`&:ŽãB¢F¯¢‰FÇ%耘 dˆÌQ\GF3˜x® hÔ Bƒ,²ÈÚýÜÝýÙÐ_7ÝÐȽçòœS‡ÃWõ½õV}Omo½U-!It£]“®V ÿ¿ÑMÀnt)º Ø.E7»Ñ¥0ëjÚ‹ÂÂBäææB*•¢  555pvv†‹‹ ///XXXtµšÿ'‘››‹üü|@*ÍGSS3¸¸¸ÀÓÓ&&Fê»Ø Ÿþ9===9a„ÖQU~ãǧL&Ó™6''‡;vìà+>> 3ØÛÛsÉ’%|È‘#GÒÓÓ“çÏŸoWZZJOOOÁËË‹£GæÄ‰¹lÙ2îß¿ŸÙÙÙFÕ‘$322øÑGk9l˜c›uëììÀU«ÞcJJ åry‡òÕ à½{÷„Œ¾ûî» ×C‡%†‡‡kM#•J¹(8Xk…8th©%ÞÅÅ…'OžÔ©Gtt4ÐÖÖ–>4Zùf̘A ÐøXEEEm~lmÁßߟW®\é°~wïÞePŸh&& £#8hhf&®Ç¯ý+^½zµÝùk$ýü ………µ[°>HII ’––¦/“ɸg÷nöìÑCH×`0ÀSsÖ¤Z(˜ p3À_µª¬‰'òþýûZõ™6mpÒ¤IF)_BBÐÌÌŒ?þø£F¼:ß{ï=®[·N4¼õÖ[œ9s&GM33³eZ¾|9›šš Ö­¶¶–k×¾OssAV¯^`h(˜”æçƒMM ‚" L>~ þûßàêÕ RªëñƯ³°°Ð`=D ø×¿þUè jjj ª/V¬XAôööÖˆ«¯¯g°’hpÀ§­×V¸p’ZEÙÚÚòâÅ‹¢úäåå±gÏžÀÇw¨lÕÕÕtqq!®]»V4:?~¬—ÜââbFFFÒËËKxwΜ9 …eee3æù4fÀðØ1°¡á9áÚ r9øÏ‚>>êC³£hCÓQ–——ÓÒÒ’m@}QWWÇ^½zwïÞÝ"îéÓ§œè÷|XøO€¿H¼Ö! ³DB477çW_}%ª—ªñõìÙ“ùùùí.ßêÕ« €®®®Zq{¨Bss3׬Y#¼¯oƒÉÏϧ——»0Ä®ZVVêO¼Ö¡¹Ü·ìÙS5÷¶3hê&J@’\¸p!0((Hoa† ..NžÔ+¿¡¡¯Ž)TìÖO=HŽT’P"‘ð믿ÖÐK.—3((ˆ8uêÔv•-##ƒ¦¦¦ÀÄÄD­é:B@”½Ø677ëL[ZZJ77Ge#ãâÚO¼Ö!#CÑ“`–üá‡ôÒ_+ÏŸ?/|¨œœ½„Õ|kÖ¬Y-ž¿¿l™¢uÈÇ@>uº*'ó£Fb}}½†Ž‘‘‘TLÌ{±  @ï²:tˆhmmÝæjÚ$ɹsç?úè#­i¶mÛ*äuê”ñɧ (€óæÍkSw­$É¿üå/›;jïQÇÎ; €lhh ©˜÷õQö:AeH@Lhªì #""4t”Éd;v,púôéz•«¸¸˜½{÷&nß¾½ÍôÆ" j¾*Ÿ™™ISSÅjwÅŠÎ#Ÿ*DG?_˜œ:uJ§î: ˜™™)2†ÍI…‘Ê9žºíï¿6nT ‹ :™|ª°QY¶>}ú°ººZCÏ»wïÒ‚ú.ÆÞ|óMàˆ#Ú4~“Æ#`DDpöìÙ¢ñaaK€C†€Ïžu>IpÁE¹^zé%ºë$ Ia>óûßÿ¾­¤z!55U¨t•í¯®®ŽŽ66ÀÕ/ˆ|X°—r(Þµk—¨¾[¶l¡bugO©Tªµ\ÉÉÉB¹ô5Ì‹€øÃ¨Ín›——GssÅtçÈ‘C>¼”He;{ö¬VÝÛ$àáÇ…9MUU•>õ¡ááálmû;¼gÐâö~ªð‘’NNN¢«ÈÆÆF¾ôÒKÔµ¨hhhìr‹/Ö».ŒEÀqãÆwìØ¡÷Á(ËÖ׿8’`p°¢lZuo“€•••а£û¤ìÛ·/[Ûþf¼ü²¢—}Áä#ÀR€æ&ŠùÑ÷ß/ªwZZ𰫝ê%{÷îÍ’’½ëÃÌÍÍ¥D9—½{÷®F¼‡‡pÛ¶K>üáÕ–ž Ÿ}z‡ò¿sçúõë§5ž$òóó‘••…Û·oãØ±cHNNFrr2V¬XÈÈHØÙÙµxçÙ³zEÙ´TnEÅ~¥µµ5ðÀz½ÓÜÜL'''š~$<~<Îu>Ð'ôTz”ܸqCkYrss›è¾}û„­7ggg–——R•$;¶ ®¬¬ä¦M›hggGtwwç/¿üÒ"͈#€ññâÃcAÁ1aïZ,ØÛÛsÁ‚yLKKä“'HšjÈHOOÔ9UpvvfLL ·lÙ"º‘aÉçû~~~z¥W¹u©ÛþÔñÖüùÀwº|ÏÔ*L—Ëoû[ ¯¯/e2+**¯çölUÕ•Eww…ƒ©···àÜA’À/¾ÐM@OOOÆÅ}Γ'?g\ÜgüôÓuœ5k‡ "¹CB‚)•~CÒº… —.]Ä“'?‘#ÛøÖ[¡‚tóæÍ-tSÁ`^¹rE¨41Ë{k,Z´ˆ€öm¬õü#Å9®"`®kkkEõT7¹¨Ÿ_¹xñ¢ðîéÓ§ ªKcmÅeeeÑF¹—¾sçNáy°ò ×úõº øÚk¯±±ñ$•Á—uu¡,*ÚÔ”x::*œXdz¤ä‹2T¼t)Ф‡šŒ!lj fzú90€¢§ù & \.ZÜš5kt¦­¬¬Z€ºíOQQQ@§.$à×JEu¬ªª|#ßÿ}ø•+WPx%—––ê]—Æ" IîQî§;99 ¶Ì?ýéOÀ Ú&`CC˜hr(óòÎ0 @á”»‡ä+B|KÚh¼¿oßîÝ»—€ø)Kƒ H’›6m*\׉,•#ƒºß_kÜK¨‹!C4ßi÷aaa€³gÏŠU½Ÿ†í¯5–¯X¸àL{j'>í¯hÍ3fÌ€““S‹¸ -- ÖÖÖØ¿›²¶nÝŠ#F ¬¬ o¿ýv§è« ªQ¦ZÙ£Àòåˉ‰Àƒ‘^Žþý=Xròm¿IãÀ€;š›G"++_|ñ¶lÙ8;;k¼Ñn.X°¶¶¶hjjÂW_}Õ"Ž$bcc´ÝûÀ¨Q£0sÆ ÀŽö*Ôܰ²Bò£G€7¶ˆ“J¥Ø°a ""nnnmʳ´´ÄñãÇaff†ÄÄDœ8qÂè:낪çëßÿù¹páB >r9°sgÇä[YI”ù”¡¡¡O‹¸'Î#6v1bcW"6v%>û,eeMÆôéÓ‘””„b[2™ø.Y¢8kÐÚï_åž®Íö'†7nòè°ðh8ZiÛó•öIoooƒ¯¾PÑèÝ»·N7~c.BHrøðáŠúku~Euï©)˜’ÒžEˆ"äå%P"‘pìØ±¬ªú€ê‹maîܹ,**=sC¶s¬ÂµkׄŒÔÝ‘Tn@ÚÉhƒê0¼ ÀLÀ† # pÁJMMm¡GRRź6/i]hjjœ/t¨3&óóóY­unjjâèÑ£ €®®–—·€ùù 411¡ŸŸ++WS€»v­ç­[§xëÖIž9sЧNbLL CBBhbbÂ;vˆžîår9=<<€«V­"©0IØ*=Œ¿ýö[ƒäUUU æŒQ+;‰|ß89 þÖÛƒµµµ‚óí·ßnwÝÜ»wO80~ôèQÑ4Æ$àºuëh?B›““#\…2{6ØØh8{¶Œbf˜­[Í„Æ{áÂVTTðèÑ£À3gÎhèÕ!’ä'Ÿ|B๭/&&†Ø·o_½Ž&¶Æ­[·„ç°ÐÈä;êì,ŠŸ9s¦ÆÇR}Èèu²_víÚE´³³½gÆX¼ÿ¾°G½aíéþþ÷¿ ùM›&a^žaLOW¼ò:e²`¶&àæÍ}ùê›………tuu¥———F9;LÀG ½IBBó›ß´èÛƒøøxÁ{ÚÆ1P7ŒPzuà˜1c4îÞ½+ä«íò"C “É ô­a æääÐUiHwsskóäâöíÛ…< !  ““Ë¡C[IzQ€qqG…íÀùóç·è|š››…mÁÖÛq& It¾¾¾oݺÕ!™IIIB«6ø.Wj´‡|WÌÌ8RyPÜÿ×zR,—Ë9^é™#¶(i/rrr„sðàÁq!`uu5÷îÝ+LwÌÍÍõ>¼ÿ~J$;öœ€55º øô黜?ðæÍ’&$Á”£¢¢hccÃeË–‰oý³òèEëëÛŒBÀØØX¡"ÐÇÇÇbyíÚ5öïß_ëp ÀÿÖƒt•c$NU{÷»ß‰Þóå—_{ôèÁŸþÙ(ú« :dkkËÜÜ\á¹:o޼ɇІÌÌLÞ¼y“/^ddd$_ýuxª!þòåËétâÄ ÆÄÄ\³f#"ÀŸ~# úé% û÷ïÏÜÜÜ¿ôó³fbâsŠ]qB*ŽãΙ3‡€æ¡6£°¶¶VðKÀ={öC,I²¢¢‚ï¼óŽpH\ð€»„âVÔå'ÛÙѲÕM¢žžžZ/¦,))aŸ>ŠùË'Ÿ|b4ÝÕ1uêTà„ „ygG\òÕÍ™™™íÒ);;[  êš7…éÉŒ!!àÚµà¡C}xëVƒƒg+ëg³0â¨ëö©TJ'''ÚÙÙiø,…€$¹|ùr†Ùþ Ajj*-ZÔ¢åëFÅÏ>ûL«3I.^¼X ©®tAAAííí €{÷î%i8% ûõëÇ1cÆpãÆÌÈÈè°N*îÞ½[¸§oß¾ âªU«xùòe¾¬¼8ÀÛÛ[Xdš˜˜000P¸fùÒ¥K¢y”””‹±¥K—j8sHHFÀõë×€Ù³gãÿø‡1DŠ¢¾¾—.]ÂÙ³g‘——‡ÂÂB¡¦¦ŽŽŽpvv†““ÆŽ‹ùóç‹î?ªƒ$¾ûî;„‡‡\]];M÷ ¨¨ÖÖÖ3f …ýr]°´´„““œúÓR©ÞÞÞ{øö·í C0‚þ°úGH"‰@’ &!!˜„$’¬þÂ\¦þB’`´×›kÜ F ‰$ †ˆH0› „`¨kÜ-LB2I÷F’X ý 5NR÷š±é1K&Š0‘ž`P„D« ô£&Šˆª›I2±Ó„7M;}s f-W%fXÉ›˜ DlÿeˆfsHýÄf­˜ˆ °ºR?›ØþJ¬.Vß@DLĬ¯ÑC"s @0ƒ ©ß`}$Üõ 6“27«1둃 AP¯V_š{I]NNíÁdn'ó4#<6ó"=Há&å~ôfªfaÇÍNé‰/sY1«‡²•ôØÉÊ‚˜ÍÉõ@¼§2û @v `Ô[’`¯1#d6r!·a¬ÇÅ`Š …ÜxI”¬êl…âL@|%ÀdtQ¿‘„V§>¤5ÛII Mé¸ú__õ´õOZ¤½E=‘‰‰ÄDnLF ðžÖ ¢Æ<ÕCÌ0DÒS[½ê¬w˜Ô’ò‡Ív±[Vk1C¨¹K“‘Ù‹ä *ÃÈ]í}ÝX¾Ðí.¡•[YoôNšÄÄ€`½Ö&vÄn§» í¬ŒÜ²mÕÒ4ë ”Q«•Nׯ/Ö'¦d9gD*´t…ù0ß¶'DRPR©%kÃ¥UÉ¥¨¶äk¡ùC뤕‘ú—Í£ØÊN¨Ëín †$j”›Ñ½cˆšŸÍVÐzÀÌÆØÙM’¬W‰ ^CÞŽö–Ò5½EŒZûÆ×,†š'™)²,ëë3'êãËF£©G²Á*]aGG¢ýÊìúöDG6ȃÀ e¨Ù) ±§evÃ19m`OD‚•R†G)¾V¥jnÂl¦§w!˜#ñ‡Pÿ?Û {½ˆ£˜Zµ «çËQ«†ùž `5a9ƒêài®¯\z³:t¤:\”UüôOÄÑÅÚÈÅÚȱÒɬÈnÉoYžîm ;•ÈüŠ@R;C«¼ ÆÜQÌr*s3¸Ê¯(‹§  ³!f¯8OD¤¿1wf!ÉšÏ3;«êÙkµ‚½qË H2ëàÁ¨ª]yã¼Ô÷¤ÌDõ©½•óoTË\Ǽ?u®OF“»&vµÎ¸®íÆžto‚ÒþîaçÖD|<Îé(HÝ¥´Ûîf1³`²»\ù"%§…˜8÷‘0"Ž…LÂúo¥HÂ97+ný¥0ûˆX?\0™ëÝÚ¨ËDõ—«ƒ?(í¯Õ!ñÖ? .ËÒ…ÊY‚èHv J²^K3$LÎëÙ Üøõ\ô¤„þ’HÏ—ˆ­¯Ö2Ñᳺ:$Æà#"š%''dmíœuöü8ˆHZÿk£cõze¼8”l åtÙÙi8*>_9·«r¶ÎÿûŸbT<4óF&Ì÷f׆”1\kœU=ò¬™ DمÜ鰛Ҹk¤Ú*:œ!oíɳ0jCëù(ò\\Ž`ÔÇIKûe&—ÈKOÄd#!³¿ÈðFdé‘Rÿ å·AÊê3UŸcÕáÑÚ0bnÜ…µlÄ 'ÅZ•W·šh-x,nñò[?Ŭn…¼h™P…:,aQ04fž½ígâ ë[áiˆËÄxÖ1~BVŸ,Ÿ}­:̳B·ÿ´ROôÏ˜Š¦Z”îÍ&:²a»ñ ž¢éÕ“#ˆ™ˆLtoB©˜Ö³Î‹bÙûf†d<±R •—õd­Â&ŽGõÚW½V÷qýÊØ÷G˧˜= OCä&“Slcø$¹|Ýbk^ÎB¾ÿ”&R„{”N/TÂb­3©8…ˆ¤9³àí¶Ð¥…+±’žèu¦Ãà@­ð£Êù Gó­AvKfu_²§3ÑRJ’(DÓ§ªƒ¯Ï*Ô'êó~T¡:´gä»ï^ô‰Žôfƒ\— 8Á: pq4ˆ,œµñSy²^ŠÈÁÖ,è- X(h_\u¾qÄ\C4IÕ‹Tê&÷†cO&+á‚Ò-Îm0u’$>xâÄìéÉU'±̙g:žúNîKcGfæõ%øøMù[–¬œxmÍäX‹û)€„˜”Å£åS'J—ê…™hfžÏìL÷^Ûý‹™D§d!Iüû®óÌZ83“m?uzéþëŸßõ¦@ÍÑV3lmáÀ“ïŸý–Z=Q˜j=rjÕ{nþç§>2]Ϊí ƒ«Î5Q Ž0úƒÔÉ/äËC)ÈÖ"‚`9<¶P•Ä}ðr‚ö?ç†{îþŸuøôj)<žzŽ.þ/­°Iä)¹-Ûdǵ°Ô.‰ƒŸYpioŠmýI•”ˆ” ‡žÏøâb)H"‘æ\_uåGÇN„·~ Ñ|匬î»ë†Îõï)¬¿í\¦­ 8‘zð·nØ×c‹U¶nôç¯|Àu·¥÷,7}r@áöeŸkK­ Gv=àÕ=¿ñõ»˜!IP€L®¼¸glÓ¦þ;ö¶¶N˜˜ÌÿöçgßÁ+%„$U-Óu»ƒO½Àó¯\û¥¿ÿ¬$]ñJ§*}KÏÝuÛc;¶ìpn¤çúû¾?SÍ÷ Ñýß@ùýcPµ1ªˆò…`æP8þtrð›iލíÚzå®”‡ÏÔ&Bã[V Ö>0 p0}òÛå±Di,QO‡Ò—Žf¯ó;ý—ž™¯Ñ¸9»þšhÓôÉEÇv.ßóí RŠÞ­ÃÉL}Óm§>}Eq"£€‹$Üþ™=ÎïÚùêôr{= 7o>œIWn½é'Ï<CaºÕ Â:~í“ÿàÍþµßzô£c…ŽÑ‰öÑBÇűE‡N­yøÙ-^8rõê#­-Ó§WìØ .¢é8FcQ…ÎüYöØïæ„9^÷'ìWŒâ5,f4G£§ÑÌ¿í.ÏGÄy‘¾9»n{vmZ$•w­Wƒçþfó÷þø©–Ú¿÷¢ ÞMÁ|®Ù]žY9Ÿ·ôOü¸\Ÿhˆàm‚®J ”ËÉøÇ»¾ð•û´d‹¿û› ¯¯Ü™R‘-€|íáO©Ÿßµö LMs–Ô Ö!M~xñ¡ÌØÓ)ï­ä¯¬‘—…c$ha\¯×/EÜ$œ„Åaë‡sWmÏ®I‹”ÆIÌ3_{dÍ‘+¬~ÏùžuãìãÂ& êY˜ØÒúÞÖ°½© #Y® ;xËËb½ †þÏ£?¼e×îm®ÝúƺÕ:Ï!È@í.§s#=ê×\ºÄг±z -M±)…žûFV]ÔuGÉF2˜™†’£pp„™þDëæjve¼‚}B"µ®­°fœHáøØ`åHAßyz»ÃãvžŽYàêè,ÅðÉË6t®˜`¿†m>™\µgÕ(@=H–95Ç+ÑÔñK?:7ˆåKôd\p¾ŽFR œ^¾q}ÿòeà¤éÖ8ß2½vå€æÊ€’ÉZßÒsw½ï±[¯y ÀCÏ~x÷›×@WÁ}¬š(V3Ô@e8¨ É«ÉÏØ½cúgwó§ôÐÀ‘¹¤ÜÓO߃Úar¥ Ÿt`w&LeäÚK˜•ûØxýÉןT_ý(~ñ~Ôjs*uñø·Æýÿ5&2ø„fŒ·èh›„Ú𦦥îÙ±íåÛ^žýгCK¾òÏ|ë©«1ŠÙ©/»"­á<*k€̰ŒÈŸŽ=;ÑÄ\æZÐÝåãá#øx¶¨^ ¡TÉ/_†é£?Wm@K¶™Käê·Æ#±â§G”`c¾Pµ–&j-!4E—w_¸÷ç¼yËn%¦°q˰Ek…1ÐLIÀUòÈNdwðÙÇÚvÿf›ô‰*•sŒfe¯Š­Gh§äùb LEêµÀPÂÈ÷H¯<µáïþÇG•ÉŠ˜»äã¼6· ŽÄÿù:>}W¯Å(3"H&«jÕ„+±{u¦ÇvÞúë_ø# Hˆ­­ÓW¯9|ïG¼iËî‡þð¾{¿ü¥ÝùXxÇäCÚ¬6¯g´(¹H¨Œ®Þà»`"òÁYIS•&zj ž)H\[cBt¨—ï,˜Ïp#ôÔÅQÐÛru@a³ O<ƒÝ¯ÜÈUÛ<äšvŒÄø\q“këX‘ Æ&ÚŸyåÆŸÿý¯?¶û}‚äŸÿÆ,l»Û®ì¢B&P€–Õ5Å„²±àhj:RÌ‹&³]Øéüû5_"o(xÑ—ŒœYàÊ©ñ¨ÃCt©3½ìŠüÖ¦€jµ†¯ýÓ™‰Ò€…'=‚æ©\Ù{ÀésKÙ#]úûÉrb@±¤¯ü˽ZÒÅîx¢ÑFK¸dÁ¸~„.¸¶d@áµ”EmLc|‰Ád€*ͪ®Ó3p )Çä!»ºJî}[‡’™:€Óû³Q5Ä”– RruþÝ™°­yí¼̼& ¬è‰R/Ó–ÍofÒeoZßPÀ•;»§„päì*í«ûŽŠ¸}öïMAË?­Á„¡f=NAã[Á&Ce„$æžg*‰Ø Õæ%¿~JÝxÏ~uÙþ§WÙ’èelj² Õó®ŽÛJ4ñŠŸ/ì,ÕFý¬š½äå>þõåS/Üè•Ï-ã¶Š’La ×/ êÂ7pñ$Åp˜êùDqá­e£;Ó“GS6Âg&ž…XóÚ”GP©6Ðýú©^Àkî<¶~ûG_ZqáD§ÏçõÄíDšPÊ´8»®'»^53ÖµRuÈzf—„øŽg¶_·À‹{¯éX©•Èp3g@ÛJˆ-“^³þ€ÆKGzÂ8»Òry$tµ'Í+îŸîýÜ4€ú”8ôZkm,IljÃ)xKl#pCæåŸzã–_Ý <ü·/n×(‡£GÍ"r³«w$Dzã¢k“Ñá“sb‡’k£Óûä·:]&J&«÷Üý½_ùäæg²_øËû-kÉcÅ{YeÕáS6]þýÿògê’½|³sVA+gÖI !!’håä2nÝVï¼½šè ~ýW»J§U”#¼z»~e"'ÛÖ–TÛƒ8-'$F››ŽT¾¶hõdD‚‰H ™¯·--.Û ôÏ1ŒDõz03“í8½ìõýŸ{éú‘ñv¶¸›¶ZÆ üË(YL³gG–ì=ò®yæÎ—¿K#ûÂ@"0ÕÏØŠ™î%Ó›×VÅkº’$¤j«ò—ÄŸN½y¤^˜c†íAöþö›s"«Þ‘€ªCªR¬+\) *°¯ˆà5l54]™*F‘,yiðšÔ‚ökWÿ 7 =)Ó=f;Ï$O8$!lõÖTPÕ-B1= /ÂÂÙÌ|ßhSa¶þÔ·PÌ'·Á2}˜±0H5É eå'Å“®3y½*.1tq›G&r.ËuÓ°ã!ÚüM¡ g¦^kºÁsé•B±õ(x^¥‘ÇFtÆ—ÛV/2a„ ÿ¶X6ìÂ;"Ÿfç`r38C·ì½Ë²ÍÂØ:GÏœ«®Ë®]’èLRŠiF¾°]u^« – -,9hV]J1+fê—ÎM¿ÞœÝ¶ûIŠG¹s˜­J lc’tœ!²\wJ³h@`ÓLèjJÂk¤aOÄ‹ld!Ÿ¬¸?W':vV›’fŽU/ÔF6¤–­M/_‘ìNQFˆÐàJ– ¥$KÌ~ã‰×Ò¡FE[îRå\S)g“K:ó[bJF¶<è2#fÛ%ášÒoš|Mós d£}~ÊO(­dÇñ11£ˆ±¯AšÁn{I:E:„¨ 9Ó ÆÑþòé#• 3½WeV÷$ z˜óbv݆~>ëeÕ¸4Z:¿ôûó°½™äë]‰ ¶,@>ø>+‡^ãžÏút¥ Á½"4ý¶WÀö ˜v>¿SA·JÀÞeêÿ¨'°ad(ÇêóL["È‹µñSÕ‹U®-ó !D¨¼Ÿj_äÖ^‘¤kƒ°Sª²rzzß‘ÂsÓµ±¹ß˜ò«ºïɤ–2˜IÙ9Âÿ_õ¾ÆNSól­Û©rÅ黪+‹Hå–^'âý6~jª, .»øÝa°­¦^K앉ŽÇ˧küxÑô Óû^˜Þ #\©Â€B€rakK[’êË%ÚÒA«!mû8*Qùèä‹'&_.GSMßÕ–Y“Ëô‚BG/&•û𰣇{üÅFCÁ Ýãƒ8C š‰pÔ[rI–Î.8FdöÚ(-tª_ß´¾?Ý÷xi@þ‡ØÐã—‹´7)R«Z6v¥–v¥—” )m)–ƒÅ£G'^¨ÏÙ@ghÉ%í·%,1ÓøÏó¬h-õÅ£ø³îtð<„Ge S3´t`Uãx³XC-±._y8™n"×À€d0akrÑ¡Úø@½ðvq¢k\«Eµý“{ì7ÉAARdKÑT¡6ÄókŠ D2“\ O[™•®ŽtCª½c3³CTü£Ê{Ä^/­í“i·0?“®:÷(½zÏ•ñº9Vx4&¥;ÌýBîʧ®OÈw†å?^|«·Ë:ÞŸJ,d{ÆR/ÓŒm]¢íÌЛÆo‹·=¬º9½Æ+cO  ‚ÃXE¬pç7Âk|Jh˜Ÿã¸»{º ïõqdFÓäîÎ]µ#Ý'Þ"üû„"ÓÑrµßœ ?jÖhÅE¬OÔ¨"q ¶œ’«®¬x4È 4'r5”%R<w6z»ÌŠl Fºƒ–;s>ÕºmÙ< ïô'©5‹îÉ¥ûLUÛÖÀK&çsªãá1š§"15pT m³¦ëó!¯ôÿ4òvé@V;Î;ÀÁ9Ex[îÈ Eéuí ò?“Û¼(l?^½x¸|æ•ò’Ö÷¬Yø±D¢CBH¶5B¯=’ü#]ôI#ÌÂÃ[âÄp¯»=Æ MeÇëÃWl#ö¹þñ3ðIoäÄê û ®)vÒëd²‘c§´>EÉ® sa¢Ëq€ Ë ªçËçÇëcÇgÕe­,‹M¹dwß‚›º²›RÉ.IúD+v»ÐµOÛ°Õ8-»•çþõÀ C.Õ]à.¢U Í1Žùáb9‡d;n™ZZi[Sf'^ˆåôÒõ¸O,È+¹™£¡È?nÊÇkÈ.g‚€ҫ[Hˆ­í·2ÓŒœ™¬O–Šõ©™h’ÉRˆD:lkM.mO¯L';Ñ")`‹§{ãy-ÊìÈ•ÞQrÖïxÇ£¹øÄÚR&4RÔ8tX<:!ÚŽ‚Ïq¥žýâÆ6w€Olsj†u¬o=wÃ;±ÈuisìĽxQ&ȧ¶Ît/›¢xÔP«v qüÜkÍ8Ƴùyc#aà ·Çh,*Sä…aÔpüž=_,^ @CÏÍ;È4¬ eÎR¸c| & Äë@Wìí¾x±Æ[f[Ôðv·¹óí¼¶`0\IÍÑã=¾þ£ÂŒ3›~4l#…øùXJÖls½ØA`ñ2Êÿá]ˆŽÀ!×IEND®B`‚voxbo-1.8.5~svn1246/client/icons/a_search.png000066400000000000000000000166661153177201300210070ustar00rootroot00000000000000‰PNG  IHDRx<"ÏéÿsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ )8*“è,6IDATxÚÍ|i”]Õuæ·Ï½o~5—TU*Í’B†Ð3ÓØ`“x YMbâN;xHwŒétwâ^‹¤“v–Ûéxyèt¼ì¦W“;Æv0ƒM@H€eƒÍ¥Y%Õ\õjx¯ÞpïÙýãŒ÷•DbˆïÒÒz¯ÞÎÝgŸ=|ûÛ‡v‡!A¬þ’H"$$ˆIH&!‰$«BB˜ÓÔ!!$ I{¾9Çb’H’`ˆ˜³9A†:Ç]Â$$“tO$‰€…ÐwPã$u­›³„`¢™á Å@C°:Aß*`¢˜ˆ衺!Iæ&ö5ὦ}}sމÌFº0Ø|1A ˆØþÏ̈l抉˜Vg’š9bû+˜!Ìœbž¢ñ¸z"š=Ï–e£Ž¸(²­"¿:ÓÓ ADÁ FÝŽ‰ÀjT`@@DÝ—Ìù f©W#RCôÈH˜˜ ÿhžEDfðZí;‚‰I]NænúMÁ惺#„;X¿4þAFœú­Ì¤€ˆH4yÌ“™ÍṲ̂¤Á1¨‚h"®ïkLŠJÇÓe®7ß*ûä(R°)·²;ìXžYR:%2j,$õ’$Ø÷4#d5æ«}O†P×°H…@Ò½Bi«9s7ÑCVXäÏ„z¨šN­a¡V¥œF•Õ³êéR:®¾²¹# —ÀFS@Ò^%qb"=bB™£Áxþgõ‘CÒ”¬E8ÛÁ@ÄÀ,ÏøéÜ]a{GØzYacgª³(Z­ÚêY7#—ZRä)3 ö…EdÆ,Ô}¤¾Z£ä,ª;E†$Òbe³ÜÐÝ’"(fNj4ÜÂqÒ$&„Z kÈ,am[àM£:YšùW£)süB}â'µáÓq9^¸ÎwLD¥‰¨t¸z@_º§3ìØ¿¸¶·¤Ú¬*y¢ÔÕ6|Gd>þ ­ŒÔÿlnÅVvfaë¥É‰­ÎWæKϺú&Wi=3“›"µ¨@Ò>‚zŒ³¿úØ{œR­Ö` ÂѶÚÐŽÚð,7ðÏ>†ê#Cõ‘ó…«²«ú²Ëú2Ë3AKJdÍL;-3k™˜ ‚œ6°§ƒ "ÁÊ )§cí†ÖDã´Œî«×SÒd0;Gb×1êïL6Ô°çÙëaOó3Vµ•Áõgϳ†Æy1¨ÂñŽú誧ßÈVüÓŽ˜ã˜ãƒ•+rA>+ò… ¥˜êèH-^”]ž ;RAA/Z"€A˜;ϵªaÉ„ÁUæÔØ vŽ‘a׊sòDú/êZ=Ó YÓá™"bfuS²ÆØe{ã0– "d™ )1ó?Q~¬zæ+å¦c>®ÌÇ•©Æ8ªÇ²"ßé_^ØÔ_¸8% ÉñvÑd£ ‚qUn5±2‰Ú¾ÛUN 0Ášò´Ð7ˆZ¡Saç3ÈͶ¬½vÓÕ¸ Ϫ³õø  ˉ§ë#o©”›Žª¬ ÎÌÅ3 ZRØ” òv*™²G©¸È À¬ZkÙ n&œÍ±¡ÁY#ç„«$-gÕ}•O#ýx$¢cgÔÈCÛÀ)Yy¶>6-xÛR}d°r M9_c¬™ DYÛ Ộö°µõæT5ÅÄVÖÆ(mµ™!È®¿Ö¬kfªšñÉ%2ÆÒ1YÅËñOëã§ã þ…ŽÉúÐd}XPzvÃ8mëºæ9R2ú®½+Á‰^ Í A‘Ëž ½õ³X/gæuVù¹ÄÉk±ìc†q4&ë¢ÙèÍGr¿¨£•*QI‰†|CÇZ³W·šhõ>·xù­—â’³ ßèEˬm´JXÈè:“04fžM:ãÜ£ó­^¾hæÙ;y .O-ÈúÞèÈQª-ÈG,#Ä¥_Ü"ð 1kI9‚˜‰Hû6¡TBë•éô0wŽ1ä2™ˆX)…ÚÂ;Y+ÏÁɨ^yE6zmü‰=ƒ<«mVáT\©óù}àªTç{òëûÓ]JW9žg9)+uæÓÑäd<·þD qüOr!ì(„vá«’<½#ÑšÌÀb&¤sÁ%2n«b7©*Žfg£µyб·o«æ3‘!0±gO˜˜¦. 7ùWÙåÿº°¡Uä$ ÊP:%D1,JЪL¿$zWñ²R\~uþðD4=T}S‚îH÷¶g–øî]‰Í nzÙ×Ñ/EÚò¨p% -A‚ˆ 'ÂHŒPO»ôP²[ÏKø#p‹Ëó É€½DQžÏ:‡$6¦)ÉHMºÖ»¶ ¥%l]šé—%Yžh”öTNEÓãq>çýÛÓ=ý……°C{²Þž‚ï95d€$¹èËbk^ÎB¾ÿ”6ºu·Òé…ÎÕ1©T…ˆ¤:³à­¸l•¬±’žèU"“CpnAG,wÕ…m]A«1Aêæ„+× ¼5hi Úú2Kk ÕGG£•ƒY‰e$½8=ä»3K—6/)l E–}lȤ$f¥‚XGÊ¿iÏÉ`ᬟʓõR)õskÖ+[X°0pÉ`³áãâªÓü@0³+œx"]¬×F<È ” 82°P|²Aõé°t(·íóôó—χZä‡{?;ü™» #Q›KÍŽæÆŽ¶|eñíËg& 샓¬³²i!2ï}@iÇOaç‹x}?†GÁ’ºÚÃ%ùL¥çàókãZ†ÍJÕAÑC?ùLó|7Âr976ÞqüDÿk¯oxö§¿26Ñ釨Mí}âæ…/ÒˆR¥ÙÖÇ×<þü ß~òƒsÕ¼†¢v‡ÁBA7Ë=Æø#™£_h©‡R­;0D Á$Þäð9.ÿÎ?à·>}~Kºl þþ>l½é”÷hI¯?¾ê‰¯^Q-²*÷¨ªŠ)a|åůû¶ãÃíñ;u¬OÕYTD’xè'wŸûB)ŶíWÿÕ7ïèVE%u!›²Îž'Þ{î; ŽöÝñßþ÷þk¥´;.9˜ÝAßףGH¢…ÒËQ¸BvÞÒ;@cJìùDûÔ® Ûú“*))A<[|ýôJAà@‰,WÖW}hâLËôo|ÇOGЬ,¶~`Åê­K[;—×–^6¾á¦Á\[ @e:óÀ=7ÛÝg‹U¶nô•¿ `ßÎU?øÚ»cHHP*/^6uõû_Ý|å#íÿñŽÿT­¥mK‚úéÝ^z~Ó}_¿’È«½}›7\wÝ®ÖÖ9Ó3-ÿùÞ?ܽg£„¤ªeºn·çÉ÷xöÅ+¿ø~O’®xe3µ•ýƒ·ßôØu[Ÿ08ÖwÕ§.×óÁ§„èùP}&þ&hLˆÆ5ÆDõLPÞNnKÝŸå˜Ú®Œ‚´üµc‹³„h:ŽÑ˜E\£“_Îú£"€°Èëÿ|šýŠQ´Ä„v¾&ä?öÀÒÛÞ‹w^~A¡X£ñGf^z ôÌ}ÃÛïþÒÔ=]{ð(ÝøµÿúœÑÂPÃeU¤££GþözõÓê§ÞpÐ&£Ó€%ƒj5ýÿæö/|éS ùÊ}öð IhCG0®PðWþŽúù²u{TͰ FKゆ¿›ëº¹ÑuS­ó]µ–™ý¶píHиÊùÔ†²—oÁçîÆwQ¥ö&ñ©xv*žýÆÓá·o .Zg3§OWŠæ³Ë”HÍÇÕL}ùWÑÙ¡S'GF¿'Y" Z:Ò=]Ùåù°sb¸MG ¹º{M4Zlà7û xôÇï¾þ]»®¹êÅ+ßñêúµÇö^ãÞËWP²èÇip¬OýZÌΉâlå3%ab7bð¾|×M5‹n™ŸÞŸaK%ÁR‹íi•Î÷ÖÓ)ÜünüÖÕ-ÿoÇÜ›EJMLcâ%õ­9U9®-R8jÿ˜élÐR ;z;Ûîÿ.ÛŒÁSy—.s°dnd‹Ï™?þ݃·]sÕ‹n¼vç¾Ãk½ŸÜ+ˆ› ·kDT“‹ÈUXl~`àP›#™r•veâ ynGÝeØgC`J÷j6ßu@:…-ÕþeáéãÑÌ[ /5d½!'fC§qϽXÒƒVÌê§ZÒK‰B]M@šd3¯*0^y}ce>›ÏU·lÜïf¦I£ÁœD úý_¿_ýúÄ®ë ¨”ÐG3Sà%&^ŽQHµn©çW5ÈÇmÍR-qëºkÆ ‰ +ë«?8Þm Àá‡{ƒ=·ç ÷—÷½éÌ,ff!ho&8±¦ýºÞÂ¥¹T¯^¤²ä&cbÌH,űË6mX¶ôŒÎ‡)á·æÖ­:¦¹2 tº±²ðö÷¾­›®ýÓƒ¹Žˆ«Sw¶lýüçþej.G¦ž<3ÜÔªðÜÄÅK¢î΀ÉR»ÂR“ɵu¬XÓO½xͯÿñ×ÛùAò+¿ÿ'Ým“¢9pwO†^¥-P€Âڀʱ”²^éÍz_º³ÔÆî¯/ÊÇ«oÕP5Ð*²Ÿ»Û€;o.¾Í‚®EÓ?ž ˜ÐєЃ@®Zq À‰Á~Ë¡`$"<ËMHÅ’¾ôO(d+ºîñ°Ùi¨8‘=LYáLíWÖƒ<(½œQw•Î [_â3ù³t¤ NéZ?Ç~¸þjôÌ´÷½tÍd<ÿzíô¤¬œªÕ9–o11áÏ¿‚®š³\‡¶«1nݲ7—­xu߆¦î‚4Ó@Ê bÐSkÔ›V “öÙ/ý%h Zö»sêËÈó§ ù©`f8«?›çˆÐ”b4ßÐÀóA¡-lY‘é•3\lL=_>PŠçfâÊ[$ñáQl{—¬ÒH¯ŸU³—¼üæGQ|ò'×°_ñ zC[ h´DaéÊF…>L‘LR,Ñ„@Ô÷•î«ÆŸÉÎÌÀ²;`lÊ—Ž Z¼eZ‡zCY©SS¸âè„E‘_Ÿ)ö¦ºKqåX}8³l(ìbÆÔXöÌ¡nAAÌqHéWÓ"·ô’#í, í,ÕÇ#®Ç,qw)ñÕoâ‹ÿ¥A¶¾l ¡dH6·ÝòÔµïÜà¹]—[¥9\‚TŠ’PPÈóÓãË7¼®ñÒ±¾0É®´Õ  ÀQ–—znÅgæD³bߟt)­…%©)‰7£õa>þ•{t~|âéE>=0‘+%ƒœ¢(´çóý¡wß5LÕ¹ô—ó#ãÝ’ˆI£Òô×ÿ%€]O®øÆ½žjLŽ×†—w—£éùh6âÆ¹%>:Ž¡±úÂ¤Ž‰ÒéúGïøáÇï|À\9ÿ…ÿõi±ÆËð‡lsEKÎ"å³Õ?þí/«Sþñ…œF­œ[/%„„DH¢•ÓK¹õЍë}õT§Txô+w-š?¡¢áÕÛõ#SEÙ¶n^µM0ˆ‘jº.™Ûðo†[–V <Ú;²§•3-ÅkgbLDé–¨­¿²tËØÆ÷œÌ·W”KÙûï¹eòtzyÒv!_¬õ¯ëƒ`ô^ƒ[XІž9òÌž£ãçâ{TðòÞ±•«N«‚€+Ì÷-Û¼iàúkŸoo›Pšn½ûÞ{Ïô©”c!»®¥P^·ê(T ´g·®ßû±[¿»¢ç4€ï=ýþW6;àÿ\–#çþ¢m~4eZNˆE õÝŇöžw©<Ú»ãÞMzà5¶Ð={9ÏÅ«¯ùÑ×ÞY/ê^ò[Qè¯_øŸg½°ÞÀãO᣿‡ò93Ð[oÂ#ßz’jüãök¿vßÇF&»½Šù@4ðø ç}ëŸþÀg¾úßkQ:ÄÙÒ3ŽÍP}$(„ÓϧGŸÌUGCI Æ4' hg›‰F9˜;“ÙÝzè‡}C»;’4Y0åB‰ê\jf4?z´ãØK½ûv¬œ™*J›Á’-c'ÛIšMQ-³bQÛòžòþcsçÄ /£4ö6ˆ¢ \Îw;±ô•×6íøÙUc“l+å¦ÃE—£™Þ ×s•ü©±%»\ö§~í…ý—éÈkwHºÕ‰3fº—Lo\[S¢éJ’ª­ÊŸvóGW¬³QªG dªpú)1 ¨:$ÈÔ„×ØGÄð¶šš®LC™}饱Ï­tW¬ü³|v¥„`áÞB¿”é³g'õjm‹!Xµs‘PLÈ0€!3!éŸ nG†@çÕ/jx=ŽeÊÊ3°»£rBE–¤âƒÂìq*ï9^ö\–ãȲã!ÚüAŠúîc®vÒR_=¤”| žW@i¦Ã±ñå¶UÀ‹L!ûÀŠG3eN„w>ÍÎÁäfp¶óÉԯȌÊBÛ‚CQåd<»«>4'ë lÊô­J-Zv†”¶g3F¾H®ÕxØÌЦRXrЂº3ÕŽïŸÚv~uc¢‰ÛèQî,cFUa“¤séäZ¸<¶â’î#/‹'«P^# kND²ÈfAbû•àµöiÀw8®ü rèt<;'늻4Ï=GG¯Î]tInyGÐjøp†àmò°k""f¿ñÄké`¢š¬ÎE3cµÁ‘ù#Ãó‡rþBøM\f&[tõ#fÛ%á¨ædyÓäkz’Ÿ !».F$(9Vs‰ü¡°3 NL)µiÕ0 ºFâò÷+“>=¬Îqãíåý¯Õo(lZ–^\ vèšSób^@Ç×jQãêTmìÈÜ«cÕåh:¾°f¤P䲩nß»:“+ ¾/È!MKföxH“G´ÓQ‡¶¬…°ØÛ!ÑÔèú¼<›#œ€àÖéD<;Ï•„CŽDÓß›þ¹ Z’êÊ‹ìêt!Ì/Nu‡"›“P$QƒuŽÆãsqe¬6T稗#nÌF¥š¬È K í‘Û ™Ét‰Ø+4›Êº1• ¶Ý&‚›ë5Þ(HáÑÚ0ÃïÄrÎÕY<܈tgñÒLºÛs³j% GÐjÖQ"}õ 3T¤ŸXåfq‡ìL„£Þ’ëL²tvÁ ‚°pð ³×Fi¡Sã™4Ëuù&ÿ3q(O¨Þ“·æ(d–-n½* –˜i|€ç‡yA´Î–úâQü5·‚‰‰ÏBe0‰€i™nŸÀÙÔqʉÞXÛu.=ö©d?úå:òéÞU].f–[³j8›¦ýÔö"º`lfvj2õ¦&þ…‡„3í-ä¶mO^½ÇçÊ0/¤G“¶D&(¾4½(O©_)çÒ‹W/º½­°z{ݵ©!/Wd1½”p}dB#gX3L{Z¶ÂÃX\˜¡O±‘#“ÊnÈðÖ´öKol{ˆ ´6ìÌRøK"ålªkÝâ;ºŠ[¥|YÀš¡ÝVÅ…ï·loq¶\@Ý$e:’Ñ 7Ñœ<È•ÍZR€ÛÛà ½]få(ï°Ý#DŽ‚¬ÍÅbgëšI„‰æÛY¯wxA‚æ©HLÉÀÎ Ú‚®Ï‡\éÏý­4ÊÁjñ’nçýÎ-cÚÄâ°¥3lÙYr&šy¥zr2.FÓ¿@§D®-ÝÛ•[Ó[ÜœOõ„AÁažvg¶Ì¯ŽE~Øj"]Þ’,™»†òÄÖQÍÎТw–j*È57œ(úºj<ˆ YöuÇî»äíü¤a ø¦ € Ñ´t­kÓKª§£©Ù¸v¤>\‘µáh"fÙ¸ÃPH öôâ€ÂLP”.¤:ZR½ÅÔ¢\ªKˆDJ’€—©:ÅLl…e«SMu} _Ø-fØ‚> ÄC»ÈÛ±€iG@‰3Ÿ¼nñ@òª¨îÙìE&HàS¦Œ+ìMÉõD‘JA¬Ëä%Ä–ü:&1WKqùx}hFVfã²Ç,Æ)JÕ9j ÛÓ"»4¿®¶çÃNƒÁÄBXb§4šh¸¯êé¢)CÖ¦V­i½Q€‚è<ìÐ߻˟9‹nª=NÌq{­™@[·(³×‡¯ØF®d—LS§¥#9g˜9=wáNg¬“I˜b òa±/Óû›Øy5¿|Ç éü„Û I=š‰ôfDÊbÞÑŠÝ*t{ÉØ°Õf"f *Ï/üë†\ª»À]D»€)LŠïet.ãsÍÓp;i˜Ï™½Þ ß;lº””íNWåÇeºÎ¶°ë;,Ö-lk\.™˜H¨2‚seVB® Üfl‰/š2š ØÛôÄ&ß®Và)x2lð[Ân”ÖTŽÒ&»…\“¬Jx.¢¹+†Ù¡½^ßzóN-ìm(E¶Ò/ž%{ Êèïë`”ÚÛ±Å{´×A &£Ï²u4ƒ— ï˜\—Ü&=jkyV»ë± @€¦ž«GdV…2g)Ø¡-ä5‹'3Z ’°·ú’ÅošmQÃ[Ývl¶„f„ÑP·eˆŒd„Ñ_SHòh0”\ÇÎ xÚÅTFÖls½ÄF`É2Êÿçߦ›y ÿIEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_black.png000066400000000000000000000002631153177201300213100ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÚ)Е3IDAT8Ëcüÿÿÿ*&*ƒ‘‘‘"ƒ`¥º G 5pÔÀQé\R«à¦º ¿Ã %q’ÄIEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_blue.png000066400000000000000000000002621153177201300211620ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDùC» pHYs  šœtIMEÙ- άµÌ2IDAT8Ëcüÿÿÿ*&*ƒ‘‘2ƒ`þ¤º G 5pÔÀQé\R«Ü¦º ÁÀ&Þ1·UIEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_bold.png000066400000000000000000000006511153177201300211550ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ&3ZÔ™)IDAT8ËÍT»Šƒ@½>c!bo!~B,ü&…)Óú°³°ó?lì,ƒ`9`¥Â DrÓ-kfÙuÝ)öÀmfΜâœ3W#"…ÐA1‚š¦ý8¶mÃñx„<Ï¿V¤O€_M’$ôŽ? êºN·Ûm!ø­‡œs@D@DBÀårYÜ?ŸO¨ªj}(¦ic cà8œÏg‰cYÖòÍÚô†a€ëõ*‰EQ¤&ÆE!…²¹‡AÀ~¿W[ 4M×׆sNˆHˆHÓ4QÓ4Çñ‚³ÛíH±N0Ë2É£¾ï%^Y–Û=|<ÒÙ8Žëj3Ï3Üï÷·m I’H<ÏóÔ…âû>Íó¬æ/ªëzûr0 ƒ\×¥0 ét:Q×uRhæ['ÿ߯~@À±¸]= IEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_down.png000066400000000000000000000003301153177201300211760ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDùC» pHYs  šœtIMEÙשI„XIDAT8Ëí”Á Cuøÿ¿¼NA#M»µSà|8‘”$¥Qf}`]6ªZÍcy¹rŽk/v…˜9õ¼ˆ£dN5d§8ML´È*ìvùÿsx"3û8>küIEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_green.png000066400000000000000000000002631153177201300213340ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDùC» pHYs  šœtIMEÙ,5Ö™&3IDAT8Ëcüÿÿÿ*&*ƒq!#EýÿOŽ8jਣÒÇ@ÆA_b›6 !Ö'v™IEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_ital.png000066400000000000000000000006221153177201300211640ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ*!ZVêÝIDAT8ËÍ”1Š…@ †ãkT¬ÔÂ^ð6‚`©Ç°oàI,¼ƒ`¡"â!ìÄV+; ‘¼nØaŸÎà¾bH>’&á‹ö‚/E†‚ PGUUH’äwrز,䨶ëº~ŒåŽãHó<¿Œå¦iJ`²,ã¾ï—±\R–%ñ=ÏI’ž?Êqж-¹ApŸÀj·ë:J¿anã™VUE|Ó4Á²¬¿ýßú1Ûeµš+IDAT8Ëí”?Šƒ@Æ¿§Q«€ ; sK Á*$ÇÐãÞÁÞÆÎkØhH!B¼@@ ˆo;wý“lX²°Å~ðàÍ›™ß0óÍ 13ãðfM€¾ïc·ÛˆÆPUŽã ÏsÀåreYEDY–áºî'„g:ŸÏ `Œ²,yMiš2βlR§ùÃQ'm"Zl­ï{H’„¾ï'ãiÍ”¯€gžÑ¢ÿwMù>3OÜ} „ï×iÛÛíö5 ®ëcÞuÝ*°ª*†ñðx<ŽyQ«À8Žq:VÏb¡¦ix¿ß3¶m›¯×ëØw¿ß9Š">ܶíb.=ú¾n·Â0D’$¨ë¦iBÓ4(ŠÏóÁª)ôîÿpóè ÿô*mæ…?÷R>Ú ×ñù˺ IEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_noimage.png000066400000000000000000000030301153177201300216460ustar00rootroot00000000000000‰PNG  IHDRP(i`}sRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ.e„ý±˜IDAThÞíYmH“m=Ó}´ÍP Éi ˆ3£Y´ˆ°ýp6Y‹„H*kYöEIP ¡¢` Gƒ+òO؇ý(²Œµd„Ì-+'«=çýåp=«·×Þœås`°çÜ×ý܇ûãzÎ-#IH˜2²$ $%%%%HJJþ'Èd2ÔÕÕáñãÇX»v-4 t:Nœ8oKÓH$‚ææfèõz(•JèõzìÙ³>|ȼ‚ÌÐh4rÑ¢EESSL&qá¬Zµ OžÞd{ C¡P ßÞÞN¼wï^Ú1¾|ùÂááaF"†B!`ccc²½¼¼œz½^ÔïÙ³g¢ü–/_N“ÉÄH$"ú­^½š:nÊþ¯K¸¨¨(­=•®m‚Ÿl] ‚—˯׋W¯^!‘H¤ôNþ÷îÌf³h¼ŠŠ ××ׇX,†üüüôAVÖÌØdO}¯mrpøða¸\.Øl68pP©T ‹ÅA¦”— ¨®®ÆÙ³ggFø»ÐÙÙ‰eË–áæÍ›)|0Åãõë×igÛ·(++C4EMMÍßý%ÇÓβӧO‹¸ºº:„B!ø|¾þüùó¢X‡Ãx<ž´ãþÊíÞŒšv»^¯µµµ°ÙlH$¸qã>}ú$Š=rä®_¿Ž-[¶ ¥¥%YÆô÷÷‹¶ŒÖÖVøý~455Áï÷cýúõP©TƒðûýXºt)ÜnwæË˜Ÿµ§HòÒ¥K@ŸÏ—äÆÆÆ¸ÿ~êt:Êår.\¸N§“###ißßßßO«ÕJFÃÜÜ\nÞ¼™@»ÝžÇyîÜ9VUUQ­VS©TÒ`0ÐápðáÇžø»ðüùsàÁƒÿþ[¹_Åøø¸ˆëèèlذA2þ ‹%%%X±b¾~ý ŸÏ‡Û·o£¦¦wîÜ™ž[¿?y¹ž9s†‹/¦Z­¦B¡`ii)=ʱ±1ÉÒ—iI@ ?ƒI~•ð¶–-IEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_red.png000066400000000000000000000002621153177201300210050ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDùC» pHYs  šœtIMEÙ,³Ü,M2IDAT8Ëcüÿÿÿ*&*8‹‘‘2“ ¥º G 5pÔÀQé]R©à¦º ½Â&œ›»xIEND®B`‚voxbo-1.8.5~svn1246/client/icons/icon_up.png000066400000000000000000000003241153177201300206560ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDùC» pHYs  šœtIMEÙ-P8ãTIDAT8ËíÔ1 @Úøÿ/ãd ÚÁÁN$Ò› pw7ahâ|0 {(ƒ2‹eQî`™7îV;<Áf»<ÅFÞ`QWþ±KTGç‡Á ìÏS…N‚IEND®B`‚voxbo-1.8.5~svn1246/client/icons/windowlogo.png000066400000000000000000000045111153177201300214140ustar00rootroot00000000000000‰PNG  IHDRxx9d6ÒsRGB®Îé pHYs  šœtIMEÙ +'–-ÅÛIDATxÚímHSmǯ¹¹Í­¦Öœ/¨ÅÒ$—i53 J ËPI  ¨ ’XØ?A(FÑA 1{1TÐ/Š––†EøÖ4 ó}®¹ëùðç¾Ï= ¼E€HŽùˆH$/úø &Á &H0A‚ L`‚“`‚$˜ Á &H0A‚I0A‚ L`‚$˜ Á &Á &H0A‚ L¸‚Ä™ÆÑÑÑ.ïH$T*™L2™ |||@­VƒF£ÀÀ@ ƒíÛ·Ctt4lÞ¼yÃ?˜µdý?R©T*Õê :âããaÇŽàííý×rˆ}|T$­Ë‡IIIœœ €¸¸¸u¼^Ye2;v Ξ= Gu«ì• è(ðïÃâë¾EDD`QQ¾ÿ׋ȩV«ñþýû¸¼¼ìÎ ž/ø÷-55_¾|‰V«•w‚W¶={ö`OO0¯lIIIøîÝ;^ T*•ØÐÐ \Á€^^^xíÚ5üõëïÊårlkk[S·u²:;;!11‘ùzD“ÉKKK077ccc0>>Ð××===ÐÝÝ V«Õ©Î„^¯‡§OŸBppðºt²Éú{æùùy˜…ïß¿¯æ¬­­…¯_¿Ú}}hh(ôöö‚ŸŸßÆv²:;;Ýò—355…µµµ˜••…2™Ìáo{dd$ŽŒŒ¬Ë_°»²¶´´ N§³›­°°pãOÑî ý;“““h0P¥R9$9** F#g#"Z,<þÞ¹s'³><<ìǹ´´ýýýÐÝÝ uuuÐØØf³™Ù‰¬««a gÖGFFܺ¿ììlËå·_XX€ÙÙY˜™™q¸Ã ?†}ûö­éXy!8$$„Yÿöí›[÷788ø×²¨T*8wî»4‹ƒ—‚Õj5³>77çñ233áôéÓžžîÖ‰ÿ¼lïti2™<>C}}=ŒŽŽÂÐÐ\¸p”J¥ÛÞ›SãÁÂl63ÍÛÛ›S³*Õj5Þ½{wÍs¿‹ãÁ¼Öóò²÷ æTžÉÉI(,,„ôôô5–ðBðââ"³ÎºÓå €ˆof³&&&àóçÏÐÜÜ ¥¥¥‘‘ û?dSSèõú5Kæü)zbb‚ylÆ#§ìF4 èííÍÜ_bb"ÎÏÏ ÷=99ɬ»³ÃâN‚‚‚ ¤¤:::˜×ò]]]P\\,ÜS4kÕ‘ëä&>>˜ƒúeeeÐÓÓ#LÁönE†††z|†ØØX(--µY_^^†;wîSpoo/³ƉÌc­­­…?~àÿco0ÂSJ¥pòäI›õ¥¥%§§ q^°Åb7oÞ0Û¸:Ýe#8xð ³ÞÞÞ.,ÁíííÌ9à …bbb8“'66–Ywvòç×ÔÔ0ëiii ‹9“gË–-Ìúøø¸p›Ífxôè³MFF§2Ù›ÿlkÞ/WUU1{•b±˜s‚í=¢²°° Á&“Éî\¥'N¸uY‡õÀÞe³wå8+Ø`0ؽÁqùòeÎå`Öø/¸±±ÊÊʘmôz=¤¦¦r.[kk+³ÉoÁoß¾…œœæä5‘Hd÷ à‰X­V¨¯¯g¶qtuN njj‚´´4»‘‹/BBBç?yòÄî)úСCN¿¯Ç›L&¼qãŠÅb»Ó]víÚ…‹‹‹œ[£cxxCBB˜û qjKðô5:, VWWcTT”Cs™q``€SË(!"ŽŒŒ`\\œÝ|·oßæÇ",?~Ä›7o¢V«ux¢Z@@öõõqj!4³ÙŒUUUèïïo7_xx8ÎÍÍ9aC§Í.,,€Ñh„/_¾@__twwCkk+ŒŽŽ:õ>Û¶mƒgÏžqâžóèè(tuuA[[TWW;tëÑËË *++]š™â¶µ*µZ­ÝùÉ+ÐVÖªtua‘ßÉÉÉÊÊJ·¯¿Ö¬¿c±X`zzfff˜Ï"Ù¢¬¬ ®^½êrN®6õõõ¼]NP$ayy¹°–ŽŒŒÄŠŠ ·ô”=9kpp0677 c½h…BÙÙÙXWWç¶åî=5«R©Ä¢¢"œ™™qK|6I,C\\$''CJJ 9rÄc§¾º‹½{÷Bnn.äçç»å©ÂÖU°T*]ýi…B±ú³:´ZíêÏêDGGæM›x%P"‘€\.___ ­V 111ÉÉÉN"üÁ\{Æg-ð%+ýòÏ!Á$˜ Á &H0A‚ L`L`‚$˜ Á &H0 &H0A‚ L`‚$˜ Á$˜ Á &H0A‚ L`¡!‚ÿÖq øÉ?/à.s{é¦IEND®B`‚voxbo-1.8.5~svn1246/client/patientdata.txt000066400000000000000000000035531153177201300204470ustar00rootroot00000000000000 # "session" examiner date # session "Dan Kimberg" 1980 11 16 02 00 00 # node - id - parent - value session 10101 scan 1000 0 ignored scan:type 1001 1000 MRIx scan:date 1002 1000 "2002 12 1 0 0 0" session 10102 scan 2000 0 ignored2 scan:type 2001 2000 hahaha scan:date 2002 2000 none scan:tech 2006 2000 doris scan:lesion 2003 2000 ignored scan:lesion:location 2004 2003 "some gyrus or something" scan:lesion:size 2005 2003 222 scan:lesion:side 2007 2003 middle session 10101 #demographics 3000 0 xxx #demographics:firstname 3001 3000 bob #demographics:lastname 3002 3000 thebuilder #demographics:dob 3003 3000 "1967 5 10 0 0 0" #demographics:phone 3004 3000 1-800-EAT-DIRT session 10102 demographics 4000 0 xxx demographics:firstname 4001 4000 dora demographics:lastname 4002 4000 theexplorer demographics:DOB 4003 4000 "1960 4 2 0 0 0" demographics:phonenumber 4004 4000 1-800-EAT-FOOD demographics:sampletime 4005 4000 "0 0 0 3 30 27" demographics:sampledate 4006 4000 "1963 11 22 0 0 0" demographics:sampledatetime 4007 4000 "1964 12 23 4 31 28" simpletest 5000 0 xxx simpletest:datetime 5001 5000 "1967 5 10 15 30 00" simpletest:combo 5002 5000 "bogo scan" simpletest:string 5003 5000 "very useful data" simpletest:string 5004 5000 "very useful data 2" simpletest:text 5005 5000 "big block of text" #simpletest:image 5006 5000 noval #simpletest:brainimage 5007 5000 noval simpletest 6000 0 yyy simpletest:combo 6002 6000 "bogo scan" simpletest:missing 6003 6000 "surprise, this node doesn't exist" voxbo-1.8.5~svn1246/client/searchPatient.cpp000066400000000000000000000223621153177201300207050ustar00rootroot00000000000000/**************************************************************************** ** ** This interface is written to search patient information. ** ** Because the interface has to be scrollable, QT designer is not used. ** ****************************************************************************/ using namespace std; #include #include "searchPatient.h" #include "dbclient.h" #include "dbview.h" // Ctor that builds search interface SearchPatient::SearchPatient(DBclient *c) : QMainWindow() { dbcp=c; mainArea = new QScrollArea; sp_ui = new QWidget; setupUI(); mainArea->setWidget(sp_ui); mainArea->setMinimumWidth(950); setCentralWidget(mainArea); setWindowTitle(tr("Search Patient")); setDockWindow(); //setMinimumSize(400, 400); //resize(950, 400); } /* Set up new patient information interface. */ void SearchPatient::setupUI() { spLayout = new QVBoxLayout; addTitle(); // add a simple title addSearch(); // add search criteria addButtons(); // add three pushbuttons at the end sp_ui->setLayout(spLayout); } /* Add the title on new patient interface. */ void SearchPatient::addTitle() { QLabel *title = new QLabel("

Search Patient
"); //title->setGeometry(200, 20, 100, 50); spLayout->addWidget(title); //spLayout->addSpacing(10); } /* Set up search interface. */ void SearchPatient::addSearch() { s_field = new QComboBox; s_field->addItem("Any Field"); searchScoreIDs.clear(); map::const_iterator iter; for (iter = dbcp->dbs.scorenames.begin(); iter != dbcp->dbs.scorenames.end(); ++iter) { if ((iter->second).flags.count("searchable")) { string tmpStr = (iter->second).screen_name; s_field->addItem(QString::fromStdString(tmpStr)); searchScoreIDs.push_back((iter->second).name); } } QHBoxLayout *searchLn = new QHBoxLayout; searchLn->addWidget(s_field); s_relation = new QComboBox; s_relation->addItem("equal"); s_relation->addItem("include"); s_relation->addItem("wildcard"); s_relation->setMinimumWidth(240); searchLn->addWidget(s_relation); s_inputLn = new QLineEdit; s_inputLn->setMinimumWidth(300); searchLn->addWidget(s_inputLn); optBox1 = new QGroupBox; QHBoxLayout *box1_layout = new QHBoxLayout; searchAll = new QRadioButton("Search all Patients"); searchPart = new QRadioButton("Search among Patients Found"); searchAll->setChecked(true); box1_layout->addWidget(searchAll); box1_layout->addWidget(searchPart); optBox1->setLayout(box1_layout); optBox1->setEnabled(false); QGroupBox *optBox2 = new QGroupBox; QHBoxLayout *box2_layout = new QHBoxLayout; sensButt = new QRadioButton("Case Sensitive"); insensButt = new QRadioButton("Case Insensitive"); sensButt->setChecked(true); box2_layout->addWidget(sensButt); box2_layout->setSpacing(10); box2_layout->addWidget(insensButt); optBox2->setLayout(box2_layout); QHBoxLayout *opt_layout = new QHBoxLayout; opt_layout->addWidget(optBox1); opt_layout->setSpacing(50); opt_layout->addWidget(optBox2); QVBoxLayout *s_layout = new QVBoxLayout; s_layout->addLayout(searchLn); s_layout->addLayout(opt_layout); spLayout->addLayout(s_layout); } /* Add three buttons at the bottom. */ void SearchPatient::addButtons() { QPushButton *okButt = new QPushButton("&Search!"); QPushButton *resetButt = new QPushButton("&Reset"); QPushButton *cancelButt = new QPushButton("&Cancel"); connect(okButt, SIGNAL(clicked()), this, SLOT(startSearch())); connect(resetButt, SIGNAL(clicked()), this, SLOT(clickReset())); connect(cancelButt, SIGNAL(clicked()), this, SLOT(clickCancel())); okButt->setFixedSize(80, 25); resetButt->setFixedSize(80, 25); cancelButt->setFixedSize(80, 25); QHBoxLayout *buttLn = new QHBoxLayout; buttLn->addWidget(okButt); buttLn->addSpacing(20); buttLn->addWidget(resetButt); buttLn->addSpacing(20); buttLn->addWidget(cancelButt); spLayout->addSpacing(20); spLayout->addLayout(buttLn); } /* Add the dock window */ void SearchPatient::setDockWindow() { QDockWidget *searchDock = new QDockWidget(this); searchResults = new QWidget; searchResults->setMinimumHeight(150); searchDock->setWidget(searchResults); //searchDock->setFloating(false); searchDock->setFeatures(QDockWidget::NoDockWidgetFeatures); r_line1 = new QLabel("Search Request: NA"); r_line2 = new QLabel("Search Results: NA"); r_list = new QListWidget; connect(r_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(showOnePatient())); QVBoxLayout *result_layout = new QVBoxLayout; result_layout->addWidget(r_line1); result_layout->addWidget(r_line2); result_layout->addWidget(r_list); //r_line1->hide(); //r_line2->hide(); //r_list->hide(); searchResults->setLayout(result_layout); addDockWidget(Qt::BottomDockWidgetArea, searchDock); } /* Click "ok" will search tables in database. */ void SearchPatient::startSearch() { if (s_inputLn->text().isEmpty()) { QMessageBox::critical(0, "Error", "Search aborted: no input string found."); return; } if (searchPart->isChecked() && !currentPatients.size()) { QMessageBox::critical(0, "Error", "Search aborted: no patients found yet."); return; } patientSearchTags ps_tags; setTags(ps_tags); vector pmList; int search_stat = dbcp->reqSearchPatient(ps_tags, pmList); if (search_stat) { QMessageBox::critical(0, "Error", "Patient search failed."); return; } currentPatients.clear(); for (unsigned i = 0; i < pmList.size(); i++) currentPatients.push_back(pmList[i].patientID); showMatches(pmList); } // Set patient search tags void SearchPatient::setTags(patientSearchTags &tags_out) { int field_index = s_field->currentIndex(); if (field_index == 0) tags_out.scoreName=""; else tags_out.scoreName = searchScoreIDs[field_index -1]; tags_out.relationship = s_relation->currentText().toStdString(); tags_out.searchStr = s_inputLn->text().toStdString(); if (insensButt->isChecked()) tags_out.case_sensitive = false; else tags_out.case_sensitive = true; if (searchPart->isChecked()) tags_out.patientIDs = currentPatients; } /* This function shows search results in the dock window. */ void SearchPatient::showMatches(const vector& pmList) { QString reqStr = "" + s_field->currentText() + " " + s_relation->currentText() + " " + s_inputLn->text(); if (insensButt->isChecked()) reqStr.append(" (case insensitive)"); reqStr.append(""); if (optBox1->isEnabled() && searchPart->isChecked()) reqStr = r_line1->text() + " AND " + reqStr; else reqStr = "Search Request: " + reqStr; r_line1->setText(reqStr); int p_no = currentPatients.size(); QString p_no_str; if (p_no < 2) p_no_str = QString::number(p_no) + " patient found"; else p_no_str = QString::number(p_no) + " patients found"; r_line2->setText("Search Results: " + p_no_str); // Remove current elements in r_list if (r_list->count()) r_list->clear(); if (p_no == 0) { optBox1->setEnabled(false); return; } // Add the current matches for (unsigned i = 0; i < pmList.size(); i++) { QString itemStr = "Patient " + QString::number(currentPatients[i]) + ": "; string tmpStr; map::const_iterator it; unsigned j = 0; for (it = pmList[i].scoreMap.begin(); it != pmList[i].scoreMap.end(); ++it) { tmpStr.append(it->first); tmpStr.append("="); tmpStr.append(it->second); if (j < pmList[i].scoreMap.size() - 1) tmpStr.append(", "); j++; } r_list->addItem(itemStr + QString::fromStdString(tmpStr)); } if (r_list->count()) optBox1->setEnabled(true); } /* Click "reset" will clear up all input data on the form. */ void SearchPatient::clickReset() { s_field->setCurrentIndex(0); s_relation->setCurrentIndex(0); s_inputLn->clear(); } /* CLick "cancel" will close the curent interface. */ void SearchPatient::clickCancel() { close(); } /* This slot replies click of any patient item in list widget. */ void SearchPatient::showOnePatient() { int pIndex = r_list->currentRow(); int32 pID = currentPatients[pIndex]; // Ask DBview to retrieve all scores of a certain patient // DBpatient myPatient; //int stat = dbcp->reqOnePatient(pID, myPatient); // Make sure patient score values are retrieved successfully //if (stat) { // QMessageBox::critical(0, "Error", "Failed to get patient score values."); // return; //} // populate DBpatient data based on lists of DBscorevalue and DBsession DBview *pview = new DBview(dbcp, pID); //pview->patient = &myPatient; pview->layout_view("patient"); pview->show(); } /* This function checks whether an input string is already an element of the input string vector. * If it is, return false; otherwise true. */ bool isNewElement(vector inputArray, string inputStr) { for (uint i = 0; i < inputArray.size(); i++) { if (inputArray[i] == inputStr) return false; } return true; } /* This function checks whether an input integer is already an element of the input integer vector. * If it is, return false; otherwise true. */ bool isNewElement(vector inputArray, int inputInt) { for (uint i = 0; i < inputArray.size(); i++) { if (inputArray[i] == inputInt) return false; } return true; } voxbo-1.8.5~svn1246/client/searchPatient.h000066400000000000000000000061601153177201300203500ustar00rootroot00000000000000 // searchPatient.h // Copyright (c) 2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu /**************************************************************************** ** ** Header of searchPatient interface. ** ****************************************************************************/ #ifndef SEARCHPATIENT_H #define SEARCHPATIENT_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "db_util.h" #include "dbclient.h" class SearchPatient : public QMainWindow { Q_OBJECT public: SearchPatient(DBclient *c); void setupUI(); void addTitle(); void addSearch(); void addButtons(); void setDockWindow(); void setTags(patientSearchTags &); void showMatches(const vector &); public slots: void startSearch(); void clickReset(); void clickCancel(); void showOnePatient(); public: DBclient* dbcp; QScrollArea *mainArea; QWidget *sp_ui; QVBoxLayout *spLayout; QComboBox *s_field; QComboBox *s_relation; QLineEdit *s_inputLn; QGroupBox *optBox1; QRadioButton *searchAll, *searchPart; QRadioButton *sensButt, *insensButt; QWidget *searchResults; QLabel *r_line1, *r_line2; QListWidget *r_list; vector searchScoreIDs; // FIXME dan changed this from int32 to string -- ok? vector currentPatients; //string dbHome, scoreValueDbName, sessionDbName; //string adminDbName, pidStr, patientDbName; }; bool isNewElement(vector, string); bool isNewElement(vector, int32); /* class ShowPatient : public QMainWindow */ /* { */ /* Q_OBJECT */ /* public: */ /* ShowPatient(int, vector); */ /* int showPatientInfo(int, vector); */ /* void addScoreInfo(string, string); */ /* string dbHome, scoreDbName, scoreValueDbName; */ /* QScrollArea *mainArea; */ /* QWidget *main_ui; */ /* QVBoxLayout *mainLayout; */ /* }; */ #endif voxbo-1.8.5~svn1246/client/test.cpp000066400000000000000000000067161153177201300170770ustar00rootroot00000000000000 #include #include #include #include #include #include #include "mydefs.h" #include "dbview.h" #include "vbview.h" #include "dbmainwindow.h" #include using namespace std; using boost::format; //void read_types(); //void read_scorenames(); void read_scoredata(DBpatient &pt); // GLOBALS for this test program int f_writable=0; localClient client; Q_IMPORT_PLUGIN(qjpeg) Q_IMPORT_PLUGIN(qgif) Q_IMPORT_PLUGIN(qtiff) int main(int argc,char **argv) { QList foo=QImageReader::supportedImageFormats(); vbforeach (QByteArray &xx,foo) cout << xx.constData() << endl; // parse command line args for testing purposes tokenlist args; args.Transfer(argc-1,argv+1); for (int i=0; ilayout_view("test"); // view->layout_view("newpatient"); // view->layout_view("oldpatient"); app.exec(); exit(0); } void read_scoredata(DBpatient &pt) { FILE *fp; tokenlist toks; char buf[1024]; int sessionid=0; if ((fp=fopen("patientdata.txt","r"))==NULL) return; while (fgets(buf,1023,fp)) { toks.ParseLine(buf); if (toks[0][0]=='#') continue; if (toks[0][0]=='%') continue; if (toks[0][0]=='!') continue; if (toks[0][0]==';') continue; if (toks[0]=="session") { sessionid=strtol(toks[1]); continue; } // at this point, must be a score line if (toks.size()!=4) continue; DBscorevalue sv; sv.id=strtol(toks(1),NULL,10); sv.parentid=strtol(toks(2),NULL,10); sv.scorename=toks[0]; // find datatype via scorename if (client.dbs.scorenames.count(sv.scorename)) { DBscorename &sn=client.dbs.scorenames[sv.scorename]; sv.datatype=sn.datatype; } else { cout << "unknown scorename " << sv.scorename << endl; sv.datatype="string"; } // all data in test file are strings or dates //cout << " sname: " << sv.scorename << endl; //cout << " type: " << sv.datatype << endl; //cout << " tok3: " << toks[3] << endl; if(toks[3].size()) { char tmps[toks[3].size()+1]; strcpy(tmps,toks(3)); //cout << " tmps: " << tmps << endl; sv.deserialize((uint8 *)tmps,strlen(tmps)+1); } //sv.v_string=toks[3]; //cout << "string: " << sv.v_string << endl; //cout << " date: " << sv.v_date.getDateStr() << endl << endl; // etc. sv.sessionid=sessionid; if (f_writable) sv.permission="rw"; else sv.permission="r"; // map id to the actual score pt.scores[sv.id]=sv; // add to parent-children multimap for this patient's scores pt.children.insert(pair(sv.parentid,sv.id)); // multimap score name id (e.g., id of "scan:type") to instances pt.names.insert(pair(sv.scorename,sv.id)); // multimap session ids to tests if (sv.parentid==0) pt.sessiontests.insert(pair(sv.sessionid,sv.id)); } fclose(fp); } voxbo-1.8.5~svn1246/client/test_scorenames.txt000066400000000000000000000030711153177201300213420ustar00rootroot00000000000000 # this is a test scorenames.txt file scan stub scan:type scan_type scan:date date scan:tech string scan:nicescan bool #scan:notes shortstring #scan:foobar stub #scan:foobar:xxx scan_type #scan:foobar:yyy scan_type #scan:foobar:zzz stub #scan:foobar:zzz:a shortstring #scan:foobar:zzz:b shortstring #scan:foobar:zzz:c shortstring scan:lesion stub scan:lesion:size integer scan:lesion:side side_type scan:lesion:location lesion_location demographics stub demographics:firstname shortstring demographics:lastname shortstring demographics:DOB date demographics:adefault shortstring default "your a default here" demographics:bdefault shortstring default "some b stuff" demographics:nodefault shortstring demographics:phonenumber shortstring demographics:sampletime time demographics:sampledate date demographics:sampledatetime datetime simpletest stub simpletest:datetime datetime repeating simpletest:combo scan_type simpletest:string string repeating simpletest:text text repeating simpletest:integer integer simpletest:float float simpletest:image image simpletest:brainimage brainimage forms stub forms forms:posttest repeating forms:posttest:notes_from_coordinator text default "please fill this out" forms:posttest:deadline date forms:posttest:experimenter string default "your name here" forms:posttest:date date forms:posttest:payment stub repeating forms:posttest:payment:for string forms:posttest:payment:amount string default "enter amount paid here" forms:posttest:tests test_type customizable repeating forms:posttest:payment_for_that string default "enter amount paid here" voxbo-1.8.5~svn1246/client/test_types.txt000066400000000000000000000005411153177201300203460ustar00rootroot00000000000000 scan_type description type of the scan scan_type MRI scan_type MRA scan_type CT scan_type flatbed scan_type once-over scan_type expensive side_type description side of the injury side_type left side_type right side_type middle lesion_location description location of the lesion lesion_location here lesion_location there lesion_location everywhere voxbo-1.8.5~svn1246/client/test_views.txt000066400000000000000000000011471153177201300203420ustar00rootroot00000000000000 # this is a sample views.txt file # here is an existing patient view patient newtab Patient Summary patient banner todaysdate space username patient sessionlist patient testlist # here is a new patient view newpatient banner todaysdate space username newpatient test simpletest # here is my simple four-tab test view test newtab bssd test banner todaysdate space username test test scan test test scan:type test test demographics test newtab sdata test session 10101 test session 10102 test newtab simple test test simpletest test newtab all sessions test sessionlist test newtab all tests test testlist voxbo-1.8.5~svn1246/configure.py000077500000000000000000000071501153177201300164650ustar00rootroot00000000000000#!/usr/bin/python from optparse import OptionParser import sys,os,glob # possible targets include: all, db, vlsm, spm def printhelp(): print " " print "VoxBo configuration script (configure.py)" print "summary: script for running simple VLSM analyses" print "usage:" print " configure [] []" print "arguments include any combination of the following:" print " -a find target directory automatically" print " -s build shared libraries (default: static)" print " --nox skip X-based stuff" print " vlsm build just the VLSM-relevant binaries" print " spm build just the SPM-relevant binaries" print " nd build the neurodebian package" print " --prefix=PREFIX use PREFIX as the installation prefix" print " --bindir=BINDIR use BINDIR as the binary installation location" print " --libdir=LIBDIR use LIBDIR as the library installation location" print "notes:" print " This script was not created with autoconf!" print " " parser=OptionParser() #usage="usage: %prog options...") parser.add_option("--prefix",dest="PREFIX",default="",help="installation prefix") parser.add_option("--bindir",dest="BINDIR",default="",help="binary installation path") parser.add_option("--libdir",dest="LIBDIR",default="",help="library installation path") parser.add_option("--nox",dest="nox",action="store_true",default=False,help="skip x stuff") parser.add_option("-a","--autodir",dest='autodir',action="store_true",default=False,help="find install dir automatically") parser.add_option("-s","--shared",dest='shared',action="store_true",default=False,help="build shared libs [default: static]") parser.add_option("-p","--package",dest="package",default="all",help="which package to build") parser.remove_option("-h") parser.add_option("-h","--help",dest="helpflag",action="store_true",default=False,help="help") (opts,args)=parser.parse_args() if opts.helpflag: printhelp() sys.exit(0) for arg in args: opts.package=arg optstring="" if opts.nox: optstring+="VB_NOX=1\n" if opts.package=="neurodebian" or opts.package=="nd": print "Configured NeuroDebian subpackage" # opts.shared=True optstring+="VB_TARGET?=spm\n" elif opts.package=="spm": print "Configured SPM subpackage" optstring+="VB_TARGET?=spm\n" elif opts.package=="vlsm": print "Configured VLSM subpackage" optstring+="VB_TARGET?=vlsm\n" elif opts.package=="db": print "Configured DB subpackage" optstring+="VB_TARGET?=db\n" else: print "Configured full package" if opts.shared: print "Configured to build shared VoxBo libraries" optstring+="VB_SHARED=1\n" else: print "Configured to build static VoxBo libraries" if (len(opts.BINDIR)): optstring+="VB_BINDIR="+opts.BINDIR+"\n" if (len(opts.LIBDIR)): optstring+="VB_LIBDIR="+opts.LIBDIR+"\n" # autodir: if no prefix specified, look around if len(opts.PREFIX): optstring+="VB_PREFIX="+opts.PREFIX+"\n" print "Using prefix",opts.PREFIX elif opts.autodir: prefix="." if (len(opts.PREFIX)): prefix=opts.PREFIX else: a=glob.glob("/usr/local/[Vv]ox[Bb]o") a=a+glob.glob(os.environ['HOME']+"/[Vv]ox[Bb]o") a=a+glob.glob("../bin") for pref in a: if os.access(pref+"/bin",os.W_OK): prefix=pref break optstring+="VB_PREFIX="+prefix+"\n" print "Using prefix",prefix if optstring=="" and os.access("make_vars.txt",os.F_OK): os.unlink("make_vars.txt") if optstring!="": f=open("make_vars.txt","w") f.write(optstring) f.close() voxbo-1.8.5~svn1246/crunch/000077500000000000000000000000001153177201300154065ustar00rootroot00000000000000voxbo-1.8.5~svn1246/crunch/Makefile000066400000000000000000000070371153177201300170550ustar00rootroot00000000000000 # Makefile for crunch -include ../make_vars.txt include ../make_stuff.txt # object files for the executables TESTOBJECTS = test.o VBMM2OBJECTS = vbmm2.o VOXSURFOBJECTS = voxsurf.o MGLMOBJECTS = vbmakeglm.o REALIGNOBJECTS = realign.o realignutils.o utils.o smoothutils.o matrixutils.o\ crunchcube.o SMOOTHOBJECTS = utils.o smoothutils.o matrixutils.o crunchcube.o NORMOBJECTS = norm.o realignutils.o utils.o smoothutils.o matrixutils.o\ norm_utils.o norm_main.o norm_brainwarp.o crunchcube.o PERFMASKOBJECTS = perfmask.o realignutils.o utils.o smoothutils.o matrixutils.o\ norm_utils.o norm_main.o norm_brainwarp.o crunchcube.o # miscellaneous flags and such INCDIRS += -I/usr/local/include/octave LIBDIRS += -L/usr/local/lib/octave LIBS =$(LDFLAGS) $(LIBDIRS) -lm -lvbglm -lvbprefs -lvbio -lvbutil -lz -lpng $(DLLIB) $(GSL_LIBS) OCTLIBS = $(LIBS) -loctave -lcruft $(FORTLIB) ALLBINS=vbmm2 vbmakeglm vbmakefilter #realign norm ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else ifeq ($(VB_TARGET),spm) BINS=$(ALLBINS) else BINS= endif # the main targets all: $(BINS) install: ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) # rule to build the libvoxbo libraries $(VBLIBS): +make -C ../lib $@ # THE EXECUTABLES realign: $(REALIGNOBJECTS) $(VBLIBS) $(CXX) -o realign $(REALIGNOBJECTS) $(OCTLIBS) smooth: $(SMOOTHOBJECTS) $(VBLIBS) $(CXX) -o smooth $(SMOOTHOBJECTS) $(LIBS) test: $(TESTOBJECTS) $(VBLIBS) $(CXX) -o vbtest $(TESTOBJECTS) $(LIBS) norm: $(NORMOBJECTS) $(VBLIBS) $(CXX) -o norm $(NORMOBJECTS) $(OCTLIBS) perfmask: $(PERFMASKOBJECTS) $(VBLIBS) $(CXX) -o perfmask $(PERFMASKOBJECTS) $(LIBS) vbmakeglm: $(MGLMOBJECTS) $(VBLIBS) $(CXX) -o vbmakeglm $(MGLMOBJECTS) -lvbprefs $(LIBS) vbmakefilter: vbmakefilter.o $(VBLIBS) $(CXX) -o vbmakefilter vbmakefilter.o -lvbprefs $(LIBS) vbmm2: $(VBMM2OBJECTS) $(VBLIBS) $(CXX) -o vbmm2 $(VBMM2OBJECTS) $(LIBS) $(GSL_LIBS) # THE TOPLEVEL OBJECTS vbmm2.o: vbmm2.cpp $(VBLIBS) $(CXX) -c -o vbmm2.o vbmm2.cpp $(CXXFLAGS) vbmakeglm.o: vbmakeglm.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o vbmakeglm.o vbmakeglm.cpp $(CXXFLAGS) vbmakefilter.o: vbmakefilter.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o vbmakefilter.o vbmakefilter.cpp $(CXXFLAGS) realign.o: realign.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o realign.o realign.cpp $(CXXFLAGS) smooth.o: smooth.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o smooth.o smooth.cpp $(CXXFLAGS) voxsurf.o: voxsurf.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o voxsurf.o voxsurf.cpp $(CXXFLAGS) $(VSFLAGS) test.o: test.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o test.o test.cpp $(CXXFLAGS) norm.o: norm.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o norm.o norm.cpp $(CXXFLAGS) perfmask.o: perfmask.cpp vbcrunch.h $(VBLIBS) $(CXX) -c -o perfmask.o perfmask.cpp $(CXXFLAGS) # THE UTIL OBJECTS realignutils.o: realignutils.cpp vbcrunch.h $(CXX) -c -o realignutils.o realignutils.cpp $(CXXFLAGS) smoothutils.o: smoothutils.cpp vbcrunch.h $(CXX) -c -o smoothutils.o smoothutils.cpp $(CXXFLAGS) utils.o: utils.cpp vbcrunch.h $(CXX) -c -o utils.o utils.cpp $(CXXFLAGS) matrixutils.o: matrixutils.cpp vbcrunch.h $(CXX) -c -o matrixutils.o matrixutils.cpp $(CXXFLAGS) crunchcube.o: crunchcube.cpp vbcrunch.h $(CXX) -c -o crunchcube.o crunchcube.cpp $(CXXFLAGS) norm_main.o: norm_main.cpp vbcrunch.h $(CXX) -c -o norm_main.o norm_main.cpp $(CXXFLAGS) norm_utils.o: norm_utils.cpp vbcrunch.h $(CXX) -c -o norm_utils.o norm_utils.cpp $(CXXFLAGS) norm_brainwarp.o: norm_brainwarp.cpp vbcrunch.h $(CXX) -c -o norm_brainwarp.o norm_brainwarp.cpp $(CXXFLAGS) voxbo-1.8.5~svn1246/crunch/crunchcube.cpp000066400000000000000000000044251153177201300202400ustar00rootroot00000000000000 // crunchcube.cpp // methods for the CrunchCube class, derived from Cube for purposes // of crunching // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbcrunch.h" CrunchCube::CrunchCube() { Init(); } void CrunchCube::Init() { transform.resize(6); transform.fill(0.0); dimx = dimy = dimz = 0; voxsize[0]=voxsize[1]=voxsize[2]=0.0; scl_slope=1.0; scl_inter=0.0; origin[0]=origin[1]=origin[2]=0; M.resize(0,0); savedM.resize(0,0); M1.resize(0,0); datasize=offset=voxels=0; datatype=vb_short; header.clear(); data = (unsigned char *)NULL; header_valid=data_valid=0; } CrunchCube::CrunchCube(const Cube &old) { Init(); dimx = old.dimx; dimy = old.dimy; dimz = old.dimz; origin[0] = old.origin[0]; origin[1] = old.origin[1]; origin[2] = old.origin[2]; scl_slope=old.scl_slope; scl_inter=old.scl_inter; voxsize[0] = old.voxsize[0]; voxsize[1] = old.voxsize[1]; voxsize[2] = old.voxsize[2]; datatype = old.datatype; datasize = old.datasize; offset=old.offset; voxels = old.voxels; header_valid = old.header_valid; data_valid = old.data_valid; header = old.header; if (old.data && old.voxels > 0) { data = new unsigned char[voxels*datasize]; if (!data) { fprintf(stderr,"vbcrunch failed to allocate space for a cube\n"); exit(5); } memcpy(data,old.data,voxels*datasize); } else data = (unsigned char *)NULL; } voxbo-1.8.5~svn1246/crunch/matrixutils.cpp000066400000000000000000000110151153177201300204750ustar00rootroot00000000000000 // matrixutils.cpp // various matrix manipulation primitives // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbcrunch.h" // dan_linspace() // seems to work RowVector dan_linspace(double first,double last,int points) { double increment; RowVector result(points); int i; increment = (last-first)/(points-1); for(i=0; i to.rows()-1) { to_mi=0; to_ni++; } if (from_mi > from.rows()-1) { from_mi=0; from_ni++; } } } // diff() // seems to work Matrix diff(const Matrix &m) { Matrix tmpm(m.rows()-1,m.cols()); int i,j; for(i=0; in > 1) // cerr << "argh!" << endl // QR = m_get(A->m,A->n); // QR = m_copy(A,QR); // diag = v_get(A->n); // QRfactor(QR,diag); // /* set values of b here */ // x = QRsolve(QR,diag,b,NULL); // tmp=m_get(x->dim,1); // set_col(tmp,0,x); // return tmp; // } // } // vectorize() RowVector vectorize(const Matrix &in) { RowVector res(in.rows()*in.cols()); int i,j,k; k=0; for (i=0; i. // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // written to accomplish the same thing as some original IDL code by // Geoff Aguirre using namespace std; #include #include #include #include #include "vbutil.h" #include "vbjobspec.h" #include "vbprefs.h" #include "vbio.h" #include VBPrefs vbp; class FilterParams { public: string exofiltname; string noisename; int lows,highs; // low and high frequencies to remove vector middles; // middle frequencies to remove string kernelname; // temporal smoothing kernel double kerneltr; // sampling interval of kernel file string noisemodel; // noise model int pri; double TR; int orderg; int init(tokenlist &args); int MakeNoise(); int MakeExoFilt(); }; void MCopy(VB_Vector &c,Vec &vec); void MCopy(Vec &vec,VB_Vector &c); void vbmakefilter_help(); void vbmakefilter_version(); int main(int argc,char **argv) { tokenlist args; args.Transfer(argc-1,argv+1); if (args.size() == 0) { vbmakefilter_help(); exit(0); } if (args[0]=="-h") { vbmakefilter_help(); exit(0); } if (args[0]=="-v") { vbmakefilter_version(); } FilterParams fp; if (fp.init(args)) exit(5); if (fp.MakeNoise()) exit(6); if (fp.MakeExoFilt()) exit(7); exit(0); } // this is the sole constructor, it chews on the passed arguments int FilterParams::init(tokenlist &args) { exofiltname=""; noisename=""; lows=highs=0; middles.clear(); kernelname=""; kerneltr=2000.0; noisemodel=""; pri=2; TR=2000.0; orderg=100; for (int i=0; i1) kerneltr=strtod(tmpl[1]); } printf("[I] vbmakefilter: using kernel TR of %.2f\n",kerneltr); } printf("[I] vbmakefilter: using data TR of %.2f\n",TR); for (i=0; i 0) { if (IRF.ReadFile(kernelname.c_str())) { printf("[E] vbmakefilter: couldn't read kernel file %s\n",kernelname.c_str()); return 101; // error! } } // interpolate the HRF to the resolution of your data if (kernelname.size()>0 && TR != kerneltr) { IRF=cspline_resize(IRF,kerneltr/TR); } // set exofilt to irf padded with zeros, scaled if (IRF.getLength()) { total=0.0; for (i=0; i<(int)IRF.getLength(); i++) { exofilt[i]=IRF[i]; total+=IRF[i]; } total /= orderg; for (i=0; infreq) continue; realp(i+1)=imagp(i+1)=0.0; realp(orderg-i-1)=imagp(orderg-i-1)=0.0; } } for (size_t m=0; mnfreq) continue; realp(middles[m])=imagp(middles[m])=0.0; int ind=orderg-middles[m]; realp(ind)=imagp(ind)=0.0; } if (highs) { for (i=0; i create exofilt\n"); printf(" -i create intrinsic noise model\n"); printf(" -t how many TRs\n"); printf(" -lf low frequencies to remove\n"); printf(" -mf other frequencies to remove\n"); printf(" -hf high frequencies to remove\n"); printf(" -k convolution kernel for exofilt\n"); printf(" -n 1/f noise model file name\n"); printf(" -h help\n"); printf(" -v version\n"); } void vbmakefilter_version() { printf("VoxBo vb2tes (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/crunch/norm.cpp000066400000000000000000000353211153177201300170710ustar00rootroot00000000000000 // norm.cpp // VoxBo spatial normalization (brain warping) module // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // note that the guts of the underlying code were based on SPM96b // source code written for MATLAB by John Ashburner using namespace std; #include "vbcrunch.h" class Norm { private: string imagename; // name of the image to be normalized string refname; // name of the reference image string paramname; // name of param file to read or write string outname; // name of file to write string zname; // file with the z dimension we want tokenlist args; // structure to be used for argument parsing enum {calc,apply} mode; Matrix affine,dims,MF,transform; Matrix bb; RowVector vox; int affineonly; public: Norm(int argc,char **argv); ~Norm(); void init(); void guessvoxandbb(double v0,double v1,double v2); int Crunch(); int CalcParams(); int WriteParams(); int ReadParams(); int NormalizeFile(); void SetOutName(); void SetParamsName(); int Norm3D(const string &filename); int Norm4D(const string &filename); }; void norm_help(); int main(int argc,char *argv[]) { tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs norm_help(); exit(0); } Norm *nn=new Norm(argc,argv); // init norm object, parse args if (!nn) { printf("norm error: couldn't allocate a tiny Norm structure\n"); exit(5); } int err=nn->Crunch(); // do the crunching delete nn; // clean up exit(err); } void Norm::init() { mode=apply; bb.resize(2,3); vox.resize(3); // defaults bb(0,0) = 0; bb(1,0) = 0; bb(0,1) = 0; bb(1,1) = 0; bb(0,2) = 0; bb(1,2) = 0; vox(0) = 0; vox(1) = 0; vox(2) = 0; imagename=""; refname=""; paramname=""; outname=""; affineonly=0; } void Norm::guessvoxandbb(double v0,double v1,double v2) { // if we don't have voxel sizes, use the one passed (from the first file) if (vox(0) == 0) { vox(0)=v0; vox(1)=v1; vox(2)=v2; } if (zname.size()) { Cube cb; cb.ReadFile(zname); if (cb.data_valid) { // vox(0)=cb.voxsize[0]; // vox(1)=cb.voxsize[1]; vox(2)=cb.voxsize[2]; } else printf("norm: warning: 3D file specified with -z couldn't be read\n"); } // if we don't have a bounding box, make an educated guess if (bb(0,0) == 0) { bb(0,0) = -floor(76.0/vox(0)) * vox(0); bb(1,0) = floor(77.0/vox(0)) * vox(0); bb(0,1) = -floor(114.0/vox(1)) * vox(1); bb(1,1) = floor(77.0/vox(1)) * vox(1); bb(0,2) = -floor(45.0/vox(2)) * vox(2); bb(1,2) = floor(87.0/vox(2)) * vox(2); } } Norm::Norm(int argc,char *argv[]) { init(); for (int i=1; iheader=image.header; // FIXME below lines removed due to odd ob1 origins // newimage->origin[0]--; // newimage->origin[1]--; // newimage->origin[2]--; struct tm *mytm; // when normed time_t mytime; // " char tmp[STRINGLEN],timestring[STRINGLEN]; mytime = time(NULL); mytm = localtime(&mytime); strftime(timestring,STRINGLEN,"%d%b%Y_%T",mytm); sprintf(tmp,"Normalized by norm:\t%s",timestring); newimage->AddHeader(tmp); sprintf(tmp,"Normalization parameters:\t%s",paramname.c_str()); newimage->AddHeader(tmp); sprintf(tmp,"Original voxel sizes:\t%.4f\t%.4f\t%.4f",image.voxsize[0],image.voxsize[1], image.voxsize[2]); newimage->AddHeader(tmp); sprintf(tmp,"Bounding box:\t%.4f %.4f %.4f %.4f %.4f %.4f",bb(0,0),bb(1,0),bb(0,1), bb(1,1),bb(0,2),bb(1,2)); newimage->AddHeader(tmp); newimage->SetFileName(outname); newimage->SetFileFormat(image.GetFileFormat()); newimage->WriteFile(); delete newimage; return (0); // no error! } int Norm::NormalizeFile() { int errcount = 0; for (int i=0; iReadFile(filename); newtes = (Tes *)NULL; if (!mytes->data_valid) { printf("norm: invalid tes file: %s\n",filename.c_str()); delete mytes; return 200; // panic and exit } guessvoxandbb(mytes->voxsize[0],mytes->voxsize[1],mytes->voxsize[2]); // are we going to use o1o2o3? if (mytes->origin[0] == 0 && mytes->origin[1] == 0 && mytes->origin[2] == 0) { o1 = mytes->dimx; o2 = mytes->dimy; o3 = mytes->dimz; guessorigin(o1,o2,o3); mytes->SetOrigin(o1,o2,o3); } else { o1 = mytes->origin[0]; o2 = mytes->origin[1]; o3 = mytes->origin[2]; } int interval = (int)(mytes->dimt / 20); if (interval < 1) interval = 1; for (int i=0; idimt; i++) { CrunchCube mycube; mytes->getCube(i,mycube); // now normalize it mycube.origin[0]++; mycube.origin[1]++; mycube.origin[2]++; newcube = dan_write_sn(&mycube,affine,dims,transform,MF,bb,vox,5,affineonly); // FIXME below lines removed due to odd origins, should be double-checked // newcube->origin[0]--; // newcube->origin[1]--; // newcube->origin[2]--; if (!newtes) { // if we haven't allocated the new tes yet newtes = new Tes(); newtes->SetVolume(newcube->dimx,newcube->dimy,newcube->dimz,mytes->dimt, newcube->datatype); newtes->SetVoxSizes(vox(0),vox(1),vox(2)); newtes->origin[0]=newcube->origin[0]; newtes->origin[1]=newcube->origin[1]; newtes->origin[2]=newcube->origin[2]; if (!newtes->data) { delete mytes; delete newcube; printf("norm: error: couldn't allocate space for the normalized image\n"); return(1); } newtes->header=mytes->header; } newtes->SetCube(i,newcube); // bang it back into the tes delete newcube; if ((i+1) % interval == 0) printf("Percent done: %d\n",(i*100)/mytes->dimt); fflush(stdout); } mytime = time(NULL); mytm = localtime(&mytime); strftime(timestring,STRINGLEN,"%d%b%Y_%T",mytm); sprintf(tmp,"Normalized by norm:\t%s",timestring); newtes->AddHeader(tmp); sprintf(tmp,"Normalization parameters:\t%s",paramname.c_str()); newtes->AddHeader(tmp); sprintf(tmp,"Original voxel sizes:\t%.4f\t%.4f\t%.4f",mytes->voxsize[0],mytes->voxsize[1], mytes->voxsize[2]); newtes->AddHeader(tmp); sprintf(tmp,"Bounding box:\t%.4f %.4f %.4f %.4f %.4f %.4f",bb(0,0),bb(1,0),bb(0,1), bb(1,1),bb(0,2),bb(1,2)); newtes->AddHeader(tmp); newtes->SetFileName(outname); newtes->SetFileFormat(mytes->GetFileFormat()); int err=newtes->WriteFile(); delete mytes; delete newtes; return(err); } int Norm::ReadParams() { int m,n,trows,tcols,i; affine.resize(4,4); dims.resize(6,3); MF.resize(4,4); VB_Vector vv(paramname); if (!vv.valid) return(FALSE); i=0; for(n=0; n<4; n++) for(m=0; m<4; m++) { affine(m,n) = vv[i++]; } for(n=0; n<3; n++) for(m=0; m<6; m++) { dims(m,n)=vv[i++]; } for(n=0; n<4; n++) for(m=0; m<4; m++) { MF(m,n)=vv[i++]; } trows=(int)vv[i++]; tcols=(int)vv[i++]; transform.resize(trows,tcols); for(n=0; n<(int)tcols; n++) for(m=0; m<(int)trows; m++) { transform(m,n)=vv[i++]; } return TRUE; } int Norm::WriteParams() { int totallen,m,n,trows,tcols; char timestring[STRINGLEN]; FILE *fp; struct tm *mytm; // when normed time_t mytime; // " // doesn't use standard vec writing code, just rolls its own if ((fp=fopen(paramname.c_str(),"w"))==NULL) { printf("norm: couldn't write parameter file %s\n",paramname.c_str()); return (100); } fprintf(fp,";VB98\n;REF1\n;\n"); mytime = time(NULL); mytm = localtime(&mytime); strftime(timestring,STRINGLEN,"%d%b%Y_%T",mytm); fprintf(fp,"; Normalization parameters calculated %s\n",timestring); fprintf(fp,"; Template image: %s\n",refname.c_str()); fprintf(fp,"; Image image: %s\n",imagename.c_str()); // total size of param file should be 16 + 18 + 16 + 2 + len(transform) totallen = 16 + 18 + 16 + 2 + (transform.rows() * transform.cols()); for(n=0; n<4; n++) for(m=0; m<4; m++) fprintf(fp,"%.8f\n",(double)affine(m,n)); for(n=0; n<3; n++) for(m=0; m<6; m++) fprintf(fp,"%.8f\n",(double)dims(m,n)); for(n=0; n<4; n++) for(m=0; m<4; m++) fprintf(fp,"%.8f\n",MF(m,n)); trows = (int)transform.rows(); tcols = (int)transform.cols(); fprintf(fp,"%d\n",transform.rows()); fprintf(fp,"%d\n",transform.cols()); transform.resize((int)trows,(int)tcols); for(n=0; n refimage is the reference image\n"); printf(" -o set the name for the normalized data\n"); printf(" -p set the name for the param file to be read/written\n"); printf(" -v desired voxel sizes\n"); printf(" -z filename with desired z voxel size\n"); printf(" -bb bounding box\n"); printf(" -a affine transformation only\n"); printf("examples:\n"); printf("To calculate params:\n"); printf(" norm -calc -r template.cub -p myparams.ref myanatomy.cub\n"); printf("To apply those params\n"); printf(" norm -apply -o nfunc.cub -p myparams.ref func.cub\n"); printf("\n"); } voxbo-1.8.5~svn1246/crunch/norm_brainwarp.cpp000066400000000000000000000455321153177201300211430ustar00rootroot00000000000000 // spm_brainwarp.c 1.8 (c) John Ashburner MRCCU/FIL 96/08/08"; #include #include "vbcrunch.h" extern double floor(), fabs(); // INPUTS // T[3*nz*ny*nx + ni*4] - current transform // dt2 - data type of image to normalize // scale2 - scale factor of image to normalize // dim2[3] - x, y & z dimensions of image to normalize // dat2[dim2[2]*dim2[1]*dim2[0]] - voxels of image to normalize // ni - number of templates // dt1[ni] - data types of templates // scale1[ni] - scale factors of templates // dim1[3] - x, y & z dimensions of templates // dat1[ni*dim1[2]*dim1[1]*dim1[0]] - voxels of templates // nx - number of basis functions in x // BX[dim1[0]*nx]- basis functions in x // dBX[dim1[0]*nx]- derivatives of basis functions in x // ny - number of basis functions in y // BY[dim1[1]*ny]- basis functions in y // dBY[dim1[1]*ny]- derivatives of basis functions in y // nz - number of basis functions in z // BZ[dim1[2]*nz]- basis functions in z // dBZ[dim1[2]*nz]- derivatives of basis functions in z // M[4*4] - transformation matrix // samp[3] - frequency of sampling template. // OUTPUTS // alpha[(3*nz*ny*nx+ni*4)^2] - A'A // beta[(3*nz*ny*nx+ni*4)] - A'b // pss[1*1] - sum of squares difference // pnsamp[1*1] - number of voxels sampled void mrqcof(double T[],double alpha[],double beta[],double pss[],int dt2, double scale2,int dim2[],unsigned char dat2[],int ni,int dt1[], double scale1[],int dim1[],unsigned char *dat1[],int nx,double BX[], double dBX[],int ny,double BY[],double dBY[],int nz,double BZ[], double dBZ[],double M[],int samp[],int *pnsamp) { int i1,i2, s0[3], x1,x2, y1,y2, z1,z2, m1, m2, nsamp = 0, ni4; double dvds0[3],dvds1[3], *dvdt, s2[3], *ptr1, *ptr2, *Tz, *Ty, tmp, *betaxy, *betax, *alphaxy, *alphax, ss=0.0, *scale1a; double *Jz[3][3], *Jy[3][3], J[3][3]; double *bz3[3], *by3[3], *bx3[3]; bx3[0] = dBX; bx3[1] = BX; bx3[2] = BX; by3[0] = BY; by3[1] = dBY; by3[2] = BY; bz3[0] = BZ; bz3[1] = BZ; bz3[2] = dBZ; ni4 = ni*4; /* rate of change of voxel with respect to change in parameters */ dvdt = (double *)calloc( 3*nx + ni4 , sizeof(double)); /* Intermediate storage arrays */ Tz = (double *)calloc( 3*nx*ny , sizeof(double)); Ty = (double *)calloc( 3*nx , sizeof(double)); betax = (double *)calloc( 3*nx + ni4 , sizeof(double)); betaxy = (double *)calloc( 3*nx*ny + ni4 , sizeof(double)); alphax = (double *)calloc((3*nx + ni4)*(3*nx + ni4), sizeof(double)); alphaxy = (double *)calloc((3*nx*ny + ni4)*(3*nx*ny + ni4), sizeof(double)); for (i1=0; i1<3; i1++) { for(i2=0; i2<3; i2++) { Jz[i1][i2] = (double *)calloc(nx*ny, sizeof(double)); Jy[i1][i2] = (double *)calloc(nx , sizeof(double)); } } /* pointer to scales for each of the template images */ scale1a = T + 3*nx*ny*nz; /* only zero half the matrix */ m1 = 3*nx*ny*nz+ni4; for (x1=0;x1=1.0 && s2[0]=1.0 && s2[1]=1.0 && s2[2]dimx; dim1[1] = (int)REF->dimy; dim1[2] = (int)REF->dimz; if (BX.rows() != dim1[0]) cerr << "Wrong sized X basis functions." << endl; nx = BX.cols(); if (dBX.rows() != dim1[0] || dBX.cols() != nx) cerr << "Wrong sized X basis function derivatives." << endl; if (BY.rows() != dim1[1]) cerr << "Wrong sized Y basis functions." << endl; ny = BY.cols(); if (BY.rows() != dim1[1] || dBY.cols() != ny) cerr << "Wrong sized Y basis function derivatives." << endl; if (BZ.rows() != dim1[2]) cerr << "Wrong sized Z basis functions." << endl; nz = BZ.cols(); if (BZ.rows() != dim1[2] || dBZ.cols() != nz) cerr << "Wrong sized Z basis function derivatives." << endl; if ((T.rows()*T.cols()) != 3*nx*ny*nz+ni*4) cerr << "Transform is wrong size." << endl; /* sample about every fwhm/2 */ samp[0] = (int) round(fwhm/2.0/REF->voxsize[0]); samp[0] = (int) ((samp[0]<1) ? 1 : samp[0]); samp[1] = (int) round(fwhm/2.0/REF->voxsize[1]); samp[1] = (int) ((samp[1]<1) ? 1 : samp[1]); samp[2] = (int) round(fwhm/2.0/REF->voxsize[2]); samp[2] = (int) ((samp[2]<1) ? 1 : samp[2]); dat1[0] = REF->data; dt1[0] = REF->datatype; scale1[0] = REF->scl_slope; if (scale1[0]==0.0) scale1[0]=1.0; dat2 = IMAGE->data; dim2[0] = (int)IMAGE->dimx; dim2[1] = (int)IMAGE->dimy; dim2[2] = (int)IMAGE->dimz; dt2 = IMAGE->datatype; scale2 = IMAGE->scl_slope; if (scale2==0.0) scale2=1.0; m = 3*nx*ny*nz+ni*4; alpha = new double[m*m]; beta = new double[m]; var = new double[1]; vBX = arrayize(BX); vBY = arrayize(BY); vBZ = arrayize(BZ); vdBX = arrayize(dBX); vdBY = arrayize(dBY); vdBZ = arrayize(dBZ); vAffine = arrayize(Affine); vT = arrayize(T); mrqcof(vT,alpha,beta,var,dt2,scale2,dim2,dat2, ni,dt1,scale1,dim1,dat1, nx,vBX,vdBX,ny,vBY,vdBY,nz,vBZ,vdBZ, vAffine,samp,&nsamp); free(vBX); free(vBY); free(vBZ); free(vdBX); free(vdBY); free(vdBZ); free(vAffine); free(vT); // alpha ret_m1.resize(m,m); for(i=0; ivoxsize[0]; dims(2,1) = sREF->voxsize[1]; dims(2,2) = sREF->voxsize[2]; dims(3,0) = sREF->origin[0]; dims(3,1) = sREF->origin[1]; dims(3,2) = sREF->origin[2]; dims(4,0) = sIMAGE->dimx; dims(4,1) = sIMAGE->dimy; dims(4,2) = sIMAGE->dimz; dims(5,0) = sIMAGE->voxsize[0]; dims(5,1) = sIMAGE->voxsize[1]; dims(5,2) = sIMAGE->voxsize[2]; delete sIMAGE; delete sREF; return TRUE; } // dan_write_sn.cpp // adapted from SPM96 code: // spm_write_sn.m 1.4 John Ashburner MRCCU/FIL 96/09/11 // c/c++ port by Dan Kimberg CrunchCube * dan_write_sn(CrunchCube *VOL,Matrix &affine,Matrix &dims,Matrix &transform, Matrix &MF,Matrix &bb,RowVector &Vox,int Hold,int affdefault) { Matrix tx,ty,tz; Matrix MP,mtmp,mtmp1,Mult; Matrix basX,basY,basZ,X,Y; RowVector x,y,z,Dim(3,0.0),dv; Matrix X2,Y2,Z2,d; Matrix X1,Y1,Z1,Mask; int i,j,k,l,affine_only,d1,d2,d3,offset; CrunchCube *NEWVOL; offset=0; // used later to keep track of plane as we're writing NEWVOL = new CrunchCube(VOL); MP = dan_get_space_image(VOL); // MP maps this_image -> original_mm // MG maps template -> normalised_mm // MF maps orig_image -> original_mm // Transform maps template -> orig_image // // We want template -> this_image // // Transform MF inv(MP) // template -> orig_image -> original_mm -> this_image // from mm space to voxel space. x = dan_span(bb(0,0),bb(1,0),Vox(0)); for(i=0; i < x.length(); i++) x(i) = (x(i) / dims(2,0)) + dims(3,0); y = dan_span(bb(0,1),bb(1,1),Vox(1)); for(i=0; i < y.length(); i++) y(i) = (y(i) / dims(2,1)) + dims(3,1); z = dan_span(bb(0,2),bb(1,2),Vox(2)); for(i=0; i < z.length(); i++) z(i) = (z(i) / dims(2,2)) + dims(3,2); Dim(0) = x.length(); Dim(1) = y.length(); Dim(2) = z.length(); NEWVOL->voxsize[0] = Vox(0); NEWVOL->voxsize[1] = Vox(1); NEWVOL->voxsize[2] = Vox(2); NEWVOL->resize(x.length(),y.length(),z.length()); NEWVOL->origin[0] = (int)round((-bb(0,0) / Vox(0)) + 1); NEWVOL->origin[1] = (int)round((-bb(0,1) / Vox(1)) + 1); NEWVOL->origin[2] = (int)round((-bb(0,2) / Vox(2)) + 1); // for some reason, can't multiply columnvector by rowvector mtmp.resize(x.length(),1); mtmp1.resize(1,(int)Dim(1)); mtmp.insert(x.transpose(),0,0); mtmp1.fill(1.0); X = mtmp * mtmp1; mtmp.resize((int)Dim(0),1); mtmp1.resize(1,y.length()); mtmp.fill(1.0); mtmp1.insert(y,0,0); Y = mtmp * mtmp1; affine_only = affdefault; // if any zeros, do affine only for(i=0; i < dims.cols(); i++) if (dims(1,i) == 0.0) affine_only = 1; if (affine_only) { basX = zeros(1,1); basY = zeros(1,1); basZ = zeros(1,1); } else { // is the -1 below to compensate for matlab's 1-indexing? or do i need it? basX = dan_dctmtx((int)dims(0,0),(int)dims(1,0),x-1.0); basY = dan_dctmtx((int)dims(0,1),(int)dims(1,1),y-1.0); basZ = dan_dctmtx((int)dims(0,2),(int)dims(1,2),z-1.0); } // affine_only is 0 for test case // Cycle over planes for (j=0; j < z.length(); j++) { // Nonlinear deformations if (!affine_only) { // 2D transforms for each plane d1=(int)dims(1,0); d2=(int)dims(1,1); d3=(int)dims(1,2); ColumnVector cvtmp = basZ.row(j).transpose(); mtmp = reshape(transform.column(0),d1*d2,d3); tx = reshape(mtmp * cvtmp,d1,d2); mtmp = reshape(transform.column(1),d1*d2,d3); ty = reshape(mtmp * cvtmp,d1,d2); mtmp = reshape(transform.column(2),d1*d2,d3); tz = reshape(mtmp * cvtmp,d1,d2); X1 = X + (basX * tx * basY.transpose()); Y1 = Y + (basX * ty * basY.transpose()); Z1 = z(j) + (basX * tz * basY.transpose()); } // try it both ways -- doesn't matter! // Mult = backslash(MP,MF * affine); Mult = backslash(MP,MF) * affine; if (!affine_only) { X2= Mult(0,0)*X1 + Mult(0,1)*Y1 + Mult(0,2)*Z1 + Mult(0,3); Y2= Mult(1,0)*X1 + Mult(1,1)*Y1 + Mult(1,2)*Z1 + Mult(1,3); Z2= Mult(2,0)*X1 + Mult(2,1)*Y1 + Mult(2,2)*Z1 + Mult(2,3); } else { X2= Mult(0,0)*X + Mult(0,1)*Y + (Mult(0,2)*z(j) + Mult(0,3)); Y2= Mult(1,0)*X + Mult(1,1)*Y + (Mult(1,2)*z(j) + Mult(1,3)); Z2= Mult(2,0)*X + Mult(2,1)*Y + (Mult(2,2)*z(j) + Mult(2,3)); } Mask = X2; // just for the size, we're going to overwrite it for(k=0; k < X2.rows(); k++) { for(l=0; l < X2.cols(); l++) { if ((X2(k,l) >= 1-TINY) && (X2(k,l) <= (VOL->dimx+TINY)) && (Y2(k,l) >= 1-TINY) && (Y2(k,l) <= (VOL->dimy+TINY)) && (Z2(k,l) >= 1-TINY) && (Z2(k,l) <= (VOL->dimz+TINY))) Mask(k,l)=1; else Mask(k,l)=0; } } // try it both ways -- doesn't matter! // Mult = backslash(MP,MF * affine); Mult = backslash(MP,MF) * affine; if (!affine_only) { X2= Mult(0,0)*X1 + Mult(0,1)*Y1 + Mult(0,2)*Z1 + Mult(0,3); Y2= Mult(1,0)*X1 + Mult(1,1)*Y1 + Mult(1,2)*Z1 + Mult(1,3); Z2= Mult(2,0)*X1 + Mult(2,1)*Y1 + Mult(2,2)*Z1 + Mult(2,3); } else { X2= Mult(0,0)*X + Mult(0,1)*Y + (Mult(0,2)*z(j) + Mult(0,3)); Y2= Mult(1,0)*X + Mult(1,1)*Y + (Mult(1,2)*z(j) + Mult(1,3)); Z2= Mult(2,0)*X + Mult(2,1)*Y + (Mult(2,2)*z(j) + Mult(2,3)); } d = dan_sample_vol(VOL,X2,Y2,Z2,Hold); for(k=0; k < d.rows(); k++) for(l=0; l < d.cols(); l++) d(k,l) *= Mask(k,l); dv = vectorize(d); // remove because we always use scale=1 // for(k=0; kscalefactor; // bound the non-floating datatypes if (VOL->datatype == vb_byte) dan_bound(dv,(double)0,(double)255); else if (VOL->datatype == vb_short) dan_bound(dv,(double)-32768,(double)32767); else if (VOL->datatype == vb_long) dan_bound(dv,(double)-pow(2.0,32.0),(double)pow(2.0,31.0)-1); // write one plane of data for (k=0; kdatatype == vb_float) ((float *)(NEWVOL->data))[k+offset] = (float) dv(k); else if (VOL->datatype == vb_double) ((double *)(NEWVOL->data))[k+offset] = (double) dv(k); else if (VOL->datatype == vb_long) ((int *)(NEWVOL->data))[k+offset] = (int) dv(k); else if (VOL->datatype == vb_short) ((short *)(NEWVOL->data))[k+offset] = (short) dv(k); else if (VOL->datatype == vb_byte) ((unsigned char *)(NEWVOL->data))[k+offset] = (unsigned char) dv(k); else cerr << "vbcrunch: bad datatype on writing normalized image to cube\n"; } offset += dv.length(); } return NEWVOL; } voxbo-1.8.5~svn1246/crunch/norm_utils.cpp000066400000000000000000000755161153177201300203230ustar00rootroot00000000000000 // norm_utils.cpp // Dan Kimberg, 1998-2002 using namespace std; #include "vbcrunch.h" #include Matrix ret_m1,ret_m2; double ret_d1; void set_element(Matrix &m,int pos,double val); RowVector findnonzero(const Matrix &mat); RowVector findnonzero(const RowVector &vec); void set_elements(Matrix &mat,RowVector &locs,RowVector &vals); void add_elements(RowVector &vec,const RowVector &locs, const ColumnVector &additions); void add_elements(Matrix &mat,const RowVector &locs, const ColumnVector &additions); // dan_affsub1.c // closely based on // spm_affsub1.m 1.1 John Ashburner FIL 96/07/08 // function [alpha, beta, chi2] = spm_affsub1(REF,IMAGE,MG,MF,Hold,samp,P) int dan_affsub1(CrunchCube *REF,CrunchCube *IMAGE,const Matrix &MG,const Matrix &MF, int Hold,int samp,const RowVector &P) { Matrix alpha(13,13,0.0),beta(13,1,0.0),dMdP(13,13,0.0); int skipx,skipy,skipz,i,j,n; Matrix X,Y,Mat; Matrix mtmp1,mtmp2,tmp,dFdM,F,dx,dy,dz; RowVector tP,t0,XM,YM,ZM,mask1,X1,Y1,Z1; double chi2; // Coordinates of templates mtmp1.resize(REF->dimx,REF->dimx); mtmp1.fill(0.0); for(i=0; idimx; i++) mtmp1(i,i)=i+1; mtmp2.resize(REF->dimx,REF->dimy); mtmp2.fill(1.0); X = mtmp1 * mtmp2; // these matrices don't really have to be built again mtmp1.resize(REF->dimx,REF->dimy); mtmp1.fill(1.0); mtmp2.resize(REF->dimy,REF->dimy); mtmp2.fill(0.0); for(i=0; i < REF->dimy; i++) mtmp2(i,i) = i+1; Y = mtmp1 * mtmp2; // Sample about every samp mm skipx = (int)MAX(round(samp/REF->voxsize[0]),1); skipy = (int)MAX(round(samp/REF->voxsize[1]),1); skipz = (int)MAX(round(samp/REF->voxsize[2]),1); RowVector mask0(0); for(i=0; idimz; p+= skipz) { XM = index(X,mask0); YM = index(Y,mask0); //% Transformed template coordinates. X1 = (Mat(0,0) * XM) + (Mat(0,1) * YM) + ((Mat(0,2) * p) + Mat(0,3)); Y1 = (Mat(1,0) * XM) + (Mat(1,1) * YM) + ((Mat(1,2) * p) + Mat(1,3)); Z1 = (Mat(2,0) * XM) + (Mat(2,1) * YM) + ((Mat(2,2) * p) + Mat(2,3)); //% Only resample from within the volume IMAGE. mask1.resize(0); for(i=0; i < X1.length(); i++) { if (X1(i) >=1 && Y1(i) >=1 && Z1(i) >=1 && X1(i) < (IMAGE->dimx - .01) && Y1(i) < (IMAGE->dimy - .01) && Z1(i) < (IMAGE->dimz - .01)) { mask1.resize(mask1.length()+1,i); } } // Don't waste time on an empty plane. if (mask1.length() > 0) { // Only resample from within the volume IMAGE. if (mask1.length() != mask0.length()) { X1 = index(X1,mask1); Y1 = index(Y1,mask1); Z1 = index(Z1,mask1); XM = index(XM,mask1); YM = index(YM,mask1); } dFdM.resize(mask1.length(),13); dFdM.fill(0.0); // Sample image to normalise & get local NEGATIVE derivatives F = dan_sample_vol(IMAGE,X1,Y1,Z1,Hold); dx = (F - dan_sample_vol(IMAGE,X1+.01,Y1,Z1,Hold))/(.01); dy = (F - dan_sample_vol(IMAGE,X1,Y1+.01,Z1,Hold))/(.01); dz = (F - dan_sample_vol(IMAGE,X1,Y1,Z1+.01,Hold))/(.01); // Generate Design Matrix for(i=0; i < dFdM.rows(); i++) { dFdM(i,0) = XM(i) * dx(i,0); dFdM(i,1) = YM(i) * dx(i,0); dFdM(i,2) = p * dx(i,0); dFdM(i,3) = dx(i,0); dFdM(i,4) = XM(i) * dy(i,0); dFdM(i,5) = YM(i) * dy(i,0); dFdM(i,6) = p * dy(i,0); dFdM(i,7) = dy(i,0); dFdM(i,8) = XM(i) * dz(i,0); dFdM(i,9) = YM(i) * dz(i,0); dFdM(i,10)= p * dz(i,0); dFdM(i,11)= dz(i,0); } // Sample reference image(s) ZM.resize(mask1.length()); ZM.fill((double)p); tmp = dan_sample_vol(REF,XM,YM,ZM,Hold); for(i=0; i < dFdM.rows(); i++) dFdM(i,12) = tmp(i,0); for(i=0; i < F.rows(); i++) F(i,0) -= tmp(i,0) * P(12); for(i=0; i < F.rows(); i++) for(j=0; j < F.cols(); j++) chi2 += pow(F(i,j),2); n += F.rows() * F.cols(); //% Most of the work alpha = alpha + dan_atranspa(dFdM); beta = beta + (dFdM.transpose() * F); dFdM.resize(0,0); } } alpha = (dMdP.transpose() * alpha) * dMdP; beta = dMdP.transpose() * beta; // chi2 = chi2/(n - 12 - size(REF,2)); chi2 /= (double)(n-13); ret_m1 = alpha; ret_m2 = beta; ret_d1 = chi2; return TRUE; } // % FORMAT nP = spm_affsub2(REF,IMAGE,MG,MF,Hold,samp,oP,free,pdesc,gorder) // % MG - Space of the template image(s). // % MF - Space of the object image. // % samp - Frequency (in mm) of sampling. // % oP - Old parameter estimates. // % free - Ones and zeros indicating which parameters to fit. // % pdesc - Description of parameters. // % nP - New parameter estimates. // dan_affsub2.c // based closely on // spm_affsub2.m 1.4 John Ashburner FIL 96/08/21 // function P = spm_affsub2(REF,IMAGE,MG,MF,Hold,samp,P,free,pdesc,gorder) RowVector dan_affsub2(CrunchCube *REF,CrunchCube *IMAGE,const Matrix &MG,const Matrix &MF, int Hold,int samp, RowVector P,const RowVector &free,const RowVector &pdesc) { double pchi2,bestchi2,ochi2,chi2_t; int iter,countdown,i,nf; Matrix alpha_t,beta_t,aqqq,mtmp1,mtmp2; RowVector bestP,vtmp,qq,qqq,bqq,pp,ppp; Matrix alpha(P.length(),P.length(),0.0); RowVector beta(P.length(),0.0); ColumnVector cvtmp; pchi2 = 9e99; iter = 1; countdown = 0; bestP = P; bestchi2 = 9e99; while (iter <= 64 && countdown < 3) { ochi2 = pchi2; pchi2 = 1; alpha.fill(0.0); beta.fill(0.0); //% generate alpha and beta //%----------------------------------------------------------------------- // totally unnecessary loop! for (int im = 1; im<= 1; im++) { pp = findnonzero(pdesc); ppp = findnonzero(pdesc.transpose() * pdesc); vtmp = index(P,pp); dan_affsub1(REF,IMAGE,MG,MF,Hold,samp,vtmp); alpha_t = ret_m1; beta_t = ret_m2; chi2_t = ret_d1; cvtmp = vectorize(beta_t).transpose()/chi2_t; add_elements(beta,pp,cvtmp); cvtmp = vectorize(alpha_t).transpose() / chi2_t; add_elements(alpha,ppp,cvtmp); pchi2 *= chi2_t; } // If \chi^2 is better than the previous best, then save the parameters // from the previous iteration. if (pchi2 < bestchi2) { bestchi2 = pchi2; bestP = P; } //% Update parameter estimates //%----------------------------------------------------------------------- // qq = find(free); // qqq = find(free*free'); // nf = sum(free ~= 0); qq = findnonzero(free); qqq = findnonzero(free.transpose() * free); nf=0; for (i=0; idimx); k2=MAX(k2,1); k2=MIN(k2,(int)REF->dimy); k3=MAX(k3,1); k3=MIN(k3,(int)REF->dimz); //% Scaling is to improve stability. //%----------------------------------------------------------------------- stabilise = 64.0; basX = dan_dctmtx(REF->dimx,k1) * stabilise; basY = dan_dctmtx(REF->dimy,k2) * stabilise; basZ = dan_dctmtx(REF->dimz,k3) * stabilise; dbasX = dan_dctmtxdiff(REF->dimx,k1) * stabilise; dbasY = dan_dctmtxdiff(REF->dimy,k2) * stabilise; dbasZ = dan_dctmtxdiff(REF->dimz,k3) * stabilise; dd1.resize(k1,1); for(i=0; idimx),2); dd2.resize(k2,1); for(i=0; idimy),2); dd3.resize(k3,1); for(i=0; idimz),2); IC0 = kron(kron(ones(k3,1),ones(k2,1)),dd1) + kron(kron(ones(k3,1),dd2),ones(k1,1)) + kron(kron(dd3,ones(k2,1)),ones(k1,1)); IC0 = IC0 / (3.0*((double)(REF->dimx * REF->dimy * REF->dimz) / (double)((k1*k2*k3)-1))); IC0 = IC0 * (pow(sd1,-2) * pow(stabilise,6)); IC1 = IC0; IC1 = IC1.stack(IC0); IC1 = IC1.stack(IC0); IC1 = IC1.stack(zeros(4,1)); IC2.resize(IC1.rows() * IC1.cols(),IC1.rows()*IC1.cols()); IC2.fill(0.0); for(i=0; i<(IC1.rows()*IC1.cols()); i++) { IC2(i,i) = get_element(IC1,i); } // IC2 seems to be identical to matlab's output // Generate starting estimates. s1 = 3*k1*k2*k3; s2 = s1 + 4; T.resize(s2,1); T.fill(0.0); T(s1,0) = 1; for (i=0; i -1) { T = backslash(alpha + (IC2*var),(alpha*T)+beta); // T seems to be almost but not quite identical to matlab's output } else T = T + backslash(alpha,beta); } //% Dimensions and values of the 3D-DCT //%----------------------------------------------------------------------- // Transform = reshape(T(1:s1),prod(k),3)*stabilise.^3; //T.resize(s1,1); Transform = reshape(T,k1*k2*k3,3) * pow(stabilise,3); // Dims = [REF(1:3,1)'; k]; Matrix Dims(2,3,0.0); Dims(0,0) = REF->dimx; Dims(0,1) = REF->dimy; Dims(0,2) = REF->dimz; Dims(1,0) = k1; Dims(1,1) = k2; Dims(1,2) = k3; // Scaling for each template image. remainder = get_element(T,s1); // formerly T((1:4:4) + s1); ret_m1 = Transform; ret_m2 = Dims; ret_d1 = remainder; return TRUE; } // does this really compute the kronecker tensor product? Matrix kron(const Matrix &A,const Matrix &B) { Matrix C(A.rows() * B.rows(),A.cols() * B.cols()); int i,j,k,l; for (i=0; i < A.rows(); i++) { for (j=0; j < A.cols(); j++) { for (k=0; k < B.rows(); k++) { for (l=0; l < B.cols(); l++) { C(i*B.rows() + k,j*B.cols() + l) = A(i,j) * B(k,l); } } } } return C; } RowVector dan_span(double from,double to,double increment) { int size = ((int)((to-from)/increment))+1; if (size < 0) size=0; RowVector tmp(size); for(int i=0; i= mat.rows()) { k=0; l++; if (l >= mat.cols()) { cerr << "reshape(Matrix) - ran out of stuff\n"; return mtmp; } } } } return mtmp; } Matrix reshape(const ColumnVector &vec,int m,int n) { Matrix mtmp(m,n,0.0); int i,j; int k; k=0; for(i=0; i= vec.length()) { cerr << "error in cvec reshape() - ran out of vector stuff\n"; return mtmp; } else { mtmp(j,i) = vec(k); k++; } } } return mtmp; } Matrix reshape(const RowVector &vec,int m,int n) { Matrix mtmp(m,n,0.0); int i,j; int k; k=0; for(i=0; i= vec.length()) { cerr << "error in rvec reshape() - ran out of vector stuff\n"; return mtmp; } else { mtmp(j,i) = vec(k); k++; } } } return mtmp; } RowVector index(const Matrix &mat,const RowVector &vec) { RowVector ret(vec.length()); int i; for(i=0; i n) maxnm = (int) m; else maxnm = (int) n; Matrix AP(n,m,0.0); SVD decomp(A); Matrix U = decomp.left_singular_matrix(); Matrix V = decomp.right_singular_matrix(); DiagMatrix S = decomp.singular_values(); tol = maxnm * (double)S(0,0) * DBL_MIN; r=0; for(i=0; i < S.length(); i++) if (S(i,i) > tol) r++; if (r) { Matrix Sm(r,r,0.0); for(j=0; jdimx; dimy = map->dimy; dimz = map->dimz; m = x.rows(); n = x.cols(); hold = abs(hold); RowVector img(m*n,0.0); if (hold > 127 || hold == 2) cerr << "Bad hold value."; xv = vectorize(x); yv = vectorize(y); zv = vectorize(z); double scale=map->scl_slope; if (scale==0.0) scale=1.0; if (map->datatype == vb_short && hold == 1) { resample_1(m*n,(short *)map->data,img,xv,yv,zv, dimx,dimy,dimz, background,scale); } else if (map->datatype == vb_long && hold == 1) { resample_1(m*n,(int *)map->data,img,xv,yv,zv, dimx,dimy,dimz, background,scale); } else if (map->datatype == vb_byte && hold == 1) { resample_1(m*n,(unsigned char *)map->data,img,xv,yv,zv, dimx,dimy,dimz, background,scale); } else if (map->datatype == vb_float && hold == 1) { resample_1(m*n,(float *)map->data,img,xv,yv,zv, dimx,dimy,dimz, background,scale); } else if (map->datatype == vb_double && hold == 1) { resample_1(m*n,(double *)map->data,img,xv,yv,zv, dimx,dimy,dimz, background,scale); } else if (map->datatype == vb_short && hold > 2) { resample_sinc(m*n,(short *)map->data,img,xv,yv,zv, dimx,dimy,dimz, hold,background,scale); } else if (map->datatype == vb_long && hold > 2) { resample_sinc(m*n,(int *)map->data,img,xv,yv,zv, dimx,dimy,dimz, hold,background,scale); } else if (map->datatype == vb_byte && hold > 2) { resample_sinc(m*n,(unsigned char *)map->data,img,xv,yv,zv, dimx,dimy,dimz, hold,background,scale); } else if (map->datatype == vb_float && hold > 2) { resample_sinc(m*n,(float *)map->data,img,xv,yv,zv, dimx,dimy,dimz, hold,background,scale); } else if (map->datatype == vb_double && hold > 2) { resample_sinc(m*n,(double *)map->data,img,xv,yv,zv, dimx,dimy,dimz, hold,background,scale); } else { cerr << "in dan_sample_vol() - unrecognized type " << map->datatype << endl; } Matrix Y(m,n); k=0; for(int i=0; i void resample_sinc(int m,T *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,int nn,double background, double scale) { int i, dim1xdim2 = dimx*dimy; int dx1, dy1, dz1; static double tablex[255],tabley[255],tablez[255]; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && z(i)<=dimz+TINY && y(i)>=1-TINY && y(i)<=dimy+TINY && x(i)>=1-TINY && x(i)<=dimx+TINY) { T *dp1; double dat=0.0, *tp1, *tp1end, *tp2end, *tp3end; make_lookup(x(i), nn, dimx, &dx1, tablex, &tp3end); make_lookup(y(i), nn, dimy, &dy1, tabley, &tp2end); make_lookup(z(i), nn, dimz, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= dimx; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { T *dp2 = dp1 + dy1; double dat2 = 0.0, *tp2 = tabley; while (tp2 <= tp2end) { register double dat3 = 0.0, *tp3 = tablex; register T *dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += dimx; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } out(i) = scale*dat; } else out(i) = background; } } template void resample_1(int m,T *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,double background,double scale) { int i, dim1xdim2 = dimx*dimy; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && zi<=dimz+TINY && yi>=1-TINY && yi<=dimy+TINY && xi>=1-TINY && xi<=dimx+TINY) { double k111,k112,k121,k122,k211,k212,k221,k222; double dx1, dx2, dy1, dy2, dz1, dz2; int off1, off2, offx, offy, offz, xcoord, ycoord, zcoord; xcoord = (int)floor(xi); dx1=xi-xcoord; dx2=1.0-dx1; ycoord = (int)floor(yi); dy1=yi-ycoord; dy2=1.0-dy1; zcoord = (int)floor(zi); dz1=zi-zcoord; dz2=1.0-dz1; xcoord = (xcoord < 1) ? ((offx=0),1) : ((offx=(xcoord>=dimx) ? 0 : 1 ),xcoord); ycoord = (ycoord < 1) ? ((offy=0),1) : ((offy=(ycoord>=dimy) ? 0 : dimx ),ycoord); zcoord = (zcoord < 1) ? ((offz=0),1) : ((offz=(zcoord>=dimz) ? 0 : dim1xdim2),zcoord); off1 = xcoord + dimx*(ycoord + dimy*zcoord); k222 = vol[off1]; k122 = vol[off1+offx]; off2 = off1+offy; k212 = vol[off2]; k112 = vol[off2+offx]; off1+= offz; k221 = vol[off1]; k121 = vol[off1+offx]; off2 = off1+offy; k211 = vol[off2]; k111 = vol[off2+offx]; /* resampled pixel value (trilinear interpolation) */ out(i) = scale*(((k222*dx2 + k122*dx1)*dy2 + (k212*dx2 + k112*dx1)*dy1)*dz2 + ((k221*dx2 + k121*dx1)*dy2 + (k211*dx2 + k111*dx1)*dy1)*dz1); } else out(i) = background; } } void resample_short_sinc(int m,short *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,int nn,double background, double scale) { int i, dim1xdim2 = dimx*dimy; int dx1, dy1, dz1; static double tablex[255], tabley[255], tablez[255]; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && z(i)<=dimz+TINY && y(i)>=1-TINY && y(i)<=dimy+TINY && x(i)>=1-TINY && x(i)<=dimx+TINY) { short *dp1; double dat=0.0, *tp1, *tp1end, *tp2end, *tp3end; make_lookup(x(i), nn, dimx, &dx1, tablex, &tp3end); make_lookup(y(i), nn, dimy, &dy1, tabley, &tp2end); make_lookup(z(i), nn, dimz, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= dimx; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { short *dp2 = dp1 + dy1; double dat2 = 0.0, *tp2 = tabley; while (tp2 <= tp2end) { register double dat3 = 0.0, *tp3 = tablex; register short *dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += dimx; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } out(i) = scale*dat; } else out(i) = background; } } void resample_char_sinc(int m,unsigned char *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,int nn,double background, double scale) { int i, dim1xdim2 = dimx*dimy; int dx1, dy1, dz1; static double tablex[255], tabley[255], tablez[255]; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && z(i)<=dimz+TINY && y(i)>=1-TINY && y(i)<=dimy+TINY && x(i)>=1-TINY && x(i)<=dimx+TINY) { unsigned char *dp1; double dat=0.0, *tp1, *tp1end, *tp2end, *tp3end; make_lookup(x(i), nn, dimx, &dx1, tablex, &tp3end); make_lookup(y(i), nn, dimy, &dy1, tabley, &tp2end); make_lookup(z(i), nn, dimz, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= dimx; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { unsigned char *dp2 = dp1 + dy1; double dat2 = 0.0, *tp2 = tabley; while (tp2 <= tp2end) { register double dat3 = 0.0, *tp3 = tablex; register unsigned char *dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += dimx; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } out(i) = scale*dat; } else out(i) = background; } } // sinc resampling void resample_int_sinc(int m,int *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,int nn,double background, double scale) { int i, dim1xdim2 = dimx*dimy; int dx1, dy1, dz1; static double tablex[255], tabley[255], tablez[255]; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && z(i)<=dimz+TINY && y(i)>=1-TINY && y(i)<=dimy+TINY && x(i)>=1-TINY && x(i)<=dimx+TINY) { int *dp1; double dat=0.0, *tp1, *tp1end, *tp2end, *tp3end; make_lookup(x(i), nn, dimx, &dx1, tablex, &tp3end); make_lookup(y(i), nn, dimy, &dy1, tabley, &tp2end); make_lookup(z(i), nn, dimz, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= dimx; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { int *dp2 = dp1 + dy1; double dat2 = 0.0,*tp2 = tabley; while (tp2 <= tp2end) { register double dat3 = 0.0, *tp3 = tablex; register int *dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += dimx; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } out(i) = scale*dat; } else out(i) = background; } } void resample_short_1(int m,short *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,double background,double scale) { int i, dim1xdim2 = dimx*dimy; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && zi<=dimz+TINY && yi>=1-TINY && yi<=dimy+TINY && xi>=1-TINY && xi<=dimx+TINY) { double k111,k112,k121,k122,k211,k212,k221,k222; double dx1, dx2, dy1, dy2, dz1, dz2; int off1, off2, offx, offy, offz, xcoord, ycoord, zcoord; xcoord = (int)floor(xi); dx1=xi-xcoord; dx2=1.0-dx1; ycoord = (int)floor(yi); dy1=yi-ycoord; dy2=1.0-dy1; zcoord = (int)floor(zi); dz1=zi-zcoord; dz2=1.0-dz1; xcoord = (xcoord < 1) ? ((offx=0),1) : ((offx=(xcoord>=dimx) ? 0 : 1 ),xcoord); ycoord = (ycoord < 1) ? ((offy=0),1) : ((offy=(ycoord>=dimy) ? 0 : dimx ),ycoord); zcoord = (zcoord < 1) ? ((offz=0),1) : ((offz=(zcoord>=dimz) ? 0 : dim1xdim2),zcoord); off1 = xcoord + dimx*(ycoord + dimy*zcoord); k222 = vol[off1]; k122 = vol[off1+offx]; off2 = off1+offy; k212 = vol[off2]; k112 = vol[off2+offx]; off1+= offz; k221 = vol[off1]; k121 = vol[off1+offx]; off2 = off1+offy; k211 = vol[off2]; k111 = vol[off2+offx]; /* resampled pixel value (trilinear interpolation) */ out(i) = scale*(((k222*dx2 + k122*dx1)*dy2 + (k212*dx2 + k112*dx1)*dy1)*dz2 + ((k221*dx2 + k121*dx1)*dy2 + (k211*dx2 + k111*dx1)*dy1)*dz1); } else out(i) = background; } } void resample_char_1(int m,unsigned char *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,double background,double scale) { int i, dim1xdim2 = dimx*dimy; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && zi<=dimz+TINY && yi>=1-TINY && yi<=dimy+TINY && xi>=1-TINY && xi<=dimx+TINY) { double k111,k112,k121,k122,k211,k212,k221,k222; double dx1, dx2, dy1, dy2, dz1, dz2; int off1, off2, offx, offy, offz, xcoord, ycoord, zcoord; xcoord = (int)floor(xi); dx1=xi-xcoord; dx2=1.0-dx1; ycoord = (int)floor(yi); dy1=yi-ycoord; dy2=1.0-dy1; zcoord = (int)floor(zi); dz1=zi-zcoord; dz2=1.0-dz1; xcoord = (xcoord < 1) ? ((offx=0),1) : ((offx=(xcoord>=dimx) ? 0 : 1 ),xcoord); ycoord = (ycoord < 1) ? ((offy=0),1) : ((offy=(ycoord>=dimy) ? 0 : dimx ),ycoord); zcoord = (zcoord < 1) ? ((offz=0),1) : ((offz=(zcoord>=dimz) ? 0 : dim1xdim2),zcoord); off1 = xcoord + dimx*(ycoord + dimy*zcoord); k222 = vol[off1]; k122 = vol[off1+offx]; off2 = off1+offy; k212 = vol[off2]; k112 = vol[off2+offx]; off1+= offz; k221 = vol[off1]; k121 = vol[off1+offx]; off2 = off1+offy; k211 = vol[off2]; k111 = vol[off2+offx]; /* resampled pixel value (trilinear interpolation) */ out(i) = scale*(((k222*dx2 + k122*dx1)*dy2 + (k212*dx2 + k112*dx1)*dy1)*dz2 + ((k221*dx2 + k121*dx1)*dy2 + (k211*dx2 + k111*dx1)*dy1)*dz1); } else out(i) = background; } } void resample_int_1(int m,int *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,double background,double scale) { int i, dim1xdim2 = dimx*dimy; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && zi<=dimz+TINY && yi>=1-TINY && yi<=dimy+TINY && xi>=1-TINY && xi<=dimx+TINY) { double k111,k112,k121,k122,k211,k212,k221,k222; double dx1, dx2, dy1, dy2, dz1, dz2; int off1, off2, offx, offy, offz, xcoord, ycoord, zcoord; xcoord = (int)floor(xi); dx1=xi-xcoord; dx2=1.0-dx1; ycoord = (int)floor(yi); dy1=yi-ycoord; dy2=1.0-dy1; zcoord = (int)floor(zi); dz1=zi-zcoord; dz2=1.0-dz1; xcoord = (xcoord < 1) ? ((offx=0),1) : ((offx=(xcoord>=dimx) ? 0 : 1 ),xcoord); ycoord = (ycoord < 1) ? ((offy=0),1) : ((offy=(ycoord>=dimy) ? 0 : dimx ),ycoord); zcoord = (zcoord < 1) ? ((offz=0),1) : ((offz=(zcoord>=dimz) ? 0 : dim1xdim2),zcoord); off1 = xcoord + dimx*(ycoord + dimy*zcoord); k222 = vol[off1]; k122 = vol[off1+offx]; off2 = off1+offy; k212 = vol[off2]; k112 = vol[off2+offx]; off1+= offz; k221 = vol[off1]; k121 = vol[off1+offx]; off2 = off1+offy; k211 = vol[off2]; k111 = vol[off2+offx]; /* resampled pixel value (trilinear interpolation) */ out(i) = scale*(((k222*dx2 + k122*dx1)*dy2 + (k212*dx2 + k112*dx1)*dy1)*dz2 + ((k221*dx2 + k121*dx1)*dy2 + (k211*dx2 + k111*dx1)*dy1)*dz1); } else out(i) = background; } } Matrix ones(int m,int n) { Matrix tmp(m,n,1.0); return tmp; } RowVector ones(int d) { RowVector tmp(d,1.0); return tmp; } Matrix zeros(int m,int n) { Matrix tmp(m,n,0.0); return tmp; } RowVector zeros(int d) { RowVector tmp(d,0.0); return tmp; } voxbo-1.8.5~svn1246/crunch/oldvbmf.cpp000066400000000000000000000221151153177201300175440ustar00rootroot00000000000000 // vbmakefilter.cpp // hack to create exofilt file // Copyright (c) 2005 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // written to accomplish the same thing as some original IDL code by // Geoff Aguirre using namespace std; #include #include #include #include #include "vbutil.h" #include "vbjobspec.h" #include "vbprefs.h" #include "vbio.h" #include VBPrefs vbp; class FilterParams { public: string exofiltname; string noisename; int lows,highs; // low and high frequencies to remove vector middles; // middle frequencies to remove string kernelname; // temporal smoothing kernel double kerneltr; // sampling interval of kernel file string noisemodel; // noise model int pri; double TR; int orderg; int init(tokenlist &args); int MakeNoise(); int MakeExoFilt(); }; void MCopy(VB_Vector &c,Vec &vec); void MCopy(Vec &vec,VB_Vector &c); void vbmakefilter_help(); void vbmakefilter_version(); int main(int argc,char **argv) { tokenlist args; args.Transfer(argc-1,argv+1); if (args.size() == 0) { vbmakefilter_help(); exit(0); } if (args[0]=="-h") { vbmakefilter_help(); exit(0); } if (args[0]=="-v") { vbmakefilter_version(); } FilterParams fp; if (fp.init(args)) exit(5); if (fp.MakeNoise()) exit(6); if (fp.MakeExoFilt()) exit(7); exit(0); } // this is the sole constructor, it chews on the passed arguments int FilterParams::init(tokenlist &args) { exofiltname=""; noisename=""; lows=highs=0; middles.clear(); kernelname=""; kerneltr=2000.0; noisemodel=""; pri=2; TR=2000.0; orderg=100; for (int i=0; i1) kerneltr=strtod(tmpl[1]); } printf("[I] vbmakefilter: using kernel TR of %.2f\n",kerneltr); } printf("[I] vbmakefilter: using data TR of %.2f\n",TR); for (i=0; i 0) { if (IRF.ReadFile(kernelname.c_str())) { printf("[E] vbmakefilter: couldn't read kernel file %s\n",kernelname.c_str()); return 101; // error! } } // interpolate the HRF to the resolution of your data if (kernelname.size()>0 && TR != kerneltr) { IRF=cspline_resize(IRF,kerneltr/TR); } // set exofilt to irf padded with zeros, scaled if (IRF.getLength()) { total=0.0; for (i=0; i<(int)IRF.getLength(); i++) { exofilt[i]=IRF[i]; total+=IRF[i]; } total /= orderg; for (i=0; i create exofilt\n"); printf(" -i create intrinsic noise model\n"); printf(" -t how many TRs\n"); printf(" -lf low frequencies to remove\n"); printf(" -mf other frequencies to remove\n"); printf(" -hf high frequencies to remove\n"); printf(" -k convolution kernel for exofilt\n"); printf(" -n 1/f noise model file name\n"); printf(" -h help\n"); printf(" -v version\n"); } void vbmakefilter_version() { printf("VoxBo vb2tes (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/crunch/perfmask.cpp000066400000000000000000000215441153177201300177300ustar00rootroot00000000000000 // perfmask.cpp // create mask from a segmentation, for perfusion purposes // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbcrunch.h" class Voxel { public: int x,y,z; }; class Region { public: vector vox; }; class Perfmask { private: tokenlist args; // structure to be used for argument parsing CrunchCube *mycube,*newcube,*incube; double zsize; // size of slices in mm double x1,y1,z1; // start voxel (0 indexed) in x,y,z int nx,ny,nz; // number of voxels in resampled image int dimx,dimy,dimz; // original dimensions float keepvalue; // the mask value we want to keep double voxsize[3]; // original voxsize double xstep,ystep,zstep; // resample interval in voxels public: Perfmask(int argc,char **argv); int Go(); // do it int ResampleCube(); // do it for each cube int UseDims(const string &refname); void SelectRegions(CrunchCube *rcube); }; void growregion(Region ®,Cube &cb,int x,int y,int z); int regionsize(const Region &r1,const Region &r2); void perfmask_help(); int main(int argc,char *argv[]) { tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs perfmask_help(); exit(0); } Perfmask *r=new Perfmask(argc,argv); // init perfmask object, parse args if (!r) { printf("*** perfmask: couldn't allocate a tiny structure\n"); exit(5); } int err; err=r->Go(); delete r; // clean up if (err) printf("*** perfmask: error resampling (%d).\n",err); else printf("perfmask: done.\n"); exit(err); } Perfmask::Perfmask(int argc,char *argv[]) { args.Transfer(argc-1,argv+1); zsize=0.0; x1=y1=z1=0; xstep=ystep=zstep=1.0; nx=41; ny=51; nz=27; keepvalue=1.0; } int Perfmask::Go() { if (args.size() < 3) { printf("*** perfmask: requires segmentation, reference epi, and output filename\n"); return 110; } switch(ImageType(FileFormat(args[0]))) { case vb_3d: mycube = new CrunchCube; mycube->ReadFile(args[0]); if (!mycube->data_valid) { printf("*** perfmask: invalid 3D file: %s\n",args[0].c_str()); delete mycube; mycube=NULL; return 101; } dimx=mycube->dimx; dimy=mycube->dimy; dimz=mycube->dimz; voxsize[0]=mycube->voxsize[0]; voxsize[1]=mycube->voxsize[1]; voxsize[2]=mycube->voxsize[2]; break; default: printf("*** perfmask: unrecognized filetype\n"); return 103; break; } x1=y1=z1=0; xstep=ystep=zstep=1.0; nx=dimx; ny=dimy; nz=dimz; UseDims(args[1]); for (int i=0; idimx; i++) { for (int j=0; jdimy; j++) { for (int k=0; kdimz; k++) { if (abs(mycube->GetValue(i,j,k)-keepvalue) > 0.2) { mycube->SetValue(i,j,k,0.0); } } } } incube=new CrunchCube(); incube->SetVolume(mycube->dimx,mycube->dimy,mycube->dimz,vb_float); incube->voxsize[0]=mycube->voxsize[0]; incube->voxsize[1]=mycube->voxsize[1]; incube->voxsize[2]=mycube->voxsize[2]; // copy data, now in floats for (int i=0; idimx; i++) { for (int j=0; jdimy; j++) { for (int k=0; kdimz; k++) { incube->SetValue(i,j,k,mycube->GetValue(i,j,k)); } } } SelectRegions(incube); if (ResampleCube()) return 101; // mask out the non-1's for (int i=0; idimx; i++) { for (int j=0; jdimy; j++) { for (int k=0; kdimz; k++) { if (abs(newcube->GetValue(i,j,k)-keepvalue) < 0.2) newcube->SetValue(i,j,k,keepvalue); else newcube->SetValue(i,j,k,0.0); } } } newcube->SetFileName(args[2]); newcube->header=mycube->header; if (mycube->origin[0]) { newcube->origin[0]=(int)round((mycube->origin[0]-x1)/xstep); newcube->origin[1]=(int)round((mycube->origin[1]-y1)/ystep); newcube->origin[2]=(int)round((mycube->origin[2]-z1)/zstep); } if (newcube->WriteFile()) printf("*** perfmask: error writing %s\n",args[2].c_str()); else printf("perfmask: wrote %s.\n",args[2].c_str()); delete newcube; return 0; } void Perfmask::SelectRegions(CrunchCube *rcube) { vector regionlist; int i,j,k; double val; // find all the regions for (i=0; idimx; i++) { for (j=0; jdimy; j++) { for (k=0; kdimz; k++) { val=rcube->GetValue(i,j,k); if (val != 0.0) { Region rg; growregion(rg,*rcube,i,j,k); // clears the voxels as a side effect! regionlist.push_back(rg); } } } } // sort by size sort(regionlist.begin(),regionlist.end(),regionsize); // mark up the cube for just those regions larger than 5 voxels cout << regionlist.size() << endl; for (i=0; i<(int)regionlist.size(); i++) { k=regionlist[i].vox.size(); cout << k << endl; if (k < 200) continue; for (j=0; j<(int)regionlist[i].vox.size(); j++) { rcube->SetValue(regionlist[i].vox[j].x,regionlist[i].vox[j].y,regionlist[i].vox[j].z,1.0); } } } int regionsize(const Region &r1,const Region &r2) { return (r1.vox.size() > r2.vox.size()); } void growregion(Region ®,Cube &cb,int x,int y,int z) { Voxel vx; vx.x=x; vx.y=y; vx.z=z; reg.vox.push_back(vx); cb.SetValue(x,y,z,0.0); int i,j,k; for (i=x-1; icb.dimx-1) continue; for (j=y-1; jcb.dimy-1) continue; for (k=z-1; kcb.dimz-1) continue; if (i==x && j==y && k==z) continue; if (cb.GetValue(i,j,k)) growregion(reg,cb,i,j,k); } } } } int Perfmask::UseDims(const string &refname) { CrunchCube *refcube; refcube = new CrunchCube; refcube->ReadFile(refname); if (!refcube->data_valid) { printf("*** perfmask: invalid 3D file: %s\n",args[1].c_str()); delete refcube; return 501; // panic and exit } nx=refcube->dimx; ny=refcube->dimy; nz=refcube->dimz; // FIXME is the following correct? xstep=(double)(dimx)/nx; ystep=(double)(dimy)/ny; zstep=(double)(dimz)/nz; delete refcube; return 0; } int Perfmask::ResampleCube() { int i,j,k; if (!incube) return 5; newcube=new CrunchCube(); newcube->SetVolume(nx,ny,nz,incube->datatype); newcube->voxsize[0]=xstep*incube->voxsize[0]; newcube->voxsize[1]=ystep*incube->voxsize[1]; newcube->voxsize[2]=zstep*incube->voxsize[2]; RowVector c1(1),c2(1),c3(1),out(1); for (k=0; kdatatype) { case vb_byte: resample_sinc(1,(unsigned char *)incube->data,out,c1,c2,c3, incube->dimx,incube->dimy,incube->dimz,5, 0.0,1.0); break; case vb_short: resample_sinc(1,(short *)incube->data,out,c1,c2,c3, incube->dimx,incube->dimy,incube->dimz,5, 0.0,1.0); break; case vb_long: resample_sinc(1,(int *)incube->data,out,c1,c2,c3, incube->dimx,incube->dimy,incube->dimz,5, 0.0,1.0); break; case vb_float: resample_sinc(1,(float *)incube->data,out,c1,c2,c3, incube->dimx,incube->dimy,incube->dimz,5, 0.0,1.0); break; case vb_double: resample_sinc(1,(double *)incube->data,out,c1,c2,c3, incube->dimx,incube->dimy,incube->dimz,5, 0.0,1.0); break; } newcube->SetValue(i,j,k,out(0)); } } } return 0; // no error } void growregion(Region ®,Cube &cb,int x,int y,int z); void perfmask_help() { printf("\nVoxBo perfmask (v%s)\n",vbversion.c_str()); printf("summary: create a mask from a segmentation in the space of an epi image\n"); printf("usage: perfmask [flags]\n"); printf("flags:\n"); printf("\n"); } voxbo-1.8.5~svn1246/crunch/realign.cpp000066400000000000000000000376051153177201300175460ustar00rootroot00000000000000 // realign.cpp // VoxBo realignment (motion correction) module // Copyright (c) 1998-2003 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // The guts of the underlying code were based on SPM source code // written in MATLAB by John Ashburner. See the SPM web site at: // (http://www.fil.ion.bpmf.ac.uk/spm/) using namespace std; #include "vbcrunch.h" const double TOLERANCE = 0.5; const int MAXITERATIONS = 4; const double SPIKETHRESH = 0.5; const double DRIFTTHRESH = 0.5; class Realignment { private: string refimage; string outfile; string paramfile; tokenlist args; CrunchCube *refcub,*sref,*mycub,*newcub; int startcub,i,o1,o2,o3; int maxiterations; int refnum; // index of reference image within tes double spikethresh; double driftthresh; double tolerance; Matrix moveparams; double minvoxsize; int maxdim; int paramcheckonly; int summarizeflag; double tol_trans,tol_rot; Tes *mytes; // current tes file char timestring[STRINGLEN]; // text representation of time of realignment public: Realignment(int argc,char **argv); ~Realignment(); int Crunch(); void Check(); void Summarize(); void WriteMoveParams(const string &tesname,const string &outfile); void ParamFileCheck(); }; void realign_help(); int main(int argc,char *argv[]) { stringstream tmps; tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs realign_help(); exit(0); } Realignment *r=new Realignment(argc,argv); // init realign object if (!r) { tmps << "realign: couldn't allocate a tiny realignment structure"; printErrorMsg(VB_ERROR,tmps.str()); exit(5); } int error = r->Crunch(); // do the crunching delete r; // clean up exit(error); } Realignment::Realignment(int argc,char *argv[]) { refimage=""; refnum=0; maxiterations=MAXITERATIONS; spikethresh=SPIKETHRESH; driftthresh=DRIFTTHRESH; tolerance=TOLERANCE; paramcheckonly=FALSE; summarizeflag=FALSE; for (i=1; iReadFile(args[i]); if (!mytes->data_valid) { tmps.str(""); tmps << "realign: " << args[i] << " is not a valid 4D file."; printErrorMsg(VB_ERROR,tmps.str()); delete mytes; return 105; // panic and exit } // set default outfile name if (!outfile.size()) outfile=xdirname(args[i])+(string)"/r"+xfilename(args[i]); // guess default origin and load reference image if (i == 0 || (o1==0 && o2==0 && o3==0)) { minvoxsize = mytes->voxsize[0]; if (mytes->voxsize[1] < minvoxsize) minvoxsize=mytes->voxsize[1]; if (mytes->voxsize[2] < minvoxsize) minvoxsize=mytes->voxsize[2]; if (minvoxsize < 0.0001) { tmps.str(""); tmps << "realign: invalid voxel sizes for tes file " << args[i]; printErrorMsg(VB_ERROR,tmps.str()); delete mytes; return 150; } maxdim = mytes->dimx; if (mytes->dimy > maxdim) maxdim = mytes->dimy; if (mytes->dimz > maxdim) maxdim = mytes->dimz; tol_trans=minvoxsize * tolerance; tol_rot = atan(tolerance / ((float)maxdim / 2.0)); if (mytes->origin[0] == 0 && mytes->origin[1] == 0 && mytes->origin[2] == 0) { o1 = mytes->dimx; o2 = mytes->dimy; o3 = mytes->dimz; guessorigin(o1,o2,o3); mytes->SetOrigin(o1,o2,o3); } else { o1 = mytes->origin[0]; o2 = mytes->origin[1]; o3 = mytes->origin[2]; } if (refimage.size()) { tmps.str(""); tmps << "realign: loading reference image " << refimage; printErrorMsg(VB_INFO,tmps.str()); refcub = new CrunchCube(); // refcub->ReadHeader(refimage); refcub->ReadFile(refimage); } else { // if no template specified, use first image if (refnum >= mytes->dimt) { tmps.str(""); tmps << "realign: index " << refnum << "is large, using " << mytes->dimt-1 << " instead"; printErrorMsg(VB_INFO,tmps.str()); refnum=0; } if (refnum < 0) { tmps.str(""); tmps << "realign: index " << refnum << " is less than zero, using the first image instead"; printErrorMsg(VB_ERROR,tmps.str()); refnum=0; } tmps.str(""); tmps << "realign: using image " << refnum << " as the reference image"; printErrorMsg(VB_INFO,tmps.str()); refcub = new CrunchCube((*mytes)[refnum]); startcub = 1; } } if (!refcub->data_valid) { tmps.str(""); tmps << "realign: invalid reference volume"; printErrorMsg(VB_ERROR,tmps.str()); delete mytes; return 120; } if (refcub->dimx != mytes->dimx || refcub->dimy != mytes->dimy || refcub->dimz != mytes->dimz || refcub->voxsize[0] != mytes->voxsize[0] || refcub->voxsize[1] != mytes->voxsize[1] ||refcub->voxsize[2] != mytes->voxsize[2]) { tmps.str(""); tmps << "realign: tes file " << args[i] << " doesn't match the size/dimensions of the reference volume"; printErrorMsg(VB_ERROR,tmps.str()); delete mytes; return 130; } refcub->SetOrigin(o1,o2,o3); tmps.str(""); tmps << "realign: realigning " << args[i]; printErrorMsg(VB_INFO,tmps.str()); moveparams.resize(mytes->dimt,7); // make room for movement parameters moveparams.fill(0.0); sref = dan_smooth_image(refcub,8,8,8); sref->SetOrigin(o1,o2,o3); int percentinterval = mytes->dimt / 10; int countdown = percentinterval; for (int j=startcub; jdimt; j++) { iter = 0; corrected = FALSE; while (iter < maxiterations && corrected == FALSE) { CrunchCube mycub; mytes->getCube(j,mycub); newcub = realign_twoimages(refcub,sref,&mycub); mytes->SetCube(j,newcub); if (newcub->transform(0) < tol_trans && // transform = movement params newcub->transform(1) < tol_trans && newcub->transform(2) < tol_trans && newcub->transform(3) < tol_rot && newcub->transform(4) < tol_rot && newcub->transform(5) < tol_rot) corrected=TRUE; if (iter == 0) { // add the movement params to the list moveparams(j,0)=newcub->transform(0); moveparams(j,1)=newcub->transform(1); moveparams(j,2)=newcub->transform(2); moveparams(j,3)=newcub->transform(3) * (180.0)/PI; moveparams(j,4)=newcub->transform(4) * (180.0)/PI; moveparams(j,5)=newcub->transform(5) * (180.0)/PI; } iter++; moveparams(j,6)=iter; delete newcub; } countdown--; if (countdown == 0) { printf("Percent done: %d\n",(j*100)/mytes->dimt); fflush(stdout); countdown = percentinterval; } } delete sref; mytime = time(NULL); mytm = localtime(&mytime); strftime(timestring,STRINGLEN,"%d%b%Y_%T",mytm); sprintf(tmp,"realign_date: %s",timestring); mytes->AddHeader(tmp); sprintf(tmp,"realign_tolerance: %.4f %.4f",tol_trans,tol_rot); mytes->AddHeader(tmp); if (refimage.size()) sprintf(tmp,"realign_ref: %s",refimage.c_str()); else sprintf(tmp,"realign_ref: [image:%d]",refnum); mytes->AddHeader(tmp); mytes->SetFileName(outfile); int err=mytes->WriteFile(); if (!err) { tmps.str(""); tmps << "realign: wrote " << outfile; printErrorMsg(VB_INFO,tmps.str()); outfile.replace(outfile.size()-4,4,"_MoveParams.ref"); WriteMoveParams(args[i],outfile); Check(); } else { tmps.str(""); tmps << "realign: error writing " << outfile; printErrorMsg(VB_ERROR,tmps.str()); delete mytes; delete refcub; return 110; } delete mytes; } delete refcub; return(0); // no error } void Realignment::WriteMoveParams(const string &tesname,const string &outfile) { int i; FILE *fp; if ((fp = fopen(outfile.c_str(),"w"))) { fprintf(fp,";VB98\n;REF1\n"); fprintf(fp,"; Movement params from motion correction of %s\n",tesname.c_str()); if (refimage.size()) fprintf(fp,"; aligned to cube %s\n",refimage.c_str()); else fprintf(fp,"; aligned to the first image of series\n"); fprintf(fp,"; The seven parameter values (x,y,z,pitch,roll,yaw,iterations)\n"); fprintf(fp,"; are written in order for each time point, translations in mm,\n"); fprintf(fp,"; rotations in degrees\n\n"); for (i=0; idimt; i++) { fprintf(fp,"%.6g\n",(double)moveparams(i,0)); fprintf(fp,"%.6g\n",(double)moveparams(i,1)); fprintf(fp,"%.6g\n",(double)moveparams(i,2)); fprintf(fp,"%.6g\n",(double)moveparams(i,3)); fprintf(fp,"%.6g\n",(double)moveparams(i,4)); fprintf(fp,"%.6g\n",(double)moveparams(i,5)); fprintf(fp,"%.6f\n",(double)moveparams(i,6)); } fclose(fp); } } void Realignment::Summarize() { double totaltrans=0.0; double totalrot=0.0; int i; int multiples=0; for (i=startcub+1; i1) multiples++; } double meantrans=totaltrans/(double)(moveparams.rows()*3); double meanrot=totalrot/(double)(moveparams.rows()*3); printf("realign: mean translation: %.2f\n",meantrans); printf("realign: mean rotation: %.2f\n",meanrot); printf("realign: mulitply corrected images: %d\n",multiples); } void Realignment::Check() { double spike_mm=minvoxsize*spikethresh; double spike_degrees=atan(spikethresh/(maxdim / 2.0)) * (180.0/PI); double drift_mm=minvoxsize*driftthresh; double drift_degrees=atan(driftthresh/(maxdim / 2.0)) * (180.0/PI); int i,spikes[6],drifts[6]; int multiples=0; for (i=0; i<6; i++) { spikes[i]=drifts[i]=0; } for (i=startcub+1; i spike_mm) spikes[0]++; if ((moveparams(i,1)-moveparams(i-1,1)) > spike_mm) spikes[1]++; if ((moveparams(i,2)-moveparams(i-1,2)) > spike_mm) spikes[2]++; if ((moveparams(i,3)-moveparams(i-1,3)) > spike_degrees) spikes[3]++; if ((moveparams(i,4)-moveparams(i-1,4)) > spike_degrees) spikes[4]++; if ((moveparams(i,5)-moveparams(i-1,5)) > spike_degrees) spikes[5]++; } for (i=startcub; i drift_mm) drifts[0]++; if (moveparams(i,1) > drift_mm) drifts[1]++; if (moveparams(i,2) > drift_mm) drifts[2]++; if (moveparams(i,3) > drift_degrees) drifts[3]++; if (moveparams(i,4) > drift_degrees) drifts[4]++; if (moveparams(i,5) > drift_degrees) drifts[5]++; if (moveparams(i,6) > 1.0) multiples++; } string filename; if (mytes) filename=mytes->GetFileName(); else filename="your parameter file"; printf("Summary of extreme corrections for %s\n",filename.c_str()); printf("Thresholds: spike mm=%.2f drift mm=%.2f spike degrees=%.2f drift degrees=%.2f\n", spike_mm,drift_mm,spike_degrees,drift_degrees); printf(" Spikes in X dimension: %d\n",spikes[0]); printf(" Spikes in Y dimension: %d\n",spikes[1]); printf(" Spikes in Z dimension: %d\n",spikes[2]); printf(" Spikes in pitch: %d\n",spikes[3]); printf(" Spikes in roll: %d\n",spikes[4]); printf(" Spikes in yaw: %d\n",spikes[5]); printf(" Drifts in X dimension: %d\n",drifts[0]); printf(" Drifts in Y dimension: %d\n",drifts[1]); printf(" Drifts in Z dimension: %d\n",drifts[2]); printf(" Drifts in pitch: %d\n",drifts[3]); printf(" Drifts in roll: %d\n",drifts[4]); printf(" Drifts in yaw: %d\n",drifts[5]); printf(" Images corrected more than once: %d\n",multiples); // merely printing aline beginning with "VOXBO WARNING" will ensure that // this log is sent to the user if ((spikes[0]+spikes[1]+spikes[2]+spikes[3]+spikes[4]+spikes[5]+ drifts[0]+drifts[1]+drifts[2]+drifts[3]+drifts[4]+drifts[5]+multiples) > 0) printf("VOXBO WARNING check log file for extreme motion\n"); } void realign_help() { printf("\nVoxBo realign (v%s)\n",vbversion.c_str()); printf("usage: realign [flags] file [file ...]\n"); printf("flags:\n"); printf(" -r refimage is the reference image\n"); printf(" -n number of the reference image\n"); printf(" -o set the name for the realigned file\n"); printf(" -p set the name for the param file to be saved\n"); printf(" -t tolerance for (in voxels, default %.1f)\n",TOLERANCE); printf(" -i max # of iterations (default %d)\n",MAXITERATIONS); printf(" -s spike warning threshold (in voxels, default %.1f)\n",SPIKETHRESH); printf(" -d drift warning threshold (in voxels, default %.1f)\n",DRIFTTHRESH); printf(" -c [file ...] check parameters from each file\n"); printf(" -q [file ...] summarize parameters from each file\n"); } voxbo-1.8.5~svn1246/crunch/realignutils.cpp000066400000000000000000000400121153177201300206110ustar00rootroot00000000000000 // realignutils.cpp // a lot of the computational guts of the realignment routines // new code Copyright (c) 1998-2002 by The VoxBo Development Team // based closely on original MATLAB code by John Ashburner // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbcrunch.h" // realign_twoimages() CrunchCube * realign_twoimages(CrunchCube *REF,CrunchCube *sREF,CrunchCube *VOL) { Matrix dQ(6,6,0.0),dXdQ,X,Y; RowVector vtmp(9,0.0),q(6,0.0); Matrix bb,sb,C1,mtmp; Matrix B,x; Matrix d,dX,C2,y,q0,q1,M; RowVector S,sbv,q2,Xm,Ym,tmp,Mask,dv,Count; CrunchCube *sVOL,*NEWVOL; int i,j,k,Hold,h,Mx,Nx,n,err,dim[3]; double a; // just some initialization, probably missed a few important ones err=0; // now into the direct SPM translation Hold = 3; // sREF = dan_smooth_image(REF,8,8,8) // the above commented out because now we smooth the ref once to do // an entire series // spm: center, bounding box, and margins bb = dan_bb_image(REF); // vectorize sb, because that's how we use it sb = diff(bb); sbv = vectorize(sb); // spm: compute matrices, dQ = 6 ortholinear transformation parameters a = PI/180; dQ(0,0) = 1; dQ(1,1) = 1; dQ(2,2) = 1; dQ(3,3) = a; dQ(4,4) = a; dQ(5,5) = a; // spm: define height of transverse slices (S) used in subsampling volume // V1(6) is map->voxsize[2] S = dan_linspace((bb(0,2) + 6/(sREF->voxsize[2])),(bb(1,2) - 8/(sREF->voxsize[2])),8); h = 5; // number of recursions Mx = (int)sbv(0); // rows per slice Nx = (int)sbv(1); // columns per slice n = Mx*Nx; // voxels per slice C1 = dan_get_space_image(REF); // spm: compute X (the reference image) and dX/dQ (the effects of moving X). X.resize(n*S.length(),1,0.0); Y.resize(n*S.length(),1,0.0); dXdQ.resize(n*S.length(),6,0.0); vtmp(0) = -(bb(0,0)); vtmp(1) = -(bb(0,1)); // vtmp(2) set inside the loop vtmp(3) = 0; vtmp(4) = 0; vtmp(5) = 0; vtmp(6) = 1; vtmp(7) = 1; vtmp(8) = 1; for (i=0; i < S.length(); i++) { vtmp(2) = -(S(i)); B = dan_matrix(vtmp); x = dan_slice_vol(sREF,B.inverse(),Mx,Nx,Hold); copysegment(X,x,n,i*n); for (j=0; j < 6; j++) { mtmp = (B * (C1.inverse() * (dan_matrix(dQ.row(j)) * C1))).inverse(); d = dan_slice_vol(sREF,mtmp,Mx,Nx,Hold); dX = d - x; copysegment(dXdQ,dX,n,(i*n)+(j*(dXdQ.rows()))); } } // Here is the documentation from SPM on what this code does: // least squares solution for Q the movements where: // Y = X + dX/dQ.Q => Q = [-dX/dQ Y]\X // The estimate is repeated iteratively h times and the estimates of // Q are cumulated arithmetically (an aproximation but good enough) //================== // this is the big loop // each image is smoothed and parameters are calculated //================== q.fill(0.0); C2 = dan_get_space_image(VOL); sVOL = dan_smooth_image(VOL,8,8,8); vtmp(0) = -(bb(0,0)); vtmp(1) = -(bb(0,1)); // vtmp(2) set within the loop vtmp(3) = 0; vtmp(4) = 0; vtmp(5) = 0; vtmp(6) = 1; vtmp(7) = 1; vtmp(8) = 1; for (i = 0; i < h; i++) { for (j = 0; j < S.length(); j++) { vtmp(2) = -(S(j)); B = dan_matrix(vtmp); mtmp = (B * (C1.inverse() * (dan_matrix(q) * C2))).inverse(); y = dan_slice_vol(sVOL,mtmp,Mx,Nx,Hold); copysegment(Y,y,n,j*n); } q1 = -dXdQ; q1 = q1.append(Y.column(0)); q0 = backslash(q1,X); q2 = vectorize(q0); q2.resize(6,0.0); q = q - (RowVector)(dQ * q2.transpose()); } delete sVOL; //================== saving realignment parameters VOL->M = dan_get_space_image(VOL); dan_get_space_image(VOL,dan_matrix(q) * VOL->M); //================== //================== apply realignment parameters // get properties of first image Hold = 5; M = dan_get_space_image(REF); dim[0] = (int)REF->dimx; dim[1] = (int)REF->dimy; dim[2] = (int)REF->dimz; //================== //// seem to be calling dan_get_space_image() more than necessary //// since the maps are now kept in memory, we can probably //// store the output of this function with the MAP instead of on disk // get properties of the rest of the images REF->M = backslash(M,dan_get_space_image(REF)); VOL->M = backslash(M,dan_get_space_image(VOL)); Xm.resize((int)(dim[0]*dim[1]),0.0); Ym.resize((int)(dim[0]*dim[1]),0.0); Xm.fill(0.0); Ym.fill(0.0); k=0; for (i=0; itransform = q; vtmp(0) = 0; vtmp(1) = 0; // vtmp(2) set inside the loop vtmp(3) = 0; vtmp(4) = 0; vtmp(5) = 0; vtmp(6) = 1; vtmp(7) = 1; vtmp(8) = 1; // now actually do the realignment! int offset = 0; for (j=1; j<=dim[2]; j++) { vtmp(2) = -j; B = dan_matrix(vtmp); // first calculate the masks for this plane Count.resize(dim[0]*dim[1],0.0); Mask.resize(dim[0]*dim[1],0.0); Mask.fill(0.0); REF->M1 = (B * REF->M).inverse(); VOL->M1 = (B * VOL->M).inverse(); // M1, M, and B appear to be good throughout Mask = mask_from_image(REF,Xm,Ym); Count = Mask; Mask = mask_from_image(VOL,Xm,Ym); Count = Count + Mask; for (k=0; k 1) Mask(k)=1.0; else Mask(k)=0.0; } // formerly, loop across files started here // now, we just do the volume to be mapped //// make sure dan_slice_vol() doesn't modify the VOL directly d = dan_slice_vol(VOL,VOL->M1,dim[0],dim[1],Hold); dv = vectorize(d); // apply the mask // bound the image according to the datatype -- not necessary for floats if (VOL->datatype == vb_byte) dan_bound(dv,(double)0,(double)255); else if (VOL->datatype == vb_short) dan_bound(dv,(double)-32768,(double)32767); else if (VOL->datatype == vb_long) dan_bound(dv,-(double)pow(2.0,31.0),(double)pow(2.0,31.0)-1); for (k=0; kdatatype == vb_float) ((float *)(NEWVOL->data))[k+offset] = (float) dv(k); else if (VOL->datatype == vb_double) ((double *)(NEWVOL->data))[k+offset] = (double) dv(k); else if (VOL->datatype == vb_long) ((int *)(NEWVOL->data))[k+offset] = (int) dv(k); else if (VOL->datatype == vb_short) ((short *)(NEWVOL->data))[k+offset] = (short) dv(k); else if (VOL->datatype == vb_byte) ((unsigned char *)(NEWVOL->data))[k+offset] = (unsigned char) dv(k); } offset += dv.length(); } return NEWVOL; } RowVector mask_from_image(CrunchCube *map,RowVector &Xm,RowVector &Ym) { RowVector Mask,tmp; int k; tmp.resize(Xm.length()); tmp.fill(0.0); Mask.resize(Xm.length()); Mask.fill(0.0); for (k=0; kM1(0,0)*Xm(k)) + (map->M1(0,1)*Ym(k)) + (map->M1(0,3)); if ((tmp(k) >= (1.0-TINY)) && (tmp(k) <= ((double)map->dimx+TINY))) Mask(k)=1; else Mask(k)=0; } for (k=0; kM1(1,0) * Xm(k)) + (map->M1(1,1) * Ym(k)) + (map->M1(1,3)); if ((tmp(k) >= (1.0-TINY)) && (tmp(k) <= ((double)map->dimy+TINY)) && Mask(k)) Mask(k)=1; else Mask(k) = 0; } for (k=0; kM1(2,0)*Xm(k)) + (map->M1(2,1)*Ym(k)) + (map->M1(2,3)); if ((tmp(k) >= (1.0-TINY)) && (tmp(k) <= ((double)map->dimz+TINY)) && Mask(k)) Mask(k)=1; else Mask(k) = 0; } return Mask; } // dan_bb_image() Matrix dan_bb_image(CrunchCube *map) { Matrix bb(2,3); double meanx,meany,meanz; double xmin,ymin; int minx,maxx,miny,maxy,minz,maxz,i; RowVector x((int)map->dimx,0.0); RowVector y((int)map->dimy,0.0); RowVector z((int)map->dimz,0.0); maxx=maxy=maxz=0; meanx = meany = meanz = 0.0; dan_box_image(map,x,y,z); xmin = x.min(); ymin = y.min(); x = x - xmin; y = y - ymin; for(i=0;i= meanx) { maxx = i+1; if (!minx) minx=i+1; } } for(i=0;i= meany) { maxy = i+1; if (!miny) miny=i+1; } } for(i=0;i= meanz) { maxz = i+1; if (!minz) minz=i+1; } } bb(0,0) = minx; bb(1,0) = maxx; bb(0,1) = miny; bb(1,1) = maxy; bb(0,2) = minz; bb(1,2) = maxz; return bb; } void dan_box_image(CrunchCube *map,RowVector &X,RowVector &Y,RowVector &Z) { double *kd; int d[3]; int i,x,y,z,N,*ki; unsigned char *ku; short *ks; float *kf; d[0] = (int)map->dimx; d[1] = (int)map->dimy; d[2] = (int)map->dimz; N = d[0]*d[1]*d[2]; // integrate if (map->datatype == vb_byte) { ku = (unsigned char *)map->data; for (i = 0; i < N; i++) { z = (int) floor((double)i / (d[0]*d[1])); y = (int) floor((double)(i - z*(d[0]*d[1]) ) / (d[0])); x = (int) i - z*(d[0]*d[1]) - y*d[0]; X(x) += (double) ku[i]; Y(y) += (double) ku[i]; Z(z) += (double) ku[i]; } } else if (map->datatype == vb_short) { ks = (short *)map->data; for (i = 0; i < N; i++) { z = (int) floor((double)i / (d[0]*d[1])); y = (int) floor((double)(i - z*(d[0]*d[1]) ) / (d[0])); x = (int) i - z*(d[0]*d[1]) - y*d[0]; X(x) += (double) ks[i]; Y(y) += (double) ks[i]; Z(z) += (double) ks[i]; } } else if (map->datatype == vb_long) { ki = (int *)map->data; for (i = 0; i < N; i++) { z = (int) floor((double)i / (d[0]*d[1])); y = (int) floor((double)(i - z*(d[0]*d[1]) ) / (d[0])); x = (int) i - z*(d[0]*d[1]) - y*d[0]; X(x) += (double) ki[i]; Y(y) += (double) ki[i]; Z(z) += (double) ki[i]; } } else if (map->datatype == vb_float) { kf = (float *)map->data; for (i = 0; i < N; i++) { z = (int) floor((double)i / (d[0]*d[1])); y = (int) floor((double)(i - z*(d[0]*d[1]) ) / (d[0])); x = (int) i - z*(d[0]*d[1]) - y*d[0]; X(x) += (double) kf[i]; Y(y) += (double) kf[i]; Z(z) += (double) kf[i]; } } else if (map->datatype == vb_double) { kd = (double *)map->data; for (i = 0; i < N; i++) { z = (int) floor((double)i / (d[0]*d[1])); y = (int) floor((double)(i - z*(d[0]*d[1]) ) / (d[0])); x = (int) i - z*(d[0]*d[1]) - y*d[0]; X(x) += (double) kd[i]; Y(y) += (double) kd[i]; Z(z) += (double) kd[i]; } } else cerr << "error: dan_box() data type not supported" << endl; } void dan_bound(RowVector &vec,double low,double high) { int i; for (i=0; i high) vec(i) = high; } } // dan_matrix() Matrix dan_matrix(const RowVector &P) { RowVector p; Matrix A(4,4),B(4,4),AX(4,4); int n,i; n = P.length(); p=P; p.resize(12,0.0); for (i=n; i<12; i++) { if (i < 9 && i > 5) p(i)=1; else p(i)=0; } ident(A); ident(B); B(0,3)=p(0); B(1,3)=p(1); B(2,3)=p(2); AX = A * B; ident(B); B(1,1)=cos(p(3)); B(1,2)=sin(p(3)); B(2,1)=-sin(p(3)); B(2,2)=cos(p(3)); A = AX * B; ident(B); B(0,0)=cos(p(4)); B(0,2)=sin(p(4)); B(2,0)=-sin(p(4)); B(2,2)=cos(p(4)); AX = A * B; ident(B); B(0,0)=cos(p(5)); B(0,1)=sin(p(5)); B(1,0)=-sin(p(5)); B(1,1)=cos(p(5)); A = AX * B; ident(B); B(0,0)=p(6); B(1,1)=p(7); B(2,2)=p(8); AX = A * B; ident(B); B(0,1)=p(9); B(0,2)=p(10); B(1,2)=p(11); A = AX * B; return A; } // dan_slice_vol() Matrix dan_slice_vol(CrunchCube *map,const Matrix &mat,int m,int n,int hold) { int xdim,ydim,zdim,status,i,j,k; double background; Matrix Y; double *img; background=0.0; xdim = abs((int)map->dimx); ydim = abs((int)map->dimy); zdim = abs((int)map->dimz); // get transformation matrix img = new double[m*n]; for (i=0; idatatype == vb_long) status = slice_int_sinc(mat,img,m,n,(int *)map->data,xdim,ydim,zdim, hold, background); else if (map->datatype == vb_short) status = slice_short_sinc(mat,img,m,n,(short *)map->data,xdim,ydim,zdim, hold, background); // { // for (int z=0; z<4; z++) { // status = slice_short_sinc_threaded(mat,img,m,n,(short *)map->data,xdim,ydim,zdim, // hold, background); // } // } else if (map->datatype == vb_byte) status = slice_sinc(mat,img,m,n,(unsigned char *)(map->data),xdim,ydim,zdim, hold, background); else if (map->datatype == vb_float) status = slice_sinc(mat,img,m,n,(float *)(map->data),xdim,ydim,zdim, hold, background); else if (map->datatype == vb_double) status = slice_sinc(mat,img,m,n,(double *)(map->data),xdim,ydim,zdim, hold, background); else { cerr << "error: dan_slice_vol(): data type other than signed int or short" << endl; } if (status) cerr << "error: dan_slice_vol(): slicing failed\n" << endl; Y.resize(m,n,0.0); k=0; for(i=0; i int slice_sinc(const Matrix &mat,double *image,int xdim1,int ydim1,T *vol, int xdim2,int ydim2,int zdim2,int nn,double background) { double dat2,*tp2; register T *dp1,*dp2,*dp3; // register register double dat3; register double *tp3; int dim1xdim2 = xdim2*ydim2; int dx1, dy1, dz1; static double tablex[255], tabley[255], tablez[255]; double y, dx3, dy3, dz3, ds3; // new ones double x,x3,y3,z3,s3,x4,y4,z4,dat,*tp1,*tp1end,*tp2end,*tp3end; dx3=mat(0,0); dy3=mat(1,0); dz3=mat(2,0); ds3=mat(3,0); vol -= (1 + xdim2*(1 + ydim2)); for(y=1; y<=ydim1; y++) { x3 = mat(0,3) + y*mat(0,1); y3 = mat(1,3) + y*mat(1,1); z3 = mat(2,3) + y*mat(2,1); s3 = mat(3,3) + y*mat(3,1); for(x=1; x<=xdim1; x++) { s3 += ds3; if (s3 == 0.0) return(-1); x4=(x3 += dx3)/s3; y4=(y3 += dy3)/s3; z4=(z3 += dz3)/s3; if (z4>=1.0-TINY && z4<=(double)zdim2+TINY && y4>=1.0-TINY && y4<=(double)ydim2+TINY && x4>=1.0-TINY && x4<=(double)xdim2+TINY) { dat=0.0; make_lookup(x4, nn, xdim2, &dx1, tablex, &tp3end); make_lookup(y4 , nn, ydim2, &dy1, tabley, &tp2end); make_lookup(z4, nn, zdim2, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= xdim2; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { dp2 = dp1 + dy1; dat2 = 0.0; tp2 = tabley; while (tp2 <= tp2end) { dat3 = 0.0; tp3 = tablex; dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += xdim2; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } *(image++) = dat; } else *(image++) = background; } } return(0); } voxbo-1.8.5~svn1246/crunch/resample.cpp000066400000000000000000000446331153177201300177340ustar00rootroot00000000000000 // resample.cpp // sinc resampling of volumes, adapted from spm // Copyright (c) 1998-2004 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // note that the guts of the underlying sinc resample code were ported // from SPM96b source code written for MATLAB by John Ashburner using namespace std; #include "vbcrunch.h" class Resample { private: string imagename; // name of the image to be normalized string refname; // name of the reference image string outname; // name of the output image vector newheaders; // headers to be added to output file enum {vb_3d,vb_4d} mode; enum {vb_nn,vb_sinc} method; tokenlist args; // structure to be used for argument parsing CrunchCube *mycube,*newcube; Tes *mytes,*newtes; double zsize; // size of slices in mm double x1,y1,z1; // start voxel (0 indexed) in x,y,z int nx,ny,nz; // number of voxels in resampled image int dimx,dimy,dimz; // original dimensions double voxsize[3]; // original voxsize double xstep,ystep,zstep; // resample interval in voxels public: Resample(int argc,char **argv); ~Resample(); void init(); int Setup(); // set up parameters int ResampleFile(); // detect filetype int Resample3D(); // set up for 3d int Resample4D(); // set up for 4d int ResampleCube(); // dispatch to sinc or nn resample int SincResampleCube(); // do it for each cube int NNResampleCube(); // do it for each cube void AdjustCornerAndOrigin(VBImage &im); // methods for working out the resample parameters int UseZ(const string &refname,double zsize); int UseDims(const string &refname); int UseTLHC(const string &refname); int UseCorner(const string &refname); int SetAlign(const string mode,const string ref); }; void resample_help(); int main(int argc,char *argv[]) { tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs resample_help(); exit(0); } Resample *r=new Resample(argc,argv); // init resample object, parse args if (!r) { printf("*** resample: couldn't allocate a tiny structure\n"); exit(5); } int err; err=r->Setup(); // set the start, stop, nslices, etc. if (!err) err = r->ResampleFile(); // do it delete r; // clean up if (err) printf("*** resample: error resampling (%d).\n",err); else printf("resample: done.\n"); exit(err); } void Resample::init() { imagename=refname=""; zsize=0.0; x1=y1=z1=0; xstep=ystep=zstep=1.0; nx=41; ny=51; nz=27; method=vb_sinc; } Resample::Resample(int argc,char *argv[]) { init(); args.Transfer(argc-1,argv+1); } int Resample::Setup() { if (args.size() < 2) { printf("*** resample: requires at least an input and an output filename\n"); return 110; } switch(EligibleFileTypes(args[0])[0].getDimensions()) { case 4: mytes = new Tes; mytes->ReadFile(args[0]); if (!mytes->data_valid) { printf("*** resample: invalid 4D file: %s\n",args[0].c_str()); delete mytes; mytes=NULL; return 100; } dimx=mytes->dimx; dimy=mytes->dimy; dimz=mytes->dimz; voxsize[0]=mytes->voxsize[0]; voxsize[1]=mytes->voxsize[1]; voxsize[2]=mytes->voxsize[2]; mode=vb_4d; break; case 3: mycube = new CrunchCube; mycube->ReadFile(args[0]); if (!mycube->data_valid) { printf("*** resample: invalid 3D file: %s\n",args[0].c_str()); delete mycube; mycube=NULL; return 101; } dimx=mycube->dimx; dimy=mycube->dimy; dimz=mycube->dimz; voxsize[0]=mycube->voxsize[0]; voxsize[1]=mycube->voxsize[1]; voxsize[2]=mycube->voxsize[2]; mode=vb_3d; break; default: printf("*** resample: can only resample 3D and 4D data\n"); return 102; break; } x1=y1=z1=0; xstep=ystep=zstep=1.0; nx=dimx; ny=dimy; nz=dimz; for (int i=0; idimx-1; xstep=-1; nx=mycube->dimx; } else if (args[i]=="--flipy") { y1=mycube->dimy-1; ystep=-1; ny=mycube->dimy; } else if (args[i]=="--flipz") { z1=mycube->dimz-1; zstep=-1; nz=mycube->dimz; } } char tmps[STRINGLEN]; sprintf(tmps,"resample_x: start %.6f step %.2f count %d",x1,xstep,nx); newheaders.push_back(tmps); printf("[I] resample: %s\n",tmps); sprintf(tmps,"resample_y: start %.6f step %.2f count %d",y1,ystep,ny); newheaders.push_back(tmps); printf("[I] resample: %s\n",tmps); sprintf(tmps,"resample_z: start %.6f step %.2f count %d",z1,zstep,nz); newheaders.push_back(tmps); printf("[I] resample: %s\n",tmps); return 0; } Resample::~Resample() { } int Resample::SetAlign(const string mode,const string ref) { Cube refcube; if (refcube.ReadFile(refname)) return 100; if (mode=="-aa" || mode=="-ax") { if (ref=="origin") x1=(float)mycube->origin[0]-(((float)refcube.origin[0]*refcube.voxsize[0])/mycube->voxsize[0]); } if (mode=="-aa" || mode=="-ay") { if (ref=="origin") y1=(float)mycube->origin[1]-(((float)refcube.origin[1]*refcube.voxsize[1])/mycube->voxsize[1]); } if (mode=="-aa" || mode=="-az") { if (ref=="origin") z1=(float)mycube->origin[2]-(((float)refcube.origin[2]*refcube.voxsize[2])/mycube->voxsize[2]); } return 0; } int Resample::UseCorner(const string &refname) { Cube refcube; stringstream tmps; if (refcube.ReadFile(refname)) { Tes reftes; if (!(reftes.ReadFile(refname))) { refcube=reftes[0]; } else { printf("*** resample: invalid reference file: %s\n",refname.c_str()); return 501; // panic and exit } } // first get the corner coordinates of both images tokenlist ourline,refline; ourline.ParseLine(mycube->GetHeader("AbsoluteCornerPosition:")); refline.ParseLine(refcube.GetHeader("AbsoluteCornerPosition:")); if (ourline.size()!=3) { tmps.str(""); tmps << "resample: input image file doesn't have an absolute corner position tag"; printErrorMsg(VB_ERROR,tmps.str()); return 101; } if (refline.size()!=3) { tmps.str(""); tmps << "resample: reference image file doesn't have an absolute corner position tag"; printErrorMsg(VB_ERROR,tmps.str()); return 101; } double ourpos[3],refpos[3]; ourpos[0]=strtod(ourline[0]); ourpos[1]=strtod(ourline[1]); ourpos[2]=strtod(ourline[2]); refpos[0]=strtod(refline[0]); refpos[1]=strtod(refline[1]); refpos[2]=strtod(refline[2]); // find the start point x1=(refpos[0]-ourpos[0])/mycube->voxsize[0]; y1=(refpos[1]-ourpos[1])/mycube->voxsize[1]; z1=(refpos[2]-ourpos[2])/mycube->voxsize[2]; // the sampling interval should provide for 4x resolution in-plane xstep=(refcube.voxsize[0]/4.0)/mycube->voxsize[0]; ystep=(refcube.voxsize[1]/4.0)/mycube->voxsize[1]; zstep=refcube.voxsize[2]/mycube->voxsize[2]; // the number of voxels should be the width of the target image nx=refcube.dimx*4; ny=refcube.dimy*4; nz=refcube.dimz; return 0; } int Resample::UseZ(const string &refname,double zsize) { CrunchCube *refcube; refcube = new CrunchCube; refcube->ReadFile(refname); if (!refcube->data_valid) { printf("*** resample: invalid 3D file: %s\n",refname.c_str()); delete refcube; return 501; // panic and exit } double ourstart,ourend,refstart,refend; // old style: startloc/endloc ourstart=strtod(mycube->GetHeader("StartLoc:")); ourend=strtod(mycube->GetHeader("EndLoc:")); refstart=strtod(refcube->GetHeader("StartLoc:")); refend=strtod(refcube->GetHeader("EndLoc:")); // new style: zrange string refzrange=refcube->GetHeader("ZRange:"); string ourzrange=mycube->GetHeader("ZRange:"); if (refzrange.size()) { tokenlist range(refzrange); refstart=strtod(range[0]); refend=strtod(range[1]); } if (ourzrange.size()) { tokenlist range(ourzrange); ourstart=strtod(range[0]); ourend=strtod(range[1]); } if (zsize < .001) zsize=refcube->voxsize[2]; nx=dimx; ny=dimy; z1=(refstart-ourstart)/voxsize[2]; nz=(int)((abs(refend-refstart)/zsize)+0.5)+1; zstep=zsize/voxsize[2]; delete refcube; return 0; } int Resample::UseDims(const string &refname) { CrunchCube *refcube; refcube = new CrunchCube; refcube->ReadFile(refname); if (!refcube->data_valid) { printf("*** resample: invalid 3D file: %s\n",args[1].c_str()); delete refcube; return 501; // panic and exit } nx=refcube->dimx; ny=refcube->dimy; nz=refcube->dimz; // FIXME is the following correct? xstep=(double)(dimx)/nx; ystep=(double)(dimy)/ny; zstep=(double)(dimz)/nz; delete refcube; return 0; } int Resample::UseTLHC(const string &refname) { CrunchCube *refcube; refcube = new CrunchCube; refcube->ReadFile(refname); if (!refcube->data_valid) { printf("*** resample: invalid 3D file: %s\n",refname.c_str()); delete refcube; return 501; // panic and exit } double ourLR,refLR,ourAP,refAP; ourLR=refLR=ourAP=refAP=0.0; // new style: zrange string reftlhc=refcube->GetHeader("im_tlhc:"); string ourtlhc=mycube->GetHeader("im_tlhc:"); if (reftlhc.size()) { tokenlist range(reftlhc); refLR=strtod(range[0]); refAP=strtod(range[1]); } if (ourtlhc.size()) { tokenlist range(ourtlhc); ourLR=strtod(range[0]); ourAP=strtod(range[1]); } nx=dimx; ny=dimy; nz=dimz; x1=y1=z1=0; xstep=ystep=zstep=1.0; if (abs(ourLR-refLR)>0.001) { x1=(ourLR-refLR)/mycube->voxsize[0]; } if (abs(ourAP-refAP)>0.001) { y1=(refAP-ourAP)/mycube->voxsize[1]; } if (x1==0 && y1==0) { printf("resample: no fov adjustment neeeded\n"); } delete refcube; return 0; } int Resample::ResampleFile() { printf("resample: resampling %s\n",args[0].c_str()); if (mode == vb_3d) return Resample3D(); else if (mode == vb_4d) return Resample4D(); else { printf("*** resample: error\n"); return 200; } } int Resample::Resample3D() { stringstream tmps; if (ResampleCube()) return 101; newcube->SetFileName(args[1]); newcube->SetFileFormat(mycube->GetFileFormat()); newcube->header=mycube->header; if (mycube->origin[0]) { newcube->origin[0]=lround((mycube->origin[0]-x1)/xstep); newcube->origin[1]=lround((mycube->origin[1]-y1)/ystep); newcube->origin[2]=lround((mycube->origin[2]-z1)/zstep); } // add new headers for (size_t i=0; iAddHeader(newheaders[i]); newcube->AddHeader((string)"resample_date: "+timedate()); AdjustCornerAndOrigin(*newcube); if (newcube->WriteFile()) printf("*** resample: error writing %s\n",args[1].c_str()); else printf("resample: wrote %s.\n",args[1].c_str()); delete newcube; return 0; } int Resample::Resample4D() { newtes=new Tes(); newtes->SetVolume(nx,ny,nz,mytes->dimt,mytes->datatype); newtes->voxsize[0]=fabs(xstep*mytes->voxsize[0]); newtes->voxsize[1]=fabs(ystep*mytes->voxsize[1]); newtes->voxsize[2]=fabs(zstep*mytes->voxsize[2]); if (mytes->origin[0]) { newtes->origin[0]=lround((mytes->origin[0]-x1)/xstep); newtes->origin[1]=lround((mytes->origin[1]-y1)/ystep); newtes->origin[2]=lround((mytes->origin[2]-z1)/zstep); } for (int i=0; idimt; i++) { mycube=new CrunchCube((*mytes)[i]); if (ResampleCube()) return 102; newtes->SetCube(i,newcube); delete newcube; delete mycube; } // add new headers for (size_t i=0; iAddHeader(newheaders[i]); newtes->AddHeader((string)"resample_date: "+timedate()); newtes->SetFileName(args[1]); newtes->SetFileFormat(mytes->GetFileFormat()); newtes->header=mytes->header; AdjustCornerAndOrigin(*newtes); if (int err=newtes->WriteFile()) printf("*** resample: error %d writing %s\n",err,args[1].c_str()); else printf("resample: wrote %s.\n",args[1].c_str()); return 0; } void Resample::AdjustCornerAndOrigin(VBImage &im) { vector newheader; tokenlist args; for (size_t i=0; iSetVolume(nx,ny,nz,mycube->datatype); newcube->voxsize[0]=fabs(xstep*mycube->voxsize[0]); newcube->voxsize[1]=fabs(ystep*mycube->voxsize[1]); newcube->voxsize[2]=fabs(zstep*mycube->voxsize[2]); for (k=0; kSetValue(i,j,k,mycube->GetValue(c1,c2,c3)); } } } return 0; // no error } int Resample::SincResampleCube() { int i,j,k; if (!mycube) return 5; newcube=new CrunchCube(); newcube->SetVolume(nx,ny,nz,mycube->datatype); newcube->voxsize[0]=fabs(xstep*mycube->voxsize[0]); newcube->voxsize[1]=fabs(ystep*mycube->voxsize[1]); newcube->voxsize[2]=fabs(zstep*mycube->voxsize[2]); RowVector c1(1),c2(1),c3(1),out(1); for (k=0; kdatatype) { case vb_byte: resample_sinc(1,(unsigned char *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_short: resample_sinc(1,(short *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_long: resample_sinc(1,(int *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_float: resample_sinc(1,(float *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_double: resample_sinc(1,(double *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; } newcube->SetValue(i,j,k,out(0)); } } } return 0; // no error } void resample_help() { printf("\nVoxBo resample (v%s)\n",vbversion.c_str()); printf("usage: resample [flags]\n"); printf("flags:\n"); printf(" -rr ref=image in desired space\n"); printf(" -rc ref=image with desired field of view\n"); printf(" -rz [z] same but specify size in z\n"); printf(" -rd ref=image of desired dimensions\n"); printf(" -ra aligns to ref on all dims, using corner position\n"); printf(" -d desired dimensions\n"); printf(" -nn use nearest neighbor interpolation (default is sinc)\n"); printf(" -xx a=start voxel (from 0); b=interval in voxels; c=# of voxels\n"); printf(" -yy same for y dimension\n"); printf(" -zz same for z dimension\n"); printf("\n"); printf(" -r generic ref cube\n"); printf(" -aa, -ax, -ay, -az [origin/corner]\n"); printf(" -sa, -sx, -sy, -sz [n]\n"); printf("\n"); printf("Some examples for an axial image of dimensions 64x64x21:\n"); printf(" invert the order of the slices: resample in.cub out.cub -zz 20 -1 21\n"); printf(" swap left-right: resample in.cub out.cub -xx 63 -1 64\n"); printf(" interpolate in-plane: resample in.cub out.cub -xx 0 .25 256 -yy 0 .25 256\n"); printf(" crop to 40x64x21: resample in.cub out.cub -xx 12 1 40\n"); printf("\n"); } voxbo-1.8.5~svn1246/crunch/smooth.cpp000066400000000000000000000044601153177201300174270ustar00rootroot00000000000000 // smooth.cpp // VoxBo smoothing module // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // The guts of the underlying code were based on SPM source code // written in MATLAB by John Ashburner. See the SPM web site at: // (http://www.fil.ion.bpmf.ac.uk/spm/) using namespace std; #include "vbcrunch.h" class Smoothing { private: string infile,outfile; int s0,s1,s2; public: Smoothing(int argc,char **argv); ~Smoothing(); int Crunch(); }; void vbsmooth_help(); int main(int argc,char *argv[]) { tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs realign_help(); exit(0); } Smoothing *r=new Smoothing(argc,argv); // init realign object if (!r) { printf("smoothing error: couldn't allocate a tiny structure\n"); exit(5); } int error = r->Crunch(); // do the crunching delete r; // clean up exit(error); } Smoothing::Smoothing(int argc,char *argv[]) { if (argc != 4 && argc != 6) { smooth_help(); exit(5); } infile=argv[1]; outfile=argv[2]; s0=s1=s2=strtod(argv[3],NULL); if (argc == 6) { s1=strtod(argv[4],NULL); s2=strtod(argv[5],NULL); } } int Smoothing::Crunch() { } Smoothing::~Smoothing() { } void smooth_help() { printf("smooth - another fine component of VoxBo!\n\n"); printf("usage: smooth [s2 s3]\n"); } voxbo-1.8.5~svn1246/crunch/smoothutils.cpp000066400000000000000000000406051153177201300205110ustar00rootroot00000000000000 // smooth.cpp // smoothing and related routines for use in realignment and normalization // new code Copyright (c) 1998-2002 by The VoxBo Development Team // based on original MATLAB code for SPM by John Ashburner // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbcrunch.h" CrunchCube * dan_smooth_image(CrunchCube *map,int s0,int s1,int s2) { CrunchCube *V; RowVector S(3),ijk(3); Matrix mtmp; int i,j,k; double xsum,ysum,zsum; short x1,y1,z1; S(0) = s0; S(1) = s1; S(2) = s2; // compute convolution parameters S(0) /= map->voxsize[0]; S(1) /= map->voxsize[1]; S(2) /= map->voxsize[2]; if (S(0) < 1) S(0) = 1; if (S(1) < 1) S(1) = 1; if (S(2) < 1) S(2) = 1; S(0) = S(0) / sqrt(8.0*log(2.0)); S(1) = S(1) / sqrt(8.0*log(2.0)); S(2) = S(2) / sqrt(8.0*log(2.0)); x1 = (short)round(6.0*S(0)); y1 = (short)round(6.0*S(1)); z1 = (short)round(6.0*S(2)); RowVector x((2*x1)+1); RowVector y((2*y1)+1); RowVector z((2*z1)+1); for (i=-x1; i <= x1; i++) x(i+x1) = i; for (i=-y1; i <= y1; i++) y(i+y1) = i; for (i=-z1; i <= z1; i++) z(i+z1) = i; for (i=0; i < x.length(); i++) x(i) = exp(-pow(x(i),2) / (2*pow(S(0),2))); for (i=0; i < y.length(); i++) y(i) = exp(-pow(y(i),2) / (2*pow(S(1),2))); for (i=0; i < z.length(); i++) z(i) = exp(-pow(z(i),2) / (2*pow(S(2),2))); xsum = sum(x); ysum = sum(y); zsum = sum(z); for (i=0; i < x.length(); i++) x(i) /= xsum; for (i=0; i < y.length(); i++) y(i) /= ysum; for (i=0; i < z.length(); i++) z(i) /= zsum; i = (x.length() - 1)/2; j = (y.length() - 1)/2; k = (z.length() - 1)/2; ijk(0) = -i; ijk(1) = -j; ijk(2) = -k; V = new CrunchCube(map); dan_conv_image(map,V,x,y,z,ijk); mtmp = dan_get_space_image(map); dan_get_space_image(V,mtmp); return V; } short fixshort(double tmp) { if (tmp > 32767.0) tmp=32767.0; if (tmp < -32768.0) tmp=-32768.0; return((short)round(tmp)); } // dan_conv_image // applies the gaussian filter (computed in dan_smooth()) to the provided image void dan_conv_image(CrunchCube *map,CrunchCube *newmap,const RowVector &filtx, const RowVector &filty,const RowVector &filtz, const RowVector &offsets) { int xdim,ydim,zdim; unsigned char *Vol; double *tmp; xdim = (int)(map->dimx); ydim = (int)(map->dimy); zdim = (int)(map->dimz); if (!map->data || !newmap->data) { cerr << "bad map or newmap came into conv_image()" << endl; exit(0); } Vol = map->data; // Vol = data in memory // xdim, ydim, zdim tmp = new double[xdim*ydim*zdim]; if (!tmp) { cerr << "failed to allocate space for an image" << endl; exit(0); } for (int i=0; idatatype,tmp) != 0) { fprintf(stderr,"error in conv_image - convxyz returned an error code\n"); } if (map->datatype == vb_long) { for(int i=0; ivoxels; i++) ((int *)newmap->data)[i] = (int)round(tmp[i]); } else if (map->datatype == vb_short) { for(int i=0; ivoxels; i++) ((short *)(newmap->data))[i] = (short)round(tmp[i]); } else if (map->datatype == vb_byte) { for(int i=0; ivoxels; i++) ((unsigned char *)(newmap->data))[i] = (unsigned char)(tmp[i] + 0.5); } else if (map->datatype == vb_float) { for(int i=0; ivoxels; i++) ((float *)(newmap->data))[i] = (float)tmp[i]; } else if (map->datatype == vb_double) { for(int i=0; ivoxels; i++) ((float *)(newmap->data))[i] = tmp[i]; } else { fprintf(stderr,"error in conv_image: unrecognized datatype.\n"); } delete [] tmp; } int convxyz(unsigned char *vol,int xdim,int ydim,int zdim, const RowVector &filtx,const RowVector &filty,const RowVector &filtz, int fxdim,int fydim,int fzdim,int xoff,int yoff,int zoff,FILE *fp, int datatype,double *ovol) { double *tmp, *buff, **sortedv, *obuf; int xy, z, k, fstart, fend, startz, endz; if (fp != (FILE *)0) { cerr << "bogus args to convxyz" << endl; exit(0); } tmp = (double *)calloc(xdim*ydim*fzdim,sizeof(double)); buff = (double *)calloc(((ydim>xdim) ? ydim : xdim),sizeof(double)); obuf = (double *)calloc(xdim*ydim,sizeof(double)); sortedv = (double **)calloc(fzdim, sizeof(double *)); startz = ((fzdim+zoff-1<0) ? fzdim+zoff-1 : 0); endz = zdim+fzdim+zoff-1; if (!buff || !tmp || !obuf || !sortedv) { cerr << "Serious allocation problem in convxyz" << endl; return 0; } for (z=startz; z= 0 && z=0 && z-fzdim-zoff+1= zdim) ? z-zdim+1 : 0); fend = ((z-fzdim < 0) ? z+1 : fzdim); for(k=0; k 255.0) obuf[xy]=255.0; if (obuf[xy] < 0.0) obuf[xy]=0.0; } break; case vb_short: for(xy=0; xy 32767.0) obuf[xy]=32767.0; if (obuf[xy] < -32768.0) obuf[xy]=-32768.0; } break; case vb_long: break; case vb_float: break; case vb_double: break; default: cerr << "Unrecognized type in convxyz() in smooth.cpp." << endl; break; } for(xy=0; xy= xdim) ? x-xdim-xoff+1 : 0); fend = ((x-(xoff+fxdim) < 0) ? x-xoff+1 : fxdim); for(k=fstart; k= ydim) ? y-ydim-yoff+1 : 0); fend = ((y-(yoff+fydim) < 0) ? y-yoff+1 : fydim); for(k=fstart; kdim) /* Pixel location outside image */ *ptpend = table-1; else { table[0]=1.0; *ptpend = table; } } else { fcoord = (int)floor(coord); *d1 = fcoord-nn; if (*d1<1) *d1=1; d2 = fcoord+nn; if (d2>dim) d2 = dim; *ptpend = tpend = table+(d2 - *d1); d = *d1, tp = table; while (tp <= tpend) { dtmp = PI*(coord-(double)(d++)); *(tp++) = sin(dtmp)/dtmp* 0.5*(1.0 + cos(dtmp/nn)) ; } } } // Sinc resampling int slice_int_sinc(const Matrix &mat,double *image,int xdim1,int ydim1,int *vol, int xdim2,int ydim2,int zdim2,int nn,double background) { int dim1xdim2 = xdim2*ydim2; int dx1, dy1, dz1; static double tablex[255], tabley[255], tablez[255]; double y, dx3, dy3, dz3, ds3; double x4,y4,z4; double dat,*tp1,*tp1end,*tp2end,*tp3end; int *dp1,*dp2; register double dat3,*tp3; register int *dp3; dx3=mat(0,0); dy3=mat(1,0); dz3=mat(2,0); ds3=mat(3,0); vol -= (1 + xdim2*(1 + ydim2)); for(y=1; y<=ydim1; y++) { double x; double x3 = mat(0,3) + y*mat(0,1); double y3 = mat(1,3) + y*mat(1,1); double z3 = mat(2,3) + y*mat(2,1); double s3 = mat(3,3) + y*mat(3,1); for(x=1; x<=xdim1; x++) { //double x4,y4,z4; s3 += ds3; if (s3 == 0.0) return(-1); x4=(x3 += dx3)/s3; y4=(y3 += dy3)/s3; z4=(z3 += dz3)/s3; if (z4>=1.0-TINY && z4<=(double)zdim2+TINY && y4>=1.0-TINY && y4<=(double)ydim2+TINY && x4>=1.0-TINY && x4<=(double)xdim2+TINY) { //int *dp1; //double dat=0.0, *tp1, *tp1end, *tp2end, *tp3end; dat = 0.0; make_lookup(x4, nn, xdim2, &dx1, tablex, &tp3end); make_lookup(y4 , nn, ydim2, &dy1, tabley, &tp2end); make_lookup(z4, nn, zdim2, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= xdim2; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { //int *dp2 = dp1 + dy1; dp2 = dp1+dy1; double dat2 = 0.0, *tp2 = tabley; while (tp2 <= tp2end) { //register double dat3 = 0.0, *tp3 = tablex; //register int *dp3 = dp2 + dx1; dat3 = 0.0; tp3 = tablex; dp3 = dp2+dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += xdim2; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } *(image++) = dat; } else *(image++) = background; } } return(0); } int slice_short_sinc(const Matrix &mat,double *image,int xdim1,int ydim1, short *vol, int xdim2,int ydim2,int zdim2,int nn,double background) { register double dat3,*tp3; register short *dp3; register double dat2,*tp2; register short *dp1,*dp2; int dim1xdim2 = xdim2*ydim2; int dx1, dy1, dz1; static double tablex[255], tabley[255], tablez[255]; double y, dx3, dy3, dz3, ds3; // new ones double x,x3,y3,z3,s3,x4,y4,z4,dat,*tp1,*tp1end,*tp2end,*tp3end; dx3=mat(0,0); dy3=mat(1,0); dz3=mat(2,0); ds3=mat(3,0); vol -= (1 + xdim2*(1 + ydim2)); for(y=1; y<=ydim1; y++) { x3 = mat(0,3) + y*mat(0,1); y3 = mat(1,3) + y*mat(1,1); z3 = mat(2,3) + y*mat(2,1); s3 = mat(3,3) + y*mat(3,1); for(x=1; x<=xdim1; x++) { s3 += ds3; if (s3 == 0.0) return(-1); x4=(x3 += dx3)/s3; y4=(y3 += dy3)/s3; z4=(z3 += dz3)/s3; if (z4>=1.0-TINY && z4<=(double)zdim2+TINY && y4>=1.0-TINY && y4<=(double)ydim2+TINY && x4>=1.0-TINY && x4<=(double)xdim2+TINY) { dat=0.0; make_lookup(x4, nn, xdim2, &dx1, tablex, &tp3end); make_lookup(y4 , nn, ydim2, &dy1, tabley, &tp2end); make_lookup(z4, nn, zdim2, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= xdim2; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { dp2 = dp1 + dy1; dat2 = 0.0; tp2 = tabley; while (tp2 <= tp2end) { dat3 = 0.0; tp3 = tablex; dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += xdim2; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } *(image++) = dat; } else *(image++) = background; } } return(0); } int slice_short_sinc_threaded(const Matrix &mat,double *image,int xdim1,int ydim1, short *vol, int xdim2,int ydim2,int zdim2,int nn,double background) { register double dat3,*tp3; register short *dp3; register double dat2,*tp2; register short *dp1,*dp2; int dim1xdim2 = xdim2*ydim2; int dx1, dy1, dz1; static double tablex[255], tabley[255], tablez[255]; double y, dx3, dy3, dz3, ds3; // new ones double x,x3,y3,z3,s3,x4,y4,z4,dat,*tp1,*tp1end,*tp2end,*tp3end; dx3=mat(0,0); dy3=mat(1,0); dz3=mat(2,0); ds3=mat(3,0); vol -= (1 + xdim2*(1 + ydim2)); for(y=1; y<=ydim1; y++) { x3 = mat(0,3) + y*mat(0,1); y3 = mat(1,3) + y*mat(1,1); z3 = mat(2,3) + y*mat(2,1); s3 = mat(3,3) + y*mat(3,1); for(x=1; x<=xdim1; x++) { s3 += ds3; if (s3 == 0.0) return(-1); x4=(x3 += dx3)/s3; y4=(y3 += dy3)/s3; z4=(z3 += dz3)/s3; if (z4>=1.0-TINY && z4<=(double)zdim2+TINY && y4>=1.0-TINY && y4<=(double)ydim2+TINY && x4>=1.0-TINY && x4<=(double)xdim2+TINY) { dat=0.0; make_lookup(x4, nn, xdim2, &dx1, tablex, &tp3end); make_lookup(y4 , nn, ydim2, &dy1, tabley, &tp2end); make_lookup(z4, nn, zdim2, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= xdim2; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { dp2 = dp1 + dy1; dat2 = 0.0; tp2 = tabley; while (tp2 <= tp2end) { dat3 = 0.0; tp3 = tablex; dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += xdim2; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } *(image++) = dat; } else *(image++) = background; } } return(0); } // dan_get_space_image() // two functions, one takes a matrix, one doesn't Matrix dan_get_space_image(CrunchCube *map) { Matrix M(4,4); RowVector off(3),orig(3); if (map->savedM.cols() == 4) { return map->savedM; } orig(0)= map->origin[0]; orig(1)= map->origin[1]; orig(2)= map->origin[2]; if ((int)orig(0) == 0 && (int)orig(1)==0 && (int)orig(2) ==0) { orig(0)=map->dimx/2.0; orig(1)=map->dimy/2.0; orig(2)=map->dimz/2.0; } off(0)=map->voxsize[0] * -1.0; off(1)=map->voxsize[1] * -1.0; off(2)=map->voxsize[2] * -1.0; off = product(off,orig); M(0,0) = map->voxsize[0]; M(0,1) = 0; M(0,2) = 0; M(0,3) = off(0); M(1,0) = 0; M(1,1) = map->voxsize[1]; M(1,2) = 0; M(1,3) = off(1); M(2,0) = 0; M(2,1) = 0; M(2,2) = map->voxsize[2]; M(2,3) = off(2); M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1; return M; } Matrix dan_get_space_image(CrunchCube *map,const Matrix &matrix) { Matrix M(4,4),mt(4,4); RowVector off(3),vx(3); int i,j; double sum; // delete the matrix if it exists map->savedM.resize(0,0); M = matrix; vx(0)=abs(M(0,0)); vx(1)=abs(M(1,1)); vx(2)=abs(M(2,2)); off(0)=-(vx(0)) * round(-M(0,3) / vx(0)); off(1)=-(vx(1)) * round(-M(1,3) / vx(1)); off(2)=-(vx(2)) * round(-M(2,3) / vx(2)); mt(0,0) = vx(0); mt(0,1) = 0; mt(0,2) = 0; mt(0,3) = off(0); mt(1,0) = 0; mt(1,1) = vx(1); mt(1,2) = 0; mt(1,3) = off(1); mt(2,0) = 0; mt(2,1) = 0; mt(2,2) = vx(2); mt(2,3) = off(2); mt(3,0) = 0; mt(3,1) = 0; mt(3,2) = 0; mt(3,3) = 1; sum=0.0; for(i=0; i<4; i++) for(j=0; j<4; j++) sum += pow(matrix(i,j) * mt(i,j),2); if (sum > (double)(FLT_MIN * FLT_MIN * 12.0)) map->savedM = M; return M; } voxbo-1.8.5~svn1246/crunch/utils.cpp000066400000000000000000000074161153177201300172620ustar00rootroot00000000000000 // utils.cpp // dumb utility functions for various parts of the realign port // Copyright (c) 1998-2003 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbcrunch.h" int suffix_hdr(char *fname) { int i; i=strlen(fname); if (i < 5) strcat(fname,".hdr"); else if (fname[i-4] != '.') strcat(fname,".hdr"); else strcpy(fname+i-3,"hdr"); return 1; } int suffix_img(char *fname) { int i; i=strlen(fname); if (i < 5) strcat(fname,".img"); else if (fname[i-4] != '.') strcat(fname,".img"); else strcpy(fname+i-3,"img"); return 1; } int suffix_mat(char *fname) { int i; i=strlen(fname); if (i < 5) strcat(fname,".mat"); else if (fname[i-4] != '.') strcat(fname,".mat"); else strcpy(fname+i-3,"mat"); return 1; } int get_datasize(int type) { if (type == vb_byte) return(sizeof(unsigned char)); else if (type == vb_short) return(sizeof(short)); else if (type == vb_long) return(sizeof(int)); else if (type == vb_float) return(sizeof(float)); else if (type == vb_double) return(sizeof(double)); else return(0); } double sum(const RowVector &v) { double tot=0.0; for(int i=0; i (int)(strlen(fullname)-2)) { cerr << "error: parsename(): no filename" << endl; return FALSE; } if (ind>-1) { fullname[ind]='\0'; strcpy(dirname,fullname); strcat(dirname,"/"); strcpy(outfilename,fullname+ind+1); } else { strcpy(outfilename,fullname); dirname[0]='\0'; } return TRUE; } void print(const Matrix &mat,int size) { print("Anonymous matrix",mat,size); } void print(const RowVector &vec,int size) { print("Anonymous rowvector",vec,size); } void print(const char *s,const Matrix &mat,int size) { int i,j; j=0; cerr << endl << s << "(" << mat.rows() << "x" << mat.cols() << "):" << endl; for (i=0; i. // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // vbcrunch.h // headers needed for crunching stuff using namespace std; #include #include #include #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" #include #define PI 3.14159265358979 #define MAGIC 110494 #define TINY 0.05 #ifndef MAX #define MAX(a,b) (((a)>(b)) ? (a) : (b)) #endif #ifndef MIN #define MIN(a,b) (((a)>(b)) ? (b) : (a)) #endif // the crunchcube class is an inheritor of the Cube class that adds a // few data structures for doing things like realignment, etc. I'd // have put these in the parent class but this way the i/o lib doesn't // require matrix structures, etc. class CrunchCube : public Cube { public: Matrix M,savedM,M1; RowVector transform; CrunchCube(); CrunchCube(const Cube &cub); void Init(); void Preview(char *title); }; // prototypes from dan_smooth.c void convxy(unsigned char *pl,int dimx,int dimy, const RowVector &filtx,const RowVector &filty, int fxdim,int fydim,int xoff, int yoff,double *out,double *buff,int datatype); int convxyz(unsigned char *vol,int dimx,int dimy,int dimz, const RowVector &filtx,const RowVector &filty,const RowVector &filtz, int fxdim,int fydim,int fzdim,int xoff,int yoff,int zoff,FILE *fp, int datatype,double *ovol); void dan_conv_vol(CrunchCube *,char *,RowVector ,RowVector ,RowVector ,RowVector ); //int dan_hread(char *,IMG_header &); //int dan_hwrite(char *,IMG_header &); CrunchCube *dan_map_vol(char *); int suffix_hdr(char *); int suffix_img(char *); int suffix_mat(char *); int get_datasize(int foo); void dan_unmap_vol(CrunchCube *); Matrix dan_bb(char *); Matrix diff(const Matrix &); Matrix dan_slice_vol(CrunchCube *map,const Matrix &mat,int m,int n,int hold); Matrix dan_matrix(const RowVector &P); void copysegment(Matrix &to,const Matrix &from,int count,int offset); RowVector dan_linspace(double first,double last,int points); Matrix dan_reshape44(Matrix m,int col); void dan_bound(RowVector &vec,double low,double high); RowVector vectorize(const Matrix &in); Matrix backslash(const Matrix &one,const Matrix &two); Matrix dan_box(char *filename,RowVector dim,short type); int realign_compute(int nfiles,char **filename); int parsename(char *fname,char *dirname,char *outfilename); int parse_filelist(char *filename,char ***argv); void make_lookup(double coord,int nn,int dim,int *d1,double *table, double **ptpend); int slice_int_sinc(const Matrix &mat,double *image,int xdim1,int ydim1, int *vol, int xdim2,int ydim2,int zdim2,int nn,double background); int slice_short_sinc(const Matrix &mat,double *image,int xdim1,int ydim1, short *vol, int xdim2,int ydim2,int zdim2,int nn,double background); template int slice_sinc(const Matrix &mat,double *image,int xdim1,int ydim1,T *vol, int xdim2,int ydim2,int zdim2,int nn,double background); void print(const Matrix &mat,int size=5); void print(const char *,const Matrix &mat,int size=5); void print(const RowVector &vec,int size=5); void print(const char *,const RowVector &vec,int size=5); void print(CrunchCube *map); void print(const char *s,const ColumnVector &vec,int size=5); void ident(Matrix &mat); // functions i don't still need to write double sum(const RowVector &v); CrunchCube *dan_smooth_image(CrunchCube *,int,int,int); Matrix dan_get_space_image(CrunchCube *); Matrix dan_get_space_image(CrunchCube *,const Matrix &); Matrix dan_bb_image(CrunchCube *); RowVector mask_from_image(CrunchCube *map,RowVector &,RowVector &); RowVector dan_slice_image(CrunchCube *,Matrix,int,int,int); void dan_conv_image(CrunchCube *,CrunchCube *,const RowVector&,const RowVector&, const RowVector&,const RowVector&); void dan_box_image(CrunchCube *map,RowVector &,RowVector &,RowVector &); void write_map(CrunchCube *map); CrunchCube *read_map(short datatype,short datasize,short x,short y,short z, float xsize,float ysize,float zsize); int realign_stdio(); int realign_rlist(char *rlist); int realign_args(int argc,char **argv); void read_short(FILE *fp,short &s); void read_long(FILE *fp,long &s); void read_float(FILE *fp,float &s); void read_char(FILE *fp,char *s,int len); void write_short(FILE *fp,short &s); void write_long(FILE *fp,long &s); void write_float(FILE *fp,float &s); void write_char(FILE *fp,char *,int len); CrunchCube *realign_twoimages(CrunchCube *REF,CrunchCube *SREF,CrunchCube *VOL); void printnonzero(void *,int len); //=============== // norm protos //=============== // return value globals extern Matrix ret_m1,ret_m2,ret_m3; extern double ret_d1; void mrqcof(RowVector &T,double alpha[],double beta[],double pss[],int dt2, double scale2,int dim2[],unsigned char dat2[],int ni,int dt1[], double scale1[],int dim1[],unsigned char *dat1[],int nx,double BX[], double dBX[],int ny,double BY[],double dBY[],int nz,double BZ[], double dBZ[],double M[],int samp[],int *pnsamp); int dan_brainwarp(CrunchCube *REF,CrunchCube *IMAGE,const Matrix &Affine, const Matrix &BX,const Matrix &BY,const Matrix &BZ, const Matrix &dBX,const Matrix &dBY,const Matrix &dBZ, const Matrix &T,double fwhm); int dan_sn3d(CrunchCube *REF,CrunchCube *IMAGE,Matrix &affine,Matrix &dims, Matrix &transform,Matrix &MF); CrunchCube * dan_write_sn(CrunchCube *VOL,Matrix &Affine,Matrix &Dims,Matrix &Transform, Matrix &MF,Matrix &bb,RowVector &Vox,int Hold,int affdefault=0); int dan_affsub1(CrunchCube *REF,CrunchCube *IMAGE,const Matrix &MG,const Matrix &MF, int Hold,int samp,const RowVector &P); RowVector dan_affsub2(CrunchCube *REF,CrunchCube *IMAGE,const Matrix &MG, const Matrix &MF,int Hold,int samp, RowVector P,const RowVector &free, const RowVector &pdesc); void atranspa(int m,int n,const Matrix &A,const Matrix &C); Matrix dan_atranspa(const Matrix &A); Matrix dan_dctmtx(int N,int K); Matrix dan_dctmtx(int N,int K,const RowVector &n); Matrix dan_dctmtxdiff(int N,int K); Matrix dan_dctmtxdiff(int N,int K,const RowVector &n); int dan_snbasis_map(CrunchCube *REF,CrunchCube *IMAGE,Matrix &Affine, int k1,int k2,int k3,int iter,int fwhm,double sd1); Matrix kron(const Matrix &A,const Matrix &B); RowVector dan_span(double from,double to,double increment); double get_element(const Matrix &m,int pos); Matrix reshape(const Matrix &mat,int m,int n); Matrix reshape(const RowVector &vec,int m,int n); Matrix reshape(const ColumnVector &vec,int m,int n); RowVector index(const Matrix &mat,const RowVector &vec); RowVector index(const RowVector &v1,const RowVector &vec); Matrix pinv(const Matrix &A); Matrix dan_sample_vol(CrunchCube *map,const RowVector &x,const RowVector &y, const RowVector &z,int hold); Matrix dan_sample_vol(CrunchCube *map,const Matrix &x,const Matrix &y, const Matrix &z,int hold); template void resample_sinc(int m,T *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,int nn,double background, double scale); template void resample_1(int m,T *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z,int dimx,int dimy, int dimz,double background,double scale); void resample_short_sinc(int m,short *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,int nn,double background, double scale); void resample_int_sinc(int m,int *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z, int dimx,int dimy,int dimz,int nn,double background, double scale); void resample_short_1(int m,short *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z,int dimx,int dimy, int dimz,double background,double scale); void resample_int_1(int m,int *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z,int dimx,int dimy, int dimz,double background,double scale); void resample_char_1(int m,unsigned char *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z,int dimx,int dimy, int dimz,double background,double scale); void resample_char_sinc(int m,unsigned char *vol,RowVector &out,const RowVector &x, const RowVector &y,const RowVector &z,int dimx,int dimy, int dimz,int nn,double background,double scale); Matrix ones(int m,int n); RowVector ones(int d); Matrix zeros(int m,int n); RowVector zeros(int d); double *arrayize(const RowVector &vec); double *arrayize(const Matrix &mat); voxbo-1.8.5~svn1246/crunch/vbmakefilter.cpp000066400000000000000000000215751153177201300205770ustar00rootroot00000000000000 // vbmakefilter.cpp // hack to create exofilt file // Copyright (c) 2005 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // written to accomplish the same thing as some original IDL code by // Geoff Aguirre using namespace std; #include #include #include #include #include "vbutil.h" #include "vbjobspec.h" #include "vbprefs.h" #include "vbio.h" #include VBPrefs vbp; class FilterParams { public: string exofiltname; string noisename; int lows,highs; // low and high frequencies to remove vector middles; // middle frequencies to remove string kernelname; // temporal smoothing kernel double kerneltr; // sampling interval of kernel file string noisemodel; // noise model int pri; double TR; int orderg; int init(tokenlist &args); int MakeNoise(); int MakeExoFilt(); }; void vbmakefilter_help(); void vbmakefilter_version(); int main(int argc,char **argv) { tokenlist args; args.Transfer(argc-1,argv+1); if (args.size() == 0) { vbmakefilter_help(); exit(0); } if (args[0]=="-h") { vbmakefilter_help(); exit(0); } if (args[0]=="-v") { vbmakefilter_version(); } FilterParams fp; if (fp.init(args)) exit(5); if (fp.MakeNoise()) exit(6); if (fp.MakeExoFilt()) exit(7); exit(0); } // this is the sole constructor, it chews on the passed arguments int FilterParams::init(tokenlist &args) { exofiltname=""; noisename=""; lows=highs=0; middles.clear(); kernelname=""; kerneltr=2000.0; noisemodel=""; pri=2; TR=2000.0; orderg=100; for (size_t i=0; i1) kerneltr=strtod(tmpl[1]); } printf("[I] vbmakefilter: using kernel TR of %.2f\n",kerneltr); } printf("[I] vbmakefilter: using data TR of %.2f\n",TR); for (i=0; i 0) { if (IRF.ReadFile(kernelname.c_str())) { printf("[E] vbmakefilter: couldn't read kernel file %s\n",kernelname.c_str()); return 101; // error! } } // interpolate the HRF to the resolution of your data if (kernelname.size()>0 && TR != kerneltr) { IRF=cspline_resize(IRF,kerneltr/TR); } // set exofilt to irf padded with zeros, scaled if (IRF.getLength()) { total=0.0; for (i=0; i<(int)IRF.getLength(); i++) { exofilt[i]=IRF[i]; total+=IRF[i]; } total /= orderg; for (i=0; infreq) continue; realp(i+1)=imagp(i+1)=0.0; realp(orderg-i-1)=imagp(orderg-i-1)=0.0; } } for (size_t m=0; mnfreq) continue; realp(middles[m])=imagp(middles[m])=0.0; int ind=orderg-middles[m]; realp(ind)=imagp(ind)=0.0; } if (highs) { for (i=0; i create exofilt\n"); printf(" -i create intrinsic noise model\n"); printf(" -t how many TRs\n"); printf(" -lf low frequencies to remove\n"); printf(" -mf other frequencies to remove\n"); printf(" -hf high frequencies to remove\n"); printf(" -k convolution kernel for exofilt\n"); printf(" -n 1/f noise model file name\n"); printf(" -h help\n"); printf(" -v version\n"); } void vbmakefilter_version() { printf("VoxBo vb2tes (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/crunch/vbmakeglm.cpp000066400000000000000000000360201153177201300200600ustar00rootroot00000000000000 // vbmakeglm.cpp // hack to create voxbo glm's // Copyright (c) 1998-2010 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // written to accomplish the same thing as some original IDL code by // Geoff Aguirre using namespace std; #include #include #include #include #include "vbutil.h" #include "vbjobspec.h" #include "vbprefs.h" #include "vbio.h" #include "glmutil.h" #include "vbx.h" #include VBPrefs vbp; const int BUFLEN=1024; bool f_ignorewarnings,f_validateonly,f_setuponly; int32 f_run; string glmname; class GLMConfig { private: GLMParams global,local,*gp; public: GLMConfig(string fname,double tr,double kr); int ParseFile(string filename); }; void vbmakeglm_help(); void vbmakeglm_sample(FILE *); void vbmakeglm_make_sample(const string &fname); void vbmakeglm_show_sample(); int main(int argc,char **argv) { tokenlist args; vbp.init(); vbp.read_jobtypes(); f_run=vbp.cores; args.Transfer(argc-1,argv+1); if (args.size() == 0) { vbmakeglm_help(); exit(0); } if (args[0]=="-h") { vbmakeglm_show_sample(); exit(0); } if (args[0]=="-x") { if (args.size() > 1) vbmakeglm_make_sample(args[1]); else printf("vbmakeglm -x needs a filename to store the sample glm file\n"); exit(0); } // okay, let's fly f_ignorewarnings=0; f_validateonly=0; f_setuponly=0; vector filelist; double x_tr=0.0,x_kr=0.0; for (size_t i=0; iname=args.Tail(); } else if (args[0]=="dirname") { if (args.size() == 2) gp->dirname=args[1]; else { tmps.str(""); tmps << "vbmakeglm: dirname takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="scan") { if (args.size() != 2) { tmps.str(""); tmps << "vbmakeglm: scan takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); continue; } gp->scanlist.push_back(args[1]); } else if (args[0]=="lows") { if (args.size() == 2) gp->lows=strtol(args[1]); else { tmps.str(""); tmps << "vbmakeglm: lows takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="highs") { if (args.size() == 2) gp->highs=strtol(args[1]); else { tmps.str(""); tmps << "vbmakeglm: highs takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="middles") { if (args.size() > 0) gp->middles=args[1]; } else if (args[0]=="pieces") { if (args.size() == 2) gp->pieces=strtol(args[1]); else { printf("[E] vbmakeglm: pieces takes exactly one argument\n"); } } else if (args[0]=="orderg") { if (args.size() == 2) gp->orderg=strtol(args[1]); else { tmps.str(""); tmps << "vbmakeglm: orderg takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="refname") { if (args.size() == 2) gp->refname=args[1]; else { printf("[E] vbmakeglm: reference takes exactly one argument\n"); printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="kernel") { if (args.size() == 2) gp->kernelname=args[1]; else if (args.size()==3) { gp->kernelname=args[1]; gp->kerneltr=strtod(args[2]); } else { tmps.str(""); tmps << "vbmakeglm: kernel takes one or two arguments"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="noisemodel") { if (args.size() == 2) gp->noisemodel=args[1]; else { tmps.str(""); tmps << "vbmakeglm: noisemodel takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="gmatrix") { if (args.size() == 2) gp->gmatrix=args[1]; else { tmps.str(""); tmps << "vbmakeglm: gmatrix takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="makerandfxg") { gp->rfxgflag=1; if (args.size() > 1) { tmps.str(""); tmps << "vbmakeglm: arguments to makerandfxg ignored"; printErrorMsg(VB_WARNING,tmps.str()); } } else if (args[0]=="tr") { if (args.size() == 2) gp->TR=strtol(args[1]); else { tmps.str(""); tmps << "vbmakeglm: tr takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="pri") { if (args.size() == 2) gp->pri=strtol(args[1]); else { tmps.str(""); tmps << "vbmakeglm: pri takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="audit") { if (args.size() != 2) { tmps.str(""); tmps << "vbmakeglm: audit takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } if (args[1]=="yes" || args[1]=="1") gp->auditflag=1; else if (args[1]=="no" || args[1]=="0") gp->auditflag=0; else { tmps.str(""); tmps << "vbmakeglm: unrecognized value for audit flag (should be yes/no)"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="meannorm") { if (args.size() != 2) { tmps.str(""); tmps << "vbmakeglm: meannorm takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } if (args[1]=="yes" || args[1]=="1") { gp->meannorm=1; gp->meannormset=1; } else if (args[1]=="no" || args[1]=="0") { gp->meannorm=0; gp->meannormset=1; } } else if (args[0]=="driftcorrect") { if (args.size() != 2) { tmps.str(""); tmps << "vbmakeglm: driftcorrect takes exactly one argument"; printErrorMsg(VB_ERROR,tmps.str()); } if (args[1]=="yes" || args[1]=="1") { gp->driftcorrect=1; } else if (args[1]=="no" || args[1]=="0") { gp->driftcorrect=0; } else { tmps.str(""); tmps << "vbmakeglm: unrecognized value for driftcorrect flag (should be yes/no)"; printErrorMsg(VB_ERROR,tmps.str()); } } else if (args[0]=="email") { gp->emailflag=1; if (args.size() == 2) gp->email=args[1]; } else if (args[0]=="go" || args[0]=="end") { if (!glmname.size() || glmname==gp->name) { gp->FixRelativePaths(); gp->Validate(f_ignorewarnings); if (gp->valid && !f_validateonly) { if (!gp->CreateGLMDir()) { if (f_setuponly) ; else if (f_run) { gp->CreateGLMJobs2(); runseq(vbp,gp->seq,f_run); } else { gp->CreateGLMJobs2(); if (gp->seq.Submit(vbp)) cout << "[E] vbmakeglm: error submitting your glm sequence\n"; else cout << "[I] vbmakeglm: your glm sequence was submitted successfully\n"; } } } } gp=&global; } else if (args[0]=="contrast") { gp->contrasts.push_back(args.Tail()); } else if (args[0]=="endx" || args[0]=="noend") { gp=&global; } else if (args[0]=="include") { if (args.size() == 2) ParseFile(args[1]); } else { tmps.str(""); tmps << "vbmakeglm: unrecognized keyword " << args[0]; printErrorMsg(VB_ERROR,tmps.str()); } } } infile.close(); return 0; // no error! } void vbmakeglm_help() { printf("\nVoxBo vbmakeglm (v%s)\n",vbversion.c_str()); printf("usage: vbmakeglm [flags] file [file ...]\n"); printf("flags:\n"); printf(" -i ignore warnings, queue it anyway\n"); printf(" -v don't queue, just validate\n"); printf(" -s setup only (create filters)\n"); printf(" -tr set data TR (ms)\n"); printf(" -kr set HRF kernel sampling rate (ms)\n"); printf(" -h i'm lazy, show me a sample .glm file\n"); printf(" -n only actually submit glms matching name\n"); printf(" -x i'm really lazy, make me a sample .glm file\n"); printf(" --run= don't queue, run now on n cores\n"); printf("notes:\n"); printf(" If --run is specified without =n, the default is the total number of\n"); printf(" available cores minus 1 (or 1, if that would be 0).\n"); printf("\n"); } void vbmakeglm_make_sample(const string &fname) { printf("Creating sample glm file in %s...",fname.c_str()); fflush(stdout); FILE *fp=fopen(fname.c_str(),"a"); if (fp) { vbmakeglm_sample(fp); fclose(fp); printf("done.\n"); } else { printf("failed.\n"); } } void vbmakeglm_show_sample() { printf("Here's what a valid .glm file looks like, more or less:\n\n"); vbmakeglm_sample(stdout); } void vbmakeglm_sample(FILE *fp) { fprintf(fp,"###############################################################\n"); fprintf(fp,"# Sample .glm file for VoxBo vbmakeglm.\n"); fprintf(fp,"# At the top, put stuff that's common to all GLMS in this file.\n"); fprintf(fp,"###############################################################\n"); fprintf(fp,"\n"); fprintf(fp,"# how many low frequencies do you want to filter out?\n"); fprintf(fp,"lows 1\n\n"); fprintf(fp,"# how many high frequencies do you want to filter out?\n"); fprintf(fp,"highs 1\n\n"); fprintf(fp,"# which random frequencies fo you want to filter out? (separate by spaces)\n"); fprintf(fp,"# middles 15 16 21\n\n"); fprintf(fp,"# how many total data points per voxel (typically time points)?\n"); fprintf(fp,"orderg 160\n\n"); fprintf(fp,"# how many pieces do you want to break the matrix operations into?\n"); fprintf(fp,"pieces 10\n\n"); fprintf(fp,"# specify a kernel for exogenous smoothing by convolution\n"); fprintf(fp,"kernel /usr/local/VoxBo/elements/filters/Eigen1.ref\n\n"); fprintf(fp,"# specify a model of intrinsic noise\n"); fprintf(fp,"noisemodel /usr/local/VoxBo/elements/noisemodels/smooth_params.ref\n\n"); fprintf(fp,"# specify the location of your G matrix, or just \"makerandfxg\" for makerandfxg\n"); fprintf(fp,"gmatrix /data/Models/mytask.G\n"); fprintf(fp,"# makerandfxg\n\n"); fprintf(fp,"# the location of a reference function to copy into the GLM directory\n"); fprintf(fp,"refname /data/Models/motor.ref\n\n"); fprintf(fp,"# priority (1 for overnight, 2 for low, 3 for normal, 4 and 5 for various emergencies)\n"); fprintf(fp,"pri 3\n\n"); fprintf(fp,"# do some summary statistics on your GLM?\n"); fprintf(fp,"audit yes\n\n"); fprintf(fp,"# mean normalize? usually say yes only if you have multiple runs of BOLD data\n"); fprintf(fp,"meannorm yes\n\n"); fprintf(fp,"# correct linear drift? \n"); fprintf(fp,"driftcorrect yes\n\n"); fprintf(fp,"# your email address here\n"); fprintf(fp,"email nobody@nowhere.com\n\n"); fprintf(fp,"\n"); fprintf(fp,"###############################################################\n"); fprintf(fp,"# Then create paragraphs of specific stuff for each GLM.\n"); fprintf(fp,"# (you can also override globals here)\n"); fprintf(fp,"###############################################################\n"); fprintf(fp,"\n"); fprintf(fp,"glm larry-glm1\n"); fprintf(fp,"dirname /data/study/larry/glm1\n"); fprintf(fp,"scan /data/study/larry/larry01/larry01.tes\n"); fprintf(fp,"scan /data/study/larry/larry02/larry02.tes\n"); fprintf(fp,"end\n"); fprintf(fp,"\n"); fprintf(fp,"glm moe-glm1\n"); fprintf(fp,"dirname /data/study/moe/glm1\n"); fprintf(fp,"scan /data/study/moe/moe01/moe01.tes\n"); fprintf(fp,"scan /data/study/moe/moe02/moe02.tes\n"); fprintf(fp,"end\n"); fprintf(fp,"\n"); fprintf(fp,"glm shemp-glm1\n"); fprintf(fp,"dirname /data/study/shemp/glm1\n"); fprintf(fp,"scan /data/study/shemp/shemp01/shemp01.tes\n"); fprintf(fp,"scan /data/study/shemp/shemp02/shemp02.tes\n"); fprintf(fp,"end\n"); fprintf(fp,"\n"); } voxbo-1.8.5~svn1246/crunch/vbmm2.cpp000066400000000000000000000576711153177201300171550ustar00rootroot00000000000000 // vbmm2.cpp // VoxBo matrix multiplication // Copyright (c) 1998-2010 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" void do_print(tokenlist &args); void do_printsub(tokenlist &args); void do_compare(tokenlist &args); int do_ident(tokenlist &args); int do_zeros(tokenlist &args); int do_random(tokenlist &args); int do_invert(tokenlist &args); int do_add(tokenlist &args); int do_subtract(tokenlist &args); int do_xyt(tokenlist &args); int do_xy(tokenlist &args); int do_imxy(tokenlist &args); int do_f3(tokenlist &args); int do_pinv(tokenlist &args); int do_pca(tokenlist &args); int do_assemblecols(tokenlist &args); int do_assemblerows(tokenlist &args); int do_xyz(tokenlist &args); int do_reshape(tokenlist &args); // vector stuff int do_applyfilter(tokenlist &args); void vbmm_help(); int main(int argc,char *argv[]) { tokenlist args; int err=0; string cmd; args.Transfer(argc-1,argv+1); if (args.size()<1) { vbmm_help(); exit(0); } cmd=args[0]; args.DeleteFirst(); if (cmd=="-xy") err=do_xy(args); else if (cmd=="-imxy") err=do_imxy(args); else if (cmd=="-f3") err=do_f3(args); else if (cmd=="-pinv") err=do_pinv(args); else if (cmd=="-pca") err=do_pca(args); else if (cmd=="-xyz") err=do_xyz(args); else if (cmd=="-xyt") err=do_xyt(args); else if (cmd=="-add") err=do_add(args); else if (cmd=="-subtract") err=do_subtract(args); else if (cmd=="-invert") err=do_invert(args); else if (cmd=="-ident") err=do_ident(args); else if (cmd=="-zeros") err=do_zeros(args); else if (cmd=="-assemblecols") err=do_assemblecols(args); else if (cmd=="-assemblerows") err=do_assemblerows(args); else if (cmd=="-reshape") err=do_reshape(args); else if (cmd=="-random") err=do_random(args); else if (cmd=="-print") do_print(args); else if (cmd=="-printsub") do_printsub(args); else if (cmd=="-compare") do_compare(args); else if (cmd=="-applyfilter") do_applyfilter(args); else { printf("[E] vbmm2: unknown operation %s",cmd.c_str()); exit(10); } exit(err); } // ident args: name size int do_ident(tokenlist &args) { int r; if (args.size() < 2) { printf("[E] vbmm2: need a name and a size to create a matrix.\n"); return 5; } r = strtol(args[1]); if (r < 0) { printf("[E] vbmm2: size for identity matrix must be > 0.\n"); return 10; } printf("[I] vbmm2: creating identity matrix %s of size %d.\n",args[0].c_str(),r); VBMatrix target(r,r); target.ident(); if (target.WriteFile(args[0])) printf("[E] vbmm2: identity matrix %s (%dx%d) not created.\n",args[0].c_str(),r,r); else printf("[I] vbmm2: identity matrix %s (%dx%d) created.\n",args[0].c_str(),r,r); return 0; } // zeros args: name size int do_zeros(tokenlist &args) { if (args.size() < 2) { printf("[E] vbmm2: need a name and a size to create a matrix.\n"); return 5; } int r,c; c = r = strtol(args[1]); if (args.size() > 2) // needed only if it's not square c = strtol(args[2]); if (r < 0 || c < 0) { printf("[E] vbmm2: dimensions for zero matrix must be > 0.\n"); return 10; } printf("[I] vbmm2: creating %dx%d zero matrix %s.\n",r,c,args[0].c_str()); VBMatrix target(c,r); target.zero(); if (target.WriteFile(args[0])) printf("[E] vbmm2: zero matrix %s (%dx%d) not created.\n",args[0].c_str(),r,c); else printf("[I] vbmm2: zero matrix %s (%dx%d) created.\n",args[0].c_str(),r,c); return 0; } int do_random(tokenlist &args) { if (args.size() < 2) { printf("[E] vbmm2: need a name and a size to create a matrix.\n"); return 5; } int r,c; c = r = strtol(args[1]); if (args.size() > 2) // needed only if it's not square c = strtol(args[2]); if (r < 0 || c < 0) { printf("[E] vbmm2: dimensions for random matrix must be > 0.\n"); return 10; } printf("vbmm2: creating random %dx%d matrix %s.\n",r,c,args[0].c_str()); VBMatrix target(r,c); target.random(); if (target.WriteFile(args[0])) printf("[E] vbmm2: error writing random %dx%d matrix %s\n",r,c,args[0].c_str()); else printf("[I] vbmm2: random %dx%d matrix %s created\n",r,c,args[0].c_str()); return 0; } // args: in1 in2 out int do_subtract(tokenlist &args) { if (args.size() != 3) { printf("[E] vbmm2: usage: vbmm2 -subtract in1 in2 out\n"); return 5; } VBMatrix mat1(args[0]); VBMatrix mat2(args[1]); if (mat1.m == 0 || mat1.n == 0) { printf("[E] vbmm2: first matrix was bad.\n"); return 101; } if (mat2.m == 0 || mat2.n == 0) { printf("[E] vbmm2: second matrix was bad.\n"); return 102; } if (mat1.m != mat2.m || mat1.n != mat2.n) { fprintf(stderr,"[E] vbmm2: matrix dimensions don't match.\n"); return 103; } printf("[I] vbmm2: subtracting matrix %s from matrix %s.\n",args[1].c_str(),args[0].c_str()); mat1-=mat2; mat1.WriteFile(args[2]); printf("[I] vbmm2: done.\n"); return 0; } int do_add(tokenlist &args) { if (args.size() != 3) { printf("[E] vbmm2: usage: vbmms -add in1 in2 out\n"); return 5; } VBMatrix mat1(args[0]); VBMatrix mat2(args[1]); if (mat1.m == 0 || mat1.n == 0) { printf("[E] vbmm2: first matrix was bad.\n"); return 101; } if (mat2.m == 0 || mat2.n == 0) { printf("[E] vbmm2: second matrix was bad.\n"); return 102; } if (mat1.m != mat2.m || mat1.n != mat2.n) { fprintf(stderr,"[E] vbmm2: matrix dimensions don't match.\n"); return 103; } printf("[I] vbmm2: adding matrix %s and matrix %s.\n",args[0].c_str(),args[1].c_str()); mat1+=mat2; mat1.WriteFile(args[2]); printf("[I] vbmm2: done.\n"); return 0; } // the below should be kept in sync with similar code in vbcmp.cpp void do_compare(tokenlist &args) { if (args.size()!=2) { printf("[E] vbmm2: usage: vbmm2 -compare \n"); return; } VBMatrix mat1(args[0]); VBMatrix mat2(args[1]); if (mat1.m!=mat2.m) { printf("[E] vbmm2: matrices have different row count\n"); return; } if (mat1.n!=mat2.n) { printf("[E] vbmm2: matrices have different column count\n"); return; } int diffs_all=0,diffs_diag=0,diffs_off=0; double totals_all=0.0,totals_diag=0.0,totals_off=0.0; double max_all=0.0,max_diag=0.0,max_off=0.0; double diff; for (uint32 i=0; imax_all) max_all=diff; if (i==j) { diffs_diag++; totals_diag+=diff; if (diff>max_diag) max_diag=diff; } else { diffs_off++; totals_off+=diff; if (diff>max_off) max_off=diff; } } } if (diffs_all) totals_all/=(double)diffs_all; if (diffs_diag) totals_diag/=(double)diffs_diag; if (diffs_off) totals_off/=(double)diffs_off; if (diffs_all==0) printf("[I] vbmm2: matrices are identical\n"); else { printf("[I] vbmm2: %d total cells\n",mat1.m*mat1.n); printf("[I] vbmm2: total: %d different cells, mean abs diff %g, max diff %g\n",diffs_all,totals_all,max_all); printf("[I] vbmm2: diagonal: %d different cells, mean abs diff %g, max diff %g\n",diffs_diag,totals_diag,max_diag); printf("[I] vbmm2: off-diag: %d different cells, mean abs diff %g, max diff %g\n",diffs_off,totals_off,max_off); } } // xy args: in1 in2 out [col1 col2] int do_xy(tokenlist &args) { int c1,c2; if (args.size() != 3 && args.size() != 5) { printf("[E] vbmm2: usage: vbmm2 -xy in1 in2 out [c1 c2]\n"); return 5; } VBMatrix mat1,mat2; mat1.ReadHeader(args[0]); mat2.ReadHeader(args[1]); if (mat1.m==0||mat1.n==0||mat2.m==0||mat2.n==0) { printf("[E] vbmm2: couldn't read matrix headers\n"); return 100; } if (mat1.ReadFile(args[0])) { printf("[E] vbmm2: first matrix was bad.\n"); return 100; } if (args.size()==5) { c1 = strtol(args[3]); c2 = strtol(args[4]); if (c1<0 || c2<0) { printf("[E] vbmm2: invalid column numbers\n"); return 107; } } else { c1=0; c2=mat2.cols-1; } // figure out the outfile name for this part, if we're not doing the whole thing string outname=args[2]; char tmps[128]; if (c1!=0 || (uint32)c2!=mat2.cols-1) { sprintf(tmps,"_%08d_%08d",c1,c2); outname += tmps; } if (mat2.ReadFile(args[1],0,0,c1,c2)) { printf("[E] vbmm2: second matrix was bad.\n"); return 101; } printf("[I] vbmm2: x=%s\n",args(0)); printf("[I] vbmm2: y=%s\n",args(1)); printf("[I] vbmm2: multiplying x by y (cols %d to %d).\n",c1,c2); mat1*=mat2; if (mat1.WriteFile(outname)) printf("[E] vbmm2: failed!\n"); else printf("[I] vbmm2: done.\n"); return 0; } int do_xyt(tokenlist &args) { int c1,c2; if (args.size() != 3 && args.size() != 5) { printf("[E] vbmm2: usage: vbmm2 -xy in1 in2 out [c1 c2]\n"); return 5; } VBMatrix mat1,mat2; mat1.ReadHeader(args[0]); mat2.ReadHeader(args[1]); if (mat1.m==0||mat1.n==0||mat2.m==0||mat2.n==0) { printf("[E] vbmm2: couldn't read matrix headers\n"); return 100; } if (mat1.ReadFile(args[0])) { printf("[E] vbmm2: first matrix was bad.\n"); return 100; } if (args.size()==5) { c1 = strtol(args[3]); c2 = strtol(args[4]); } else { c1 = 0; c2 = mat2.rows-1; } // figure out the outfile name string outname=args[2]; char tmps[128]; if (c1!=0 || (uint32)c2!=mat2.rows-1) { sprintf(tmps,"_%05d_%05d",c1,c2); outname += tmps; } if (mat2.ReadFile(args[1],c1,c2,0,0)) { printf("[E] vbmm2: second matrix was bad\n"); return 101; } printf("[I] vbmm2: x=%s\n",args(0)); printf("[I] vbmm2: y=%s\n",args(1)); printf("[I] vbmm2: multiplying x by y (cols %d to %d).\n",c1,c2); mat2.transposed=1; mat1*=mat2; if (mat1.WriteFile(outname)) printf("[E] vbmm2: failed\n"); else printf("[I] vbmm2: done\n"); return 0; } int do_xyz(tokenlist &args) { if (args.size() != 4) { printf("vbmm2: usage: vbmm2 -xyz in1 in2 in3 out\n"); return 5; } VBMatrix mat1(args[0]); VBMatrix mat2(args[1]); if (!(mat1.valid() && mat2.valid())) { printf("[E] vbmm2: bad input matrix\n"); return (100); } if (mat1.n != mat2.m) { printf("[E] vbmm2: bad matrix dimensions for xyz.\n"); return (104); } printf("vbmm2: multiplying matrix %s by matrix %s.\n",args(0),args(1)); mat1*=mat2; printf("vbmm2: multiplying matrix %s by matrix %s.\n",args(1),args(2)); VBMatrix mat3(args[2]); if (mat1.n != mat3.m) { printf("[E] vbmm2: bad matrix dimensions for xyz.\n"); return (104); } mat1*=mat3; printf("vbmm2: done.\n"); mat1.WriteFile(args[3]); return 0; } int do_reshape(tokenlist &args) { if (args.size()!=4) { printf("[E] vbmm2: reshape takes four arguments\n"); return (101); } string dir=vb_tolower(args[3]); if (dir!="rows" && dir!="cols") { printf("[E] vbmm2: the last argument must be either rows or cols\n"); return (101); } int dim=strtol(args[2]); if (dim<1) { printf("[E] vbmm2: provided dimension must be positive\n"); return (101); } VB_Vector invec(args[0]); if (!invec.size()) { printf("[E] vbmm2: couldn't read input vector file %s\n",args(0)); return (101); } VBMatrix outmat; int otherdim=invec.size()/dim; if (invec.size()%dim) otherdim++; if (dir=="rows") { outmat.resize(dim,otherdim); outmat.zero(); uint32 ind=0; for (uint32 cc=0; cc1) { for (size_t i=0; i mats; uint32 rows=0,cols=0; // first read all the headers for (size_t i=0; i1) { for (size_t i=0; i mats; uint32 rows=0,cols=0; // first read all the headers for (size_t i=0; i do part of XYt\n"); printf(" vbmm2 -xy do part of XY\n"); printf(" vbmm2 -imxy I-XY in core\n"); printf(" vbmm2 -f3 V*KG*invert(KTtKG)\n"); printf(" vbmm2 -xyz XYZ in core\n"); printf(" vbmm2 -assemblecols assemble out from available parts\n"); printf(" vbmm2 -assemblecols ... assemble all in files into out\n"); printf(" vbmm2 -assemblerows assemble out from available parts\n"); printf(" vbmm2 -assemblerows ... assemble all in files into out\n"); printf(" vbmm2 -add add two matrices\n"); printf(" vbmm2 -subtract subtract in2 from in1\n"); printf(" vbmm2 -invert invert in\n"); printf(" vbmm2 -pinv pseudo-inverse, in core\n"); printf(" vbmm2 -pca calculte pca\n"); printf(" vbmm2 -ident create an identity matrix\n"); printf(" vbmm2 -zeros [rows] create a zero matrix\n"); printf(" vbmm2 -random [rows] create a matrix of random numbers\n"); printf(" vbmm2 -print display a matrix\n"); printf(" vbmm2 -printsub display part of a matrix\n"); printf(" vbmm2 -compare compare two matrices\n"); printf(" vbmm2 -reshape reshape an input vector into a matrix\n"); printf(" vbmm2 -applyfilter apply \"ExoFilt\" filter to vector\n"); printf("notes:\n"); printf(" -assemblerows and -assemblecols, given a single argument, will try\n"); printf(" to find the pieces for that file, and will delete those pieces when\n"); printf(" done. Given more than one argument, all but the last argument will be\n"); printf(" taken as input filenames, and the last will be used for the output.\n"); printf("\n"); printf(" -reshape allows you to fix the number of rows or columsn. if you fix\n"); printf(" the rows, the vector is laid out column-by-column. if you fix the cols,\n"); printf(" the vector is paid out row-by-row.\n"); printf("\n"); } voxbo-1.8.5~svn1246/crunch/voxsurf.cpp000066400000000000000000001157111153177201300176340ustar00rootroot00000000000000 // voxsurf.cpp // take a graphical peek at tes and cub files // Copyright (c) 2000-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" #include #include // for backwards compatibility with older libpngs #ifndef png_jmpbuf # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) #endif #define TT_STRUCT "Load a structural image (TES1, CUB1, img, or imgdir)." #define TT_INFO "Print info about the currently loaded structural image." #define TT_FUNCT "Load functional data." #define TT_LMASK "Load a mask cube." #define TT_SMASK "Save the mask cube." #define TT_TMASK "Toggle display of the mask." #define TT_CMASK "Clear the current mask." #define TT_QUIT "Quits." #define TT_PNG "Save a snapshot as a PNG file." class ROI { Cube *cb; GdkColor *foo; string name; }; class VBView { private: guchar *rgbbuf; GtkWidget *window; // the main window GtkWidget *darea; // the image area GtkWidget *dwindow; // the scrolled window the drawing area sits in GtkWidget *dirdialog; // file selection dialog // the text boxes GtkWidget *imgname,*maskname; // all the buttons (some currently out) GtkWidget *quitbutton,*smaskbutton,*lmaskbutton,*structbutton; GtkWidget *infobutton,*functbutton,*cmaskbutton,*tmaskbutton,*pngbutton; GtkWidget *isizelabel,*msizelabel,*iposlabel,*mposlabel; GtkWidget *radiuswidget,*tmasklabel; char ipostext[32],mpostext[32],itext[32],mtext[32]; int currentslice,width,height; string filename; int slicenum,imagenum,magnum; int lastmag,lastwidth,lastheight; double mincube,maxcube; // ,lowval,highval; double blacklevel; // center of range, from -200 to +200 double contrast; // halfwidth, from 0 to 100 double contrastwidth,grayval; // double contrast,blacklevel; // they're percentages now // the actual images, masks, etc. Cube *mycube,*cubemask; Tes *mytes,*tesmask; // adjustments and range widgets for the sliders GtkObject *sliceadj,*imageadj,*magadj,*contrastadj,*blackadj; GtkWidget *slicerange,*imagerange,*magrange,*contrastrange,*blackrange; GtkWidget *slicelabel,*imagelabel,*contrastlabel,*blacklabel; gchar slicetext[32],imagetext[32]; // rendering stuff GdkGC *mygc; GdkColor grays[256]; GdkColor maskcolors[256]; GdkColor blues[256]; // mask-related int lastx,lasty; // so that we only draw stuff when we move out of a voxel int xratio,yratio; int fstatus; int maskflag; // draw the mask? int maskval; // value to draw in green int radius; public: VBView(); ~VBView(); void NewDrawArea(); void CalcMaxMin(); // misc void LoadStruct(const string fname); void LoadMask(const string fname); void SaveMask(const string fname); void KillFileSelection(); void NewSlice(int slice); void NewImage(int image); void NewMag(int mag); void NewMaskVal(int mag); void NewContrast(double contrast); void NewBlack(double black); int InitColors(); void SetFileStatus(int s); // dialog builders void LoadStructDialog(); void LoadMaskDialog(); void SaveFileDialog(); // coordinate conversions void Draw2Mask(int &x,int &y); void Draw2Img(int &x,int &y); void Img2Mask(int &x,int &y); int Xoffset(); int Yoffset(); // handlers void HandleButton(GtkWidget *button); void PrintInfo(); void ClickPixel(int x,int y,int button); void ColorMaskPixel(int x,int y,int color); void HandleNewRadius(); // rgb buf stuff void BuildRGB(); void DrawRGB(); // write png int WritePNG(const string &filename); // guchar scaledvalue(double val); }; const int COLUMNS=6; const int SPACING=10; void on_darea_expose(GtkWidget *,GdkEventExpose *,gpointer view); void handle_vbview_button(GtkWidget *button,gpointer data); void handle_vbview_close(GtkWidget *button,gpointer data); void handle_vbview_destroy(GtkWidget *,gpointer); void handle_vbview_radiuschanged(GtkWidget *,gpointer data); void handle_file_ok(GtkWidget *,gpointer data); void handle_file_cancel(GtkWidget *,gpointer data); void handle_slice_adj(GtkWidget *adj,gpointer data); void handle_image_adj(GtkWidget *adj,gpointer data); void handle_mag_adj(GtkWidget *adj,gpointer data); void handle_mask_adj(GtkWidget *adj,gpointer data); void handle_contrast_adj(GtkWidget *adj,gpointer data); void handle_black_adj(GtkWidget *adj,gpointer data); static gint handle_button_down(GtkWidget *widget,GdkEventButton *event,gpointer view); static gint handle_motion(GtkWidget *widget,GdkEventMotion *event,gpointer view); int main(int argc,char *argv[]) { VBView *vv; gtk_init(&argc,&argv); gdk_rgb_init(); // not necessary because if gtk drawing does it gtk_widget_set_default_colormap (gdk_rgb_get_cmap()); gtk_widget_set_default_visual (gdk_rgb_get_visual()); vv = new VBView(); if (vv->InitColors()) cerr << "Some kind of problem finding colors. Expect weirdness." << endl; for (int i=1; iLoadStruct((string)argv[i]); } gtk_main(); gtk_exit(0); } VBView::VBView() { GtkWidget *mainbox,*rightbox,*leftbox,*rowbox,*label,*r2box; GtkTooltips *tooltip; blacklevel=-50; contrast=30; magnum = 1; maskflag=1; xratio = yratio = 1; width=height=1; slicenum=imagenum=0; radius=0; mycube = cubemask = (Cube *)NULL; mytes = tesmask = (Tes *)NULL; rgbbuf = (guchar *)NULL; lastmag = lastwidth = lastheight = 0; // init tooltips tooltip = gtk_tooltips_new(); // this is the window window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC(handle_vbview_destroy),&window); // this is the main box mainbox = gtk_vbox_new(FALSE,5); gtk_container_set_border_width(GTK_CONTAINER(mainbox),4); gtk_container_add(GTK_CONTAINER(window),mainbox); // rowbox for leftbox and buttons r2box = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(r2box),0); gtk_box_pack_start(GTK_BOX(mainbox),r2box,TRUE,TRUE,2); // this is the leftbox leftbox = gtk_vbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(leftbox),0); gtk_container_add(GTK_CONTAINER(r2box),leftbox); // this is the scrolled window the drawing area sits in rowbox = gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(leftbox),rowbox,TRUE,TRUE,0); dwindow = gtk_scrolled_window_new(NULL,NULL); gtk_box_pack_start(GTK_BOX(rowbox),dwindow,TRUE,TRUE,0); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(dwindow), GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); gtk_widget_set_usize(dwindow,300,300); //gtk_signal_connect(GTK_OBJECT(dwindow),"button_press_event", // GTK_SIGNAL_FUNC(handle_button_down),(gpointer)this); //gtk_signal_connect(GTK_OBJECT(dwindow),"motion_notify_event", // GTK_SIGNAL_FUNC(handle_motion),(gpointer)this); // this is the rendering area, should really have scrollbars darea = gtk_drawing_area_new(); //gtk_box_pack_start(GTK_BOX(dwindow),darea,FALSE,FALSE,0); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(dwindow),darea); gtk_widget_set_events(darea,GDK_BUTTON1_MOTION_MASK|GDK_BUTTON3_MOTION_MASK| GDK_POINTER_MOTION_MASK|GDK_BUTTON_PRESS_MASK); gtk_signal_connect (GTK_OBJECT (darea), "expose-event", GTK_SIGNAL_FUNC (on_darea_expose),(gpointer)this); // gtk_drawing_area_size(GTK_DRAWING_AREA(darea),256,256); gtk_signal_connect(GTK_OBJECT(darea),"button_press_event", GTK_SIGNAL_FUNC(handle_button_down),(gpointer)this); gtk_signal_connect(GTK_OBJECT(darea),"motion_notify_event", GTK_SIGNAL_FUNC(handle_motion),(gpointer)this); // this is the rightbox rightbox = gtk_vbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rightbox),0); gtk_box_pack_start(GTK_BOX(r2box),rightbox,TRUE,FALSE,4); gtk_widget_set_usize(rightbox,210,0); structbutton = gtk_button_new_with_label("Load Image"); gtk_widget_set_usize(structbutton,110,22); gtk_box_pack_start(GTK_BOX(rightbox),structbutton,FALSE,FALSE,0); gtk_tooltips_set_tip(tooltip,structbutton,TT_STRUCT,NULL); gtk_signal_connect(GTK_OBJECT(structbutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); //functbutton = gtk_button_new_with_label("Load Overlay"); //gtk_widget_set_usize(functbutton,110,22); //gtk_box_pack_start(GTK_BOX(rightbox),functbutton,FALSE,FALSE,2); //gtk_tooltips_set_tip(tooltip,functbutton,TT_FUNCT,NULL); //gtk_signal_connect(GTK_OBJECT(functbutton),"clicked", // (GtkSignalFunc) handle_vbview_button, // (gpointer)this); infobutton = gtk_button_new_with_label("Info"); gtk_widget_set_usize(infobutton,110,22); gtk_box_pack_start(GTK_BOX(rightbox),infobutton,FALSE,FALSE,0); gtk_tooltips_set_tip(tooltip,infobutton,TT_INFO,NULL); gtk_signal_connect(GTK_OBJECT(infobutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); pngbutton = gtk_button_new_with_label("Save PNG"); gtk_widget_set_usize(pngbutton,110,22); gtk_box_pack_start(GTK_BOX(rightbox),pngbutton,FALSE,FALSE,0); gtk_tooltips_set_tip(tooltip,pngbutton,TT_PNG,NULL); gtk_signal_connect(GTK_OBJECT(pngbutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); lmaskbutton = gtk_button_new_with_label("Load Mask"); gtk_widget_set_usize(lmaskbutton,70,22); gtk_box_pack_start(GTK_BOX(rowbox),lmaskbutton,TRUE,TRUE,0); gtk_tooltips_set_tip(tooltip,lmaskbutton,TT_LMASK,NULL); gtk_signal_connect(GTK_OBJECT(lmaskbutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); smaskbutton = gtk_button_new_with_label("Save Mask"); gtk_widget_set_usize(smaskbutton,70,22); gtk_box_pack_start(GTK_BOX(rowbox),smaskbutton,TRUE,TRUE,0); gtk_tooltips_set_tip(tooltip,smaskbutton,TT_SMASK,NULL); gtk_signal_connect(GTK_OBJECT(smaskbutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); cmaskbutton = gtk_button_new_with_label("Clear Mask"); gtk_widget_set_usize(cmaskbutton,70,22); gtk_box_pack_start(GTK_BOX(rowbox),cmaskbutton,TRUE,TRUE,0); gtk_tooltips_set_tip(tooltip,cmaskbutton,TT_CMASK,NULL); gtk_signal_connect(GTK_OBJECT(cmaskbutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); tmaskbutton = gtk_button_new_with_label("Hide Mask"); gtk_widget_set_usize(tmaskbutton,70,22); gtk_box_pack_start(GTK_BOX(rowbox),tmaskbutton,TRUE,TRUE,0); gtk_tooltips_set_tip(tooltip,tmaskbutton,TT_TMASK,NULL); gtk_signal_connect(GTK_OBJECT(tmaskbutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); GList *gl=gtk_container_children(GTK_CONTAINER(tmaskbutton)); tmasklabel=(GtkWidget *)gl->data; quitbutton = gtk_button_new_with_label("Quit"); gtk_widget_set_usize(quitbutton,110,22); gtk_box_pack_start(GTK_BOX(rightbox),quitbutton,FALSE,FALSE,0); gtk_tooltips_set_tip(tooltip,quitbutton,TT_QUIT,NULL); gtk_signal_connect(GTK_OBJECT(quitbutton),"clicked", (GtkSignalFunc) handle_vbview_button, (gpointer)this); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Image Dims:"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); isizelabel = gtk_label_new("-"); gtk_box_pack_start(GTK_BOX(rowbox),isizelabel,FALSE,FALSE,0); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Mask Dims:"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); msizelabel = gtk_label_new("-"); gtk_box_pack_start(GTK_BOX(rowbox),msizelabel,FALSE,FALSE,0); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Image Position:"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); iposlabel = gtk_label_new("-"); //gtk_widget_set_usize(GTK_WIDGET(iposlabel),120,10); //gtk_label_set_justify(GTK_LABEL(iposlabel),GTK_JUSTIFY_RIGHT); gtk_box_pack_start(GTK_BOX(rowbox),iposlabel,FALSE,FALSE,0); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Mask Position:"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); mposlabel = gtk_label_new("-"); //gtk_label_set_justify(GTK_LABEL(mposlabel),GTK_JUSTIFY_LEFT); //gtk_widget_set_usize(GTK_WIDGET(mposlabel),120,10); gtk_box_pack_start(GTK_BOX(rowbox),mposlabel,FALSE,FALSE,0); // this is the slice selection slider rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Slice"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); slicerange = gtk_hscale_new(NULL); gtk_scale_set_digits(GTK_SCALE(slicerange),0); gtk_box_pack_start(GTK_BOX(rowbox),slicerange,FALSE,FALSE,0); gtk_widget_set_sensitive(GTK_WIDGET(slicerange),FALSE); gtk_widget_set_usize(slicerange,110,30); gtk_range_set_update_policy(GTK_RANGE(slicerange),GTK_UPDATE_CONTINUOUS); //gtk_scale_set_draw_value(GTK_SCALE(slicerange),FALSE); gtk_scale_set_value_pos(GTK_SCALE(slicerange),GTK_POS_RIGHT); slicelabel = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(rowbox),slicelabel,FALSE,FALSE,0); // this is the image (time) selection slider rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Image"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); imagerange = gtk_hscale_new(NULL); gtk_scale_set_digits(GTK_SCALE(imagerange),0); gtk_box_pack_start(GTK_BOX(rowbox),imagerange,FALSE,FALSE,0); gtk_widget_set_sensitive(GTK_WIDGET(imagerange),FALSE); gtk_widget_set_usize(imagerange,110,30); gtk_range_set_update_policy(GTK_RANGE(imagerange),GTK_UPDATE_CONTINUOUS); //gtk_scale_set_draw_value(GTK_SCALE(imagerange),FALSE); gtk_scale_set_value_pos(GTK_SCALE(imagerange),GTK_POS_RIGHT); imagelabel = gtk_label_new(""); gtk_box_pack_start(GTK_BOX(rowbox),imagelabel,FALSE,FALSE,0); // this is the magnification selection slider rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Magnification"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); magrange = gtk_hscale_new(NULL); gtk_scale_set_digits(GTK_SCALE(magrange),0); gtk_box_pack_start(GTK_BOX(rowbox),magrange,FALSE,FALSE,0); gtk_widget_set_usize(magrange,110,30); gtk_range_set_update_policy(GTK_RANGE(magrange),GTK_UPDATE_DISCONTINUOUS); gtk_scale_set_value_pos(GTK_SCALE(magrange),GTK_POS_RIGHT); // because mag only ever has one adjustment, we can create it here magadj = gtk_adjustment_new(1,1,9,1,1,1); gtk_signal_connect(GTK_OBJECT(magadj),"value_changed", (GtkSignalFunc)handle_mag_adj,(gpointer)this); gtk_range_set_adjustment(GTK_RANGE(magrange),GTK_ADJUSTMENT(magadj)); // black and contrast level sliders rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Black level"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); blackrange = gtk_hscale_new(NULL); gtk_scale_set_digits(GTK_SCALE(blackrange),0); gtk_box_pack_start(GTK_BOX(rowbox),blackrange,FALSE,FALSE,0); gtk_widget_set_usize(blackrange,110,30); gtk_range_set_update_policy(GTK_RANGE(blackrange),GTK_UPDATE_CONTINUOUS); // gtk_scale_set_value_pos(GTK_SCALE(blackrange),GTK_POS_RIGHT); blackadj = gtk_adjustment_new(blacklevel,-200,201,1.0,1.0,1.0); gtk_signal_connect(GTK_OBJECT(blackadj),"value_changed", (GtkSignalFunc)handle_black_adj,(gpointer)this); gtk_range_set_adjustment(GTK_RANGE(blackrange),GTK_ADJUSTMENT(blackadj)); gtk_range_default_hslider_update(GTK_RANGE(blackrange)); gtk_widget_set_sensitive(GTK_WIDGET(blackrange),TRUE); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Contrast"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); contrastrange = gtk_hscale_new(NULL); gtk_scale_set_digits(GTK_SCALE(contrastrange),0); gtk_box_pack_start(GTK_BOX(rowbox),contrastrange,FALSE,FALSE,0); gtk_widget_set_usize(contrastrange,110,30); gtk_range_set_update_policy(GTK_RANGE(contrastrange),GTK_UPDATE_CONTINUOUS); // gtk_scale_set_value_pos(GTK_SCALE(contrastrange),GTK_POS_RIGHT); contrastadj = gtk_adjustment_new(contrast,0,101,1.0,1.0,1.0); gtk_signal_connect(GTK_OBJECT(contrastadj),"value_changed", (GtkSignalFunc)handle_contrast_adj,(gpointer)this); gtk_range_set_adjustment(GTK_RANGE(contrastrange),GTK_ADJUSTMENT(contrastadj)); gtk_range_default_hslider_update(GTK_RANGE(contrastrange)); gtk_widget_set_sensitive(GTK_WIDGET(contrastrange),TRUE); rowbox = gtk_hbox_new(FALSE,4); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(rightbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Mask draw radius:"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,0); radiuswidget = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(rowbox),radiuswidget,TRUE,TRUE,0); gtk_entry_set_text(GTK_ENTRY(radiuswidget),"0"); gtk_signal_connect(GTK_OBJECT(radiuswidget),"changed", GTK_SIGNAL_FUNC(handle_vbview_radiuschanged),(gpointer)this); // labels and stuff for filename, etc. rowbox = gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(mainbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Image file:"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,5); imgname = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(rowbox),imgname,TRUE,TRUE,0); gtk_entry_set_editable(GTK_ENTRY(imgname),FALSE); rowbox = gtk_hbox_new(FALSE,0); gtk_container_set_border_width(GTK_CONTAINER(rowbox),0); gtk_box_pack_start(GTK_BOX(mainbox),rowbox,FALSE,FALSE,0); label = gtk_label_new("Mask file:"); gtk_box_pack_start(GTK_BOX(rowbox),label,FALSE,FALSE,5); maskname = gtk_entry_new(); gtk_box_pack_start(GTK_BOX(rowbox),maskname,TRUE,TRUE,0); gtk_entry_set_editable(GTK_ENTRY(maskname),FALSE); // NewContrast(30); // NewBlack(0); gtk_widget_show_all(window); mygc = gdk_gc_new(darea->window); } void on_darea_expose(GtkWidget *,GdkEventExpose *,gpointer view) { ((VBView *)view)->DrawRGB(); } void handle_vbview_button(GtkWidget *button,gpointer data) { ((VBView *)data)->HandleButton(button); } void handle_vbview_destroy(GtkWidget *,gpointer) { gtk_main_quit(); } void handle_vbview_radiuschanged(GtkWidget *,gpointer data) { ((VBView *)data)->HandleNewRadius(); } // the way this should work: the rendering functions need to know for // each pixel first which pixel of the image it is, second which pixel // of the mask it is. we need a little translation algorithm that for // any address in the darea will tell us either the mask or the image // address. here it is: void VBView::Draw2Mask(int &x,int &y) { x=(int)(x/magnum)/xratio; y=(int)(y/magnum)/yratio; y = cubemask->dimy-y-1; } void VBView::Draw2Img(int &x,int &y) { x=(int)(x/magnum); y=(int)(y/magnum); y = mycube->dimy-y-1; } void VBView::Img2Mask(int &x,int &y) { x=(int)(x/xratio); y=(int)(y/yratio); } int VBView::Xoffset() { return (int)gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(dwindow))->value; } int VBView::Yoffset() { return (int)gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(dwindow))->value; } void VBView::HandleNewRadius() { char tmp[STRINGLEN]; strcpy(tmp,gtk_entry_get_text(GTK_ENTRY(radiuswidget))); radius=strtol(tmp); // char tmp2[STRINGLEN]; // sprintf(tmp2,"%d",radius); // if ((string)tmp != (string)tmp2) { // gtk_entry_set_position(GTK_ENTRY(radiuswidget),-1); // gtk_entry_set_text(GTK_ENTRY(radiuswidget),tmp2); // gtk_entry_set_position(GTK_ENTRY(radiuswidget),-1); // } } static gint handle_button_down(GtkWidget *widget,GdkEventButton *event,gpointer view) { if (event->type == GDK_2BUTTON_PRESS && event->button == 2) ((VBView *)view)->PrintInfo(); else if (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) ((VBView *)view)->ClickPixel((int)event->x,(int)event->y,3); else ((VBView *)view)->ClickPixel((int)event->x,(int)event->y,event->button); return TRUE; } static gint handle_motion(GtkWidget *widget,GdkEventMotion *event,gpointer view) { int button=0; if (event->state & GDK_BUTTON1_MASK) button=1; else if (event->state & GDK_BUTTON2_MASK) button=2; else if (event->state & GDK_BUTTON3_MASK) button=3; if (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK) && button==1) button=3; ((VBView *)view)->ClickPixel((int)event->x,(int)event->y,button); return TRUE; } void VBView::ClickPixel(int x,int y,int button) { if (!mycube) return; int maskx=x,masky=y; int imgx=x,imgy=y; int minx,miny,maxx,maxy,i,j; Draw2Mask(maskx,masky); Draw2Img(imgx,imgy); // if we're out of the image ... if (imgx > mycube->dimx-1 || imgy > mycube->dimy-1 || imgx < 0 || imgy < 0) { sprintf(ipostext,"(-,-) = -"); gtk_label_set_text(GTK_LABEL(iposlabel),ipostext); sprintf(mpostext,"(-,-) = -"); gtk_label_set_text(GTK_LABEL(mposlabel),mpostext); return; } // update the coordinates sprintf(ipostext,"(%d,%d) = %.1f",imgx,imgy,mycube->GetValue(imgx,imgy,slicenum)); gtk_label_set_text(GTK_LABEL(iposlabel),ipostext); sprintf(mpostext,"(%d,%d) = %d",maskx,masky,(int)cubemask->GetValue(maskx,masky,slicenum)); gtk_label_set_text(GTK_LABEL(mposlabel),mpostext); if (button == 0) // just hovering return; minx=maskx-radius; if (minx < 0) minx=0; maxx=maskx+radius; if (maxx > cubemask->dimx-1) maxx=cubemask->dimx-1; miny=masky-radius; if (miny < 0) miny=0; maxy=masky+radius; if (maxy > cubemask->dimy-1) maxy=cubemask->dimy-1; for (i=minx; i<=maxx; i++) { for (j=miny; j<=maxy; j++) { // make sure we're in the image if (i > cubemask->dimx-1 || j > cubemask->dimy-1 || i < 0 || j < 0) return; if (button == 1) { cubemask->SetValue(i,j,slicenum,1); ColorMaskPixel(i,j,1); // BuildRGB(); if (!maskflag) { maskflag=1; DrawRGB(); } } else if (button == 3) { cubemask->SetValue(i,j,slicenum,0); ColorMaskPixel(i,j,2); // BuildRGB(); if (!maskflag) { maskflag=1; DrawRGB(); } } } } } void VBView::ColorMaskPixel(int maskx,int masky,int color) { int cindex; for (int i=maskx*xratio; iGetValue(i,j,slicenum)); if (color==1) gdk_gc_set_foreground(mygc,maskcolors+cindex); else gdk_gc_set_foreground(mygc,grays+cindex); gdk_draw_rectangle(darea->window,mygc,TRUE,i*magnum,(mycube->dimy-j-1)*magnum,magnum,magnum); } } } void VBView::DrawRGB() { if (!rgbbuf) return; // should never happen gdk_draw_rgb_image (darea->window,darea->style->fg_gc[GTK_STATE_NORMAL], 0,0,width,height, GDK_RGB_DITHER_MAX, rgbbuf,width * 3); } inline guchar VBView::scaledvalue(double val) { double low=grayval-contrastwidth; double high=grayval+contrastwidth; double bval = (((val - low) * 255.0 / (high - low))); if (bval > 255) bval=255; if (bval < 0) bval=0; return (guchar)bval; } void VBView::BuildRGB() { int i,j,jj,k,l,x,y,rowsize,rr,gg,bb; guchar *pos,*pp,byteval; double dval; if (!mycube || !cubemask) return; if (!rgbbuf || magnum != lastmag || mycube->dimx != lastwidth || mycube->dimy != lastheight) rgbbuf = new guchar[mycube->dimx * mycube->dimy * 3 * magnum * magnum]; lastmag=magnum; lastwidth=mycube->dimx; lastheight=mycube->dimy; rowsize = lastwidth*3*magnum; pos = (guchar *)rgbbuf; for(i=0; idimx; i++) { for(j=0; jdimy; j++) { jj=mycube->dimy-j-1; pos=(guchar *)rgbbuf + (jj*magnum*rowsize) + (i*3*magnum); dval = mycube->GetValue(i,j,slicenum); byteval = scaledvalue(dval); x=i; y=j; Img2Mask(x,y); rr=gg=bb=byteval; if (cubemask->GetValue(x,y,slicenum) && maskflag) gg=bb=byteval*2/3; else if (maskval && maskval == (int)dval) rr=bb=byteval*2/3; for(k=0; kprint(); else if (mycube) mycube->print(); } // HandleButton() is a clearinghouse for main window button events void VBView::HandleButton(GtkWidget *button) { if (button == lmaskbutton) { LoadMaskDialog(); filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dirdialog)); KillFileSelection(); if (fstatus) LoadMask(filename); } else if (button == smaskbutton) { SaveFileDialog(); filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dirdialog)); KillFileSelection(); if (fstatus) SaveMask(filename); } else if (button == pngbutton) { SaveFileDialog(); filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dirdialog)); KillFileSelection(); if (fstatus) WritePNG(filename); } else if (button == cmaskbutton) { cubemask->clear(); BuildRGB(); DrawRGB(); } else if (button == tmaskbutton) { maskflag = 1-maskflag; if (maskflag) gtk_label_set_text(GTK_LABEL(tmasklabel),"Hide Mask"); else gtk_label_set_text(GTK_LABEL(tmasklabel),"Show Mask"); BuildRGB(); DrawRGB(); } else if (button == infobutton) { PrintInfo(); } else if (button == quitbutton) { gtk_main_quit(); } else if (button == structbutton) { LoadStructDialog(); filename = gtk_file_selection_get_filename(GTK_FILE_SELECTION(dirdialog)); KillFileSelection(); if (fstatus) LoadStruct(filename); } else if (button == functbutton) { } } void VBView::LoadMaskDialog() { dirdialog = gtk_file_selection_new("Choose a structural image file"); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(dirdialog)->ok_button), "clicked",(GtkSignalFunc)handle_file_ok,(gpointer)this); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(dirdialog)->cancel_button), "clicked",(GtkSignalFunc)handle_file_cancel,(gpointer)this); //gtk_file_selection_set_filename(GTK_FILE_SELECTION(dirdialog),dir); gtk_grab_add(dirdialog); gtk_widget_show(dirdialog); gtk_main(); } void VBView::SaveFileDialog() { dirdialog = gtk_file_selection_new("File to save:"); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(dirdialog)->ok_button), "clicked",(GtkSignalFunc)handle_file_ok,(gpointer)this); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(dirdialog)->cancel_button), "clicked",(GtkSignalFunc)handle_file_cancel,(gpointer)this); //gtk_file_selection_set_filename(GTK_FILE_SELECTION(dirdialog),dir); gtk_grab_add(dirdialog); gtk_widget_show(dirdialog); gtk_main(); } void VBView::LoadStructDialog() { dirdialog = gtk_file_selection_new("Choose a structural image file"); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(dirdialog)->ok_button), "clicked",(GtkSignalFunc)handle_file_ok,(gpointer)this); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(dirdialog)->cancel_button), "clicked",(GtkSignalFunc)handle_file_cancel,(gpointer)this); //gtk_file_selection_set_filename(GTK_FILE_SELECTION(dirdialog),dir); gtk_grab_add(dirdialog); gtk_widget_show(dirdialog); gtk_main(); } void VBView::LoadMask(const string fname) { Cube *tmpcub = new Cube; if (tmpcub->ReadFile(fname.c_str())) { cerr << "Couldn't load mask " << fname << endl; return; } if (!tmpcub->data_valid) { cerr << "Couldn't load mask " << fname << endl; delete tmpcub; return; } // should probably check z too if (mycube->dimx % tmpcub->dimx || mycube->dimy % tmpcub->dimy) { cerr << "The dimensions of mask " << fname << " are incompatible with this image." << endl; cerr << " Mask: " << tmpcub->dimx << "x" << tmpcub->dimy << "x" << tmpcub->dimz << endl; cerr << " Image: " << mycube->dimx << "x" << mycube->dimy << "x" << mycube->dimz << endl; return; } xratio = mycube->dimx / tmpcub->dimx; yratio = mycube->dimy / tmpcub->dimy; delete cubemask; cubemask = tmpcub; gtk_entry_set_text(GTK_ENTRY(maskname),fname.c_str()); sprintf(mtext,"%dx%d",cubemask->dimx,cubemask->dimy); gtk_label_set_text(GTK_LABEL(msizelabel),mtext); chdir(xdirname(fname).c_str()); BuildRGB(); DrawRGB(); } void VBView::SaveMask(const string fname) { cubemask->SetFileName(fname); cubemask->WriteFile(); gtk_entry_set_text(GTK_ENTRY(maskname),fname.c_str()); chdir(xdirname(fname).c_str()); } void VBView::LoadStruct(const string fname) { imagenum=slicenum=0; if (mytes) delete mytes; if (mycube) delete mycube; if (cubemask) delete cubemask; if (tesmask) delete tesmask; mytes = tesmask = (Tes *)NULL; mycube = cubemask = (Cube *)NULL; vectorftypes=EligibleFileTypes(fname); if (!ftypes.size()) return; switch(EligibleFileTypes(fname)[0].getDimensions()) { case 4: mytes = new Tes; mytes->ReadFile(fname.c_str()); if (mytes->data_valid) mycube = (*mytes)[0]; else { delete mytes; mytes = (Tes *)NULL; } break; case 3: mycube = new Cube; mycube->ReadFile(fname.c_str()); if (!mycube->data_valid) { delete mycube; mycube = (Cube *)NULL; } break; default: printf("voxsurf: can't handle this filetype yet\n"); break; } if (mycube) { CalcMaxMin(); // i have no idea why the following has to use dimz+1 to make it go to dimz sliceadj = gtk_adjustment_new(0.0,0.0,mycube->dimz,1.0,1.0,1.0); gtk_signal_connect(GTK_OBJECT(sliceadj),"value_changed", (GtkSignalFunc)handle_slice_adj,(gpointer)this); gtk_range_set_adjustment(GTK_RANGE(slicerange),GTK_ADJUSTMENT(sliceadj)); gtk_widget_set_sensitive(GTK_WIDGET(slicerange),TRUE); sprintf(slicetext,"(0-%d)",mycube->dimz-1); gtk_label_set_text(GTK_LABEL(slicelabel),slicetext); if (mycube->dimx % 4 == 0 && mycube->dimy % 4 == 0) // try quarter-res masks xratio = yratio = 4; else if (mycube->dimx % 2 == 0 && mycube->dimy % 2 == 0) // try quarter-res masks xratio = yratio = 2; else xratio = yratio = 1; cubemask = new Cube(mycube->dimx/xratio,mycube->dimy/yratio,mycube->dimz,vb_byte); cubemask->clear(); // display the names and dimensions of the cube and mask gtk_entry_set_text(GTK_ENTRY(imgname),fname.c_str()); gtk_entry_set_text(GTK_ENTRY(maskname),""); sprintf(itext,"%dx%d",mycube->dimx,mycube->dimy); gtk_label_set_text(GTK_LABEL(isizelabel),itext); sprintf(mtext,"%dx%d",cubemask->dimx,cubemask->dimy); gtk_label_set_text(GTK_LABEL(msizelabel),mtext); } else { gtk_widget_set_sensitive(GTK_WIDGET(slicerange),FALSE); } if (mytes) { // i have no idea why the following has to use dimt to make it go to dimt-1 imageadj = gtk_adjustment_new(0.0,0.0,mytes->dimt,1.0,1.0,1.0); gtk_signal_connect(GTK_OBJECT(imageadj),"value_changed", (GtkSignalFunc)handle_image_adj,(gpointer)this); gtk_range_set_adjustment(GTK_RANGE(imagerange),GTK_ADJUSTMENT(imageadj)); gtk_widget_set_sensitive(GTK_WIDGET(imagerange),TRUE); //tesmask = new Tes(mytes->dimx,mytes->dimy,mytes->dimz,mytes->dimt,vb_byte); sprintf(imagetext,"(0-%d)",mytes->dimt-1); gtk_label_set_text(GTK_LABEL(imagelabel),imagetext); } else { gtk_widget_set_sensitive(GTK_WIDGET(imagerange),FALSE); } if (mycube) { NewDrawArea(); gtk_adjustment_set_value(GTK_ADJUSTMENT(sliceadj),0); } chdir(xdirname(fname).c_str()); } void VBView::KillFileSelection() { gtk_grab_remove(dirdialog); gtk_widget_destroy(dirdialog); } void VBView::NewSlice(int slice) { if (!mycube) return; slicenum=slice; BuildRGB(); DrawRGB(); } void VBView::NewImage(int image) { if (mycube) delete mycube; imagenum=image; mycube = (*mytes)[imagenum]; BuildRGB(); DrawRGB(); } void VBView::NewMag(int mag) { if (!mycube) return; magnum=mag; if (mycube) { NewDrawArea(); } } void VBView::NewMaskVal(int mv) { if (!mycube) return; maskval=mv; BuildRGB(); DrawRGB(); } void VBView::NewContrast(double cont) { contrast=cont; contrastwidth=((100.0-(double)contrast)/100.0)*(maxcube-mincube); // cout << "contrastwidth: " << contrastwidth << endl; gtk_adjustment_set_value(GTK_ADJUSTMENT(contrastadj),contrast); } void VBView::NewBlack(double black) { blacklevel=black; grayval=mincube+((maxcube-mincube)*0.5)*(1.0+((double)blacklevel/100.0)); // cout << "grayval :" << grayval << endl; gtk_adjustment_set_value(GTK_ADJUSTMENT(blackadj),black); } void handle_contrast_adj(GtkWidget *adj,gpointer data) { double cont = (int)(GTK_ADJUSTMENT(adj)->value); ((VBView *)data)->NewContrast(cont); ((VBView *)data)->BuildRGB(); ((VBView *)data)->DrawRGB(); } void handle_black_adj(GtkWidget *adj,gpointer data) { double black = (int)(GTK_ADJUSTMENT(adj)->value); ((VBView *)data)->NewBlack(black); ((VBView *)data)->BuildRGB(); ((VBView *)data)->DrawRGB(); } void handle_mag_adj(GtkWidget *adj,gpointer data) { int mag = (int)(GTK_ADJUSTMENT(adj)->value); ((VBView *)data)->NewMag(mag); } void handle_mask_adj(GtkWidget *adj,gpointer data) { int maskval = (int)(GTK_ADJUSTMENT(adj)->value); ((VBView *)data)->NewMaskVal(maskval); } void handle_image_adj(GtkWidget *adj,gpointer data) { int image = (int)(GTK_ADJUSTMENT(adj)->value); ((VBView *)data)->NewImage(image); } void handle_slice_adj(GtkWidget *adj,gpointer data) { int slice = (int)(GTK_ADJUSTMENT(adj)->value); ((VBView *)data)->NewSlice(slice); } void handle_file_ok(GtkWidget *,gpointer data) { ((VBView *)data)->SetFileStatus(TRUE); gtk_main_quit(); } void handle_file_cancel(GtkWidget *,gpointer data) { ((VBView *)data)->SetFileStatus(FALSE); gtk_main_quit(); } void VBView::SetFileStatus(int s) { fstatus=s; } // CalcMaxMin() does what it sounds like it does void VBView::CalcMaxMin() { int i,j,k; double val; maxcube = mincube = mycube->GetValue(0,0,0); for(i=0; idimx; i++) { for(j=0; jdimy; j++) { for(k=0; kdimz; k++) { val = mycube->GetValue(i,j,k); if (val > maxcube) maxcube = val; if (val < mincube) mincube = val; } } } NewBlack(blacklevel); NewContrast(contrast); } // NewDrawArea() should be called any time we change the apparent size // of the image in the drawing area. Basically any time we load a new // image or change the magnification. void VBView::NewDrawArea() { width=mycube->dimx*magnum; height=mycube->dimy*magnum; gtk_drawing_area_size(GTK_DRAWING_AREA(darea),width,height); BuildRGB(); } int VBView::InitColors() { gboolean rets[256]; int i,err,big,little; for (i=0; i<256; i++) { big = i*256; little = big*2/3; grays[i].red=big; grays[i].green=big; grays[i].blue=big; maskcolors[i].red=big; maskcolors[i].green=little; maskcolors[i].blue=little; blues[i].red=little; blues[i].green=little; blues[i].blue=big; } err = gdk_colormap_alloc_colors(gdk_colormap_get_system(),grays,256,FALSE,TRUE,rets); err += gdk_colormap_alloc_colors(gdk_colormap_get_system(),maskcolors,256,FALSE,TRUE,rets); err += gdk_colormap_alloc_colors(gdk_colormap_get_system(),blues,256,FALSE,TRUE,rets); return err; } int VBView::WritePNG(const string &filename) { FILE *fp; png_structp png_ptr; png_infop info_ptr; png_uint_32 width,height; width=mycube->dimx * magnum; height=mycube->dimy * magnum; /* open the file */ fp = fopen(filename.c_str(),"wb"); if (fp == NULL) return (101); /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if (png_ptr == NULL) { fclose(fp); return (102); } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return (103); } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { /* If we get here, we had a problem reading the file */ fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); return (104); } png_init_io(png_ptr, fp); png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); png_uint_32 k,bpp=3; // bpp = bytes per pixel // png_byte image[height][width*bpp]; png_bytep row_pointers[height]; for (k = 0; k < height; k++) row_pointers[k] = rgbbuf + k*width*bpp; png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); return (0); } voxbo-1.8.5~svn1246/db_import/000077500000000000000000000000001153177201300161035ustar00rootroot00000000000000voxbo-1.8.5~svn1246/db_import/aal.csv000066400000000000000000000071141153177201300173600ustar00rootroot00000000000000"boldfaced rows just make it easier to find completely new regions",,,,, "remove _R from all structure names",,,,, "????? indicates things i didn't know what to do with",,,,, "rows with equivalent nn names shouldn't generally have other relationships",,,,, ,,,,, "AAL Region #","AAL Name","Gray","Code","Equivalent NN Name","Other relationships" ,,,,, 2,"Precentral",2002,,,"child of precentral gyrus" 58,"Postcentral",6002,,,"child of postcentral gyrus" 18,"Rolandic_Oper",2332,,"?????","overlaps Frontal_Inf, overlaps supramarginal gyrus" ,,,,, ,"Frontal_Sup",,,"superior frontal gyrus", 4,"Frontal_Sup_Dorso",2102,,,"child of Frontal_Sup" 6,"Frontal_Sup_Orb",2112,,,"child of Frontal_Sup" 24,"Frontal_Sup_Medial",2602,,,"child of Frontal_Sup" ,,,,, ,"Frontal_Mid",,,"middle frontal gyrus", 8,"Frontal_Mid_Lat",2202,,,"child of Frontal_Mid" 10,"Frontal_Mid_Orb",2212,,,"child of Frontal_Mid" ,,,,, ,"Frontal_Inf",,,"inferior frontal gyrus", 12,"Frontal_Inf_Oper",2302,,,"child of Frontal_Inf" 14,"Frontal_Inf_Tri",2312,,,"child of Frontal_Inf" 16,"Frontal_Inf_Orb",2322,,,"child of Frontal_Inf" ,,,,, ,,,,, 20,"Supp_Motor_Area",2402,,,"child of Frontal_Sup" 26,"Frontal_Med_Orb",2612,,"?????","child of Frontal_Sup" ,,,,, 22,"Olfactory",2502,,"anterior perforated substance", ,,,,, 28,"Rectus",2702,,"gyrus rectus", 30,"Insula",3002,,"insula", ,,,,, 44,"Calcarine",5002,,"calcarine sulcus", 46,"Cuneus",5012,,"cuneus", 48,"Lingual",5022,,"lingual gyrus", ,,,,, ,,,,, 50,"Occipital_Sup",5102,,"superior occipital gyrus", 52,"Occipital_Mid",5202,,,"child of occipital lobe" 54,"Occipital_Inf",5302,,,"child of occipital lobe" 56,"Fusiform",5402,,"fusiform gyrus", ,,,,, 60,"Parietal_Sup",6102,,"superior parietal lobule", 62,"Parietal_Inf",6202,,,"child of inferior parietal lobule" 64,"SupraMarginal",6212,,"supramarginal gyrus", 66,"Angular",6222,,"angular gyrus", 68,"Precuneus",6302,,"precuneus", ,,,,, 70,"Paracentral_Lobule",6402,,,"child of precentral gyrus" ,,,,, 80,"Heschl",8102,,"anterior transverse temporal gyrus", 82,"Temporal_Sup",8112,,,"child of superior temporal gyrus" 84,"Temporal_Pole_Sup",8122,,,"child of superior temporal gyrus" 86,"Temporal_Mid",8202,,,"child of middle temporal gyrus" 88,"Temporal_Pole_Mid",8212,,,"child of middle temporal gyrus" 90,"Temporal_Inf",8302,,"inferior temporal gyrus", ,,,,, "LIMBIC",,,,, 32,"Cingulum_Ant",4002,,"anterior cingulate gyrus", 34,"Cingulum_Mid",4012,,,"child of cingulate gyrus" 36,"Cingulum_Post",4022,,"posterior cingulate gyrus", 38,"Hippocampus",4102,,"hippocampus", 40,"ParaHippocampal",4112,,"parahippocampal gyrus", ,,,,, "SUBCORTICAL",,,,, 42,"Amygdala",4202,,"amygdala", 72,"Caudate",7002,,"caudate nucleus", 74,"Putamen",7012,,"putamen", 76,"Pallidum",7022,,"globus pallidus", 78,"Thalamus",7102,,"thalamus", ,,,,, ,,,,, 92,"Cerebellum_Crus1",9002,,,"child of cerebellum" 94,"Cerebellum_Crus2",9012,,,"child of cerebellum" 96,"Cerebellum_3",9022,,,"child of cerebellum" 98,"Cerebellum_4_5",9032,,,"child of cerebellum" 100,"Cerebellum_6",9042,,,"child of cerebellum" 102,"Cerebellum_7b",9052,,,"child of cerebellum" 104,"Cerebellum_8",9062,,,"child of cerebellum" 106,"Cerebellum_9",9072,,,"child of cerebellum" 108,"Cerebellum_10",9082,,,"child of cerebellum" ,,,,, 109,"Vermis_1_2",9100,,,"child of cerebellar cortex" 110,"Vermis_3",9110,,,"child of cerebellar cortex" 111,"Vermis_4_5",9120,,,"child of cerebellar cortex" 112,"Vermis_6",9130,,,"child of cerebellar cortex" 113,"Vermis_7",9140,,,"child of cerebellar cortex" 114,"Vermis_8",9150,,,"child of cerebellar cortex" 115,"Vermis_9",9160,,,"child of cerebellar cortex" 116,"Vermis_10",9170,,,"child of cerebellar cortex" voxbo-1.8.5~svn1246/db_import/add_aal_name.cpp000066400000000000000000000063221153177201300211570ustar00rootroot00000000000000/* This program loads those brain region names from aal.csv to brain region name database */ using namespace std; #include "utils/br_util.h" #include "vbutil.h" #include #include #include #include #define MAXLENGTH 5000 int addRegionName(int, string, long); const char * file_in = "aal.csv"; string name_space("AAL"); string dbHome("./"); string rDbName("region_name.db"); string sDbName("synonym.db"); string aDbName("admin.db"); string username("admin"); /* Main function */ int main() { FILE * ifp = fopen(file_in, "r"); if (!ifp) { printf("Fails to read the file: %s\n", file_in); exit(0); } char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // The first 7 lines are skipped if (lineNo < 8) continue; // Remove the trailing "return" key stripchars(line, "\n"); string tmpStr(line); vector myRow = parseCSV(tmpStr); // Print out error message if the line is not blank but the number of field is not 3 if (myRow.size() != 6) { printf("Line #%d: the number of fields is %d\n", lineNo, myRow.size()); for (uint i = 0; i < myRow.size(); i++) cout << myRow[i] << endl; continue; } // add region name into region db long srcID = 0; if (myRow[0].length()) srcID = atol(myRow[0].c_str()); string newName = myRow[1]; if (newName.length() == 0) { printf("Line #%d: blank region name, line skipped\n", lineNo); continue; } // Note that region names in this namespace are not converted to lower case int foo = addRegionName(lineNo, newName, srcID); if (foo) printf("Line #%d: fails to add region name into region db\n", lineNo); } return 0; } /* This function adds a new region name into region name database */ int addRegionName(int lineNo, string newName, long srcID) { // Make sure the name is unique among AAL namespace records in region name db int foo = chkRegionName(dbHome, rDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in region db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region \"%s\" exists in region name db\n", lineNo, newName.c_str()); return 0; } // Make sure the name is unique among AAL namespace records in synonym db foo = chkSynonymStr(dbHome, sDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in synonym db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region name \"%s\" exists in synonym name db\n", lineNo, newName.c_str()); return 1; } regionRec regionData; regionData.setNameSpace(name_space); regionData.setName(newName); regionData.setOrgID(srcID); regionData.setSource("AAL"); regionData.setCreator(username); regionData.setAddDate(time(NULL)); foo = addRegion_db(dbHome, rDbName, aDbName, regionData); if (foo) { printf("Line #%d: failed to add %s into region name db\n", lineNo, newName.c_str()); return 1; } return 0; } voxbo-1.8.5~svn1246/db_import/add_aal_relation.cpp000066400000000000000000000120761153177201300220570ustar00rootroot00000000000000/* This program loads those brain region names from mariana.csv to brain region name database */ using namespace std; #include "utils/br_util.h" #include "tokenlist.h" #include "vbutil.h" #include #include #include #include #define MAXLENGTH 5000 void addRelationship(int, string, string); vector parseRelStr(string inputStr, string separator); int getRelInfo(int, string, long *, string &); const char * file_in = "aal.csv"; string name_space("AAL"); string dbHome("./"); string rDbName("region_name.db"); string rrDbName("region_relation.db"); string aDbName("admin.db"); string username("admin"); /* Main function */ int main() { FILE * ifp = fopen(file_in, "r"); if (!ifp) { printf("Fails to read the file: %s\n", file_in); exit(0); } char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // The first 4 lines are skipped if (lineNo < 8) continue; // Remove the trailing "return" key stripchars(line, "\n"); string tmpStr(line); vector myRow = parseCSV(tmpStr); // Print out error message if the line is not blank but the number of field is not 3 if (myRow.size() != 6) { printf("Line #%d: the number of fields is %d\n", lineNo, myRow.size()); for (uint i = 0; i < myRow.size(); i++) cout << myRow[i] << endl; continue; } // add region name into region db string newName = myRow[1]; if (newName.length() == 0) { printf("Line #%d: blank region name, line skipped\n", lineNo); continue; } string nn_equiv = myRow[4]; if (nn_equiv.length() && nn_equiv != "?????") { int foo = addRelation_db(dbHome, rDbName, rrDbName, aDbName, username, newName, name_space, nn_equiv, "NN2002", "equiv"); if (foo) printf("Error code %d: fails to add equiv relationship in line #%d\n", foo, lineNo); } addRelationship(lineNo, newName, myRow[5]); } return 0; } /* Parse relationship field and add it into relationship db */ void addRelationship(int lineNo, string r1Name, string relStr) { if (relStr.length() == 0) return; // Get AAL region ID first long r1ID = getRegionID(dbHome, rDbName, r1Name, "AAL"); if (r1ID <= 0) { printf("Line #%d: failed to get region ID of %s\n", lineNo, r1Name.c_str()); return; } // deal with relationship string vector relList = parseRelStr(relStr, ", "); for (uint i = 0; i < relList.size(); i++) { long r2ID; string dbRel; int foo = getRelInfo(lineNo, relList[i], &r2ID, dbRel); if (foo) continue; foo = addRelation_db(dbHome, rrDbName, aDbName, username, r1ID, r2ID, dbRel); if (foo) printf("Error code %d: fails to add relationship in line #%d: %s\n", foo, lineNo, relList[i].c_str()); } } /* This function returns ID of an input region name. It first searches AAL namespace, * if it is not available, search NN2002 namespace. * Returns 0 if r2 name is found; * returns 1 if input relationship string couldn't be parsed. * returns 2 if the region name is not available in either namespace; * returns -1 for db error. */ int getRelInfo(int lineNo, string inputRel, long * r2ID, string & outputRel) { if (inputRel.length() == 0) return 1; if (inputRel.length() < 9) { printf("Line #%d: can not parse relationship of %s\n", lineNo, inputRel.c_str()); return 1; } string header = inputRel.substr(0, 9); if (header == "child of ") outputRel = "child"; else if (header == "overlaps ") outputRel = "overlap"; else { printf("Line #%d: can not parse relationship of %s\n", lineNo, inputRel.c_str()); return 1; } string r2Name = inputRel.substr(9, inputRel.length() - 9); (*r2ID) = getRegionID(dbHome, rDbName, r2Name, "AAL"); if (*r2ID < 0) { printf("Line #%d: db error when searching %s in AAL namespace\n", lineNo, r2Name.c_str()); return -1; } if (*r2ID > 0) return 0; (*r2ID) = getRegionID(dbHome, rDbName, r2Name, "NN2002"); if (*r2ID < 0) { printf("Line #%d: db error when searching %s in NN2002 namespace\n", lineNo, r2Name.c_str()); return -1; } if (*r2ID == 0) { printf("Line #%d: %s not found in either AAL or NN2002 namespace\n", lineNo, r2Name.c_str()); return 2; } if (outputRel == "child") outputRel = "part-of"; return 0; } /* This function parses an input string and separates it into individual sections. * The first argument is the input string, the second is the separator string. */ vector parseRelStr(string inputStr, string sepStr) { string foo = inputStr; vector sections; int strLen = foo.length(); int sepLen = sepStr.length(); if (strLen == 0 || sepLen == 0) { sections.push_back(inputStr); return sections; } string bar; while (foo.find(sepStr) != string::npos) { int sepPost = foo.find(sepStr); if (sepPost == 0) bar = ""; else bar = foo.substr(0, sepPost); sections.push_back(bar); foo = foo.substr(sepPost + sepLen, foo.length() - sepPost - sepLen); } sections.push_back(foo); return sections; } voxbo-1.8.5~svn1246/db_import/ancillary.csv000066400000000000000000003747661153177201300206250ustar00rootroot00000000000000"ID","Structure Name","BrainInfo URL" 228,"central nervous system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=228&show=n" -2035049501,"area 21 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-2035049501&show=n" 1030,"area 9 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1030&show=n" 1029,"area 46 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1029&show=n" 1028,"area 45 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1028&show=n" 1027,"area 8B of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1027&show=n" 1026,"area 8A of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1026&show=n" 1046,"area 9 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1046&show=n" 1024,"prefrontal cortex (M)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1024&show=n" 1033,"area 12 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1033&show=n" -2020933543,"area 2 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-2020933543&show=n" -1966747129,"coronal section","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1966747129&show=n" -1928144353,"postcentral opercular areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1928144353&show=n" -1914482869,"area 8 delta of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1914482869&show=n" -1845491304,"area 4c of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1845491304&show=n" 1025,"area 8 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1025&show=n" 1032,"area 11 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1032&show=n" -1689353983,"paramedian lobule (Carpenter)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1689353983&show=n" 1034,"area 13 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1034&show=n" 1035,"area 14 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1035&show=n" 1036,"area 24 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1036&show=n" 1037,"area 25 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1037&show=n" 1038,"area 25 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1038&show=n" 1039,"area 32 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1039&show=n" 1040,"area 1 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1040&show=n" 1041,"area 2 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1041&show=n" 1042,"area 3 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1042&show=n" 1043,"area 4 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1043&show=n" 1044,"area 6 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1044&show=n" 1045,"area 8 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1045&show=n" 1031,"area 10 of Walker","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1031&show=n" -315654520,"uncal sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-315654520&show=n" 2089848597,"Pes anserinus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=2089848597&show=n" -2083179520,"paralimbic brain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-2083179520&show=n" 3,"dorsal fornix","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=3&show=n" 1,"simian sulcus (M)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1&show=n" -13463437,"area 9a of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-13463437&show=n" -29048130,"area 9b of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-29048130&show=n" -33798197,"area 15 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-33798197&show=n" -71070090,"horizontal section","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-71070090&show=n" -83666187,"area 6a of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-83666187&show=n" -131281919,"area 13 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-131281919&show=n" -148660185,"area 33 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-148660185&show=n" -207629746,"area 30 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-207629746&show=n" -1765016033,"striatopallidal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1765016033&show=n" -262518499,"transverse parietal sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-262518499&show=n" -1709721928,"area 8 alpha of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1709721928&show=n" -373122255,"area 7 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-373122255&show=n" -384884670,"area 6a alpha of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-384884670&show=n" -518784893,"area 10a of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-518784893&show=n" -526706239,"area 4a of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-526706239&show=n" -556215080,"area 14 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-556215080&show=n" -565099161,"striatonigral fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-565099161&show=n" -701499077,"area 6b beta of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-701499077&show=n" -892929184,"area 1-2 of Roberts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-892929184&show=n" -1051871313,"area SS II of Roberts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1051871313&show=n" -1202814717,"area 17 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1202814717&show=n" -1350910069,"area 8 gamma of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1350910069&show=n" -1471285997,"Cornu Ammonis (Shaw)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-1471285997&show=n" 2,"spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=2&show=n" -224729317,"area 31 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=-224729317&show=n" 1345317144,"area 6a beta of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1345317144&show=n" 1003508451,"area 24 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1003508451&show=n" 1003597394,"area 27 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1003597394&show=n" 1008020136,"trigeminal nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1008020136&show=n" 1008354279,"habenulo-interpeduncular tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1008354279&show=n" 1010167331,"central sulcus of Roland","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1010167331&show=n" 1015266456,"SPINAL TRIGEMINAL NUCLEUS","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1015266456&show=n" 1100413820,"amygdalo-hypothalamic fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1100413820&show=n" 1105600111,"area 32 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1105600111&show=n" 1125944345,"area 10 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1125944345&show=n" 1163298324,"tail of dentate gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1163298324&show=n" 1174415963,"insulo-orbito-temporopolar complex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1174415963&show=n" 1277448219,"area 22 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1277448219&show=n" 1003428832,"area 1 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1003428832&show=n" 1314674288,"area 27 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1314674288&show=n" 1238979849,"area 12 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1238979849&show=n" 1349650774,"area 9c of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1349650774&show=n" 1357706422,"area 29 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1357706422&show=n" 1435660775,"molecular layer of hippocampus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1435660775&show=n" 1593334089,"area 4 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1593334089&show=n" 1656098830,"area OFO of Roberts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1656098830&show=n" 1676376609,"area 9 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1676376609&show=n" 1694634099,"area 19 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1694634099&show=n" 1737923155,"area 26 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1737923155&show=n" 1898647097,"area 6 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1898647097&show=n" 2057547199,"fissura transversa cerebelli","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=2057547199&show=n" 2056223035,"area 18 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=2056223035&show=n" 1956980395,"area 20 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1956980395&show=n" 1047,"prefrontal area 11 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1047&show=n" 4,"Nucleus tegmentalis anterior","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=4&show=n" 1059,"area 28 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1059&show=n" 1051,"area 18 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1051&show=n" 1050,"area 5 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1050&show=n" 1289712953,"superior cerebellar peduncle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1289712953&show=n" 998628271,"amygdalostriate fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=998628271&show=n" 1053,"area 20 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1053&show=n" 1054,"area 21 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1054&show=n" 1055,"area 22 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1055&show=n" 1056,"area 43 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1056&show=n" 1052,"area 19 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1052&show=n" 1058,"area 26 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1058&show=n" 166031697,"area 3 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=166031697&show=n" 374289681,"area 11 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=374289681&show=n" 453123881,"area 8 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=453123881&show=n" 576034881,"area 5 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=576034881&show=n" 956079803,"area 7 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=956079803&show=n" 981678211,"sagittal section","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=981678211&show=n" 968004493,"plane of section","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=968004493&show=n" 1057,"area 23 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1057&show=n" 967667589,"anterior thalamic radiations","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=967667589&show=n" 584536106,"area 6b of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=584536106&show=n" 929019813,"area 9d of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=929019813&show=n" 928924128,"area 8 beta of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=928924128&show=n" 928783190,"area 4b of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=928783190&show=n" 1049,"area 11 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1049&show=n" 924990868,"area PrCO of Roberts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=924990868&show=n" 905301150,"area 6b alpha of the Vogts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=905301150&show=n" 709032212,"solitary cells of Meynert","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=709032212&show=n" 811364308,"corticofugal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=811364308&show=n" 757736275,"area 23 of Mauss-08","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=757736275&show=n" 926436668,"opercular region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=926436668&show=n" 329,"lacrimal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=329&show=n" 330,"Nucleus parasolitarius","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=330&show=n" 331,"Nucleus paraventricularis anterior","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=331&show=n" 332,"Nucleus paraventricularis posterior","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=332&show=n" 333,"Nucleus ventralis medialis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=333&show=n" 335,"capsule of nucleus lateralis dorsalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=335&show=n" 339,"capsule of anterior nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=339&show=n" 337,"posterior cerebellar commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=337&show=n" 338,"entopeduncular nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=338&show=n" 315,"periventricular zone of hypothalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=315&show=n" 340,"posterior limitans thalamic nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=340&show=n" 336,"anterior cerebellar commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=336&show=n" 328,"Nucleus ventralis corporis trapezoidei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=328&show=n" 327,"Nucleus dorsalis corporis trapezoidei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=327&show=n" 326,"Nucleus area H2","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=326&show=n" 325,"Nucleus area H1","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=325&show=n" 324,"Corpus quadrigemina","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=324&show=n" 323,"frenulum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=323&show=n" 322,"Nucleus subfascicularis, pars parvocellularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=322&show=n" 321,"Nucleus subfascicularis, pars magnocellularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=321&show=n" 320,"Nucleus reticularis magnocellularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=320&show=n" 319,"mammillo-infundibular nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=319&show=n" 318,"medial zone of hypothalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=318&show=n" 316,"lateral zone of hypothalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=316&show=n" 314,"prothalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=314&show=n" 369,"Gyrus occipitalis medius (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=369&show=n" 317,"medial hypothalamic zone (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=317&show=n" 355,"anterior funiculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=355&show=n" 370,"Gyrus occipitalis inferior (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=370&show=n" 282,"laterodorsal tegmental nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=282&show=n" 368,"Gyrus parietalis occipitalis (M)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=368&show=n" 313,"perifornical nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=313&show=n" 366,"intralimbic sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=366&show=n" 365,"Sulcus cunei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=365&show=n" 364,"acoustic sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=364&show=n" 363,"Tegmen ventriculi quarti","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=363&show=n" 361,"Nucleus supravestibularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=361&show=n" 360,"Stratum gliosum subependymale","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=360&show=n" 359,"Sagulum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=359&show=n" 358,"Nucleus parvocellularis compactus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=358&show=n" 367,"medial frontal gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=367&show=n" 356,"supralemniscal process","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=356&show=n" 341,"Pes hippocampi","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=341&show=n" 354,"Decussatio corporis trapezoidei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=354&show=n" 353,"ventral decussation of pons","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=353&show=n" 352,"comb system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=352&show=n" 351,"Decussatio fibrarum vestibularium","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=351&show=n" 350,"Nuclei conterminalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=350&show=n" 349,"molecular layer of cerebellar cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=349&show=n" 348,"Purkinje cell layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=348&show=n" 347,"Stratum grisea colliculi superioris","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=347&show=n" 346,"granular layer of cerebellar cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=346&show=n" 345,"Stratum alba colliculi superioris","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=345&show=n" 344,"ventral thalamus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=344&show=n" 343,"thalamus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=343&show=n" 342,"Area medioradiata","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=342&show=n" 357,"Processus griseum pontis tegmentalis lateralis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=357&show=n" 265,"precerebellar nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=265&show=n" 279,"annular nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=279&show=n" 278,"paranigral nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=278&show=n" 277,"parafornical nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=277&show=n" 276,"parabrachial pigmented nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=276&show=n" 275,"Nucleus parabrachialis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=275&show=n" 274,"Nucleus olivaris dissipatus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=274&show=n" 273,"Nucleus lateralis anuli aqueductus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=273&show=n" 272,"Nucleus medianus anuli aqueductus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=272&show=n" 271,"Nucleus alaris (Olszewski)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=271&show=n" 269,"Tractus olfacto-mesencephalicus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=269&show=n" 268,"pallidohypothalamic fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=268&show=n" 284,"nucleus papilliformis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=284&show=n" 266,"Area commissurae postopticae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=266&show=n" 283,"lateroventral tegmental nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=283&show=n" 264,"interposed nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=264&show=n" 263,"circumventricular organs","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=263&show=n" 262,"parabigeminal area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=262&show=n" 261,"cerebellar tentorium","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=261&show=n" 260,"Sylvian triangle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=260&show=n" 259,"falx cerebelli","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=259&show=n" 258,"falx cerebri","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=258&show=n" 257,"intralimbic gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=257&show=n" 256,"subthalamic reticular nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=256&show=n" 255,"corpus striatum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=255&show=n" 371,"corticobulbar fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=371&show=n" 438,"cervical flexure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=438&show=n" 267,"basal part of midbrain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=267&show=n" 297,"magnocellular division of accessory basal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=297&show=n" 311,"Nucleus interanterodorsalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=311&show=n" 310,"Nucleus habenularis lateralis, pars parvocellularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=310&show=n" 309,"subhabenular nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=309&show=n" 308,"Nucleus habenularis lateralis mixtocellularis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=308&show=n" 307,"Nucleus habenularis lateralis interstitialis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=307&show=n" 306,"Nucleus habenularis lateralis magnocellularis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=306&show=n" 305,"Nucleus geniculatus lateralis ventralis, pars oralis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=305&show=n" 304,"Nucleus geniculatus lateralis ventralis, pars caudalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=304&show=n" 303,"Nucleus centralis superior thalami","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=303&show=n" 302,"Nucleus centralis lateralis inferior thalami","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=302&show=n" 301,"corticoamygdalar transition area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=301&show=n" 300,"cortical amygdaloid transition area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=300&show=n" 280,"Nucleus rotundus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=280&show=n" 298,"parvicellular division of accessory basal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=298&show=n" 281,"Nucleus lateralis mesencephali","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=281&show=n" 296,"Area retro-olivaris","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=296&show=n" 295,"lumbar cistern","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=295&show=n" 294,"Bulbus cornus occipitalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=294&show=n" 293,"Margo superior","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=293&show=n" 292,"Margo medialis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=292&show=n" 291,"Margo inferior","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=291&show=n" 290,"Tractus opticus, radix lateralis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=290&show=n" 288,"Tractus opticus, radix medialis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=288&show=n" 287,"Radiatio geniculo-temporalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=287&show=n" 286,"Radices descendentes nervi vestibulari","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=286&show=n" 285,"Nucleus subputaminalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=285&show=n" 312,"Nucleus interanteroventralis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=312&show=n" 299,"ventromedial division of accessory basal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=299&show=n" 448,"ependymal layer of neural tube","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=448&show=n" 435,"primary olfactory areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=435&show=n" 461,"general visceral efferents","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=461&show=n" 460,"general visceral afferents","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=460&show=n" 459,"general somatic efferents","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=459&show=n" 458,"general somatic afferents","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=458&show=n" 457,"tela choroidea","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=457&show=n" 456,"choroid plexus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=456&show=n" 455,"transverse rhombencephalic sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=455&show=n" 454,"cerebral vesicle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=454&show=n" 453,"quadrigeminal plate","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=453&show=n" 452,"cerebellar plate","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=452&show=n" 451,"basal plate","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=451&show=n" 463,"special visceral afferents","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=463&show=n" 449,"alar plate","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=449&show=n" 464,"special visceral efferents","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=464&show=n" 447,"marginal layer of neural tube","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=447&show=n" 446,"mantle layer of neural tube","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=446&show=n" 445,"neural crest","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=445&show=n" 444,"neural tube","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=444&show=n" 443,"neural fold","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=443&show=n" 442,"neural groove","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=442&show=n" 441,"neural plate","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=441&show=n" 440,"pontine flexure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=440&show=n" 439,"cephalic flexure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=439&show=n" 190,"raphe nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=190&show=n" 437,"endopiriform nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=437&show=n" 436,"olfactory entorhinal cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=436&show=n" 450,"roof plate","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=450&show=n" 477,"perihypoglossal nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=477&show=n" 492,"nigrotectal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=492&show=n" 491,"nigrostriatal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=491&show=n" 490,"dentatorubral fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=490&show=n" 489,"dentatoreticular fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=489&show=n" 488,"cochlear nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=488&show=n" 487,"spiral ganglion","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=487&show=n" 486,"vestibular ganglion","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=486&show=n" 485,"sensory root of trigeminal nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=485&show=n" 484,"trigeminal ganglion","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=484&show=n" 482,"supraoptic decussations","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=482&show=n" 481,"accessory nerve nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=481&show=n" 480,"frontal eye field","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=480&show=n" 462,"special somatic afferents","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=462&show=n" 478,"superficial medullary stratum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=478&show=n" 434,"gustatory area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=434&show=n" 476,"centromedian-parafascicular nuclear complex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=476&show=n" 475,"thalamic association nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=475&show=n" 474,"cortical thalamic relay nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=474&show=n" 473,"specific sensory thalamic relay nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=473&show=n" 472,"vagus nerve nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=472&show=n" 471,"comma tract of Schultze","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=471&show=n" 470,"medial raphe nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=470&show=n" 469,"vestibular cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=469&show=n" 468,"vestibular nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=468&show=n" 467,"cell group y","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=467&show=n" 466,"cell group f","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=466&show=n" 465,"gustatory nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=465&show=n" 479,"paramedian pontine reticular formation","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=479&show=n" 387,"Fibrae parietotemporopontinae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=387&show=n" 254,"lentiform fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=254&show=n" 402,"interlocking gyri (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=402&show=n" 401,"deep transitional gyrus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=401&show=n" 400,"ambiens gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=400&show=n" 399,"thalamocortical radiations","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=399&show=n" 398,"posterior thalamic radiations","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=398&show=n" 397,"inferior thalamic radiations","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=397&show=n" 396,"superior thalamic radiations","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=396&show=n" 393,"auditory radiation","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=393&show=n" 392,"radiations of corpus callosum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=392&show=n" 391,"parietotemporo-occipitopontine tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=391&show=n" 390,"thalamoparietal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=390&show=n" 404,"paracentral lobule","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=404&show=n" 388,"periventricular fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=388&show=n" 405,"anterior paracentral gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=405&show=n" 386,"Fibrae paraventriculares","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=386&show=n" 385,"Fibrae intrathalamicae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=385&show=n" 384,"temporopontine fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=384&show=n" 383,"occipitopontine fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=383&show=n" 382,"parietopontine fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=382&show=n" 381,"frontopontine fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=381&show=n" 379,"corticothalamic fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=379&show=n" 378,"corticostriate fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=378&show=n" 377,"corticorubral fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=377&show=n" 376,"corticoreticular fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=376&show=n" 375,"corticopontine fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=375&show=n" 374,"pyramidal system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=374&show=n" 389,"Fibrae supraopticae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=389&show=n" 418,"extrastriate areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=418&show=n" 433,"planum polare","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=433&show=n" 432,"planum temporale","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=432&show=n" 431,"visual parasensory association cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=431&show=n" 430,"paralimbic association cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=430&show=n" 429,"auditory association cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=429&show=n" 428,"primary auditory area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=428&show=n" 426,"supplementary motor cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=426&show=n" 425,"supplementary motor areas (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=425&show=n" 424,"medial prefrontal cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=424&show=n" 423,"prefrontal cortex (Zilles)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=423&show=n" 422,"prefrontal cortex (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=422&show=n" 421,"primary motor cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=421&show=n" 403,"anterior cuneolingual gyrus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=403&show=n" 419,"primary somesthetic area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=419&show=n" 373,"corticospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=373&show=n" 417,"parastriate area 18","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=417&show=n" 416,"peristriate area 19","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=416&show=n" 415,"striate area 17","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=415&show=n" 414,"association cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=414&show=n" 413,"Vogts' areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=413&show=n" 412,"Economo's areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=412&show=n" 411,"Bonin and Bailey's areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=411&show=n" 410,"Brodmann's areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=410&show=n" 409,"vestibulo-oculomotor fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=409&show=n" 408,"pontocerebellar fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=408&show=n" 407,"fields of Forel","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=407&show=n" 406,"posterior paracentral gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=406&show=n" 420,"secondary somesthetic area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=420&show=n" 83,"area 23c of Vogt","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=83&show=n" 70,"ectorhinal area 36","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=70&show=n" 97,"retrosubicular area 48","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=97&show=n" 96,"perirhinal area 35","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=96&show=n" 95,"dorsal entorhinal area 34","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=95&show=n" 93,"agranular retrolimbic area 30","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=93&show=n" 92,"granular retrolimbic area 29","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=92&show=n" 91,"ectosplenial area 26","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=91&show=n" 90,"subgenual area 25","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=90&show=n" 89,"pregenual area 33","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=89&show=n" 88,"dorsal anterior cingulate area 32","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=88&show=n" 87,"area 23a of Vogt","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=87&show=n" 86,"area 24a of Vogt","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=86&show=n" 99,"precentral region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=99&show=n" 84,"area 24b of Vogt","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=84&show=n" 100,"precentral area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=100&show=n" 82,"area 24c of Vogt","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=82&show=n" 81,"ventral anterior cingulate area 24","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=81&show=n" 80,"dorsal posterior cingulate area 31","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=80&show=n" 79,"ventral posterior cingulate area 23","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=79&show=n" 78,"posterior transverse temporal area 42 (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=78&show=n" 77,"anterior transverse temporal area 41 (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=77&show=n" 76,"parainsular area 52 (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=76&show=n" 75,"superior temporal area 22","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=75&show=n" 74,"inferior temporal area 20","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=74&show=n" 73,"middle temporal area 21","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=73&show=n" 72,"temporopolar area 38 (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=72&show=n" 133,"amygdalostriate transition area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=133&show=n" 85,"area 23b of Vogt","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=85&show=n" 117,"gracile fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=117&show=n" 192,"ventricular system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=192&show=n" 131,"layer VII (Cajal)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=131&show=n" 130,"layer VI (Cajal)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=130&show=n" 129,"multiform layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=129&show=n" 128,"internal pyramidal layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=128&show=n" 127,"internal granular layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=127&show=n" 126,"external pyramidal layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=126&show=n" 125,"Stria laminae granularis externa","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=125&show=n" 124,"external granular layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=124&show=n" 123,"Stria laminae molecularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=123&show=n" 122,"molecular layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=122&show=n" 121,"Radix dorsalis nervi spinalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=121&show=n" 98,"postcentral region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=98&show=n" 119,"superficial features","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=119&show=n" 69,"angular area 39 (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=69&show=n" 116,"cuneate fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=116&show=n" 115,"mammillothalamic tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=115&show=n" 114,"spinothalamic tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=114&show=n" 112,"hippocampal region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=112&show=n" 111,"retrosplenial region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=111&show=n" 110,"Area cingularis intermedia","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=110&show=n" 106,"cingulate region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=106&show=n" 105,"insular region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=105&show=n" 104,"temporal region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=104&show=n" 103,"occipital region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=103&show=n" 102,"parietal region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=102&show=n" 101,"frontal region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=101&show=n" 120,"Radices ventrales nervi spinalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=120&show=n" 19,"primary intermediate sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=19&show=n" 71,"occipitotemporal area 37 (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=71&show=n" 34,"caudal postcentral area 2","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=34&show=n" 33,"intermediate postcentral area 1","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=33&show=n" 30,"frontoparietal operculum (Ono)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=30&show=n" 29,"parahippocampal ramus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=29&show=n" 28,"paramedian zone of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=28&show=n" 27,"ventral thalamus (Martinez)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=27&show=n" 26,"angular sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=26&show=n" 25,"posterior limb of lateral sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=25&show=n" 24,"uncal notch","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=24&show=n" 23,"tentorial incisure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=23&show=n" 22,"posterior descending limb of lateral sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=22&show=n" 36,"subcentral area 43","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=36&show=n" 20,"bicommissural line","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=20&show=n" 38,"subparafascicular thalamic nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=38&show=n" 18,"anterior hypothalamic group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=18&show=n" 17,"ocular nerves","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=17&show=n" 15,"posterior inferior sulcus (M)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=15&show=n" 14,"orbitoinsular sulcus (M)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=14&show=n" 12,"arcuate sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=12&show=n" 11,"superior frontal sulcus (M)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=11&show=n" 10,"medial occipitotemporal gyrus (Mai)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=10&show=n" 9,"Gyrus occipitotemporalis medialis (Nomina)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=9&show=n" 8,"Polus insulae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=8&show=n" 7,"Cortex praestriatus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=7&show=n" 6,"Gyrus hippocampi (Shantha)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=6&show=n" 5,"Cortex piriformis (Shantha)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=5&show=n" 21,"secondary intermediate sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=21&show=n" 52,"opercular area 44","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=52&show=n" 68,"supramarginal area 40 (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=68&show=n" 67,"area 7 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=67&show=n" 66,"superior parietal area 7","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=66&show=n" 65,"preparietal area 5","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=65&show=n" 64,"middle frontal area 46","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=64&show=n" 63,"prefrontal area 11","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=63&show=n" 60,"rostral area 12","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=60&show=n" 59,"area 12 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=59&show=n" 58,"area 10 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=58&show=n" 57,"frontopolar area (Mai)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=57&show=n" 56,"frontopolar area 10","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=56&show=n" 55,"orbital area 47","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=55&show=n" 35,"rostral postcentral area 3","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=35&show=n" 53,"triangular area 45","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=53&show=n" 134,"striatal cell bridges","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=134&show=n" 51,"main cingulate gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=51&show=n" 50,"superior cingulate gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=50&show=n" 49,"superior cingulate sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=49&show=n" 47,"granular frontal area 9","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=47&show=n" 46,"nonprimary motor cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=46&show=n" 45,"intermediate frontal area 8","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=45&show=n" 44,"premotor cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=44&show=n" 43,"cingulate gigantopyramidal field","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=43&show=n" 42,"motor cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=42&show=n" 41,"agranular frontal area 6","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=41&show=n" 40,"gigantopyramidal area 4","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=40&show=n" 39,"Nucleus ventralis oralis, pars medialis (Dewulf)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=39&show=n" 54,"triangular area (Wernicke)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=54&show=n" 206,"cerebellar peduncles","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=206&show=n" 493,"nigrotegmental fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=493&show=n" 219,"cerebral projection fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=219&show=n" 218,"brain stem","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=218&show=n" 217,"thalamic medullary laminae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=217&show=n" 216,"Nucleus ventralis raphae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=216&show=n" 215,"Nucleus dorsalis raphae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=215&show=n" 214,"cerebellar hemisphere","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=214&show=n" 213,"cerebellar fissures","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=213&show=n" 212,"cerebellar folia","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=212&show=n" 211,"cerebral gyri","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=211&show=n" 210,"cerebral lobes","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=210&show=n" 209,"cerebellar fiber tracts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=209&show=n" 221,"cerebral commissural fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=221&show=n" 207,"peduncle of lenticular nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=207&show=n" 222,"cerebral hemisphere","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=222&show=n" 205,"supracapsular part of globus pallidus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=205&show=n" 204,"limiting medullary lamina of globus pallidus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=204&show=n" 203,"medial tuberal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=203&show=n" 202,"lateral tuberal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=202&show=n" 201,"tuberal nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=201&show=n" 200,"tegmental nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=200&show=n" 199,"lateral lemniscal nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=199&show=n" 197,"cerveau isole","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=197&show=n" 196,"encephale isole","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=196&show=n" 195,"horns of lateral ventricle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=195&show=n" 194,"vesicles of brain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=194&show=n" 132,"amygdalohippocampal area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=132&show=n" 208,"cerebral sulci","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=208&show=n" 236,"precommissural archicortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=236&show=n" 252,"Wernicke's area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=252&show=n" 251,"Broca's area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=251&show=n" 250,"medial olfactory stria","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=250&show=n" 249,"isthmus of brain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=249&show=n" 248,"isthmus of hindbrain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=248&show=n" 247,"limbic system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=247&show=n" 246,"temporal lobe (Ono)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=246&show=n" 245,"occipital lobe (Ono)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=245&show=n" 243,"limbic lobe (Anthoney)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=243&show=n" 242,"Rhinencephalon (Nomina)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=242&show=n" 241,"rhinencephalon","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=241&show=n" 240,"cerebral peduncle (Hensyl)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=240&show=n" 220,"cerebral association fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=220&show=n" 237,"pyriform lobe","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=237&show=n" 191,"paraoptic nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=191&show=n" 235,"allocortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=235&show=n" 234,"spinal nerves","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=234&show=n" 233,"cranial nerves","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=233&show=n" 232,"sensorimotor strip","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=232&show=n" 231,"ascending reticular activating system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=231&show=n" 230,"autonomic nervous system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=230&show=n" 229,"peripheral nervous system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=229&show=n" 227,"nervous system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=227&show=n" 226,"reticular nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=226&show=n" 225,"reticular formation","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=225&show=n" 224,"superior nucleus of cranial nerve 5 (Goldberg)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=224&show=n" 223,"cerebrum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=223&show=n" 239,"(pre-)piriform cortex, temporal area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=239&show=n" 147,"lobule VII of cerebellar vermis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=147&show=n" 193,"ventricles of brain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=193&show=n" 160,"external band of Baillarger","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=160&show=n" 159,"bands of Baillarger","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=159&show=n" 158,"band of Kaes-Bechterew","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=158&show=n" 157,"polar type cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=157&show=n" 156,"parietal type cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=156&show=n" 155,"frontal type cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=155&show=n" 154,"granulous cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=154&show=n" 153,"modified granular cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=153&show=n" 152,"agranular cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=152&show=n" 151,"basal lamina","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=151&show=n" 150,"Horsley-Clarke zero plane","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=150&show=n" 162,"internal band of Baillarger","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=162&show=n" 148,"basal forebrain bundle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=148&show=n" 163,"band of Gennari","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=163&show=n" 146,"vermis of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=146&show=n" 145,"white laminae of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=145&show=n" 144,"supragranular layers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=144&show=n" 143,"Regio rolandica","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=143&show=n" 142,"Regio praesubicularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=142&show=n" 141,"Regio entorhinalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=141&show=n" 140,"Stratum radiatum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=140&show=n" 139,"Stratum oriens","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=139&show=n" 138,"Stratum pyramidale hippocampi","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=138&show=n" 137,"Stratum lacunosum-moleculare","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=137&show=n" 136,"infragranular layers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=136&show=n" 135,"anterior amygdaloid area (Lauer)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=135&show=n" 149,"Frankfurt zero plane","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=149&show=n" 176,"Subnucleus reticulatus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=176&show=n" 538,"inferior longitudinal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=538&show=n" 189,"median raphe","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=189&show=n" 188,"Colliculus superior, stratum superficiale","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=188&show=n" 187,"Colliculus superior, stratum profundum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=187&show=n" 186,"Colliculus superior, stratum intermedium","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=186&show=n" 185,"Pars reticulata, subnucleus medialis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=185&show=n" 184,"Pars reticulata, subnucleus lateralis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=184&show=n" 183,"Substantia nigra, pars reticulata (Poirier)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=183&show=n" 182,"Substantia nigra, pars reticulata (Francois)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=182&show=n" 181,"mixed cell part of substantia nigra","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=181&show=n" 180,"pars lateralis of substantia nigra","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=180&show=n" 179,"Substantia nigra, pars compacta (Poirier)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=179&show=n" 161,"sublenticular stria","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=161&show=n" 177,"Nucleus substantia nigrae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=177&show=n" 253,"lentiform nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=253&show=n" 175,"Subnucleus compactus (Olszewski & Baxter)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=175&show=n" 174,"Subnucleus compactus, pars gamma","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=174&show=n" 173,"Subnucleus compactus, pars alpha","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=173&show=n" 172,"Subnucleus compactus, pars beta","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=172&show=n" 171,"Substantia nigra (Poirier)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=171&show=n" 170,"Substantia nigra (Francois)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=170&show=n" 169,"Paleothalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=169&show=n" 168,"vermal zone of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=168&show=n" 167,"paravermal cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=167&show=n" 166,"paravermal zone of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=166&show=n" 165,"lateral zone of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=165&show=n" 164,"corticohypothalamic fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=164&show=n" 178,"Substantia nigra, pars compacta (Francois)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=178&show=n" 836,"Nucleus dorsooralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=836&show=n" 821,"accessory oculomotor nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=821&show=n" 850,"Nucleus zentrolateralis caudalis externus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=850&show=n" 849,"Nucleus zentrolateralis caudalis internus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=849&show=n" 848,"Nucleus zentrolateralis intermedius externus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=848&show=n" 847,"Nucleus zentrolateralis intermedius internus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=847&show=n" 846,"Nucleus ventrointermedius externus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=846&show=n" 845,"Nucleus ventrointermedius internus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=845&show=n" 844,"Nucleus dorsointermedius superior (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=844&show=n" 843,"Nucleus dorsointermedius internus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=843&show=n" 842,"Nucleus dorsointermedius externus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=842&show=n" 841,"ventrolateral posterior nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=841&show=n" 840,"ventrolateral anterior nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=840&show=n" 839,"Nucleus lateropolaris (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=839&show=n" 852,"Nucleus parataenialis parvocellularis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=852&show=n" 829,"tuberculum cinereum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=829&show=n" 535,"inferior occipitofrontal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=535&show=n" 823,"lateral ventral subnucleus of midbrain central gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=823&show=n" 824,"lateral subnucleus of midbrain central gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=824&show=n" 825,"medial subnucleus of midbrain central gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=825&show=n" 826,"dorsal subnucleus of midbrain central gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=826&show=n" 838,"Nucleus dorsooralis externus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=838&show=n" 828,"tuberal region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=828&show=n" 837,"Nucleus dorsooralis internus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=837&show=n" 830,"intermediate olfactory stria","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=830&show=n" 831,"ventral posterior lateral nucleus, anterior division","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=831&show=n" 832,"ventral posterior lateral nucleus, posterior division","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=832&show=n" 833,"Nucleus ventralis lateralis (Walker)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=833&show=n" 834,"ventral lateral nucleus (Ilinsky)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=834&show=n" 853,"Nucleus parataenialis interstitialis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=853&show=n" 827,"supraoptic region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=827&show=n" 867,"Nucleus pulvinaris medialis internus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=867&show=n" 882,"Nucleus paramedianus caudalis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=882&show=n" 881,"Nucleus paramedianus oralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=881&show=n" 880,"Nucleus geniculatus medialis, pars parvocellularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=880&show=n" 879,"Nucleus geniculatus medialis limitans (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=879&show=n" 878,"Nucleus geniculatus medialis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=878&show=n" 877,"Nucleus pulvinaris oroventralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=877&show=n" 876,"Nucleus pulvinaris oromedialis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=876&show=n" 875,"Nucleus pulvinaris orolateralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=875&show=n" 874,"Nucleus pulvinaris oralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=874&show=n" 873,"Nucleus pulvinaris suprabrachialis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=873&show=n" 872,"intergeniculate pulvinar","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=872&show=n" 871,"Nucleus pulvinaris ventralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=871&show=n" 870,"Nucleus pulvinaris medialis ventralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=870&show=n" 851,"Nucleus ventrocaudalis anterior externus (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=851&show=n" 861,"Nucleus anteroreuniens (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=861&show=n" 854,"Nucleus intralamellaris (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=854&show=n" 855,"Nucleus intralamellaris oralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=855&show=n" 856,"Nucleus intralamellaris ventralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=856&show=n" 857,"Nucleus intralamellaris interpolaris (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=857&show=n" 858,"Nucleus intralamellaris caudalis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=858&show=n" 869,"Nucleus pulvinaris medialis zentralis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=869&show=n" 860,"Nucleus centralis thalami, magnocellularis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=860&show=n" 868,"Nucleus pulvinaris medialis dorsalis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=868&show=n" 862,"Nucleus limitans (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=862&show=n" 863,"Nucleus limitans medialis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=863&show=n" 864,"Nucleus limitans portae (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=864&show=n" 865,"superficial pulvinar nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=865&show=n" 866,"Nucleus pulvinaris medialis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=866&show=n" 820,"stem of lateral sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=820&show=n" 859,"Nucleus centralis thalami, parvocellularis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=859&show=n" 769,"periallocortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=769&show=n" 822,"lateral dorsal subnucleus of midbrain central gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=822&show=n" 784,"fundus striati","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=784&show=n" 783,"basal ganglia (Martin)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=783&show=n" 782,"subthalamic fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=782&show=n" 781,"basal ganglia (Carpenter)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=781&show=n" 780,"precommissural septum (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=780&show=n" 779,"septal region (Riley)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=779&show=n" 778,"septal region (Swanson)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=778&show=n" 777,"septal region (Carpenter)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=777&show=n" 776,"true septum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=776&show=n" 775,"retrocommissural hippocampus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=775&show=n" 774,"Isocortex maturus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=774&show=n" 772,"longitudinal striae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=772&show=n" 786,"ventral striatum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=786&show=n" 763,"paleocortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=763&show=n" 756,"mesocortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=756&show=n" 757,"proisocortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=757&show=n" 758,"true isocortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=758&show=n" 759,"allocortex (Stephan)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=759&show=n" 760,"semicortex (Rose)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=760&show=n" 771,"area infraradiata ventralis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=771&show=n" 762,"Allocortex bulbi olfactorii","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=762&show=n" 770,"periarchicortical cingulate areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=770&show=n" 764,"peripaleocortical claustral region","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=764&show=n" 765,"septal area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=765&show=n" 766,"paleocortex (Zilles)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=766&show=n" 767,"Schizocortex (Rose)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=767&show=n" 768,"Periarchicortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=768&show=n" 787,"extended amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=787&show=n" 761,"Allocortex primitivus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=761&show=n" 803,"Fasciola cinerea (Amaral)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=803&show=n" 819,"intralingual ramus of collateral sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=819&show=n" 818,"medial frontal sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=818&show=n" 817,"intermediate precentral sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=817&show=n" 816,"marginal precentral sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=816&show=n" 815,"frontomarginal gyrus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=815&show=n" 814,"frontomarginal sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=814&show=n" 813,"sulcus of preoccipital incisura (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=813&show=n" 812,"semiannular sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=812&show=n" 811,"superior parietal sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=811&show=n" 810,"medial precentral sulcus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=810&show=n" 809,"descending terminal ramus (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=809&show=n" 808,"Gyrus temporalis occipitalis lateralis (M)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=808&show=n" 806,"Area infraradiata dorsalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=806&show=n" 785,"dorsal striatum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=785&show=n" 795,"intermediate nucleus of preoptic area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=795&show=n" 788,"amygdaloid island","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=788&show=n" 789,"striatopallidal system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=789&show=n" 790,"dorsal pallidum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=790&show=n" 791,"ventral pallidum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=791&show=n" 792,"large island of Calleja","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=792&show=n" 805,"Subregio postcingularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=805&show=n" 794,"medial corticohypothalamic tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=794&show=n" 804,"Subregio praecingularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=804&show=n" 796,"sexual dimorphic nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=796&show=n" 798,"Regio hypothalamica dorsalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=798&show=n" 799,"accessory neurosecretory nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=799&show=n" 801,"frontal operculum (Ono)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=801&show=n" 802,"Gyrus fasciolaris (Amaral)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=802&show=n" 885,"Nucleus centralis densocellularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=885&show=n" 793,"archicortex (Carpenter)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=793&show=n" 963,"lateral nuclear group of anterior horn","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=963&show=n" 883,"Nucleus paramedianus principalis (Hassler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=883&show=n" 978,"posterior intermediate septum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=978&show=n" 977,"posterior horn nuclear group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=977&show=n" 976,"posterior gray column","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=976&show=n" 975,"pontine reticulospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=975&show=n" 974,"pallidohypothalamic nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=974&show=n" 973,"olivospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=973&show=n" 972,"medullary reticulospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=972&show=n" 971,"medial nuclear group of anterior horn","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=971&show=n" 970,"medial bundle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=970&show=n" 969,"margo denticulatus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=969&show=n" 967,"lumbosacral nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=967&show=n" 966,"lumbar segments","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=966&show=n" 980,"posterior median septum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=980&show=n" 957,"intermediomedial nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=957&show=n" 949,"dorsal root fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=949&show=n" 950,"fastigioreticular fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=950&show=n" 951,"fastigiospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=951&show=n" 952,"gracile fasciculus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=952&show=n" 953,"gray commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=953&show=n" 965,"lumbar enlargement","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=965&show=n" 956,"intermediolateral nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=956&show=n" 964,"lateral spinothalamic tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=964&show=n" 958,"internuncial nuclear group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=958&show=n" 959,"interstitiospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=959&show=n" 960,"lateral bundle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=960&show=n" 961,"lateral cervical nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=961&show=n" 962,"lateral funiculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=962&show=n" 981,"posterior median sulcus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=981&show=n" 954,"inferior commissure of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=954&show=n" 995,"sacral autonomic nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=995&show=n" 1011,"triangle of Phillippe-Gombault","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1011&show=n" 1010,"thoracic segments","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1010&show=n" 1008,"sulcomarginal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1008&show=n" 1007,"subventricular terminal island","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1007&show=n" 1006,"spinovestibular tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1006&show=n" 1005,"spinotectal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1005&show=n" 1004,"spinoreticular tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1004&show=n" 1003,"spinopontine tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1003&show=n" 1002,"spinocortical tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1002&show=n" 1001,"spinocervical tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1001&show=n" 1000,"spinal part of accessory nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=1000&show=n" 999,"spinal accessory nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=999&show=n" 998,"septomarginal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=998&show=n" 979,"posterior intermediate sulcus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=979&show=n" 989,"Rexed's lamina V","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=989&show=n" 982,"posterior white column","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=982&show=n" 983,"posterolateral sulcus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=983&show=n" 984,"Rexed's lamina I","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=984&show=n" 985,"reticular nucleus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=985&show=n" 986,"Rexed's lamina III","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=986&show=n" 997,"sacral segments","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=997&show=n" 988,"Rexed's lamina IX","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=988&show=n" 996,"sacral parasympathetic cell column","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=996&show=n" 990,"Rexed's lamina VI","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=990&show=n" 991,"Rexed's lamina VII","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=991&show=n" 992,"Rexed's lamina VIII","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=992&show=n" 993,"Rexed's lamina X","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=993&show=n" 994,"Rexed's laminae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=994&show=n" 946,"commissural nucleus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=946&show=n" 987,"Rexed's lamina IV","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=987&show=n" 899,"nonmotor region of ventral nuclear group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=899&show=n" 914,"Fasciculi proprii","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=914&show=n" 913,"Conus medullaris","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=913&show=n" 912,"Cauda equina","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=912&show=n" 911,"monkey brain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=911&show=n" 910,"human brain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=910&show=n" 909,"paraflocculus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=909&show=n" 908,"intrarhinal sulcus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=908&show=n" 907,"medial fiber bundle of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=907&show=n" 906,"intermediate fiber bundle of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=906&show=n" 905,"lateral fiber bundle of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=905&show=n" 904,"paralaminar nucleus of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=904&show=n" 903,"parvicellular division of basal nucleus (Amaral)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=903&show=n" 902,"intermediate division of basal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=902&show=n" 948,"dorsal nucleus of Clarke","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=948&show=n" 893,"superior marginal sulcus of insula","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=893&show=n" 752,"tapetum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=752&show=n" 886,"Nucleus centralis inferior thalami","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=886&show=n" 888,"Nucleus centralis intermedialis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=888&show=n" 889,"Fasciculus subthalamicus (Riley)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=889&show=n" 890,"dorsomedial central lateral nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=890&show=n" 901,"magnocellular division of basal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=901&show=n" 892,"anterior marginal sulcus of insula (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=892&show=n" 900,"cortical maps","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=900&show=n" 894,"inferior marginal sulcus of insula","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=894&show=n" 895,"motor thalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=895&show=n" 896,"anterolateral region of motor thalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=896&show=n" 897,"anteromedial region of motor thalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=897&show=n" 898,"posterior region of motor thalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=898&show=n" 917,"posterior cornucommissural nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=917&show=n" 891,"commissural nucleus of thalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=891&show=n" 940,"centrobasal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=940&show=n" 915,"Filum terminale","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=915&show=n" 934,"Caput of dorsal horn","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=934&show=n" 935,"central cervical nuclear group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=935&show=n" 936,"central cervical nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=936&show=n" 937,"central gelatinous substance","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=937&show=n" 932,"association nuclear group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=932&show=n" 939,"central nuclear group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=939&show=n" 931,"anterolateral sulcus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=931&show=n" 941,"cervical enlargement","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=941&show=n" 942,"cervical segments","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=942&show=n" 943,"cervicothalamic tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=943&show=n" 944,"coccygeal segments","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=944&show=n" 945,"commissural nuclear group","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=945&show=n" 884,"Nucleus centralis latocellularis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=884&show=n" 938,"central gray columns","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=938&show=n" 924,"anterior gray commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=924&show=n" 947,"cuneate fasciculus of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=947&show=n" 918,"Nucleus pericornualis anterior","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=918&show=n" 919,"proper sensory nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=919&show=n" 920,"Nucleus proprius ventralis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=920&show=n" 921,"Rexed's lamina II","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=921&show=n" 933,"basal operculum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=933&show=n" 923,"anterior gray column","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=923&show=n" 916,"anterior cornucommissural nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=916&show=n" 925,"anterior horn nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=925&show=n" 926,"anterior median fissure of spinal cord","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=926&show=n" 927,"anterior spinothalamic tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=927&show=n" 928,"anterior white commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=928&show=n" 929,"anterolateral corticospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=929&show=n" 930,"anterolateral funiculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=930&show=n" 922,"Zona spongiosa","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=922&show=n" 576,"deep tegmental gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=576&show=n" 624,"accessory trochlear nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=624&show=n" 591,"sensory radiation","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=591&show=n" 590,"inferior division of oculomotor nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=590&show=n" 589,"parasubicular area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=589&show=n" 588,"prehippocampal rudiment","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=588&show=n" 587,"posterior part of inferior parietal lobule","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=587&show=n" 586,"polymorphic layer of dentate gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=586&show=n" 585,"granular layer of dentate gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=585&show=n" 584,"molecular layer of dentate gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=584&show=n" 583,"regio inferior of the hippocampus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=583&show=n" 582,"diverticulum unci","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=582&show=n" 581,"subicular complex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=581&show=n" 580,"hippocampal formation (Amaral)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=580&show=n" 593,"rhinencephalon (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=593&show=n" 570,"basal optic root","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=570&show=n" 562,"meninges","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=562&show=n" 563,"inferior optic radiation","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=563&show=n" 565,"sublenticular gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=565&show=n" 566,"basal ganglia (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=566&show=n" 567,"basal ganglia (clinical)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=567&show=n" 579,"hippocampal rudiment","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=579&show=n" 569,"decussation of superior medullary velum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=569&show=n" 577,"nucleus intracuneiformis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=577&show=n" 571,"nucleus of transverse peduncular tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=571&show=n" 572,"medial vestibulospinal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=572&show=n" 573,"parasplenial lobules","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=573&show=n" 574,"total fissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=574&show=n" 575,"olfactory ventricle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=575&show=n" 594,"Cornu ammonis (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=594&show=n" 568,"circle of Willis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=568&show=n" 608,"Nucleus minimus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=608&show=n" 755,"semicortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=755&show=n" 622,"accessory facial nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=622&show=n" 621,"supratrochlear nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=621&show=n" 620,"Nucleus tangentialis (Winkler)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=620&show=n" 619,"posteromedian lobule","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=619&show=n" 618,"septohippocampal nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=618&show=n" 617,"retrofacial nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=617&show=n" 616,"nucleus retroambigualis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=616&show=n" 615,"precommissural septum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=615&show=n" 614,"uncinate gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=614&show=n" 613,"subcallosal gyrus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=613&show=n" 612,"anterior parolfactory gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=612&show=n" 611,"posterior parolfactory gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=611&show=n" 592,"ventral tegmental gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=592&show=n" 602,"medial tegmental process of Jacobsohn","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=602&show=n" 595,"tegmental gray of pons","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=595&show=n" 596,"paleocerebellum (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=596&show=n" 597,"neocerebellum (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=597&show=n" 598,"Lobulus simplex (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=598&show=n" 599,"postnodular fissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=599&show=n" 610,"Regio diagonalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=610&show=n" 601,"pontine gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=601&show=n" 609,"Regio periseptalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=609&show=n" 603,"lateral tegmental process of Jacobsohn","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=603&show=n" 604,"parahypoglossal gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=604&show=n" 605,"Paraphysis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=605&show=n" 606,"motor nucleus of tegmentum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=606&show=n" 607,"parabducens nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=607&show=n" 559,"dura mater","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=559&show=n" 600,"Lobulus medianus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=600&show=n" 508,"tectal tracts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=508&show=n" 523,"chorda tympani","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=523&show=n" 522,"lemniscal system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=522&show=n" 521,"layers of presubiculum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=521&show=n" 520,"layers of subiculum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=520&show=n" 519,"layers of CA3 field","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=519&show=n" 518,"layers of CA2 field","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=518&show=n" 517,"layers of CA1 field","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=517&show=n" 516,"layers of fascia dentata","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=516&show=n" 515,"layers of superior colliculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=515&show=n" 514,"midbrain-diencephalic junction","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=514&show=n" 513,"spinomedullary junction","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=513&show=n" 512,"medullary-pontine junction","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=512&show=n" 511,"trigeminocerebellar fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=511&show=n" 561,"arachnoid","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=561&show=n" 502,"rubro-olivary fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=502&show=n" 495,"pallidonigral fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=495&show=n" 496,"pallidosubthalamic fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=496&show=n" 497,"pallidotegmental fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=497&show=n" 498,"pallidothalamic fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=498&show=n" 499,"reticulocerebellar fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=499&show=n" 510,"thalamostriate fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=510&show=n" 501,"rubrobulbar fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=501&show=n" 509,"tegmentocerebellar fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=509&show=n" 503,"rubroreticular fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=503&show=n" 504,"strionigral fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=504&show=n" 505,"striopallidal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=505&show=n" 506,"tectoreticular fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=506&show=n" 507,"tectothalamic fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=507&show=n" 526,"secondary trigeminal tracts","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=526&show=n" 500,"retinotectal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=500&show=n" 552,"nuclei of habenulopeduncular tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=552&show=n" 524,"septo-hypothalamo-mesencephalic continuum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=524&show=n" 546,"metathalamus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=546&show=n" 547,"lateral nuclear group (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=547&show=n" 548,"intralaminar nuclei (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=548&show=n" 549,"medial nuclear group (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=549&show=n" 544,"facial nerve nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=544&show=n" 551,"dorsal thalamus (Swanson)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=551&show=n" 543,"recesses of third ventricle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=543&show=n" 553,"Nuclei colliculi superioris","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=553&show=n" 554,"Nucleus colliculi inferioris","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=554&show=n" 556,"posterior column nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=556&show=n" 557,"Telencephalon medium","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=557&show=n" 558,"brain sand","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=558&show=n" 625,"nucleus of mammillary peduncle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=625&show=n" 550,"dorsal thalamus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=550&show=n" 533,"substriatal terminal island","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=533&show=n" 560,"pia mater","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=560&show=n" 527,"primary sensory areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=527&show=n" 528,"internal sagittal stratum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=528&show=n" 529,"geniculocalcarine radiation","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=529&show=n" 530,"subcallosal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=530&show=n" 545,"commissures of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=545&show=n" 532,"subcaudate terminal island","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=532&show=n" 525,"Papez circuit","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=525&show=n" 534,"tubercular terminal island(s)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=534&show=n" 537,"superior longitudinal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=537&show=n" 539,"uncinate fasciculus of forebrain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=539&show=n" 540,"arcuate fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=540&show=n" 541,"cingulum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=541&show=n" 542,"corona radiata","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=542&show=n" 531,"subcallosal stratum (Mai)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=531&show=n" 704,"chiasmal ridge","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=704&show=n" 623,"extrapyramidal system","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=623&show=n" 718,"central tegmental tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=718&show=n" 717,"trigeminal lemniscus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=717&show=n" 716,"ciliary body","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=716&show=n" 715,"Cingulum ammonale","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=715&show=n" 714,"Fasciculus obliquus crucis cerebri","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=714&show=n" 713,"bundle of Probst","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=713&show=n" 712,"vomeronasal-terminal nerve complex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=712&show=n" 711,"vomeronasal nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=711&show=n" 710,"vomeronasal organ","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=710&show=n" 709,"accessory olfactory bulb","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=709&show=n" 708,"accessory olfactory cortical areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=708&show=n" 707,"thalamic commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=707&show=n" 720,"pretectal area (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=720&show=n" 697,"second auditory area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=697&show=n" 690,"prosubiculum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=690&show=n" 691,"corticosubcortical gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=691&show=n" 692,"parietotemporal association cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=692&show=n" 693,"temporal association areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=693&show=n" 694,"projection areas of cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=694&show=n" 706,"vertical occipital fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=706&show=n" 696,"auditory cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=696&show=n" 705,"Meckel's cave","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=705&show=n" 698,"visual-auditory cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=698&show=n" 699,"area 17 of Brodmann-09","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=699&show=n" 700,"commissures of midbrain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=700&show=n" 701,"commissures of telencephalon","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=701&show=n" 703,"commissure of Probst","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=703&show=n" 721,"principal olivary nucleus (Martinez)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=721&show=n" 695,"temporal vestibular area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=695&show=n" 735,"paralemniscal gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=735&show=n" 494,"nigrothalamic fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=494&show=n" 750,"ventral periventricular hypothalamic nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=750&show=n" 749,"dorsal periventricular hypothalamic nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=749&show=n" 748,"periventricular nucleus of hypothalamus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=748&show=n" 747,"pontomedullary junction","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=747&show=n" 746,"hypothalamohypophyseal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=746&show=n" 745,"tuberohypophysial tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=745&show=n" 744,"spinal trigeminal tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=744&show=n" 743,"medial longitudinal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=743&show=n" 741,"visceral oculomotor nuclei","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=741&show=n" 740,"lateral somatic cell columns","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=740&show=n" 739,"subependymal gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=739&show=n" 738,"grey commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=738&show=n" 719,"dorsal longitudinal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=719&show=n" 729,"dorsomedial division of lateral nucleus of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=729&show=n" 722,"Forel's Field H1+H2 (Olszewski)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=722&show=n" 723,"Nucleus principalis nervi oculomotorii","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=723&show=n" 724,"medial parietal gyrus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=724&show=n" 725,"Cingulum limitans","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=725&show=n" 726,"posterior perforated substance","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=726&show=n" 737,"central gray substance","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=737&show=n" 728,"medial nucleus of amygdala (Amaral)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=728&show=n" 736,"medial lemniscus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=736&show=n" 730,"ventrolateral division of lateral nucleus of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=730&show=n" 731,"medial division of central nucleus of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=731&show=n" 732,"lateral division of central nucleus of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=732&show=n" 733,"basal nucleus of amygdala (Amaral)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=733&show=n" 734,"Nucleus amygdaloideus corticalis","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=734&show=n" 687,"parieto-occipital cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=687&show=n" 727,"anterior cortical nucleus of amygdala","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=727&show=n" 640,"Nucleus intercalatus (Le Gros Clark)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=640&show=n" 655,"transverse temporal gyri","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=655&show=n" 654,"lateral medullary lamina of inferior colliculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=654&show=n" 653,"medial medullary lamina of inferior colliculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=653&show=n" 652,"Nucleus lateralis pars caudalis of midbrain","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=652&show=n" 651,"falciform fold (H)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=651&show=n" 650,"infundibular process (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=650&show=n" 649,"Hypophysis (Carpenter)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=649&show=n" 648,"intermediate zone of cerebellum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=648&show=n" 647,"infundibular stalk (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=647&show=n" 646,"Rathke's pouch","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=646&show=n" 645,"middle lobe of Ingvar","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=645&show=n" 644,"middle lobe of Elliot Smith","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=644&show=n" 643,"Nucleus interfascicularis hypoglossi","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=643&show=n" 689,"medullary lamina of red nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=689&show=n" 633,"heterotypic cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=633&show=n" 626,"interstitial nucleus of mammillary peduncle","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=626&show=n" 627,"frontal nucleus of lateral lemniscus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=627&show=n" 628,"corticomedial nuclear group (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=628&show=n" 629,"nucleus of bulbar accessory nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=629&show=n" 630,"caudate-lenticular complex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=630&show=n" 642,"Nucleus intercalatus (Malone)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=642&show=n" 632,"ventral premammillary nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=632&show=n" 641,"Nucleus intercalatus (Rose)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=641&show=n" 635,"limitrophic cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=635&show=n" 636,"interlobar fissures","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=636&show=n" 637,"intralobar fissures","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=637&show=n" 638,"capsule of inferior colliculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=638&show=n" 639,"accessory nerve","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=639&show=n" 658,"subthalamicotegmental tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=658&show=n" 631,"dorsal premammillary nucleus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=631&show=n" 681,"epithalamus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=681&show=n" 656,"transcapsular caudatolenticular gray striae","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=656&show=n" 675,"Gyrus parietalis medialis (Winters)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=675&show=n" 676,"transverse fasciculus of cuneus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=676&show=n" 677,"ventral occipital fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=677&show=n" 678,"medial olfactory area","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=678&show=n" 673,"short association fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=673&show=n" 680,"olfactory stalk","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=680&show=n" 672,"long association bundles","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=672&show=n" 682,"occipital eye fields","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=682&show=n" 683,"preoccipital eye fields","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=683&show=n" 684,"amygdaloinsular fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=684&show=n" 685,"amygdalotemporal fasciculus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=685&show=n" 686,"periventricular layer","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=686&show=n" 754,"neocortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=754&show=n" 679,"secondary olfactory areas","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=679&show=n" 665,"interstitial nucleus of habenular commissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=665&show=n" 688,"temporo-occipital cortex","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=688&show=n" 659,"cerebellorubrothalamic tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=659&show=n" 660,"orbitofrontal fibers","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=660&show=n" 661,"lamina cornea","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=661&show=n" 662,"peduncle of substantia nigra","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=662&show=n" 674,"transverse fasciculus of lingula","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=674&show=n" 664,"caudal nucleus of zona incerta","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=664&show=n" 657,"superficial pontine stratum","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=657&show=n" 666,"band of Giacomini","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=666&show=n" 667,"glomus of choroid plexus","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=667&show=n" 668,"transverse cerebral fissure","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=668&show=n" 669,"intercollicular gray","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=669&show=n" 670,"cingulate gyrus (Crosby)","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=670&show=n" 671,"geniculate ganglion","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=671&show=n" 663,"prerubral tract","http://braininfo.rprc.washington.edu/Scripts/ancilcentraldirectory.asp?ID=663&show=n" voxbo-1.8.5~svn1246/db_import/buildNameSpace.cpp000066400000000000000000000041201153177201300214600ustar00rootroot00000000000000/* This program loads data from plain text brain region namespace file to namespace database */ using namespace std; #include "tokenlist.h" #include "vbutil.h" #include #include #include #include "mydb.h" #include "name_space.h" #define MAXLENGTH 5000 // Some gloabla variables const char * inputFilename = "namespace.txt"; string dbHome("./"); string nDbName("namespace.db"); int addRecords(int, tokenlist); /* Main function */ int main() { FILE * ifp = fopen(inputFilename, "r"); char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // The first line has column names, skipped if (lineNo == 1) continue; // remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); tokenlist myRow; myRow.SetQuoteChars("\""); myRow.SetSeparator(","); myRow.ParseLine(tmpStr); // Print out error message if the line is not blank but the number of field is less than 2 if (myRow.size() < 2) { printf("Line #%d: the number of fields is %d\n", lineNo, myRow.size()); for (int i = 0; i < myRow.size(); i++) cout << myRow[i] << endl; continue; } int foo = addRecords(lineNo, myRow); if (foo) break; } fclose(ifp); return 0; } /* This function dumps some of the fields in a row into namespace database */ int addRecords(int lineNo, tokenlist myRow) { namespaceRec nData; string nameStr = myRow[0]; nData.setName(nameStr); nData.setDescription(myRow[1]); Dbt key((char *) nameStr.c_str(), nameStr.length() + 1); void * buff = nData.getBuffer(); int size = nData.getBufferSize(); Dbt data(buff, size); mydb nDB(dbHome, nDbName); try { int foo = nDB.getDb().put(NULL, &key, &data, 0); if (foo) { printf("Line %d: namespace db put error\n", lineNo); return 1; } } catch (DbException &e) { nDB.getDb().err(e.get_errno(), "Error in addRecords()"); return -1; } catch(exception &e) { nDB.getDb().errx("Error in addRecords(): %s", e.what()); return -2; } return 0; } voxbo-1.8.5~svn1246/db_import/buildRelation.cpp000066400000000000000000000130701153177201300214050ustar00rootroot00000000000000/* load.cpp: load data from plain text file to patient database */ using namespace std; #include "utils/br_util.h" #include "tokenlist.h" #include "vbutil.h" #include #include #include #define MAXLENGTH 5000 // Some gloabla variables const char * inputFilename = "hierarchy.csv"; string name_space("NN2002"); string dbHome("./"); string rName("region_name.db"); string rrName("region_relation.db"); string aDbName("admin.db"); string id_field("Next Relationship ID"); string username("admin"); void addRecords(); int addRegionRelation(int, string, long); long getRegionID(string, string, string, long); string convertName(string ); /* Main function */ int main() { int foo = setAdmin_db(dbHome, aDbName, id_field, 1); if (foo) { printf("Unable to initialize relationship ID to 1 in admin db\n"); return 0; } addRecords(); return 0; } /* This function adds a certain score into score database */ void addRecords() { FILE * ifp = fopen(inputFilename, "r"); char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // The first line is the column names, so it is skipped if (lineNo == 1) continue; // remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); tokenlist myRow; myRow.SetQuoteChars("\""); myRow.SetSeparator(","); myRow.ParseLine(tmpStr); // Print out error message if the line is not blank but the number of field is not 7 or 8 if (myRow.size() != 8 && myRow.size() != 7) { printf("Line #%d: the number of fields is %d\n", lineNo, myRow.size()); for (int i = 0; i < myRow.size(); i++) cout << myRow[i] << endl; continue; } // Skip the region whose parent ID is same as source ID if (myRow[0] == myRow[5]) { printf("Line #%d: source ID is same as parent ID, skipped\n", lineNo); continue; } string newName = convertName(myRow[1]); if (newName == "") { printf("Line #%d: blank region name or (M) attached in \"%s\", line skipped\n", lineNo, myRow(1)); continue; } long parentID = atol(myRow(5)); int foo = addRegionRelation(lineNo, newName, parentID); if (foo) break; } fclose(ifp); } /* This function dumps some of the fields in a row into region relation database */ int addRegionRelation(int lineNo, string r1_name, long parentID) { long relationID = getAdmin_db(dbHome, aDbName, id_field); if (relationID <= 0) { printf("Line #%ld: fails to get next available relationship ID from admin db", relationID); return -1; } long r1_id = getRegionID(dbHome, rName, r1_name, name_space); if (r1_id <= 0) { printf("Line #%d: fails to get region ID of %s from region name db\n", lineNo, r1_name.c_str()); return 1; } long r2_id = getRegionID(dbHome, rName, name_space, parentID); if (r2_id <= 0) { printf("Line %d: parent ID not found (source ID is %ld)\n", lineNo, parentID); return -1; } if (r1_id == r2_id) { printf("Line %d: region ID is same as parent ID, skipped\n", lineNo); return 0; } regionRelationRec rrData; rrData.setID(relationID); rrData.setRegion1(r1_id); rrData.setRegion2(r2_id); rrData.setRelationship("child"); rrData.setAddDate(time(NULL)); rrData.setCreator(username); rrData.setComments("NN2002.hierarchy.parent"); Dbt key(&relationID, sizeof(long)); void * buff = rrData.getBuffer(); int size = rrData.getBufferSize(); Dbt data(buff, size); mydb regionRelationDB(dbHome, rrName); try { int foo = regionRelationDB.getDb().put(NULL, &key, &data, 0); if (foo) { printf("Line %d: relationship db put error\n", lineNo); return 1; } } catch (DbException &e) { regionRelationDB.getDb().err(e.get_errno(), "Error in addRegionRelation()"); return -1; } catch(exception &e) { regionRelationDB.getDb().errx("Error in addRegionRelation(): %s", e.what()); return -2; } relationID++; int bar = setAdmin_db(dbHome, aDbName, id_field, relationID); if (bar) { printf("Line %d: fails to set relationship ID to %ld\n", lineNo, relationID); return 2; } return 0; } /* This function searches region name db according to its original ID and namespace * and returns the region ID. * Returns -1 or -2 for exceptions; * returns 0 if it is not found or any other errors; */ long getRegionID(string dbHome, string rDbName, string name_space, long orgID) { mydb rDB(dbHome, rDbName); Dbc *cursorp; Dbt key, data; int ret; long foo = 0; try { rDB.getDb().cursor(NULL, &cursorp, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { regionRec rData(data.get_data()); if (rData.getNameSpace() == name_space && rData.getOrgID() == orgID) { foo = rData.getID(); break; } } } catch(DbException &e) { rDB.getDb().err(e.get_errno(), "Error in getRegionID()"); foo = -1; } catch(exception &e) { rDB.getDb().errx("Error in getRegionID(): %s", e.what()); foo = -2; } cursorp->close(); return foo; } /* This function first checks the input region name. * If it ends with "(H)", remove that part and convert it to lower case letters. * If if ends with "(M)", skip the record completely; */ string convertName(string inputStr) { int strLen = inputStr.length(); if (strLen < 4) return toLowerCase(inputStr); string newStr; string last4 = inputStr.substr(strLen - 4, 4); if (last4 == " (M)") return ""; else if (last4 == " (H)") newStr = inputStr.substr(0, strLen - 4); else newStr = inputStr; return toLowerCase(newStr); } voxbo-1.8.5~svn1246/db_import/hierarchy.csv000066400000000000000000004337161153177201300206140ustar00rootroot00000000000000"ID","English","Latin","Abbrev","V/S","Parent ID","P/S","BrainInfo URL" 9,"telodiencephalic fissure","Fissura telo-diencephalica","tdf","Vol",8,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=9&show=y" 430,"interventricular foramen","Foramen interventriculare","IVF","Vol",271,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=430&show=y" 442,"optic chiasm","Chiasma opticum","ox","Vol",271,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=442&show=y" 443,"optic tract","Tractus opticus","opt","Vol",271,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=443&show=y" 444,"habenulo-interpeduncular tract of diencephalon","Tractus habenulo-interpeduncularis diencephali","hipd","Vol",271,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=444&show=y" 256,"substantia innominata","Substantia innominata","SI","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=256&show=y" 257,"basal nucleus","Nucleus basalis","B","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=257&show=y" 258,"islands of Calleja","Insula Callejae","IClj","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=258&show=y" 259,"nucleus accumbens","Nucleus accumbens","Acb","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=259&show=y" 260,"subcallosal area","Area subcallosa","SCA","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=260&show=y" 261,"olfactory bulb","Bulbus olfactorius","Olf","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=261&show=y" 262,"anterior olfactory nucleus","Nucleus olfactorius anterior","AO","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=262&show=y" 263,"medial olfactory gyrus","Gyrus medius olfactorius","MOG","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=263&show=y" 264,"anterior perforated substance","Substantia perforata anterior","APS","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=264&show=y" 265,"olfactory tract","Tractus olfactorius","olf","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=265&show=y" 266,"lateral olfactory stria","Stria olfactoria lateralis","lo","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=266&show=y" 267,"diagonal band","Stria diagonalis","db","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=267&show=y" 268,"stria terminalis","Stria terminalis","st","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=268&show=y" 270,"ventral amygdalofugal projection","Tractus amygdalofugalis ventralis","vaf","Vol",12,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=270&show=y" 233,"claustral amygdaloid area","Area claustralis amygdalae","ClA","Vol",206,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=233&show=y" 234,"claustrum","Claustrum","Cl","Vol",206,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=234&show=y" 1008802938,"LIMBIC LOBE","Lobus fornicatus","LL","Vol",20,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1008802938&show=y" 172,"semioval center","Centrum semiovale","sovc","Vol",171,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=172&show=y" 190,"lamina terminalis","Lamina terminalis","LT","Vol",171,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=190&show=y" 235,"external capsule","Capsula externa","ec","Vol",171,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=235&show=y" 236,"extreme capsule","Capsula extrema","exc","Vol",171,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=236&show=y" 280,"pineal body","Corpus pineale","Pi","Vol",275,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=280&show=y" 281,"stria medullaris of thalamus","Stria medullaris thalami","sm","Vol",275,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=281&show=y" 282,"habenular commissure","Commissura habenularum","hbc","Vol",275,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=282&show=y" 251,"anterior column of fornix","Columna fornicis anterior","afx","Vol",250,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=251&show=y" 252,"precommissural fornix","Fornix precommissuralis","pfx","Vol",250,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=252&show=y" 253,"body of fornix","Corpus fornicis","bfx","Vol",250,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=253&show=y" 254,"posterior column of fornix","Crus fornicis","pcfx","Vol",250,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=254&show=y" 255,"commissure of fornix","Commissura fornicis","cfx","Vol",250,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=255&show=y" 413,"dorsal hypothalamic area","Nucleus hypothalamicus dorsalis","DH","Vol",358,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=413&show=y" 414,"postcommissural fornix","Fornix postcommissuralis","pofx","Vol",358,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=414&show=y" 415,"dorsal longitudinal fasciculus of hypothalamus","Fasciculus longitudinalis dorsalis (hypothalami)","dlfh","Vol",358,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=415&show=y" 416,"medial forebrain bundle","Fasciculus prosencephalicus medialis","mfb","Vol",358,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=416&show=y" 200,"choroid plexus of lateral ventricle","Plexus choroideus (ventriculi lateralis)","cplv","Vol",191,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=200&show=y" 201,"tela choroidea of lateral ventricle","Tela choroidea (ventriculi lateralis)","tclv","Vol",191,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=201&show=y" 202,"frontal horn of lateral ventricle","Cornu frontale (ventriculi lateralis)","FLV","Vol",191,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=202&show=y" 203,"body of lateral ventricle","Pars centralis (ventriculi lateralis)","BLV","Vol",191,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=203&show=y" 204,"temporal horn of lateral ventricle","Cornu temporale (ventriculi lateralis)","TLV","Vol",191,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=204&show=y" 205,"occipital horn of lateral ventricle","Cornu occipitale (ventriculi lateralis)","OLV","Vol",191,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=205&show=y" 418,"subthalamic nucleus","Nucleus subthalamicus","STh","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=418&show=y" 419,"nucleus of ansa lenticularis","Nucleus ansae lenticularis","AL","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=419&show=y" 420,"nucleus of field H","Nucleus area H","FH","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=420&show=y" 421,"zona incerta","Zona incerta","ZI","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=421&show=y" 422,"field H1","Fasciculus thalamicus","H1","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=422&show=y" 423,"field H","Area tegmentalis H","H","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=423&show=y" 424,"field H2","Fasciculus lenticularis (diencephali)","H2","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=424&show=y" 425,"capsule of subthalamic nucleus","Capsula nuclei subthalamici","csth","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=425&show=y" 426,"pallidohabenular bundle","Fasciculus pallido-habenularis","phb","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=426&show=y" 427,"ansa lenticularis","Ansa lenticularis","al","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=427&show=y" 428,"ansa peduncularis","Ansa peduncularis","ap","Vol",417,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=428&show=y" 348,"thalamic reticular nucleus","Nucleus reticularis thalami","Rt","Vol",283,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=348&show=y" 357,"stratum zonale of thalamus","Stratum zonale thalami","SZ","Vol",283,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=357&show=y" 434,"velum interpositum","Velum interpositum","vi","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=434&show=y" 435,"choroid plexus of third ventricle","Plexus choroidea (ventriculi tertii)","cp3v","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=435&show=y" 436,"tela choroidea of third ventricle","Tela choroidea (ventriculi tertii)","tc3v","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=436&show=y" 437,"subfornical organ","Organum subfornicale","SFO","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=437&show=y" 438,"suprapineal recess","Recessus suprapinealis","SPiRe","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=438&show=y" 439,"pineal recess","Recessus pinealis","PiRe","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=439&show=y" 440,"optic recess","Recessus opticus","ORe","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=440&show=y" 441,"infundibular recess","Recessus infundibularis","IRe","Vol",429,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=441&show=y" 225,"central amygdaloid nucleus","Nucleus amygdalae centralis","CeA","Vol",219,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=225&show=y" 232,"intercalated amygdaloid nuclei","Nucleus amygdalae intercalatus","IA","Vol",219,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=232&show=y" 227,"lateral amygdaloid nucleus","Nucleus amygdalae lateralis","LA","Vol",226,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=227&show=y" 231,"accessory basal amygdaloid nucleus","Nucleus amygdalae basalis accessorius","ABA","Vol",226,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=231&show=y" 221,"anterior amygdaloid area","Area amygdaloidea anterior","AA","Vol",220,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=221&show=y" 222,"cortical amygdaloid nucleus","Nucleus amygdalae corticalis","CoA","Vol",220,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=222&show=y" 223,"medial amygdaloid nucleus","Nucleus amygdalae medialis","MeA","Vol",220,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=223&show=y" 224,"nucleus of lateral olfactory tract","Nucleus striae olfactoriae lateralis","LOT","Vol",220,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=224&show=y" 229,"lateral part of basal amygdaloid nucleus","Nucleus amygdalae basalis, pars lateralis","BAL","Vol",228,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=229&show=y" 230,"medial part of basal amygdaloid nucleus","Nucleus amygdalae basalis, pars medialis","BAM","Vol",228,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=230&show=y" 188,"anterior part of anterior commissure","Commissura anterior, pars anterior","aca","Vol",187,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=188&show=y" 189,"posterior part of anterior commissure","Commissura anterior, pars posterior","acp","Vol",187,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=189&show=y" 365,"anteroventral periventricular nucleus","Nucleus periventricularis anteroventralis","AVPe","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=365&show=y" 366,"supraoptic crest","Organum vasculosum","SoC","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=366&show=y" 367,"suprachiasmatic nucleus","Nucleus suprachiasmaticus","SCh","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=367&show=y" 368,"supraoptic nucleus","Nucleus supraopticus","SO","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=368&show=y" 369,"anterior nucleus of hypothalamus","Nucleus hypothalamicus anterior","AH","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=369&show=y" 370,"paraventricular nucleus of hypothalamus","Nucleus paraventricularis hypothalami","Pa","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=370&show=y" 371,"dorsal supraoptic decussation","Commissura supraoptica dorsalis","dsox","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=371&show=y" 372,"ventral supraoptic decussation","Commissura supraoptica ventralis","vsox","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=372&show=y" 373,"anterior hypothalamic commissure","Commissura hypothalamica anterior","ahc","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=373&show=y" 374,"supraopticohypophysial tract","Tractus supraopticohypophysialis","soh","Vol",359,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=374&show=y" 361,"median preoptic nucleus","Nucleus preopticus medianus","MnPO","Vol",360,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=361&show=y" 362,"preoptic periventricular nucleus","Nucleus periventricularis preopticus","POP","Vol",360,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=362&show=y" 363,"medial preoptic nucleus","Nucleus preopticus medialis","MPO","Vol",360,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=363&show=y" 364,"lateral preoptic nucleus","Nucleus preopticus lateralis","LPO","Vol",360,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=364&show=y" 286,"anterodorsal nucleus","Nucleus anterodorsalis","AD","Vol",285,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=286&show=y" 287,"anteromedial nucleus","Nucleus anteromedialis","AM","Vol",285,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=287&show=y" 288,"anteroventral nucleus","Nucleus anteroventralis","AV","Vol",285,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=288&show=y" 153,"paraterminal gyrus","Gyrus paraterminalis","PTG","Vol",152,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=153&show=y" 158,"fasciolar gyrus","Gyrus fasciolaris","FG","Vol",152,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=158&show=y" 170,"subiculum","Subiculum","S","Vol",159,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=170&show=y" 168,"alveus","Alveus","alv","Vol",159,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=168&show=y" 169,"fimbria of hippocampus","Fimbria hippocampi","fi","Vol",159,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=169&show=y" 155,"induseum griseum","Induseum griseum","IG","Vol",154,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=155&show=y" 156,"lateral longitudinal stria","Stria longitudinalis lateralis","lls","Vol",154,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=156&show=y" 157,"medial longitudinal stria","Stria longitudinalis medialis","mls","Vol",154,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=157&show=y" 162,"fascia dentata","Fascia dentata","fd","Vol",161,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=162&show=y" 163,"hilus of dentate gyrus","Hilus gyri dentati","hdg","Vol",161,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=163&show=y" 165,"CA1 field","Cornu Ammonis 1","CA1","Vol",164,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=165&show=y" 166,"CA2 field","Cornu Ammonis 2","CA2","Vol",164,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=166&show=y" 167,"CA3 field","Cornu Ammonis 3","CA3","Vol",164,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=167&show=y" 143,"anterior cingulate gyrus","Gyrus cinguli anterior","ACgG","Vol",141,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=143&show=y" 144,"posterior cingulate gyrus","Gyrus cinguli posterior","PCgG","Vol",141,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=144&show=y" 145,"isthmus of cingulate gyrus","Isthmus gyri cinguli","ICgG","Vol",141,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=145&show=y" -1973597309,"isthmus cingulate white matter","Substantia medullaris isthmus cinguli","icgw","Vol",685484116,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1973597309&show=y" -1384141764,"posterior cingulate white matter","Substantia medullaris cinguli posterior","pcgw","Vol",685484116,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1384141764&show=y" 1750646129,"anterior cingulate white matter","Substantia medullaris cinguli anterior","acgw","Vol",685484116,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1750646129&show=y" 174,"anterior forceps of corpus callosum","Forceps frontalis","acc","Vol",173,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=174&show=y" 175,"rostrum of corpus callosum","Rostrum corpus callosi","rcc","Vol",173,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=175&show=y" 176,"genu of corpus callosum","Genu corpus callosi","gcc","Vol",173,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=176&show=y" 177,"body of corpus callosum","Truncus corpus callosi","bcc","Vol",173,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=177&show=y" 178,"splenium of corpus callosum","Splenium corpus callosi","scc","Vol",173,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=178&show=y" 179,"posterior forceps of corpus callosum","Forceps occipitalis","pcc","Vol",173,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=179&show=y" 65,"superior frontal gyrus","Gyrus frontalis superior","SFG","Vol",37,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=65&show=y" 66,"middle frontal gyrus","Gyrus frontalis medius","MFG","Vol",37,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=66&show=y" 71,"precentral gyrus","Gyrus precentralis","PrG","Vol",37,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=71&show=y" 76,"gyrus rectus","Gyrus rectus","GRe","Vol",37,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=76&show=y" -2063754382,"superior transverse frontopolar gyrus (H)","Gyrus frontopolaris transversus superior (H)","TFPGS","Vol",962901580,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-2063754382&show=y" -1465682436,"inferior rostral gyrus (H)","Gyrus rostralis inferior (H)","IRoG","Vol",37,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1465682436&show=y" 309168177,"superior rostral gyrus (H)","Gyrus rostralis superior (H)","SRoG","Vol",37,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=309168177&show=y" 855537679,"medial transverse frontopolar gyrus (H)","Gyrus frontopolaris transversus med. (H)","TFPGM","Vol",962901580,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=855537679&show=y" 1233666840,"inferior transverse frontopolar gyrus (H)","Gyrus frontopolaris transversus inferior (H)","TFPGI","Vol",962901580,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1233666840&show=y" 72,"fronto-orbital gyrus (M)","Gyrus fronto-orbitalis (M)","FOG","Vol",73,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=72&show=y" 68,"triangular part of inferior frontal gyrus (H)","Gyrus frontalis inferior, pars triangularis (H)","TrIFG","Vol",67,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=68&show=y" 69,"opercular part of inferior frontal gyrus (H)","Gyrus frontalis inferior, pars opercularis (H)","OpIFG","Vol",67,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=69&show=y" 70,"orbital part of inferior frontal gyrus (H)","Gyrus frontalis inferior, pars orbitalis (H)","OrIFG","Vol",67,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=70&show=y" 74,"lateral orbital gyrus","Gyrus orbitalis lateralis","LOrG","Vol",73,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=74&show=y" 75,"medial orbital gyrus","Gyrus orbitalis medialis","MOrG","Vol",73,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=75&show=y" -1761421113,"posterior orbital gyrus (H)","Gyrus orbitalis posterior (H)","POrG","Vol",73,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1761421113&show=y" -1278177547,"intermediate orbital gyrus (H)","Gyrus orbitalis longitudinalis medius","IOrG","Vol",73,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1278177547&show=y" -1772196785,"precentral white matter","Substantia medullaris precentralis","prw","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1772196785&show=y" -1517302059,"lateral orbital white matter","Substantia medullaris orbitalis lateralis","lorw","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1517302059&show=y" -1480491770,"medial orbital white matter","Substantia medullaris orbitalis medialis","morw","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1480491770&show=y" -437238407,"superior frontal white matter","Substantia medullaris frontalis superior","sfw","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-437238407&show=y" 904236454,"middle frontal white matter","Substantia medullaris frontalis medius","mfw","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=904236454&show=y" 953926355,"rectus white matter","Substantia medullaris rectus","rew","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=953926355&show=y" 957385971,"inferior frontal white matter","Substantia medullaris frontalis inferioris","ifw","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=957385971&show=y" 1206633712,"fronto-orbital white matter","Substantia medullaris fronto-orbitalis","fow","Vol",264031898,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1206633712&show=y" 214,"lateral globus pallidus","Globus pallidus lateralis","LGP","Vol",213,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=214&show=y" 215,"medial globus pallidus","Globus pallidus medialis","MGP","Vol",213,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=215&show=y" 216,"lateral medullary lamina","Lamina medullaris lateralis","lml","Vol",213,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=216&show=y" 217,"medial medullary lamina","Lamina medullaris medialis","mml","Vol",213,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=217&show=y" 218,"accessory medullary lamina","Lamina medullaris accessoria","aml","Vol",213,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=218&show=y" 278,"lateral habenular nucleus","Nucleus habenularis lateralis","LHb","Vol",277,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=278&show=y" 279,"medial habenular nucleus","Nucleus habenularis medialis","MHb","Vol",277,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=279&show=y" 101,"precentral gyrus of insula (H)","Gyrus precentralis insulae (H)","PrGI","Vol",93,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=101&show=y" 105,"accessory short gyrus (H)","Gyrus brevis accessorius (H)","ASG","Vol",93,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=105&show=y" 106,"anterior accessory gyrus (H)","Gyrus accessorius anterior (H)","AAG","Vol",93,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=106&show=y" 103,"first posterior central gyrus (H)","Gyrus centralis posterior primus (H)","PCG1","Vol",102,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=103&show=y" 104,"second posterior central gyrus (H)","Gyrus centralis posterior secundus (H)","PCG2","Vol",102,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=104&show=y" 98,"first short gyrus (H)","Gyrus brevis I (H)","SG1","Vol",97,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=98&show=y" 99,"second short gyrus (H)","Gyrus brevis II (H)","SG2","Vol",97,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=99&show=y" 100,"intermediate short gyrus (H)","Gyrus brevis intermedius (H)","ISG","Vol",97,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=100&show=y" 377,"intermediate periventricular nucleus","Nucleus periventricularis hypothalami","IPe","Vol",375,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=377&show=y" 378,"arcuate nucleus of hypothalamus","Nucleus infundibularis","ArcH","Vol",375,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=378&show=y" 379,"retrochiasmatic area","Area retrochiasmatica","RCh","Vol",375,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=379&show=y" 380,"dorsomedial nucleus of hypothalamus","Nucleus hypothalamicus dorsomedialis","DMH","Vol",375,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=380&show=y" 381,"ventromedial nucleus of hypothalamus","Nucleus hypothalamicus ventromedialis","VMH","Vol",375,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=381&show=y" 391,"tuberal part of hypophysis","Pars tuberalis (hypophysis)","THP","Vol",390,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=391&show=y" 392,"intermediate part of hypophysis","Pars intermedia (hypophysis)","IHP","Vol",390,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=392&show=y" 393,"distal part of hypophysis","Pars distalis (hypophysis)","DHP","Vol",390,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=393&show=y" 388,"infundibular stem","Infundibulum","InfS","Vol",384,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=388&show=y" 389,"pars nervosa of hypophysis","Pars nervosa (hypophysis)","PNHP","Vol",384,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=389&show=y" 386,"anterior median eminence","Eminentia mediana anterior","AME","Vol",385,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=386&show=y" 387,"posterior median eminence","Eminentia mediana posterior","PME","Vol",385,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=387&show=y" 181,"anterior limb of internal capsule","Crus anterius capsulae internae","aic","Vol",180,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=181&show=y" 182,"genu of internal capsule","Genu capsulae internae","gic","Vol",180,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=182&show=y" 980193017,"probable internal capsule","probable internal capsule","ic4","Vol",180,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=980193017&show=y" 184,"lenticulothalamic part of internal capsule","Pars thalamolentiformis (capsulae internae)","ltic","Vol",183,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=184&show=y" 185,"retrolenticular part of internal capsule","Pars retrolentiformis (capsulae internae)","rlic","Vol",183,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=185&show=y" 186,"sublenticular part of internal capsule","Pars sublentiformis (capsulae internae)","slic","Vol",183,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=186&show=y" 306,"centromedian nucleus","Nucleus centromedianus","CMn","Vol",300,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=306&show=y" 307,"parafascicular nucleus","Nucleus parafascicularis","PF","Vol",300,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=307&show=y" 302,"central dorsal nucleus","Nucleus centralis dorsalis","CD","Vol",301,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=302&show=y" 303,"central lateral nucleus","Nucleus centralis lateralis","CL","Vol",301,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=303&show=y" 304,"central medial nucleus","Nucleus centralis medialis","CM","Vol",301,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=304&show=y" 305,"paracentral nucleus","Nucleus paracentralis","PC","Vol",301,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=305&show=y" 410,"tuberomammillary nucleus","Nucleus tuberomamillaris","TM","Vol",409,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=410&show=y" 411,"lateral tuberal nuclei","Nuclei tuberis lateralis","LTu","Vol",409,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=411&show=y" 412,"lateral hypothalamic nucleus","Nucleus hypothalamicus lateralis","LHy","Vol",409,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=412&show=y" 309,"lateral dorsal nucleus","Nucleus lateralis dorsalis","LD","Vol",308,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=309&show=y" 310,"lateral posterior nucleus","Nucleus lateralis posterior","LP","Vol",308,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=310&show=y" 312,"oral pulvinar nucleus","Nucleus pulvinaris oralis","OPul","Vol",311,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=312&show=y" 313,"lateral pulvinar nucleus","Nucleus pulvinaris lateralis","LPul","Vol",311,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=313&show=y" 314,"medial pulvinar nucleus","Nucleus pulvinaris medialis","MPul","Vol",311,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=314&show=y" 315,"inferior pulvinar nucleus","Nucleus pulvinaris inferior","IPul","Vol",311,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=315&show=y" 296,"paralaminar part of medial dorsal nucleus","Nucleus medialis dorsalis, pars paralaminaris","MDPL","Vol",295,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=296&show=y" 297,"magnocellular part of medial dorsal nucleus","Nucleus medialis dorsalis, pars magnocellularis","MDM","Vol",295,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=297&show=y" 298,"parvicellular part of medial dorsal nucleus","Nucleus medialis dorsalis, pars parvocellularis","MDPC","Vol",295,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=298&show=y" 299,"densocellular part of medial dorsal nucleus","Nucleus medialis dorsalis, pars densocellularis","MDD","Vol",295,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=299&show=y" 336,"dorsal nucleus of lateral geniculate body","Nucleus corporis geniculati lateralis, pars dorsal","DLG","Vol",335,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=336&show=y" 337,"ventral nucleus of lateral geniculate body","Nucleus corporis geniculati lateralis, pars ventra","VLG","Vol",335,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=337&show=y" 339,"dorsal nucleus of medial geniculate body","Nucleus corporis geniculati medialis, pars dorsali","DMG","Vol",338,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=339&show=y" 340,"ventral nucleus of medial geniculate body","Nucleus corporis geniculati medialis, pars ventral","VMG","Vol",338,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=340&show=y" 341,"magnocellular nucleus of medial geniculate body","Nucleus corporis geniculati medialis, pars magnoce","MMG","Vol",338,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=341&show=y" 342,"capsule of medial geniculate body","Capsula corporis geniculati medialis","cmg","Vol",338,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=342&show=y" 290,"paratenial nucleus","Nucleus paratenialis","PT","Vol",289,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=290&show=y" 291,"paraventricular nucleus of thalamus","Nucleus paraventricularis thalami","PV","Vol",289,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=291&show=y" 292,"reuniens nucleus","Nucleus reuniens","Re","Vol",289,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=292&show=y" 293,"rhomboidal nucleus","Nucleus rhomboidalis","Rh","Vol",289,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=293&show=y" 294,"subfascicular nucleus","Nucleus subfascicularis","SF","Vol",289,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=294&show=y" 139,"cuneus","Cuneus","Cun","Vol",122,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=139&show=y" 140,"lingual gyrus","Gyrus lingualis","LiG","Vol",122,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=140&show=y" 136,"superior occipital gyrus (H)","Gyrus occipitalis superior (H)","SOG","Vol",122,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=136&show=y" 137,"lateral occipital gyrus (H)","Gyrus occipitalis lateralis (H)","LOG","Vol",122,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=137&show=y" 134,"occipital gyrus (M)","Gyrus occipitalis (M)","OG","Vol",122,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=134&show=y" 135,"annectant gyrus (M)","Gyrus annectens (M)","AG","Vol",122,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=135&show=y" 138,"inferior occipital gyrus (M)","Gyrus occipitalis inferior (M)","IOG","Vol",122,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=138&show=y" -2005119656,"lingual white matter","Substantia medullaris lingualis","liw","Vol",964479090,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-2005119656&show=y" -1269332145,"cuneate white matter","Substantia medullaris cuneatus","cuw","Vol",964479090,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1269332145&show=y" -1176007523,"inferior occipital white matter","Substantia medullaris occipitalis inferior","iow","Vol",964479090,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1176007523&show=y" 496247337,"occipital white matter","Substantia medullaris occipitalis","ow","Vol",964479090,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=496247337&show=y" 922579890,"annectant white matter","Substantia medullaris annectens","aw","Vol",964479090,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=922579890&show=y" 147,"prepyriform area","Area prepyriformis","PPA","Vol",146,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=147&show=y" 148,"periamygdaloid area","Regio periamygdalaris","PA","Vol",146,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=148&show=y" 149,"presubiculum","Presubiculum","PrS","Vol",146,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=149&show=y" 150,"entorhinal area","Area entorhinalis","Ent","Vol",146,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=150&show=y" 151,"posterior parahippocampal gyrus","Gyrus parahippocampalis, pars posterior","PPHG","Vol",146,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=151&show=y" 210592544,"entorhinal white matter","Substantia medullaris entorhinalis","entw","Vol",831957031,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=210592544&show=y" 953935429,"posterior parahippocampal white matter","Substantia medullaris parahippocampalis posterior","pphw","Vol",831957031,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=953935429&show=y" 87,"postcentral gyrus","Gyrus postcentralis","PoG","Vol",77,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=87&show=y" 88,"superior parietal lobule","Lobulus parietalis superior","SPL","Vol",77,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=88&show=y" 92,"precuneus","Precuneus","PCu","Vol",77,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=92&show=y" 90,"supramarginal gyrus","Gyrus supramarginalis","SMG","Vol",89,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=90&show=y" 91,"angular gyrus","Gyrus angularis","AnG","Vol",89,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=91&show=y" -1838638796,"supramarginal white matter","Substantia medullaris supramarginalis","smw","Vol",1506581130,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1838638796&show=y" -80092279,"superior parietal white matter","Substantia medullaris parietalis superior","spw","Vol",1506581130,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-80092279&show=y" 1108401838,"postcentral white matter","Substantia medullaris postcentralis","pow","Vol",1506581130,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1108401838&show=y" 1292180074,"precuneate white matter","Substantia medullaris precuneatus","pcuw","Vol",1506581130,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1292180074&show=y" 2035150043,"angular white matter","Substantia medullaris angularis","anw","Vol",1506581130,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=2035150043&show=y" 396,"lateral mammillary nucleus","Nucleus corporis mamillaris lateralis","LM","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=396&show=y" 400,"supramammillary nucleus","Nucleus supramamillaris","SuM","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=400&show=y" 401,"premammillary nucleus","Nucleus premamillaris","PMm","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=401&show=y" 402,"posterior periventricular nucleus","Nucleus periventricularis posterior","PPe","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=402&show=y" 403,"posterior nucleus of hypothalamus","Nucleus hypothalamicus posterior","PH","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=403&show=y" 404,"supramammillary commissure","Commissura supramamillaris","sumx","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=404&show=y" 405,"mammillary princeps fasciculus","Fasciculus mamillaris princeps","mpr","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=405&show=y" 406,"mammillotegmental fasciculus","Fasciculus mamillotegmentalis","mtg","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=406&show=y" 407,"mammillothalamic tract of hypothalamus","Fasciculus mamillothalamicus (hypothalami)","mthh","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=407&show=y" 408,"mammillary peduncle","Pedunculus corporis mamillaris","mpe","Vol",394,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=408&show=y" 398,"medial part of medial mammillary nucleus","Nucleus corporis mamillaris medialis, pars mediali","MMM","Vol",397,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=398&show=y" 399,"lateral part of medial mammillary nucleus","Nucleus corporis mamillaris medialis, pars lateral","MML","Vol",397,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=399&show=y" 344,"limitans nucleus","Nucleus limitans","Lim","Vol",343,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=344&show=y" 345,"posterior nucleus of thalamus","Nucleus posterior thalami","PTh","Vol",343,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=345&show=y" 346,"suprageniculate nucleus","Nucleus suprageniculatus","SG","Vol",343,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=346&show=y" 347,"submedial nucleus","Nucleus submedius","SM","Vol",343,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=347&show=y" 242,"dorsal septal nucleus","Nucleus dorsalis septi","DS","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=242&show=y" 243,"lateral septal nucleus","Nucleus lateralis septi","LS","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=243&show=y" 244,"medial septal nucleus","Nucleus medialis septi","MS","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=244&show=y" 245,"triangular septal nucleus","Nucleus triangularis septi","TS","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=245&show=y" 246,"septofimbrial nucleus","Nucleus septalis fimbrialis","SFi","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=246&show=y" 247,"nucleus of diagonal band","Nucleus fasciculi diagonalis","DB","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=247&show=y" 248,"nucleus of anterior commissure","Nucleus commissurae anterioris","AC","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=248&show=y" 249,"nucleus of stria terminalis","Nucleus striae terminalis","StT","Vol",241,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=249&show=y" 239,"cave of septum pellucidum","Cavum septi pellucidi","CSP","Vol",238,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=239&show=y" 240,"lamina of septum pellucidum","Lamina septi pellucidi","lsp","Vol",238,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=240&show=y" 212,"putamen","Putamen","Pu","Vol",207,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=212&show=y" 209,"head of caudate nucleus","Caput (caudatus)","HCd","Vol",208,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=209&show=y" 210,"body of caudate nucleus","Corpus (caudatus)","BCd","Vol",208,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=210&show=y" 211,"tail of caudate nucleus","Cauda (caudatus)","TCd","Vol",208,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=211&show=y" 118,"superior temporal gyrus","Gyrus temporalis superior","STG","Vol",107,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=118&show=y" 119,"middle temporal gyrus","Gyrus temporalis medius","MTG","Vol",107,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=119&show=y" 120,"inferior temporal gyrus","Gyrus temporalis inferior","ITG","Vol",107,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=120&show=y" 121,"fusiform gyrus","Gyrus fusiformis","FuG","Vol",107,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=121&show=y" 116,"anterior transverse temporal gyrus (H)","Gyrus temporalis transversus anterior (H)","ATTG","Vol",107,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=116&show=y" 117,"posterior transverse temporal gyrus (H)","Gyrus temporalis transversus posterior (H)","PTTG","Vol",107,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=117&show=y" -1497723952,"inferior temporal white matter","Substantia medullaris temporalis inferior","itw","Vol",1780216775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-1497723952&show=y" -659272139,"superior temporal white matter","Substantia medullaris temporalis superior","stw","Vol",1780216775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-659272139&show=y" -314374533,"middle temporal white matter","Substantia medullaris temporalis medius","mtw","Vol",1780216775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=-314374533&show=y" 63505126,"fusiform white matter","Substantia medullaris fusiformis","fuw","Vol",1780216775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=63505126&show=y" 350,"external medullary lamina","Lamina medullaris externa","eml","Vol",349,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=350&show=y" 351,"internal medullary lamina","Lamina medullaris interna","iml","Vol",349,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=351&show=y" 352,"anterior thalamic peduncle","Pedunculus rostralis thalami","atp","Vol",349,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=352&show=y" 353,"superior thalamic peduncle","Pedunculus thalami superior","sthp","Vol",349,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=353&show=y" 354,"inferior thalamic peduncle","Pedunculus thalami inferior","itp","Vol",349,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=354&show=y" 355,"posterior thalamic peduncle","Pedunculus ventrocaudalis thalami","ptp","Vol",349,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=355&show=y" 356,"mammillothalamic tract of thalamus","Fasciculus mamillothalamicus (thalami)","mthth","Vol",349,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=356&show=y" 318,"parvicellular part of ventral anterior nucleus","Nucleus ventralis anterior, pars parvocellularis","VAPC","Vol",317,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=318&show=y" 319,"magnocellular part of ventral anterior nucleus","Nucleus ventralis anterior, pars magnocellularis","VAMC","Vol",317,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=319&show=y" 321,"oral part of ventral lateral nucleus","Nucleus ventralis lateralis, pars oralis","VLO","Vol",320,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=321&show=y" 322,"caudal part of ventral lateral nucleus","Nucleus ventralis lateralis, pars caudalis","VLC","Vol",320,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=322&show=y" 323,"medial part of ventral lateral nucleus","Nucleus ventralis lateralis, pars medialis","VLM","Vol",320,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=323&show=y" 324,"pars postrema of ventral lateral nucleus","Nucleus ventralis lateralis, pars postrema","VLP","Vol",320,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=324&show=y" 325,"area X","Area X","X","Vol",320,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=325&show=y" 333,"ventral posteroinferior nucleus","Nucleus ventralis posterior inferior","VPI","Vol",326,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=333&show=y" 328,"oral part of ventral posterolateral nucleus","Nucleus ventralis posterolateralis, pars oralis","VPLO","Vol",327,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=328&show=y" 329,"caudal part of ventral posterolateral nucleus","Nucleus ventralis posterolateralis, pars caudalis","VPLC","Vol",327,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=329&show=y" 331,"principal part of ventral posteromedial nucleus","Nucleus ventralis posteromedialis, pars principali","VPMPr","Vol",330,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=331&show=y" 332,"parvicellular part of ventral posteromedial nucleus","Nucleus ventralis posterior medialis, pars parvocellularis","VPMPC","Vol",330,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=332&show=y" 751,"commissural nucleus of vagus nerve","Nucleus commissuralis","Cm10","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=751&show=y" 752,"dorsal motor nucleus of vagus nerve","Nucleus dorsalis nervi vagi","10","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=752&show=y" 753,"central gray substance of medulla","Substantia grisea centralis (myelencephali)","CGM","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=753&show=y" 754,"hypoglossal nucleus","Nucleus nervi hypoglossi","12","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=754&show=y" 755,"nucleus prepositus","Nucleus prepositus","PrP","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=755&show=y" 756,"nucleus intercalatus","Nucleus intercalatus","In","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=756&show=y" 757,"diffuse reticular nucleus","Nucleus reticularis diffusus","DRt","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=757&show=y" 758,"paratrigeminal nucleus","Nucleus paratrigeminalis","Pa5","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=758&show=y" 759,"peritrigeminal nucleus","Nucleus peritrigeminalis","Pe5","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=759&show=y" 760,"sublingual nucleus","Nucleus sublingualis","SLg","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=760&show=y" 761,"inferior salivatory nucleus","Nucleus salivatorius inferior","IS","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=761&show=y" 762,"nucleus ambiguus","Nucleus ambiguus","Amb","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=762&show=y" 763,"gracile nucleus","Nucleus gracilis","Gr","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=763&show=y" 764,"cuneate nucleus","Nucleus cuneatus","Cu","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=764&show=y" 765,"accessory cuneate nucleus","Nucleus cuneatus accessorius","ACu","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=765&show=y" 766,"lateral pericuneate nucleus","Nucleus pericuneatus lateralis","LPCu","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=766&show=y" 767,"medial pericuneate nucleus","Nucleus pericuneatus medialis","MPCu","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=767&show=y" 768,"caudal part of spinal trigeminal nucleus","Nucleus spinalis nervi trigemini, pars caudalis","CSp5","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=768&show=y" 769,"area postrema","Area postrema","APO","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=769&show=y" 770,"central canal","Canalis centralis","CC","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=770&show=y" 771,"pontobulbar nucleus","Nucleus pontobulbaris","PnB","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=771&show=y" 772,"arcuate nucleus of medulla","Nucleus arcuatus myelencephali","ArcM","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=772&show=y" 773,"supraspinal nucleus","Nucleus supraspinalis","SSp","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=773&show=y" 774,"medullary anterior horn","Cornu anterius medullaris","MAH","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=774&show=y" 718,"dorsal cochlear nucleus","Nucleus cochlearis dorsalis","DCo","Vol",717,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=718&show=y" 746,"principal inferior olivary nucleus","Nucleus olivaris inferior principalis","PrIO","Vol",745,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=746&show=y" 747,"dorsal accessory inferior olivary nucleus","Nucleus olivaris accessorius dorsalis","DIO","Vol",745,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=747&show=y" 748,"medial accessory inferior olivary nucleus","Nucleus olivaris accessorius medialis","MIO","Vol",745,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=748&show=y" 749,"amiculum of inferior olive","Amiculum olivare","amio","Vol",745,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=749&show=y" 750,"hilum of inferior olive","Hilum nuclei olivaris inferioris","hio","Vol",745,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=750&show=y" 335458770,"interpolar part of spinal trigeminal nucleus","Nucleus spinalis nervi trigemini, pars interpolaris","ISp5","Vol",695,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=335458770&show=y" 601,"vestibulocochlear nerve fibers","Fibrae nervi statoacustici","8nf","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=601&show=y" 776,"juxtarestiform body","Corpus juxtarestiforme","jx","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=776&show=y" 777,"predorsal bundle","Fasciculus predorsalis","pd","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=777&show=y" 778,"inferior cerebellar peduncle","Pedunculus cerebellaris inferior","icp","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=778&show=y" 779,"dorsolateral fasciculus of medulla","Fasciculus dorsolateralis","dfm","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=779&show=y" 780,"dorsal longitudinal fasciculus of medulla","Fasciculus longitudinalis dorsalis (myelencephali)","dlfm","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=780&show=y" 781,"medial longitudinal fasciculus of medulla","Fasciculus longitudinalis medialis (myelencephali)","mlfm","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=781&show=y" 782,"solitary tract","Tractus solitarius","sol","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=782&show=y" 783,"tectospinal tract","Tractus tectospinalis","ts","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=783&show=y" 784,"medial lemniscus of medulla","Lemniscus medialis (myelencephali)","mlm","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=784&show=y" 785,"decussation of medial lemniscus","Decussatio lemniscorum medialium","mlx","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=785&show=y" 786,"cuneate fasciculus of medulla","Fasciculus cuneatus (myelencephali)","cu","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=786&show=y" 787,"gracile fasciculus of medulla","Fasciculus gracilis (myelencephali)","gr","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=787&show=y" 788,"spinal trigeminal tract of medulla","Tractus spinalis nervi trigemini (myelencephali)","sp5m","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=788&show=y" 789,"accessory nerve fibers","Fibrae nervi accessorius","11nf","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=789&show=y" 790,"glossopharyngeal nerve fibers","Fibrae nervi glossopharyngei","9nf","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=790&show=y" 791,"vagal nerve fibers","Fibrae nervi vagi","10nf","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=791&show=y" 792,"internal arcuate fibers","Fibrae arcuatae internae","ia","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=792&show=y" 793,"dorsal external arcuate fibers","Fibrae arcuatae externae dorsales","dea","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=793&show=y" 794,"ventral external arcuate fibers","Fibrae arcuatae externae ventrales","vea","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=794&show=y" 795,"hypoglossal nerve fibers","Fibrae nervi hypoglossi","12nf","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=795&show=y" 796,"pyramidal decussation","Decussatio pyramidum","pyx","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=796&show=y" 797,"pyramidal tract","Tractus pyramidalis","py","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=797&show=y" 798,"lateral corticospinal tract","Tractus corticospinalis lateralis","lcsp","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=798&show=y" 799,"ventral corticospinal tract","Tractus corticospinalis ventralis","vcsp","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=799&show=y" 800,"cuneocerebellar tract","Tractus cuneocerebelli","ccb","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=800&show=y" 801,"olivocerebellar tract","Tractus olivocerebellaris","oc","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=801&show=y" 802,"reticulospinal tract","Tractus reticulospinalis","rts","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=802&show=y" 803,"rubrospinal tract","Tractus rubrospinalis","rs","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=803&show=y" 804,"posterior spinocerebellar tract","Tractus spinocerebellaris posterior","psc","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=804&show=y" 805,"anterior spinocerebellar tract","Tractus spinocerebellaris anterior","asc","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=805&show=y" 806,"spino-olivary tract","Tractus spino-olivaris","spo","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=806&show=y" 807,"spinothalamic tract of medulla","Tractus spinothalamicus (myelencephali)","stm","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=807&show=y" 808,"tectobulbar tract","Tractus tectobulbaris","tb","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=808&show=y" 809,"vestibulospinal tract","Tractus vestibulospinalis","vs","Vol",775,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=809&show=y" 736,"nucleus raphe magnus","Nucleus raphe magnus","RMg","Vol",735,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=736&show=y" 737,"nucleus raphe obscurus","Nucleus raphe obscurus","ROb","Vol",735,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=737&show=y" 738,"nucleus raphe pallidus","Nucleus raphe pallidus","RPa","Vol",735,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=738&show=y" 740,"dorsolateral subnucleus of solitary tract","Subnucleus dorsolateralis","DLSol","Vol",739,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=740&show=y" 741,"dorsomedial subnucleus of solitary tract","Subnucleus dorsomedialis","DMSol","Vol",739,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=741&show=y" 742,"medial subnucleus of solitary tract","Subnucleus medialis","MSol","Vol",739,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=742&show=y" 743,"parvicellular subnucleus of solitary tract","Subnucleus parvicellularis","PSol","Vol",739,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=743&show=y" 744,"ventrolateral subnucleus of solitary tract","Subnucleus ventrolateralis","VLSol","Vol",739,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=744&show=y" 712,"superior vestibular nucleus","Nucleus vestibularis superior","SuVe","Vol",711,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=712&show=y" 713,"lateral vestibular nucleus","Nucleus vestibularis lateralis","LVe","Vol",711,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=713&show=y" 714,"medial vestibular nucleus","Nucleus vestibularis medialis","MVe","Vol",711,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=714&show=y" 715,"inferior vestibular nucleus","Nucleus vestibularis inferior","IVe","Vol",711,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=715&show=y" 716,"interstitial nucleus of vestibular nerve","Nucleus vestibularis interstitialis","ISVe","Vol",711,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=716&show=y" 613,"pontine nuclei","Nuclei pontis","Pn","Vol",612,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=613&show=y" 614,"longitudinal pontine fibers","Fibrae pontis longitudinales","lp","Vol",612,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=614&show=y" 615,"transverse pontine fibers","Fibrae pontis transversae","tpf","Vol",612,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=615&show=y" 616,"middle cerebellar peduncle","Pedunculus cerebellaris medius","mcp","Vol",612,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=616&show=y" 727,"gigantocellular nucleus","Nucleus reticularis gigantocellularis","Gi","Vol",726,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=727&show=y" 728,"lateral paragigantocellular nucleus","Nucleus paragigantocellularis lateralis","LPGi","Vol",726,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=728&show=y" 729,"dorsal paragigantocellular nucleus","Nucleus paragigantocellularis dorsalis","DPGi","Vol",726,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=729&show=y" 730,"ventral reticular nucleus","Nucleus reticularis ventralis","VRt","Vol",726,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=730&show=y" 677,"flocculus","Flocculus","Fl","Vol",676,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=677&show=y" 678,"nodulus","Nodulus","Nd","Vol",676,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=678&show=y" 651,"anterior quadrangular lobule","Lobulus quadrangularis anterior","AQL","Vol",650,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=651&show=y" 652,"alar central lobule","Ala lobuli centralis","ACL","Vol",650,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=652&show=y" 662,"simple lobule","Lobulus simplex","SL","Vol",661,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=662&show=y" 666,"gracile lobule","Lobulus gracilis","GrL","Vol",661,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=666&show=y" 667,"biventer lobule","Lobulus biventer","BvL","Vol",661,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=667&show=y" 668,"cerebellar tonsil","Tonsilla cerebelli","CbT","Vol",661,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=668&show=y" 669,"paraflocculus","Paraflocculus","PFl","Vol",661,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=669&show=y" 654,"lingula","Lingula","Lg","Vol",653,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=654&show=y" 655,"central lobule","Lobulus centralis","CLb","Vol",653,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=655&show=y" 656,"culmen","Culmen","Cul","Vol",653,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=656&show=y" 671,"declive","Declive","Dec","Vol",670,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=671&show=y" 672,"folium","Folium vermis","Fol","Vol",670,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=672&show=y" 673,"tuber of vermis","Tuber vermis","TV","Vol",670,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=673&show=y" 674,"pyramis of vermis","Pyramis vermis","PyV","Vol",670,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=674&show=y" 675,"uvula","Uvula vermis","Uv","Vol",670,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=675&show=y" 664,"superior semilunar lobule","Lobulus semilunaris superior","SSL","Vol",663,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=664&show=y" 665,"inferior semilunar lobule","Lobulus semilunaris inferior","ISL","Vol",663,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=665&show=y" 689,"arbor vitae","Arbor vitae","abv","Vol",688,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=689&show=y" 690,"medullary body","Corpus medullare","mdb","Vol",688,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=690&show=y" 691,"peduncle of flocculus","Pedunculus flocculi","pfl","Vol",688,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=691&show=y" 692,"superior medullary lamina","Lamina medullaris superior","sml","Vol",688,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=692&show=y" 693,"inferior medullary lamina","Lamina medullaris inferior","inml","Vol",688,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=693&show=y" 694,"inferior medullary velum","Velum medullare inferius","imv","Vol",688,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=694&show=y" 685,"emboliform nucleus","Nucleus emboliformis","Emb","Vol",679,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=685&show=y" 686,"globose nucleus","Nucleus globosus","Glo","Vol",679,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=686&show=y" 687,"fastigial nucleus","Nucleus fastigii","Fas","Vol",679,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=687&show=y" 681,"neodentate part of dentate nucleus","Pars neodentata","NDt","Vol",680,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=681&show=y" 682,"paleodentate part of dentate nucleus","Pars paleodentata","PDt","Vol",680,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=682&show=y" 683,"amiculum of dentate nucleus","Amiculum nuclei dentati","amdt","Vol",680,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=683&show=y" 684,"hilum of dentate nucleus","Hilum nuclei dentati","hdt","Vol",680,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=684&show=y" 635,"choroid plexus of fourth ventricle","Plexus choroidea (ventriculi quarti)","cp4v","Vol",617,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=635&show=y" 636,"tela choroidea of fourth ventricle","Tela choroidea (ventriculi quarti)","tc4v","Vol",617,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=636&show=y" 637,"lateral aperture of fourth ventricle","Apertura lateralis ventriculi quarti","LA4V","Vol",617,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=637&show=y" 638,"median aperture of fourth ventricle","Apertura mediana ventriculi quarti","MA4V","Vol",617,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=638&show=y" 639,"lateral recess of fourth ventricle","Recessus lateralis","LR4V","Vol",617,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=639&show=y" 724,"lateral reticular nucleus","Nucleus reticularis lateralis","LRt","Vol",723,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=724&show=y" 725,"parvicellular reticular nucleus","Nucleus reticularis parvocellularis","PCRt","Vol",723,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=725&show=y" 732,"dorsal paramedian reticular nucleus","Nucleus paramedianus dorsalis","DPRt","Vol",731,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=732&show=y" 733,"accessory paramedian reticular nucleus","Nucleus paramedianus accessorius","APRt","Vol",731,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=733&show=y" 734,"ventral paramedian reticular nucleus","Nucleus paramedianus ventralis","VPRt","Vol",731,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=734&show=y" 551,"motor nucleus of trigeminal nerve","Nucleus motorius nervi trigemini","Mo5","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=551&show=y" 552,"principal sensory nucleus of trigeminal nerve","Nucleus principalis nervi trigemini","Pr5","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=552&show=y" 578,"locus ceruleus","Locus coeruleus","LC","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=578&show=y" 579,"nucleus subceruleus","Nucleus subceruleus","SubC","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=579&show=y" 580,"abducens nucleus","Nucleus nervi abducentis","6","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=580&show=y" 581,"facial motor nucleus","Nucleus nervi facialis","7","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=581&show=y" 582,"medial parabrachial nucleus","Nucleus parabrachialis medialis","MPB","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=582&show=y" 583,"lateral parabrachial nucleus","Nucleus parabrachialis lateralis","LPB","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=583&show=y" 584,"pontine raphe nucleus","Nucleus raphe pontis","RPn","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=584&show=y" 585,"superior salivatory nucleus","Nucleus salivatorius superior","SuS","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=585&show=y" 586,"dorsal nucleus of lateral lemniscus","Nucleus lemnisci lateralis, pars dorsalis","DLL","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=586&show=y" 587,"ventral nucleus of lateral lemniscus","Nucleus lemnisci lateralis, pars ventralis","VLL","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=587&show=y" 588,"superior medullary velum","Velum medullare superius","smv","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=588&show=y" 589,"trapezoid body","Corpus trapezoideum","tz","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=589&show=y" 590,"decussation of trochlear nerve","Decussatio trochlearis","4x","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=590&show=y" 592,"uncinate fasciculus of pons","Fasciculus uncinatus (pontis)","unc","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=592&show=y" 593,"abducens nerve fibers","Fibrae nervi abducentis","6nf","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=593&show=y" 594,"dorsal longitudinal fasciculus of pons","Fasciculus longitudinalis dorsalis (pontis)","dlfp","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=594&show=y" 595,"medial longitudinal fasciculus of pons","Fasciculus longitudinalis medialis (pontis)","mlfp","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=595&show=y" 596,"central tegmental tract of pons","Tractus tegmentalis centralis (pontis)","ctgp","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=596&show=y" 598,"dorsal acoustic stria","Striae acusticae dorsalis","das","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=598&show=y" 599,"intermediate acoustic stria","Striae acusticae intermedius","ias","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=599&show=y" 600,"ventral acoustic stria","Striae acusticae ventralis","vas","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=600&show=y" 602,"dorsal trigeminal tract","Tractus trigeminalis dorsalis","d5","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=602&show=y" 603,"trigeminal nerve fibers","Fibrae nervi trigemini","5nf","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=603&show=y" 604,"motor root of trigeminal nerve","Nervus trigeminus, radix motoria","mo5","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=604&show=y" 605,"lateral lemniscus","Lemniscus lateralis","ll","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=605&show=y" 606,"medial lemniscus of pons","Lemniscus medialis (pontis)","mlp","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=606&show=y" 607,"spinothalamic tract of pons","Tractus spinothalamicus (pontis)","stp","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=607&show=y" 608,"tectopontine tract","Tractus tectopontinus","tp","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=608&show=y" 609,"ventral trigeminal tract","Tractus trigeminalis ventralis","v5","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=609&show=y" 610,"spinal trigeminal tract of pons","Tractus spinalis nervi trigemini (pontis)","sp5p","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=610&show=y" 611,"vestibulocerebellar tract","Tractus vestibulocerebelli","vcb","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=611&show=y" 1007150190,"superior cerebellar peduncle of pons","Pedunculus cerebellaris superior (pontis)","scpp","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1007150190&show=y" 1015268157,"oral part of spinal trigeminal nucleus","Nucleus spinalis nervi trigemini, pars oralis","OSp5","Vol",548,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1015268157&show=y" 575,"ascending fibers of facial nerve","Fibrae ascendens nervi facialis","asc7","Vol",574,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=575&show=y" 576,"internal genu of facial nerve","Genu nervi facialis","g7","Vol",574,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=576&show=y" 577,"descending fibers of facial nerve","Fibrae descendens nervi facialis","d7","Vol",574,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=577&show=y" 557,"superior central nucleus","Nucleus centralis superior","SuC","Vol",556,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=557&show=y" 558,"inferior central nucleus","Nucleus centralis inferior","ICe","Vol",556,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=558&show=y" 559,"nucleus of medial eminence","Nucleus eminentiae teretis","MeE","Vol",556,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=559&show=y" 560,"oral pontine reticular nucleus","Nucleus reticularis pontis oralis","PnO","Vol",556,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=560&show=y" 561,"caudal pontine reticular nucleus","Nucleus reticularis pontis caudalis","PnC","Vol",556,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=561&show=y" 562,"central gray substance of pons","Substantia grisea centralis (pontis)","CGPn","Vol",556,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=562&show=y" 563,"reticulotegmental nucleus","Nucleus reticularis tegmenti pontis","RtTg","Vol",556,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=563&show=y" 568,"preolivary nucleus","Nucleus preolivaris","PrO","Vol",564,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=568&show=y" 569,"periolivary nucleus","Nucleus periolivaris","PeO","Vol",564,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=569&show=y" 570,"retro-olivary cell group","Nucleus retro-olivaris","RO","Vol",564,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=570&show=y" 571,"trapezoid nuclei","Nucleus corporis trapezoidei","Tz","Vol",564,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=571&show=y" 572,"olivocochlear bundle","Tractus olivocochlearis","ocb","Vol",564,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=572&show=y" 573,"peduncle of superior olive","Pedunculus olivae superioris","pso","Vol",564,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=573&show=y" 566,"lateral superior olivary nucleus","Nucleus olivaris superior lateralis","LSO","Vol",565,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=566&show=y" 567,"medial superior olivary nucleus","Nucleus olivaris superior medialis","MSO","Vol",565,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=567&show=y" 720,"anteroventral cochlear nucleus","Nucleus cochlearis anteroventralis","AVCo","Vol",719,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=720&show=y" 721,"posteroventral cochlear nucleus","Nucleus cochlearis posteroventralis","PVCo","Vol",719,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=721&show=y" 530,"cerebral crus","Crus cerebri","ccr","Vol",478,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=530&show=y" 473,"parabigeminal nucleus","Nucleus parabigeminalis","PBG","Vol",448,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=473&show=y" 474,"subcommissural organ","Organum subcommissurale","SCO","Vol",448,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=474&show=y" 475,"posterior commissure","Commissura posterior","pc","Vol",448,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=475&show=y" 476,"corticotectal tract","Tractus corticotectalis","ctt","Vol",448,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=476&show=y" 468,"pericentral nucleus of inferior colliculus","Nucleus pericentralis (colliculi inferioris)","PCIC","Vol",467,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=468&show=y" 469,"external nucleus of inferior colliculus","Nucleus externus (colliculi inferioris)","EIC","Vol",467,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=469&show=y" 470,"central nucleus of inferior colliculus","Nucleus centralis (colliculi inferioris)","CIC","Vol",467,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=470&show=y" 471,"brachium of inferior colliculus","Brachium colliculi inferioris","bic","Vol",467,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=471&show=y" 472,"commissure of inferior colliculus","Commissura colliculorum inferiorum","cic","Vol",467,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=472&show=y" 494,"subcuneiform nucleus","Nucleus subcuneiformis","SubCn","Vol",492,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=494&show=y" 477,"trochlear nerve fibers","Fibrae nervi trochlearis","4nf","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=477&show=y" 500,"cerebral aqueduct","Aqueductus cerebri","Aq","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=500&show=y" 501,"central gray substance of midbrain","Substantia grisea centralis (mesencephali)","CGMB","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=501&show=y" 502,"nucleus of posterior commissure","Nucleus commissura posterior","PCom","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=502&show=y" 503,"dorsal raphe nucleus","Nucleus raphe dorsalis","DR","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=503&show=y" 504,"trochlear nucleus","Nucleus nervi trochlearis","4","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=504&show=y" 505,"nucleus of Darkschewitsch","Nucleus Darkschewitsch","Dk","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=505&show=y" 506,"interstitial nucleus of Cajal","Nucleus interstitialis Cajal","ICjl","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=506&show=y" 507,"rostral interstitial nucleus of medial longitudinal fasciculus","Nucleus interstitialis rostralis","RI","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=507&show=y" 508,"dorsal tegmental nucleus","Nucleus dorsalis tegmenti","DTg","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=508&show=y" 509,"ventral tegmental nucleus","Nucleus ventralis tegmenti","VTg","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=509&show=y" 510,"linear nucleus","Nucleus linearis","Li","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=510&show=y" 511,"peripeduncular nucleus","Nucleus peripeduncularis","PPd","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=511&show=y" 512,"ventral tegmental area","Area tegmentalis ventralis","VTA","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=512&show=y" 513,"interpeduncular nucleus","Nucleus interpeduncularis","IP","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=513&show=y" 514,"dorsal tegmental decussation","Decussatio dorsalis tegmenti","dtgx","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=514&show=y" 515,"ventral tegmental decussation","Decussatio ventralis tegmenti","vtgx","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=515&show=y" 516,"dorsal longitudinal fasciculus of midbrain","Fasciculus longitudinalis dorsalis (mesencephali)","dlfmb","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=516&show=y" 517,"medial longitudinal fasciculus of midbrain","Fasciculus longitudinalis medialis (mesencephali)","mlfmb","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=517&show=y" 518,"decussation of superior cerebellar peduncle","Decussatio pedunculorum cerebellarium superiorum","xscp","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=518&show=y" 519,"central tegmental tract of midbrain","Tractus tegmentalis centralis (mesencephali)","ctgmb","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=519&show=y" 520,"oculomotor nerve fibers","Fibrae nervi oculomotorii","3nf","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=520&show=y" 521,"pallidotegmental fasciculus","Fasciculus pallido-tegmentalis","ptf","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=521&show=y" 522,"lateral pes lemniscus","Pes lemniscus lateralis","lpl","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=522&show=y" 523,"medial pes lemniscus","Pes lemniscus medialis","mpl","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=523&show=y" 524,"medial lemniscus of midbrain","Lemniscus medialis (mesencephali)","mlmb","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=524&show=y" 525,"dentatothalamic tract","Tractus dentatothalamicus","dt","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=525&show=y" 526,"spinothalamic tract of midbrain","Tractus spinothalamicus (mesencephali)","stmb","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=526&show=y" 550,"mesencephalic nucleus of trigeminal nerve","Nucleus mesencephalicus nervi trigemini","Me5","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=550&show=y" 591,"mesencephalic tract of trigeminal nerve","Tractus mesencephalicus nervi trigemini","me5","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=591&show=y" 439377875,"habenulo-interpeduncular tract of midbrain","Tractus habenulo-interpeduncularis mesencephali","hipm","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=439377875&show=y" 573155162,"superior cerebellar peduncle of midbrain","Pedunculus cerebellaris superior (mesencephalon)","scpmb","Vol",482,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=573155162&show=y" 484,"dorsal oculomotor nucleus","Nucleus nervi oculomotorii, pars dorsalis","D3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=484&show=y" 485,"intermediate oculomotor nucleus","Nucleus nervi oculomotorii, pars intermedius","I3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=485&show=y" 486,"medial oculomotor nucleus","Nucleus nervi oculomotorii, pars medialis","M3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=486&show=y" 487,"ventral oculomotor nucleus","Nucleus nervi oculomotorii, pars ventralis","V3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=487&show=y" 489,"parvocellular oculomotor nucleus","Nucleus nervi oculomotorii parvocellularis","PC3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=489&show=y" 451,"nucleus of pretectal area","Nucleus area pretectalis","PTA","Vol",450,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=451&show=y" 452,"principal pretectal nucleus","Nucleus pretectalis principalis","PPt","Vol",450,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=452&show=y" 453,"nucleus of optic tract","Nucleus tractus optici","OT","Vol",450,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=453&show=y" 454,"sublentiform nucleus","Nucleus sublentiformis","SLn","Vol",450,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=454&show=y" 455,"olivary pretectal nucleus","Nucleus olivaris pretectalis","OPt","Vol",450,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=455&show=y" 528,"pars compacta","Pars compacta","SNC","Vol",527,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=528&show=y" 529,"pars reticulata","Pars reticularis","SNR","Vol",527,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=529&show=y" 457,"zonal layer of superior colliculus","Stratum zonale colliculi superioris","Zo","Vol",456,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=457&show=y" 458,"superficial gray layer of superior colliculus","Stratum cinereum","SuG","Vol",456,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=458&show=y" 459,"superficial white layer of superior colliculus","Stratum opticum","SuWh","Vol",456,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=459&show=y" 465,"brachium of superior colliculus","Brachium colliculi superioris","bsc","Vol",456,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=465&show=y" 466,"commissure of superior colliculus","Commissura colliculorum superiorum","csc","Vol",456,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=466&show=y" 493,"cuneiform nucleus","Nucleus cuneiformis","CnF","Vol",492,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=493&show=y" 495,"pedunculopontine tegmental nucleus","Nucleus tegmenti pedunculopontinus","PPTg","Vol",492,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=495&show=y" 499,"capsule of red nucleus","Capsula nuclei rubris tegmenti","cr","Vol",496,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=499&show=y" 488,"anterior median oculomotor nucleus","Nucleus nervi oculomotorii medianus anterior","AM3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=488&show=y" 490,"central oculomotor nucleus","Nucleus nervi oculomotorii centralis","C3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=490&show=y" 491,"caudal central oculomotor nucleus","Nucleus caudalis centralis oculomotorii","CC3","Vol",483,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=491&show=y" 497,"parvocellular part of red nucleus","Pars parvocellularis (ruber)","RPC","Vol",496,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=497&show=y" 498,"magnocellular part of red nucleus","Pars magnocellularis (ruber)","RMC","Vol",496,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=498&show=y" 461,"middle gray layer of superior colliculus","Stratum griseum mediale","MGr","Vol",460,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=461&show=y" 462,"middle white layer of superior colliculus","Stratum album mediale","MWh","Vol",460,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=462&show=y" 463,"deep gray layer of superior colliculus","Stratum griseum profundum","DpG","Vol",460,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=463&show=y" 464,"deep white layer of superior colliculus","Stratum album profundum","DpWh","Vol",460,"Primary","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=464&show=y" 1,"BRAIN","Encephalon","Br","Vol",1,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1&show=y" 8,"FOREBRAIN","Prosencephalon","FB","Vol",1,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=8&show=y" 445,"MIDBRAIN","Mesencephalon","MB","Vol",1,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=445&show=y" 531,"HINDBRAIN","Rhombencephalon","HB","Vol",1,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=531&show=y" 12,"TELENCEPHALON","Telencephalon","Tel","Vol",8,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=12&show=y" 271,"DIENCEPHALON","Diencephalon","DiE","Vol",8,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=271&show=y" 275,"EPITHALAMUS","Epithalamus","ETh","Vol",271,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=275&show=y" 283,"THALAMUS","Thalamus","Th","Vol",271,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=283&show=y" 358,"HYPOTHALAMUS","Hypothalamus","Hy","Vol",271,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=358&show=y" 417,"SUBTHALAMUS","Subthalamus","SbTh","Vol",271,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=417&show=y" 429,"THIRD VENTRICLE","Ventriculus tertius","3V","Vol",271,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=429&show=y" 20,"CEREBRAL CORTEX","Cortex cerebri","Cx","Vol",12,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=20&show=y" 191,"lateral ventricle","Ventriculus lateralis","LV","Vol",12,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=191&show=y" 206,"BASAL GANGLIA","Ganglia basales","BG","Vol",12,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=206&show=y" 237,"SEPTUM","Septum","Spt","Vol",12,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=237&show=y" 250,"FORNIX","Fornix","fx","Vol",12,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=250&show=y" 171,"CEREBRAL WHITE MATTER","Substantia medullaris cerebri","cw","Vol",12,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=171&show=y" 207,"STRIATUM","Striatum","Str","Vol",206,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=207&show=y" 213,"GLOBUS PALLIDUS","Globus pallidus","GP","Vol",206,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=213&show=y" 219,"AMYGDALA","Corpus amygdaloideum","Amg","Vol",206,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=219&show=y" 37,"FRONTAL LOBE","Lobus frontalis","FL","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=37&show=y" 77,"PARIETAL LOBE","Lobus parietalis","PL","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=77&show=y" 93,"INSULA","Insula","Ins","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=93&show=y" 107,"TEMPORAL LOBE","Lobus temporalis","TL","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=107&show=y" 122,"OCCIPITAL LOBE","Lobus occipitalis","OL","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=122&show=y" 141,"CINGULATE GYRUS","Gyrus cingulatus","CgG","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=141&show=y" 146,"PARAHIPPOCAMPAL GYRUS","Gyrus parahippocampalis","PHG","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=146&show=y" 152,"ARCHICORTEX","Archeocortex","ACx","Vol",20,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=152&show=y" 173,"CORPUS CALLOSUM","Corpus callosum","cc","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=173&show=y" 180,"INTERNAL CAPSULE","Capsula interna","ic","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=180&show=y" 187,"ANTERIOR COMMISSURE","Commissura anterior","ac","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=187&show=y" 264031898,"FRONTAL WHITE MATTER","Substantia medullaris lobus frontalis","fw","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=264031898&show=y" 685484116,"CINGULATE WHITE MATTER","Substantia medullaris cingulatus","cgw","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=685484116&show=y" 831957031,"PARAHIPPOCAMPAL WHITE MATTER","Substantia medullaris parahippocampalis","phw","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=831957031&show=y" 964479090,"OCCIPITAL LOBE WHITE MATTER","Substantia medullaris lobus occipitalis","olw","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=964479090&show=y" 1506581130,"PARIETAL WHITE MATTER","Substantia medullaris parietalis","pw","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1506581130&show=y" 1780216775,"TEMPORAL WHITE MATTER","Substantia medullaris temporalis","tw","Vol",171,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1780216775&show=y" 277,"HABENULA","Habenula","Hb","Vol",275,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=277&show=y" 359,"ANTERIOR HYPOTHALAMIC REGION","Regio hypothalamica anterior","AHR","Vol",358,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=359&show=y" 375,"INTERMEDIATE HYPOTHALAMIC REGION","Regio hypothalamica intermedia","IHR","Vol",358,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=375&show=y" 394,"POSTERIOR HYPOTHALAMIC REGION","Regio hypothalamica posterior","PHR","Vol",358,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=394&show=y" 409,"LATERAL HYPOTHALAMIC AREA","Area hypothalamica lateralis","LH","Vol",358,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=409&show=y" 238,"SEPTUM PELLUCIDUM","Septum pellucidum","spt","Vol",237,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=238&show=y" 241,"SEPTAL NUCLEI","Nuclei septales","SptN","Vol",237,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=241&show=y" 285,"ANTERIOR NUCLEAR GROUP","Nuclei anteriores","ANG","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=285&show=y" 289,"MIDLINE NUCLEAR GROUP","Nuclei mediani","MNG","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=289&show=y" 295,"MEDIAL DORSAL NUCLEUS","Nucleus medialis dorsalis","MD","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=295&show=y" 300,"INTRALAMINAR NUCLEAR GROUP","Nuclei intralaminares","ILG","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=300&show=y" 308,"LATERAL NUCLEAR GROUP","Nuclei laterales thalami","LNG","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=308&show=y" 316,"VENTRAL NUCLEAR GROUP","Nuclei ventrales thalami","VNG","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=316&show=y" 334,"METATHALAMUS","Metathalamus","MTh","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=334&show=y" 343,"POSTERIOR NUCLEAR COMPLEX","Nuclei posteriores thalami","PNC","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=343&show=y" 349,"THALAMIC FIBER TRACTS","Fasciculi thalami","thf","Vol",283,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=349&show=y" 220,"CORTICOMEDIAL NUCLEAR GROUP","Pars corticomedialis","CMA","Vol",219,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=220&show=y" 226,"BASOLATERAL NUCLEAR GROUP","Pars basolateralis","BL","Vol",219,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=226&show=y" 228,"BASAL AMYGDALOID NUCLEUS","Nucleus amygdalae basalis","BA","Vol",226,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=228&show=y" 360,"PREOPTIC AREA","Area preoptica","POA","Vol",359,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=360&show=y" 154,"SUPRACALLOSAL GYRUS","Gyrus supracallosus","SCG","Vol",152,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=154&show=y" 159,"HIPPOCAMPAL FORMATION","Formatio hippocampi","HiF","Vol",152,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=159&show=y" 161,"DENTATE GYRUS","Gyrus dentatus","DG","Vol",159,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=161&show=y" 164,"HIPPOCAMPUS","Hippocampus","Hi","Vol",159,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=164&show=y" 67,"INFERIOR FRONTAL GYRUS","Gyrus frontalis inferior","IFG","Vol",37,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=67&show=y" 73,"ORBITAL GYRI","Gyri orbitales","OrG","Vol",37,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=73&show=y" 962901580,"TRANSVERSE FRONTOPOLAR GYRI (H)","Gyrus frontopolaris transversus (H)","TFPG","Vol",37,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=962901580&show=y" 97,"SHORT INSULAR GYRI (H)","Gyri breves insulae (H)","SIG","Vol",93,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=97&show=y" 102,"LONG INSULAR GYRI (H)","Gyrus longus insulae (H)","LIG","Vol",93,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=102&show=y" 382,"HYPOPHYSIS","Hypophysis","HP","Vol",375,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=382&show=y" 384,"NEUROHYPOPHYSIS","Neurohypophysis","NHP","Vol",382,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=384&show=y" 390,"ADENOHYPOPHYSIS","Adenohypophysis","AHP","Vol",382,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=390&show=y" 385,"MEDIAN EMINENCE","Eminentia postinfundibularis","ME","Vol",384,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=385&show=y" 183,"POSTERIOR LIMB OF INTERNAL CAPSULE","Crus posterius capsulae internae","pic","Vol",180,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=183&show=y" 301,"ROSTRAL INTRALAMINAR NUCLEI","Nuclei intralaminares rostrales","RIL","Vol",300,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=301&show=y" 311,"PULVINAR","Pulvinar","Pul","Vol",308,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=311&show=y" 335,"LATERAL GENICULATE BODY","Corpus geniculatum laterale","LG","Vol",334,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=335&show=y" 338,"MEDIAL GENICULATE BODY","Corpus geniculatum mediale","MG","Vol",334,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=338&show=y" 89,"INFERIOR PARIETAL LOBULE","Lobulus parietalis inferior","IPL","Vol",77,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=89&show=y" 397,"MEDIAL MAMMILLARY NUCLEUS","Nucleus corporis mamillaris medialis","MM","Vol",394,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=397&show=y" 208,"CAUDATE NUCLEUS","Nucleus caudatus","Cd","Vol",207,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=208&show=y" 317,"VENTRAL ANTERIOR NUCLEUS","Nucleus ventralis anterior","VA","Vol",316,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=317&show=y" 320,"VENTRAL LATERAL NUCLEUS","Nucleus ventralis lateralis","VL","Vol",316,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=320&show=y" 326,"VENTRAL POSTERIOR NUCLEUS","Nuclei ventrales posteriores","VP","Vol",316,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=326&show=y" 327,"VENTRAL POSTEROLATERAL NUCLEUS","Nucleus ventralis posterolateralis","VPL","Vol",326,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=327&show=y" 330,"VENTRAL POSTEROMEDIAL NUCLEUS","Nucleus ventralis posteromedialis","VPM","Vol",326,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=330&show=y" 534,"METENCEPHALON","Metencephalon","Met","Vol",531,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=534&show=y" 695,"MEDULLA OBLONGATA","Myelencephalon","MO","Vol",531,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=695&show=y" 711,"VESTIBULAR NUCLEI","Nuclei vestibulares","Ve","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=711&show=y" 717,"COCHLEAR NUCLEI","Nuclei cochleares","Co","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=717&show=y" 722,"MEDULLARY RETICULAR FORMATION","Formatio reticularis myelencephali","MeRF","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=722&show=y" 735,"RAPHE NUCLEI OF MEDULLA","Nuclei raphe (myelencephali)","RaM","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=735&show=y" 739,"SOLITARY NUCLEUS","Nucleus solitarius","Sol","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=739&show=y" 745,"INFERIOR OLIVARY COMPLEX","Regio olivaris inferior","IO","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=745&show=y" 775,"MEDULLARY WHITE MATTER","Substantia alba myelencephali","mw","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=775&show=y" 538,"PONS","Pons","Pons","Vol",534,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=538&show=y" 640,"CEREBELLUM","Cerebellum","Cb","Vol",534,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=640&show=y" 644,"CEREBELLAR CORTEX","Cortex cerebelli","CbCx","Vol",640,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=644&show=y" 679,"DEEP CEREBELLAR NUCLEI","Nuclei cerebelli","DCb","Vol",640,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=679&show=y" 688,"CEREBELLAR WHITE MATTER","Substantia medullaris cerebelli","cbw","Vol",640,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=688&show=y" 719,"VENTRAL COCHLEAR NUCLEI","Nucleus cochlearis ventralis","VCo","Vol",717,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=719&show=y" 723,"LATERAL MEDULLARY RETICULAR GROUP","Nuclei laterales myelencephali","LMRt","Vol",722,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=723&show=y" 726,"CENTRAL MEDULLARY RETICULAR GROUP","Nuclei centrales myelencephali","CMRt","Vol",722,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=726&show=y" 731,"PARAMEDIAN MEDULLARY RETICULAR GROUP","Nuclei paramedianes myelencephali","PMRt","Vol",722,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=731&show=y" 548,"PONTINE TEGMENTUM","Tegmentum pontis","PTg","Vol",538,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=548&show=y" 612,"BASAL PART OF PONS","Pars basilaris pontis","Bpons","Vol",538,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=612&show=y" 617,"FOURTH VENTRICLE","Ventriculus quartus","4V","Vol",538,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=617&show=y" 647,"ANTERIOR LOBE OF CEREBELLUM","Lobus anterior cerebelli","ALCb","Vol",644,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=647&show=y" 657,"POSTERIOR LOBE OF CEREBELLUM","Lobus posterior cerebelli","PLCb","Vol",644,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=657&show=y" 676,"FLOCCULONODULAR LOBE","Lobus flocculonodularis","FNL","Vol",644,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=676&show=y" 650,"HEMISPHERE OF ANTERIOR LOBE","Hemispherium lobus anterior","HAL","Vol",647,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=650&show=y" 653,"VERMIS OF ANTERIOR LOBE","Vermis lobus anterior","VAL","Vol",647,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=653&show=y" 661,"HEMISPHERE OF POSTERIOR LOBE","Hemispherium lobus posterior","HPL","Vol",657,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=661&show=y" 670,"VERMIS OF POSTERIOR LOBE","Vermis lobus posterior","VPLb","Vol",657,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=670&show=y" 663,"ANSIFORM LOBULE","Lobulus ansiformis","An","Vol",661,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=663&show=y" 680,"DENTATE NUCLEUS","Nucleus dentatus","Dt","Vol",679,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=680&show=y" 553,"SPINAL TRIGEMINAL NUCLEUS","Nucleus spinalis nervi trigemini","Sp5","Vol",695,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=553&show=y" 556,"PONTINE RETICULAR FORMATION","Formatio reticularis pontis","PRF","Vol",548,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=556&show=y" 564,"SUPERIOR OLIVARY COMPLEX","Regio olivaris superioris","SOC","Vol",548,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=564&show=y" 574,"FACIAL NERVE FIBERS","Fibrae nervi facialis","7nf","Vol",548,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=574&show=y" 565,"SUPERIOR OLIVE","Oliva superior","SOl","Vol",564,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=565&show=y" 448,"TECTUM","Tectum mesencephali","Tec","Vol",445,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=448&show=y" 478,"CEREBRAL PEDUNCLE","Pedunculus cerebri","CP","Vol",445,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=478&show=y" 482,"MIDBRAIN TEGMENTUM","Tegmentum mesencephali","MTg","Vol",478,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=482&show=y" 527,"SUBSTANTIA NIGRA","Substantia nigra","SN","Vol",478,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=527&show=y" 450,"PRETECTAL REGION","Area pretectalis","PTec","Vol",448,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=450&show=y" 456,"SUPERIOR COLLICULUS","Colliculus superior","SC","Vol",448,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=456&show=y" 467,"INFERIOR COLLICULUS","Colliculus inferior","IC","Vol",448,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=467&show=y" 483,"OCULOMOTOR NUCLEAR COMPLEX","Nuclei nervi oculomotorii","3","Vol",482,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=483&show=y" 492,"MIDBRAIN RETICULAR FORMATION","Formatio reticularis mesencephali","MBRF","Vol",482,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=492&show=y" 496,"RED NUCLEUS","Nucleus ruber","R","Vol",482,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=496&show=y" 460,"STRATUM LEMNISCI OF SUPERIOR COLLICULUS","Stratum lemnisci","StL","Vol",456,"Super","http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=460&show=y" 2,"cerebrocerebellar fissure","Fissura cerebrocerebellaris","ccbf","Sur",1,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=2&show=y" 3,"anterior cerebellar incisure","Incisura anterior cerebelli","acbi","Sur",1,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=3&show=y" 4,"superior pontine sulcus","Sulcus superior pontis","sps","Sur",1,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=4&show=y" 5,"choroidal fissure","Fissura choroidea","chf","Sur",1,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=5&show=y" 6,"interpeduncular cistern","Cisterna interpeduncularis","icis","Sur",1,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=6&show=y" 7,"superior cistern","Cisterna superior","scis","Sur",1,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=7&show=y" 10,"cistern of lamina terminalis","Cisterna laminae terminalis","cislt","Sur",8,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=10&show=y" 11,"chiasmatic cistern","Cisterna chiasmatica","ccis","Sur",8,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=11&show=y" 272,"optic nerve","Nervus opticus","2n","Sur",271,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=272&show=y" 273,"anterior tubercle","Tuberculum anterius thalami","at","Sur",271,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=273&show=y" 274,"terminal sulcus","Sulcus terminalis","tms","Sur",271,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=274&show=y" 13,"olfactory nerve","Nervus olfactorius","1n","Sur",12,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=13&show=y" 14,"terminal nerve","Nervus terminalis","trn","Sur",12,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=14&show=y" 15,"olfactory trigone","Trigonum olfactorium","olt","Sur",12,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=15&show=y" 16,"longitudinal fissure","Fissura longitudinalis cerebri","lf","Sur",12,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=16&show=y" 17,"callosal sulcus","Sulcus corporis callosi","cas","Sur",12,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=17&show=y" 19,"posterior parolfactory sulcus","Sulcus parolfactorius posterior","ppos","Sur",12,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=19&show=y" 18,"anterior parolfactory sulcus (H)","Sulcus parolfactorius anterior (H)","aps","Sur",12,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=18&show=y" 21,"uncus","Uncus","un","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=21&show=y" 22,"rhinal sulcus","Sulcus rhinalis","rhs","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=22&show=y" 23,"hippocampal sulcus","Sulcus hippocampi","his","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=23&show=y" 24,"cingulate sulcus","Sulcus cinguli","cgs","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=24&show=y" 25,"calcarine sulcus","Sulcus calcarinus","ccs","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=25&show=y" 28,"collateral sulcus","Sulcus collateralis","cos","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=28&show=y" 29,"central sulcus","Sulcus centralis","cs","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=29&show=y" 30,"lateral sulcus","Sulcus lateralis","ls","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=30&show=y" 31,"limen of insula","Limen insulae","lmi","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=31&show=y" 32,"circular sulcus of insula","Sulcus circularis insulae","crs","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=32&show=y" 33,"parieto-occipital sulcus","Sulcus parieto-occipitalis","pos","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=33&show=y" 35,"preoccipital notch","Incisura preoccipitalis","pon","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=35&show=y" 36,"occipitotemporal sulcus","Sulcus occipitotemporalis","ots","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=36&show=y" 26,"anterior calcarine sulcus (H)","Sulcus calcarinus anterior (H)","accs","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=26&show=y" 27,"simian fossa (M)","Fossa simiarum (M)","sf","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=27&show=y" 34,"anterior parieto-occipital sulcus (M)","Sulcus parieto-occipitalis anterior (M)","apos","Sur",20,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=34&show=y" 276,"habenular trigone","Trigonum habenulae","hbt","Sur",275,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=276&show=y" 192,"calcar avis","Calcar avis","cav","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=192&show=y" 193,"collateral eminence","Eminentia collateralis","coe","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=193&show=y" 194,"parieto-occipital eminence","Eminentia parieto-occipitalis","poce","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=194&show=y" 195,"lamina affixa","Lamina affixa","lma","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=195&show=y" 196,"tenia choroidea of lateral ventricle","Tenia choroidea (ventriculi lateralis)","tnclv","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=196&show=y" 197,"tenia of fimbria","Tenia fimbria","tfb","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=197&show=y" 198,"tenia of fornix","Tenia fornicis","tfx","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=198&show=y" 199,"collateral trigone","Trigonum collaterale","clt","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=199&show=y" 1806126526,"terminal velum","Velum terminale","tv","Sur",191,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=1806126526&show=y" 284,"interthalamic adhesion","Adhesio interthalamica","itha","Sur",283,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=284&show=y" 431,"tenia of thalamus","Tenia thalami","tth","Sur",429,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=431&show=y" 432,"hypothalamic sulcus","Sulcus hypothalamicus","hys","Sur",429,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=432&show=y" 433,"habenular sulcus","Sulcus habenulae","hbs","Sur",429,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=433&show=y" 160,"fimbriodentate fissure","Fissura fimbrio-dentata","fdf","Sur",159,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=160&show=y" 142,"intracingulate sulcus","Sulcus intracinguli","icgs","Sur",141,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=142&show=y" 38,"frontal pole","Polus frontalis","frp","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=38&show=y" 39,"frontal operculum","Operculum frontale","fro","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=39&show=y" 40,"orbital operculum","Operculum orbitale","oro","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=40&show=y" 41,"precentral operculum","Operculum precentrale","pro","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=41&show=y" 52,"superior precentral sulcus","Sulcus precentralis superior","sprs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=52&show=y" 54,"anterior subcentral sulcus","Sulcus subcentralis anterior","ascs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=54&show=y" 59,"fronto-orbital sulcus","Sulcus fronto-orbitalis","fros","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=59&show=y" 60,"olfactory sulcus","Sulcus olfactorius","olfs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=60&show=y" 64,"medial orbital sulcus","Sulcus orbitalis medialis","mos","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=64&show=y" 42,"superior frontal sulcus (H)","Sulcus frontalis superior (H)","sfrs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=42&show=y" 43,"middle frontal sulcus (H)","Sulcus frontalis medius (H)","mfs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=43&show=y" 44,"inferior frontal sulcus (H)","Sulcus frontalis inferior (H)","ifrs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=44&show=y" 48,"diagonal sulcus (H)","Sulcus diagonalis (H)","dias","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=48&show=y" 49,"anterior ascending limb of lateral sulcus (H)","Ramus anterior ascendens fissurae lateralis (H)","aals","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=49&show=y" 50,"anterior horizontal limb of lateral sulcus (H)","Ramus anterior horizontalis sulcus lateralis (H)","ahls","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=50&show=y" 51,"paracentral sulcus (H)","Sulcus paracentralis (H)","pcs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=51&show=y" 53,"inferior precentral sulcus (H)","Sulcus precentralis inferior (H)","iprs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=53&show=y" 56,"superior rostral sulcus (H)","Sulcus rostralis superior (H)","sros","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=56&show=y" 57,"inferior rostral sulcus (H)","Sulcus rostralis inferior (H)","iros","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=57&show=y" 61,"orbital sulcus (H)","Sulcus orbitalis (H)","orbs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=61&show=y" 62,"transverse orbital sulcus (H)","Sulcus orbitalis transversus (H)","tos","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=62&show=y" 45,"superior ramus of arcuate sulcus (M)","Ramus superior sulcus arcuatus (M)","sras","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=45&show=y" 46,"inferior ramus of arcuate sulcus (M)","Ramus inferior sulcus arcuatus (M)","iras","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=46&show=y" 47,"principal sulcus (M)","Sulcus principalis (M)","prs","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=47&show=y" 58,"rostral sulcus (M)","Sulcus rostralis (M)","ros","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=58&show=y" 63,"lateral orbital sulcus","Sulcus orbitalis lateralis","los","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=63&show=y" 957388385,"spur of arcuate sulcus (M)","Calcar sulci arcuati (M)","sas","Sur",37,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=957388385&show=y" 94,"central insular sulcus","Sulcus centralis insulae","cis","Sur",93,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=94&show=y" 95,"longitudinal sulcus of insula (H)","Sulcus longitudinalis insulae (H)","lsi","Sur",93,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=95&show=y" 96,"posterior marginal sulcus (H)","Sulcus marginalis posterior (H)","pms","Sur",93,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=96&show=y" 376,"tuber cinereum","Tuber cinereum","tbcn","Sur",375,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=376&show=y" 383,"lateral eminence of hypophysis","Eminentia lateralis (hypophysis)","lehp","Sur",382,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=383&show=y" 123,"occipital pole","Polus occipitalis","ocp","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=123&show=y" 132,"lunate sulcus","Sulcus lunatus","lus","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=132&show=y" 124,"anterior occipital sulcus (H)","Sulcus occipitalis anterior (H)","aocs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=124&show=y" 125,"lateral occipital sulcus (H)","Sulcus occipitalis lateralis (H)","locs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=125&show=y" 127,"transverse occipital sulcus (H)","Sulcus occipitalis transversus (H)","tocs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=127&show=y" 131,"posterior calcarine sulcus (H)","Sulcus calcarinus posterior (H)","pccs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=131&show=y" 133,"intralingual sulcus (H)","Sulcus intralingualis (H)","ils","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=133&show=y" 126,"inferior occipital sulcus (M)","Sulcus occipitalis inferior (M)","iocs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=126&show=y" 128,"ectocalcarine sulcus (M)","Sulcus ectocalcarinus (M)","ecs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=128&show=y" 129,"superior calcarine sulcus (M)","Sulcus calcarinus superior (M)","sccs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=129&show=y" 130,"inferior calcarine sulcus (M)","Sulcus calcarinus inferior (M)","iccs","Sur",122,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=130&show=y" 78,"parietal operculum","Operculum parietale","pao","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=78&show=y" 79,"intraparietal sulcus","Sulcus intraparietalis","itps","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=79&show=y" 81,"postcentral sulcus","Sulcus postcentralis","pocs","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=81&show=y" 82,"superior postcentral sulcus","Sulcus postcentralis superior","spcs","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=82&show=y" 83,"inferior postcentral sulcus","Sulcus postcentralis inferior","ipcs","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=83&show=y" 84,"subparietal sulcus","Sulcus subparietalis","sbps","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=84&show=y" 85,"posterior subcentral sulcus","Sulcus subcentralis posterior","pscs","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=85&show=y" 80,"marginal sulcus (H)","Ramus marginalis sulci cingulati (H)","ms","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=80&show=y" 86,"posterior ascending limb of lateral sulcus (H)","Ramus posterior ascendens fissurae lateralis (H)","pals","Sur",77,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=86&show=y" 395,"mammillary body","Corpus mamillaris","mmb","Sur",394,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=395&show=y" 108,"temporal pole","Polus temporalis","tmp","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=108&show=y" 109,"temporal operculum","Operculum temporale","top","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=109&show=y" 111,"superior temporal sulcus","Sulcus temporalis superior","sts","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=111&show=y" 110,"transverse temporal sulcus (H)","Sulci temporales transversi (H)","tts","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=110&show=y" 112,"inferior temporal sulcus (H)","Sulcus temporalis inferior (H)","its","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=112&show=y" 113,"middle temporal sulcus (M)","Sulcus temporalis medius (M)","mts","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=113&show=y" 114,"anterior middle temporal sulcus (M)","Sulcus temporalis medius anterior (M)","amts","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=114&show=y" 115,"posterior middle temporal sulcus (M)","Sulcus temporalis medius posterior (M)","pmts","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=115&show=y" 955732021,"lateral inferior limiting sulcus","Sulcus limitans inferior lateralis","lils","Sur",107,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=955732021&show=y" 532,"inferior pontine sulcus","Sulcus inferior pontis","ips","Sur",531,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=532&show=y" 533,"cerebellomedullary cistern","Cisterna magna","cmcis","Sur",531,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=533&show=y" 696,"inferior olive","Oliva","ifol","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=696&show=y" 697,"anterior median fissure","Fissura mediana anterior","amf","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=697&show=y" 698,"glossopharyngeal nerve","Nervus glossopharyngeus","9n","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=698&show=y" 699,"vagus nerve","Nervus vagus","10n","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=699&show=y" 700,"cranial part of accessory nerve","Radices craniales nervi accessorii","c11n","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=700&show=y" 701,"hypoglossal nerve","Nervus hypoglossus","12n","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=701&show=y" 702,"pyramid of medulla","Pyramis (medullae oblongatae)","pym","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=702&show=y" 703,"dorsolateral sulcus","Sulcus dorsolateralis","dls","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=703&show=y" 704,"dorsal intermediate sulcus","Sulcus intermedius dorsalis","dis","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=704&show=y" 705,"dorsal median sulcus","Sulcus medianus dorsalis","dms","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=705&show=y" 706,"retro-olivary sulcus","Sulcus retro-olivaris","rols","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=706&show=y" 707,"ventrolateral sulcus","Sulcus ventrolateralis","vls","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=707&show=y" 708,"trigeminal tubercle","Tuberculum trigeminale","5t","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=708&show=y" 709,"cuneate tubercle","Tuberculum cuneatum","cut","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=709&show=y" 710,"gracilis tubercle","Tuberculum gracile","grt","Sur",695,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=710&show=y" 535,"cerebellopontine angle","Angulus cerebellopontinus","cbpa","Sur",534,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=535&show=y" 536,"lemniscal trigone","Trigonum lemnisci","lmt","Sur",534,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=536&show=y" 537,"pontocerebellar trigone","Trigonum pontocerebellare","pcbt","Sur",534,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=537&show=y" 641,"secondary fissure","Fissura secunda","scf","Sur",640,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=641&show=y" 642,"posterior cerebellar incisure","Incisura posterior cerebelli","pcbi","Sur",640,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=642&show=y" 643,"vallecula cerebelli","Vallecula cerebelli","vlcb","Sur",640,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=643&show=y" 539,"foramen cecum anterior","Foramen cecum anterior","fca","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=539&show=y" 540,"trigeminal nerve","Nervus trigeminus","5n","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=540&show=y" 541,"abducens nerve","Nervus abducens","6n","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=541&show=y" 542,"facial nerve","Nervus facialis","7n","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=542&show=y" 543,"intermediate nerve","Nervus intermedius","imn","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=543&show=y" 544,"vestibulocochlear nerve","Nervus vestibulocochlearis","8n","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=544&show=y" 545,"basilar sulcus","Sulcus basilaris","bss","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=545&show=y" 546,"foramen cecum posterior","Foramen cecum posterior","fcp","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=546&show=y" 547,"pontine cistern","Cisterna pontis","pcis","Sur",538,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=547&show=y" 645,"primary fissure of cerebellum","Fissura prima","pfcb","Sur",644,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=645&show=y" 646,"posterolateral fissure","Fissura posterolateralis","plf","Sur",644,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=646&show=y" 648,"precentral fissure of cerebellum","Fissura precentralis cerebelli","prfcb","Sur",647,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=648&show=y" 649,"postcentral fissure of cerebellum","Fissura postcentralis cerebelli","pofcb","Sur",647,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=649&show=y" 658,"horizontal fissure","Fissura horizontalis","hzf","Sur",657,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=658&show=y" 659,"posterior superior fissure","Fissura superior posterior","psf","Sur",657,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=659&show=y" 660,"prepyramidal fissure","Fissura prepyramidalis","ppyf","Sur",657,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=660&show=y" 618,"fastigium","Fastigium","ft","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=618&show=y" 619,"vestibular area","Area vestibularis","vba","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=619&show=y" 620,"medial eminence of fourth ventricle","Eminentia medialis","me4v","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=620&show=y" 621,"facial colliculus","Colliculus facialis","fc","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=621&show=y" 622,"superior fovea","Fovea superior","sfv","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=622&show=y" 623,"inferior fovea","Fovea inferior","ifv","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=623&show=y" 624,"funiculus separans","Funiculus separans","fsp","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=624&show=y" 625,"striae medullares","Striae medullares","strm","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=625&show=y" 626,"sulcus limitans","Sulcus limitans","slm","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=626&show=y" 627,"median sulcus","Sulcus medianus","mds","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=627&show=y" 628,"rhomboid fossa","Fossa rhomboidea","rhf","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=628&show=y" 629,"tenia of fourth ventricle","Tenia (ventriculi quarti)","t4v","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=629&show=y" 630,"acoustic tubercle","Tuberculum acusticum","act","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=630&show=y" 631,"vagal trigone","Trigonum nervi vagi","10t","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=631&show=y" 632,"hypoglossal trigone","Trigonum nervi hypoglossi","12t","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=632&show=y" 633,"obex","Obex","ob","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=633&show=y" 634,"calamus scriptorius","Calamus scriptorius","clst","Sur",617,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=634&show=y" 446,"oculomotor sulcus","Sulcus oculomotorius","ocs","Sur",445,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=446&show=y" 447,"dorsolateral fissure of midbrain","Fissura dorsolateralis mesencephali","dfmb","Sur",445,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=447&show=y" 479,"oculomotor nerve","Nervus oculomotorius","3n","Sur",478,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=479&show=y" 480,"interpeduncular fossa","Fossa interpeduncularis","ipf","Sur",478,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=480&show=y" 481,"ventrolateral fissure of midbrain","Fissura ventrolateralis mesencephali","vlfmb","Sur",478,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=481&show=y" 449,"trochlear nerve","Nervus trochlearis","4n","Sur",448,,"http://braininfo.rprc.washington.edu/Scripts/hiercentraldirectory.asp?ID=449&show=y" voxbo-1.8.5~svn1246/db_import/marianna.csv000066400000000000000000000052651153177201300204160ustar00rootroot00000000000000"""equiv"" means we already have an equivalent entry in the NN database, and don't need anything new",, """NONE"" denotes regions that have no NN equivalent - for present purposes, they are not localizing",, ,, "PennDB Name","extra synonym","NN relationships" "MCA","middle cerebral artery","NONE" "PCA","posterior cerebral artery","NONE" "ACA","anterior cererbral artery","NONE" "ACA/MCA Watershed",,"NONE" "PICA","posterior inferior cerebellar artery","NONE" "ACoA","anterior communicating artery","NONE" "ICA","internal carotid artery","NONE" "Anterior Choroidal Artery",,"NONE" "Anterior Communicating Artery",,"NONE" "Posterior Communicating Artery",,"NONE" "Pericallosal Artery",,"NONE" "Basilar Artery",,"NONE" "Circle of Willis",,"NONE" "Frontal",,"equiv frontal lobe" "Parietal",,"equiv parietal lobe" "Temporal",,"equiv temporal lobe" "Occipital",,"equiv occipital lobe" "Thalamus",,"equiv" "Pons",,"equiv" "Brainstem","brain stem","NONE" "Midbrain",,"equiv" "Basal Ganglia",,"equiv" "Frontal-Parietal",,"includes frontal lobe; includes parietal lobe" "Frontal-Temporal",,"includes frontal lobe; includes temporal lobe" "Parietal-Temporal",,"includes parietal lobe; includes temporal lobe" "Parietal-Occipital",,"includes parietal lobe; includes occipital lobe" "Occipital-Temporal",,"includes occipital lobe; includes temporal lobe" "Frontal-Temporal-Parietal-Occipital",,"includes frontal lobe; includes temporal lobe; includes parietal lobe; includes occipital lobe" "Frontal-Temporal-Parietal",,"includes frontal lobe; includes temporal lobe; includes parietal lobe" "Temporal-Parietal-Occipital",,"includes temporal lobe; includes parietal lobe; includes occipital lobe" "Corpus Callosum",,"equiv" "Pituitary",,"equiv hypophysis" "Cerebellum",,"equiv" "Vermis",,"equiv vermis of anterior lobe" "Caudate",,"equiv caudate nucleus" "Putamen",,"equiv" "Pulvinar",,"equiv" "Globus Pallidus",,"equiv" "White matter",,"equiv cerebral white matter" "Frontal white matter",,"equiv" "Temporal white matter",,"equiv" "Parietal white matter",,"equiv" "Occipital white matter",,"equiv" "Gray matter",,"NONE" "Striatocapsular region",,"NONE" "Internal capsule",,"equiv" "External capsule",,"equiv" "Corona radiata",,"NONE" "Insula",,"equiv" "Anterior cingulate",,"equiv anterior cingulate gyrus" "Subinsular cortex",,"NONE" "Centrum semiovale",,"equiv semioval center" "Sylvian Fissure",,"equiv lateral sulcus" "Perisylvian",,"NONE" "Hippocampus",,"equiv" "Cortical",,"equiv cerebral cortex" "Cerebral",,"equiv brain" "Hemisphere",,"equiv brain" "Supratentorial",,"NONE" "Intraventricular",,"NONE" "Periventricular",,"NONE" "Parenchymal",,"NONE" "Parasellar",,"NONE" "Sellar/Suprasellar",,"NONE" "Subcortical",,"NONE" "Unspecified",,"NONE" voxbo-1.8.5~svn1246/db_import/readBrodmann.cpp000066400000000000000000000124561153177201300212130ustar00rootroot00000000000000/* This program adds Brodmann areas into brain region name database * It reads the plain text file "brodmann.info", which is generated * from brodmann.nii file. FOr each Brodmann area region name, two * synonyms are added too: BA and BA . * Note that no relationship record is added from this file. */ using namespace std; #include "utils/br_util.h" #include "vbutil.h" #include #include #include #define MAXLENGTH 5000 int addRegionName(int, string); int addSynRec(int, string, string); const char * file_in = "brodmann.info"; string name_space("Brodmann"); string dbHome("./"); string rDbName("region_name.db"); string sDbName("synonym.db"); string aDbName("admin.db"); string admin_sField("Next Synonym ID"); string username("admin"); /* Main function */ int main() { FILE * ifp = fopen(file_in, "r"); if (!ifp) { printf("Fails to read the file: %s\n", file_in); exit(0); } char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // Remove the trailing "return" key stripchars(line, "\n"); string tmpStr(line); uint post1 = tmpStr.find("#"); uint post2 = tmpStr.find(":"); if (post1 == string::npos || post2 == string::npos || post2 <= post1 + 1) { printf("Line #%d is invalid: %s\n", lineNo, tmpStr.c_str()); continue; } string ba_no = tmpStr.substr(post1 + 1, post2 - post1 - 1); string ba_name = "Brodmann's Area " + ba_no; int foo = addRegionName(lineNo, ba_name); if (foo) { printf("Line #%d: fails to add %s into region db\n", lineNo, ba_name.c_str()); continue; } string ba_s1 = "BA" + ba_no; foo = addSynRec(lineNo, ba_s1, ba_name); if (foo) { printf("Line #%d: fails to add %s into synonym db\n", lineNo, ba_s1.c_str()); continue; } string ba_s2 = "BA " + ba_no; foo = addSynRec(lineNo, ba_s2, ba_name); if (foo) { printf("Line #%d: fails to add %s into synonym db\n", lineNo, ba_s2.c_str()); continue; } } return 0; } /* This function adds a new region name into region name database */ int addRegionName(int lineNo, string newName) { int foo = chkRegionName(dbHome, rDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in region db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region \"%s\" exists in region name db\n", lineNo, newName.c_str()); return 0; } foo = chkSynonymStr(dbHome, sDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in synonym db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region name \"%s\" exists in synonym name db\n", lineNo, newName.c_str()); return 1; } regionRec regionData; regionData.setNameSpace(name_space); regionData.setName(newName); regionData.setSource("brodmann.nii"); regionData.setCreator(username); regionData.setAddDate(time(NULL)); foo = addRegion_db(dbHome, rDbName, aDbName, regionData); if (foo) { printf("Line #%d: failed to add %s into region name db\n", lineNo, newName.c_str()); return 1; } return 0; } /* Add a synonym record into synonym db */ int addSynRec(int lineNo, string name, string primary) { int foo = chkRegionName(dbHome, rDbName, name, name_space); if (foo < 0) { printf("Line #%d: fails to check synonym's uniqueness in region db\n", lineNo); return -1; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: synonym \"%s\" exists in region name db\n", lineNo, name.c_str()); return 0; } foo = chkSynonymStr(dbHome, sDbName, name, name_space); if (foo < 0) { printf("Line #%d: fails to check availability of %s in synonym db\n", lineNo, name.c_str()); return -1; } // If synonym already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: synonym \"%s\" exists in synonym db\n", lineNo, name.c_str()); return 0; } long sID = getAdmin_db(dbHome, aDbName, admin_sField); if (sID <= 0) { printf("Line #%d: fails to get next available synonym ID from admin db\n", lineNo); return -1; } synonymRec sData; sData.setID(sID); sData.setName(name); sData.setPrimary(primary); sData.setNameSpace(name_space); sData.setAddDate(time(NULL)); sData.setCreator(username); Dbt key(&sID, sizeof(long)); void *buff = sData.getBuffer(); int size = sData.getBufferSize(); Dbt data(buff, size); mydb sDB(dbHome, sDbName); try { foo = sDB.getDb().put(NULL, &key, &data, DB_NOOVERWRITE); if (foo == DB_KEYEXIST) { printf("Line %d: key %ld exists\n", lineNo, sID); return 1; } } catch(DbException &e) { sDB.getDb().err(e.get_errno(), "Error in addSynRec()"); return -1; } catch(exception &e) { sDB.getDb().errx("Error in addSynRec(): %s", e.what()); return -2; } sID++; foo = setAdmin_db(dbHome, aDbName, admin_sField, sID); if (foo < 0) { printf("Line #%d: fails to set next available synonym ID (%ld) from admin db\n", lineNo, sID); return -1; } return 0; } voxbo-1.8.5~svn1246/db_import/readHierarchy.cpp000066400000000000000000000205601153177201300213640ustar00rootroot00000000000000/* This program loads data from plain text hierarchy file to brain region name database */ using namespace std; #include "utils/br_util.h" #include "tokenlist.h" #include "vbutil.h" #include #include #include #include #define MAXLENGTH 5000 void addRecords(); int addRegionName(int, string, string, long, string); int addSynRec(int, string, string, string); string convertName(string ); const char * nn_filename = "hierarchy.csv"; string name_space("NN2002"); string dbHome("./"); string rDbName("region_name.db"); string sDbName("synonym.db"); string aDbName("admin.db"); string admin_rField("Next Region ID"); string admin_sField("Next Synonym ID"); string username("admin"); /* Main function */ int main() { addRecords(); return 0; } /* This function adds a certain record into db */ void addRecords() { int foo = setAdmin_db(dbHome, aDbName, admin_rField, 1); if (foo) { printf("Fails to initialize region ID field in admin db\n"); return; } foo = setAdmin_db(dbHome, aDbName, admin_sField, 1); if (foo) { printf("Fails to initialize synonym ID field in admin db\n"); return; } FILE * ifp = fopen(nn_filename, "r"); char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // The first line is the column names, so it is skipped if (lineNo == 1) continue; // Remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); tokenlist myRow; myRow.SetQuoteChars("\""); myRow.SetSeparator(","); myRow.ParseLine(tmpStr); // Print out error message if the line is not blank but the number of field is not 7 or 8 if (myRow.size() != 8 && myRow.size() != 7) { printf("Line #%d: the number of fields is %d\n", lineNo, myRow.size()); for (int i = 0; i < myRow.size(); i++) cout << myRow[i] << endl; continue; } string newName = convertName(myRow[1]); if (newName == "") { printf("Line #%d: blank region name or (M) attached in \"%s\", line skipped\n", lineNo, myRow(1)); continue; } long srcID = atol(myRow(0)); string abbrev = myRow[3]; string link; if (myRow.size() == 7) link = myRow[6]; else link = myRow[7]; foo = addRegionName(lineNo, newName, abbrev, srcID, link); if (foo) { printf("Line #%d: fails to add region name into region db\n", lineNo); break; } string latinName = convertName(myRow[2]); if (latinName == "") printf("Line #%d: blank latin name or (M) attached in \"%s\", line skipped\n", lineNo, myRow(2)); else if (latinName != newName) { foo = addSynRec(lineNo, latinName, newName, "NN2002.hierarchy.latin"); if (foo) printf("Line #%d: fails to add latine name into synonym db\n", lineNo); } //else //printf("Line #%d: latin name is same as English name\n", lineNo); // abbreviation field is exported to region name table instead of synonym table now // string abbrev = convertName(myRow[3]); // if (abbrev == "") // printf("Line #%d: blank latin name or (M) attached in \"%s\", line skipped\n", lineNo, myRow(3)); // else if (abbrev == newName) // printf("Line #%d: abbreviation is same as English name\n", lineNo); // else if (abbrev == latinName) // printf("Line #%d: abbreviation is same as latin name\n", lineNo); // else { // foo = addSynRec(lineNo, abbrev, newName, "NN2002.hierarchy.abbreviation"); // if (foo) // printf("Line #%d: fails to add abbreviation into synonym db\n", lineNo); // } } fclose(ifp); } /* This function dumps some of the fields in a row into region name database */ int addRegionName(int lineNo, string newName, string abbrev, long srcID, string link) { int foo = chkRegionName(dbHome, rDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in region db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region \"%s\" exists in region name db\n", lineNo, newName.c_str()); return 0; } foo = chkSynonymStr(dbHome, sDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in synonym db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region name \"%s\" exists in synonym name db\n", lineNo, newName.c_str()); return 1; } long rID = getAdmin_db(dbHome, aDbName, admin_rField); if (rID <= 0) { printf("Line #%d: fails to get next available region ID from admin db\n", lineNo); return -1; } regionRec regionData; regionData.setID(rID); regionData.setNameSpace(name_space); regionData.setName(newName); regionData.setAbbrev(abbrev); regionData.setOrgID(srcID); regionData.setSource("NN2002.hierarchy"); regionData.setCreator(username); regionData.setAddDate(time(NULL)); regionData.setLink(link); Dbt key(&rID, sizeof(long)); void * buff = regionData.getBuffer(); int size = regionData.getBufferSize(); Dbt data(buff, size); mydb rDB(dbHome, rDbName); try { foo = rDB.getDb().put(NULL, &key, &data, DB_NOOVERWRITE); if (foo == DB_KEYEXIST) { printf("Line %d: region ID %ld exists\n", lineNo, rID); return 0; } } catch(DbException &e) { rDB.getDb().err(e.get_errno(), "Error in addRegionName()"); return -1; } catch(exception &e) { rDB.getDb().errx("Error in addRegionName(): %s", e.what()); return -2; } rID++; foo = setAdmin_db(dbHome, aDbName, admin_rField, rID); if (foo) { printf("Line %d: fails to update next region ID in admin db\n", lineNo); return foo; } return 0; } /* add a certain synonym record */ int addSynRec(int lineNo, string name, string primary, string comments) { int foo = chkRegionName(dbHome, rDbName, name, name_space); if (foo < 0) { printf("Line #%d: fails to check synonym's uniqueness in region db\n", lineNo); return -1; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: synonym \"%s\" exists in region name db\n", lineNo, name.c_str()); return 0; } foo = chkSynonymStr(dbHome, sDbName, name, name_space); if (foo < 0) { printf("Line #%d: fails to check availability of %s in synonym db\n", lineNo, name.c_str()); return -1; } // If synonym already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: synonym \"%s\" exists in synonym db\n", lineNo, name.c_str()); return 0; } long sID = getAdmin_db(dbHome, aDbName, admin_sField); if (sID <= 0) { printf("Line #%d: fails to get next available synonym ID from admin db\n", lineNo); return -1; } synonymRec sData; sData.setID(sID); sData.setName(name); sData.setPrimary(primary); sData.setNameSpace(name_space); sData.setAddDate(time(NULL)); sData.setCreator(username); sData.setComments(comments); Dbt key(&sID, sizeof(long)); void *buff = sData.getBuffer(); int size = sData.getBufferSize(); Dbt data(buff, size); mydb sDB(dbHome, sDbName); try { foo = sDB.getDb().put(NULL, &key, &data, DB_NOOVERWRITE); if (foo == DB_KEYEXIST) { printf("Line %d: key %ld exists\n", lineNo, sID); return 1; } } catch(DbException &e) { sDB.getDb().err(e.get_errno(), "Error in addSynRec()"); return -1; } catch(exception &e) { sDB.getDb().errx("Error in addSynRec(): %s", e.what()); return -2; } sID++; foo = setAdmin_db(dbHome, aDbName, admin_sField, sID); if (foo < 0) { printf("Line #%d: fails to set next available synonym ID (%ld) from admin db\n", lineNo, sID); return -1; } return 0; } /* This function first checks the input region name. * If it ends with "(H)", remove that part and convert it to lower case letters. * If if ends with "(M)", skip the record completely; */ string convertName(string inputStr) { int strLen = inputStr.length(); if (strLen < 4) return toLowerCase(inputStr); string newStr; string last4 = inputStr.substr(strLen - 4, 4); if (last4 == " (M)") return ""; else if (last4 == " (H)") newStr = inputStr.substr(0, strLen - 4); else newStr = inputStr; return toLowerCase(newStr); } voxbo-1.8.5~svn1246/db_import/readMarianna.cpp000066400000000000000000000204041153177201300211710ustar00rootroot00000000000000/* This program loads those brain region names from mariana.csv to brain region name database */ using namespace std; #include "utils/br_util.h" #include "tokenlist.h" #include "vbutil.h" #include #include #include #include #define MAXLENGTH 5000 int addRegionName(int, string); int addSynRec(int, string, string, string); void addRelationship(int, string, string); vector parseRelStr(string inputStr, string separator); const char * file_in = "marianna.csv"; string name_space("Marianna"); string dbHome("./"); string rDbName("region_name.db"); string sDbName("synonym.db"); string rrDbName("region_relation.db"); string aDbName("admin.db"); string admin_sField("Next Synonym ID"); string username("admin"); /* Main function */ int main() { FILE * ifp = fopen(file_in, "r"); if (!ifp) { printf("Fails to read the file: %s\n", file_in); exit(0); } char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // The first 4 lines are skipped if (lineNo < 5) continue; // Remove the trailing "return" key stripchars(line, "\n"); string tmpStr(line); vector myRow = parseCSV(tmpStr); // Print out error message if the line is not blank but the number of field is not 3 if (myRow.size() != 3) { printf("Line #%d: the number of fields is %d\n", lineNo, myRow.size()); for (uint i = 0; i < myRow.size(); i++) cout << myRow[i] << endl; continue; } // add region name into region db string newName = myRow[0]; if (newName.length() == 0) { printf("Line #%d: blank region name, line skipped\n", lineNo); continue; } // Note that region names in this namespace are not converted to lower case int foo = addRegionName(lineNo, newName); if (foo) { printf("Line #%d: fails to add region name into region db\n", lineNo); break; } // synonym is not converted to lowercase either string x_synonym = myRow[1]; if (x_synonym == newName) printf("Line #%d: synonym is identical to region name", lineNo); else if (x_synonym.length()) { foo = addSynRec(lineNo, x_synonym, newName, "extra synonym from Marianna"); if (foo) printf("Line #%d: fails to add extra synonym into synonym db\n", lineNo); } // add relationship string relStr = myRow[2]; addRelationship(lineNo, newName, relStr); } return 0; } /* This function adds a new region name into region name database */ int addRegionName(int lineNo, string newName) { int foo = chkRegionName(dbHome, rDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in region db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region \"%s\" exists in region name db\n", lineNo, newName.c_str()); return 0; } foo = chkSynonymStr(dbHome, sDbName, newName, name_space); if (foo < 0) { printf("Line #%d: fails to check region name availability in synonym db\n", lineNo); return foo; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: region name \"%s\" exists in synonym name db\n", lineNo, newName.c_str()); return 1; } regionRec regionData; regionData.setNameSpace(name_space); regionData.setName(newName); regionData.setSource("Marianna"); regionData.setCreator(username); regionData.setAddDate(time(NULL)); foo = addRegion_db(dbHome, rDbName, aDbName, regionData); if (foo) { printf("Line #%d: failed to add %s into region name db\n", lineNo, newName.c_str()); return 1; } return 0; } /* Add a synonym record into synonym db */ int addSynRec(int lineNo, string name, string primary, string comments) { int foo = chkRegionName(dbHome, rDbName, name, name_space); if (foo < 0) { printf("Line #%d: fails to check synonym's uniqueness in region db\n", lineNo); return -1; } // If region name already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: synonym \"%s\" exists in region name db\n", lineNo, name.c_str()); return 0; } foo = chkSynonymStr(dbHome, sDbName, name, name_space); if (foo < 0) { printf("Line #%d: fails to check availability of %s in synonym db\n", lineNo, name.c_str()); return -1; } // If synonym already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: synonym \"%s\" exists in synonym db\n", lineNo, name.c_str()); return 0; } long sID = getAdmin_db(dbHome, aDbName, admin_sField); if (sID <= 0) { printf("Line #%d: fails to get next available synonym ID from admin db\n", lineNo); return -1; } synonymRec sData; sData.setID(sID); sData.setName(name); sData.setPrimary(primary); sData.setNameSpace(name_space); sData.setAddDate(time(NULL)); sData.setCreator(username); sData.setComments(comments); Dbt key(&sID, sizeof(long)); void *buff = sData.getBuffer(); int size = sData.getBufferSize(); Dbt data(buff, size); mydb sDB(dbHome, sDbName); try { foo = sDB.getDb().put(NULL, &key, &data, DB_NOOVERWRITE); if (foo == DB_KEYEXIST) { printf("Line %d: key %ld exists\n", lineNo, sID); return 1; } } catch(DbException &e) { sDB.getDb().err(e.get_errno(), "Error in addSynRec()"); return -1; } catch(exception &e) { sDB.getDb().errx("Error in addSynRec(): %s", e.what()); return -2; } sID++; foo = setAdmin_db(dbHome, aDbName, admin_sField, sID); if (foo < 0) { printf("Line #%d: fails to set next available synonym ID (%ld) from admin db\n", lineNo, sID); return -1; } return 0; } /* Parse relationship field and add it into relationship db */ void addRelationship(int lineNo, string regionName, string relStr) { // "NONE" means no relationship if (relStr == "NONE") return; // "equiv" means it is equivalent to the same region in NN2002 if (relStr == "equiv") { string r2Name = toLowerCase(regionName); int foo = addRelation_db(dbHome, rDbName, rrDbName, aDbName, username, regionName, name_space, r2Name, "NN2002", "equiv"); if (foo) printf("Error code %d: fails to add relationship in line #%d: %s\n", foo, lineNo, relStr.c_str()); return; } // "equiv " means it is equivalent to a region in NN2002 whose name is the string if (relStr.length() > 6 && relStr.substr(0, 6) == "equiv ") { int strLen = relStr.length(); string r2Name = relStr.substr(6, strLen - 6); int foo = addRelation_db(dbHome, rDbName, rrDbName, aDbName, username, regionName, name_space, r2Name, "NN2002", "equiv"); if (foo) printf("Error code %d: fails to add relationship in line #%d: %s\n", foo, lineNo, relStr.c_str()); return; } // deal with "includes <>; includes <> ..." vector relList = parseRelStr(relStr, "; "); for (uint i = 0; i < relList.size(); i++) { if (relList[i].length() > 9 && relList[i].substr(0, 9) == "includes ") { int strLen = relList[i].length(); string r2Name = relList[i].substr(9, strLen - 9); int foo = addRelation_db(dbHome, rDbName, rrDbName, aDbName, username, r2Name, "NN2002", regionName, name_space, "part-of"); if (foo) printf("Error code %d: fails to add relationship for %s in line #%d: %s\n", foo, regionName.c_str(), lineNo, relList[i].c_str()); } else printf("Unknown relationship in line #%d: %s\n", lineNo, relList[i].c_str()); } } /* THis function parses an input string and separates it into individual sections. * The first argument is the input string, the second is the separator string. */ vector parseRelStr(string inputStr, string sepStr) { string foo = inputStr; vector sections; int strLen = foo.length(); int sepLen = sepStr.length(); if (strLen == 0 || sepLen == 0) { sections.push_back(inputStr); return sections; } string bar; while (foo.find(sepStr) != string::npos) { int sepPost = foo.find(sepStr); if (sepPost == 0) bar = ""; else bar = foo.substr(0, sepPost); sections.push_back(bar); foo = foo.substr(sepPost + sepLen, foo.length() - sepPost - sepLen); } sections.push_back(foo); return sections; } voxbo-1.8.5~svn1246/db_import/readSynonym.cpp000066400000000000000000000173701153177201300211270ustar00rootroot00000000000000/* This program loads data from plain text synonym file to synonym database */ using namespace std; #include "utils/br_util.h" #include "vbutil.h" #include #include #include #include #define MAXLENGTH 5000 void addRecords(); int addSynonym(int, string, long, string); string convertName(string ); bool isValidSpec(string); bool onList(string); const char * nn_filename = "synonym.csv"; string name_space("NN2002"); string dbHome("./"); string rDbName("region_name.db"); string sDbName("synonym.db"); string aDbName("admin.db"); string admin_sField("Next Synonym ID"); string username("admin"); vector removal; /* Main function */ int main() { addRecords(); return 0; } /* This function adds a certain score into synonym database */ void addRecords() { FILE * ifp = fopen(nn_filename, "r"); char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // The first line is the column names, so it is skipped if (lineNo == 1) continue; // remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); vector myRow = parseCSV(tmpStr); // Print out error message if the line is not blank but the number of field is not 7 if (myRow.size() != 7) { printf("Line %d: the number of fields is %d\n", lineNo, myRow.size()); printf("%s\n", line); continue; } string tmpSpec = myRow[2]; if (!isValidSpec(tmpSpec)) continue; // skip the line whose "synonym" or "hierarchy lookup" field is blank if (myRow[1].length() == 0 || myRow[4].length() == 0) { //printf("Line #%d: hierarchy lookup is blank, skipped\n", lineNo); continue; } if (myRow[1] == myRow[4]) { continue; } string synStr = convertName(myRow[1]); if (synStr == "") { //printf("Line #%d: (M) attached in synonym \"%s\", skipped\n", lineNo, myRow[1].c_str()); continue; } string primaryName = convertName(myRow[4]); if (primaryName == "") { //printf("Line #%d: (M) attached in primary name \"%s\", skipped\n", lineNo, myRow[4].c_str()); continue; } // skip the line whose name is same as hierarchy lookup if (synStr == primaryName) { //printf("Line #%d: synonym is identical to hierarchy lookup in lower case, skipped\n", lineNo); continue; } long srcID = atol(myRow[0].c_str()); int foo = addSynonym(lineNo, synStr, srcID, primaryName); if (foo) break; } fclose(ifp); // Remove synonyms on removal list for (uint i = 0; i < removal.size(); i++) { string delStr = removal[i]; printf("Delete %s ...\n", delStr.c_str()); int delStat = delSyn_db(dbHome, sDbName, delStr, name_space); if (delStat) printf("Line #%d: fails to delete %s from synonym db.\n", lineNo, delStr.c_str()); } } /* This function checks whether the string in species field is valid or not. */ bool isValidSpec(string spec) { if (spec == "human" || spec == "Unspecified") return true; if (spec.size() >= 6 && spec.substr(0, 6) == "Macaca") return true; return false; } /* This function dumps some of the fields in a row into synonym database */ int addSynonym(int lineNo, string synStr, long srcID, string primary_in) { bool chopExtra = false; string primary; string extraStr(" - not otherwise specified"); int foo = chkRegionName(dbHome, rDbName, primary_in, name_space); if (foo < 0) { printf("Line %d: fails to check primary name availability of %s in region name db.\n", lineNo, primary_in.c_str()); return foo; } else if (foo == 1) primary = primary_in; else { int strLen = primary_in.length(); if (strLen > 26 && primary_in.substr(strLen - 26, 26) == extraStr) { string newName = primary_in.substr(0, strLen - 26); foo = chkRegionName(dbHome, rDbName, newName, name_space); if (foo == 1) { primary = newName; chopExtra = true; } else if (foo < 0) { printf("Line %d: fails to check availability of %s in region name db.\n", lineNo, newName.c_str()); return foo; } else { printf("Line %d: unknown primary name (%s)\n", lineNo, primary_in.c_str()); return -1; } } } string nameStr = synStr; string comments; if (chopExtra) { int nameLen = synStr.length(); if (nameLen > 26 && synStr.substr(nameLen - 26, 26) == extraStr) { nameStr = synStr.substr(0, nameLen - 26); comments = "\"- not otherwise specified\" chopped from synonym and primary name"; } else comments = "\"- not otherwise specified\" chopped from primary name"; } foo = chkRegionName(dbHome, rDbName, nameStr, name_space); if (foo < 0) { printf("Line #%d: fails to check synonym availability of %s in region name db.\n", lineNo, nameStr.c_str()); return -1; } // If synonym already exists, skip it instead of terminating the program if (foo == 1) { printf("Line #%d: %s exists in region name db.\n", lineNo, nameStr.c_str()); return 0; } foo = chkSynonymStr(dbHome, sDbName, nameStr, name_space); if (foo < 0) { printf("Line #%d: fails to check availability of %s in synonym db.\n", lineNo, nameStr.c_str()); return -1; } // If synonym already exists, skip this line if (foo == 1) { string pName; int bar = getPrimary(dbHome, sDbName, nameStr, name_space, pName); if (bar != 1) printf("Line #%d: error in retrieving primary name from synonym db.\n", lineNo); else if (pName != primary) { printf("Line #%d: %s exists in synonym db with different primary name.\n", lineNo, nameStr.c_str()); if (!onList(nameStr)) removal.push_back(nameStr); } //else //printf("Line #%d: %s exists in synonym db with same primary name.\n", lineNo, nameStr.c_str()); return 0; } long sID = getAdmin_db(dbHome, aDbName, admin_sField); if (sID < 0) { printf("Line #%d: fails to get next available synonym ID from admin db\n", lineNo); return -1; } synonymRec sData; sData.clear(); sData.setID(sID); sData.setName(nameStr); sData.setPrimary(primary); sData.setNameSpace(name_space); sData.setSourceID(srcID); sData.setAddDate(time(NULL)); sData.setCreator(username); sData.setComments(comments); Dbt key(&sID, sizeof(long)); void * buff = sData.getBuffer(); int size = sData.getBufferSize(); Dbt data(buff, size); mydb sDB(dbHome, sDbName); try { int foo = sDB.getDb().put(NULL, &key, &data, DB_NOOVERWRITE); if (foo == DB_KEYEXIST) { printf("Line %d: key %ld exists\n", lineNo, sID); return 1; } } catch(DbException &e) { sDB.getDb().err(e.get_errno(), "Error in addSynRec()"); return -1; } catch(exception &e) { sDB.getDb().errx("Error in addSynRec(): %s", e.what()); return -2; } sID++; foo = setAdmin_db(dbHome, aDbName, admin_sField, sID); if (foo < 0) { printf("Line #%d: fails to set next available synonym ID (%ld) from admin db\n", lineNo, sID); return -1; } return 0; } /* This function first checks the input region name. * If it ends with "(H)", remove that part and convert it to lower case letters. * If if ends with "(M)", skip the record completely; */ string convertName(string inputStr) { int strLen = inputStr.length(); if (strLen < 4) return toLowerCase(inputStr); string newStr; string last4 = inputStr.substr(strLen - 4, 4); if (last4 == " (M)") return ""; else if (last4 == " (H)") newStr = inputStr.substr(0, strLen - 4); else newStr = inputStr; return toLowerCase(newStr); } /* This function checks whether the input string is identical to any element in removal list.*/ bool onList(string inputStr) { for (uint i = 0; i < removal.size(); i++) { if (removal[i] == inputStr) return true; } return false; } voxbo-1.8.5~svn1246/db_import/scoreConfig.cpp000066400000000000000000000073361153177201300210610ustar00rootroot00000000000000/* load.cpp: load data from plain text file to patient database */ #include "tokenlist.h" #include "vbutil.h" #include "mydb.h" #include "score.h" #include "utils/admin_util.h" #include #include #include #include using namespace std; #define MAXLENGTH 5000 string dbHome("./"); string sdbName("score.db"); string adbName("admin.db"); vector tables; void addScore(char *); string tailorStr(string); void mkTab(string ); /* Main function */ int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: scoreConfig \n"); exit(0); } try { addScore(argv[1]); } catch(DbException &e) { cerr << "Error loading databases. " << endl; cerr << e.what() << endl; return (e.get_errno()); } catch(exception &e) { cerr << "Error loading databases. " << endl; cerr << e.what() << endl; return -1; } return 0; } /* This function adds a certain score into score database */ void addScore(char *filename) { FILE * ifp = fopen(filename, "r"); // Make sure file is readable if (!ifp) { printf("File read error: %s\n", filename); return; } char line[MAXLENGTH]; int lineNo = 0; unsigned score_id = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // if a line starts with "#", ignore the line if (strchr("#\n", line[0])) continue; // remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); tokenlist myRow; myRow.SetQuoteChars("\""); myRow.SetSeparator(","); myRow.ParseLine(tmpStr); // Ignore line that has only space or tab characters if (myRow.size() == 1 && tailorStr(myRow[0]) == "") continue; // Print out error message if the line is not blank but the number of field is not 5 if (myRow.size() != 5) { printf("%s line #%d: the number of fields is %d\n", filename, lineNo, myRow.size()); continue; } score_id++; scoreRec sData; sData.clear(); sData.setID(score_id); string scoreName = tailorStr(myRow[0]); sData.setName(scoreName); sData.setType(tailorStr(myRow[1])); string tableName = tailorStr(myRow[2]); sData.setTable(tableName); sData.setDesc(tailorStr(myRow[3])); sData.setFlags(tailorStr(myRow[4])); Dbt key(&score_id, sizeof(unsigned)); void *buff = sData.getBuffer(); int size = sData.getBufferSize(); Dbt data(buff, size); mydb scoreDB(dbHome, sdbName); int foo = scoreDB.getDb().put(NULL, &key, &data, 0); if (foo) printf("%s line #%d: failed to add %s into score db\n", filename, lineNo, scoreName.c_str()); else mkTab(tableName); } fclose(ifp); score_id++; setAdmin_db(dbHome, adbName, "Next Score ID", score_id); } /* Remove an input string's leading and traling white space characters */ string tailorStr(string inputStr) { int strLen = inputStr.length(); int start = 0, end = 0; int i; for (i = 0; i < strLen; i++) { if (inputStr[i] != 9 && inputStr[i] != 32) { start = i; break; } } // if string only includes space and tab characters, reset it to blank if (i == strLen) return ""; for (int j = strLen - 1; j >= 0; j--) { if (inputStr[j] != 9 && inputStr[j] != 32) { end = j; break; } } // return the substring that does not leading and trailing space/tab characters return inputStr.substr(start, end - start + 1); } /* This function checks the input table name. If it is not on the list of tables, add it. */ void mkTab(string inputStr) { for (uint i = 0; i < tables.size(); i++) { if (tables[i] == inputStr) return; } tables.push_back(inputStr); string dbFullName = inputStr + ".db"; mydb newDB(dbHome, dbFullName, true); } voxbo-1.8.5~svn1246/db_import/synonym.csv000066400000000000000000023321621153177201300203450ustar00rootroot00000000000000"ID","Synonym","Species","Language","Hierarchy Lookup","Ancillary Lookup","PubMedHits" 967479846,"(pre-)piriform cortex, temporal area","human","English",,"(pre-)piriform cortex, temporal area",0 1218,"A I","human","Abbreviation",,"primary auditory area",0 1236,"A II","human","Abbreviation",,"second auditory area",0 1523,"abducens colliculus","human","English","facial colliculus",,0 3235,"abducens nerve","human","English","abducens nerve",,1270 3242,"abducens nerve fibers","Macaca fascicularis","English","abducens nerve fibers",,0 3241,"abducens nerve fibers","human","English","abducens nerve fibers",,0 3617,"abducens nerve nucleus","human","English","abducens nucleus",,5 3610,"abducens nucleus","human","English","abducens nucleus",,310 3611,"abducens nucleus","Macaca fascicularis","English","abducens nucleus",,310 3612,"abducens nucleus","rat","English","abducens nucleus",,310 1013196346,"abducent colliculus","human","English","facial colliculus",,0 3240,"abducent nerve","human","English","abducens nerve",,64 4290,"accessory abducens nucleus (Crosby)","human","English",,"accessory facial nucleus",0 3658,"accessory basal amygdaloid nucleus","human","English","accessory basal amygdaloid nucleus",,2 3659,"accessory basal amygdaloid nucleus","Macaca fascicularis","English","accessory basal amygdaloid nucleus",,2 3662,"accessory basal nucleus of amygdala","Macaca fascicularis","English","accessory basal amygdaloid nucleus",,1 4193,"accessory cuneate nucleus","Macaca fascicularis","English","accessory cuneate nucleus",,10 4192,"accessory cuneate nucleus","human","English","accessory cuneate nucleus",,10 4288,"accessory facial nucleus","human","English",,"accessory facial nucleus",0 2979,"accessory medullary lamina of pallidum","human","English","accessory medullary lamina",,0 3285,"accessory nerve","human","English",,"accessory nerve",643 3356,"accessory nerve fibers","Macaca fascicularis","English","accessory nerve fibers",,0 3355,"accessory nerve fibers","human","English","accessory nerve fibers",,0 3307,"accessory nerve nuclei","human","English",,"accessory nerve nuclei",0 3670,"accessory neurosecretory nuclei","human","English",,"accessory neurosecretory nuclei",4 3309,"accessory nucleus","human","English",,"spinal accessory nucleus",0 4597,"accessory oculomotor nuclei","human","English",,"accessory oculomotor nuclei",23 5114,"accessory oculomotor nucleus","human","English","parvocellular oculomotor nucleus",,10 1370,"accessory olfactory bulb","human","English",,"accessory olfactory bulb",341 1369,"accessory olfactory bulb","human","English",,"accessory olfactory bulb",341 1374,"accessory olfactory cortical areas","human","English",,"accessory olfactory cortical areas",0 4660,"accessory olivary nucleus","human","English","lateral superior olivary nucleus",,15 5642,"accessory paraflocculus","human","English","paraflocculus",,2 4754,"accessory paramedian reticular nucleus","human","English","accessory paramedian reticular nucleus",,0 3297,"accessory portion of spinal accessory nerve","human","English","cranial part of accessory nerve",,0 2705,"accessory short gyrus","Unspecified","English","accessory short gyrus (H)",,0 4661,"accessory superior olivary nucleus","human","English","lateral superior olivary nucleus",,0 4659,"accessory superior olive","human","English","lateral superior olivary nucleus",,0 5304,"accessory trochlear nucleus","human","English",,"accessory trochlear nucleus",0 3622,"accumbens nucleus","human","English","nucleus accumbens",,142 3623,"accumbens nucleus","rat","English","nucleus accumbens",,142 642,"Acervulus","human","Latin",,"brain sand",0 6987,"acoustic area","human","English","acoustic tubercle",,14 6990,"acoustic eminence","human","English","acoustic tubercle",,0 3249,"acoustic nerve","human","English",,"cochlear nerve",335 3262,"acoustic nerve (Crosby)","human","English","vestibulocochlear nerve",,0 5867,"acoustic radiations","human","English",,"auditory radiation",1 6208,"acoustic sulcus","human","English",,"acoustic sulcus",0 6984,"acoustic tubercle","human","English","acoustic tubercle",,4 3835,"AD","human","Abbreviation","anterodorsal nucleus",,0 3834,"AD","Macaca mulatta","Abbreviation","anterodorsal nucleus",,0 2861,"adenohypophysis","Macaca fascicularis","English","ADENOHYPOPHYSIS",,1296 2860,"adenohypophysis","human","English","ADENOHYPOPHYSIS",,1296 2862,"Adenohypophysis","human","Latin","ADENOHYPOPHYSIS",,1296 662,"Adhaesio interthalamica","human","Latin","interthalamic adhesion",,2 661,"Adhesio interthalamica","human","Latin","interthalamic adhesion",,3 1271,"adolfactory area","human","English","subcallosal area",,0 706,"agranular cortex","human","English",,"agranular cortex",0 846,"agranular frontal area 6","human","English",,"agranular frontal area 6",0 1019,"agranular retrolimbic area 30","human","English",,"agranular retrolimbic area 30",0 678,"Ala centralis","human","Latin","alar central lobule",,0 6968,"Ala cinerea","human","Latin","vagal trigone",,6 675,"Ala lobuli centralis","human","Latin","alar central lobule",,2 679,"alae of central lobule","human","English","alar central lobule",,0 674,"alar central lobule","Macaca fascicularis","English","alar central lobule",,0 673,"alar central lobule","human","English","alar central lobule",,0 3402,"alar plate","human","English",,"alar plate",82 680,"allocortex","human","English",,"allocortex",83 681,"Allocortex","human","Latin",,"allocortex",83 686,"allocortex (Stephan)","human","English",,"allocortex (Stephan)",0 684,"allocortex (Stephan)","human","English",,"allocortex (Stephan)",0 683,"allocortex (Stephan)","human","English",,"allocortex (Stephan)",0 687,"allocortex (Stephan)","human","English",,"allocortex (Stephan)",0 685,"Allocortex (Stephan)","human","Latin",,"allocortex (Stephan)",0 688,"Allocortex (Stephan)","human","Latin",,"allocortex (Stephan)",0 703,"Allocortex bulbi olfactorii","human","Latin",,"Allocortex bulbi olfactorii",0 700,"Allocortex primitivus","human","Latin",,"Allocortex primitivus",0 721,"alveus","rat","English","alveus",,226 719,"alveus","Macaca fascicularis","English","alveus",,226 718,"alveus","human","English","alveus",,226 720,"Alveus","human","Latin","alveus",,226 722,"Alveus hippocampi","human","Latin","alveus",,2 724,"alveus of hippocampus","rat","English","alveus",,0 723,"alveus of hippocampus","human","English","alveus",,0 3849,"AM","Macaca mulatta","Abbreviation","anteromedial nucleus",,0 3850,"AM","human","Abbreviation","anteromedial nucleus",,0 2569,"ambiens gyrus","human","English",,"ambiens gyrus",0 3640,"ambiguus nucleus","human","English","nucleus ambiguus",,54 3641,"ambiguus nucleus","rat","English","nucleus ambiguus",,54 726,"Amiculum nuclei dentati","human","Latin","amiculum of dentate nucleus",,0 725,"amiculum of dentate nucleus","human","English","amiculum of dentate nucleus",,0 727,"amiculum of inferior olive","human","English","amiculum of inferior olive",,0 729,"amiculum olivae","human","Latin","amiculum of inferior olive",,0 728,"Amiculum olivare","human","Latin","amiculum of inferior olive",,1 101,"Ammon's horn","human","English","HIPPOCAMPUS",,566 102,"Ammon's horn","rat","English","HIPPOCAMPUS",,566 717368292,"Ammon's horn","human","English",,"Cornu Ammonis (Shaw)",8 117,"amygdala","human","English","AMYGDALA",,10693 118,"Amygdala","Macaca fascicularis","English","AMYGDALA",,10693 121,"Amygdala","human","Latin","AMYGDALA",,10693 -849667502,"amygdala - not otherwise specified","Unspecified","English","AMYGDALA - not otherwise specified",,10693 1831423083,"Amygdala - not otherwise specified","Unspecified","Latin","AMYGDALA - not otherwise specified",,10693 1210,"amygdalohippocampal area","human","English",,"amygdalohippocampal area",46 1211,"amygdalohippocampal area","Macaca fascicularis","English",,"amygdalohippocampal area",46 1215,"amygdalohippocampal transition area","human","English",,"amygdalohippocampal area",0 1213,"amygdalohippocampal transition area","human","English",,"amygdalohippocampal area",0 -1602511667,"amygdalo-hypothalamic fibers","human","English",,"amygdalo-hypothalamic fibers",0 -531865570,"amygdalo-hypothalamic fibers","human","English",,,0 1333,"amygdaloid basolateral complex","human","English","BASOLATERAL NUCLEAR GROUP",,3 125,"amygdaloid body","human","English","AMYGDALA",,139 1338,"amygdaloid corticomedial complex","human","English",,"corticomedial nuclear group (Crosby)",0 2542,"amygdaloid island","human","English",,"amygdaloid island",0 2544,"amygdaloid islands","human","English",,"amygdaloid island",0 122,"amygdaloid nuclear complex","human","English","AMYGDALA",,21 123,"amygdaloid nuclear complex","Macaca fascicularis","English","AMYGDALA",,21 127,"amygdaloid nuclear groups","human","English","AMYGDALA",,0 128,"amygdaloid nucleus","human","English","AMYGDALA",,782 5838,"amygdaloinsular fasciculus","human","English",,"amygdaloinsular fasciculus",0 2057754564,"amygdalostriate fibers","human","English",,"amygdalostriate fibers",0 3718,"amygdalostriate transition area","human","English",,"amygdalostriate transition area",0 5839,"amygdalotemporal fasciculus","human","English",,"amygdalotemporal fasciculus",0 914,"angular area 39","human","English",,"angular area 39 (H)",0 2571,"angular gyrus","human","English","angular gyrus",,140 2572,"angular gyrus","Macaca mulatta","English","angular gyrus",,140 6466,"angular sulcus","human","English",,"angular sulcus (H)",0 -2059443072,"angular white matter","Unspecified","English","angular white matter",,0 731,"Angulus cerebellopontinus","human","Latin","cerebellopontine angle",,0 3122,"angulus gyri olfactorii lateralis","human","Latin","limen of insula",,0 1,"annectant gyrus","Macaca mulatta","English","annectant gyrus (M)",,7 2,"annectant gyrus","Macaca fascicularis","English","annectant gyrus (M)",,7 1392460363,"annectant white matter","Unspecified","English","annectant white matter",,0 3793,"annular nucleus","Macaca fascicularis","English",,"annular nucleus",0 735,"ansa lenticularis","rat","English","ansa lenticularis",,63 734,"ansa lenticularis","Macaca fascicularis","English","ansa lenticularis",,63 733,"ansa lenticularis","human","English","ansa lenticularis",,63 732,"ansa lenticularis","human","English","ansa lenticularis",,63 737,"Ansa lenticularis","Macaca fascicularis","Latin","ansa lenticularis",,63 736,"Ansa lenticularis","human","Latin","ansa lenticularis",,63 739,"Ansa lenticularis (Monakow)","human","Latin","ansa lenticularis",,0 744,"ansa peduncularis","human","English","ansa peduncularis",,19 745,"Ansa peduncularis","human","Latin","ansa peduncularis",,19 3202,"ansiform lobule","human","English","ANSIFORM LOBULE",,21 3203,"ansiform lobule","Macaca fascicularis","English","ANSIFORM LOBULE",,21 3204,"ansiform lobule","rat","English","ANSIFORM LOBULE",,21 2707,"anterior accessory gyrus","Unspecified","English","anterior accessory gyrus (H)",,0 1672,"anterior amygdaloid area","rat","English","anterior amygdaloid area",,59 1671,"anterior amygdaloid area","Macaca fascicularis","English","anterior amygdaloid area",,59 1670,"anterior amygdaloid area","human","English","anterior amygdaloid area",,59 3711,"anterior amygdaloid area (Lauer)","Unspecified","English",,"anterior amygdaloid area (Lauer)",0 6397,"anterior ascending limb of lateral fissure","human","English","anterior ascending limb of lateral sulcus (H)",,0 6392,"anterior ascending limb of lateral sulcus","human","English","anterior ascending limb of lateral sulcus (H)",,0 6398,"anterior ascending ramus of lateral sulcus","human","English","anterior ascending limb of lateral sulcus (H)",,0 6423,"anterior branch of lateral sulcus","human","English","anterior horizontal limb of lateral sulcus (H)",,0 6236,"anterior calcarine fissure","human","English","anterior calcarine sulcus (H)",,1 6233,"anterior calcarine sulcus","human","English","anterior calcarine sulcus (H)",,2 6234,"anterior calcarine sulcus","human","English","anterior calcarine sulcus (H)",,2 1575,"anterior cerebellar commissure","human","English",,"anterior cerebellar commissure",0 2888,"anterior cerebellar incisure","human","English","anterior cerebellar incisure",,0 519,"anterior cerebellar lobe","human","English","ANTERIOR LOBE OF CEREBELLUM",,7 2593,"anterior cingulate gyrus","Macaca fascicularis","English","anterior cingulate gyrus",,152 2592,"anterior cingulate gyrus","human","English","anterior cingulate gyrus",,152 -116600098,"anterior cingulate white matter","Unspecified","English","anterior cingulate white matter",,0 391,"anterior colliculus","human","English","SUPERIOR COLLICULUS",,19 1532,"anterior column of fornix","human","English","anterior column of fornix",,0 1533,"anterior column of fornix","Macaca fascicularis","English","anterior column of fornix",,0 154,"anterior commissure","rat","English","ANTERIOR COMMISSURE",,842 152,"anterior commissure","human","English","ANTERIOR COMMISSURE",,842 153,"anterior commissure","Macaca fascicularis","English","ANTERIOR COMMISSURE",,842 -1543486954,"anterior commissure - not otherwise specified","Unspecified","English","ANTERIOR COMMISSURE - not otherwise specified",,842 1563,"anterior commissure, anterior part","rat","English","anterior part of anterior commissure",,0 1573,"anterior commissure, posterior part","rat","English","posterior part of anterior commissure",,0 7204,"anterior cornucommissural nucleus","human","English",,"anterior cornucommissural nucleus",0 390,"anterior corpus quadrigeminum","human","English","SUPERIOR COLLICULUS",,0 3734,"anterior cortical amygdaloid nucleus","human","English",,"anterior cortical nucleus of amygdala",7 3732,"anterior cortical nucleus of amygdala","Macaca fascicularis","English",,"anterior cortical nucleus of amygdala",0 6722,"anterior corticospinal tract","human","English","ventral corticospinal tract",,3 3163,"anterior crescentic lobule of cerebellum","human","English","anterior quadrangular lobule",,0 1536,"anterior crus of fornix","human","English","anterior column of fornix",,0 6297,"anterior cuneolingual gyrus","human","English",,"anterior cuneolingual gyrus (H)",0 2360,"anterior forceps","human","English","anterior forceps of corpus callosum",,0 2357,"anterior forceps of corpus callosum","human","English","anterior forceps of corpus callosum",,0 1041,"anterior frontal cortex","human","English",,"frontal region",0 1918,"anterior funiculus","human","English",,"anterior funiculus",18 7116,"anterior gray column","human","English",,"anterior gray column",0 7120,"anterior gray commissure","human","English",,"anterior gray commissure",0 7118,"anterior gray horn","human","English",,"anterior gray column",0 6421,"anterior horizontal limb of lateral fissure","human","English","anterior horizontal limb of lateral sulcus (H)",,0 6416,"anterior horizontal limb of lateral sulcus","Unspecified","English","anterior horizontal limb of lateral sulcus (H)",,0 6424,"anterior horizontal ramus of lateral fissure","human","English","anterior horizontal limb of lateral sulcus (H)",,0 7117,"anterior horn","human","English",,"anterior gray column",1499 7125,"anterior horn nuclear group","human","English",,"anterior horn nuclei",0 7124,"anterior horn nuclei","human","English",,"anterior horn nuclei",0 1635,"anterior horn of lateral ventricle","human","English","frontal horn of lateral ventricle",,7 3801,"anterior hypothalamic area","human","English","anterior nucleus of hypothalamus",,310 1613,"anterior hypothalamic commissure","human","English","anterior hypothalamic commissure",,0 1618,"anterior hypothalamic commissure (Ganser)","human","English","anterior hypothalamic commissure",,0 1617,"anterior hypothalamic decussation of Ganser","human","English","anterior hypothalamic commissure",,0 213,"anterior hypothalamic group","human","English",,"anterior hypothalamic group",0 3804,"anterior hypothalamic nucleus","human","English","anterior nucleus of hypothalamus",,227 210,"anterior hypothalamic region","Macaca fascicularis","English","ANTERIOR HYPOTHALAMIC REGION",,35 209,"anterior hypothalamic region","human","English","ANTERIOR HYPOTHALAMIC REGION",,35 -1252935899,"anterior hypothalamic region - not otherwise specified","Unspecified","English","ANTERIOR HYPOTHALAMIC REGION - not otherwise specified",,35 4272,"anterior interposed nucleus","human","English","emboliform nucleus",,16 4271,"anterior interpositus nucleus","Macaca fascicularis","English","emboliform nucleus",,43 1729,"anterior limb of internal capsule","human","English","anterior limb of internal capsule",,4 2863,"anterior lobe (hypophysis)","human","English","ADENOHYPOPHYSIS",,0 514,"anterior lobe of cerebellum","human","English","ANTERIOR LOBE OF CEREBELLUM",,2 515,"anterior lobe of cerebellum","Macaca fascicularis","English","ANTERIOR LOBE OF CEREBELLUM",,2 2864,"anterior lobe of hypophysis","human","English","ADENOHYPOPHYSIS",,2 2865,"anterior lobe of pituitary","rat","English","ADENOHYPOPHYSIS",,14 6439,"anterior marginal sulcus of insula","human","English",,"anterior marginal sulcus of insula (H)",0 1903,"anterior median eminence","Macaca fascicularis","English","anterior median eminence",,16 1902,"anterior median eminence","human","English","anterior median eminence",,16 2307,"anterior median fissure","Macaca fascicularis","English","anterior median fissure",,9 2306,"anterior median fissure","human","English","anterior median fissure",,9 7097,"anterior median fissure of spinal cord","human","English",,"anterior median fissure of spinal cord",0 4602,"anterior median nucleus of oculomotor nerve","human","English","anterior median oculomotor nucleus",,0 4600,"anterior median oculomotor nucleus","human","English","anterior median oculomotor nucleus",,0 7036,"anterior medullary velum","human","English","superior medullary velum",,29 6612,"anterior middle temporal sulcus","Macaca fascicularis","English","anterior middle temporal sulcus (M)",,0 6611,"anterior middle temporal sulcus","Macaca fuscata","English","anterior middle temporal sulcus (M)",,0 -1483098278,"anterior middle temporal sulcus (Bonin)","Macaca mulatta","English","middle temporal sulcus (M)",,0 624957139,"anterior middle temporal sulcus (Martin-97)","Macaca fascicularis","English","middle temporal sulcus (M)",,0 3419,"anterior nuclear group","Macaca fascicularis","English","ANTERIOR NUCLEAR GROUP",,14 3418,"anterior nuclear group","human","English","ANTERIOR NUCLEAR GROUP",,14 3798,"anterior nucleus of hypothalamus","rat","English","anterior nucleus of hypothalamus",,0 3797,"anterior nucleus of hypothalamus","Macaca fascicularis","English","anterior nucleus of hypothalamus",,0 3796,"anterior nucleus of hypothalamus","human","English","anterior nucleus of hypothalamus",,0 3422,"anterior nucleus of thalamus","human","English","ANTERIOR NUCLEAR GROUP",,2 6462,"anterior occipital sulcus","human","English","anterior occipital sulcus (H)",,2 3772,"anterior olfactory nucleus","Macaca fascicularis","English","anterior olfactory nucleus",,287 3773,"anterior olfactory nucleus","rat","English","anterior olfactory nucleus",,287 3771,"anterior olfactory nucleus","human","English","anterior olfactory nucleus",,287 3131,"anterior paracentral gyrus","human","English",,"anterior paracentral gyrus",0 6509,"anterior parieto-occipital sulcus","Macaca mulatta","English","anterior parieto-occipital sulcus (M)",,1 1272,"anterior parolfactory gyrus","human","English",,"anterior parolfactory gyrus",0 6513,"anterior parolfactory sulcus","human","English","anterior parolfactory sulcus (H)",,0 6512,"anterior parolfactory sulcus","human","English","anterior parolfactory sulcus (H)",,0 1558,"anterior part of anterior commissure","Macaca fascicularis","English","anterior part of anterior commissure",,0 1557,"anterior part of anterior commissure","human","English","anterior part of anterior commissure",,0 2797,"anterior part of inferior parietal lobule","human","English","supramarginal gyrus",,0 5734,"anterior peduncle","human","English","anterior thalamic peduncle",,0 6189,"anterior perforated area","human","English","anterior perforated substance",,0 6188,"anterior perforated space","human","English","anterior perforated substance",,3 6185,"anterior perforated substance","Macaca fascicularis","English","anterior perforated substance",,18 6184,"anterior perforated substance","human","English","anterior perforated substance",,18 1535,"anterior pillar of fornix","human","English","anterior column of fornix",,0 4649,"anterior pretectal nucleus","Macaca fascicularis","English","olivary pretectal nucleus",,96 4976,"anterior pulvinar nucleus","human","English","oral pulvinar nucleus",,4 4975,"anterior pulvinar nucleus","Macaca mulatta","English","oral pulvinar nucleus",,4 6725,"anterior pyramidal tract","human","English","ventral corticospinal tract",,0 3157,"anterior quadrangular lobule","human","English","anterior quadrangular lobule",,1 3158,"anterior quadrangular lobule","Macaca fascicularis","English","anterior quadrangular lobule",,1 3164,"anterior quadrangular lobule of cerebellum","human","English","anterior quadrangular lobule",,0 5965,"anterior region (hypothalamus)","human","English",,"supraoptic region",0 3597,"anterior region of motor thalamus","Macaca","English",,"anterolateral region of motor thalamus",0 3161,"anterior semilunar lobule","human","English","anterior quadrangular lobule",,0 1101,"anterior speech cortex","human","English",,"Broca's area",0 6859,"anterior spinocerebellar tract","human","English","anterior spinocerebellar tract",,0 899620189,"anterior spinocerebellar tract","Macaca fascicularis","English","anterior spinocerebellar tract",,0 7147,"anterior spinothalamic tract","human","English",,"anterior spinothalamic tract",0 6572,"anterior subcentral dimple","Macaca mulatta","English","anterior subcentral sulcus",,0 6570,"anterior subcentral sulcus","Macaca fascicularis","English","anterior subcentral sulcus",,1 6569,"anterior subcentral sulcus","Macaca fascicularis","English","anterior subcentral sulcus",,1 1410922988,"anterior subcentral sulcus","human","English","anterior subcentral sulcus",,1 3421,"anterior thalamic nuclei","human","English","ANTERIOR NUCLEAR GROUP",,159 3423,"anterior thalamic nucleus","human","English","ANTERIOR NUCLEAR GROUP",,47 5731,"anterior thalamic peduncle","human","English","anterior thalamic peduncle",,5 994202939,"anterior thalamic radiation","human","English",,"anterior thalamic radiations",0 -34727838,"anterior thalamic radiations","human","English",,"anterior thalamic radiations",0 6995,"anterior thalamic tubercle","human","English","anterior tubercle",,0 3424,"anterior thalamus","human","English","ANTERIOR NUCLEAR GROUP",,152 6724,"anterior tract of Turck","human","English","ventral corticospinal tract",,0 951,"anterior transverse temporal area 41","human","English",,"anterior transverse temporal area 41 (H)",0 2807,"anterior transverse temporal convolution of Heschl","human","English","anterior transverse temporal gyrus (H)",,0 2803,"anterior transverse temporal gyrus","human","English","anterior transverse temporal gyrus (H)",,0 6991,"anterior tubercle","human","English","anterior tubercle",,19 6994,"anterior tubercle of thalamus","human","English","anterior tubercle",,0 3860,"anterior ventral nucleus of thalamus","human","English","anteroventral nucleus",,0 7058,"anterior vermis of cerebellum","human","English","VERMIS OF ANTERIOR LOBE",,0 7049,"anterior vestibulospinal tract","human","English",,"medial vestibulospinal tract",0 7137,"anterior white commissure","human","English",,"anterior white commissure",0 3819,"anterodorsal nucleus","human","English","anterodorsal nucleus",,42 3820,"anterodorsal nucleus","Macaca fascicularis","English","anterodorsal nucleus",,42 3829,"anterodorsal nucleus of thalamus","human","English","anterodorsal nucleus",,2 3830,"anterodorsal nucleus of thalamus","rat","English","anterodorsal nucleus",,2 3828,"anterodorsal thalamic nucleus","rat","English","anterodorsal nucleus",,24 3827,"anterodorsal thalamic nucleus","human","English","anterodorsal nucleus",,24 7225,"anterolateral corticospinal tract","human","English",,"anterolateral corticospinal tract",0 7226,"anterolateral corticospinal tract of Barnes","human","English",,"anterolateral corticospinal tract",0 7207,"anterolateral funiculus","human","English",,"anterolateral funiculus",14 3596,"anterolateral region of motor thalamus","Macaca","English",,"anterolateral region of motor thalamus",0 3595,"anterolateral region of motor thalamus","human","English",,"anterolateral region of motor thalamus",0 6644,"anterolateral sulcus of medulla","human","English","ventrolateral sulcus",,0 7101,"anterolateral sulcus of spinal cord","human","English",,"anterolateral sulcus of spinal cord",0 3836,"anteromedial nucleus","human","English","anteromedial nucleus",,30 3837,"anteromedial nucleus","Macaca fascicularis","English","anteromedial nucleus",,30 3848,"anteromedial nucleus of thalamus","rat","English","anteromedial nucleus",,2 3847,"anteromedial nucleus of thalamus","human","English","anteromedial nucleus",,2 1292,"anteromedial part of ventral lateral posterior nucleus (Jones)","human","English","area X",,0 1293,"anteromedial part of ventral lateral posterior nucleus (Jones)","Macaca","English","area X",,0 3599,"anteromedial region of motor thalamus","human","English",,"anteromedial region of motor thalamus",0 3600,"anteromedial region of motor thalamus","Macaca","English",,"anteromedial region of motor thalamus",0 3846,"anteromedial thalamic nucleus","rat","English","anteromedial nucleus",,9 3845,"anteromedial thalamic nucleus","human","English","anteromedial nucleus",,9 3869,"anteroprincipal thalamic nucleus","human","English","anteroventral nucleus",,0 4000,"anteroventral auditory nucleus","human","English","anteroventral cochlear nucleus",,0 3998,"anteroventral cochlear nucleus","human","English","anteroventral cochlear nucleus",,218 3851,"anteroventral nucleus","human","English","anteroventral nucleus",,51 3852,"anteroventral nucleus","Macaca fascicularis","English","anteroventral nucleus",,51 3861,"anteroventral nucleus of thalamus","human","English","anteroventral nucleus",,3 3862,"anteroventral nucleus of thalamus","rat","English","anteroventral nucleus",,3 4841,"anteroventral periventricular nucleus","human","English","anteroventral periventricular nucleus",,56 4843,"anteroventral periventricular nucleus","rat","English","anteroventral periventricular nucleus",,56 4842,"anteroventral periventricular nucleus","Macaca fascicularis","English","anteroventral periventricular nucleus",,56 3863,"anteroventral thalamic nucleus","rat","English","anteroventral nucleus",,39 6126,"Anulus aquaeductus","human","Latin","central gray substance of midbrain",,0 6127,"Anulus aqueductus cerebri","human","Latin","central gray substance of midbrain",,0 6128,"anulus of cerebral aqueduct","human","English","central gray substance of midbrain",,0 772,"Apertura lateralis ventriculi quarti","human","Latin","lateral aperture of fourth ventricle",,0 969894220,"apertura medialis ventriculi quarti (Magendii)","human","Latin","median aperture of fourth ventricle",,0 775,"Apertura mediana ventriculi quarti","human","Latin","median aperture of fourth ventricle",,0 344,"Aquaductus mesencephali","human","Latin","cerebral aqueduct",,0 339,"Aquaeductus cerebri","Macaca mulatta","Latin","cerebral aqueduct",,1 976577295,"aquaeductus mesencephali (Sylvii)","human","Latin","cerebral aqueduct",,0 342,"Aquaeductus Sylvii","Macaca fascicularis","Latin","cerebral aqueduct",,2 349,"aqueduct (Sylvius)","rat","English","cerebral aqueduct",,2 340,"aqueduct of Sylvius","human","English","cerebral aqueduct",,133 343,"Aqueductus (Sylvii)","human","Latin","cerebral aqueduct",,2 337,"Aqueductus cerebri","human","Latin","cerebral aqueduct",,5 338,"Aqueductus cerebri","Macaca nemestrina","Latin","cerebral aqueduct",,5 341,"Aqueductus mesencephali","human","Latin","cerebral aqueduct",,0 646,"arachnoid","human","English",,"arachnoid",2870 647,"Arachnoid","human","Latin",,"arachnoid",2870 -691867348,"Arachnoidea mater encephali","human","Latin",,"arachnoid",0 3383,"ARAS","human","Abbreviation",,"ascending reticular activating system",0 777,"arbor vitae","human","English","arbor vitae",,2 778,"Arbor vitae","human","Latin","arbor vitae",,2 779,"Arbor vitae cerebelli","human","Latin","arbor vitae",,0 555,"Archaeocerebellum","human","Latin","FLOCCULONODULAR LOBE",,1 783,"Archaeocortex","human","Latin","ARCHICORTEX",,0 659,"Archambault's loop","human","English",,"inferior optic radiation",0 556,"Archeocerebellum","human","Latin","FLOCCULONODULAR LOBE",,0 782,"Archeocortex","human","Latin","ARCHICORTEX",,2 557,"archicerebellum","human","English","FLOCCULONODULAR LOBE",,18 780,"archicortex","human","English","ARCHICORTEX",,56 781,"archicortex","Macaca fascicularis","English","ARCHICORTEX",,56 1619158171,"archicortex (Carpenter)","human","English",,"archicortex (Carpenter)",0 786,"Archicortex praecommissuralis","human","Latin",,"precommissural archicortex",0 784,"archipallium","human","English","ARCHICORTEX",,5 126,"archistriatum","human","English","AMYGDALA",,260 2142,"arcuate fasciculus","human","English",,"arcuate fasciculus",18 4400,"arcuate hypothalamic nucleus","rat","English","arcuate nucleus of hypothalamus",,32 4395,"arcuate nucleus of hypothalamus","rat","English","arcuate nucleus of hypothalamus",,12 4394,"arcuate nucleus of hypothalamus","Macaca fascicularis","English","arcuate nucleus of hypothalamus",,12 4393,"arcuate nucleus of hypothalamus","human","English","arcuate nucleus of hypothalamus",,12 3454,"arcuate nucleus of medulla","human","English","arcuate nucleus of medulla",,0 5488,"arcuate nucleus of thalamus","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,0 3460,"arcuate nucleus-1","human","English","arcuate nucleus of medulla",,1 4405,"arcuate nucleus-2","human","English","arcuate nucleus of hypothalamus",,4 5490,"arcuate nucleus-3","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,3 4403,"arcuate periventricular nucleus","human","English","arcuate nucleus of hypothalamus",,2 6212,"arcuate sulcus","Macaca mulatta","English",,"arcuate sulcus",85 870,"Area frontopolaris (Mai)","human","Latin",,"frontopolar area (Mai)",0 1401,"Area tegmentalis","Macaca fascicularis","Latin","field H",,10 1400,"Area tegmentalis H","human","Latin","field H",,0 2105,"Area tegmentalis H1","human","Latin","field H1",,0 7410,"area 1 of Brodmann-09","Cercopithecus","English",,"area 1 of Brodmann-09",0 301524238,"area 1 of Mauss-08","Unspecified","English",,"area 1 of Mauss-08",0 -858156939,"area 10 (H) of Brodmann","human","English",,"frontopolar area 10",0 -1371367804,"area 10 (M) of Brodmann","Cercopithecus","English",,"area 10 of Brodmann-09",0 872,"area 10 of Brodmann-09","Cercopithecus","English",,"area 10 of Brodmann-09",0 -1155328410,"area 10 of Mauss-08","Unspecified","English",,"area 10 of Mauss-08",0 -1330303313,"area 10 of Walker","Macaca","English",,"frontopolar area 10",0 -174285124,"area 10 of Walker","Macaca","English",,"area 10 of Walker",0 -1809100409,"area 10a of the Vogts","Cercopithecus","English",,"area 10a of the Vogts",0 7432,"area 11 of Brodmann-09","Cercopithecus","English",,"area 11 of Brodmann-09",0 -992372226,"area 11 of Mauss-08","Unspecified","English",,"area 11 of Mauss-08",0 -433795315,"area 11 of Walker","Macaca","English",,"area 11 of Walker",0 877,"area 12 of Brodmann-09","Cercopithecus","English",,"area 12 of Brodmann-09",0 316278934,"area 12 of Mauss-08","Unspecified","English",,"area 12 of Mauss-08",0 -1462090779,"area 1-2 of Roberts","Macaca mulatta","English",,"area 1-2 of Roberts",0 -927067318,"area 12 of Walker","Macaca","English",,"area 12 of Walker",0 -1704410578,"area 13 of Mauss-08","Unspecified","English",,"area 13 of Mauss-08",0 -281157629,"area 13 of Walker","Macaca","English",,"area 13 of Walker",0 -111707655,"area 14 of Mauss-08","Unspecified","English",,"area 14 of Mauss-08",0 -689761656,"area 14 of Walker","Macaca","English",,"area 14 of Walker",0 -1986461520,"area 15 of Mauss-08","Unspecified","English",,"area 15 of Mauss-08",0 697,"area 16 of Brodmann","Cercocebus torquatus","English",,"peripaleocortical claustral region",0 812,"area 17 of Brodmann","human","English",,"striate area 17",0 7438,"area 17 of Brodmann-09","Cercopithecus","English",,"area 17 of Brodmann-09",0 1601527688,"area 17 of Mauss-08","Unspecified","English",,"area 17 of Mauss-08",0 1180,"area 18 of Brodmann","human","English",,"parastriate area 18",0 7441,"area 18 of Brodmann-09","Cercopithecus","English",,"area 18 of Brodmann-09",0 -639413920,"area 18 of Mauss-08","Unspecified","English",,"area 18 of Mauss-08",0 1190,"area 19","human","English",,"peristriate area 19",0 7444,"area 19 of Brodmann-09","Cercopithecus","English",,"area 19 of Brodmann-09",0 -1176226248,"area 19 of Mauss-08","Unspecified","English",,"area 19 of Mauss-08",0 7412,"area 2 of Brodmann-09","Cercopithecus","English",,"area 2 of Brodmann-09",0 -822147674,"area 2 of Mauss-08","Unspecified","English",,"area 2 of Mauss-08",0 7447,"area 20 of Brodmann-09","Cercopithecus","English",,"area 20 of Brodmann-09",0 1971678736,"area 20 of Mauss-08","Unspecified","English",,"area 20 of Mauss-08",0 7450,"area 21 of Brodmann-09","Cercopithecus","English",,"area 21 of Brodmann-09",0 -715106072,"area 21 of Mauss-08","Unspecified","English",,"area 21 of Mauss-08",0 7453,"area 22 of Brodmann-09","Cercopithecus","English",,"area 22 of Brodmann-09",0 -1038461248,"area 22 of Mauss-08","Unspecified","English",,"area 22 of Mauss-08",0 7459,"area 23 of Brodmann-09","Cercopithecus","English",,"area 23 of Brodmann-09",0 1105512344,"area 23 of Mauss-08","Unspecified","English",,"area 23 of Mauss-08",0 -543942451,"area 23a of Vogt","Macaca mulatta","English",,"area 23a of Vogt",0 1301318154,"area 23a of Vogt","human","English",,"area 23a of Vogt",0 967159726,"area 23b of Vogt","human","English",,"area 23b of Vogt",0 58078615,"area 23b of Vogt","Macaca mulatta","English",,"area 23b of Vogt",0 -2102585972,"area 23c of Vogt","human","English",,"area 23c of Vogt",0 550015389,"area 23c of Vogt","Macaca mulatta","English",,"area 23c of Vogt",0 7400,"area 24 of Brodmann-09","Cercopithecus","English",,"area 24 of Brodmann-09",0 936805352,"area 24 of Mauss-08","Unspecified","English",,"area 24 of Mauss-08",0 986,"area 24a","human","English",,"area 24a of Vogt",0 1735148614,"area 24a of Vogt","Macaca mulatta","English",,"area 24a of Vogt",0 988,"area 24b of Vogt","human","English",,"area 24b of Vogt",0 -1495342001,"area 24b of Vogt","Macaca mulatta","English",,"area 24b of Vogt",0 990,"area 24c of Vogt","human","English",,"area 24c of Vogt",0 1594694628,"area 24c of Vogt","Macaca mulatta","English",,"area 24c of Vogt",0 1631314646,"area 25","Macaca","English",,"area 25 of Walker",0 7406,"area 25 of Brodmann-05","Cercopithecus","English",,"area 32 of Brodmann-09",0 7407,"area 25 of Brodmann-09","Old World monkeys","English",,"area 25 of Brodmann-09",0 -1030721047,"area 25 of Walker","Macaca","English",,"area 25 of Walker",0 7462,"area 26 of Brodmann-09","Cercopithecus","English",,"area 26 of Brodmann-09",0 -1176522088,"area 26 of Mauss-08","Unspecified","English",,"area 26 of Mauss-08",0 1626951787,"area 27 of Brodmann-09","Unspecified","English",,"area 27 of Brodmann-09",0 669241777,"area 27 of Mauss-08","Unspecified","English",,"area 27 of Mauss-08",0 1153,"area 28 of Brodmann (Crosby)","human","English","entorhinal area",,0 7466,"area 28 of Brodmann-09","Cercopithecus","English",,"area 28 of Brodmann-09",0 1017,"area 29 of Brodmann","human","English",,"granular retrolimbic area 29",0 1023576063,"area 29 of Mauss-08","Unspecified","English",,"area 29 of Mauss-08",0 7416,"area 3 of Brodmann-09","Cercopithecus","English",,"area 3 of Brodmann-09",0 1617146174,"area 3 of Mauss-08","Unspecified","English",,"area 3 of Mauss-08",0 1022,"area 30 of Brodmann","Unspecified","English",,"agranular retrolimbic area 30",0 -141947977,"area 30 of Mauss-08","Unspecified","English",,"area 30 of Mauss-08",0 969,"area 31 of Brodmann","Unspecified","English",,"dorsal posterior cingulate area 31",0 1352458688,"area 31 of Mauss-08","Unspecified","English",,"area 31 of Mauss-08",0 715026251,"area 32 of Brodmann-09","Cercopithecus","English",,"area 32 of Brodmann-09",0 93000580,"area 32 of Mauss-08","Unspecified","English",,"area 32 of Mauss-08",0 998,"area 33 of Brodmann","Unspecified","English",,"pregenual area 33",0 -102354724,"area 33 of Mauss-08","Unspecified","English",,"area 33 of Mauss-08",0 1028,"area 34 of Brodmann","human","English",,"dorsal entorhinal area 34",0 1726,"area 35 of Brodmann","human","English",,"perirhinal area 35",0 921,"area 36 of Brodmann","Unspecified","English",,"ectorhinal area 36",0 927,"area 37 of Brodmann","Unspecified","English",,"occipitotemporal area 37 (H)",0 931,"area 38 of Brodmann","Unspecified","English",,"temporopolar area 38 (H)",0 917,"area 39 of Brodmann","Unspecified","English",,"angular area 39 (H)",0 843,"area 4 of Brodmann","human","English",,"gigantopyramidal area 4",0 7419,"area 4 of Brodmann-09","Cercopithecus","English",,"area 4 of Brodmann-09",0 1998538710,"area 4 of Mauss-08","Unspecified","English",,"area 4 of Mauss-08",0 913,"area 40 of Brodmann","Unspecified","English",,"supramarginal area 40 (H)",0 955,"area 41 of Brodmann","Unspecified","English",,"anterior transverse temporal area 41 (H)",0 960,"area 42 of Brodmann","Unspecified","English",,"posterior transverse temporal area 42 (H)",0 7456,"area 43 of Brodmann-09","Cercopithecus","English",,"area 43 of Brodmann-09",0 2625,"area 44 of Brodmann","Unspecified","English",,"opercular area 44",0 51850427,"area 45","Macaca","English",,"area 45 of Walker",0 2635,"area 45 of Brodmann","Unspecified","English",,"triangular area 45",0 -1493476362,"area 45 of Walker","Macaca","English",,"area 45 of Walker",0 -1812045810,"area 46","Macaca","English",,"area 46 of Walker",0 890,"area 46 of Brodmann","Unspecified","English",,"middle frontal area 46",0 -565301697,"area 46 of Walker","Macaca","English",,"area 46 of Walker",0 2747,"area 47 of Brodmann","Unspecified","English",,"orbital area 47",0 1250,"area 48 of Brodmann","human","English",,"retrosubicular area 48",0 5831,"Area 49 Brodmann","human","English",,"parasubicular area",0 -435504364,"area 4a of the Vogts","Cercopithecus","English",,"area 4a of the Vogts",0 1962334853,"area 4b of the Vogts","Cercopithecus","English",,"area 4b of the Vogts",0 536340322,"area 4c of the Vogts","Cercopithecus","English",,"area 4c of the Vogts",0 7435,"area 5 of Brodmann-09","Cercopithecus","English",,"area 5 of Brodmann-09",0 2065049966,"area 5 of Mauss-08","Unspecified","English",,"area 5 of Mauss-08",0 950,"area 52 of Brodmann","Unspecified","English",,"parainsular area 52 (H)",0 850,"area 6 of Brodmann","human","English",,"agranular frontal area 6",0 7422,"area 6 of Brodmann-09","Cercopithecus","English",,"area 6 of Brodmann-09",0 -996624890,"area 6 of Mauss-08","Unspecified","English",,"area 6 of Mauss-08",0 -956975045,"area 6a alpha of the Vogts","Cercopithecus","English",,"area 6a alpha of the Vogts",0 -462003104,"area 6a beta of the Vogts","Cercopithecus","English",,"area 6a beta of the Vogts",0 -1090657055,"area 6a of the Vogts","Cercopithecus","English",,"area 6a of the Vogts",0 1099129230,"area 6b alpha of the Vogts","Cercopithecus","English",,"area 6b alpha of the Vogts",0 -1422018057,"area 6b beta of the Vogts","Cercopithecus","English",,"area 6b beta of the Vogts",0 2041420396,"area 6b of the Vogts","Cercopithecus","English",,"area 6b of the Vogts",0 906,"area 7 of Brodmann-09","Cercopithecus","English",,"area 7 of Brodmann-09",0 1120135392,"area 7 of Brodmann-09","Unspecified","English",,"area 7 of Brodmann-09",0 -2048701026,"area 7 of Mauss-08","Unspecified","English",,"area 7 of Mauss-08",0 -321707105,"area 8","Macaca","English",,"area 8 of Walker",0 -616485635,"area 8 alpha of the Vogts","Cercopithecus","English",,"area 8 alpha of the Vogts",0 656422522,"area 8 beta of the Vogts","Cercopithecus","English",,"area 8 beta of the Vogts",0 -1910821005,"area 8 delta of the Vogts","Cercopithecus","English",,"area 8 delta of the Vogts",0 1160292664,"area 8 gamma of the Vogts","Cercopithecus","English",,"area 8 gamma of the Vogts",0 7425,"area 8 of Brodmann-09","Cercopithecus","English",,"area 8 of Brodmann-09",0 1688096822,"area 8 of Mauss-08","Unspecified","English",,"area 8 of Mauss-08",0 -433189159,"area 8 of Walker","Macaca","English",,"area 8 of Walker",0 279941670,"area 8A of Walker","Macaca","English",,"area 8A of Walker",0 -139799377,"area 8B of Walker","Macaca","English",,"area 8B of Walker",0 7428,"area 9 of Brodmann-09","Cercopithecus","English",,"area 9 of Brodmann-09",0 -741191369,"area 9 of Mauss-08","Unspecified","English",,"area 9 of Mauss-08",0 81566916,"area 9 of Walker","Macaca","English",,"area 9 of Walker",0 1822402165,"area 9a of the Vogts","Cercopithecus","English",,"area 9a of the Vogts",0 -1679990638,"area 9b of the Vogts","Cercopithecus","English",,"area 9b of the Vogts",0 355280299,"area 9c of the Vogts","Cercopithecus","English",,"area 9c of the Vogts",0 -1668857584,"area 9d of the Vogts","Cercopithecus","English",,"area 9d of the Vogts",0 6988,"Area acustica","human","Latin","acoustic tubercle",,0 1676,"Area amydaliformis anterior","human","Latin","anterior amygdaloid area",,0 1212,"Area amygdalohippocampalis","human","Latin",,"amygdalohippocampal area",0 1674,"Area amygdaloidea anterior","Macaca fuscata","Latin","anterior amygdaloid area",,1 1673,"Area amygdaloidea anterior","human","Latin","anterior amygdaloid area",,1 2006561779,"Area angularis","human","Latin",,"angular area 39 (H)",0 1675,"Area anterior amygdalae","Macaca fascicularis","Latin","anterior amygdaloid area",,0 -1882253736,"Area cingularis anterior","Cercopithecus","Latin",,"area 24 of Brodmann-09",0 1143202782,"Area cingularis anterior dorsalis","human","Latin",,"dorsal anterior cingulate area 32",0 22855445,"Area cingularis anterior ventralis","human","Latin",,"ventral anterior cingulate area 24",0 -526363035,"Area cingularis intermedia","human","Latin",,"Area cingularis intermedia",0 2004543356,"Area cingularis posterior","Cercopithecus","Latin",,"area 23 of Brodmann-09",0 -469469103,"Area cingularis posterior dorsalis","human","Latin",,"dorsal posterior cingulate area 31",0 206874266,"Area cingularis posterior ventralis","human","Latin",,"ventral posterior cingulate area 23",0 3713,"Area claustralis amygdalae","Macaca fascicularis","Latin","claustral amygdaloid area",,0 1137,"Area commissurae postopticae","marmoset","Latin",,"Area commissurae postopticae",0 2388,"area dentata","Macaca mulatta","English","DENTATE GYRUS",,108 5933,"Area dorsalis hypothalami","Macaca fascicularis","Latin","dorsal hypothalamic area",,0 600975193,"Area ectorhinalis","human","Latin",,"ectorhinal area 36",0 1789238338,"Area ectosplenialis","Cercopithecus","Latin",,"area 26 of Brodmann-09",0 1608391924,"Area ectosplenialis","human","Latin",,"ectosplenial area 26",0 1422324921,"Area ectosplenialis","Cercopithecus","Latin",,"area 26 of Mauss-08",0 -1269987629,"Area entorhinalis","Cercopithecus","Latin",,"area 28 of Brodmann-09",0 889018826,"Area entorhinalis","Cercopithecus","Latin","entorhinal area",,0 1147,"Area entorhinalis (28,34)","human","Latin","entorhinal area",,0 2041003633,"Area entorhinalis dorsalis","human","Latin",,"dorsal entorhinal area 34",0 -579879027,"Area entorhinalis ventralis et dorsalis","human","Latin","entorhinal area",,0 1086638864,"Area frontalis agranularis","human","Latin",,"agranular frontal area 6",0 1638721470,"Area frontalis agranularis","Cercopithecus","Latin",,"area 6 of Brodmann-09",0 -1511955697,"Area frontalis caudalis","Cercopithecus","Latin",,"area 6 of Mauss-08",0 -281441847,"Area frontalis granularis","human","Latin",,"granular frontal area 9",0 -438269665,"Area frontalis granularis","Cercopithecus","Latin",,"area 9 of Brodmann-09",0 -281719780,"Area frontalis intermedia","human","Latin",,"intermediate frontal area 8",0 99614634,"Area frontalis intermedia","Cercopithecus","Latin",,"area 8 of Brodmann-09",0 1801756031,"Area frontalis intermedia","Cercopithecus","Latin",,"area 8 of Mauss-08",0 -880576905,"Area frontalis media","human","Latin",,"middle frontal area 46",0 -1017242162,"Area frontalis oralis","Cercopithecus","Latin",,"area 9 of Mauss-08",0 967152678,"Area frontopolaris","human","Latin",,"frontopolar area 10",0 -1616459659,"Area gigantopyramidalis","human","Latin",,"gigantopyramidal area 4",0 2091539090,"Area gigantopyramidalis","Cercopithecus","Latin",,"area 4 of Brodmann-09",0 1147208148,"Area hippocampica","Cercopithecus","Latin",,"area 29 of Mauss-08",0 5934,"Area hypothalamica dorsalis","human","Latin","dorsal hypothalamic area",,9 5935,"Area hypothalamica dorsalis","Macaca fuscata","Latin","dorsal hypothalamic area",,9 3453,"Area hypothalamica dorsalis","human","Latin",,"Regio hypothalamica dorsalis",9 1165,"Area hypothalamica lateralis","human","Latin","LATERAL HYPOTHALAMIC AREA",,4 330379396,"Area hypothalamica lateralis - not otherwise specified","Unspecified","Latin","LATERAL HYPOTHALAMIC AREA - not otherwise specified",,4 4880,"Area hypothalamica posterior","human","Latin","posterior nucleus of hypothalamus",,6 4881,"Area hypothalamica posterior","Macaca fuscata","Latin","posterior nucleus of hypothalamus",,6 1065,"Area infraradiata dorsalis","human","Latin",,"Area infraradiata dorsalis",0 997,"Area infraradiata ventralis","human","Latin",,"pregenual area 33",0 127774018,"area infraradiata ventralis","human","Latin",,"area infraradiata ventralis",0 -852089146,"Area insularis anterior","Cercopithecus","Latin",,"area 14 of Mauss-08",0 1751086615,"Area insularis posterior","Cercopithecus","Latin",,"area 13 of Mauss-08",0 1170,"Area lateralis hypothalami","Macaca fascicularis","Latin","LATERAL HYPOTHALAMIC AREA",,9 -46686263,"Area limbica anterior","Cercopithecus","Latin",,"area 24 of Mauss-08",0 243901881,"Area limbica posterior","Cercopithecus","Latin",,"area 23 of Mauss-08",0 1067,"Area medioradiata","human","Latin",,"Area medioradiata",0 -1703389660,"Area occipitalis","human","Latin",,"parastriate area 18",3 937723014,"Area occipitalis","Cercopithecus","Latin",,"area 18 of Brodmann-09",3 1150433,"Area occipitalis","Cercopithecus","Latin",,"area 18 of Mauss-08",0 923,"Area occipitotemporalis","human","Latin",,"occipitotemporal area 37 (H)",0 1098,"area of Broca","human","English",,"Broca's area",0 1104,"area of Wernicke","human","English",,"Wernicke's area",0 -2032090981,"area OFO of Roberts","Macaca mulatta","English",,"area OFO of Roberts",0 6195,"Area olfactoria (Mai)","Macaca fascicularis","Latin","anterior perforated substance",,0 6194,"Area olfactoria (Mai)","human","Latin","anterior perforated substance",,0 3897,"Area olfactoria (Roberts)","human","Latin","nucleus of diagonal band",,0 613054764,"Area opercularis","Cercopithecus","Latin",,"area 30 of Mauss-08",0 1771559615,"Area opercularis","human","Latin",,"opercular area 44",0 1652768497,"Area operculo-insularis","Cercopithecus","Latin",,"area 15 of Mauss-08",0 620945120,"Area orbitalis","human","Latin",,"orbital area 47",0 -1410446951,"Area orbitalis externa","Cercopithecus","Latin",,"area 10 of Brodmann-09",0 605701543,"Area orbitalis intermedia","Cercopithecus","Latin",,"area 11 of Mauss-08",0 207691691,"Area orbitalis interna","Cercopithecus","Latin",,"area 11 of Brodmann-09",0 -2033544209,"Area orbitalis lateralis","Cercopithecus","Latin",,"area 10 of Mauss-08",0 -343259553,"Area orbitalis medialis","Cercopithecus","Latin",,"area 12 of Mauss-08",0 1174,"Area parabigemina","human","Latin",,"parabigeminal area",0 4220,"Area parabigeminalis (Mai)","human","Latin","cuneiform nucleus",,0 1845148203,"Area parainsularis","human","Latin",,"parainsular area 52 (H)",0 428571733,"Area parastriata of Smith","human","Latin",,"parastriate area 18",0 5827,"Area parasubicularis","human","Latin",,"parasubicular area",0 767467823,"Area paratemporalis of Smith","human","Latin",,"occipitotemporal area 37 (H)",0 -1750519967,"Area parietalis","Cercopithecus","Latin",,"area 7 of Brodmann-09",5 -895765277,"Area parietalis","Cercopithecus","Latin",,"area 7 of Brodmann-09",5 -1842308921,"Area parietalis","Cercopithecus","Latin",,"area 7 of Mauss-08",0 1907577069,"Area parietalis superior","human","Latin",,"superior parietal area 7",0 1268,"Area parolfactoria","human","Latin","subcallosal area",,1 1214,"Area periamygdalae caudalis ventralis","human","Latin",,"amygdalohippocampal area",0 -738575529,"Area perirhinalis","human","Latin",,"perirhinal area 35",0 469157800,"Area perirhinalis","Cercopithecus","Latin",,"perirhinal area 35",0 -37990288,"Area peristriata of Smith","human","Latin",,"peristriate area 19",0 -1699483526,"Area postcentralis caudalis","human","Latin",,"caudal postcentral area 2",0 1092751101,"Area postcentralis caudalis","Cercopithecus","Latin",,"area 2 of Brodmann-09",0 761733679,"Area postcentralis caudalis","Cercopithecus","Latin",,"area 2 of Mauss-08",0 779298401,"Area postcentralis intermedia","Cercopithecus","Latin",,"area 1 of Mauss-08",0 120683406,"Area postcentralis intermedia","human","Latin",,"intermediate postcentral area 1",0 2067703521,"Area postcentralis intermedia","Cercopithecus","Latin",,"area 1 of Brodmann-09",0 -1131744456,"Area postcentralis oralis","Cercopithecus","Latin",,"area 3 of Brodmann-09",0 474209255,"Area postcentralis oralis","Cercopithecus","Latin",,"area 3 of Mauss-08",0 1757604902,"Area postcentralis oralis","human","Latin",,"rostral postcentral area 3",0 4879,"Area posterior hypothalami","Macaca fascicularis","Latin","posterior nucleus of hypothalamus",,0 1243,"area postrema","human","English","area postrema",,1265 1244,"Area postrema","Macaca fascicularis","English","area postrema",,1265 1245,"area postrema","rat","English","area postrema",,1265 1384768671,"Area praecentralis","Cercopithecus","Latin",,"area 4 of Mauss-08",0 892,"Area praefrontalis","human","Latin",,"prefrontal area 11",0 972752437,"Area praegenualis","Cercopithecus","Latin",,"area 32 of Mauss-08",0 1370897127,"Area praegenualis","human","Latin",,"pregenual area 33",0 -832164159,"Area praelimbica","Cercopithecus","Latin",,"area 31 of Mauss-08",0 1905717808,"Area praelimbica","Cercopithecus","Latin",,"area 32 of Brodmann-09",0 -75941646,"Area praeoccipitalis","human","Latin",,"peristriate area 19",0 735303641,"Area praeoccipitalis","Cercopithecus","Latin",,"area 19 of Mauss-08",0 1773759518,"Area praeoccipitalis","Cercopithecus","Latin",,"area 19 of Brodmann-09",0 5941,"Area praeoptica","human","Latin","PREOPTIC AREA",,3 4897,"Area praeoptica lateralis","Macaca fascicularis","Latin","lateral preoptic nucleus",,0 4896,"Area praeoptica lateralis","human","Latin","lateral preoptic nucleus",,0 4907,"Area praeoptica medialis","Macaca fascicularis","Latin","medial preoptic nucleus",,1 -923142041,"Area praeparietalis","human","Latin",,"preparietal area 5",0 1100880983,"Area praeparietalis","Cercopithecus","Latin",,"area 5 of Mauss-08",0 1496799697,"Area praeparietalis","Cercopithecus","Latin",,"area 5 of Brodmann-09",0 -337620814,"Area praesubicularis","human","Latin","presubiculum",,0 967219172,"Area praesubicularis","Cercopithecus","Latin","presubiculum",,0 1756422686,"Area praesubicularis","Cercopithecus","Latin",,"area 27 of Mauss-08",0 1305691344,"Area praesubicularis","Cercopithecus","Latin",,"area 27 of Brodmann-09",0 401,"Area praetectalis","human","Latin","PRETECTAL REGION",,10 402,"Area praetectalis","Macaca fascicularis","Latin","PRETECTAL REGION",,10 -1470349651,"Area praeterminalis","Cercopithecus","Latin",,"area 33 of Mauss-08",0 38608192,"area PrCO of Roberts","Macaca mulatta","English",,"area PrCO of Roberts",0 5938,"Area preoptica","human","Latin","PREOPTIC AREA",,16 4893,"Area preoptica lateralis","Macaca fuscata","Latin","lateral preoptic nucleus",,2 4904,"Area preopticus medialis","Macaca fuscata","Latin","medial preoptic nucleus",,0 400,"Area pretectalis","human","Latin","PRETECTAL REGION",,34 -545348795,"Area pretectalis - not otherwise specified","Unspecified","Latin","PRETECTAL REGION - not otherwise specified",,34 3778,"Area retrobulbaris","human","Latin","anterior olfactory nucleus",,0 5257,"Area retrochiasmatica","Unspecified","Latin","retrochiasmatic area",,3 423437422,"Area retrolimbica agranularis","human","Latin",,"agranular retrolimbic area 30",0 2037556288,"Area retrolimbica granularis","human","Latin",,"granular retrolimbic area 29",0 1246,"Area retro-olivaris","human","Latin",,"Area retro-olivaris",0 -720695971,"Area retrosubicularis","human","Latin",,"retrosubicular area 48",0 5946,"Area septalis","human","Latin",,"septal region (Riley)",3 -1076517823,"area SSII of Roberts","Macaca mulatta","English",,"area SS II of Roberts",0 1498587866,"Area striata","Cercopithecus","Latin",,"area 17 of Brodmann-09",13 -430539693,"Area striata","human","Latin",,"striate area 17",13 1970666217,"Area striata","Cercopithecus","Latin",,"area 17 of Mauss-08",0 1266,"Area subcallosa","human","Latin","subcallosal area",,0 -273398653,"Area subcentralis","Cercopithecus","Latin",,"area 43 of Brodmann-09",0 862939753,"Area subcentralis","human","Latin",,"subcentral area 43",0 1615427176,"Area subgenualis","Cercopithecus","Latin",,"area 25 of Brodmann-09",0 1979930477,"Area subgenualis","human","Latin",,"subgenual area 25",0 2103,"Area subthalamica tegmentalis, pars dorsomedialis","human","Latin","field H1",,0 1967,"Area subthalamica tegmentalis, pars ventrolateralis","human","Latin","field H2",,0 -86033027,"Area supramarginalis","human","Latin",,"supramarginal area 40 (H)",0 5530,"Area tegmentalis ventralis (Tsai)","human","Latin","ventral tegmental area",,1 2101,"Area tegmentalis, pars dorsalis","Macaca mulatta","Latin","field H1",,0 2102,"Area tegmentalis, pars dorsalis (Forel)","human","Latin","field H1",,0 1966,"Area tegmentalis, pars ventralis (Forel)","human","Latin","field H2",,0 -1118390063,"Area temporalis inferior","Cercopithecus","Latin",,"area 20 of Mauss-08",0 -438012330,"Area temporalis inferior","Cercopithecus","Latin",,"area 20 of Brodmann-09",0 318378271,"Area temporalis inferior","human","Latin",,"inferior temporal area 20",0 -1009774391,"Area temporalis media","Cercopithecus","Latin",,"area 21 of Mauss-08",0 -933459685,"Area temporalis media","Cercopithecus","Latin",,"area 21 of Brodmann-09",0 1024784485,"Area temporalis media","human","Latin",,"middle temporal area 21",0 -1198407743,"Area temporalis superior","Cercopithecus","Latin",,"area 22 of Mauss-08",0 -2074453801,"Area temporalis superior","human","Latin",,"superior temporal area 22",0 1984471233,"Area temporalis superior","Cercopithecus","Latin",,"area 22 of Brodmann-09",0 957471476,"Area temporalis transversa anterior","human","Latin",,"anterior transverse temporal area 41 (H)",0 -163109567,"Area temporalis transversa externa","human","Latin",,"posterior transverse temporal area 42 (H)",0 198882533,"Area temporalis transversa interna","human","Latin",,"anterior transverse temporal area 41 (H)",0 223232576,"Area temporalis transversa posterior","human","Latin",,"posterior transverse temporal area 42 (H)",0 1559906037,"Area temporopolaris","human","Latin",,"temporopolar area 38 (H)",0 3719,"Area transitoria amygdalo-striatalis","human","Latin",,"amygdalostriate transition area",0 3647,"Area transitoria cortico-amygdalaris","human","Latin",,"corticoamygdalar transition area",0 955931397,"Area triangularis","human","Latin",,"triangular area 45",6 1106,"Area triangularis (Wernicke)","human","Latin",,"triangular area (Wernicke)",0 1285,"Area vestibularis","human","Latin","vestibular area",,1 1290,"Area X","Macaca fascicularis","English","area X",,254 1288,"area X","human","English","area X",,254 1289,"Area X","Macaca mulatta","English","area X",,254 1291,"Area X of Olszewski","Macaca fuscata","English","area X",,5 790,"areal maps of cortex","human","English",,"cortical maps",0 1111,"areas of Brodmann","human","English",,"Brodmann's areas",0 1115,"areas of Economo","human","English",,"Economo's areas",0 3384,"ascending activating system","human","English",,"ascending reticular activating system",0 6402,"ascending branch of lateral sulcus","human","English","anterior ascending limb of lateral sulcus (H)",,0 2168,"ascending fibers of facial nerve","rat","English","ascending fibers of facial nerve",,0 2167,"ascending fibers of facial nerve","Unspecified","English","ascending fibers of facial nerve",,0 6396,"ascending ramus of Sylvian fissure","human","English","anterior ascending limb of lateral sulcus (H)",,0 3382,"ascending reticular activating system","human","English",,"ascending reticular activating system",0 3385,"ascending reticular system","human","English",,"ascending reticular activating system",0 6413,"ascending terminal ramus of Sylvian fissure","human","English","posterior ascending limb of lateral sulcus (H)",,0 788,"association areas of cortex","human","English",,"association cortex",0 787,"association cortex","human","English",,"association cortex",564 7130,"association nuclear group","human","English",,"association nuclear group",0 3433,"association nuclei of thalamus","human","English",,"thalamic association nuclei",0 6948,"atrium of lateral ventricle","human","English","collateral trigone",,0 6949,"Atrium ventriculi lateralis","human","Latin","collateral trigone",,0 1238,"auditory area","human","English",,"auditory cortex",120 972406608,"auditory association area","human","English",,"posterior transverse temporal area 42 (H)",0 1219,"auditory association cortex","human","English",,"auditory association cortex",38 1237,"auditory cortex","human","English",,"auditory cortex",2955 3481,"auditory ganglion","human","English",,"spiral ganglion",0 3252,"auditory nerve","human","English",,"cochlear nerve",1599 1225,"auditory parasensory association cortex","Macaca mulatta","English",,"auditory association cortex",0 1224,"auditory parasensory association cortex","human","English",,"auditory association cortex",0 5862,"auditory radiation","human","English",,"auditory radiation",10 6989,"auditory tubercle","human","English","acoustic tubercle",,1 3377,"autonomic nervous system","human","English",,"autonomic nervous system",14164 3376,"autonomic nervous system","human","English",,"autonomic nervous system",14164 3868,"AV","human","Abbreviation","anteroventral nucleus",,0 3867,"AV","Macaca mulatta","Abbreviation","anteroventral nucleus",,0 1318,"band of Gennari","human","English",,"band of Gennari",0 1301,"band of Giacomini","human","English",,"band of Giacomini",0 1300,"band of Giacomini","human","English",,"band of Giacomini",0 1303,"band of Kaes-Bechterew","human","English",,"band of Kaes-Bechterew",0 3889,"Bandeletta diagonalis","human","Latin","diagonal band",,1 1302,"Bandeletta Giacomini","human","Latin",,"band of Giacomini",0 1308,"bands of Baillarger","human","English",,"bands of Baillarger",0 3648,"basal amygdaloid nucleus","human","English","BASAL AMYGDALOID NUCLEUS",,24 3649,"basal amygdaloid nucleus","Macaca fascicularis","English","BASAL AMYGDALOID NUCLEUS",,24 3770,"basal amygdaloid nucleus, lateral part, parvocellular part","Unspecified","English",,"parvicellular division of basal nucleus (Amaral)",0 3663,"basal amygdaloid nucleus, medial part","Unspecified","English","accessory basal amygdaloid nucleus",,0 3769,"basal amygdaloid nucleus, medial part, deep portion","Unspecified","English",,"parvicellular division of basal nucleus (Amaral)",0 1375,"basal forebrain bundle","reptile","English",,"basal forebrain bundle",0 1376,"basal forebrain fasciculus","bird","English",,"basal forebrain bundle",0 3467,"basal ganglia","Unspecified","English","BASAL GANGLIA",,11794 3470,"basal ganglia (anatomic)","human","English","BASAL GANGLIA",,0 3478,"basal ganglia (Carpenter)","human","English",,"basal ganglia (Carpenter)",0 3476,"basal ganglia (clinical)","human","English",,"basal ganglia (clinical)",0 3472,"basal ganglia (Crosby)","human","English",,"basal ganglia (Crosby)",0 3479,"basal ganglia (Martin)","human","English",,"basal ganglia (Martin)",0 2952,"basal lamina","human","English",,"basal lamina",4379 3913,"basal magnocellular nucleus (substantia innominata)","human","English","basal nucleus",,0 3471,"basal nuclei","human","English","BASAL GANGLIA",,198 3912,"basal nuclei of Meynert","human","English","basal nucleus",,4 3906,"basal nucleus","Macaca fascicularis","English","basal nucleus",,395 3907,"basal nucleus","rat","English","basal nucleus",,395 3766,"basal nucleus of amygdala (Amaral)","Macaca fascicularis","English",,"basal nucleus of amygdala (Amaral)",0 3909,"basal nucleus of Meynert","human","English","basal nucleus",,200 3910,"basal nucleus of Meynert","human","English","basal nucleus",,200 5975,"basal olfactory structures","human","English",,"rhinencephalon",0 2734,"basal operculum","human","English",,"basal operculum",0 7044,"basal optic root","human","English",,"basal optic root",0 350,"basal part of midbrain","human","English",,"basal part of midbrain",0 5691,"basal part of pons","Macaca fascicularis","English","BASAL PART OF PONS",,0 5690,"basal part of pons","human","English","BASAL PART OF PONS",,0 3405,"basal plate","human","English",,"basal plate",251 355,"basal portion of midbrain","human","English",,"basal part of midbrain",0 5697,"basal portion of pons","human","English","BASAL PART OF PONS",,0 1283,"basal tegmental gray","human","English",,"ventral tegmental gray",0 5696,"base of pons","human","English","BASAL PART OF PONS",,2 1324,"baseline of Reid","human","English",,"Frankfurt zero plane",0 -1031597382,"Basihorizontal zeroplane","Macaca mulatta","English",,"Frankfurt zero plane",0 6223,"basilar sulcus","human","English","basilar sulcus",,2 1736,"Basis cerebri (Oertel)","Macaca mulatta","Latin","cerebral crus",,0 352,"Basis mesencephali","human","Latin",,"basal part of midbrain",0 1737,"Basis pedunculi (Oertel)","Macaca mulatta","Latin","cerebral crus",,0 351,"Basis pedunculi cerebri","human","Latin",,"basal part of midbrain",0 1735,"Basis pedunculi cerebri (Willis)","human","Latin","cerebral crus",,0 353,"Basis pedunculorum","human","Latin",,"basal part of midbrain",0 2088393685,"basis pedunculorum cerebralium","human","Latin",,"basal part of midbrain",0 5698,"Basis pontis","human","Latin","BASAL PART OF PONS",,103 3655,"basolateral amygdaloid nucleus","rat","English","BASAL AMYGDALOID NUCLEUS",,111 3654,"basolateral amygdaloid nucleus","human","English","BASAL AMYGDALOID NUCLEUS",,111 1329,"basolateral nuclear group","human","English","BASOLATERAL NUCLEAR GROUP",,2 1330,"basolateral nuclear group","Macaca fascicularis","English","BASOLATERAL NUCLEAR GROUP",,2 -667954265,"basolateral nuclear group - not otherwise specified","Unspecified","English","BASOLATERAL NUCLEAR GROUP - not otherwise specified",,2 3656,"basolateral nucleus (De Olmos)","human","English","BASAL AMYGDALOID NUCLEUS",,0 3668,"basomedial amygdaloid nucleus","human","English","accessory basal amygdaloid nucleus",,2 3669,"basomedial amygdaloid nucleus","rat","English","accessory basal amygdaloid nucleus",,2 3666,"basomedial nucleus (De Olmos)","human","English","accessory basal amygdaloid nucleus",,0 4025,"bed nucleus of anterior commissure","human","English","nucleus of anterior commissure",,2 4026,"bed nucleus of anterior commissure","Macaca fuscata","English","nucleus of anterior commissure",,2 4027,"bed nucleus of anterior commissure","rat","English","nucleus of anterior commissure",,2 5207,"bed nucleus of stria terminalis","human","English","nucleus of stria terminalis",,114 5208,"bed nucleus of stria terminalis","rat","English","nucleus of stria terminalis",,114 4024,"bed nucleus of the anterior commissure","human","English","nucleus of anterior commissure",,17 35,"between brain","human","English","DIENCEPHALON",,1088 239,"bicommissural line","human","English",,"bicommissural line",3 240,"bicommissural line","Macaca fascicularis","English",,"bicommissural line",3 5644,"biventer lobule","human","English","biventer lobule",,0 5645,"biventer lobule","Macaca fascicularis","English","biventer lobule",,0 5650,"biventral lobule","human","English","biventer lobule",,4 1658,"body of caudate nucleus","human","English","body of caudate nucleus",,5 1659,"body of caudate nucleus","Macaca fascicularis","English","body of caudate nucleus",,5 142,"body of corpus callosum","Macaca fascicularis","English","body of corpus callosum",,5 141,"body of corpus callosum","human","English","body of corpus callosum",,5 5237,"body of Forel","human","English","subthalamic nucleus",,0 1678,"body of fornix","Macaca fascicularis","English","body of fornix",,0 1677,"body of fornix","human","English","body of fornix",,0 1662,"body of lateral ventricle","human","English","body of lateral ventricle",,5 1663,"body of lateral ventricle","Macaca fascicularis","English","body of lateral ventricle",,5 5239,"body of Luys","human","English","subthalamic nucleus",,4 1117,"Bonin and Bailey's areas","human","English",,"Bonin and Bailey's areas",0 1553,"brachiomotor fibers","human","English",,"special visceral efferents",0 1344,"Brachium colliculi caudalis","human","Latin","brachium of inferior colliculus",,0 -553301111,"Brachium colliculi cranialis","human","Latin","brachium of superior colliculus",,0 1342,"Brachium colliculi inferioris","human","Latin","brachium of inferior colliculus",,1 1343,"Brachium colliculi inferioris","Macaca fascicularis","Latin","brachium of inferior colliculus",,1 1356,"Brachium colliculi rostralis","human","Latin","brachium of superior colliculus",,0 1354,"Brachium colliculi superioris","human","Latin","brachium of superior colliculus",,2 1355,"Brachium colliculi superioris","Macaca fascicularis","Latin","brachium of superior colliculus",,2 1892479954,"Brachium conjunctivum","Macaca fascicularis","Latin",,"superior cerebellar peduncle",165 -1363489099,"Brachium conjunctivum","human","Latin",,"superior cerebellar peduncle",165 1339,"brachium of inferior colliculus","human","English","brachium of inferior colliculus",,1 1340,"brachium of inferior colliculus","Macaca fascicularis","English","brachium of inferior colliculus",,1 1341,"brachium of inferior colliculus","rat","English","brachium of inferior colliculus",,1 1349,"brachium of medial geniculate","human","English","brachium of inferior colliculus",,0 1353,"brachium of superior colliculus","rat","English","brachium of superior colliculus",,0 1351,"brachium of superior colliculus","human","English","brachium of superior colliculus",,0 1352,"brachium of superior colliculus","Macaca fascicularis","English","brachium of superior colliculus",,0 485,"Brachium pontis","Macaca fascicularis","Latin","middle cerebellar peduncle",,34 1345,"Brachium quadrigeminum inferius","Macaca mulatta","Latin","brachium of inferior colliculus",,0 1357,"Brachium quadrigeminum superius","Macaca mulatta","Latin","brachium of superior colliculus",,0 19,"brain","human","English","BRAIN",,423036 641,"brain sand","human","English",,"brain sand",5 6974,"brain stem","human","English",,"brain stem",26444 6976,"brainstem","human","English",,"brain stem",15943 2160,"branchiomeric cranial nerve","human","English","facial nerve",,0 4287,"branchiomotor nucleus of facial nerve","human","English","facial motor nucleus",,0 1096,"Broca's area","human","English",,"Broca's area",0 3881,"Broca's diagonal gyrus","human","English","diagonal band",,0 1097,"Broca's speech area","human","English",,"Broca's area",0 1181,"Brodmann's area 18","human","English",,"parastriate area 18",0 1191,"Brodmann's area 19","human","English",,"peristriate area 19",0 1005,"Brodmann's area 25","human","English",,"subgenual area 25",0 523575139,"Brodmann's area 25","Macaca mulatta","English",,"area 25 of Brodmann-09",0 1275698262,"Brodmann's area 29","Macaca mulatta","English",,"granular retrolimbic area 29",0 1023,"Brodmann's area 30","human","English",,"agranular retrolimbic area 30",0 971,"Brodmann's area 31","human","English",,"dorsal posterior cingulate area 31",0 999,"Brodmann's area 33","human","English",,"pregenual area 33",0 1727,"Brodmann's area 35","human","English",,"perirhinal area 35",0 1251,"Brodmann's area 48","human","English",,"retrosubicular area 48",0 1110,"Brodmann's areas","human","English",,"Brodmann's areas",0 1112,"Brodmann's cortical areas","human","English",,"Brodmann's areas",0 3295,"bulbar accessory nerve","human","English","cranial part of accessory nerve",,0 3312,"bulbar accessory nucleus","human","English",,"nucleus of bulbar accessory nerve",0 3296,"bulbar part of accessory nerve","human","English","cranial part of accessory nerve",,0 2449,"bulbar reticular formation","human","English","MEDULLARY RETICULAR FORMATION",,94 44,"Bulbus","human","Latin","MEDULLA OBLONGATA",,332 1361,"Bulbus cornus occipitalis","human","Latin",,"Bulbus cornus occipitalis",0 1362,"Bulbus cornus posterioris","human","Latin",,"Bulbus cornus occipitalis",0 1365,"Bulbus olfactorius","human","Latin","olfactory bulb",,42 1366,"Bulbus olfactorius","Macaca mulatta","Latin","olfactory bulb",,42 1389,"bundle of Probst","human","English",,"bundle of Probst",0 1983,"bundle of Schutz","human","English",,"dorsal longitudinal fasciculus",0 6723,"bundle of Turck","human","English","ventral corticospinal tract",,2 2214,"bundle of Turck","human","English",,"temporopontine fibers",2 2058,"bundle of Vicq d'Azyr","human","English",,"mammillothalamic tract",0 4191,"Burdach's nucleus","Unspecified","English","cuneate nucleus",,0 2392,"CA1 field","human","English","CA1 field",,280 2395,"CA1 field of hippocampus","human","Latin","CA1 field",,8 2396,"CA2 field","human","English","CA2 field",,13 2398,"CA2 field of hippocampus","human","English","CA2 field",,0 2399,"CA3 field","human","English","CA3 field",,103 2401,"CA3 field of hippocampus","human","English","CA3 field",,7 1391,"calamus scriptorius","human","English","calamus scriptorius",,23 1392,"Calamus scriptorius","human","Latin","calamus scriptorius",,23 1393,"calcar avis","human","English","calcar avis",,4 1394,"Calcar avis","human","Latin","calcar avis",,4 1202046839,"Calcar sulci arcuati","Unspecified","Latin","spur of arcuate sulcus (M)",,0 815,"calcarine cortex","human","English",,"striate area 17",75 6231,"calcarine fissure","Macaca mulatta","English","calcarine sulcus",,68 6230,"calcarine fissure","human","English","calcarine sulcus",,68 6226,"calcarine sulcus","human","English","calcarine sulcus",,27 6227,"calcarine sulcus","Macaca mulatta","English","calcarine sulcus",,27 6308,"callosal sulcus","Macaca fascicularis","English","callosal sulcus",,12 6307,"callosal sulcus","human","English","callosal sulcus",,12 6281,"callosomarginal fissure","human","English","cingulate sulcus",,0 2591,"callosomarginal gyrus","human","English",,"cingulate gyrus (Crosby)",0 6280,"callosomarginal sulcus","human","English","cingulate sulcus",,0 6282,"calloso-marginal sulcus","human","English","cingulate sulcus",,0 2098,"Campus Foreli (pars dorsalis)","Macaca fascicularis","Latin","field H1",,0 1963,"Campus Foreli (pars ventralis)","Macaca fascicularis","Latin","field H2",,0 1397,"Campus Forelli","Macaca fascicularis","Latin",,"fields of Forel",0 1423,"Canalis centralis","Macaca fascicularis","Latin","central canal",,4 1422,"Canalis centralis","human","Latin","central canal",,4 1436,"Capsula corporis geniculati medialis","human","Latin","capsule of medial geniculate body",,0 5245,"Capsula corporis subthalamici","human","Latin","capsule of subthalamic nucleus",,0 1427,"Capsula externa","human","Latin","external capsule",,6 1428,"Capsula externa","Macaca fascicularis","Latin","external capsule",,6 1432,"Capsula extrema","Macaca fascicularis","Latin","extreme capsule",,2 1431,"Capsula extrema","human","Latin","extreme capsule",,2 132,"Capsula interna","human","Latin","INTERNAL CAPSULE",,50 133,"Capsula interna","Macaca fascicularis","Latin","INTERNAL CAPSULE",,50 1731,"Capsula interna, pars anterior","human","Latin","anterior limb of internal capsule",,0 1757,"Capsula interna, pars posterior","human","Latin","POSTERIOR LIMB OF INTERNAL CAPSULE",,0 5686,"Capsula interna, pars sublenticularis","human","Latin","sublenticular part of internal capsule",,0 2508,"Capsula internal, genu","human","Latin","genu of internal capsule",,0 5656,"Capsula nuclei rubris tegmenti","human","Latin","capsule of red nucleus",,0 5244,"Capsula nuclei subthalamici","human","Latin","capsule of subthalamic nucleus",,0 1433,"capsule of anterior nuclei","Macaca mulatta","English",,"capsule of anterior nuclei",0 5660,"capsule of inferior colliculus","human","English",,"capsule of inferior colliculus",0 1435,"capsule of medial geniculate body","Macaca fascicularis","English","capsule of medial geniculate body",,0 1434,"capsule of medial geniculate body","human","English","capsule of medial geniculate body",,0 4450,"capsule of nucleus lateralis dorsalis","Macaca mulatta","English",,"capsule of nucleus lateralis dorsalis",0 5653,"capsule of red nucleus","human","English","capsule of red nucleus",,0 5655,"capsule of red nucleus","rat","English","capsule of red nucleus",,0 5654,"capsule of red nucleus","Macaca fascicularis","English","capsule of red nucleus",,0 5243,"capsule of subthalamic nucleus","human","English","capsule of subthalamic nucleus",,0 1439,"Caput (caudatus)","human","Latin","head of caudate nucleus",,0 1440,"Caput nuclei caudati","human","Latin","head of caudate nucleus",,6 1443,"Cauda (caudatus)","human","Latin","tail of caudate nucleus",,0 7096,"Cauda equina","human","Latin",,"Cauda equina",2091 1444,"Cauda nuclei caudati","human","Latin","tail of caudate nucleus",,0 4606,"caudal central nucleus","human","English","caudal central oculomotor nucleus",,7 4605,"caudal central nucleus of oculomotor nerve","human","English","caudal central oculomotor nucleus",,0 4603,"caudal central oculomotor nucleus","human","English","caudal central oculomotor nucleus",,0 374,"caudal colliculus","human","English","INFERIOR COLLICULUS",,13 1135,"caudal commissure","human","English","posterior commissure",,1 5314,"caudal magnocellular nucleus","human","English","tuberomammillary nucleus",,13 5185,"caudal nucleus (Kandell)","human","English","caudal part of spinal trigeminal nucleus",,0 5581,"caudal nucleus of zona incerta","human","English",,"caudal nucleus of zona incerta",0 5181,"caudal part of spinal trigeminal nucleus","Macaca fascicularis","English","caudal part of spinal trigeminal nucleus",,0 5180,"caudal part of spinal trigeminal nucleus","human","English","caudal part of spinal trigeminal nucleus",,0 5372,"caudal part of ventral lateral nucleus","Macaca fascicularis","English","caudal part of ventral lateral nucleus",,0 5371,"caudal part of ventral lateral nucleus","human","English","caudal part of ventral lateral nucleus",,0 5447,"caudal part of ventral posterolateral nucleus","Macaca fascicularis","English","caudal part of ventral posterolateral nucleus",,0 5446,"caudal part of ventral posterolateral nucleus","human","English","caudal part of ventral posterolateral nucleus",,0 3313,"caudal pole of nucleus ambiguus","human","English",,"nucleus of bulbar accessory nerve",0 5042,"caudal pontine reticular nucleus","Unspecified","English","caudal pontine reticular nucleus",,41 824,"caudal postcentral area 2","human","English",,"caudal postcentral area 2",0 435694386,"caudal thalamic peduncle","human","English","inferior thalamic peduncle",,0 323104091,"caudal vestibular nucleus","human","English","inferior vestibular nucleus",,0 114,"caudate nucleus","Macaca fascicularis","English","CAUDATE NUCLEUS",,7702 113,"caudate nucleus","human","English","CAUDATE NUCLEUS",,7702 1712,"caudate putamen","rat","English","STRIATUM",,2709 3522,"caudate-lenticular complex","human","English",,"caudate-lenticular complex",0 731596848,"caudato-lenticular limb","human","English","anterior limb of internal capsule",,0 116,"Caudatus","human","Latin","CAUDATE NUCLEUS",,443 1713,"caudoputamen","rat","English","STRIATUM",,206 1453,"cave of septum pellucidum","human","English","cave of septum pellucidum",,0 1455,"cavum of septum pellucidum","human","English","cave of septum pellucidum",,0 1454,"Cavum septi pellucidi","human","Latin","cave of septum pellucidum",,89 1459,"Cavum trigeminale","human","Latin",,"Meckel's cave",0 4248,"cell column of Clarke","human","English",,"dorsal nucleus of Clarke",0 4742,"cell group B7","human","English","dorsal raphe nucleus",,1 3940,"cell group B8","human","English","superior central nucleus",,0 1460,"cell group f","human","English",,"cell group f",0 1461,"cell group y","human","English",,"cell group y",0 1146660374,"cella media ventriculi lateralis","human","Latin","body of lateral ventricle",,0 6131,"central (periaqueductal) gray","rat","English","central gray substance of midbrain",,4 3696,"central amygdaloid nucleus","rat","English","central amygdaloid nucleus",,235 3695,"central amygdaloid nucleus","Macaca fascicularis","English","central amygdaloid nucleus",,235 3694,"central amygdaloid nucleus","human","English","central amygdaloid nucleus",,235 1420,"central canal","Macaca fascicularis","English","central canal",,763 1419,"central canal","human","English","central canal",,763 1421,"central canal","rat","English","central canal",,763 7131,"central cervical nuclear group","human","English",,"central cervical nuclear group",0 7217,"central cervical nucleus","human","English",,"central cervical nucleus",0 3969,"central dorsal nucleus","Macaca fascicularis","English","central dorsal nucleus",,0 6255,"central fissure","human","English","central sulcus",,31 6264,"central fissure of insula","human","English","central insular sulcus",,0 6263,"central fissure of island","human","English","central insular sulcus",,0 7134,"central gelatinous substance","human","English",,"central gelatinous substance",0 7122,"central gray columns","human","English",,"central gray columns",0 6137,"central gray of pons","rat","English","central gray substance of pons",,0 6110,"central gray substance","human","English",,"central gray substance",71 6140,"central gray substance of medulla","Macaca fascicularis","English","central gray substance of medulla",,0 6139,"central gray substance of medulla","human","English","central gray substance of medulla",,0 6115,"central gray substance of midbrain","human","English","central gray substance of midbrain",,1 6116,"central gray substance of midbrain","Macaca fascicularis","English","central gray substance of midbrain",,1 6133,"central gray substance of pons","Macaca fascicularis","English","central gray substance of pons",,0 6132,"central gray substance of pons","human","English","central gray substance of pons",,0 2472,"central group (medullary reticular formation)","human","English","CENTRAL MEDULLARY RETICULAR GROUP",,0 6261,"central insula sulcus","human","English","central insular sulcus",,0 6258,"central insular sulcus","Papio","English","central insular sulcus",,2 6259,"central insular sulcus","human","English","central insular sulcus",,2 3949,"central lateral nucleus","Macaca fascicularis","English","central lateral nucleus",,71 3948,"central lateral nucleus","human","English","central lateral nucleus",,71 3955,"central lateral nucleus of thalamus","rat","English","central lateral nucleus",,0 3954,"central lateral nucleus of thalamus","human","English","central lateral nucleus",,0 3951,"central lateral thalamic nucleus","human","English","central lateral nucleus",,4 3952,"central lateral thalamic nucleus","rat","English","central lateral nucleus",,4 87,"central lobe","human","English","INSULA",,24 677,"central lobule","human","English","alar central lobule",,12 668,"central lobule","human","English","central lobule",,12 670,"central lobule","rat","English","central lobule",,12 669,"central lobule","Macaca fascicularis","English","central lobule",,12 672,"central lobule of cerebellum","human","English","central lobule",,0 3991,"central magnocellular nucleus of thalamus","human","English","centromedian nucleus",,0 3958,"central medial nucleus","human","English","central medial nucleus",,35 3959,"central medial nucleus","Macaca fascicularis","English","central medial nucleus",,35 3967,"central medial nucleus (Jones)","human","English",,"commissural nucleus of thalamus",0 3968,"central medial nucleus (Jones)","Macaca","English",,"commissural nucleus of thalamus",0 3964,"central medial nucleus of thalamus","rat","English","central medial nucleus",,0 3962,"central medial thalamic nucleus","human","English","central medial nucleus",,11 3963,"central medial thalamic nucleus","rat","English","central medial nucleus",,11 2470,"central medullary reticular group","Macaca fascicularis","English","CENTRAL MEDULLARY RETICULAR GROUP",,0 2469,"central medullary reticular group","human","English","CENTRAL MEDULLARY RETICULAR GROUP",,0 3367,"central nervous system","human","English",,"central nervous system",72315 7123,"central nuclear group","human","English",,"central nuclear group",0 512,"central nuclei","human","English","DEEP CEREBELLAR NUCLEI",,294 3698,"central nucleus of amygdala","rat","English","central amygdaloid nucleus",,47 3697,"central nucleus of amygdala","Macaca fascicularis","English","central amygdaloid nucleus",,47 3705,"central nucleus of amygdala (Lauer)","Unspecified","English",,"lateral division of central nucleus of amygdala",0 3923,"central nucleus of inferior colliculus","rat","English","central nucleus of inferior colliculus",,11 3921,"central nucleus of inferior colliculus","human","English","central nucleus of inferior colliculus",,11 3922,"central nucleus of inferior colliculus","Macaca fascicularis","English","central nucleus of inferior colliculus",,11 7095,"central nucleus of lumbosacral enlargement","human","English",,"lumbosacral nucleus",0 3930,"central nucleus of Perlia","human","English","central oculomotor nucleus",,0 3994,"central nucleus-1","human","English","centromedian nucleus",,0 3928,"central oculomotor nucleus","Macaca fascicularis","English","central oculomotor nucleus",,1 3245,"central part of abducens nerve","rat","English","abducens nerve fibers",,0 2166,"central part of facial nerve","rat","English","FACIAL NERVE FIBERS",,0 3354,"central part of glossopharyngeal nerve","rat","English","glossopharyngeal nerve fibers",,0 300,"central part of hypoglossal nerve","rat","English","hypoglossal nerve fibers",,0 1669,"central part of lateral ventricle","human","English","body of lateral ventricle",,2 288,"central part of oculomotor nerve","rat","English","oculomotor nerve fibers",,0 3323,"central part of trigeminal nerve","rat","English","trigeminal nerve fibers",,0 324,"central part of trochlear nerve","rat","English","trochlear nerve fibers",,0 3349,"central part of vagus nerve","rat","English","vagal nerve fibers",,0 308,"central part of vestibulocochlear nerve","rat","English","vestibulocochlear nerve fibers",,0 6250,"central sulcus","human","English","central sulcus",,345 6251,"central sulcus","Macaca mulatta","English","central sulcus",,345 6262,"central sulcus of insula","human","English","central insular sulcus",,0 6254,"central sulcus of Rolando","Macaca fascicularis","English","central sulcus",,0 6900,"central tegmental bundle","rat","English",,"central tegmental tract",0 6899,"central tegmental bundle","human","English",,"central tegmental tract",0 6898,"central tegmental fasciculus","human","English",,"central tegmental tract",0 6893,"central tegmental tract","human","English",,"central tegmental tract",52 6894,"central tegmental tract","rat","English",,"central tegmental tract",52 6904,"central tegmental tract of midbrain","Macaca fascicularis","English","central tegmental tract of midbrain",,0 6902,"central tegmental tract of pons","Macaca fascicularis","English","central tegmental tract of pons",,0 6928,"central trigeminal tract","human","English",,"trigeminal lemniscus",0 3996,"centre median nucleus","human","English","centromedian nucleus",,17 7208,"centrobasal nucleus","human","English",,"centrobasal nucleus",0 3956,"centrolateral thalamic nucleus","rat","English","central lateral nucleus",,5 3984,"centromedian nucleus","Macaca fascicularis","English","centromedian nucleus",,42 3983,"centromedian nucleus","human","English","centromedian nucleus",,42 3990,"centromedian thalamic nucleus","human","English","centromedian nucleus",,10 4679,"centromedian-parafascicular nuclear complex","human","English",,"centromedian-parafascicular nuclear complex",0 5747,"centroparietal peduncle","human","English","superior thalamic peduncle",,0 5745,"centroparietal thalamic peduncle","human","English","superior thalamic peduncle",,0 3988,"Centrum medianum","Macaca fascicularis","Latin","centromedian nucleus",,126 3987,"Centrum medianum thalami","Macaca fascicularis","Latin","centromedian nucleus",,4 1468,"Centrum ovale","human","Latin","semioval center",,28 1463,"Centrum semiovale","human","Latin","semioval center",,253 2340,"cephalic flexure","human","English",,"cephalic flexure",8 3607,"cerebellar channel of motor thalamus","Macaca","English",,"posterior region of motor thalamus",0 3606,"cerebellar channel of motor thalamus","human","English",,"posterior region of motor thalamus",0 449,"cerebellar cortex","Macaca fascicularis","English","CEREBELLAR CORTEX",,4065 450,"cerebellar cortex","rat","English","CEREBELLAR CORTEX",,4065 448,"cerebellar cortex","human","English","CEREBELLAR CORTEX",,4065 1913,"cerebellar fiber tracts","human","English",,"cerebellar fiber tracts",0 2261,"cerebellar fissures","human","English",,"cerebellar fissures",13 2346,"cerebellar folia","human","English",,"cerebellar folia",73 2842,"cerebellar hemisphere","human","English",,"cerebellar hemisphere",554 5700,"cerebellar peduncles","human","English",,"cerebellar peduncles",0 3407,"cerebellar plate","human","English",,"cerebellar plate",0 6689,"cerebellar tentorium","human","English",,"cerebellar tentorium",31 6692,"cerebellar tonsil","Macaca fascicularis","English","cerebellar tonsil",,17 6691,"cerebellar tonsil","human","English","cerebellar tonsil",,17 1784,"cerebellar vermis","human","English",,"vermis of cerebellum",810 452,"cerebellar white matter","Macaca fascicularis","English","CEREBELLAR WHITE MATTER",,297 1492,"cerebellomedullary cistern","human","English","cerebellomedullary cistern",,30 730,"cerebellopontine angle","human","English","cerebellopontine angle",,2042 2195,"cerebellorubral tract","human","English",,"dentatorubral fibers",0 502,"cerebello-rubro-thalamic fibers","human","English",,"cerebellorubrothalamic tract",0 499,"cerebellorubrothalamic tract","human","English",,"cerebellorubrothalamic tract",0 2133,"cerebellospinal tract","human","English","uncinate fasciculus of pons",,2 -1154251380,"cerebellothalamic tract","human","English",,"cerebellorubrothalamic tract",0 443,"cerebellum","human","English","CEREBELLUM",,31023 445,"Cerebellum","Macaca fascicularis","Latin","CEREBELLUM",,31023 444,"Cerebellum","human","Latin","CEREBELLUM",,31023 937147219,"cerebellum - not otherwise specified","Unspecified","English","CEREBELLUM - not otherwise specified",,31023 -1314095208,"Cerebellum - not otherwise specified","Unspecified","Latin","CEREBELLUM - not otherwise specified",,31023 334,"cerebral aqueduct","human","English","cerebral aqueduct",,815 335,"cerebral aqueduct","Macaca fascicularis","English","cerebral aqueduct",,815 336,"cerebral aqueduct","rat","English","cerebral aqueduct",,815 348,"cerebral aqueduct (Sylvius)","human","English","cerebral aqueduct",,0 347,"cerebral aqueduct of Sylvius","human","English","cerebral aqueduct",,0 3387,"cerebral association fibers","human","English",,"cerebral association fibers",0 3389,"cerebral commissural fibers","human","English",,"cerebral commissural fibers",0 46,"cerebral cortex","human","English","CEREBRAL CORTEX",,56049 47,"cerebral cortex","Macaca mulatta","English","CEREBRAL CORTEX",,56049 1732,"cerebral crus","human","English","cerebral crus",,1 1733,"cerebral crus","Macaca fascicularis","English","cerebral crus",,1 2558,"cerebral gyri","human","English",,"cerebral gyri",0 2110,"cerebral hemisphere","human","English",,"cerebral hemisphere",1871 3124,"cerebral lobes","human","English",,"cerebral lobes",0 3220,"cerebral neocortex","human","English",,"neocortex",186 251,"cerebral peduncle","human","English","CEREBRAL PEDUNCLE",,243 252,"cerebral peduncle","Macaca fascicularis","English","CEREBRAL PEDUNCLE",,243 1743,"cerebral peduncle (clinical definition)","human","English","cerebral crus",,0 256,"cerebral peduncle (Hensyl)","human","English",,"cerebral peduncle (Hensyl)",0 3391,"cerebral projection fibers","human","English",,"cerebral projection fibers",0 6203,"cerebral sulci","human","English",,"cerebral sulci",78 7053,"cerebral ventricles","human","English",,"ventricles of brain",9290 764,"cerebral vesicle","human","English",,"cerebral vesicle",0 7064,"cerebral white matter","human","English","CEREBRAL WHITE MATTER",,991 7065,"cerebral white matter","Macaca fascicularis","English","CEREBRAL WHITE MATTER",,991 -12267642,"cerebral white matter - not otherwise specified","Unspecified","English","CEREBRAL WHITE MATTER - not otherwise specified",,991 2332,"cerebrocerebellar fissure","Unspecified","English","cerebrocerebellar fissure",,0 2335,"cerebro-cerebellar fissure","human","English","cerebrocerebellar fissure",,0 539,"cerebrocerebellum","human","English","POSTERIOR LOBE OF CEREBELLUM",,1 2113,"cerebrum","human","English",,"cerebrum",2850 92,"cerveau isolé","Unspecified","English",,"cerveau isole",0 7091,"cervical enlargement","human","English",,"cervical enlargement",0 2339,"cervical flexure","human","English",,"cervical flexure",14 7156,"cervical segments","human","English",,"cervical segments",0 7157,"cervical segments of spinal cord","human","English",,"cervical segments",0 7240,"cervicothalamic fibers","human","English",,"cervicothalamic tract",0 7239,"cervicothalamic tract","human","English",,"cervicothalamic tract",5 1479,"Chiasma","human","Latin","optic chiasm",,711 1823,"Chiasma fibrorum proprium tecti","human","Latin","dorsal tegmental decussation",,0 1480,"Chiasma nervorum opticorum","Macaca fascicularis","Latin","optic chiasm",,0 1476,"Chiasma opticum","human","Latin","optic chiasm",,12 1477,"Chiasma opticum","Macaca nemestrina","Latin","optic chiasm",,12 5964,"chiasmal level of hypothalamus","human","English",,"supraoptic region",0 1505,"chiasmal ridge","human","English",,"chiasmal ridge",0 212,"chiasmal zone","human","English","ANTERIOR HYPOTHALAMIC REGION",,0 1502,"chiasmatic cistern","human","English","chiasmatic cistern",,23 4638,"chief inferior olivary nucleus","human","English","principal inferior olivary nucleus",,0 3925,"chief nucleus of inferior colliculus","human","English","central nucleus of inferior colliculus",,0 4669,"chief nucleus of superior olive","human","English","medial superior olivary nucleus",,0 -1576104411,"chief sensory nucleus","human","English","principal sensory nucleus of trigeminal nerve",,0 4668,"chief superior olivary nucleus","human","English","medial superior olivary nucleus",,0 5571,"chief vestibular nucleus","human","English","medial vestibular nucleus",,0 1482,"chorda tympani","human","English",,"chorda tympani",745 1483,"Chorda tympani","human","Latin",,"chorda tympani",745 2268,"chorioid fissure","human","English","choroidal fissure",,0 5773,"chorioid plexus","human","English",,"choroid plexus",14 5787,"chorioid plexus of fourth ventricle","human","English","choroid plexus of fourth ventricle",,0 5778,"chorioid plexus of lateral ventricle","human","English","choroid plexus of lateral ventricle",,0 5782,"chorioid plexus of third ventricle","human","English","choroid plexus of third ventricle",,0 2267,"choroid fissure","human","English","choroidal fissure",,39 5769,"choroid plexus","human","English",,"choroid plexus",4427 5783,"choroid plexus of fourth ventricle","human","English","choroid plexus of fourth ventricle",,0 5774,"choroid plexus of lateral ventricle","human","English","choroid plexus of lateral ventricle",,4 5779,"choroid plexus of third ventricle","human","English","choroid plexus of third ventricle",,0 2265,"choroidal fissure","human","English","choroidal fissure",,30 149,"ciliary body","human","English",,"ciliary body",4925 2089558478,"cingular gyrus","Macaca","English","CINGULATE GYRUS",,0 2586,"cingulate area","human","English","CINGULATE GYRUS",,70 805,"cingulate core","human","English",,"cingulate gigantopyramidal field",0 6283,"cingulate fissure","human","English","cingulate sulcus",,0 804,"cingulate gigantopyramidal field","human","English",,"cingulate gigantopyramidal field",0 2579,"cingulate gyrus","human","English","CINGULATE GYRUS",,520 2580,"cingulate gyrus","Macaca mulatta","English","CINGULATE GYRUS",,520 2590,"cingulate gyrus (Crosby)","human","English",,"cingulate gyrus (Crosby)",0 2588,"cingulate region","rat","English","CINGULATE GYRUS",,44 2587,"cingulate region","human","English","CINGULATE GYRUS",,44 1054,"cingulate region","human","English",,"cingulate region",44 6274,"cingulate sulcus","human","English","cingulate sulcus",,73 6275,"cingulate sulcus","Macaca mulatta","English","cingulate sulcus",,73 -120058171,"cingulate white matter","Unspecified","English","CINGULATE WHITE MATTER",,0 984,"cingulofrontal transition cortex","human","English",,"dorsal anterior cingulate area 32",0 970,"cinguloparietal transition area","human","English",,"dorsal posterior cingulate area 31",0 1484,"cingulum","human","English",,"cingulum",222 1486,"Cingulum","Macaca fascicularis","Latin",,"cingulum",222 1485,"Cingulum","human","Latin",,"cingulum",222 1487,"Cingulum ammonale","human","Latin",,"Cingulum ammonale",0 1488,"Cingulum limitans","human","Latin",,"Cingulum limitans",0 1491,"circle of Willis","human","English",,"circle of Willis",1138 6290,"circular fissure","human","English","circular sulcus of insula",,0 6288,"circular insular sulcus","human","English","circular sulcus of insula",,0 6287,"circular sulcus (of Reil)","human","English","circular sulcus of insula",,0 6285,"circular sulcus of insula","Macaca mulatta","English","circular sulcus of insula",,0 6284,"circular sulcus of insula","human","English","circular sulcus of insula",,0 6291,"circuminsular sulcus","human","English","circular sulcus of insula",,0 5602,"circumventricular organs","human","English",,"circumventricular organs",469 5601,"circumventricular organs","human","English",,"circumventricular organs",469 1500,"cistern of lamina terminalis","human","English","cistern of lamina terminalis",,0 1510,"Cisterna ambiens","human","Latin","superior cistern",,7 1494,"Cisterna cerebellomedullaris","human","Latin","cerebellomedullary cistern",,18 1496,"Cisterna cerebello-medullaris","human","Latin","cerebellomedullary cistern",,3 1503,"Cisterna chiasmatica","human","Latin","chiasmatic cistern",,0 1504,"Cisterna chiasmatis","human","Latin","chiasmatic cistern",,1 1511,"Cisterna colliculorum","human","Latin","superior cistern",,0 1498,"Cisterna interpeduncularis","human","Latin","interpeduncular cistern",,0 1501,"Cisterna laminae terminalis","human","Latin","cistern of lamina terminalis",,0 1493,"Cisterna magna","human","Latin","cerebellomedullary cistern",,1805 1514,"Cisterna pontis","human","Latin","pontine cistern",,13 1509,"Cisterna superior","human","Latin","superior cistern",,0 1499,"Cisternae intercruralis","human","Latin","interpeduncular cistern",,0 4247,"Clarke's column","human","English",,"dorsal nucleus of Clarke",0 4249,"Clarke's nucleus","human","English",,"dorsal nucleus of Clarke",0 3712,"claustral amygdaloid area","Unspecified","English","claustral amygdaloid area",,0 1515,"claustrum","human","English","claustrum",,575 1516,"claustrum","rat","English","claustrum",,575 1517,"Claustrum","human","Latin","claustrum",,575 1518,"Claustrum","Macaca fascicularis","Latin","claustrum",,575 3716,"claustrum diffusa","human","English","claustral amygdaloid area",,0 3717,"claustrum parvum","human","English","claustral amygdaloid area",,0 7002,"Clava","human","Latin","gracilis tubercle",,39 1779,"Clivus","human","Latin","declive",,599 1780,"Clivus-2","human","Latin","declive",,4 3371,"CNS","human","Abbreviation",,"central nervous system",0 7164,"coccygeal segments","human","English",,"coccygeal segments",17 7165,"coccygeal segments of spinal cord","human","English",,"coccygeal segments",0 3251,"cochlear division of acoustic nerve","human","English",,"cochlear nerve",0 3246,"cochlear nerve","human","English",,"cochlear nerve",2056 570,"cochlear nuclei","Macaca fascicularis","English","COCHLEAR NUCLEI",,429 571,"cochlear nuclei","rat","English","COCHLEAR NUCLEI",,429 569,"cochlear nuclei","human","English","COCHLEAR NUCLEI",,429 793125165,"COCHLEAR NUCLEI - not otherwise specified","Unspecified","English","COCHLEAR NUCLEI - not otherwise specified",,429 573,"cochlear nucleus","Macaca fascicularis","English","COCHLEAR NUCLEI",,1603 306,"cochlear-vestibular nerve","human","English","vestibulocochlear nerve fibers",,1 3263,"cochlear-vestibular nerve","human","English","vestibulocochlear nerve",,1 3261,"cochleovestibular nerve","human","English","vestibulocochlear nerve",,13 1886,"collateral eminence","human","English","collateral eminence",,1 6303,"collateral fissure","human","English","collateral sulcus",,1 6301,"collateral sulcus","Macaca mulatta","English","collateral sulcus",,25 6300,"collateral sulcus","human","English","collateral sulcus",,25 6946,"collateral trigone","human","English","collateral trigone",,2 386,"Colliculus bigeminalis oralis","human","Latin","SUPERIOR COLLICULUS",,0 367,"Colliculus caudalis","human","Latin","INFERIOR COLLICULUS",,2 1954023587,"Colliculus cranialis","human","Latin","SUPERIOR COLLICULUS",,0 1522,"Colliculus facialis","human","Latin","facial colliculus",,2 366,"Colliculus inferior","Macaca fascicularis","Latin","INFERIOR COLLICULUS",,36 365,"Colliculus inferior","human","Latin","INFERIOR COLLICULUS",,36 240402115,"Colliculus inferior - not otherwise specified","Unspecified","Latin","INFERIOR COLLICULUS - not otherwise specified",,36 3627,"Colliculus nuclei caudati","human","Latin","nucleus accumbens",,0 3626,"colliculus of caudate nucleus","human","English","nucleus accumbens",,0 385,"Colliculus rostralis","human","Latin","SUPERIOR COLLICULUS",,0 384,"Colliculus superior","Macaca fascicularis","Latin","SUPERIOR COLLICULUS",,60 383,"Colliculus superior","human","Latin","SUPERIOR COLLICULUS",,60 965184124,"Colliculus superior - not otherwise specified","Unspecified","Latin","SUPERIOR COLLICULUS - not otherwise specified",,60 1524,"Colliculus superior, stratum intermedium","Macaca fuscata","Latin",,"Colliculus superior, stratum intermedium",0 1525,"Colliculus superior, stratum profundum","Macaca fuscata","Latin",,"Colliculus superior, stratum profundum",0 1531,"Colliculus superior, stratum superficiale","Macaca fuscata","Latin",,"Colliculus superior, stratum superficiale",0 1934,"column of Burdach","human","English",,"cuneate fasciculus",0 1681,"column of fornix","human","English","body of fornix",,1 1951,"column of Goll","human","English",,"gracile fasciculus",0 1682,"Columna fornicis","Macaca fascicularis","Latin","body of fornix",,5 6749,"comb bundle","human","English",,"nigrostriatal fibers",2 1745,"comb system","human","English",,"comb system",0 2002,"comma field of Schultze","human","English",,"comma tract of Schultze",0 1999,"comma tract of Schultze","human","English",,"comma tract of Schultze",0 155,"Commissura anterior","human","Latin","ANTERIOR COMMISSURE",,21 156,"Commissura anterior","Macaca fascicularis","Latin","ANTERIOR COMMISSURE",,21 -1494523425,"Commissura anterior - not otherwise specified","Unspecified","Latin","ANTERIOR COMMISSURE - not otherwise specified",,21 157,"Commissura anterior cerebri","human","Latin","ANTERIOR COMMISSURE",,0 1562,"Commissura anterior, crus anterius","human","Latin","anterior part of anterior commissure",,0 1572,"Commissura anterior, crus posterius","human","Latin","posterior part of anterior commissure",,0 1559,"Commissura anterior, pars anterior","human","Latin","anterior part of anterior commissure",,0 1560,"Commissura anterior, pars olfactoria","human","Latin","anterior part of anterior commissure",,0 1570,"Commissura anterior, pars posterior","human","Latin","posterior part of anterior commissure",,0 1577,"Commissura cerebellaris inferior","human","Latin",,"posterior cerebellar commissure",0 1588,"Commissura colliculi inferioris","human","Latin","commissure of inferior colliculus",,0 1589,"Commissura colliculi inferioris","Macaca fascicularis","Latin","commissure of inferior colliculus",,0 1599,"Commissura colliculi superior","Macaca mulatta","Latin","commissure of superior colliculus",,0 1597,"Commissura colliculi superioris","human","Latin","commissure of superior colliculus",,1 1598,"Commissura colliculi superioris","Macaca fascicularis","Latin","commissure of superior colliculus",,1 1587,"Commissura colliculorum caudalium","human","Latin","commissure of inferior colliculus",,0 1519063344,"Commissura colliculorum cranialium","human","Latin","commissure of superior colliculus",,0 1586,"Commissura colliculorum inferiorum","human","Latin","commissure of inferior colliculus",,0 1596,"Commissura colliculorum rostralium","human","Latin","commissure of superior colliculus",,0 1595,"Commissura colliculorum superiorum","human","Latin","commissure of superior colliculus",,0 1134,"Commissura epithalami","human","Latin","posterior commissure",,0 1133,"Commissura epithalamica","human","Latin","posterior commissure",,1 1603,"Commissura fornicis","human","Latin","commissure of fornix",,1 4343,"Commissura habenularis","human","Latin","habenular commissure",,1 4342,"Commissura habenularum","Macaca fascicularis","Latin","habenular commissure",,0 4341,"Commissura habenularum","human","Latin","habenular commissure",,0 1606,"Commissura hippocampalis dorsalis","human","Latin","commissure of fornix",,0 1604,"Commissura hippocampi","human","Latin","commissure of fornix",,2 1605,"Commissura hippocampi dorsalis","Macaca fascicularis","Latin","commissure of fornix",,0 1614,"Commissura hypothalamica anterior","human","Latin","anterior hypothalamic commissure",,0 4345,"Commissura infirma","human","Latin",,"inferior commissure of spinal cord",0 140,"Commissura magna","human","Latin","CORPUS CALLOSUM",,0 664,"Commissura media","human","Latin","interthalamic adhesion",,0 1132,"Commissura posterior","Macaca fascicularis","Latin","posterior commissure",,15 1131,"Commissura posterior","human","Latin","posterior commissure",,15 1561,"Commissura rostralis, pars anterior","human","Latin","anterior part of anterior commissure",,0 1571,"Commissura rostralis, pars posterior","human","Latin","posterior part of anterior commissure",,0 1620,"Commissura supramamillaris","Macaca fascicularis","Latin","supramammillary commissure",,0 1621,"Commissura supramammillaris","human","Latin","supramammillary commissure",,0 1799,"Commissura supraoptica dorsalis","human","Latin","dorsal supraoptic decussation",,1 1800,"Commissura supraoptica dorsalis","Macaca fascicularis","Latin","dorsal supraoptic decussation",,1 1615,"Commissura supraoptica dorsalis pars dorsalis","human","Latin","anterior hypothalamic commissure",,0 1806,"Commissura supraoptica dorsalis pars ventralis (Meynert)","human","Latin","dorsal supraoptic decussation",,0 1616,"Commissura supraoptica superior pars dorsalis","human","Latin","anterior hypothalamic commissure",,0 1810,"Commissura supraoptica ventralis","human","Latin","ventral supraoptic decussation",,0 7129,"commissural nuclear group","human","English",,"commissural nuclear group",0 7214,"commissural nucleus of spinal cord","human","English",,"commissural nucleus of spinal cord",0 3965,"commissural nucleus of thalamus","human","English",,"commissural nucleus of thalamus",0 4029,"commissural nucleus of vagus nerve","human","English","commissural nucleus of vagus nerve",,0 4033,"commissural nucleus-1","human","English","commissural nucleus of vagus nerve",,0 7215,"commissural nucleus-2","human","English",,"commissural nucleus of spinal cord",0 7040,"commissure of anterior medullary velum","human","English",,"decussation of superior medullary velum",0 1622,"commissure of Forel","human","English","supramammillary commissure",,0 1601,"commissure of fornix","human","English","commissure of fornix",,0 1602,"commissure of fornix","Macaca fascicularis","English","commissure of fornix",,0 1813,"commissure of Gudden","human","English","ventral supraoptic decussation",,0 4346,"commissure of Haller","human","English",,"inferior commissure of spinal cord",0 6047,"commissure of Held","human","English","intermediate acoustic stria",,0 1591,"commissure of inferior colliculi","human","English","commissure of inferior colliculus",,0 1585,"commissure of inferior colliculus","rat","English","commissure of inferior colliculus",,0 1584,"commissure of inferior colliculus","Macaca fascicularis","English","commissure of inferior colliculus",,0 1583,"commissure of inferior colliculus","human","English","commissure of inferior colliculus",,0 1802,"commissure of Meynert","human","English","dorsal supraoptic decussation",,1 4348,"commissure of Probst","human","English",,"commissure of Probst",0 1600,"commissure of superior colliculi","human","English","commissure of superior colliculus",,0 1594,"commissure of superior colliculus","rat","English","commissure of superior colliculus",,0 1593,"commissure of superior colliculus","Macaca fascicularis","English","commissure of superior colliculus",,0 1592,"commissure of superior colliculus","human","English","commissure of superior colliculus",,0 1627,"commissure y","human","English","supramammillary commissure",,0 1582,"commissures of cerebellum","human","English",,"commissures of cerebellum",0 1828,"commissures of midbrain","human","English",,"commissures of midbrain",0 1830,"commissures of telencephalon","human","English",,"commissures of telencephalon",0 1708,"Conarium","Unspecified","Latin","pineal body",,6767 7088,"Conus medullaris","human","Latin",,"Conus medullaris",414 7089,"Conus terminalis","human","Latin",,"Conus medullaris",7 1100,"convolution of Broca","human","English",,"Broca's area",0 4,"convolutions of Gratiolet","Unspecified","English","annectant gyrus (M)",,0 2802,"convolutions of Heschl","human","English",,"transverse temporal gyri",0 103,"Cornu ammonis","human","Latin","HIPPOCAMPUS",,113 108,"Cornu ammonis (Crosby)","human","Latin",,"Cornu ammonis (Crosby)",0 -979163560,"Cornu Ammonis (Shaw)","human","Latin",,"Cornu Ammonis (Shaw)",0 2393,"Cornu Ammonis 1","human","Latin","CA1 field",,9 2397,"Cornu Ammonis 2","human","Latin","CA2 field",,2 2400,"Cornu Ammonis 3","human","Latin","CA3 field",,4 1632,"Cornu anterius (ventriculi lateralis)","human","Latin","frontal horn of lateral ventricle",,0 1638,"Cornu anterius medullaris","Unspecified","Latin","medullary anterior horn",,0 1636,"Cornu anterius ventriculi lateralis","human","Latin","frontal horn of lateral ventricle",,0 1631,"Cornu frontale (ventriculi lateralis)","human","Latin","frontal horn of lateral ventricle",,0 1641,"Cornu inferius (ventriculi lateralis)","human","Latin","temporal horn of lateral ventricle",,0 1645,"Cornu inferius ventriculi lateralis","human","Latin","temporal horn of lateral ventricle",,0 1648,"Cornu occipitale (ventriculi lateralis)","human","Latin","occipital horn of lateral ventricle",,0 1649,"Cornu posterius (ventriculi lateralis)","human","Latin","occipital horn of lateral ventricle",,0 1653,"Cornu posterius ventriculi lateralis","human","Latin","occipital horn of lateral ventricle",,0 1640,"Cornu temporale (ventriculi lateralis)","human","Latin","temporal horn of lateral ventricle",,0 1655,"corona radiata","human","English",,"corona radiata",281 1656,"Corona radiata","human","Latin",,"corona radiata",281 1657,"Corona radiata","Macaca fascicularis","Latin",,"corona radiata",281 -1103612612,"coronal section","Unspecified","English",,"coronal section",114 3070,"Corpora quadrigemina","human","Latin",,"Corpus quadrigemina",355 1660,"Corpus (caudatus)","human","Latin","body of caudate nucleus",,1 124,"Corpus amygdalae","Macaca fascicularis","Latin","AMYGDALA",,0 119,"Corpus amygdaloideum","human","Latin","AMYGDALA",,10 120,"Corpus amygdaloideum","Macaca nemestrina","Latin","AMYGDALA",,10 3725,"Corpus amygdaloideum pars corticomedialis","human","Latin","cortical amygdaloid nucleus",,0 3726,"Corpus amygdaloideum pars olfactoria","human","Latin","cortical amygdaloid nucleus",,0 368,"Corpus bigeminalis caudalis","human","Latin","INFERIOR COLLICULUS",,0 369,"Corpus bigeminum posterioris","Macaca mulatta","Latin","INFERIOR COLLICULUS",,0 135,"corpus callosum","human","English","CORPUS CALLOSUM",,5931 137,"corpus callosum","rat","English","CORPUS CALLOSUM",,5931 136,"corpus callosum","Macaca fascicularis","English","CORPUS CALLOSUM",,5931 138,"Corpus callosum","human","Latin","CORPUS CALLOSUM",,5931 5982,"Corpus callosum rostrum","human","Latin","rostrum of corpus callosum",,0 5990,"Corpus callosum splenium","human","Latin","splenium of corpus callosum",,2 145,"Corpus callosum truncus","human","Latin","body of corpus callosum",,1 147,"corpus callosum, body","rat","English","body of corpus callosum",,0 146,"Corpus callosum, corpus","human","Latin","body of corpus callosum",,0 2368,"Corpus callosum, forceps major","human","Latin","posterior forceps of corpus callosum",,0 2361,"Corpus callosum, forceps minor","human","Latin","anterior forceps of corpus callosum",,0 2501,"Corpus callosum, genu","human","Latin","genu of corpus callosum",,0 2502,"Corpus callosum, genu","rat","Latin","genu of corpus callosum",,0 2503,"Corpus callosum, genu","human","Latin","genu of corpus callosum",,0 5988,"Corpus callosum, splenium","human","Latin","splenium of corpus callosum",,0 5989,"Corpus callosum, splenium","rat","Latin","splenium of corpus callosum",,0 446,"Corpus cerebelli","human","Latin","CEREBELLUM",,73 151,"Corpus ciliare","human","Latin",,"ciliary body",3 150,"Corpus ciliaris","human","Latin",,"ciliary body",0 1679,"Corpus fornicis","human","Latin","body of fornix",,2 4109,"Corpus geniculatum externum, nucleus accessorius","human","Latin","ventral nucleus of lateral geniculate body",,0 175,"Corpus geniculatum laterale","human","Latin","LATERAL GENICULATE BODY",,30 176,"Corpus geniculatum laterale","Macaca fascicularis","Latin","LATERAL GENICULATE BODY",,30 4097,"Corpus geniculatum laterale (Hassler)","human","Latin","dorsal nucleus of lateral geniculate body",,0 4101,"Corpus geniculatum laterale, pars oralis","Macaca fascicularis","Latin","ventral nucleus of lateral geniculate body",,0 187,"Corpus geniculatum mediale","human","Latin","MEDIAL GENICULATE BODY",,7 188,"Corpus geniculatum mediale","Macaca fascicularis","Latin","MEDIAL GENICULATE BODY",,7 177,"Corpus geniculatus lateralis","human","Latin","LATERAL GENICULATE BODY",,1 4129,"Corpus geniculatus mediale, pars magnocellularis","Macaca fascicularis","Latin","magnocellular nucleus of medial geniculate body",,0 189,"Corpus geniculatus medialis","human","Latin","MEDIAL GENICULATE BODY",,0 5238,"Corpus hypothalamicum","human","Latin","subthalamic nucleus",,0 1684,"Corpus juxtarestiforme","human","Latin","juxtarestiform body",,0 5240,"Corpus Luysi","human","Latin","subthalamic nucleus",,2 1691,"Corpus mamillare","human","Latin","mammillary body",,21 1689,"Corpus mamillare","human","Latin","mammillary body",,21 1686,"Corpus mamillaris","Macaca fascicularis","Latin","mammillary body",,3 1687,"Corpus mammillare","human","Latin","mammillary body",,5 1688,"Corpus mammillare","Macaca nemestrina","Latin","mammillary body",,5 463,"Corpus medullare","human","Latin","medullary body",,9 464,"Corpus medullare (cerebellum)","human","Latin","medullary body",,0 466,"Corpus medullare cerebelli","human","Latin","medullary body",,1 1465,"Corpus medullare cerebri","human","Latin","semioval center",,0 465,"Corpus medullare of cerebellum","human","Latin","medullary body",,0 1661,"Corpus nuclei caudati","human","Latin","body of caudate nucleus",,1 1697,"Corpus parabigeminum","human","Latin","parabigeminal nucleus",,1 1700,"Corpus pineale","human","Latin","pineal body",,3625 1701,"Corpus pineale","Macaca nemestrina","Latin","pineal body",,0 4854,"Corpus pontobulbare","Macaca fascicularis","Latin","pontobulbar nucleus",,4 4853,"Corpus pontobulbare","human","Latin","pontobulbar nucleus",,0 3066,"Corpus quadrigemina","human","Latin",,"Corpus quadrigemina",0 3073,"Corpus quadrigeminum","human","Latin",,"Corpus quadrigemina",0 370,"Corpus quadrigeminum inferius","human","Latin","INFERIOR COLLICULUS",,0 387,"Corpus quadrigeminum superius","human","Latin","SUPERIOR COLLICULUS",,1 474,"Corpus restiforme","Macaca fascicularis","Latin","inferior cerebellar peduncle",,0 473,"Corpus restiforme","human","Latin","inferior cerebellar peduncle",,0 110,"corpus striatum","human","English",,"corpus striatum",18700 111,"Corpus striatum","human","Latin",,"corpus striatum",18700 -686953088,"corpus striatum (Savel'ev)","human","Latin","BASAL GANGLIA",,0 5607,"Corpus subcommissurale","human","Latin","subcommissural organ",,0 5613,"Corpus subfornicale","human","Latin","subfornical organ",,1 5236,"Corpus subthalamicum","human","Latin","subthalamic nucleus",,1 635,"Corpus trapezoideum","Macaca fascicularis","Latin","trapezoid body",,5 634,"Corpus trapezoideum","human","Latin","trapezoid body",,5 1667,"Corpus ventriculi lateralis","human","Latin","body of lateral ventricle",,0 451,"Cortex cerebelli","human","Latin","CEREBELLAR CORTEX",,4 50,"Cortex cerebralis","human","Latin","CEREBRAL CORTEX",,0 48,"Cortex cerebri","human","Latin","CEREBRAL CORTEX",,55 2595,"Cortex cingularis anterior","Macaca fascicularis","Latin","anterior cingulate gyrus",,0 3223,"Cortex completus","human","Latin",,"neocortex",0 1148,"Cortex entorhinalis","human","Latin","entorhinal area",,2 81,"Cortex insularis","Macaca fascicularis","Latin","INSULA",,0 80,"Cortex insularis","human","Latin","INSULA",,0 3214,"Cortex intermedius","human","Latin",,"mesocortex",0 4829,"cortex of inferior colliculus","human","English","pericentral nucleus of inferior colliculus",,2 86,"cortex of island","human","English","INSULA",,0 1201,"Cortex periamydaloideus","human","Latin","periamygdaloid area",,0 5809,"Cortex piriformis","human","Latin","prepyriform area",,12 1720,"Cortex piriformis (Shantha)","Macaca fascicularis","Latin",,"Cortex piriformis (Shantha)",0 1728,"Cortex praestriatus","Macaca fascicularis","Latin",,"Cortex praestriatus",0 3723,"cortical amygdaloid nucleus","Macaca fascicularis","English","cortical amygdaloid nucleus",,53 1206,"cortical amygdaloid nucleus","Macaca fascicularis","English","periamygdaloid area",,53 3722,"cortical amygdaloid nucleus","human","English","cortical amygdaloid nucleus",,53 3645,"cortical amygdaloid transition area","Macaca fascicularis","English",,"cortical amygdaloid transition area",0 1113,"cortical areas of Brodmann","human","English",,"Brodmann's areas",0 972400807,"cortical association areas","human","English",,"association cortex",0 2560,"cortical convolutions","human","English",,"cerebral gyri",0 789,"cortical maps","Unspecified","English",,"cortical maps",0 3431,"cortical relay nuclei","human","English",,"cortical thalamic relay nuclei",0 3430,"cortical thalamic relay nuclei","human","English",,"cortical thalamic relay nuclei",0 3646,"corticoamygdalar transition area","human","English",,"corticoamygdalar transition area",0 2172,"corticobulbar fibers","human","English",,"corticobulbar fibers",10 2174,"corticobulbar tract","human","English",,"corticobulbar fibers",18 1572347973,"corticofugal fibers","human","English","longitudinal pontine fibers",,52 146930210,"corticofugal fibers","human","English",,"corticofugal fibers",0 2179,"corticohypothalamic fibers","human","English",,"corticohypothalamic fibers",0 1335,"corticomedial nuclear group","Macaca fascicularis","English","CORTICOMEDIAL NUCLEAR GROUP",,0 1334,"corticomedial nuclear group","human","English","CORTICOMEDIAL NUCLEAR GROUP",,0 1337,"corticomedial nuclear group (Crosby)","human","English",,"corticomedial nuclear group (Crosby)",0 2176,"corticonuclear fibers","human","English",,"corticobulbar fibers",12 2177,"corticonuclear projections","human","English",,"corticobulbar fibers",11 2180,"corticopontine fibers","human","English",,"corticopontine fibers",14 2182,"corticopontine tract","human","English",,"corticopontine fibers",9 2183,"corticoreticular fibers","human","English",,"corticoreticular fibers",0 2185,"corticorubral fibers","human","English",,"corticorubral fibers",8 2187,"corticorubral tract","human","English",,"corticorubral fibers",0 6739,"corticospinal decussation","human","English","pyramidal decussation",,0 6710,"corticospinal fibers","human","English",,"corticospinal tract",60 6705,"corticospinal tract","human","English",,"corticospinal tract",616 2188,"corticostriate fibers","human","English",,"corticostriate fibers",0 2189,"corticostriate tract","human","English",,"corticostriate fibers",0 91,"corticosubcortical gray","human","English",,"corticosubcortical gray",0 1051667926,"corticotectal fibers","human","English","corticotectal tract",,9 6729,"corticotectal tract","Macaca fascicularis","English","corticotectal tract",,6 6728,"corticotectal tract","human","English","corticotectal tract",,6 6730,"corticotectal tract","rat","English","corticotectal tract",,6 2190,"corticothalamic fibers","human","English",,"corticothalamic fibers",18 2192,"corticothalamic tract","human","English",,"corticothalamic fibers",0 3298,"cranial accessory nerve","human","English","cranial part of accessory nerve",,1 392,"cranial colliculus","human","English","SUPERIOR COLLICULUS",,0 3258,"Cranial Nerve VIII","human","English","vestibulocochlear nerve",,14 309,"cranial nerves","human","English",,"cranial nerves",3479 3290,"cranial part of accessory nerve","human","English","cranial part of accessory nerve",,0 3293,"cranial portion of eleventh cranial nerve","human","English","cranial part of accessory nerve",,0 1742,"Crura cerebri","human","Latin","cerebral crus",,5 3175,"crus 2","rat","English","inferior semilunar lobule",,9 1730,"Crus anterius capsulae internae","human","Latin","anterior limb of internal capsule",,0 477,"Crus cerebelli ad medullam oblongatam","human","Latin","inferior cerebellar peduncle",,0 487,"Crus cerebelli ad pontem","human","Latin","middle cerebellar peduncle",,0 1368754155,"Crus cerebello-cerebrale","human","Latin",,"superior cerebellar peduncle",0 1734,"Crus cerebri","human","Latin","cerebral crus",,52 1750,"Crus fornicis","human","Latin","posterior column of fornix",,0 3182,"crus I","rat","English","superior semilunar lobule",,68 3180,"Crus I","human","Latin","superior semilunar lobule",,68 3181,"Crus I","Macaca nemestrina","Latin","superior semilunar lobule",,68 3183,"Crus I (cerebelli)","Macaca fascicularis","Latin","superior semilunar lobule",,0 3170,"Crus II","human","Latin","inferior semilunar lobule",,58 476,"Crus medullo-cerebellare","human","Latin","inferior cerebellar peduncle",,0 1751,"crus of fornix","human","English","posterior column of fornix",,0 486,"Crus ponto-cerebellare","human","Latin","middle cerebellar peduncle",,0 1756,"Crus posterius capsulae internae","human","Latin","POSTERIOR LIMB OF INTERNAL CAPSULE",,0 1758,"culmen","human","English","culmen",,40 1759,"culmen","Macaca fascicularis","English","culmen",,40 1760,"culmen","rat","English","culmen",,40 1761,"Culmen","human","Latin","culmen",,40 1763,"Culmen anterior, posterior","Macaca nemestrina","Latin","culmen",,0 1765,"Culmen monticuli","human","Latin","culmen",,0 1764,"culmen of cerebellum","human","English","culmen",,0 1930,"cuneate fascicle","Macaca fascicularis","English",,"cuneate fasciculus",4 1931,"cuneate fascicle","rat","English",,"cuneate fasciculus",4 1925,"cuneate fasciculus","human","English",,"cuneate fasciculus",24 1926,"cuneate fasciculus","Macaca fascicularis","English",,"cuneate fasciculus",24 1927,"cuneate fasciculus","rat","English",,"cuneate fasciculus",24 1938,"cuneate fasciculus of medulla","Macaca fascicularis","English","cuneate fasciculus of medulla",,0 1937,"cuneate fasciculus of medulla","human","English","cuneate fasciculus of medulla",,0 1941,"cuneate fasciculus of spinal cord","human","English",,"cuneate fasciculus of spinal cord",0 1772,"cuneate lobule","human","English","cuneus",,0 4184,"cuneate nucleus","human","English","cuneate nucleus",,429 4185,"cuneate nucleus","Macaca fascicularis","English","cuneate nucleus",,429 4186,"cuneate nucleus","rat","English","cuneate nucleus",,429 6996,"cuneate tubercle","human","English","cuneate tubercle",,3 -541867292,"cuneate white matter","Unspecified","English","cuneate white matter",,0 5647,"cuneiform lobe","human","English","biventer lobule",,0 4217,"cuneiform nucleus","rat","English","cuneiform nucleus",,97 4216,"cuneiform nucleus","Macaca fascicularis","English","cuneiform nucleus",,97 4215,"cuneiform nucleus","human","English","cuneiform nucleus",,97 -1665608691,"cuneocerebellar fibers","human","English","cuneocerebellar tract",,0 6742,"cuneocerebellar tract","human","English","cuneocerebellar tract",,3 1766,"cuneus","human","English","cuneus",,51 1768,"Cuneus","Macaca mulatta","Latin","cuneus",,51 1767,"Cuneus","human","Latin","cuneus",,51 1771,"cuneus gyrus","human","English","cuneus",,1 1770,"cuneus of hemisphere","human","English","cuneus",,0 791,"cytoarchitectural fields of cerebral cortex","human","English",,"cortical maps",0 4055,"Darkshevich's nucleus","human","English","nucleus of Darkschewitsch",,0 1775,"declive","rat","English","declive",,27 1773,"declive","human","English","declive",,27 1774,"declive","Macaca fascicularis","English","declive",,27 1776,"Declive","human","Latin","declive",,27 1778,"Declivus","human","Latin","declive",,1 1870,"Decussatio brachii conjunctivi","Macaca fascicularis","Latin","decussation of superior cerebellar peduncle",,0 1869,"Decussatio brachii conjunctivi","human","Latin","decussation of superior cerebellar peduncle",,0 1579,"Decussatio cerebellaris inferior","human","Latin",,"posterior cerebellar commissure",0 1792,"Decussatio corporis trapezoidei","Macaca mulatta","Latin",,"Decussatio corporis trapezoidei",0 1871,"Decussatio crurorum cerebello-cerebralium","human","Latin","decussation of superior cerebellar peduncle",,0 1820,"Decussatio dorsalis tegmenti","Macaca fascicularis","Latin","dorsal tegmental decussation",,0 1787,"Decussatio fibrarum vestibularium","Macaca mulatta","Latin",,"Decussatio fibrarum vestibularium",0 1824,"Decussatio fibrorum medialium tecti","human","Latin","dorsal tegmental decussation",,0 1856,"Decussatio lemnisci medialis","Macaca fascicularis","Latin","decussation of medial lemniscus",,0 1857,"Decussatio lemniscorum","Macaca mulatta","Latin","decussation of medial lemniscus",,0 1855,"Decussatio lemniscorum medialium","human","Latin","decussation of medial lemniscus",,0 6737,"Decussatio motoria","human","Latin","pyramidal decussation",,0 1884,"Decussatio nervorum trochlearium","Macaca mulatta","Latin","decussation of trochlear nerve",,0 1883,"Decussatio nervorum trochlearium","human","Latin","decussation of trochlear nerve",,0 1868,"Decussatio pedunculorum cerebellarium superiorum","Macaca mulatta","Latin","decussation of superior cerebellar peduncle",,0 1867,"Decussatio pedunculorum cerebellarium superiorum","human","Latin","decussation of superior cerebellar peduncle",,0 1791,"Decussatio pontis","Macaca mulatta","Latin",,"ventral decussation of pons",0 1578,"Decussatio posterior cerebelli","human","Latin",,"posterior cerebellar commissure",0 6736,"Decussatio pyramidum","Macaca fascicularis","Latin","pyramidal decussation",,0 6735,"Decussatio pyramidum","human","Latin","pyramidal decussation",,0 1858,"Decussatio sensoria","human","Latin","decussation of medial lemniscus",,0 1822,"Decussatio tegmentalis dorsalis (Meynert)","human","Latin","dorsal tegmental decussation",,0 1878,"Decussatio tegmenti ventralis","Macaca nemestrina","Latin","ventral tegmental decussation",,0 1882,"Decussatio trochlearis","human","Latin","decussation of trochlear nerve",,0 1790,"Decussatio ventralis pontis","human","Latin",,"ventral decussation of pons",0 1876,"Decussatio ventralis tegmenti","human","Latin","ventral tegmental decussation",,0 1877,"Decussatio ventralis tegmenti","Macaca fascicularis","Latin","ventral tegmental decussation",,0 7039,"decussation of anterior medullary velum","human","English",,"decussation of superior medullary velum",0 1872,"decussation of brachium conjunctivum","Macaca fascicularis","English","decussation of superior cerebellar peduncle",,3 6740,"decussation of corticospinal tract","human","English","pyramidal decussation",,0 1879,"decussation of Forel","human","English","ventral tegmental decussation",,0 1861,"decussation of lemnisci","human","English","decussation of medial lemniscus",,0 1862,"decussation of lemniscus","human","English","decussation of medial lemniscus",,0 1860,"decussation of medial lemnisci","human","English","decussation of medial lemniscus",,0 1853,"decussation of medial lemniscus","Macaca fascicularis","English","decussation of medial lemniscus",,0 1852,"decussation of medial lemniscus","human","English","decussation of medial lemniscus",,0 1854,"decussation of medial lemniscus","rat","English","decussation of medial lemniscus",,0 1481,"decussation of optic nerve fibers","human","English","optic chiasm",,0 6741,"decussation of pyramidal tract fibers","human","English","pyramidal decussation",,0 1864,"decussation of superior cerebellar peduncle","human","English","decussation of superior cerebellar peduncle",,1 1865,"decussation of superior cerebellar peduncle","Macaca fascicularis","English","decussation of superior cerebellar peduncle",,1 1866,"decussation of superior cerebellar peduncle","rat","English","decussation of superior cerebellar peduncle",,1 266917139,"decussation of superior cerebellar peduncles","human","English","decussation of superior cerebellar peduncle",,3 7037,"decussation of superior medullary velum","human","English",,"decussation of superior medullary velum",0 1881,"decussation of trochlear nerve","human","English","decussation of trochlear nerve",,1 1885,"decussation of trochlear nerve (IV)","human","English","decussation of trochlear nerve",,0 7038,"decussation of velum","human","English",,"decussation of superior medullary velum",0 1625,"Decussation supramamillaris","human","Latin","supramammillary commissure",,0 1827,"Decussationes tegmentales","human","Latin","dorsal tegmental decussation",,0 1821,"Decussationes tegmenti","human","Latin","dorsal tegmental decussation",,0 1829,"decussations of midbrain","human","English",,"commissures of midbrain",0 1831,"decussations of telencephalon","human","English",,"commissures of telencephalon",0 506,"deep cerebellar nuclei","rat","English","DEEP CEREBELLAR NUCLEI",,475 504,"deep cerebellar nuclei","human","English","DEEP CEREBELLAR NUCLEI",,475 505,"deep cerebellar nuclei","Macaca fascicularis","English","DEEP CEREBELLAR NUCLEI",,475 6008,"deep gray layer of superior colliculus","human","English","deep gray layer of superior colliculus",,0 3042,"deep layer of large pyramidal cells","human","English",,"internal pyramidal layer",0 2432,"deep midbrain tegmental gray","human","English",,"deep tegmental gray",0 3475,"deep nuclear gray of hemisphere","human","English",,"basal ganglia (Crosby)",0 5754,"deep pes lemniscus","human","English","lateral pes lemniscus",,0 2430,"deep tegmental gray","human","English",,"deep tegmental gray",0 5525,"deep tegmental nucleus of Gudden","human","English","ventral tegmental nucleus",,1 6295,"deep transitional gyrus","human","English",,"deep transitional gyrus (H)",0 6010,"deep white layer of superior colliculus","human","English","deep white layer of superior colliculus",,0 5559,"Deiter's nucleus","Macaca mulatta","English","lateral vestibular nucleus",,11 4514,"densocellular part of medial dorsal nucleus","Unspecified","English","densocellular part of medial dorsal nucleus",,0 6356,"dentate fissure","Unspecified","English","hippocampal sulcus",,1 2383,"dentate gyrus","human","English","DENTATE GYRUS",,5523 2384,"dentate gyrus","Macaca fascicularis","English","DENTATE GYRUS",,5523 2385,"dentate gyrus","rat","English","DENTATE GYRUS",,5523 624,"dentate nucleus","rat","English","DENTATE NUCLEUS",,545 623,"dentate nucleus","Macaca fascicularis","English","DENTATE NUCLEUS",,545 622,"dentate nucleus","human","English","DENTATE NUCLEUS",,545 6744,"dentatoreticular fibers","human","English",,"dentatoreticular fibers",0 6745,"dentatoreticular tract","human","English",,"dentatoreticular fibers",0 2193,"dentatorubral fibers","human","English",,"dentatorubral fibers",0 6799,"dentatothalamic fibers","human","English","dentatothalamic tract",,0 6797,"dentatothalamic tract","Macaca fascicularis","English","dentatothalamic tract",,2 6796,"dentatothalamic tract","human","English","dentatothalamic tract",,2 2170,"descending fibers of facial nerve","Macaca fascicularis","English","descending fibers of facial nerve",,0 5150,"descending root of V","human","English",,"spinal trigeminal tract",0 6640,"descending terminal ramus","human","English",,"descending terminal ramus (H)",0 6415,"descending terminal ramus of Sylvian fissure","human","English",,"posterior descending limb of lateral sulcus (H)",0 5151,"descending tract of trigeminal","human","English",,"spinal trigeminal tract",0 5552,"descending vestibular nucleus","human","English","inferior vestibular nucleus",,43 -602417248,"DG internal feature","Unspecified","English","DG internal feature",,0 -263154883,"DG internal feature 1","Unspecified","English","DG internal feature 1",,0 1976172467,"DG internal feature 2","Unspecified","English","DG internal feature 2",,0 3875,"diagonal band","rat","English","diagonal band",,1206 3873,"diagonal band","human","English","diagonal band",,1206 3874,"diagonal band","Macaca fascicularis","English","diagonal band",,1206 3879,"diagonal band of Broca","human","English","diagonal band",,631 3880,"diagonal gyrus","human","English","diagonal band",,0 6638,"diagonal sulcus","human","English","diagonal sulcus (H)",,0 31,"diencephalon","Macaca fascicularis","English","DIENCEPHALON",,4149 30,"diencephalon","human","English","DIENCEPHALON",,4149 32,"Diencephalon","human","Latin","DIENCEPHALON",,4149 4429,"diffuse reticular nucleus","Unspecified","English","diffuse reticular nucleus",,0 5750,"digitationes cornu Ammonis","human","Latin",,"Pes hippocampi",0 5751,"digitationes hippocampi","human","Latin",,"Pes hippocampi",0 2867,"distal part of hypophysis","human","English","distal part of hypophysis",,0 2382,"diverticulum unci","human","English",,"diverticulum unci",0 4612,"dorsal accessory inferior olivary nucleus","Macaca fascicularis","English","dorsal accessory inferior olivary nucleus",,0 4611,"dorsal accessory inferior olivary nucleus","human","English","dorsal accessory inferior olivary nucleus",,0 4618,"dorsal accessory olivary nucleus","human","English","dorsal accessory inferior olivary nucleus",,5 6042,"dorsal acoustic stria","human","English","dorsal acoustic stria",,20 6924,"dorsal and ventral trigeminothalamic tracts","human","English",,"trigeminal lemniscus",0 980,"dorsal anterior cingulate area 32","human","English",,"dorsal anterior cingulate area 32",0 6916,"dorsal ascending trigeminal tract","human","English","dorsal trigeminal tract",,0 1519,"dorsal claustrum","human","English","claustrum",,11 4003,"dorsal cochlear nucleus","human","English","dorsal cochlear nucleus",,405 4004,"dorsal cochlear nucleus","Macaca fascicularis","English","dorsal cochlear nucleus",,405 4005,"dorsal cochlear nucleus","Macaca fascicularis","English","dorsal cochlear nucleus",,405 4006,"dorsal cochlear nucleus","rat","English","dorsal cochlear nucleus",,405 682582961,"dorsal division of ansa lenticularis","human","English","field H2",,0 4010,"dorsal division of cochlear nucleus","human","English","dorsal cochlear nucleus",,0 6917,"dorsal division of trigeminal lemniscus","human","English","dorsal trigeminal tract",,0 4244,"dorsal efferent nucleus of vagus","human","English","dorsal motor nucleus of vagus nerve",,1 1025,"dorsal entorhinal area 34","human","English",,"dorsal entorhinal area 34",0 2144,"dorsal external arcuate fibers","human","English","dorsal external arcuate fibers",,0 4289,"dorsal facial nucleus","human","English",,"accessory facial nucleus",0 6072,"dorsal fornix","human","English",,"dorsal fornix",55 1826,"dorsal fountain decussation","human","English","dorsal tegmental decussation",,0 7109,"dorsal funicular gray","human","English",,"posterior gray column",0 7133,"dorsal gray commissure","human","English",,"gray commissure",44 1607,"dorsal hippocampal commissure","human","English","commissure of fornix",,20 7108,"dorsal horn","human","English",,"posterior gray column",4454 5929,"dorsal hypothalamic area","human","English","dorsal hypothalamic area",,56 5930,"dorsal hypothalamic area","Macaca fascicularis","English","dorsal hypothalamic area",,56 5931,"dorsal hypothalamic area","rat","English","dorsal hypothalamic area",,56 6457,"dorsal intermediate sulcus","human","English","dorsal intermediate sulcus",,0 3403,"dorsal lamina","human","English",,"alar plate",0 4093,"dorsal lateral geniculate nucleus","Macaca","English","dorsal nucleus of lateral geniculate body",,940 4094,"dorsal lateral geniculate nucleus","rat","English","dorsal nucleus of lateral geniculate body",,940 1977,"dorsal longitudinal fasciculus","rat","English",,"dorsal longitudinal fasciculus",6 1976,"dorsal longitudinal fasciculus","human","English",,"dorsal longitudinal fasciculus",6 1991,"dorsal longitudinal fasciculus of hypothalamus","Macaca fascicularis","English","dorsal longitudinal fasciculus of hypothalamus",,0 1997,"dorsal longitudinal fasciculus of medulla","Macaca fascicularis","English","dorsal longitudinal fasciculus of medulla",,0 1993,"dorsal longitudinal fasciculus of midbrain","Macaca fascicularis","English","dorsal longitudinal fasciculus of midbrain",,0 1995,"dorsal longitudinal fasciculus of pons","Macaca fascicularis","English","dorsal longitudinal fasciculus of pons",,0 1981,"dorsal longitudinal fasciculus of Schultze","human","English",,"dorsal longitudinal fasciculus",0 1982,"dorsal longitudinal fasciculus of Schutz","human","English",,"dorsal longitudinal fasciculus",0 1979,"dorsal longitudinal tract","human","English",,"dorsal longitudinal fasciculus",0 4373,"dorsal medial nucleus of thalamus","human","English","MEDIAL DORSAL NUCLEUS",,0 6453,"dorsal median sulcus","human","English","dorsal median sulcus",,0 6456,"dorsal median sulcus of medulla","human","English","dorsal median sulcus",,0 4237,"dorsal motor nucleus of vagus nerve","rat","English","dorsal motor nucleus of vagus nerve",,6 4236,"dorsal motor nucleus of vagus nerve","Macaca fascicularis","English","dorsal motor nucleus of vagus nerve",,6 4235,"dorsal motor nucleus of vagus nerve","human","English","dorsal motor nucleus of vagus nerve",,6 4252,"dorsal nucleus (Clarke)","human","English",,"dorsal nucleus of Clarke",0 4246,"dorsal nucleus of Clarke","human","English",,"dorsal nucleus of Clarke",0 4089,"dorsal nucleus of lateral geniculate body","human","English","dorsal nucleus of lateral geniculate body",,1 4090,"dorsal nucleus of lateral geniculate body","Macaca fascicularis","English","dorsal nucleus of lateral geniculate body",,1 4477,"dorsal nucleus of lateral lemniscus","Macaca fascicularis","English","dorsal nucleus of lateral lemniscus",,2 4476,"dorsal nucleus of lateral lemniscus","human","English","dorsal nucleus of lateral lemniscus",,2 4478,"dorsal nucleus of lateral lemniscus","rat","English","dorsal nucleus of lateral lemniscus",,2 4121,"dorsal nucleus of medial geniculate body","human","English","dorsal nucleus of medial geniculate body",,0 4125,"dorsal nucleus of medial geniculate complex","human","English","dorsal nucleus of medial geniculate body",,0 4481,"dorsal nucleus of the lateral lemniscus","human","English","dorsal nucleus of lateral lemniscus",,119 4740,"dorsal nucleus of the raphe","human","English","dorsal raphe nucleus",,19 4240,"dorsal nucleus of vagus nerve","Macaca fascicularis","English","dorsal motor nucleus of vagus nerve",,2 4741,"dorsal nucleus raphe","rat","English","dorsal raphe nucleus",,3 4596,"dorsal oculomotor cell column","human","English","dorsal oculomotor nucleus",,0 4593,"dorsal oculomotor nucleus","human","English","dorsal oculomotor nucleus",,1 4594,"dorsal oculomotor nucleus","Macaca fascicularis","English","dorsal oculomotor nucleus",,1 2537,"dorsal pallidum","human","English",,"dorsal pallidum",30 5649,"dorsal paraflocculus","human","English","biventer lobule",,25 5030,"dorsal paragigantocellular nucleus","Macaca fascicularis","English","dorsal paragigantocellular nucleus",,2 5031,"dorsal paragigantocellular nucleus","rat","English","dorsal paragigantocellular nucleus",,2 4748,"dorsal paramedian nuclei of raphe","human","English","dorsal paramedian reticular nucleus",,0 4743,"dorsal paramedian reticular nucleus","human","English","dorsal paramedian reticular nucleus",,0 5378,"dorsal part of ventral lateral posterior nucleus (Jones)","human","English","caudal part of ventral lateral nucleus",,0 5379,"dorsal part of ventral lateral posterior nucleus (Jones)","Macaca","English","caudal part of ventral lateral nucleus",,0 4921,"dorsal periventricular hypothalamic nucleus","human","English",,"dorsal periventricular hypothalamic nucleus",0 1520,"dorsal portion of claustrum","human","English","claustrum",,0 6675,"dorsal portion of pons","human","English","PONTINE TEGMENTUM",,0 966,"dorsal posterior cingulate area 31","human","English",,"dorsal posterior cingulate area 31",0 4155,"dorsal premammillary nucleus","human","English",,"dorsal premammillary nucleus",18 4734,"dorsal raphe nucleus","human","English","dorsal raphe nucleus",,1141 4735,"dorsal raphe nucleus","Macaca fascicularis","English","dorsal raphe nucleus",,1141 4736,"dorsal raphe nucleus","rat","English","dorsal raphe nucleus",,1141 7140,"dorsal root fibers","human","English",,"dorsal root fibers",0 6914,"dorsal secondary ascending tract of V","human","English","dorsal trigeminal tract",,0 6918,"dorsal secondary tract of V","human","English","dorsal trigeminal tract",,0 5287,"dorsal septal nucleus","rat","English","dorsal septal nucleus",,13 5286,"dorsal septal nucleus","Macaca fascicularis","English","dorsal septal nucleus",,13 6847,"dorsal spinocerebellar tract","human","English","posterior spinocerebellar tract",,93 7153,"dorsal spinothalamic tract","human","English",,"lateral spinothalamic tract",0 2545,"dorsal striatum","human","English",,"dorsal striatum",442 1714,"dorsal striatum (Swanson)","rat","English","STRIATUM",,0 2948,"dorsal subnucleus of midbrain central gray","human","English",,"dorsal subnucleus of midbrain central gray",0 2147,"dorsal superficial arcuate fibers","human","English","dorsal external arcuate fibers",,0 1803,"dorsal supraoptic commissure","human","English","dorsal supraoptic decussation",,1 1804,"dorsal supraoptic commissure (of Ganser)","human","English","dorsal supraoptic decussation",,0 1798,"dorsal supraoptic decussation","Macaca fascicularis","English","dorsal supraoptic decussation",,5 1797,"dorsal supraoptic decussation","human","English","dorsal supraoptic decussation",,5 1801,"dorsal supraoptic decussation of Meynert","human","English","dorsal supraoptic decussation",,0 1817,"dorsal tegmental decussation","human","English","dorsal tegmental decussation",,12 1818,"dorsal tegmental decussation","Macaca fascicularis","English","dorsal tegmental decussation",,12 1819,"dorsal tegmental decussation","rat","English","dorsal tegmental decussation",,12 4255,"dorsal tegmental nucleus","human","English","dorsal tegmental nucleus",,130 4256,"dorsal tegmental nucleus","Macaca fascicularis","English","dorsal tegmental nucleus",,130 4262,"dorsal tegmental nucleus (Gudden)","rat","English","dorsal tegmental nucleus",,1 167,"dorsal thalamus (Anthoney)","human","English","THALAMUS",,0 3501,"dorsal thalamus (Crosby)","human","English",,"dorsal thalamus (Crosby)",0 3502,"dorsal thalamus (Swanson)","rat","English",,"dorsal thalamus (Swanson)",0 6919,"dorsal trigeminal lemniscus","human","English","dorsal trigeminal tract",,0 6913,"dorsal trigeminal pathway","human","English","dorsal trigeminal tract",,0 6908,"dorsal trigeminal tract","human","English","dorsal trigeminal tract",,2 6911,"dorsal trigeminothalamic tract","human","English","dorsal trigeminal tract",,2 6912,"dorsal trigmino-thalamic tract","human","English","dorsal trigeminal tract",,0 5572,"dorsal vestibular nucleus","human","English","medial vestibular nucleus",,4 4322,"dorsal visceral gray","human","English",,"gustatory nucleus",0 2943,"dorsolateral division of midbrain central gray","human","English",,"lateral dorsal subnucleus of midbrain central gray",0 7073,"dorsolateral fasciculus of medulla","human","English","dorsolateral fasciculus of medulla",,0 2274,"dorsolateral fissure of cerebellum","human","English","posterolateral fissure",,0 6318,"dorsolateral fissure of midbrain","human","English","dorsolateral fissure of midbrain",,0 5134,"dorsolateral subnucleus of solitary tract","human","English","dorsolateral subnucleus of solitary tract",,0 6313,"dorsolateral sulcus","human","English","dorsolateral sulcus",,11 3975,"dorsomedial central lateral nucleus","Macaca","English",,"dorsomedial central lateral nucleus",0 3974,"dorsomedial central lateral nucleus","human","English",,"dorsomedial central lateral nucleus",0 3759,"dorsomedial division of lateral nucleus of amygdala","Macaca fascicularis","English",,"dorsomedial division of lateral nucleus of amygdala",0 4386,"dorsomedial hypothalamic nucleus","rat","English","dorsomedial nucleus of hypothalamus",,274 4385,"dorsomedial hypothalamic nucleus","human","English","dorsomedial nucleus of hypothalamus",,274 4366,"dorsomedial nuclear group","human","English","MEDIAL DORSAL NUCLEUS",,1 4372,"dorsomedial nucleus","human","English","MEDIAL DORSAL NUCLEUS",,390 4382,"dorsomedial nucleus of hypothalamus","rat","English","dorsomedial nucleus of hypothalamus",,3 4381,"dorsomedial nucleus of hypothalamus","Macaca fascicularis","English","dorsomedial nucleus of hypothalamus",,3 4380,"dorsomedial nucleus of hypothalamus","human","English","dorsomedial nucleus of hypothalamus",,3 5136,"dorsomedial subnucleus of solitary tract","human","English","dorsomedial subnucleus of solitary tract",,0 6459,"dorsomedial sulcus","human","English","dorsal intermediate sulcus",,0 4520,"dorsomedial thalamic nucleus, magnocellular part","human","English","magnocellular part of medial dorsal nucleus",,0 4529,"dorsomedial thalamic nucleus, paralaminar part","human","English","paralaminar part of medial dorsal nucleus",,0 4539,"dorsomedial thalamic nucleus, parvicellular part","human","English","parvicellular part of medial dorsal nucleus",,0 643,"dura mater","human","English",,"dura mater",4831 644,"Dura mater","human","Latin",,"dura mater",4831 1114,"Economo's areas","human","English",,"Economo's areas",0 6320,"ectocalcarine sulcus","Macaca mulatta","English","ectocalcarine sulcus (M)",,0 918,"ectorhinal area 36","human","English",,"ectorhinal area 36",0 1007,"ectosplenial area 26","human","English",,"ectosplenial area 26",0 5109,"Edinger-Westphal nucleus","human","English","parvocellular oculomotor nucleus",,161 5113,"Edinger-Westphal nucleus of oculomotor nerve","human","English","parvocellular oculomotor nucleus",,0 5718,"efferent cochlear bundle","human","English","olivocochlear bundle",,1 -1306008426,"efferent cochlear bundle","human","English","peduncle of superior olive",,1 3259,"eighth cranial nerve","human","English","vestibulocochlear nerve",,194 3288,"eleventh cranial nerve","human","English",,"accessory nerve",10 3358,"eleventh cranial nerve fibers","human","English","accessory nerve fibers",,0 4268,"emboliform nucleus","human","English","emboliform nucleus",,1 4269,"emboliform nucleus","Macaca fascicularis","English","emboliform nucleus",,1 1887,"Eminentia collateralis","human","Latin","collateral eminence",,0 1908,"Eminentia lateralis (hypophysis)","human","Latin","lateral eminence of hypophysis",,0 1892,"Eminentia medialis","human","Latin","medial eminence of fourth ventricle",,5 1900,"Eminentia medialis (Shantha)","Macaca fascicularis","Latin","MEDIAN EMINENCE",,0 1893,"Eminentia medialis metencephali","human","Latin","medial eminence of fourth ventricle",,0 1904,"Eminentia mediana anterior","Unspecified","Latin","anterior median eminence",,0 1906,"Eminentia mediana posterior","Unspecified","Latin","posterior median eminence",,0 1888,"Eminentia occipito-temporalis","human","Latin","collateral eminence",,0 1890,"Eminentia parieto-occipitalis","Unspecified","Latin","parieto-occipital eminence",,0 6193,"Eminentia parolfactoria","human","Latin","anterior perforated substance",,0 1899,"Eminentia postinfundibularis","human","Latin","MEDIAN EMINENCE",,0 1894,"Eminentia teres","human","Latin","medial eminence of fourth ventricle",,0 6962,"Eminentia teres","human","Latin","hypoglossal trigone",,0 7005,"Eminentia trigemini","human","Latin","trigeminal tubercle",,0 93,"encephale isole","Unspecified","English",,"encephale isole",111 20,"Encephalon","human","Latin","BRAIN",,96 1155,"endopiriform nucleus","Macaca","English",,"endopiriform nucleus",126 3462,"entopeduncular nucleus","human","English",,"entopeduncular nucleus",462 3461,"entopeduncular nucleus","human","English",,"entopeduncular nucleus",462 2536,"entopeduncular nucleus (Monakow)","rat","English","medial globus pallidus",,0 1146,"entorhinal area","rat","English","entorhinal area",,174 1145,"entorhinal area","Macaca fascicularis","English","entorhinal area",,174 1144,"entorhinal area","human","English","entorhinal area",,174 1150,"entorhinal cortex","rat","English","entorhinal area",,2397 1149,"entorhinal cortex","human","English","entorhinal area",,2397 1676225697,"entorhinal white matter","Unspecified","English","entorhinal white matter",,0 447,"epencephalon-1","Unspecified","English","CEREBELLUM",,0 38,"epencephalon-2","Unspecified","English","METENCEPHALON",,0 3398,"ependymal layer of neural tube","human","English",,"ependymal layer of neural tube",0 1706,"Epiphysis","Macaca fascicularis","Latin","pineal body",,2467 1705,"Epiphysis","human","Latin","pineal body",,9 1707,"Epiphysis cerebri","human","Latin","pineal body",,2467 1136,"epithalamic commissure","human","English","posterior commissure",,0 198,"epithalamus","human","English","EPITHALAMUS",,102 201,"epithalamus","rat","English","EPITHALAMUS",,102 199,"epithalamus","Macaca fascicularis","English","EPITHALAMUS",,102 200,"Epithalamus","human","Latin","EPITHALAMUS",,102 202,"epithalamus (Crosby)","human","English",,"epithalamus (Crosby)",0 2081258360,"eulaminate cortex","human","English",,"neocortex",0 1900839961,"eulaminate isocortex","human","English",,"neocortex",0 5816,"Eupalaeocortex","human","Latin","prepyriform area",,0 2541,"extended amygdala","human","English",,"extended amygdala",87 1310,"external band of Baillarger","human","English",,"external band of Baillarger",0 3304,"external branch of accessory nerve","human","English",,"spinal part of accessory nerve",0 6323,"external calcarine fissure","chimpanzee","English","ectocalcarine sulcus (M)",,0 6322,"external calcarine fissure","Macaca mulatta","English","ectocalcarine sulcus (M)",,0 1425,"external capsule","Macaca fascicularis","English","external capsule",,156 1424,"external capsule","human","English","external capsule",,156 1426,"external capsule","rat","English","external capsule",,156 4201,"external cuneate nucleus","human","English","accessory cuneate nucleus",,121 4202,"external cuneate nucleus","rat","English","accessory cuneate nucleus",,121 2520,"external globus pallidus","human","English","lateral globus pallidus",,25 2959,"external granular layer","human","English",,"external granular layer",292 2967,"external medullary lamina","human","English","external medullary lamina",,12 2968,"external medullary lamina","Macaca fascicularis","English","external medullary lamina",,12 2969,"external medullary lamina","rat","English","external medullary lamina",,12 2997,"external medullary lamina of globus pallidus","human","English","lateral medullary lamina",,0 2994,"external medullary lamina of lentiform nucleus","human","English","lateral medullary lamina",,0 2977,"external medullary lamina of thalamus","rat","English","external medullary lamina",,0 2976,"external medullary lamina of thalamus","human","English","external medullary lamina",,0 4276,"external nucleus of inferior colliculus","human","English","external nucleus of inferior colliculus",,4 955991800,"external orbital area 10 (M)","Cercopithecus","English",,"area 10 of Brodmann-09",0 3033,"external pyramidal layer","human","English",,"external pyramidal layer",4 2025,"external sagittal stratum","human","English",,"inferior longitudinal fasciculus",0 1312,"external stripe of Baillarger","human","English",,"external band of Baillarger",0 4254,"extrapyramidal pathway","human","English",,"extrapyramidal system",0 4253,"extrapyramidal system","human","English",,"extrapyramidal system",201 1197,"extrastriate areas","human","English",,"extrastriate areas",91 1429,"extreme capsule","human","English","extreme capsule",,10 1430,"extreme capsule","rat","English","extreme capsule",,10 1521,"facial colliculus","human","English","facial colliculus",,16 4278,"facial motor nucleus","human","English","facial motor nucleus",,132 4279,"facial motor nucleus","Macaca fascicularis","English","facial motor nucleus",,132 2155,"facial nerve","human","English","facial nerve",,7203 2156,"facial nerve","Macaca fascicularis","English","facial nerve",,7203 2163,"facial nerve fibers","Macaca fascicularis","English","FACIAL NERVE FIBERS",,21 2162,"facial nerve fibers","human","English","FACIAL NERVE FIBERS",,21 4291,"facial nerve nuclei","human","English",,"facial nerve nuclei",0 4283,"facial nucleus","rat","English","facial motor nucleus",,538 4282,"facial nucleus","Macaca fascicularis","English","facial motor nucleus",,538 3117,"Facies superficiales","human","Latin",,"superficial features",0 5600,"facies supratemporalis","human","Latin","temporal operculum",,0 2710,"falciform fold","human","English",,"falciform fold (H)",4 -121972698,"falciform lobe","human","English","LIMBIC LOBE",,0 203691817,"falciform lobe","human","English",,"limbic lobe (Anthoney)",0 1909,"falx cerebelli","human","English",,"falx cerebelli",4 1910,"Falx cerebelli","human","Latin",,"falx cerebelli",4 1911,"falx cerebri","human","English",,"falx cerebri",144 1912,"Falx cerebri","human","Latin",,"falx cerebri",144 2406,"fascia dentata","Macaca mulatta","English","fascia dentata",,411 2405,"fascia dentata","human","English","fascia dentata",,411 2407,"Fascia dentata","human","Latin","fascia dentata",,411 2390,"Fascia dentata (Crosby)","Macaca fuscata","Latin","DENTATE GYRUS",,0 2389,"Fascia dentata (Crosby)","human","Latin","DENTATE GYRUS",,0 2391,"Fascia dentata hippocampi (Shantha)","Macaca fascicularis","Latin","DENTATE GYRUS",,0 1914,"Fasciculi cerebelli","human","Latin",,"cerebellar fiber tracts",0 5756,"Fasciculi laterales pontis","human","Latin","lateral pes lemniscus",,0 7241,"Fasciculi proprii","human","Latin",,"Fasciculi proprii",0 1917,"Fasciculi thalami","human","Latin","THALAMIC FIBER TRACTS",,0 6708,"Fasciculus cerebro-spinalis","human","Latin",,"corticospinal tract",0 2014,"Fasciculus commissurae posterioris","human","Latin",,"medial longitudinal fasciculus",0 1929,"Fasciculus cuneatus","Macaca nemestrina","Latin",,"cuneate fasciculus",24 1928,"Fasciculus cuneatus","human","Latin",,"cuneate fasciculus",24 -900729684,"Fasciculus cuneatus (Burdachi)","human","Latin","cuneate fasciculus of medulla",,0 1939,"Fasciculus cuneatus (myelencephali)","human","Latin","cuneate fasciculus of medulla",,0 1940,"Fasciculus cuneatus (myelencephali)","Macaca nemestrina","Latin","cuneate fasciculus of medulla",,0 1942,"Fasciculus cuneatus (spinalis)","human","Latin",,"cuneate fasciculus of spinal cord",0 3877,"Fasciculus diagonalis Brocae","Macaca fascicularis","Latin","diagonal band",,2 7074,"Fasciculus dorsolateralis","human","Latin","dorsolateral fasciculus of medulla",,0 636164794,"fasciculus dorsolateralis gracilis (Golli)","human","Latin","gracile fasciculus of medulla",,0 2135,"Fasciculus fastigio-vestibularis","human","Latin","uncinate fasciculus of pons",,0 2026,"Fasciculus fronto-occipitalis inferior","human","Latin",,"inferior longitudinal fasciculus",0 1945,"Fasciculus gracilis","human","Latin",,"gracile fasciculus",96 1946,"Fasciculus gracilis","Macaca nemestrina","Latin",,"gracile fasciculus",96 1957,"Fasciculus gracilis (myelencephali)","Macaca nemestrina","Latin","gracile fasciculus of medulla",,0 1956,"Fasciculus gracilis (myelencephali)","human","Latin","gracile fasciculus of medulla",,0 1959,"Fasciculus gracilis (spinalis)","human","Latin",,"gracile fasciculus of spinal cord",0 1229017046,"Fasciculus habenulo-interpeduncularis","human","Latin",,"habenulo-interpeduncular tract",0 2000,"Fasciculus interfascicularis","human","Latin",,"comma tract of Schultze",0 7248,"Fasciculus interstitiospinalis","human","Latin",,"interstitiospinal tract",0 1962,"Fasciculus lenticularis (diencephali)","human","Latin","field H2",,0 1968,"Fasciculus lenticularis hypothalami","human","Latin","field H2",,0 1978,"Fasciculus longitudinalis dorsalis","human","Latin",,"dorsal longitudinal fasciculus",0 1992,"Fasciculus longitudinalis dorsalis (hypothalami)","Unspecified","Latin","dorsal longitudinal fasciculus of hypothalamus",,0 1994,"Fasciculus longitudinalis dorsalis (mesencephali)","Unspecified","Latin","dorsal longitudinal fasciculus of midbrain",,0 1998,"Fasciculus longitudinalis dorsalis (myelencephali)","Unspecified","Latin","dorsal longitudinal fasciculus of medulla",,0 1996,"Fasciculus longitudinalis dorsalis (pontis)","Unspecified","Latin","dorsal longitudinal fasciculus of pons",,0 2015,"Fasciculus longitudinalis dorsalis (Riley)","human","Latin",,"medial longitudinal fasciculus",0 1980,"Fasciculus longitudinalis dorsalis (Schuetz)","human","Latin",,"dorsal longitudinal fasciculus",0 2024,"Fasciculus longitudinalis inferior","human","Latin",,"inferior longitudinal fasciculus",0 2007,"Fasciculus longitudinalis medialis","Macaca fascicularis","Latin",,"medial longitudinal fasciculus",56 2006,"Fasciculus longitudinalis medialis","human","Latin",,"medial longitudinal fasciculus",56 2018,"Fasciculus longitudinalis medialis (mesencephali)","Unspecified","Latin","medial longitudinal fasciculus of midbrain",,0 2020,"Fasciculus longitudinalis medialis (myelencephali)","Unspecified","Latin","medial longitudinal fasciculus of medulla",,0 2022,"Fasciculus longitudinalis medialis (pontis)","Unspecified","Latin","medial longitudinal fasciculus of pons",,0 1986,"Fasciculus longitudinalis periependymalis","human","Latin",,"dorsal longitudinal fasciculus",0 2016,"Fasciculus longitudinalis posterior (posticus)","human","Latin",,"medial longitudinal fasciculus",0 2028,"Fasciculus longitudinalis superior","human","Latin",,"superior longitudinal fasciculus",0 2073,"Fasciculus longitudinalis telencephali medialis","human","Latin","medial forebrain bundle",,0 2037,"Fasciculus mamillaris","human","Latin","mammillary princeps fasciculus",,0 2032,"Fasciculus mamillaris princeps","Macaca fascicularis","Latin","mammillary princeps fasciculus",,0 2031,"Fasciculus mamillaris princeps","human","Latin","mammillary princeps fasciculus",,0 2040,"Fasciculus mamillotegmentalis","human","Latin","mammillotegmental fasciculus",,0 2049,"Fasciculus mamillothalamicus","human","Latin",,"mammillothalamic tract",0 2055,"Fasciculus mamillo-thalamicus","Macaca nemestrina","Latin",,"mammillothalamic tract",0 2062,"Fasciculus mamillothalamicus (hypothalami)","Unspecified","Latin","mammillothalamic tract of hypothalamus",,0 2060,"Fasciculus mamillothalamicus (thalami)","Unspecified","Latin","mammillothalamic tract of thalamus",,0 2034,"Fasciculus mammillaris princeps","Macaca nemestrina","Latin","mammillary princeps fasciculus",,0 2033,"Fasciculus mammillaris princeps","human","Latin","mammillary princeps fasciculus",,0 5762,"Fasciculus obliquus crucis cerebri","human","Latin",,"Fasciculus obliquus crucis cerebri",0 2121,"Fasciculus occipitofrontalis inferior","human","Latin",,"inferior occipitofrontal fasciculus",0 2123,"Fasciculus occipito-frontalis inferior","human","Latin",,"inferior occipitofrontal fasciculus",0 2080,"Fasciculus occipitofrontalis superior","human","Latin",,"subcallosal fasciculus",0 2081,"Fasciculus occipito-frontalis superior","human","Latin",,"subcallosal fasciculus",0 5764,"Fasciculus of Fere","human","English",,"Fasciculus obliquus crucis cerebri",0 1948,"fasciculus of Goll","Macaca fascicularis","English",,"gracile fasciculus",0 2056,"fasciculus of Vicq d'Azyr","human","English",,"mammillothalamic tract",0 3884,"Fasciculus olfactorius","human","Latin","diagonal band",,0 3886,"Fasciculus olfactorius (hippocampi)","human","Latin","diagonal band",,0 3887,"Fasciculus olfactorius cornu Ammonis","human","Latin","diagonal band",,0 1382,"Fasciculus pallido-habenularis","Unspecified","Latin","pallidohabenular bundle",,0 6824,"Fasciculus pallido-hypothalamicus","human","Latin",,"pallidohypothalamic fasciculus",0 2064,"Fasciculus pallido-tegmentalis","Unspecified","Latin","pallidotegmental fasciculus",,0 2068,"Fasciculus parieto-occipitopontinus","human","Latin",,"parietotemporo-occipitopontine tract",0 2223,"Fasciculus parieto-temporo-pontinus","human","Latin",,"Fibrae parietotemporopontinae",0 1988,"Fasciculus periaquaeductalis","human","Latin",,"dorsal longitudinal fasciculus",0 1386,"Fasciculus praedorsalis (Tschermak)","human","Latin","predorsal bundle",,0 1384,"Fasciculus predorsalis","Unspecified","Latin","predorsal bundle",,0 7242,"Fasciculus proprius","human","Latin",,"Fasciculi proprii",0 2070,"Fasciculus prosencephalicus medialis","human","Latin","medial forebrain bundle",,0 6704,"Fasciculus pyramidalis","human","Latin","pyramidal tract",,0 1816385858,"fasciculus retroflexus","human","English",,"habenulo-interpeduncular tract",141 -2086765413,"Fasciculus retroflexus","human","Latin",,"habenulo-interpeduncular tract",141 -426825408,"Fasciculus retroflexus","rat","Latin",,"habenulo-interpeduncular tract",141 909754433,"Fasciculus retroflexus (of Meynert)","human","Latin",,"habenulo-interpeduncular tract",1 3888,"Fasciculus septo-amygdalicus","human","Latin","diagonal band",,0 7236,"Fasciculus septomarginalis","human","Latin",,"septomarginal fasciculus",0 606,"Fasciculus solitarius","human","Latin","solitary tract",,8 2075,"Fasciculus subcallosus","human","Latin",,"subcallosal fasciculus",0 2093,"Fasciculus subthalamicus","human","Latin",,"subthalamic fasciculus",0 1788,"Fasciculus subthalamicus (Riley)","human","Latin",,"Fasciculus subthalamicus (Riley)",0 6901,"Fasciculus tegmentalis centralis","human","Latin",,"central tegmental tract",0 1989,"Fasciculus tegmentalis dorsalis","human","Latin",,"dorsal longitudinal fasciculus",0 2097,"Fasciculus thalamicus","human","Latin","field H1",,1 2104,"Fasciculus thalamicus hypothalami","human","Latin","field H1",,0 2117,"Fasciculus uncinatus","Macaca fascicularis","Latin",,"uncinate fasciculus of forebrain",0 2116,"Fasciculus uncinatus","human","Latin",,"uncinate fasciculus of forebrain",0 2128,"Fasciculus uncinatus (pontis)","Unspecified","Latin","uncinate fasciculus of pons",,0 2115,"Fasciculus uncinatus (prosencephali)","Unspecified","Latin",,"uncinate fasciculus of forebrain",0 1921,"Fasciculus ventralis","Macaca mulatta","Latin",,"anterior funiculus",0 2604,"fasciola cinerea","human","English","fasciolar gyrus",,5 2606,"Fasciola cinerea","rat","Latin","fasciolar gyrus",,5 2605,"Fasciola cinerea","human","Latin","fasciolar gyrus",,5 3672,"Fasciola cinerea (Amaral)","human","Latin",,"Fasciola cinerea (Amaral)",0 2600,"fasciolar gyrus","Macaca fascicularis","English","fasciolar gyrus",,0 2599,"fasciolar gyrus","human","English","fasciolar gyrus",,0 481487959,"fasiculii longitudinales pyramidales","human","Latin","longitudinal pontine fibers",,0 4294,"fastigial nucleus","rat","English","fastigial nucleus",,285 4292,"fastigial nucleus","human","English","fastigial nucleus",,285 4293,"fastigial nucleus","Macaca fascicularis","English","fastigial nucleus",,285 2131,"fastigiobulbar tract","human","English","uncinate fasciculus of pons",,0 7231,"fastigioreticular fibers","human","English",,"fastigioreticular fibers",0 7230,"fastigiospinal fibers","human","English",,"fastigiospinal tract",0 7229,"fastigiospinal tract","human","English",,"fastigiospinal tract",0 2140,"fastigium","human","English","fastigium",,10 2141,"Fastigium","human","Latin","fastigium",,10 405725555,"Feld 2","human","Latin",,"caudal postcentral area 2",0 6078,"fibers of Piccolomini","human","English","striae medullares",,0 2143,"Fibrae arcuatae cerebri","human","Latin",,"arcuate fasciculus",0 2150,"Fibrae arcuatae externae anteriores","human","Latin","ventral external arcuate fibers",,0 2145,"Fibrae arcuatae externae dorsales","human","Latin","dorsal external arcuate fibers",,0 2146,"Fibrae arcuatae externae posteriores","human","Latin","dorsal external arcuate fibers",,0 2149,"Fibrae arcuatae externae ventrales","human","Latin","ventral external arcuate fibers",,0 2154,"Fibrae arcuatae internae","Macaca fascicularis","Latin","internal arcuate fibers",,0 2169,"Fibrae ascendens nervi facialis","Macaca mulatta","Latin","ascending fibers of facial nerve",,0 2178,"Fibrae corticobulbares laterales","human","Latin",,"corticobulbar fibers",0 2173,"Fibrae corticonucleares","human","Latin",,"corticobulbar fibers",0 2181,"Fibrae corticopontinae","human","Latin",,"corticopontine fibers",0 2184,"Fibrae corticoreticulares","human","Latin",,"corticoreticular fibers",0 2186,"Fibrae corticorubrales","human","Latin",,"corticorubral fibers",0 6709,"Fibrae corticospinales","human","Latin",,"corticospinal tract",0 967677769,"Fibrae corticotectales","human","Latin","corticotectal tract",,0 2191,"Fibrae corticothalamicae","human","Latin",,"corticothalamic fibers",0 -1783605928,"Fibrae dentatae rubrales","human","Latin",,"dentatorubral fibers",0 2194,"Fibrae dentatorubrales","human","Latin",,"dentatorubral fibers",0 2171,"Fibrae descendens nervi facialis","Macaca mulatta","Latin","descending fibers of facial nerve",,0 2197,"Fibrae frontopontinae","human","Latin",,"frontopontine fibers",0 2219,"Fibrae intrathalamicae","human","Latin",,"Fibrae intrathalamicae",0 1530,"Fibrae marginalis tecti","human","Latin",,"Colliculus superior, stratum profundum",0 3243,"Fibrae nervi abducentis","Macaca mulatta","Latin","abducens nerve fibers",,0 3357,"Fibrae nervi accessorius","human","Latin","accessory nerve fibers",,0 2164,"Fibrae nervi facialis","Unspecified","Latin","FACIAL NERVE FIBERS",,0 3352,"Fibrae nervi glossopharyngei","human","Latin","glossopharyngeal nerve fibers",,0 298,"Fibrae nervi hypoglossi","Macaca mulatta","Latin","hypoglossal nerve fibers",,0 286,"Fibrae nervi oculomotorii","Macaca mulatta","Latin","oculomotor nerve fibers",,0 303,"Fibrae nervi statoacustici","Macaca mulatta","Latin","vestibulocochlear nerve fibers",,0 3322,"Fibrae nervi trigemini","Unspecified","Latin","trigeminal nerve fibers",,0 322,"Fibrae nervi trochlearis","human","Latin","trochlear nerve fibers",,0 3347,"Fibrae nervi vagi","human","Latin","vagal nerve fibers",,0 2205,"Fibrae occipitopontinae","human","Latin",,"occipitopontine fibers",0 2218,"Fibrae orbitofrontalis","human","Latin",,"orbitofrontal fibers",0 6826,"Fibrae pallidohypothalamicae","human","Latin",,"pallidohypothalamic fasciculus",0 2220,"Fibrae paraventriculares","human","Latin",,"Fibrae paraventriculares",0 2201,"Fibrae parietopontinae","human","Latin",,"parietopontine fibers",0 2221,"Fibrae parietotemporopontinae","human","Latin",,"Fibrae parietotemporopontinae",0 4349,"Fibrae perforantes brachii conjunctivi","human","Latin",,"commissure of Probst",0 1747,"Fibrae perforantes pedunculi","human","Latin",,"comb system",0 1746,"Fibrae perforantes pedunculi","human","Latin",,"comb system",0 2225,"Fibrae periventriculares","human","Latin",,"periventricular fibers",0 2235,"Fibrae pontis longitudinales","human","Latin","longitudinal pontine fibers",,0 -1977106407,"fibrae pontis superficiales","human","Latin","transverse pontine fibers",,0 2240,"Fibrae pontis transversae","Macaca fascicularis","Latin","transverse pontine fibers",,0 2239,"Fibrae pontis transversae","human","Latin","transverse pontine fibers",,0 6839,"Fibrae pontocerebellares","human","Latin",,"pontocerebellar fibers",0 5197,"Fibrae striae terminalis","human","Latin","stria terminalis",,0 1990,"Fibrae substantiae griseae centralis","human","Latin",,"dorsal longitudinal fasciculus",0 2250,"Fibrae supraopticae","human","Latin",,"Fibrae supraopticae",0 2211,"Fibrae temporopontinae","human","Latin",,"temporopontine fibers",0 2252,"Fibrae thalamoparietales","human","Latin",,"thalamoparietal fibers",0 2241,"Fibrae transversae superficiales pontis","human","Latin","transverse pontine fibers",,0 3362,"Fibrae vestibulares","Macaca mulatta","Latin",,"vestibular nerve",0 7227,"fibres pyramidales homolaterales superficelles of Dejerine","human","English",,"anterolateral corticospinal tract",0 2404,"field CA4 of hippocampal formation","Macaca mulatta","English","hilus of dentate gyrus",,0 1398,"field H","human","English","field H",,218 1399,"field H","Macaca fascicularis","English","field H",,218 2095,"field H1","human","English","field H1",,7 2096,"field H1","Macaca fascicularis","English","field H1",,7 1960,"field H2","human","English","field H2",,5 1961,"field H2","Macaca fascicularis","English","field H2",,5 1107,"field of Wernicke","human","English",,"triangular area (Wernicke)",0 1395,"fields of Forel","human","English",,"fields of Forel",0 1396,"fields of Forel","rat","English",,"fields of Forel",0 3319,"fifth cranial nerve","human","English","trigeminal nerve",,114 1456,"fifth ventricle","human","English","cave of septum pellucidum",,4 3284,"Fila olfactoria","human","Latin","olfactory nerve",,25 4796,"filiform nucleus","human","English","paraventricular nucleus of hypothalamus",,1 7090,"Filum terminale","human","Latin",,"Filum terminale",263 2257,"Fimbria","human","Latin","fimbria of hippocampus",,1184 2258,"Fimbria","Macaca fascicularis","Latin","fimbria of hippocampus",,1184 2256,"Fimbria hippocampi","rat","Latin","fimbria of hippocampus",,13 2255,"Fimbria hippocampi","human","Latin","fimbria of hippocampus",,13 2260,"Fimbria fornicis","human","Latin","fimbria of hippocampus",,1 2259,"fimbria of fornix","human","English","fimbria of hippocampus",,0 2254,"fimbria of hippocampus","Macaca fascicularis","English","fimbria of hippocampus",,2 2253,"fimbria of hippocampus","human","English","fimbria of hippocampus",,2 6325,"fimbriodentate fissure","Macaca fascicularis","English","fimbriodentate fissure",,1 6324,"fimbriodentate fissure","human","English","fimbriodentate fissure",,1 6326,"fimbriodentate sulcus","human","English","fimbriodentate fissure",,0 3283,"first cranial nerve","human","English","olfactory nerve",,7 3269,"first genu","human","English","internal genu of facial nerve",,4 -1581968911,"first part of root of facial nerve","human","English","ascending fibers of facial nerve",,0 2701,"first posterior central gyrus","Unspecified","English","first posterior central gyrus (H)",,0 2552,"first short gyrus","Unspecified","English","first short gyrus (H)",,0 2808,"first transverse gyrus of Heschl","human","English","anterior transverse temporal gyrus (H)",,1 6647,"Fissura ventrolateralis mesencephali","Unspecified","Latin","ventrolateral fissure of midbrain",,0 6265,"Fissura centralis insulae","human","Latin","central insular sulcus",,0 2333,"Fissura cerebrocerebellaris","human","Latin","cerebrocerebellar fissure",,0 2334,"Fissura cerebro-cerebellaris","human","Latin","cerebrocerebellar fissure",,0 2266,"Fissura choroidea","human","Latin","choroidal fissure",,0 2271,"Fissura dorsolateralis","human","Latin","posterolateral fissure",,0 6319,"Fissura dorsolateralis mesencephali","Unspecified","Latin","dorsolateral fissure of midbrain",,0 6329,"Fissura fimbriodentata","Unspecified","Latin","fimbriodentate fissure",,0 6327,"Fissura fimbrio-dentata","human","Latin","fimbriodentate fissure",,0 2288,"Fissura horizontalis","human","Latin","horizontal fissure",,0 1944120245,"fissura horizontalis cerebelli","human","Latin","horizontal fissure",,0 2286,"Fissura inferior anterior","human","Latin","prepyramidal fissure",,0 2290,"Fissura intercruralis","human","Latin","horizontal fissure",,0 2296,"Fissura interhemispherica","Macaca mulatta","Latin","longitudinal fissure",,0 2295,"Fissura interhemispherica","human","Latin","longitudinal fissure",,0 6378,"Fissura lateralis","human","Latin","lateral sulcus",,1 6379,"Fissura lateralis cerebri","human","Latin","lateral sulcus",,0 6380,"Fissura lateralis cerebri (Sylvii)","Macaca fascicularis","Latin","lateral sulcus",,0 2304,"Fissura longitudinalis cerebrales","human","Latin","longitudinal fissure",,0 2294,"Fissura longitudinalis cerebri","Macaca fascicularis","Latin","longitudinal fissure",,0 2293,"Fissura longitudinalis cerebri","human","Latin","longitudinal fissure",,0 2297,"Fissura longitudinalis magna","human","Latin","longitudinal fissure",,0 2309,"Fissura mediana anterior","human","Latin","anterior median fissure",,0 2308,"Fissura mediana ventralis","human","Latin","anterior median fissure",,0 2285,"Fissura parafloccularis","human","Latin","prepyramidal fissure",,0 6508,"Fissura parieto-occipitalis","human","Latin","parieto-occipital sulcus",,0 2322,"Fissura postcentralis cerebelli","human","Latin","postcentral fissure of cerebellum",,0 2270,"Fissura posterolateralis","human","Latin","posterolateral fissure",,0 2319,"Fissura praecentralis","human","Latin","precentral fissure of cerebellum",,0 2323,"Fissura praeculminata","human","Latin","postcentral fissure of cerebellum",,0 2283,"Fissura praepyramidalis","human","Latin","prepyramidal fissure",,0 2318,"Fissura precentralis cerebelli","human","Latin","precentral fissure of cerebellum",,0 2282,"Fissura prepyramidalis","Unspecified","Latin","prepyramidal fissure",,0 2313,"Fissura prima","human","Latin","primary fissure of cerebellum",,9 6560,"Fissura rhinalis","Macaca mulatta","Latin","rhinal sulcus",,0 2326,"Fissura secunda","human","Latin","secondary fissure",,1 2316,"Fissura superior anterior","human","Latin","primary fissure of cerebellum",,0 2278,"Fissura superior posterior","human","Latin","posterior superior fissure",,0 2337,"Fissura telo-diencephalica","human","Latin","telodiencephalic fissure",,0 -1851841388,"fissura transversa cerebelli","human","Latin",,"fissura transversa cerebelli",0 2331,"Fissura transversa cerebralis","human","Latin",,"transverse cerebral fissure",0 2329,"Fissura transversa cerebri","human","Latin",,"transverse cerebral fissure",0 2262,"Fissurae cerebelli","human","Latin",,"cerebellar fissures",0 2263,"Fissure cerebelli","human","Latin",,"cerebellar fissures",0 6257,"fissure of Rolando","human","English","central sulcus",,2 6385,"fissure of Sylvius","human","English","lateral sulcus",,3 552,"flocculonodular lobe","human","English","FLOCCULONODULAR LOBE",,21 553,"flocculonodular lobe","Macaca fascicularis","English","FLOCCULONODULAR LOBE",,21 2342,"flocculus","human","English","flocculus",,463 2345,"flocculus","rat","English","flocculus",,463 2344,"Flocculus","Macaca nemestrina","Latin","flocculus",,463 2343,"Flocculus","human","Latin","flocculus",,463 319088913,"flocculus cerebelli","human","Latin","flocculus",,0 -2065481970,"flocculus secundus cerebelli","human","Latin","paraflocculus",,0 2347,"Folia cerebelli","human","Latin",,"cerebellar folia",0 2348,"folia of cerebellum","human","English",,"cerebellar folia",0 2350,"folium","Macaca fascicularis","English","folium",,155 2349,"folium","human","English","folium",,155 2351,"Folium vermis","human","Latin","folium",,1 767,"Foramen caecum anterius","human","Latin","foramen cecum anterior",,0 770,"Foramen caecum posterius","human","Latin","foramen cecum posterior",,0 765,"foramen cecum anterior","human","English","foramen cecum anterior",,0 766,"Foramen cecum anterior","Unspecified","Latin","foramen cecum anterior",,0 768,"foramen cecum posterior","human","English","foramen cecum posterior",,0 769,"Foramen cecum posterior","Unspecified","Latin","foramen cecum posterior",,0 2355,"Foramen interventriculare","human","Latin","interventricular foramen",,1 773,"Foramen of Luschka","human","English","lateral aperture of fourth ventricle",,24 776,"foramen of Magendie","human","English","median aperture of fourth ventricle",,32 2356,"foramen of Monro","human","English","interventricular foramen",,228 2358,"Forceps frontalis","human","Latin","anterior forceps of corpus callosum",,0 2367,"forceps major","human","English","posterior forceps of corpus callosum",,10 2366,"Forceps major","human","Latin","posterior forceps of corpus callosum",,10 2370,"Forceps major corporis callosi","human","Latin","posterior forceps of corpus callosum",,0 2371,"forceps major of corpus callosum","human","English","posterior forceps of corpus callosum",,0 2359,"Forceps minor","human","Latin","anterior forceps of corpus callosum",,15 2362,"Forceps minor corporis callosi","human","Latin","anterior forceps of corpus callosum",,0 2363,"Forceps minor of corpus callosum","human","Latin","anterior forceps of corpus callosum",,0 2365,"Forceps occipitalis","human","Latin","posterior forceps of corpus callosum",,0 13,"forebrain","human","English","FOREBRAIN",,12613 2108,"Forelli campus I","Macaca nemestrina","Latin","field H1",,0 1971,"Forelli campus II","Macaca nemestrina","Latin","field H2",,0 1403,"Forel's field H","human","English","field H",,20 2109,"Forel's field H1","human","English","field H1",,0 1408,"Forel's Field H1+H2 (Olszewski)","Macaca mulatta","English",,"Forel's Field H1+H2 (Olszewski)",0 1970,"Forel's field H2","human","English","field H2",,0 2374,"Formatio hippocampi","Unspecified","Latin","HIPPOCAMPAL FORMATION",,0 2417,"Formatio reticularis","human","Latin",,"reticular formation",43 2418,"Formatio reticularis","Macaca nemestrina","Latin",,"reticular formation",43 2424,"Formatio reticularis mesencephali","Unspecified","Latin","MIDBRAIN RETICULAR FORMATION",,9 -178161018,"Formatio reticularis mesencephali - not otherwise specified","Unspecified","Latin","MIDBRAIN RETICULAR FORMATION - not otherwise specified",,9 2447,"Formatio reticularis myelencephali","Macaca fascicularis","Latin","MEDULLARY RETICULAR FORMATION",,0 2443,"Formatio reticularis pontis","Macaca fascicularis","Latin","PONTINE RETICULAR FORMATION",,564 2428,"Formatio reticularis tegmentalis","human","Latin","MIDBRAIN RETICULAR FORMATION",,0 2427,"Formatio reticularis tegmenti mesencephali","Macaca fascicularis","Latin","MIDBRAIN RETICULAR FORMATION",,1 1609,"fornical commissure","human","English","commissure of fornix",,4 1653220015,"fornicate convolution","human","English","LIMBIC LOBE",,0 1281812534,"fornicate convolution","human","English",,"limbic lobe (Anthoney)",0 -1889991022,"fornicate gyrus","human","English","LIMBIC LOBE",,0 -889629755,"fornicate gyrus","human","English",,"limbic lobe (Anthoney)",0 524951892,"fornicate lobe","human","English",,"limbic lobe (Anthoney)",0 201827445,"fornicate lobe","human","English","LIMBIC LOBE",,0 160,"fornix","rat","English","FORNIX",,1864 159,"fornix","human","English","FORNIX",,1864 161,"Fornix","human","Latin","FORNIX",,1864 162,"Fornix","Macaca fascicularis","Latin","FORNIX",,1864 1698249194,"fornix cerebri","human","Latin","FORNIX",,1 6073,"Fornix dorsalis","human","Latin",,"dorsal fornix",0 6075,"Fornix longus","Unspecified","Latin",,"dorsal fornix",0 2228,"Fornix postcommissuralis","Unspecified","Latin","postcommissural fornix",,33 2232,"Fornix praecommissuralis","human","Latin","precommissural fornix",,0 2231,"Fornix precommissuralis","Unspecified","Latin","precommissural fornix",,0 6074,"Fornix superior","human","Latin",,"dorsal fornix",4 1680,"Fornix, corpus","human","Latin","body of fornix",,0 1534,"Fornix, crus anterius","human","Latin","anterior column of fornix",,0 1754,"Fornix, crus posterius","human","Latin","posterior column of fornix",,0 2479,"Fossa intercruralis","Macaca mulatta","Latin","interpeduncular fossa",,0 2476,"Fossa interpeduncularis","Macaca fascicularis","Latin","interpeduncular fossa",,2 2475,"Fossa interpeduncularis","human","Latin","interpeduncular fossa",,2 -692512216,"fossa interpeduncularis (Tarini)","human","Latin","interpeduncular fossa",,0 2481,"Fossa rhomboidea","human","Latin","rhomboid fossa",,2 11,"Fossa simiarum","Macaca","Latin","simian fossa (M)",,0 1825,"fountain decussation of Meynert","human","English","dorsal tegmental decussation",,0 319,"fourth cranial nerve","human","English","trochlear nerve",,44 759,"fourth ventricle","rat","English","FOURTH VENTRICLE",,1460 757,"fourth ventricle","human","English","FOURTH VENTRICLE",,1460 758,"fourth ventricle","Macaca fascicularis","English","FOURTH VENTRICLE",,1460 2484,"Fovea caudalis","human","Latin","inferior fovea",,0 -1415089176,"Fovea cranialis","human","Latin","superior fovea",,0 2483,"Fovea inferior","human","Latin","inferior fovea",,0 2487,"Fovea rostralis","human","Latin","superior fovea",,0 2486,"Fovea superior","human","Latin","superior fovea",,0 -2141362509,"Frankfurt zero plane","Unspecified","English",,"Frankfurt zero plane",0 2488,"frenulum","human","English",,"frenulum",109 -1428006216,"frenulum veli medullare anterioris","human","Latin",,"frenulum",0 2490,"Frenulum veli medullaris rostralis","human","Latin",,"frenulum",0 2491,"Frenulum veli medullaris superioris","human","Latin",,"frenulum",0 2489,"Frenulum veli medullaris superius","human","Latin",,"frenulum",0 1044,"frontal association areas","human","English",,"frontal region",0 851,"frontal belt","human","English",,"agranular frontal area 6",0 845,"frontal core","human","English",,"gigantopyramidal area 4",0 54,"frontal cortex","human","English","FRONTAL LOBE",,0 1045,"frontal cortex (Nauta)","human","English",,"frontal region",0 1118,"frontal eye field","human","English",,"frontal eye field",255 -240667991,"frontal forceps","human","English","anterior forceps of corpus callosum",,0 1119,"frontal gaze center","human","English",,"frontal eye field",0 1629,"frontal horn of lateral ventricle","human","English","frontal horn of lateral ventricle",,1 1630,"frontal horn of lateral ventricle","Macaca fascicularis","English","frontal horn of lateral ventricle",,1 52,"frontal lobe","Macaca fascicularis","English","FRONTAL LOBE",,12815 51,"frontal lobe","human","English","FRONTAL LOBE",,12815 1120,"frontal lobe eye field","human","English",,"frontal eye field",0 1121,"frontal motor eye field","human","English",,"frontal eye field",0 4488,"frontal nucleus of lateral lemniscus","human","English",,"frontal nucleus of lateral lemniscus",0 5585,"frontal operculum","human","English","frontal operculum",,69 5588,"frontal operculum (Ono)","human","English",,"frontal operculum (Ono)",0 5735,"frontal peduncle","human","English","anterior thalamic peduncle",,0 114134474,"frontal plane","Unspecified","English",,"coronal section",1031 5791,"frontal pole","human","English","frontal pole",,130 1036,"frontal region","human","English",,"frontal region",597 55,"frontal region","rat","English","FRONTAL LOBE",,597 5733,"frontal thalamic peduncle","human","English","anterior thalamic peduncle",,0 712,"frontal type cortex","human","English",,"frontal type cortex",0 -1974555373,"FRONTAL WHITE MATTER","Unspecified","English","FRONTAL WHITE MATTER",,184 1519234811,"frontal white matter - not otherwise specified","Unspecified","English","FRONTAL WHITE MATTER - not otherwise specified",,184 6390,"frontomarginal gyrus","human","English",,"frontomarginal gyrus (H)",0 6388,"frontomarginal sulcus","human","English",,"frontomarginal sulcus (H)",0 6484,"fronto-orbital dimple","Macaca mulatta","English","fronto-orbital sulcus",,0 2654,"fronto-orbital gyrus","Macaca mulatta","English","fronto-orbital gyrus (M)",,2 6480,"fronto-orbital sulcus","Macaca fascicularis","English","fronto-orbital sulcus",,0 6479,"fronto-orbital sulcus","human","English","fronto-orbital sulcus",,0 56704561,"fronto-orbital white matter","Unspecified","English","fronto-orbital white matter",,0 5592,"frontoparietal operculum (Ono)","human","English",,"frontoparietal operculum (Ono)",0 869,"frontopolar area (Mai)","human","English",,"frontopolar area (Mai)",0 871,"fronto-polar area (Mai)","human","English",,"frontopolar area (Mai)",0 864,"frontopolar area 10","human","English",,"frontopolar area 10",0 -1316099477,"frontopolar area 12 (M)","Unspecified","English",,"area 12 of Brodmann-09",0 2196,"frontopontine fibers","human","English",,"frontopontine fibers",0 2198,"frontopontine tract","human","English",,"frontopontine fibers",0 7244,"fundamental columns","human","English",,"Fasciculi proprii",0 3803,"fundamental gray substance","primate","English","anterior nucleus of hypothalamus",,0 2546,"fundus striati","human","English",,"fundus striati",0 2547,"Fundus striati","human","Latin",,"fundus striati",0 1920,"Funiculus anterior","Macaca mulatta","Latin",,"anterior funiculus",0 1919,"Funiculus anterior","human","Latin",,"anterior funiculus",0 1932,"Funiculus cuneatus","human","Latin",,"cuneate fasciculus",0 1949,"Funiculus gracilis","human","Latin",,"gracile fasciculus",0 2494,"Funiculus lateralis","Macaca mulatta","Latin",,"lateral funiculus",4 2493,"Funiculus lateralis","human","Latin",,"lateral funiculus",4 619,"Funiculus posterior s. F. cu, F. gr","Macaca mulatta","Latin",,"posterior white column",0 2495,"funiculus separans","human","English","funiculus separans",,1 2496,"Funiculus separans","human","Latin","funiculus separans",,1 2656,"fusiform gyrus","human","English","fusiform gyrus",,161 2657,"fusiform gyrus","Macaca fascicularis","English","fusiform gyrus",,161 2658,"fusiform gyrus","human","English","fusiform gyrus",,161 3026,"fusiform layer","human","English",,"multiform layer",0 -26204561,"fusiform white matter","Unspecified","English","fusiform white matter",,0 3468,"Ganglia basales","human","Latin","BASAL GANGLIA",,0 4260,"Ganglion dorsale tegmenti","human","Latin","dorsal tegmental nucleus",,0 1005138991,"Ganglion habenulae","human","Latin","HABENULA",,0 -1517519573,"Ganglion intercrurale","human","Latin","HABENULA",,0 1606174226,"Ganglion interpedunculare","human","Latin","HABENULA",,0 3914,"ganglion of Meynert","human","English","basal nucleus",,0 5523,"Ganglion profundum tegmenti","human","Latin","ventral tegmental nucleus",,0 5522,"Ganglion tegmenti ventrale","human","Latin","ventral tegmental nucleus",,0 3483,"Ganglion trigeminale","human","Latin",,"trigeminal ganglion",14 1807,"Ganser's commissure","human","English","dorsal supraoptic decussation",,0 3484,"Gasserian ganglion","human","English",,"trigeminal ganglion",266 5229,"gelatinosus thalamic nucleus","rat","English","submedial nucleus",,1 7184,"gelatinous substance","human","English",,"Rexed's lamina II",13 1540,"general somatic afferents","human","English",,"general somatic afferents",0 1546,"general somatic efferents","human","English",,"general somatic efferents",0 1542,"general visceral afferents","human","English",,"general visceral afferents",0 1544,"general visceral efferents","human","English",,"general visceral efferents",0 3486,"geniculate ganglion","human","English",,"geniculate ganglion",365 3487,"geniculate ganglion of facial nerve","human","English",,"geniculate ganglion",0 171,"geniculate group of the dorsal thalamus","rat","English","METATHALAMUS",,0 5868,"geniculocalcarine radiation","human","English",,"geniculocalcarine radiation",0 5874,"geniculocalcarine tract","human","English",,"geniculocalcarine radiation",2 5865,"geniculotemporal radiations","human","English",,"auditory radiation",0 5866,"geniculotemporal tract","human","English",,"auditory radiation",0 2507,"Genu capsulae internae","human","Latin","genu of internal capsule",,0 2504,"Genu corporis callosi","human","Latin","genu of corpus callosum",,6 2500,"Genu corpus callosi","human","Latin","genu of corpus callosum",,0 3267,"Genu nervi facialis","Macaca mulatta","Latin","internal genu of facial nerve",,0 3266,"Genu nervi facialis","human","Latin","internal genu of facial nerve",,0 2497,"genu of corpus callosum","human","English","genu of corpus callosum",,7 2498,"genu of corpus callosum","Macaca fascicularis","English","genu of corpus callosum",,7 2499,"genu of corpus callosum","rat","English","genu of corpus callosum",,7 3270,"genu of facial nerve","rat","English","internal genu of facial nerve",,1 2506,"genu of internal capsule","human","English","genu of internal capsule",,2 4997,"gigantocellular nucleus","rat","English","gigantocellular nucleus",,32 4996,"gigantocellular nucleus","Macaca fascicularis","English","gigantocellular nucleus",,32 5000,"gigantocellular reticular nucleus","rat","English","gigantocellular nucleus",,84 839,"gigantopyramidal area 4","human","English",,"gigantopyramidal area 4",0 1702,"Glandula pinealis","human","Latin","pineal body",,1 4304,"globose nucleus","Macaca fascicularis","English","globose nucleus",,1 4303,"globose nucleus","human","English","globose nucleus",,1 2509,"globus pallidus","human","English","GLOBUS PALLIDUS",,4507 2512,"globus pallidus","rat","English","GLOBUS PALLIDUS",,4507 2511,"Globus pallidus","Macaca fascicularis","Latin","GLOBUS PALLIDUS",,4507 2510,"Globus pallidus","human","Latin","GLOBUS PALLIDUS",,4507 2526,"Globus pallidus (rat)","rat","Latin","lateral globus pallidus",,0 2521,"Globus pallidus externus","human","Latin","lateral globus pallidus",,9 2530,"Globus pallidus internus","human","Latin","medial globus pallidus",,48 2519,"Globus pallidus lateralis","human","Latin","lateral globus pallidus",,1 2528,"Globus pallidus medialis","human","Latin","medial globus pallidus",,9 3002,"Globus pallidus, lamina medullaris interna","Macaca fascicularis","Latin","medial medullary lamina",,0 2989,"Globus pallidus, lamina medullaris externa","Macaca fascicularis","Latin","lateral medullary lamina",,0 2525,"globus pallidus, lateral segment","rat","English","lateral globus pallidus",,0 2535,"globus pallidus, medial segment","rat","English","medial globus pallidus",,0 2522,"Globus pallidus, pars externa","Macaca fuscata","Latin","lateral globus pallidus",,0 2529,"Globus pallidus, pars interna","Macaca fuscata","Latin","medial globus pallidus",,0 2517,"Globus pallidus, pars supracapsularis","human","Latin",,"supracapsular part of globus pallidus",0 -589430626,"Glomus choroideum","human","Latin",,"glomus of choroid plexus",0 5789,"glomus of chorioid plexus","human","English",,"glomus of choroid plexus",0 5788,"glomus of choroid plexus","human","English",,"glomus of choroid plexus",0 3271,"glossopharyngeal nerve","human","English","glossopharyngeal nerve",,1179 3351,"glossopharyngeal nerve fibers","Macaca fascicularis","English","glossopharyngeal nerve fibers",,1 3350,"glossopharyngeal nerve fibers","human","English","glossopharyngeal nerve fibers",,1 4319,"Goll's nucleus","Unspecified","English","gracile nucleus",,0 2117517131,"goose's foot","human","English",,"Pes anserinus",0 1947,"gracile fascicle","rat","English",,"gracile fasciculus",0 1944,"gracile fasciculus","rat","English",,"gracile fasciculus",24 1943,"gracile fasciculus","human","English",,"gracile fasciculus",24 1954,"gracile fasciculus of medulla","human","English","gracile fasciculus of medulla",,0 1955,"gracile fasciculus of medulla","Macaca fascicularis","English","gracile fasciculus of medulla",,0 1958,"gracile fasciculus of spinal cord","human","English",,"gracile fasciculus of spinal cord",0 3134,"gracile lobule","Macaca fascicularis","English","gracile lobule",,0 3133,"gracile lobule","human","English","gracile lobule",,0 4315,"gracile nucleus","Macaca fascicularis","English","gracile nucleus",,170 4316,"gracile nucleus","rat","English","gracile nucleus",,170 4314,"gracile nucleus","human","English","gracile nucleus",,170 6999,"gracilis tubercle","human","English","gracilis tubercle",,0 858,"granular frontal area 9","human","English",,"granular frontal area 9",0 6028,"granular layer of cerebellar cortex","human","English",,"granular layer of cerebellar cortex",0 2412,"granular layer of dentate gyrus","Macaca mulatta","English",,"granular layer of dentate gyrus",0 2411,"granular layer of dentate gyrus","human","English",,"granular layer of dentate gyrus",0 1013,"granular retrolimbic area 29","human","English",,"granular retrolimbic area 29",0 709,"granulous cortex","human","English",,"granulous cortex",0 7132,"gray commissure","human","English",,"gray commissure",52 2916,"gray stria of Lancisi","human","English","induseum griseum",,0 1495,"great cistern","human","English","cerebellomedullary cistern",,3 2289,"great horizontal fissure","human","English","horizontal fissure",,1 2806,"great transverse gyrus of Heschl","human","English","anterior transverse temporal gyrus (H)",,0 6144,"grey commissure","Macaca mulatta","English",,"grey commissure",0 6121,"Griseum centrale","Macaca mulatta","Latin","central gray substance of midbrain",,72 6113,"Griseum centrale","Macaca mulatta","Latin",,"central gray substance",72 6123,"Griseum centrale mesencephali","Macaca mulatta","Latin","central gray substance of midbrain",,2 6122,"Griseum centrale mesencephali","human","Latin","central gray substance of midbrain",,2 2949,"Griseum centrale mesencephali, subnucleus dorsalis","human","Latin",,"dorsal subnucleus of midbrain central gray",0 2947,"Griseum centrale mesencephali, subnucleus lateralis","human","Latin",,"lateral subnucleus of midbrain central gray",0 2951,"Griseum centrale mesencephali, subnucleus medialis","human","Latin",,"medial subnucleus of midbrain central gray",0 6136,"Griseum centrale pontis","Macaca mulatta","Latin","central gray substance of pons",,2 6142,"Griseum periventriculare","Macaca fascicularis","Latin","central gray substance of medulla",,14 6135,"Griseum periventriculare","Macaca fascicularis","Latin","central gray substance of pons",,14 6112,"Griseum periventriculare","Macaca fascicularis","Latin",,"central gray substance",14 3438,"Griseum periventriculare hypothalami","Macaca fascicularis","Latin",,"periventricular zone of hypothalamus",1 4850,"Griseum periventriculare hypothalami","Macaca fascicularis","Latin","posterior periventricular nucleus",,1 6120,"Griseum periventriculare mesencephali","Macaca fascicularis","Latin","central gray substance of midbrain",,0 2436,"Griseum pontis","Macaca fascicularis","Latin",,"pontine gray",13 4110,"Griseum praegeniculatum","human","Latin","ventral nucleus of lateral geniculate body",,0 1541,"GSA","human","Abbreviation",,"general somatic afferents",0 1547,"GSE","human","Abbreviation",,"general somatic efferents",0 1812,"Gudden's commissure","human","English","ventral supraoptic decussation",,0 1241,"gustatory area","human","English",,"gustatory area",0 1242,"gustatory cortex","human","English",,"gustatory area",40 4321,"gustatory gray","human","English",,"gustatory nucleus",0 4320,"gustatory nucleus","human","English",,"gustatory nucleus",0 5507,"gustatory thalamic nucleus","rat","English","parvicellular part of ventral posteromedial nucleus",,2 1543,"GVA","human","Abbreviation",,"general visceral afferents",0 1545,"GVE","human","Abbreviation",,"general visceral efferents",0 2550,"Gyri breves insulae","human","Latin","SHORT INSULAR GYRI (H)",,0 2561,"Gyri cerebrales","human","Latin",,"cerebral gyri",0 2559,"Gyri cerebri","human","Latin",,"cerebral gyri",0 2585,"Gyri cinguli","human","Latin","CINGULATE GYRUS",,2 2699,"Gyri longi","human","Latin","LONG INSULAR GYRI (H)",,0 2698,"Gyri longus insulae","human","Latin","LONG INSULAR GYRI (H)",,0 2800,"gyri of Heschl","human","English",,"transverse temporal gyri",0 2563,"Gyri orbitales","human","Latin","ORBITAL GYRI",,0 2799,"Gyri temporales transversi","human","Latin",,"transverse temporal gyri",0 2708,"Gyrus accessorius anterior","human","Latin","anterior accessory gyrus (H)",,0 2709,"Gyrus accessorius anterior of insula","human","Latin","anterior accessory gyrus (H)",,0 3123,"Gyrus ambiens (Noback)","human","Latin","limen of insula",,0 2570,"Gyrus ambiens (Willis)","human","Latin",,"ambiens gyrus",0 2575,"Gyrus angularis","human","Latin","angular gyrus",,6 3,"Gyrus annectens","Unspecified","Latin","annectant gyrus (M)",,0 2706,"Gyrus brevis accessorius","human","Latin","accessory short gyrus (H)",,0 2553,"Gyrus brevis I","human","Latin","first short gyrus (H)",,0 2555,"Gyrus brevis II","human","Latin","second short gyrus (H)",,0 2557,"Gyrus brevis intermedius","human","Latin","intermediate short gyrus (H)",,0 2778,"Gyrus centralis anterior","Macaca nemestrina","Latin","precentral gyrus",,1 2770,"Gyrus centralis posterior","Macaca nemestrina","Latin","postcentral gyrus",,1 2702,"Gyrus centralis posterior primus","human","Latin","first posterior central gyrus (H)",,0 2727,"Gyrus centralis posterior primus","human","Latin","first posterior central gyrus (H)",,0 2704,"Gyrus centralis posterior secundus","human","Latin","second posterior central gyrus (H)",,0 2728,"Gyrus centralis posterior secundus","human","Latin","second posterior central gyrus (H)",,0 2581,"Gyrus cingulatus","human","Latin","CINGULATE GYRUS",,0 2583,"Gyrus cinguli","Macaca nemestrina","Latin","CINGULATE GYRUS",,1320 2582,"Gyrus cinguli","human","Latin","CINGULATE GYRUS",,1320 2594,"Gyrus cinguli anterior","human","Latin","anterior cingulate gyrus",,3 2598,"Gyrus cinguli posterior","human","Latin","posterior cingulate gyrus",,53 1769,"Gyrus cuneus","human","Latin","cuneus",,0 2386,"Gyrus dentatus","human","Latin","DENTATE GYRUS",,63 2387,"Gyrus dentatus","Macaca nemestrina","Latin","DENTATE GYRUS",,63 3882,"Gyrus diagonalis","human","Latin","diagonal band",,0 -1461860482,"gyrus diagonalis rhinencephli","human","Latin","diagonal band",,0 2653,"Gyrus F1","human","Latin","superior frontal gyrus",,0 2642,"Gyrus F2","human","Latin","middle frontal gyrus",,0 2614,"Gyrus F3","human","Latin","INFERIOR FRONTAL GYRUS",,1 2601,"Gyrus fasciolaris","human","Latin","fasciolar gyrus",,1 3671,"Gyrus fasciolaris (Amaral)","human","Latin",,"Gyrus fasciolaris (Amaral)",0 -725078823,"Gyrus fornicatus","human","Latin","LIMBIC LOBE",,0 754963656,"Gyrus fornicatus","human","Latin",,"limbic lobe (Anthoney)",0 2609,"Gyrus frontalis inferior","human","Latin","INFERIOR FRONTAL GYRUS",,1 2610,"Gyrus frontalis inferior","Macaca nemestrina","Latin","INFERIOR FRONTAL GYRUS",,1 2616,"Gyrus frontalis inferior, pars opercularis","human","Latin","opercular part of inferior frontal gyrus (H)",,0 2741,"Gyrus frontalis inferior, pars orbitalis","human","Latin","orbital part of inferior frontal gyrus (H)",,0 2627,"Gyrus frontalis inferior, pars triangularis","human","Latin","triangular part of inferior frontal gyrus (H)",,0 2644,"Gyrus frontalis medialis","human","Latin",,"medial frontal gyrus",0 2639,"Gyrus frontalis medialis (Winters)","Macaca nemestrina","Latin","middle frontal gyrus",,0 2638,"Gyrus frontalis medius","human","Latin","middle frontal gyrus",,2 2652,"Gyrus frontalis primus","human","Latin","superior frontal gyrus",,0 2641,"Gyrus frontalis secundus","human","Latin","middle frontal gyrus",,0 2649,"Gyrus frontalis superior","Macaca nemestrina","Latin","superior frontal gyrus",,2 2648,"Gyrus frontalis superior","human","Latin","superior frontal gyrus",,2 2645,"Gyrus frontalis superior pars medialis","human","Latin",,"medial frontal gyrus",0 2613,"Gyrus frontalis tertius","human","Latin","INFERIOR FRONTAL GYRUS",,0 6391,"Gyrus frontomarginalis","human","Latin",,"frontomarginal gyrus (H)",0 2655,"Gyrus fronto-orbitalis","Unspecified","Latin","fronto-orbital gyrus (M)",,0 1140864346,"Gyrus frontopolaris transversus","human","Latin","TRANSVERSE FRONTOPOLAR GYRI (H)",,0 715407110,"Gyrus frontopolaris transversus inferior","human","Latin","inferior transverse frontopolar gyrus (H)",,0 -1122141995,"Gyrus frontopolaris transversus med.","human","Latin","medial transverse frontopolar gyrus (H)",,0 -1399752976,"Gyrus frontopolaris transversus superior","human","Latin","superior transverse frontopolar gyrus (H)",,0 2659,"Gyrus fusiformis","human","Latin","fusiform gyrus",,2 2660,"Gyrus fusiformis","Macaca mulatta","Latin","fusiform gyrus",,2 2752,"Gyrus hippocampi","human","Latin","PARAHIPPOCAMPAL GYRUS",,4 1721,"Gyrus hippocampi (Shantha)","Macaca fascicularis","Latin",,"Gyrus hippocampi (Shantha)",0 553790951,"gyrus intralimbicus","human","Latin",,"intralimbic gyrus",0 2686,"Gyrus lingualis","human","Latin","lingual gyrus",,0 2685,"Gyrus lingualis","Macaca mulatta","Latin","lingual gyrus",,0 2684,"Gyrus lingualis","human","Latin","lingual gyrus",,0 2697,"Gyrus longus insulae","human","Latin","LONG INSULAR GYRI (H)",,0 2730,"Gyrus medius olfactorius","human","Latin","medial olfactory gyrus",,0 2712,"Gyrus occipitalis","Macaca nemestrina","Latin","occipital gyrus (M)",,0 2725,"Gyrus occipitalis inferior","human","Latin",,"Gyrus occipitalis inferior (H)",0 2714,"Gyrus occipitalis inferior","Unspecified","Latin","inferior occipital gyrus (M)",,0 2716,"Gyrus occipitalis lateralis","Unspecified","Latin","lateral occipital gyrus (H)",,0 2723,"Gyrus occipitalis medius","human","Latin",,"Gyrus occipitalis medius (H)",0 2717,"Gyrus occipitalis medius (Mai)","human","Latin","lateral occipital gyrus (H)",,0 2721,"Gyrus occipitalis primus","human","Latin","superior occipital gyrus (H)",,0 2718,"Gyrus occipitalis secundus","human","Latin","lateral occipital gyrus (H)",,0 2720,"Gyrus occipitalis superior","human","Latin","superior occipital gyrus (H)",,0 2726,"Gyrus occipitalis tertius","human","Latin",,"Gyrus occipitalis inferior (H)",0 2662,"Gyrus occipitotemporalis lateralis","human","Latin","fusiform gyrus",,1 2661,"Gyrus occipito-temporalis lateralis","human","Latin","fusiform gyrus",,0 2693,"Gyrus occipitotemporalis medialis","human","Latin",,"medial occipitotemporal gyrus (Mai)",0 2690,"Gyrus occipitotemporalis medialis","human","Latin","lingual gyrus",,0 2694,"Gyrus occipito-temporalis medialis","human","Latin",,"medial occipitotemporal gyrus (Mai)",0 2695,"Gyrus occipitotemporalis medialis (Nomina)","human","Latin",,"Gyrus occipitotemporalis medialis (Nomina)",0 -1363059143,"gyrus olfactorius lateralis","human","Latin","prepyriform area",,0 -1171340686,"Gyrus orbitalis","Macaca mulatta","Latin","ORBITAL GYRI",,0 2733,"Gyrus orbitalis lateralis","human","Latin","lateral orbital gyrus",,0 -684263612,"gyrus orbitalis longitudinalis","human","Latin","ORBITAL GYRI",,0 1017131791,"gyrus orbitalis longitudinalis externus","human","Latin","lateral orbital gyrus",,0 -1507742763,"gyrus orbitalis longitudinalis internus","human","Latin","medial orbital gyrus",,0 416956971,"Gyrus orbitalis longitudinalis medius","human","Latin","intermediate orbital gyrus (H)",,0 2738,"Gyrus orbitalis medialis","human","Latin","medial orbital gyrus",,0 2739,"Gyrus orbitalis medius","Unspecified","Latin","medial orbital gyrus",,0 -1573083059,"Gyrus orbitalis posterior","human","Latin","posterior orbital gyrus (H)",,0 -53916582,"gyrus orbitalis transversus","human","Latin","TRANSVERSE FRONTOPOLAR GYRI (H)",,0 2566,"Gyrus orbitofrontalis","human","Latin","ORBITAL GYRI",,0 2750,"Gyrus parahippocampalis","human","Latin","PARAHIPPOCAMPAL GYRUS",,3 2751,"Gyrus parahippocampalis","Macaca nemestrina","Latin","PARAHIPPOCAMPAL GYRUS",,3 2757,"Gyrus parahippocampalis, pars posterior","Unspecified","Latin","posterior parahippocampal gyrus",,0 2755,"Gyrus parahippocampi","human","Latin","PARAHIPPOCAMPAL GYRUS",,0 2762,"Gyrus paraterminalis","human","Latin","paraterminal gyrus",,0 2577,"Gyrus parietalis inferior","Macaca nemestrina","Latin","angular gyrus",,0 2576,"Gyrus parietalis inferior","human","Latin","angular gyrus",,0 3149,"Gyrus parietalis medialis","human","Latin",,"medial parietal gyrus",0 3147,"Gyrus parietalis medialis (Winters)","Macaca nemestrina","Latin",,"Gyrus parietalis medialis (Winters)",0 2722,"Gyrus parietalis occipitalis","Macaca nemestrina","Latin",,"Gyrus parietalis occipitalis (M)",0 3154,"Gyrus parietalis superior","Macaca nemestrina","Latin","superior parietal lobule",,0 3153,"Gyrus parietalis superior","human","Latin","superior parietal lobule",,0 2769,"Gyrus postcentralis","human","Latin","postcentral gyrus",,186 2777,"Gyrus praecentralis","human","Latin","precentral gyrus",,0 2776,"Gyrus precentralis","human","Latin","precentral gyrus",,4 2782,"Gyrus precentralis insulae","human","Latin","precentral gyrus of insula (H)",,0 2784,"gyrus rectus","human","English","gyrus rectus",,48 2785,"gyrus rectus","Macaca fascicularis","English","gyrus rectus",,48 2787,"Gyrus rectus","Macaca nemestrina","Latin","gyrus rectus",,48 2786,"Gyrus rectus","human","Latin","gyrus rectus",,48 2603,"Gyrus retrosplenialis hippocampi","human","Latin","fasciolar gyrus",,0 332774538,"Gyrus rostralis inferior","human","Latin","inferior rostral gyrus (H)",,0 -1981198905,"Gyrus rostralis superior","human","Latin","superior rostral gyrus (H)",,0 1209,"Gyrus semilunaris","human","Latin","periamygdaloid area",,0 2764,"Gyrus subcallosus","human","Latin","paraterminal gyrus",,0 2919,"Gyrus supracallosus","human","Latin","SUPRACALLOSAL GYRUS",,0 2794,"Gyrus supramarginalis","human","Latin","supramarginal gyrus",,4 2815,"Gyrus temporalis inferior","Macaca nemestrina","Latin","inferior temporal gyrus",,0 2814,"Gyrus temporalis inferior","human","Latin","inferior temporal gyrus",,0 2819,"Gyrus temporalis medius","human","Latin","middle temporal gyrus",,1 2668,"Gyrus temporalis occipitalis lateralis","Macaca nemestrina","Latin",,"Gyrus temporalis occipitalis lateralis (M)",0 2824,"Gyrus temporalis superior","Macaca nemestrina","Latin","superior temporal gyrus",,1 2823,"Gyrus temporalis superior","human","Latin","superior temporal gyrus",,1 2804,"Gyrus temporalis transversus anterior","human","Latin","anterior transverse temporal gyrus (H)",,0 2810,"Gyrus temporalis transversus posterior","Unspecified","Latin","posterior transverse temporal gyrus (H)",,0 2805,"Gyrus temporalis transversus primus","human","Latin","anterior transverse temporal gyrus (H)",,0 2833,"Gyrus uncinatus","human","Latin",,"uncinate gyrus",0 2834,"Gyrus uncinatus","Macaca fascicularis","Latin",,"uncinate gyrus",0 1405,"H field of Forel","human","English","field H",,4 2099,"H1 bundle of Forel","human","English","field H1",,0 2107,"H1 field of Forel","human","English","field H1",,0 1964,"H2 bundle of Forel","human","English","field H2",,0 2836,"habenula","human","English","HABENULA",,856 2837,"habenula","Macaca fascicularis","English","HABENULA",,856 2838,"Habenula","human","Latin","HABENULA",,856 4338,"habenular commissure","human","English","habenular commissure",,51 4340,"habenular commissure","rat","English","habenular commissure",,51 4339,"habenular commissure","Macaca fascicularis","English","habenular commissure",,51 2840,"habenular nuclei","human","English","HABENULA",,164 6348,"habenular sulcus","human","English","habenular sulcus",,0 6952,"habenular trigone","human","English","habenular trigone",,0 -876706729,"habenulointerpeduncular fasciculus","human","English",,"habenulo-interpeduncular tract",0 -165596818,"habenulointerpeduncular tract","human","English",,"habenulo-interpeduncular tract",4 162261290,"habenulo-interpeduncular tract","human","English",,"habenulo-interpeduncular tract",15 523483235,"habenulo-interpeduncular tract","Macaca fascicularis","English",,"habenulo-interpeduncular tract",15 2003598941,"habenulo-interpeduncular tract of diencephalon","Macaca fascicularis","English","habenulo-interpeduncular tract of diencephalon",,0 643328536,"habenulo-interpeduncular tract of midbrain","Macaca fascicularis","English","habenulo-interpeduncular tract of midbrain",,0 -1817214647,"habenulopeduncular tract","human","English",,"habenulo-interpeduncular tract",5 1437,"head of caudate nucleus","human","English","head of caudate nucleus",,29 1438,"head of caudate nucleus","Macaca fascicularis","English","head of caudate nucleus",,29 2844,"Hemisphaerium cerebelli","human","Latin",,"cerebellar hemisphere",0 2849,"hemisphere of anterior lobe","Macaca fascicularis","English","HEMISPHERE OF ANTERIOR LOBE",,0 2848,"hemisphere of anterior lobe","human","English","HEMISPHERE OF ANTERIOR LOBE",,0 2846,"hemisphere of cerebellum","human","English",,"cerebellar hemisphere",0 2852,"hemisphere of posterior lobe","Macaca fascicularis","English","HEMISPHERE OF POSTERIOR LOBE",,0 2851,"hemisphere of posterior lobe","human","English","HEMISPHERE OF POSTERIOR LOBE",,0 -874944313,"hemispheria cerebri","human","Latin",,"cerebral hemisphere",0 2300,"hemispheric sulcus","human","English","longitudinal fissure",,3 2847,"hemispheric zone","human","English",,"cerebellar hemisphere",0 2843,"Hemispherium cerebelli","human","Latin",,"cerebellar hemisphere",0 2112,"Hemispherium cerebralis","human","Latin",,"cerebral hemisphere",0 2111,"Hemispherium cerebri","human","Latin",,"cerebral hemisphere",0 2850,"Hemispherium lobus anterior","Unspecified","Latin","HEMISPHERE OF ANTERIOR LOBE",,0 2853,"Hemispherium lobus posterior","Unspecified","Latin","HEMISPHERE OF POSTERIOR LOBE",,0 2801,"Heschl's convolutions","human","English",,"transverse temporal gyri",0 682,"heterogenetic cortex","human","English",,"allocortex",0 704,"heterotypic cortex","human","English",,"heterotypic cortex",0 705,"heterotypical cortex","human","English",,"heterotypic cortex",0 -140260780,"Hi internal feature","Unspecified","English","Hi internal feature",,0 1867950390,"Hi internal feature 1","Unspecified","English","Hi internal feature 1",,0 -646058552,"Hi internal feature 2","Unspecified","English","Hi internal feature 2",,0 2855,"Hilum nuclei dentati","human","Latin","hilum of dentate nucleus",,0 2858,"Hilum nuclei olivaris caudalis","human","Latin","hilum of inferior olive",,0 2857,"Hilum nuclei olivaris inferioris","human","Latin","hilum of inferior olive",,0 2854,"hilum of dentate nucleus","human","English","hilum of dentate nucleus",,0 2856,"hilum of inferior olive","human","English","hilum of inferior olive",,0 2403,"Hilus gyri dentati","Unspecified","Latin","hilus of dentate gyrus",,0 2402,"hilus of dentate gyrus","human","English","hilus of dentate gyrus",,7 -767956845,"hilus of inferior olivary nucleus","human","English","hilum of inferior olive",,0 23,"hindbrain","human","English","HINDBRAIN",,1868 1261471228,"hip internal feature","Unspecified","English","hip internal feature",,0 1608,"hippocampal commissure","human","English","commissure of fornix",,125 6355,"hippocampal fissure","Macaca mulatta","English","hippocampal sulcus",,75 6354,"hippocampal fissure","human","English","hippocampal sulcus",,75 2373,"hippocampal formation","Macaca fascicularis","English","HIPPOCAMPAL FORMATION",,2860 2372,"hippocampal formation","human","English","HIPPOCAMPAL FORMATION",,2860 2377,"hippocampal formation (Amaral)","human","English",,"hippocampal formation (Amaral)",0 2754,"hippocampal gyrus","Macaca mulatta","English","PARAHIPPOCAMPAL GYRUS",,41 2753,"hippocampal gyrus","human","English","PARAHIPPOCAMPAL GYRUS",,41 1061,"hippocampal region","human","English",,"hippocampal region",2 2376,"hippocampal rudiment","human","English",,"hippocampal rudiment",0 6352,"hippocampal sulcus","Macaca mulatta","English","hippocampal sulcus",,10 6351,"hippocampal sulcus","human","English","hippocampal sulcus",,10 98,"hippocampus","human","English","HIPPOCAMPUS",,45933 100,"Hippocampus","Macaca fascicularis","English","HIPPOCAMPUS",,45933 99,"Hippocampus","human","Latin","HIPPOCAMPUS",,45933 2375,"hippocampus (Crosby)","human","English","HIPPOCAMPAL FORMATION",,0 104,"hippocampus major","human","English","HIPPOCAMPUS",,1 2765,"Hippocampus praecommissuralis","human","Latin","paraterminal gyrus",,0 1792840352,"Hippocampus praecommissuralis","marmoset","Latin","paraterminal gyrus",,0 105,"hippocampus proper","human","English","HIPPOCAMPUS",,173 106,"Hippocampus retrocommissuralis","human","Latin",,"retrocommissural hippocampus",0 2088863265,"Hippocampus retrocommissuralis","marmoset","Latin",,"retrocommissural hippocampus",0 2922,"Hippocampus supracommissuralis","human","Latin","SUPRACALLOSAL GYRUS",,0 -261765253,"Hippocampus supracommissuralis","marmoset","Latin","SUPRACALLOSAL GYRUS",,0 3218,"homogenetic cortex","human","English",,"neocortex",0 -29471046,"homotypic cortex","human","English",,"neocortex",0 -228479386,"homotypic isocortex","human","English",,"neocortex",0 942600883,"homotypical cortex","human","English",,"neocortex",5 2134,"hook bundle of Russell","human","English","uncinate fasciculus of pons",,4 6221,"horizontal arcuate sulcus","Macaca mulatta","English","superior ramus of arcuate sulcus (M)",,0 6366,"horizontal dimple","human","English","intracingulate sulcus",,0 2287,"horizontal fissure","human","English","horizontal fissure",,17 6422,"horizontal limb of lateral fissure","human","English","anterior horizontal limb of lateral sulcus (H)",,0 6425,"horizontal ramus of Sylvian fissure","human","English","anterior horizontal limb of lateral sulcus (H)",,0 -1025634625,"horizontal section","Unspecified","English",,"horizontal section",0 1328,"horizontal zero","Macaca fascicularis","English",,"Horsley-Clarke zero plane",0 1654,"horns of lateral ventricle","human","English",,"horns of lateral ventricle",0 1327,"Horsley-Clark zero stereotaxic reference","Macaca nemestrina","English",,"Horsley-Clarke zero plane",0 1326,"Horsley-Clarke zero plane","Unspecified","English",,"Horsley-Clarke zero plane",0 1325,"Horsley-Frankfurt zero reference line","Macaca nemestrina","English",,"Frankfurt zero plane",0 4928,"HPe","Macaca fascicularis","Abbreviation","intermediate periventricular nucleus",,0 136385704,"human brain","human","English",,"human brain",10284 1043,"hyperfrontal cortex","human","English",,"frontal region",0 6961,"hypoglossal eminence","human","English","hypoglossal trigone",,0 289,"hypoglossal nerve","human","English","hypoglossal nerve",,1796 290,"hypoglossal nerve","Macaca fascicularis","English","hypoglossal nerve",,1796 297,"hypoglossal nerve fibers","Macaca fascicularis","English","hypoglossal nerve fibers",,3 296,"hypoglossal nerve fibers","human","English","hypoglossal nerve fibers",,3 4590,"hypoglossal nerve nucleus","human","English","hypoglossal nucleus",,8 4584,"hypoglossal nucleus","Macaca fascicularis","English","hypoglossal nucleus",,520 4583,"hypoglossal nucleus","human","English","hypoglossal nucleus",,520 4585,"hypoglossal nucleus","rat","English","hypoglossal nucleus",,520 6958,"hypoglossal trigone","human","English","hypoglossal trigone",,0 238,"hypophysial stalk","human","English",,"infundibular stalk (Crosby)",60 227,"hypophysis","Macaca fascicularis","English","HYPOPHYSIS",,1873 226,"hypophysis","human","English","HYPOPHYSIS",,1873 228,"Hypophysis","human","Latin","HYPOPHYSIS",,1873 233,"Hypophysis (Carpenter)","human","Latin",,"Hypophysis (Carpenter)",0 229,"Hypophysis cerebri","human","Latin","HYPOPHYSIS",,10 6357,"hypothalamic sulcus","human","English","hypothalamic sulcus",,8 6837,"hypothalamohypophyseal tract","human","English",,"hypothalamohypophyseal tract",0 25330887,"hypothalamo-hypophysial tract","human","English",,"hypothalamohypophyseal tract",14 -1987757661,"hypothalamus","Unspecified","English","HYPOTHALAMUS - not otherwise specified",,38705 203,"hypothalamus","human","English","HYPOTHALAMUS",,38705 206,"Hypothalamus","Macaca fascicularis","English","HYPOTHALAMUS",,38705 204,"hypothalamus","Macaca fascicularis","English","HYPOTHALAMUS",,38705 205,"Hypothalamus","human","Latin","HYPOTHALAMUS",,38705 1475580840,"Hypothalamus","Unspecified","Latin","HYPOTHALAMUS - not otherwise specified",,38705 -388716587,"Incisura","human","Latin",,"tentorial incisure",178 2891,"Incisura","human","Latin","anterior cerebellar incisure",,178 2889,"Incisura anterior cerebelli","Unspecified","Latin","anterior cerebellar incisure",,0 2911,"Incisura impressio unci","human","Latin",,"uncal notch",0 142581578,"incisura parieto-occipitalis","human","Latin","preoccipital notch",,0 2901,"Incisura posterior cerebelli","Unspecified","Latin","posterior cerebellar incisure",,0 2904,"Incisura praeoccipitalis","human","Latin","preoccipital notch",,0 2903,"Incisura preoccipitalis","human","Latin","preoccipital notch",,0 2909,"Incisura unci","human","Latin",,"uncal notch",0 2890,"incisure of tentorium cerebelli","human","English","anterior cerebellar incisure",,0 2981,"incomplete medullary lamina of globus pallidus","human","English","accessory medullary lamina",,0 2913,"induseum griseum","rat","English","induseum griseum",,15 2914,"Induseum griseum","human","Latin","induseum griseum",,15 2915,"indusium griseum","human","English","induseum griseum",,52 2912,"indusium griseum","human","English","induseum griseum",,52 1350,"inferior brachium","human","English","brachium of inferior colliculus",,0 6242,"inferior calcarine sulcus","Macaca fascicularis","English","inferior calcarine sulcus (M)",,0 4387,"inferior central nucleus","human","English","inferior central nucleus",,7 4390,"inferior central nucleus (of Roller)","human","English","inferior central nucleus",,0 4389,"inferior central nucleus of raphe","human","English","inferior central nucleus",,0 4391,"inferior central tegmental nucleus","human","English","inferior central nucleus",,0 1581,"inferior cerebellar commissure","human","English",,"posterior cerebellar commissure",0 1580,"inferior cerebellar decussation","human","English",,"posterior cerebellar commissure",0 468,"inferior cerebellar peduncle","Macaca fascicularis","English","inferior cerebellar peduncle",,65 469,"inferior cerebellar peduncle","rat","English","inferior cerebellar peduncle",,65 467,"inferior cerebellar peduncle","human","English","inferior cerebellar peduncle",,65 1347,"inferior collicular brachium","human","English","brachium of inferior colliculus",,0 1590,"inferior collicular commissure","human","English","commissure of inferior colliculus",,1 363,"inferior colliculus","human","English","INFERIOR COLLICULUS",,2199 364,"inferior colliculus","Macaca fascicularis","English","INFERIOR COLLICULUS",,2199 -73800438,"inferior colliculus - not otherwise specified","Unspecified","English","INFERIOR COLLICULUS - not otherwise specified",,2199 3927,"inferior colliculus, central nucleus","rat","English","central nucleus of inferior colliculus",,0 4344,"inferior commissure of spinal cord","human","English",,"inferior commissure of spinal cord",0 278,"inferior division of oculomotor nerve","human","English",,"inferior division of oculomotor nerve",0 2482,"inferior fovea","Unspecified","English","inferior fovea",,1 2611,"inferior frontal convolution","human","English","INFERIOR FRONTAL GYRUS",,3 6334,"inferior frontal fissure","human","English","inferior frontal sulcus (H)",,0 2607,"inferior frontal gyrus","human","English","INFERIOR FRONTAL GYRUS",,169 2608,"inferior frontal gyrus","Macaca mulatta","English","INFERIOR FRONTAL GYRUS",,169 2620,"inferior frontal gyrus, opercular part","human","English","opercular part of inferior frontal gyrus (H)",,0 2743,"inferior frontal gyrus, orbital part","human","English","orbital part of inferior frontal gyrus (H)",,0 2630,"inferior frontal gyrus, triangular part","human","English","triangular part of inferior frontal gyrus (H)",,0 6330,"inferior frontal sulcus","human","English","inferior frontal sulcus (H)",,12 -1538582344,"inferior frontal white matter","Unspecified","English","inferior frontal white matter",,0 2122,"inferior fronto-occipital fasciculus","human","English",,"inferior occipitofrontal fasciculus",0 1644,"inferior horn of lateral ventricle","human","English","temporal horn of lateral ventricle",,0 6441,"inferior limiting sulcus","Macaca","English",,"inferior marginal sulcus of insula",0 2023,"inferior longitudinal fasciculus","human","English",,"inferior longitudinal fasciculus",7 6440,"inferior marginal sulcus of insula","human","English",,"inferior marginal sulcus of insula",0 3094,"inferior medullary lamina","human","English","inferior medullary lamina",,0 7021,"inferior medullary velum","human","English","inferior medullary velum",,6 2724,"inferior occipital gyrus","human","English",,"Gyrus occipitalis inferior (H)",8 2713,"inferior occipital gyrus","Macaca mulatta","English","inferior occipital gyrus (M)",,8 890262768,"inferior occipital gyrus (M)","human","English",,,0 6464,"inferior occipital sulcus","Macaca fascicularis","English","inferior occipital sulcus (M)",,10 -1941387878,"inferior occipital white matter","Unspecified","English","inferior occipital white matter",,0 2120,"inferior occipitofrontal fasciculus","human","English",,"inferior occipitofrontal fasciculus",0 592,"inferior olivary complex","human","English","INFERIOR OLIVARY COMPLEX",,162 600,"inferior olivary complex","rat","English","INFERIOR OLIVARY COMPLEX",,162 -2032942224,"inferior olivary complex - not otherwise specified","Unspecified","English","INFERIOR OLIVARY COMPLEX - not otherwise specified",,162 4622,"inferior olivary complex, dorsal accessory olive","rat","English","dorsal accessory inferior olivary nucleus",,0 4631,"inferior olivary complex, medial accessory olive","rat","English","medial accessory inferior olivary nucleus",,0 4642,"inferior olivary complex, principal olive","rat","English","principal inferior olivary nucleus",,0 639,"inferior olivary eminence","human","English","inferior olive",,0 2859,"inferior olivary hilum","human","English","hilum of inferior olive",,2 594,"inferior olivary nuclear complex","Macaca fascicularis","English","INFERIOR OLIVARY COMPLEX",,6 593,"inferior olivary nuclear complex","human","English","INFERIOR OLIVARY COMPLEX",,6 598,"inferior olivary nucleus","Macaca fascicularis","English","INFERIOR OLIVARY COMPLEX",,279 4639,"inferior olivary nucleus (Barr & Kiernan)","human","English","principal inferior olivary nucleus",,0 601,"inferior olive","rat","English","INFERIOR OLIVARY COMPLEX",,1063 636,"inferior olive","human","English","inferior olive",,1063 4621,"inferior olive, dorsal nucleus","rat","English","dorsal accessory inferior olivary nucleus",,0 4632,"inferior olive, medial nucleus","rat","English","medial accessory inferior olivary nucleus",,0 4641,"inferior olive, principal nucleus","rat","English","principal inferior olivary nucleus",,0 653,"inferior optic radiation","human","English",,"inferior optic radiation",0 3145,"inferior parietal gyrus","human","English","INFERIOR PARIETAL LOBULE",,5 3143,"inferior parietal lobule","human","English","INFERIOR PARIETAL LOBULE",,203 2796,"inferior parietal lobule (Krieg)","Macaca mulatta","English","supramarginal gyrus",,0 2795,"inferior parietal lobule (Krieg)","Macaca mulatta","English","supramarginal gyrus",,0 6540,"inferior part of precentral fissure","human","English","inferior precentral sulcus (H)",,0 5729,"inferior peduncle","human","English","inferior thalamic peduncle",,10 6522,"inferior pontine sulcus","human","English","inferior pontine sulcus",,0 3146,"inferior portion of parietal gyrus","human","English","INFERIOR PARIETAL LOBULE",,0 6531,"inferior postcentral sulcus","human","English","inferior postcentral sulcus",,2 6538,"inferior precentral sulcus","human","English","inferior precentral sulcus (H)",,7 4947,"inferior pulvinar nucleus","Macaca fascicularis","English","inferior pulvinar nucleus",,9 4946,"inferior pulvinar nucleus","human","English","inferior pulvinar nucleus",,9 1346,"inferior quadrigeminal brachium","human","English","brachium of inferior colliculus",,0 6215,"inferior ramus of arcuate sulcus","Macaca fascicularis","English","inferior ramus of arcuate sulcus (M)",,0 6244,"inferior ramus of calcarine fissure","Macaca mulatta","English","inferior calcarine sulcus (M)",,0 331097421,"inferior rostral gyrus","human","English","inferior rostral gyrus (H)",,0 6567,"inferior rostral sulcus","human","English","inferior rostral sulcus (H)",,1 5121,"inferior salivatory nucleus","human","English","inferior salivatory nucleus",,14 5122,"inferior salivatory nucleus","rat","English","inferior salivatory nucleus",,14 3165,"inferior semilunar lobule","human","English","inferior semilunar lobule",,3 3166,"inferior semilunar lobule","Macaca fascicularis","English","inferior semilunar lobule",,3 932,"inferior temporal area 20","human","English",,"inferior temporal area 20",0 6596,"inferior temporal fissure (Crosby)","human","English","occipitotemporal sulcus",,0 2813,"inferior temporal gyrus","Macaca mulatta","English","inferior temporal gyrus",,90 2812,"inferior temporal gyrus","human","English","inferior temporal gyrus",,90 6598,"inferior temporal sulcus","human","English","inferior temporal sulcus (H)",,11 6599,"inferior temporal sulcus","human","English","inferior temporal sulcus (H)",,11 6595,"inferior temporal sulcus (Roberts)","human","English","occipitotemporal sulcus",,0 6593,"inferior temporal sulcus (Szikla)","human","English","occipitotemporal sulcus",,0 6607,"inferior temporal sulcus-1","human","English","inferior temporal sulcus (H)",,0 6597,"inferior temporal sulcus-2","human","English","occipitotemporal sulcus",,0 -865635439,"inferior temporal white matter","Unspecified","English","inferior temporal white matter",,0 5721,"inferior thalamic peduncle","Macaca fascicularis","English","inferior thalamic peduncle",,22 5720,"inferior thalamic peduncle","human","English","inferior thalamic peduncle",,22 5889,"inferior thalamic radiation","human","English",,"inferior thalamic radiations",0 5888,"inferior thalamic radiations","human","English",,"inferior thalamic radiations",0 -1489282247,"inferior transverse frontopolar gyrus","human","English","inferior transverse frontopolar gyrus (H)",,0 5545,"inferior vestibular nucleus","Macaca fascicularis","English","inferior vestibular nucleus",,30 5546,"inferior vestibular nucleus","rat","English","inferior vestibular nucleus",,30 5544,"inferior vestibular nucleus","human","English","inferior vestibular nucleus",,30 3097,"inferior white lamina","human","English","inferior medullary lamina",,0 3054,"infragranular layers","human","English",,"infragranular layers",218 3055,"infragranular layers of cortex","human","English",,"infragranular layers",0 4402,"infundibular hypothalamic nucleus","Macaca fascicularis","English","arcuate nucleus of hypothalamus",,3 4401,"infundibular nucleus","human","English","arcuate nucleus of hypothalamus",,107 4404,"infundibular periventricular nucleus","human","English","arcuate nucleus of hypothalamus",,0 2887,"infundibular process","human","English","NEUROHYPOPHYSIS",,11 225,"infundibular process (Crosby)","human","English",,"infundibular process (Crosby)",0 5909,"infundibular recess","rat","English","infundibular recess",,76 5908,"infundibular recess","human","English","infundibular recess",,76 224,"infundibular stalk","human","English","infundibular stem",,61 236,"infundibular stalk","human","English",,"infundibular stalk (Crosby)",61 222,"infundibular stem","rat","English","infundibular stem",,28 221,"infundibular stem","human","English","infundibular stem",,28 223,"Infundibulum","human","Latin","infundibular stem",,993 3041,"inner layer of large pyramidal cells","human","English",,"internal pyramidal layer",0 3005,"inner medullary lamina","human","English","medial medullary lamina",,0 75,"insula","human","English","INSULA",,573 76,"insula","Macaca","English","INSULA",,573 77,"Insula","human","Latin","INSULA",,573 78,"Insula","Macaca nemestrina","Latin","INSULA",,573 2543,"Insula amygdaloidea","human","Latin",,"amygdaloid island",0 2926,"Insula Callejae","Macaca fascicularis","Latin","islands of Calleja",,0 745132657,"insula cerebri","human","Latin","INSULA",,0 84,"insula lobule","human","English","INSULA",,0 698,"Insula olfactoria","Cercocebus torquatus","Latin",,"peripaleocortical claustral region",0 2085,"Insula terminalis subcaudata","human","Latin",,"subcaudate terminal island",0 2087,"Insula terminalis substriatalis","human","Latin",,"substriatal terminal island",0 2091,"Insula terminalis subventricularis","human","Latin",,"subventricular terminal island",0 2089,"Insula terminalis tubercularis","human","Latin",,"tubercular terminal island(s)",0 82,"insular cortex","human","English","INSULA",,526 1444856714,"insular gyrus","human","English","INSULA",,0 85,"insular lobe","human","English","INSULA",,6 1052,"insular region","human","English",,"insular region",25 88,"insular region","rat","English","INSULA",,24 590237224,"insulo-orbito-temporopolar complex","primate","English",,"insulo-orbito-temporopolar complex",0 34,"interbrain","human","English","DIENCEPHALON",,8 5206,"intercalate nucleus of stria terminalis","human","English","nucleus of stria terminalis",,0 3735,"intercalated amygdaloid nuclei","Macaca fascicularis","English","intercalated amygdaloid nuclei",,2 4181,"intercalated mammillary nucleus","human","English","lateral part of medial mammillary nucleus",,0 3738,"intercalated masses of nucleus amygdaloideus","Macaca fuscata","English","intercalated amygdaloid nuclei",,0 3739,"intercalated nuclei of amygdala","rat","English","intercalated amygdaloid nuclei",,0 3635,"intercalated nucleus of medulla","rat","English","nucleus intercalatus",,0 2433,"intercollicular gray","human","English",,"intercollicular gray",0 2001,"interfascicular bundle","human","English",,"comma tract of Schultze",0 4832,"interfornical nucleus","human","English",,"perifornical nucleus",0 5018,"intergeniculate pulvinar","human","English",,"intergeniculate pulvinar",0 139,"interhemispheric commissure","Macaca fascicularis","English","CORPUS CALLOSUM",,1 2299,"interhemispheric fissure","human","English","longitudinal fissure",,206 6360,"interlobar fissures","human","English",,"interlobar fissures",0 6296,"interlocking gyri","human","English",,"interlocking gyri (H)",0 6044,"intermediate acoustic stria","human","English","intermediate acoustic stria",,5 6046,"intermediate acoustic stria of Held","human","English","intermediate acoustic stria",,1 541,"intermediate cortex","human","English",,"paravermal cortex",0 3707,"intermediate division of basal nucleus","Macaca fascicularis","English",,"intermediate division of basal nucleus",0 6969,"intermediate eminence","human","English","vagal trigone",,0 3708,"intermediate fiber bundle of amygdala","Macaca fascicularis","English",,"intermediate fiber bundle of amygdala",0 852,"intermediate frontal area 8","human","English",,"intermediate frontal area 8",0 2640,"intermediate frontal gyrus","human","English","middle frontal gyrus",,0 6339,"intermediate frontal sulcus","human","English","middle frontal sulcus (H)",,0 6002,"intermediate gray layer","human","English","middle gray layer of superior colliculus",,54 1102930234,"intermediate gray substance","human","English",,"Rexed's lamina VII",0 214,"intermediate hypothalamic region","Macaca fascicularis","English","INTERMEDIATE HYPOTHALAMIC REGION",,0 -1418662436,"intermediate hypothalamic region - not otherwise specified","Unspecified","English","INTERMEDIATE HYPOTHALAMIC REGION - not otherwise specified",,0 2875,"intermediate lobe of hypophysis","human","English","intermediate part of hypophysis",,1 4180,"intermediate mammillary nucleus","Unspecified","English","lateral part of medial mammillary nucleus",,0 4179,"intermediate mammillary nucleus","human","English","lateral part of medial mammillary nucleus",,0 3276,"intermediate nerve","human","English","intermediate nerve",,18 3278,"intermediate nerve of Wrisberg","human","English","intermediate nerve",,0 4932,"intermediate nucleus of preoptic area","human","English",,"intermediate nucleus of preoptic area",0 4610,"intermediate oculomotor cell column","human","English","intermediate oculomotor nucleus",,0 4608,"intermediate oculomotor nucleus","human","English","intermediate oculomotor nucleus",,0 6094,"intermediate olfactory stria","human","English",,"intermediate olfactory stria",0 -1336328430,"intermediate orbital gyrus","human","English","intermediate orbital gyrus (H)",,0 2871,"intermediate part of hypophysis","human","English","intermediate part of hypophysis",,0 4925,"intermediate periventricular nucleus","Unspecified","English","intermediate periventricular nucleus",,0 4927,"intermediate periventricular nucleus of hypothalamus","rat","English","intermediate periventricular nucleus",,0 819,"intermediate postcentral area 1","human","English",,"intermediate postcentral area 1",0 1094,"intermediate precentral cortex","Unspecified","English",,"premotor cortex",0 6630,"intermediate precentral sulcus","human","English",,"intermediate precentral sulcus (H)",0 3767,"intermediate principal nucleus","Unspecified","English",,"basal nucleus of amygdala (Amaral)",1 526,"intermediate region of cerebellum","human","English",,"intermediate zone of cerebellum",0 2873,"intermediate region of hypophysis","human","English","intermediate part of hypophysis",,0 2556,"intermediate short gyrus","Unspecified","English","intermediate short gyrus (H)",,0 2820,"intermediate temporal gyrus","human","English","middle temporal gyrus",,0 6014,"intermediate white layer","human","English","middle white layer of superior colliculus",,6 525,"intermediate zone of cerebellum","human","English",,"intermediate zone of cerebellum",0 3442,"intermediate zone of hypothalamus","human","English",,"medial zone of hypothalamus",0 7114,"intermediolateral cell column","human","English",,"intermediolateral nucleus",0 7111,"intermediolateral nucleus","human","English",,"intermediolateral nucleus",165 7212,"intermediomedial cell column","human","English",,"intermediomedial nucleus",0 7211,"intermediomedial nucleus","human","English",,"intermediomedial nucleus",8 2151,"internal arcuate fibers","human","English","internal arcuate fibers",,5 2152,"internal arcuate fibers","Macaca fascicularis","English","internal arcuate fibers",,5 2153,"internal arcuate fibers","rat","English","internal arcuate fibers",,5 1313,"internal band of Baillarger","human","English",,"internal band of Baillarger",0 3294,"internal branch of accessory nerve","human","English","cranial part of accessory nerve",,0 130,"internal capsule","Macaca fascicularis","English","INTERNAL CAPSULE",,1233 129,"internal capsule","human","English","INTERNAL CAPSULE",,1233 131,"internal capsule","rat","English","INTERNAL CAPSULE",,1233 134,"internal capsule radiations","human","English","INTERNAL CAPSULE",,0 3264,"internal genu of facial nerve","human","English","internal genu of facial nerve",,0 3265,"internal genu of facial nerve","Macaca fascicularis","English","internal genu of facial nerve",,0 2531,"internal globus pallidus","human","English","medial globus pallidus",,61 2963,"internal granular layer","human","English",,"internal granular layer",188 4165,"internal mammillary nucleus","human","English","MEDIAL MAMMILLARY NUCLEUS",,0 3082,"internal medullary lamina","rat","English","internal medullary lamina",,48 3081,"internal medullary lamina","Macaca fascicularis","English","internal medullary lamina",,48 3080,"internal medullary lamina","human","English","internal medullary lamina",,48 3096,"internal medullary lamina of cerebellum","human","English","inferior medullary lamina",,0 3007,"internal medullary lamina of globus pallidus","human","English","medial medullary lamina",,0 3004,"internal medullary lamina of lentiform nucleus","human","English","medial medullary lamina",,0 3087,"internal medullary lamina of thalamus","human","English","internal medullary lamina",,1 3088,"internal medullary lamina of thalamus","rat","English","internal medullary lamina",,1 3037,"internal pyramidal layer","human","English",,"internal pyramidal layer",0 6019,"internal sagittal stratum","human","English",,"internal sagittal stratum",0 1317,"internal stripe of Baillarger","human","English",,"internal band of Baillarger",0 7128,"internuncial nuclear group","human","English",,"internuncial nuclear group",0 6371,"interparietal fissure","human","English","intraparietal sulcus",,0 1497,"interpeduncular cistern","human","English","interpeduncular cistern",,60 2474,"interpeduncular fossa","human","English","interpeduncular fossa",,24 4415,"interpeduncular ganglion","human","English","interpeduncular nucleus",,0 4409,"interpeduncular nucleus","human","English","interpeduncular nucleus",,557 4410,"interpeduncular nucleus","Macaca fascicularis","English","interpeduncular nucleus",,557 4411,"interpeduncular nucleus","rat","English","interpeduncular nucleus",,557 -317291404,"interpeduncular perforated substance","human","English",,"posterior perforated substance",0 -488887641,"interpolar part of spinal trigeminal nucleus","Macaca fascicularis","English","interpolar part of spinal trigeminal nucleus",,0 839380459,"interpolar part of spinal trigeminal nucleus","human","English","interpolar part of spinal trigeminal nucleus",,0 4312,"interposed nucleus","rat","English",,"interposed nucleus",0 4311,"interposed nucleus","human","English",,"interposed nucleus",0 4417,"interstitial nucleus of Cajal","Macaca fascicularis","English","interstitial nucleus of Cajal",,221 4418,"interstitial nucleus of Cajal","rat","English","interstitial nucleus of Cajal",,221 4416,"interstitial nucleus of Cajal","human","English","interstitial nucleus of Cajal",,221 4350,"interstitial nucleus of habenular commissure","human","English",,"interstitial nucleus of habenular commissure",0 5709,"interstitial nucleus of mammillary peduncle","human","English",,"interstitial nucleus of mammillary peduncle",0 4421,"interstitial nucleus of medial longitudinal fasciculus (Crosby)","human","English","interstitial nucleus of Cajal",,0 5204,"interstitial nucleus of stria terminalis","human","English","nucleus of stria terminalis",,0 4427,"interstitial nucleus of vestibular nerve","rat","English","interstitial nucleus of vestibular nerve",,0 4425,"interstitial nucleus of vestibular nerve","human","English","interstitial nucleus of vestibular nerve",,0 4426,"interstitial nucleus of vestibular nerve","Macaca fuscata","English","interstitial nucleus of vestibular nerve",,0 7249,"interstitiospinal fibers","human","English",,"interstitiospinal tract",5 7247,"interstitiospinal tract","human","English",,"interstitiospinal tract",0 660,"interthalamic adhesion","human","English","interthalamic adhesion",,8 666,"interthalamic connection","human","English","interthalamic adhesion",,1 2353,"interventricular foramen","human","English","interventricular foramen",,40 2354,"interventricular foramen","Macaca fascicularis","English","interventricular foramen",,40 511,"intracerebellar nuclei","human","English","DEEP CEREBELLAR NUCLEI",,33 6364,"intracingulate sulcus","Macaca fascicularis","English","intracingulate sulcus",,0 4763,"intralamellar thalamic nuclei","human","English",,"Nucleus intralamellaris ventralis (Hassler)",0 3491,"intralaminar nuclear group","human","English","INTRALAMINAR NUCLEAR GROUP",,2 3492,"intralaminar nuclear group","Macaca fascicularis","English","INTRALAMINAR NUCLEAR GROUP",,2 3497,"intralaminar nuclei (Crosby)","human","English",,"intralaminar nuclei (Crosby)",0 3495,"intralaminar nuclei of thalamus","human","English","INTRALAMINAR NUCLEAR GROUP",,1 3494,"intralaminar thalamic nuclei","human","English","INTRALAMINAR NUCLEAR GROUP",,129 2670,"intralimbic gyrus","human","English",,"intralimbic gyrus",0 2669,"intralimbic gyrus","human","English",,"intralimbic gyrus",0 6359,"intralimbic sulcus","human","English",,"intralimbic sulcus",0 6634,"intralingual ramus of collateral sulcus","human","English",,"intralingual ramus of collateral sulcus (H)",0 6305,"intralingual sulcus","human","English","intralingual sulcus (H)",,0 6363,"intralobar fissures","human","English",,"intralobar fissures",0 6370,"intraparietal fissure","human","English","intraparietal sulcus",,2 6367,"intraparietal sulcus","human","English","intraparietal sulcus",,178 6368,"intraparietal sulcus","Macaca fascicularis","English","intraparietal sulcus",,178 2378,"intrarhinal sulcus","human","English",,"intrarhinal sulcus",0 509,"intrinsic nuclei of cerebellum","human","English","DEEP CEREBELLAR NUCLEI",,0 83,"island of Reil","human","English","INSULA",,4 2925,"islands of Calleja","rat","English","islands of Calleja",,184 2923,"islands of Calleja","human","English","islands of Calleja",,184 2924,"islands of Calleja","Macaca fascicularis","English","islands of Calleja",,184 3219,"isocortex","human","English",,"neocortex",201 3222,"Isocortex (sensu lato)","human","Latin",,"neocortex",0 3228,"Isocortex maturus","human","Latin",,"true isocortex",0 553382447,"Isocortex maturus","human","Latin",,"Isocortex maturus",0 -1241647096,"isthmus cingulate white matter","Unspecified","English","isthmus cingulate white matter",,0 2931,"Isthmus cinguli","human","Latin","isthmus of cingulate gyrus",,0 431,"Isthmus encephali","human","Latin",,"isthmus of brain",0 2930,"Isthmus gyri cingulatus","human","Latin","isthmus of cingulate gyrus",,0 2929,"Isthmus gyri cinguli","human","Latin","isthmus of cingulate gyrus",,0 430,"isthmus of brain","human","English",,"isthmus of brain",0 428,"isthmus of brainstem","human","English",,"isthmus of hindbrain",0 2927,"isthmus of cingulate gyrus","human","English","isthmus of cingulate gyrus",,1 2928,"isthmus of cingulate gyrus","Macaca fascicularis","English","isthmus of cingulate gyrus",,1 2932,"isthmus of fornicate gyrus","human","English","isthmus of cingulate gyrus",,0 2935,"Isthmus of Gyrus fornicatus","human","Latin","isthmus of cingulate gyrus",,0 423,"isthmus of hindbrain","human","English",,"isthmus of hindbrain",0 2933,"isthmus of limbic lobe","human","English","isthmus of cingulate gyrus",,0 426,"isthmus of pons","human","English",,"isthmus of hindbrain",0 425,"isthmus of rhombencephalon","human","English",,"isthmus of hindbrain",0 424,"Isthmus rhombencephali","human","Latin",,"isthmus of hindbrain",0 429,"Isthmus-1","human","Latin",,"isthmus of hindbrain",885 2934,"Isthmus-2","human","Latin","isthmus of cingulate gyrus",,5 993376333,"istmus","human","Latin",,"isthmus of brain",1 346,"Iter","human","Latin","cerebral aqueduct",,74 1373,"Jacobson's organ","human","English",,"vomeronasal organ",0 3226,"juxtallocortex","human","English",,"proisocortex",0 1683,"juxtarestiform body","human","English","juxtarestiform body",,10 6007,"Kamm system","human","English",,"peduncle of substantia nigra",0 710,"koniocortex","human","English",,"granulous cortex",16 4433,"lacrimal nucleus","human","English",,"lacrimal nucleus",0 2975,"Lamella medullaris externa","Macaca mulatta","Latin","external medullary lamina",,0 2991,"Lamella pallidi externa","human","Latin","lateral medullary lamina",,0 2984,"Lamella pallidi incompleta","human","Latin","accessory medullary lamina",,0 3011,"Lamella pallidi interna","human","Latin","medial medullary lamina",,0 3014,"Lamella pallidi limitans","human","Latin",,"limiting medullary lamina of globus pallidus",0 2953,"lamina affixa","human","English","lamina affixa",,0 2954,"Lamina affixa","human","Latin","lamina affixa",,0 2957,"Lamina cinerea","human","Latin",,"lamina cornea",0 3069,"Lamina collicularis","human","Latin",,"Corpus quadrigemina",0 2955,"lamina cornea","human","English",,"lamina cornea",0 2956,"Lamina cornea","human","Latin",,"lamina cornea",0 3039,"Lamina ganglionaris","human","Latin",,"internal pyramidal layer",0 -470718733,"Lamina ganglionaris","Cercopithecus","Latin",,"internal pyramidal layer",0 -582388256,"Lamina ganularis externa","Cercopithecus","Latin",,"external granular layer",0 2960,"Lamina granularis externa","human","Latin",,"external granular layer",0 2964,"Lamina granularis interna","human","Latin",,"internal granular layer",0 7170,"lamina I","human","English",,"Rexed's lamina I",0 7186,"lamina II","human","English",,"Rexed's lamina II",0 7188,"lamina III","human","English",,"Rexed's lamina III",0 2958,"Lamina infrachoroidea","human","Latin",,"lamina cornea",0 7190,"lamina IV","human","English",,"Rexed's lamina IV",169 7200,"lamina IX","human","English",,"Rexed's lamina IX",154 2980,"Lamina medullaris accessoria","human","Latin","accessory medullary lamina",,0 2970,"Lamina medullaris externa","human","Latin","external medullary lamina",,1 2971,"Lamina medullaris externa (thalami)","human","Latin","external medullary lamina",,0 2998,"Lamina medullaris externa pallidi","human","Latin","lateral medullary lamina",,0 2973,"Lamina medullaris externa thalami","Macaca fascicularis","Latin","external medullary lamina",,0 2972,"Lamina medullaris externa thalami","human","Latin","external medullary lamina",,0 2982,"Lamina medullaris incompleta pallidi","human","Latin","accessory medullary lamina",,0 3095,"Lamina medullaris inferior","Unspecified","Latin","inferior medullary lamina",,0 3083,"Lamina medullaris interna","human","Latin","internal medullary lamina",,1 3008,"Lamina medullaris interna pallidi","human","Latin","medial medullary lamina",,0 3085,"Lamina medullaris interna thalami","Macaca fascicularis","Latin","internal medullary lamina",,0 3084,"Lamina medullaris interna thalami","human","Latin","internal medullary lamina",,0 2988,"Lamina medullaris lateralis","Macaca nemestrina","Latin","lateral medullary lamina",,0 2987,"Lamina medullaris lateralis","human","Latin","lateral medullary lamina",,0 3018,"Lamina medullaris lateralis of inferior colliculus","human","Latin",,"lateral medullary lamina of inferior colliculus",0 3000,"Lamina medullaris medialis","human","Latin","medial medullary lamina",,2 3001,"Lamina medullaris medialis","Macaca nemestrina","Latin","medial medullary lamina",,2 3016,"Lamina medullaris medialis of inferior colliculus","human","Latin",,"medial medullary lamina of inferior colliculus",0 5659,"Lamina medullaris nuclei rubris","human","Latin",,"medullary lamina of red nucleus",0 3091,"Lamina medullaris superior","Unspecified","Latin","superior medullary lamina",,0 2974,"Lamina medullaris thalami externa","Macaca nemestrina","Latin","external medullary lamina",,0 3086,"Lamina medullaris thalami interna","Macaca nemestrina","Latin","internal medullary lamina",,0 3020,"Lamina molecularis (cerebri)","human","Latin",,"molecular layer",0 3025,"Lamina multiformis","human","Latin",,"multiform layer",0 991440806,"Lamina multiformis","Cercopithecus","Latin",,"multiform layer",0 3057,"lamina of septum pellucidum","human","English","lamina of septum pellucidum",,0 2992,"Lamina pallidi externa","human","Latin","lateral medullary lamina",,0 2983,"Lamina pallidi incompleta","human","Latin","accessory medullary lamina",,0 3010,"Lamina pallidi interna","human","Latin","medial medullary lamina",,0 3013,"Lamina pallidi limitans","human","Latin",,"limiting medullary lamina of globus pallidus",0 3021,"Lamina plexiformis","human","Latin",,"molecular layer",0 1503983991,"Lamina pyramidalis","Cercopithecus","Latin",,"external pyramidal layer",0 3034,"Lamina pyramidalis externa","human","Latin",,"external pyramidal layer",0 3038,"Lamina pyramidalis interna","human","Latin",,"internal pyramidal layer",0 3072,"Lamina quadrigemina","human","Latin",,"Corpus quadrigemina",13 3409,"Lamina quadrigemina","human","Latin",,"quadrigeminal plate",13 970121380,"lamina quadrigemina tecti","human","Latin",,"Corpus quadrigemina",0 3058,"Lamina septi pellucidi","human","Latin","lamina of septum pellucidum",,0 3068,"Lamina tectalis","human","Latin",,"Corpus quadrigemina",0 3067,"Lamina tecti","human","Latin",,"Corpus quadrigemina",0 3074,"lamina terminalis","human","English","lamina terminalis",,567 3076,"lamina terminalis","rat","English","lamina terminalis",,567 3075,"Lamina terminalis","human","Latin","lamina terminalis",,567 7192,"lamina V","human","English",,"Rexed's lamina V",342 7194,"lamina VI","human","English",,"Rexed's lamina VI",105 7196,"lamina VII","human","English",,"Rexed's lamina VII",186 7198,"lamina VIII","human","English",,"Rexed's lamina VIII",87 7202,"lamina X","human","English",,"Rexed's lamina X",0 -1106168315,"Lamina zonalis","Cercopithecus","Latin",,"molecular layer",0 3078,"Laminae albae","human","Latin",,"white laminae of cerebellum",0 3079,"Laminae albae cerebelli","human","Latin",,"white laminae of cerebellum",0 3099,"Laminae medullares thalami","human","Latin",,"thalamic medullary laminae",0 1838,"Laqueus medialis","human","Latin",,"medial lemniscus",0 -496130255,"large island of Calleja","mammal","English",,"large island of Calleja",0 4688,"large-celled nucleus of optic tract","human","English","nucleus of optic tract",,0 3743,"lateral amygdaloid nucleus","rat","English","lateral amygdaloid nucleus",,75 3742,"lateral amygdaloid nucleus","Macaca fascicularis","English","lateral amygdaloid nucleus",,75 3741,"lateral amygdaloid nucleus","human","English","lateral amygdaloid nucleus",,75 771,"lateral aperture of fourth ventricle","human","English","lateral aperture of fourth ventricle",,0 3686,"lateral basal nucleus of the amygdala","Unspecified","English","lateral part of basal amygdaloid nucleus",,3 7086,"lateral bundle","human","English",,"lateral bundle",0 6384,"lateral cerebral fissure","human","English","lateral sulcus",,1 7218,"lateral cervical nucleus","dog","English",,"lateral cervical nucleus",0 1015373747,"lateral column","human","English",,"lateral funiculus",142 6711,"lateral corticospinal tract","human","English","lateral corticospinal tract",,43 6712,"lateral corticospinal tract","Macaca fascicularis","English","lateral corticospinal tract",,43 4197,"lateral cuneate nucleus","Macaca fascicularis","English","accessory cuneate nucleus",,20 3704,"lateral division of central nucleus of amygdala","Macaca fascicularis","English",,"lateral division of central nucleus of amygdala",0 1969403414,"lateral division of globus pallidus","human","English","lateral globus pallidus",,0 1167,"lateral division of hypothalamus","human","English","LATERAL HYPOTHALAMIC AREA",,0 3685,"lateral division of the basal nucleus","Unspecified","English","lateral part of basal amygdaloid nucleus",,0 4436,"lateral dorsal nucleus","Macaca fascicularis","English","lateral dorsal nucleus",,20 4435,"lateral dorsal nucleus","human","English","lateral dorsal nucleus",,20 4445,"lateral dorsal nucleus of thalamus","rat","English","lateral dorsal nucleus",,0 4444,"lateral dorsal nucleus of thalamus","human","English","lateral dorsal nucleus",,0 2942,"lateral dorsal subnucleus of midbrain central gray","human","English",,"lateral dorsal subnucleus of midbrain central gray",0 4442,"lateral dorsal thalamic nucleus","human","English","lateral dorsal nucleus",,4 1286,"lateral eminence of fourth ventricle","human","English","vestibular area",,0 1907,"lateral eminence of hypophysis","human","English","lateral eminence of hypophysis",,0 -479626474,"lateral fasciculus","human","English",,"cuneate fasciculus",0 3709,"lateral fiber bundle of amygdala","Macaca fascicularis","English",,"lateral fiber bundle of amygdala",0 3106,"lateral fillet","human","English","lateral lemniscus",,0 6382,"lateral fissure","human","English","lateral sulcus",,24 6381,"lateral fissure of Sylvius","Macaca fascicularis","English","lateral sulcus",,0 1377,"lateral forebrain bundle","Unspecified","English",,"basal forebrain bundle",63 2492,"lateral funiculus","human","English",,"lateral funiculus",311 173,"lateral geniculate body","human","English","LATERAL GENICULATE BODY",,490 174,"lateral geniculate body","Macaca fascicularis","English","LATERAL GENICULATE BODY",,490 182,"lateral geniculate complex","rat","English","LATERAL GENICULATE BODY",,64 4095,"lateral geniculate complex, dorsal part","rat","English","dorsal nucleus of lateral geniculate body",,0 4103,"lateral geniculate complex, ventral part","rat","English","ventral nucleus of lateral geniculate body",,0 179,"lateral geniculate nucleus","human","English","LATERAL GENICULATE BODY",,2535 180,"lateral geniculate nucleus","Macaca fascicularis","English","LATERAL GENICULATE BODY",,2535 2518,"lateral globus pallidus","Macaca fascicularis","English","lateral globus pallidus",,29 1168,"lateral group of hypothalamic nuclei","human","English","LATERAL HYPOTHALAMIC AREA",,0 2457,"lateral group of medullary reticular formation","human","English","LATERAL MEDULLARY RETICULAR GROUP",,0 4330,"lateral habenula","rat","English","lateral habenular nucleus",,251 4324,"lateral habenular nucleus","Macaca fascicularis","English","lateral habenular nucleus",,147 4325,"lateral habenular nucleus","rat","English","lateral habenular nucleus",,147 4323,"lateral habenular nucleus","human","English","lateral habenular nucleus",,147 7112,"lateral horn","human","English",,"intermediolateral nucleus",78 1163,"lateral hypothalamic area","human","English","LATERAL HYPOTHALAMIC AREA",,1617 1164,"lateral hypothalamic area","Macaca fascicularis","English","LATERAL HYPOTHALAMIC AREA",,1617 -427045009,"lateral hypothalamic area - not otherwise specified","Unspecified","English","LATERAL HYPOTHALAMIC AREA - not otherwise specified",,1617 1166,"lateral hypothalamic group","human","English","LATERAL HYPOTHALAMIC AREA",,1 1171,"lateral hypothalamic nucleus","human","English","lateral hypothalamic nucleus",,31 1169,"lateral hypothalamic zone (Crosby)","human","English","LATERAL HYPOTHALAMIC AREA",,0 -104286382,"lateral inferior limiting sulcus","Macaca mulatta","English","lateral inferior limiting sulcus",,0 968084311,"lateral inferior limiting sulcus","Macaca fascicularis","English","lateral inferior limiting sulcus",,0 3514,"lateral lemniscal nuclei","human","English",,"lateral lemniscal nuclei",12 3101,"lateral lemniscus","Macaca fascicularis","English","lateral lemniscus",,485 3102,"lateral lemniscus","rat","English","lateral lemniscus",,485 3100,"lateral lemniscus","human","English","lateral lemniscus",,485 2845,"lateral lobe of cerebellum","human","English",,"cerebellar hemisphere",0 6053,"lateral longitudinal stria","human","English","lateral longitudinal stria",,0 4149,"lateral mammillary hypothalamic nucleus","Macaca fuscata","English","lateral mammillary nucleus",,0 4147,"lateral mammillary nucleus","rat","English","lateral mammillary nucleus",,50 4144,"lateral mammillary nucleus","human","English","lateral mammillary nucleus",,50 4145,"lateral mammillary nucleus","human","English","lateral mammillary nucleus",,50 4146,"lateral mammillary nucleus","Macaca fascicularis","English","lateral mammillary nucleus",,0 4182,"lateral mammillary nucleus (Gagel)","human","English","lateral part of medial mammillary nucleus",,0 4542,"lateral mediodorsal nucleus","Macaca","English","parvicellular part of medial dorsal nucleus",,0 2985,"lateral medullary lamina","human","English","lateral medullary lamina",,3 2986,"lateral medullary lamina","Macaca fascicularis","English","lateral medullary lamina",,3 2993,"lateral medullary lamina of globus pallidus","human","English","lateral medullary lamina",,0 3017,"lateral medullary lamina of inferior colliculus","human","English",,"lateral medullary lamina of inferior colliculus",0 2990,"lateral medullary lamina of pallidum","human","English","lateral medullary lamina",,0 2454,"lateral medullary reticular group","human","English","LATERAL MEDULLARY RETICULAR GROUP",,0 2455,"lateral medullary reticular group","Macaca fascicularis","English","LATERAL MEDULLARY RETICULAR GROUP",,0 2996,"lateral medullary stria","human","English","lateral medullary lamina",,0 3513,"lateral nuclear group","human","English",,"lateral nuclear group (Crosby)",4 3508,"lateral nuclear group","Macaca fascicularis","English","LATERAL NUCLEAR GROUP",,4 3507,"lateral nuclear group","human","English","LATERAL NUCLEAR GROUP",,4 7178,"lateral nuclear group of anterior horn","human","English",,"lateral nuclear group of anterior horn",0 3747,"lateral nucleus of amygdala","Macaca fascicularis","English","lateral amygdaloid nucleus",,7 3748,"lateral nucleus of amygdala","rat","English","lateral amygdaloid nucleus",,7 626,"lateral nucleus of cerebellum","Macaca fascicularis","English","DENTATE NUCLEUS",,0 627,"lateral nucleus of cerebellum","rat","English","DENTATE NUCLEUS",,0 5556,"lateral nucleus of Deiters","human","English","lateral vestibular nucleus",,0 1539,"lateral nucleus of oculomotor nerve","human","English",,"lateral somatic cell columns",0 3511,"lateral nucleus of thalamus","human","English","LATERAL NUCLEAR GROUP",,2 2209,"lateral occipital fasciculus","human","English",,"vertical occipital fasciculus",0 2715,"lateral occipital gyrus","human","English","lateral occipital gyrus (H)",,3 6468,"lateral occipital sulcus","human","English","lateral occipital sulcus (H)",,5 2665,"lateral occipitotemporal gyrus","human","English","fusiform gyrus",,8 2664,"lateral occipitotemporal gyrus","human","English","fusiform gyrus",,8 2666,"lateral occipito-temporal gyrus","human","English","fusiform gyrus",,2 2816,"lateral occipitotemporal gyrus (Heimer-83)","human","English","inferior temporal gyrus",,0 134970371,"lateral occipitotemporal sulcus","human","English","occipitotemporal sulcus",,0 1538,"lateral oculomotor nucleus","human","English",,"lateral somatic cell columns",0 1142,"lateral olfactory area","human","English",,"primary olfactory areas",0 5811,"lateral olfactory gyrus","human","English","prepyriform area",,3 6089,"lateral olfactory stria","human","English","lateral olfactory stria",,1 6092,"lateral olfactory tract","human","English","lateral olfactory stria",,417 3784,"lateral olfactory tract","rat","English","olfactory tract",,417 2732,"lateral orbital gyrus","Macaca mulatta","English","lateral orbital gyrus",,2 2731,"lateral orbital gyrus","human","English","lateral orbital gyrus",,2 6485,"lateral orbital sulcus","Macaca mulatta","English","lateral orbital sulcus",,1 -1705330318,"lateral orbital white matter","Unspecified","English","lateral orbital white matter",,0 2523,"lateral pallidal segment","human","English","lateral globus pallidus",,13 4694,"lateral parabrachial nucleus","Macaca fascicularis","English","lateral parabrachial nucleus",,196 4695,"lateral parabrachial nucleus","rat","English","lateral parabrachial nucleus",,196 4693,"lateral parabrachial nucleus","human","English","lateral parabrachial nucleus",,196 5026,"lateral paragigantocellular nucleus","rat","English","lateral paragigantocellular nucleus",,35 5025,"lateral paragigantocellular nucleus","Macaca fascicularis","English","lateral paragigantocellular nucleus",,35 4475,"lateral parolfactory nucleus","human","English","lateral septal nucleus",,0 3680,"lateral part of basal amygdaloid nucleus","Unspecified","English","lateral part of basal amygdaloid nucleus",,0 4174,"lateral part of medial mammillary nucleus","human","English","lateral part of medial mammillary nucleus",,1 4204,"lateral pericuneate nucleus","human","English","lateral pericuneate nucleus",,0 5752,"lateral pes lemniscus","human","English","lateral pes lemniscus",,0 5758,"lateral pontine bundle","human","English","lateral pes lemniscus",,0 4451,"lateral posterior nucleus","human","English","lateral posterior nucleus",,156 4452,"lateral posterior nucleus","Macaca fascicularis","English","lateral posterior nucleus",,156 4461,"lateral posterior nucleus of thalamus","rat","English","lateral posterior nucleus",,1 4460,"lateral posterior nucleus of thalamus","human","English","lateral posterior nucleus",,1 4459,"lateral posterior thalamic nucleus","rat","English","lateral posterior nucleus",,18 4458,"lateral posterior thalamic nucleus","human","English","lateral posterior nucleus",,18 1038,"lateral prefrontal cortex","human","English",,"frontal region",0 4894,"lateral preoptic area","human","English","lateral preoptic nucleus",,257 4895,"lateral preoptic area","rat","English","lateral preoptic nucleus",,257 4898,"lateral preoptic hypothalamic nucleus","human","English","lateral preoptic nucleus",,0 4890,"lateral preoptic nucleus","Macaca fascicularis","English","lateral preoptic nucleus",,21 4889,"lateral preoptic nucleus","human","English","lateral preoptic nucleus",,21 3749,"lateral principal nucleus of amygdala","Macaca fascicularis","English","lateral amygdaloid nucleus",,0 4953,"lateral pulvinar nucleus","Macaca fascicularis","English","lateral pulvinar nucleus",,6 4952,"lateral pulvinar nucleus","human","English","lateral pulvinar nucleus",,6 4959,"lateral pulvinar nucleus of thalamus","human","English","lateral pulvinar nucleus",,0 6716,"lateral pyramidal tract","human","English","lateral corticospinal tract",,3 5912,"lateral recess of fourth ventricle","human","English","lateral recess of fourth ventricle",,0 5002,"lateral reticular nucleus","Macaca fascicularis","English","lateral reticular nucleus",,371 5003,"lateral reticular nucleus","rat","English","lateral reticular nucleus",,371 5001,"lateral reticular nucleus","human","English","lateral reticular nucleus",,371 5007,"lateral reticular nucleus (medulla)","human","English","lateral reticular nucleus",,0 7256,"lateral reticulospinal tract","human","English",,"medullary reticulospinal tract",0 4470,"lateral septal nucleus","rat","English","lateral septal nucleus",,314 4469,"lateral septal nucleus","Macaca fascicularis","English","lateral septal nucleus",,314 4468,"lateral septal nucleus","human","English","lateral septal nucleus",,314 1537,"lateral somatic cell columns","human","English",,"lateral somatic cell columns",0 7151,"lateral spinothalamic tract","human","English",,"lateral spinothalamic tract",14 4176,"lateral subdivision of medial mammillary nucleus","human","English","lateral part of medial mammillary nucleus",,0 2946,"lateral subnucleus of midbrain central gray","human","English",,"lateral subnucleus of midbrain central gray",0 6373,"lateral sulcus","human","English","lateral sulcus",,59 6374,"lateral sulcus","Macaca mulatta","English","lateral sulcus",,59 4654,"lateral superior olivary nucleus","human","English","lateral superior olivary nucleus",,70 4655,"lateral superior olivary nucleus","Macaca fascicularis","English","lateral superior olivary nucleus",,70 4658,"lateral superior olive","rat","English","lateral superior olivary nucleus",,221 4657,"lateral superior olive","human","English","lateral superior olivary nucleus",,221 2438,"lateral tegmental process of Jacobsohn","human","English",,"lateral tegmental process of Jacobsohn",0 3510,"lateral thalamic nuclei","human","English","LATERAL NUCLEAR GROUP",,64 3576,"lateral tuberal hypothalamic nuclei","human","English","lateral tuberal nuclei",,0 3574,"lateral tuberal nuclei","Macaca fascicularis","English","lateral tuberal nuclei",,3 3573,"lateral tuberal nuclei","human","English","lateral tuberal nuclei",,3 3579,"lateral tuberal nucleus","human","English",,"lateral tuberal nucleus",25 4070,"lateral ventral nucleus of thalamus","human","English","VENTRAL LATERAL NUCLEUS",,0 2944,"lateral ventral subnucleus of midbrain central gray","human","English",,"lateral ventral subnucleus of midbrain central gray",0 749,"lateral ventricle","rat","English","lateral ventricle",,2653 748,"lateral ventricle","Macaca fascicularis","English","lateral ventricle",,2653 747,"lateral ventricle","human","English","lateral ventricle",,2653 5554,"lateral vestibular nucleus","Macaca fascicularis","English","lateral vestibular nucleus",,433 5555,"lateral vestibular nucleus","rat","English","lateral vestibular nucleus",,433 5553,"lateral vestibular nucleus","human","English","lateral vestibular nucleus",,433 6056,"lateral white stria of Lancisi","human","English","lateral longitudinal stria",,0 7081,"lateral zone of cerebellum","human","English",,"lateral zone of cerebellum",0 7082,"lateral zone of cerebellum","Unspecified","English",,"lateral zone of cerebellum",0 3439,"lateral zone of hypothalamus","human","English",,"lateral zone of hypothalamus",0 3440,"lateral zone of the hypothalamus","rat","English",,"lateral zone of hypothalamus",0 4465,"laterodorsal nucleus, caudal part","human","English","lateral posterior nucleus",,0 4448,"laterodorsal nucleus, superficial part","human","English","lateral dorsal nucleus",,0 5064,"laterodorsal tegmental nucleus","human","English",,"laterodorsal tegmental nucleus",193 4446,"laterodorsal thalamic nucleus","rat","English","lateral dorsal nucleus",,10 5065,"lateroventral tegmental nucleus","human","English",,"lateroventral tegmental nucleus",0 3023,"Layer I","human","English",,"molecular layer",711 2961,"Layer II","human","English",,"external granular layer",759 3035,"Layer III","human","English",,"external pyramidal layer",718 2965,"Layer IV","human","English",,"internal granular layer",1020 3032,"layer of fusiform cells","human","English",,"layer VII (Cajal)",0 3036,"layer of medium-sized and large pyramidal cells","human","English",,"external pyramidal layer",0 3030,"layer of medium-sized pyramidal and triangular cells","human","English",,"layer VI (Cajal)",0 2962,"layer of small pyramids","human","English",,"external granular layer",0 2966,"layer of small stellate and pyramidal cells","human","English",,"internal granular layer",0 3040,"Layer V","human","English",,"internal pyramidal layer",1082 3027,"Layer VI","human","English",,"multiform layer",509 3029,"layer VI (Cajal)","human","English",,"layer VI (Cajal)",0 3031,"layer VII (Cajal)","human","English",,"layer VII (Cajal)",0 3061,"layers of CA1 field","Macaca fascicularis","English",,"layers of CA1 field",0 3062,"layers of CA2 field","Macaca fascicularis","English",,"layers of CA2 field",0 3063,"layers of CA3 field","Macaca fascicularis","English",,"layers of CA3 field",0 3060,"layers of fascia dentata","Macaca fascicularis","English",,"layers of fascia dentata",0 3065,"layers of presubiculum","Macaca fascicularis","English",,"layers of presubiculum",0 3064,"layers of subiculum","Macaca fascicularis","English",,"layers of subiculum",0 3059,"layers of superior colliculus","human","English",,"layers of superior colliculus",0 4449,"LD","human","Abbreviation","lateral dorsal nucleus",,0 3594,"lemniscal channel","Macaca","English",,"nonmotor region of ventral nuclear group",0 3593,"lemniscal channel","human","English",,"nonmotor region of ventral nuclear group",0 3107,"lemniscal system","human","English",,"lemniscal system",0 6956,"lemniscal trigone","human","English","lemniscal trigone",,0 3105,"Lemniscus acusticus","Macaca mulatta","Latin","lateral lemniscus",,0 3104,"Lemniscus lateralis","Macaca fascicularis","Latin","lateral lemniscus",,12 3103,"Lemniscus lateralis","human","Latin","lateral lemniscus",,12 1835,"Lemniscus medialis","human","Latin",,"medial lemniscus",27 1844,"Lemniscus medialis (mesencephali)","human","Latin","medial lemniscus of midbrain",,0 1851,"Lemniscus medialis (myelencephali)","human","Latin","medial lemniscus of medulla",,0 1848,"Lemniscus medialis (pontis)","Macaca fascicularis","Latin","medial lemniscus of pons",,0 1847,"Lemniscus medialis (pontis)","human","Latin","medial lemniscus of pons",,0 1836,"Lemniscus sensibilis","human","Latin",,"medial lemniscus",0 1837,"Lemniscus sensitivus","Macaca mulatta","Latin",,"medial lemniscus",0 6864,"Lemniscus spinalis","human","Latin",,"spinothalamic tract",0 6922,"Lemniscus trigeminalis","human","Latin",,"trigeminal lemniscus",0 1965,"lenticular fasciculus of diencephalon","human","English","field H2",,0 -240808930,"lenticular fasciculus of telencephalon","human","English","field H2",,0 3521,"lenticular nucleus","human","English",,"lentiform nuclei",103 5687,"lenticulothalamic part of internal capsule","human","English","lenticulothalamic part of internal capsule",,0 1975,"lentiform fibers","human","English",,"lentiform fibers",0 3517,"lentiform nuclei","human","English",,"lentiform nuclei",53 3520,"lentiform nucleus","human","English",,"lentiform nuclei",114 4690,"lentiform nucleus of pretectal area","human","English","nucleus of optic tract",,0 -1914200717,"limbic lobe","human","English","LIMBIC LOBE",,51 3108,"limbic lobe (Anthoney)","human","English",,"limbic lobe (Anthoney)",41 3114,"limbic system","human","English",,"limbic system",5790 3120,"Limen insulae","human","Latin","limen of insula",,5 3121,"limen insulae","human","Latin","limen of insula",,5 3118,"limen of insula","human","English","limen of insula",,1 3119,"limen of insula","Macaca fascicularis","English","limen of insula",,1 4489,"limitans nucleus","human","English","limitans nucleus",,8 4490,"limitans nucleus","human","English","limitans nucleus",,8 4493,"limitans thalamic nucleus","human","English","limitans nucleus",,0 6289,"limiting fissure","human","English","circular sulcus of insula",,0 3012,"limiting medullary lamina of globus pallidus","human","English",,"limiting medullary lamina of globus pallidus",0 3234,"limitrophic cortex","human","English",,"limitrophic cortex",0 1319,"line of Gennari","human","English",,"band of Gennari",0 1322,"line of Vicq d'Azyr","human","English",,"band of Gennari",0 4498,"linear nucleus","human","English","linear nucleus",,44 2683,"lingual gyrus","human","English","lingual gyrus",,44 2682,"lingual gyrus","Macaca fascicularis","English","lingual gyrus",,44 2681,"lingual gyrus","human","English","lingual gyrus",,44 1230415993,"lingual white matter","Unspecified","English","lingual white matter",,0 2671,"lingula","human","English","lingula",,190 2672,"lingula","Macaca fascicularis","English","lingula",,190 2673,"lingula","rat","English","lingula",,190 2674,"Lingula","human","Latin","lingula",,190 2675,"Lingula","Macaca nemestrina","Latin","lingula",,190 2677,"Lingula cerebelli","Macaca fascicularis","Latin","lingula",,0 2676,"Lingula cerebelli","human","Latin","lingula",,0 2680,"lingula of cerebellum","human","English","lingula",,0 2687,"lingula of cerebral hemisphere","human","English","lingual gyrus",,0 7078,"Lissauer's tract","human","English","dorsolateral fasciculus of medulla",,104 5349,"LO (Percheron)","Macaca","Abbreviation",,"Nucleus lateropolaris (Hassler)",0 3126,"Lobi cerebrales","human","Latin",,"cerebral lobes",0 3125,"Lobi cerebri","human","Latin",,"cerebral lobes",0 6698,"lobule H IX of Larsell","human","English","cerebellar tonsil",,0 3200,"lobule H VI of Larsell","human","English","simple lobule",,0 2679,"lobule I of Larsell","human","English","lingula",,0 2678,"lobule I of vermis","human","English","lingula",,0 7012,"lobule IX of Larsell","human","English","uvula",,0 7011,"lobule IX of vermis","human","English","uvula",,0 1777,"lobule VI of vermis","human","English","declive",,0 1786,"lobule VII of cerebellar vermis","human","English",,"lobule VII of cerebellar vermis",0 5851,"lobule VIII of Larsell","human","English","pyramid of medulla",,0 5855,"lobule VIII of vermis","human","English","pyramis of vermis",,0 3415,"lobule X of Larsell","human","English","nodulus",,1 3414,"lobule X of vermis","human","English","nodulus",,0 676,"lobules II, III of vermis","human","English","alar central lobule",,0 1762,"lobules IV, V of vermis","human","English","culmen",,0 3205,"Lobulus ansiformis cerebelli","human","Latin","ANSIFORM LOBULE",,0 5646,"Lobulus biventer","human","Latin","biventer lobule",,1 -1517506811,"lobulus biventer cerebelli","human","Latin","biventer lobule",,0 5648,"Lobulus biventralis","human","Latin","biventer lobule",,0 671,"Lobulus centralis","human","Latin","central lobule",,4 3135,"Lobulus gracilis","human","Latin","gracile lobule",,1 562,"Lobulus medianus","human","Latin",,"Lobulus medianus",0 563,"Lobulus medius medianus","human","Latin",,"Lobulus medianus",0 3128,"Lobulus paracentralis","human","Latin",,"paracentral lobule",0 5640,"Lobulus parafloccularis cerebelli","human","Latin","paraflocculus",,0 3136,"Lobulus paramedianus cerebelli","human","Latin","gracile lobule",,0 3144,"Lobulus parietalis inferior","human","Latin","INFERIOR PARIETAL LOBULE",,1 3152,"Lobulus parietalis superior","human","Latin","superior parietal lobule",,0 3172,"Lobulus posterior inferior","human","Latin","inferior semilunar lobule",,0 3185,"Lobulus posterior superior","human","Latin","superior semilunar lobule",,0 -2032444017,"Lobulus quadrangularis (Pars cranialis)","human","Latin","anterior quadrangular lobule",,0 3160,"Lobulus quadrangularis (pars rostralis)","human","Latin","anterior quadrangular lobule",,0 3159,"Lobulus quadrangularis anterior","human","Latin","anterior quadrangular lobule",,0 3192,"Lobulus quadrangularis pars caudalis/posterior","human","Latin","simple lobule",,0 3193,"Lobulus quadrangularis pars inferoposterior","human","Latin","simple lobule",,0 3169,"Lobulus semilunaris caudalis","human","Latin","inferior semilunar lobule",,0 1914069831,"Lobulus semilunaris cranialis","human","Latin","superior semilunar lobule",,0 3167,"Lobulus semilunaris inferior","human","Latin","inferior semilunar lobule",,2 3168,"Lobulus semilunaris inferior","Macaca nemestrina","Latin","inferior semilunar lobule",,2 3179,"Lobulus semilunaris rostralis","human","Latin","superior semilunar lobule",,0 3178,"Lobulus semilunaris superior","human","Latin","superior semilunar lobule",,2 3191,"Lobulus simplex","human","Latin","simple lobule",,27 3201,"Lobulus simplex (Crosby)","human","Latin",,"Lobulus simplex (Crosby)",0 517,"Lobus anterior (cerebelli)","Macaca fascicularis","Latin","ANTERIOR LOBE OF CEREBELLUM",,0 516,"Lobus anterior cerebelli","human","Latin","ANTERIOR LOBE OF CEREBELLUM",,0 533,"Lobus caudalis cerebelli","human","Latin","POSTERIOR LOBE OF CEREBELLUM",,2 -1493349805,"Lobus cranialis cerebelli","human","Latin","ANTERIOR LOBE OF CEREBELLUM",,0 554,"Lobus flocculonodularis","human","Latin","FLOCCULONODULAR LOBE",,0 53,"Lobus frontalis","human","Latin","FRONTAL LOBE",,5 482264089,"lobus insulae anterior","human","Latin","SHORT INSULAR GYRI (H)",,0 -753431569,"lobus insulae posterior","human","Latin","LONG INSULAR GYRI (H)",,0 79,"Lobus insularis","human","Latin","INSULA",,0 -1005319881,"lobus limbicus","human","Latin","LIMBIC LOBE",,1 67,"Lobus occipitalis","human","Latin","OCCIPITAL LOBE",,1 3138,"Lobus paramedianus","Macaca nemestrina","Latin","gracile lobule",,1 3137,"Lobus paramedianus cerebelli","Macaca fascicularis","Latin","gracile lobule",,0 58,"Lobus parietalis","human","Latin","PARIETAL LOBE",,2 532,"Lobus posterior cerebelli","human","Latin","POSTERIOR LOBE OF CEREBELLUM",,0 518,"Lobus rostralis cerebelli","human","Latin","ANTERIOR LOBE OF CEREBELLUM",,0 72,"Lobus temporalis","human","Latin","TEMPORAL LOBE",,0 440,"Locus caeruleus","Macaca mulatta","Latin","locus ceruleus",,45 439,"Locus caeruleus","human","Latin","locus ceruleus",,45 438,"Locus caeruleus","human","Latin","locus ceruleus",,45 432,"locus ceruleus","human","English","locus ceruleus",,748 436,"locus coeruleus","rat","Latin","locus ceruleus",,4961 435,"Locus coeruleus","Macaca fascicularis","Latin","locus ceruleus",,4961 434,"Locus coeruleus","human","Latin","locus ceruleus",,4961 1378,"long association bundles","human","English",,"long association bundles",0 -1717520490,"long association fibers","human","English",,"long association bundles",0 2700,"long gyrus of insula","human","English","LONG INSULAR GYRI (H)",,0 2696,"long insular gyri","human","English","LONG INSULAR GYRI (H)",,1 1379,"longitudinal association bundles","human","English",,"long association bundles",0 2298,"longitudinal cerebral fissure","human","English","longitudinal fissure",,7 2236,"longitudinal fasciculus of the pons","rat","English","longitudinal pontine fibers",,0 2292,"longitudinal fissure","Macaca fascicularis","English","longitudinal fissure",,31 2291,"longitudinal fissure","human","English","longitudinal fissure",,31 2305,"longitudinal fissure of hemisphere","human","English","longitudinal fissure",,0 6273,"longitudinal insular sulcus","human","English","longitudinal sulcus of insula (H)",,0 2233,"longitudinal pontine fibers","human","English","longitudinal pontine fibers",,1 2234,"longitudinal pontine fibers","Macaca fascicularis","English","longitudinal pontine fibers",,1 6070,"longitudinal striae","human","English",,"longitudinal striae",5 2301,"longitudinal sulcus","human","English","longitudinal fissure",,0 6270,"longitudinal sulcus of insula","human","English","longitudinal sulcus of insula (H)",,0 658,"loop of Archambault","human","English",,"inferior optic radiation",0 657,"loop of Meyer","human","English",,"inferior optic radiation",0 6245,"lower calcarine sulcus","Macaca mulatta","English","inferior calcarine sulcus (M)",,0 4467,"LP","human","Abbreviation","lateral posterior nucleus",,0 4466,"LP","Macaca mulatta","Abbreviation","lateral posterior nucleus",,0 5344,"LRpo (Percheron)","Macaca","Abbreviation",,"Nucleus dorsooralis (Hassler)",0 1506,"lumbar cistern","human","English",,"lumbar cistern",10 7092,"lumbar enlargement","human","English",,"lumbar enlargement",213 7160,"lumbar segments","human","English",,"lumbar segments",395 7161,"lumbar segments of spinal cord","human","English",,"lumbar segments",0 7093,"lumbosacral enlargement","human","English",,"lumbar enlargement",45 7094,"lumbosacral nucleus","human","English",,"lumbosacral nucleus",0 6430,"lunate fissure","human","English","lunate sulcus",,0 6428,"lunate sulcus","Macaca fascicularis","English","lunate sulcus",,21 1611,"Lyra","human","Latin","commissure of fornix",,87 1612,"Lyra Davidis","human","Latin","commissure of fornix",,0 -892490986,"macaque brain","Macaca","English",,"monkey brain",0 3673,"magnocellular division of accessory basal nucleus","Macaca fascicularis","English",,"magnocellular division of accessory basal nucleus",0 3706,"magnocellular division of basal nucleus","Macaca fascicularis","English",,"magnocellular division of basal nucleus",0 4525,"magnocellular mediodorsal nucleus","Macaca","English","magnocellular part of medial dorsal nucleus",,1 4127,"magnocellular nucleus of medial geniculate body","Macaca fascicularis","English","magnocellular nucleus of medial geniculate body",,0 4126,"magnocellular nucleus of medial geniculate body","human","English","magnocellular nucleus of medial geniculate body",,0 4524,"magnocellular part of dorsomedial nucleus","human","English","magnocellular part of medial dorsal nucleus",,0 4518,"magnocellular part of medial dorsal nucleus","Macaca fascicularis","English","magnocellular part of medial dorsal nucleus",,0 5661,"magnocellular part of red nucleus","human","English","magnocellular part of red nucleus",,1 5662,"magnocellular part of red nucleus","Macaca fascicularis","English","magnocellular part of red nucleus",,1 5316,"magnocellular part of ventral anterior nucleus","Macaca fascicularis","English","magnocellular part of ventral anterior nucleus",,0 5315,"magnocellular part of ventral anterior nucleus","human","English","magnocellular part of ventral anterior nucleus",,0 5322,"Magnocellular ventral anterior nucleus","Macaca","Latin","magnocellular part of ventral anterior nucleus",,1 5321,"Magnocellular ventral anterior nucleus","human","Latin","magnocellular part of ventral anterior nucleus",,1 1222,"magnopyramidal region of Braak","human","English",,"auditory association cortex",0 1220,"magnopyramidal temporal belt","human","English",,"auditory association cortex",0 1221,"magnopyramidal temporal field","human","English",,"auditory association cortex",0 6211,"main cingulate gyrus","human","English",,"main cingulate gyrus",0 1368,"main olfactory bulb","rat","English","olfactory bulb",,306 4637,"main olivary nucleus","human","English","principal inferior olivary nucleus",,1 545536642,"main sensory nucleus","human","English","principal sensory nucleus of trigeminal nerve",,52 4671,"main superior olivary nucleus","human","English","medial superior olivary nucleus",,0 1485977850,"major root of trigeminal nerve","human","English",,"sensory root of trigeminal nerve",0 1690,"mamillary body","human","English","mammillary body",,96 2057,"mamillothalamic fasciculus","human","English",,"mammillothalamic tract",0 2051,"mamillothalamic tract","Macaca fascicularis","English",,"mammillothalamic tract",20 2052,"mamillo-thalamic tract","human","English",,"mammillothalamic tract",0 1685,"mammillary body","human","English","mammillary body",,186 219,"mammillary level of hypothalamus","human","English","POSTERIOR HYPOTHALAMIC REGION",,0 5704,"mammillary peduncle","Macaca fascicularis","English","mammillary peduncle",,15 5705,"mammillary peduncle","rat","English","mammillary peduncle",,15 5703,"mammillary peduncle","human","English","mammillary peduncle",,15 2030,"mammillary princeps fasciculus","Macaca fascicularis","English","mammillary princeps fasciculus",,0 2029,"mammillary princeps fasciculus","human","English","mammillary princeps fasciculus",,0 218,"mammillary region","human","English","POSTERIOR HYPOTHALAMIC REGION",,25 3447,"mammillo-infundibular nuclei","human","English",,"mammillo-infundibular nucleus",0 5313,"mammilloinfundibular nucleus","human","English","tuberomammillary nucleus",,0 3446,"mammillo-infundibular nucleus","human","English",,"mammillo-infundibular nucleus",0 2039,"mammillotegmental fasciculus","Macaca fascicularis","English","mammillotegmental fasciculus",,0 2038,"mammillotegmental fasciculus","human","English","mammillotegmental fasciculus",,0 2041,"mammillotegmental tract","human","English","mammillotegmental fasciculus",,5 2042,"mammillotegmental tract","rat","English","mammillotegmental fasciculus",,5 2043,"mammillo-tegmental tract","human","English","mammillotegmental fasciculus",,2 2048,"mammillothalamic tract","rat","English",,"mammillothalamic tract",43 2047,"mammillothalamic tract","human","English",,"mammillothalamic tract",43 2061,"mammillothalamic tract of hypothalamus","Macaca fascicularis","English","mammillothalamic tract of hypothalamus",,0 2059,"mammillothalamic tract of thalamus","Macaca fascicularis","English","mammillothalamic tract of thalamus",,0 3399,"mantle layer of neural tube","human","English",,"mantle layer of neural tube",0 6437,"marginal branch of cingulate sulcus","human","English","marginal sulcus (H)",,0 2650,"marginal gyrus","human","English","superior frontal gyrus",,16 6293,"marginal insular sulcus","human","English","circular sulcus of insula",,0 3400,"marginal layer of neural tube","human","English",,"marginal layer of neural tube",0 6629,"marginal precentral sulcus","human","English",,"marginal precentral sulcus (H)",0 6438,"marginal ramus of cingulate sulcus","human","English","marginal sulcus (H)",,1 6435,"marginal sulcus","human","English","marginal sulcus (H)",,2 -1456493709,"marginal sulcus (H)","human","English",,,0 6292,"marginal sulcus of insula","human","English","circular sulcus of insula",,0 6298,"margo denticulatus","human","English",,"margo denticulatus",0 3206,"Margo inferior","human","Latin",,"Margo inferior",0 3207,"Margo inferolateralis","human","Latin",,"Margo inferior",0 3209,"Margo inferomedialis","human","Latin",,"Margo medialis",0 3208,"Margo medialis","human","Latin",,"Margo medialis",0 3210,"Margo superior","human","Latin",,"Margo superior",0 3211,"Margo superomedialis","human","Latin",,"Margo superior",0 3740,"Massa intercalata","human","Latin","intercalated amygdaloid nuclei",,1 663,"Massa intermedia","human","Latin","interthalamic adhesion",,32 5959,"Massa praecommissuralis","human","Latin","SEPTUM",,0 33,"mature diencephalon","human","English","DIENCEPHALON",,1 4379,"MD","human","Abbreviation","MEDIAL DORSAL NUCLEUS",,0 4378,"MD","Macaca mulatta","Abbreviation","MEDIAL DORSAL NUCLEUS",,0 1458,"Meckel's cave","human","English",,"Meckel's cave",0 4300,"medial (fastigial) nucleus","rat","English","fastigial nucleus",,1 4624,"medial accessory inferior olivary nucleus","Macaca fascicularis","English","medial accessory inferior olivary nucleus",,0 4623,"medial accessory inferior olivary nucleus","human","English","medial accessory inferior olivary nucleus",,0 4629,"medial accessory olivary nucleus","human","English","medial accessory inferior olivary nucleus",,8 3751,"medial amygdaloid nucleus","Macaca fascicularis","English","medial amygdaloid nucleus",,202 3752,"medial amygdaloid nucleus","rat","English","medial amygdaloid nucleus",,202 3750,"medial amygdaloid nucleus","human","English","medial amygdaloid nucleus",,202 3459,"medial arcuate nucleus","human","English","arcuate nucleus of medulla",,3 3692,"medial basal nucleus of amygdala","Unspecified","English","medial part of basal amygdaloid nucleus",,0 7087,"medial bundle","human","English",,"medial bundle",0 -1485212469,"medial cortical zone","human","English",,"vermis of cerebellum",0 2019551297,"medial corticohypothalamic tract","human","English",,"medial corticohypothalamic tract",10 3693,"medial division of basal nucleus","Unspecified","English","medial part of basal amygdaloid nucleus",,0 3703,"medial division of central nucleus of amygdala","Macaca fascicularis","English",,"medial division of central nucleus of amygdala",0 -378419745,"medial division of globus pallidus","human","English","medial globus pallidus",,0 4132,"medial division of medial geniculate body","human","English","magnocellular nucleus of medial geniculate body",,0 4360,"medial dorsal nucleus","Macaca fascicularis","English","MEDIAL DORSAL NUCLEUS",,29 -1594935099,"medial dorsal nucleus - not otherwise specified","Unspecified","English","MEDIAL DORSAL NUCLEUS - not otherwise specified",,29 4375,"medial dorsal thalamic nucleus","human","English","MEDIAL DORSAL NUCLEUS",,7 1895,"medial eminence","human","English","medial eminence of fourth ventricle",,31 1760800545,"medial eminence","human","English","MEDIAN EMINENCE",,0 1891,"medial eminence of fourth ventricle","human","English","medial eminence of fourth ventricle",,0 2139907240,"medial fasciculus","human","English",,"gracile fasciculus",0 3710,"medial fiber bundle of amygdala","Macaca fascicularis","English",,"medial fiber bundle of amygdala",0 2069,"medial forebrain bundle","human","English","medial forebrain bundle",,1362 2071,"medial forebrain fasciculus","human","English","medial forebrain bundle",,0 2643,"medial frontal gyrus","human","English",,"medial frontal gyrus",21 967216542,"medial frontal gyrus (Mai)","human","English","middle frontal gyrus",,0 6631,"medial frontal sulcus","human","English",,"medial frontal sulcus (H)",0 185,"medial geniculate body","human","English","MEDIAL GENICULATE BODY",,446 186,"medial geniculate body","Macaca fascicularis","English","MEDIAL GENICULATE BODY",,446 197,"medial geniculate complex","rat","English","MEDIAL GENICULATE BODY",,31 4134,"medial geniculate complex, medial part","rat","English","magnocellular nucleus of medial geniculate body",,0 4140,"medial geniculate complex, ventral part","rat","English","ventral nucleus of medial geniculate body",,0 195,"medial geniculate nucleus","Macaca fascicularis","English","MEDIAL GENICULATE BODY",,199 196,"medial geniculate nucleus","rat","English","MEDIAL GENICULATE BODY",,199 194,"medial geniculate nucleus","human","English","MEDIAL GENICULATE BODY",,199 4133,"medial geniculate nucleus, medial part","rat","English","magnocellular nucleus of medial geniculate body",,0 4118,"medial geniculate nucleus, parvocellular portion","human","English",,"Nucleus geniculatus medialis, pars parvocellularis",0 4139,"medial geniculate nucleus, ventral part","rat","English","ventral nucleus of medial geniculate body",,0 2527,"medial globus pallidus","Macaca fascicularis","English","medial globus pallidus",,38 4357,"medial habenula","rat","English","medial habenular nucleus",,235 4353,"medial habenular nucleus","rat","English","medial habenular nucleus",,124 4352,"medial habenular nucleus","Macaca fascicularis","English","medial habenular nucleus",,124 4351,"medial habenular nucleus","human","English","medial habenular nucleus",,124 3443,"medial hypothalamic zone (Crosby)","human","English",,"medial hypothalamic zone (Crosby)",0 1833,"medial lemniscus","Macaca fascicularis","English",,"medial lemniscus",258 1834,"medial lemniscus","rat","English",,"medial lemniscus",258 1832,"medial lemniscus","human","English",,"medial lemniscus",258 1850,"medial lemniscus of medulla","Macaca fascicularis","English","medial lemniscus of medulla",,0 1849,"medial lemniscus of medulla","human","English","medial lemniscus of medulla",,0 1842,"medial lemniscus of midbrain","human","English","medial lemniscus of midbrain",,0 1843,"medial lemniscus of midbrain","Macaca fascicularis","English","medial lemniscus of midbrain",,0 1846,"medial lemniscus of pons","Macaca fascicularis","English","medial lemniscus of pons",,0 1845,"medial lemniscus of pons","human","English","medial lemniscus of pons",,0 2010,"medial longitudinal bundle","human","English",,"medial longitudinal fasciculus",0 2009,"medial longitudinal fascicle","rat","English",,"medial longitudinal fasciculus",39 2008,"medial longitudinal fascicle","Macaca fascicularis","English",,"medial longitudinal fasciculus",39 2005,"medial longitudinal fasciculus","rat","English",,"medial longitudinal fasciculus",408 2004,"medial longitudinal fasciculus","human","English",,"medial longitudinal fasciculus",408 2019,"medial longitudinal fasciculus of medulla","Macaca fascicularis","English","medial longitudinal fasciculus of medulla",,0 2017,"medial longitudinal fasciculus of midbrain","Macaca fascicularis","English","medial longitudinal fasciculus of midbrain",,0 2021,"medial longitudinal fasciculus of pons","Macaca fascicularis","English","medial longitudinal fasciculus of pons",,0 2302,"medial longitudinal fissure","human","English","longitudinal fissure",,0 6060,"medial longitudinal stria","human","English","medial longitudinal stria",,0 6062,"medial longitudinal stria of Lancisi","human","English","medial longitudinal stria",,0 4159,"medial mammillary nucleus","Macaca fascicularis","English","MEDIAL MAMMILLARY NUCLEUS",,86 4160,"medial mammillary nucleus","rat","English","MEDIAL MAMMILLARY NUCLEUS",,86 4157,"medial mammillary nucleus","human","English","MEDIAL MAMMILLARY NUCLEUS",,86 4158,"medial mammillary nucleus","human","English","MEDIAL MAMMILLARY NUCLEUS",,86 4172,"medial mammillary nucleus (Carpenter)","Unspecified","English","medial part of medial mammillary nucleus",,0 4171,"medial mammillary nucleus (Carpenter)","human","English","medial part of medial mammillary nucleus",,0 4177,"medial mammillary nucleus, lateral part","human","English","lateral part of medial mammillary nucleus",,0 4169,"medial mammillary nucleus, medial part","human","English","medial part of medial mammillary nucleus",,0 4170,"medial mammillary nucleus, median part","rat","English","medial part of medial mammillary nucleus",,0 2999,"medial medullary lamina","human","English","medial medullary lamina",,4 3009,"medial medullary lamina of globus pallidus","human","English","medial medullary lamina",,0 3015,"medial medullary lamina of inferior colliculus","human","English",,"medial medullary lamina of inferior colliculus",0 3003,"medial medullary lamina of pallidum","human","English","medial medullary lamina",,0 3006,"medial medullary stria","human","English","medial medullary lamina",,0 4367,"medial nuclear group","human","English","MEDIAL DORSAL NUCLEUS",,2 3498,"medial nuclear group (Crosby)","human","English",,"medial nuclear group (Crosby)",0 7180,"medial nuclear group of anterior horn","human","English",,"medial nuclear group of anterior horn",0 3757,"medial nucleus of amygdala","rat","English","medial amygdaloid nucleus",,7 3758,"medial nucleus of amygdala (Amaral)","Macaca fascicularis","English",,"medial nucleus of amygdala (Amaral)",0 4131,"medial nucleus of medial geniculate body","human","English","magnocellular nucleus of medial geniculate body",,0 2689,"medial occipitotemporal gyrus","human","English","lingual gyrus",,2 2692,"medial occipitotemporal gyrus","human","English",,"medial occipitotemporal gyrus (Mai)",2 2688,"medial occipitotemporal gyrus","human","English","lingual gyrus",,2 2667,"medial occipitotemporal gyrus-1 (Heimer)","human","English","fusiform gyrus",,0 2691,"medial occipitotemporal gyrus-2","human","English","lingual gyrus",,0 5408,"medial oculomotor cell column","Unspecified","English","medial oculomotor nucleus",,0 5406,"medial oculomotor nucleus","human","English","medial oculomotor nucleus",,0 5936,"medial olfactory area","human","English",,"medial olfactory area",1 2729,"medial olfactory gyrus","human","English","medial olfactory gyrus",,1 6098,"medial olfactory stria","human","English",,"medial olfactory stria",1 6101,"medial olfactory tract","Unspecified","English",,"medial olfactory stria",36 6100,"medial olfactory tract","human","English",,"medial olfactory stria",36 2736,"medial orbital gyrus","human","English","medial orbital gyrus",,1 2737,"medial orbital gyrus","Macaca mulatta","English","medial orbital gyrus",,1 6490,"medial orbital sulcus","Macaca mulatta","English","medial orbital sulcus",,1 -268743111,"medial orbital sulcus","human","English","medial orbital sulcus",,0 -153723377,"medial orbital white matter","Unspecified","English","medial orbital white matter",,0 2532,"medial pallidal segment","human","English","medial globus pallidus",,16 4699,"medial parabrachial nucleus","rat","English","medial parabrachial nucleus",,50 4698,"medial parabrachial nucleus","Macaca fascicularis","English","medial parabrachial nucleus",,50 4697,"medial parabrachial nucleus","human","English","medial parabrachial nucleus",,50 3148,"medial parietal gyrus","human","English",,"medial parietal gyrus",0 6511,"medial parieto-occipital fissure","Macaca mulatta","English","anterior parieto-occipital sulcus (M)",,1 4550,"medial parolfactory nucleus","human","English","medial septal nucleus",,0 3691,"medial part of basal amygdaloid nucleus","Unspecified","English","medial part of basal amygdaloid nucleus",,0 2791,"medial part of gyri orbitales","human","English","gyrus rectus",,0 4166,"medial part of medial mammillary nucleus","human","English","medial part of medial mammillary nucleus",,0 -7773324,"medial part of solitary nucleus","human","English","medial subnucleus of solitary tract",,0 5383,"medial part of ventral lateral nucleus","human","English","medial part of ventral lateral nucleus",,0 5384,"medial part of ventral lateral nucleus","Macaca fascicularis","English","medial part of ventral lateral nucleus",,0 4206,"medial pericuneate nucleus","human","English","medial pericuneate nucleus",,0 5766,"medial pes lemniscus","human","English","medial pes lemniscus",,0 6633,"medial precentral sulcus","human","English",,"medial precentral sulcus (H)",0 1086,"medial prefrontal cortex","human","English",,"medial prefrontal cortex",1006 4905,"medial preoptic area","human","English","medial preoptic nucleus",,1363 4906,"medial preoptic hypothalamic nucleus","human","English","medial preoptic nucleus",,2 4900,"medial preoptic nucleus","Macaca fascicularis","English","medial preoptic nucleus",,392 4901,"medial preoptic nucleus","rat","English","medial preoptic nucleus",,392 4899,"medial preoptic nucleus","human","English","medial preoptic nucleus",,392 3665,"medial principal nucleus","Unspecified","English","accessory basal amygdaloid nucleus",,2 4962,"medial pulvinar nucleus","Macaca fascicularis","English","medial pulvinar nucleus",,17 4961,"medial pulvinar nucleus","human","English","medial pulvinar nucleus",,17 3947,"medial raphe nucleus","human","English",,"medial raphe nucleus",29 7252,"medial reticulospinal tract","human","English",,"pontine reticulospinal tract",3 4545,"medial septal nucleus","Macaca fascicularis","English","medial septal nucleus",,331 4544,"medial septal nucleus","human","English","medial septal nucleus",,331 4546,"medial septal nucleus","rat","English","medial septal nucleus",,331 6064,"medial stripe of Lancisi","human","English","medial longitudinal stria",,0 4168,"medial subdivision of medial mammillary nucleus","human","English","medial part of medial mammillary nucleus",,0 2950,"medial subnucleus of midbrain central gray","human","English",,"medial subnucleus of midbrain central gray",0 5132,"medial subnucleus of solitary tract","human","English","medial subnucleus of solitary tract",,0 4663,"medial superior olivary nucleus","human","English","medial superior olivary nucleus",,49 4664,"medial superior olivary nucleus","Macaca fascicularis","English","medial superior olivary nucleus",,49 4666,"medial superior olive","human","English","medial superior olivary nucleus",,109 4667,"medial superior olive","rat","English","medial superior olivary nucleus",,109 2437,"medial tegmental process of Jacobsohn","human","English",,"medial tegmental process of Jacobsohn",0 4369,"medial thalamic nuclei","human","English","MEDIAL DORSAL NUCLEUS",,71 4365,"medial thalamic nucleus","human","English","MEDIAL DORSAL NUCLEUS",,32 -1890020188,"medial transverse frontopolar gyrus","human","English","medial transverse frontopolar gyrus (H)",,0 3581,"medial tuberal nucleus","human","English",,"medial tuberal nucleus",8 5564,"medial vestibular nucleus","rat","English","medial vestibular nucleus",,349 5562,"medial vestibular nucleus","human","English","medial vestibular nucleus",,349 5563,"medial vestibular nucleus","Macaca fascicularis","English","medial vestibular nucleus",,349 7048,"medial vestibulospinal tract","human","English",,"medial vestibulospinal tract",24 6063,"medial white stria of Lancisi","human","English","medial longitudinal stria",,0 3441,"medial zone of hypothalamus","human","English",,"medial zone of hypothalamus",0 774,"median aperture of fourth ventricle","human","English","median aperture of fourth ventricle",,0 1896,"median eminence","human","English","MEDIAN EMINENCE",,4159 1897,"median eminence","Macaca fascicularis","English","MEDIAN EMINENCE",,4159 1898,"median eminence","rat","English","MEDIAN EMINENCE",,4159 1901,"median eminence of tuber cinereum","human","English","MEDIAN EMINENCE",,0 1840,"median fillet","human","English",,"medial lemniscus",0 6451,"median fissure of floor of fourth ventricle","human","English","median sulcus",,0 3941,"median nucleus of the raphe","human","English","superior central nucleus",,1 4910,"median preoptic nucleus","rat","English","median preoptic nucleus",,211 4909,"median preoptic nucleus","Macaca fascicularis","English","median preoptic nucleus",,211 4908,"median preoptic nucleus","human","English","median preoptic nucleus",,211 5898,"median raphe","human","English",,"median raphe",719 3945,"median raphe nucleus","rat","English","superior central nucleus",,310 6448,"median sulcus","human","English","median sulcus",,25 6450,"median sulcus of rhomboid fossa","human","English","median sulcus",,0 4371,"mediodorsal nucleus","human","English","MEDIAL DORSAL NUCLEUS",,260 4374,"mediodorsal nucleus","human","English","MEDIAL DORSAL NUCLEUS",,260 4370,"mediodorsal thalamic nucleus","human","English","MEDIAL DORSAL NUCLEUS",,155 4543,"mediodorsal thalamic nucleus, pars fasciculosa","human","English","parvicellular part of medial dorsal nucleus",,0 5083,"medioventral nucleus","Macaca mulatta","English","reuniens nucleus",,1 43,"medulla","human","English","MEDULLA OBLONGATA",,28832 40,"medulla oblongata","Macaca fascicularis","English","MEDULLA OBLONGATA",,10519 39,"medulla oblongata","human","English","MEDULLA OBLONGATA",,10519 42,"Medulla oblongata","human","Latin","MEDULLA OBLONGATA",,10519 1923,"Medulla spinalis","human","Latin",,"spinal cord",24 1637,"medullary anterior horn","human","English","medullary anterior horn",,0 462,"medullary body","Unspecified","English","medullary body",,2 1466,"medullary center","human","English","semioval center",,4 6143,"medullary central gray substance","human","English","central gray substance of medulla",,0 5658,"medullary lamina of red nucleus","human","English",,"medullary lamina of red nucleus",0 5850,"medullary pyramid","human","English","pyramid of medulla",,61 2446,"medullary reticular formation","Macaca fascicularis","English","MEDULLARY RETICULAR FORMATION",,397 2445,"medullary reticular formation","human","English","MEDULLARY RETICULAR FORMATION",,397 7255,"medullary reticulospinal fibers","human","English",,"medullary reticulospinal tract",0 7254,"medullary reticulospinal tract","human","English",,"medullary reticulospinal tract",0 1863,"medullary sensory decussation","human","English","decussation of medial lemniscus",,0 455,"medullary substance of cerebellum","human","English","CEREBELLAR WHITE MATTER",,0 -1163843859,"medullary substance of frontal lobe","human","English","FRONTAL WHITE MATTER",,0 460,"medullary substance of medulla","human","English","MEDULLARY WHITE MATTER",,0 457,"medullary white matter","Unspecified","English","MEDULLARY WHITE MATTER",,5 -884325547,"medullary white matter - not otherwise specified","Unspecified","English","MEDULLARY WHITE MATTER - not otherwise specified",,5 2936,"medullary-pontine junction","human","English",,"medullary-pontine junction",0 651,"meninges","human","English",,"meninges",3164 652,"Meninges","human","Latin",,"meninges",3164 -1987290305,"mesencephalic aqueduct","human","English","cerebral aqueduct",,14 1020035023,"mesencephalic nucleus of trigeminal nerve","human","English","mesencephalic nucleus of trigeminal nerve",,0 4565,"mesencephalic root of V","human","English","mesencephalic tract of trigeminal nerve",,0 262,"mesencephalic tectum","human","English","TECTUM",,37 269,"mesencephalic tegmentum","human","English","MIDBRAIN TEGMENTUM",,240 4557,"mesencephalic tract of trigeminal nerve","Macaca fascicularis","English","mesencephalic tract of trigeminal nerve",,1 4556,"mesencephalic tract of trigeminal nerve","human","English","mesencephalic tract of trigeminal nerve",,1 4558,"mesencephalic tract of trigeminal nerve","rat","English","mesencephalic tract of trigeminal nerve",,1 4574,"mesencephalic trigeminal nucleus","rat","English","mesencephalic nucleus of trigeminal nerve",,199 4564,"mesencephalic trigeminal tract","rat","English","mesencephalic tract of trigeminal nerve",,13 4563,"mesencephalic trigeminal tract","human","English","mesencephalic tract of trigeminal nerve",,13 17,"Mesencephalon","human","Latin","MIDBRAIN",,9093 18,"mesencephalon","human","Latin","MIDBRAIN",,9093 1839,"Mesial fillet","human","Latin",,"medial lemniscus",0 2533,"mesial pallidum","human","English","medial globus pallidus",,0 3212,"mesocortex","human","English",,"mesocortex",26 3213,"Mesocortex","human","Latin",,"mesocortex",26 -1844791893,"mesocortical region","primate","English",,"paralimbic brain",0 169,"metathalamus","Macaca fascicularis","English","METATHALAMUS",,9 168,"metathalamus","human","English","METATHALAMUS",,9 170,"Metathalamus","human","Latin","METATHALAMUS",,9 1556,"metathalamus (Crosby)","human","English",,"metathalamus (Crosby)",0 36,"metencephalon","human","English","METENCEPHALON",,135 37,"Metencephalon","human","Latin","METENCEPHALON",,135 45,"metepencephalon","human","English","MEDULLA OBLONGATA",,0 656,"Meyer's loop","human","English",,"inferior optic radiation",0 774002018,"Meynertschen Solitaerszellen","Cercopithecus","Latin",,"solitary cells of Meynert",0 436546732,"Mid horizontal zeroplane","Macaca mulatta","English",,"Horsley-Clarke zero plane",0 15,"midbrain","human","English","MIDBRAIN",,8570 16,"midbrain","Macaca fascicularis","English","MIDBRAIN",,8570 2422,"midbrain reticular formation","human","English","MIDBRAIN RETICULAR FORMATION",,350 2423,"midbrain reticular formation","Macaca fascicularis","English","MIDBRAIN RETICULAR FORMATION",,350 -438160199,"MIDBRAIN RETICULAR FORMATION - not otherwise specified","Unspecified","English","MIDBRAIN RETICULAR FORMATION - not otherwise specified",,350 263,"midbrain tectum","human","English","TECTUM",,82 266,"midbrain tegmentum","human","English","MIDBRAIN TEGMENTUM",,329 267,"midbrain tegmentum","Macaca fascicularis","English","MIDBRAIN TEGMENTUM",,329 2940,"midbrain-diencephalic junction","human","English",,"midbrain-diencephalic junction",4 2941,"midbrain-diencephalic junction","human","English",,"midbrain-diencephalic junction",4 478,"middle cerebellar peduncle","human","English","middle cerebellar peduncle",,71 480,"middle cerebellar peduncle","rat","English","middle cerebellar peduncle",,71 479,"middle cerebellar peduncle","Macaca fascicularis","English","middle cerebellar peduncle",,71 665,"middle commissure","human","English","interthalamic adhesion",,0 886,"middle frontal area 46","human","English",,"middle frontal area 46",0 6341,"middle frontal fissure","human","English","middle frontal sulcus (H)",,0 2636,"middle frontal gyrus","human","English","middle frontal gyrus",,102 2637,"middle frontal gyrus","Macaca mulatta","English","middle frontal gyrus",,102 6335,"middle frontal sulcus","human","English","middle frontal sulcus (H)",,0 1646070319,"middle frontal white matter","Unspecified","English","middle frontal white matter",,0 6000,"middle gray layer of superior colliculus","human","English","middle gray layer of superior colliculus",,0 3444,"middle hypothalamic zone (Crosby)","human","English",,"medial hypothalamic zone (Crosby)",0 560,"middle lobe of Elliot Smith","human","English",,"middle lobe of Elliot Smith",0 2874,"middle lobe of hypophysis","human","English","intermediate part of hypophysis",,0 561,"middle lobe of Ingvar","human","English",,"middle lobe of Ingvar",0 537,"middle lobe-1 of cerebellum","human","English","POSTERIOR LOBE OF CEREBELLUM",,0 2574,"middle part of inferior parietal lobule","human","English","angular gyrus",,0 6400,"middle ramus of lateral fissure","human","English","anterior ascending limb of lateral sulcus (H)",,0 3601,"middle region of motor thalamus","Macaca","English",,"anteromedial region of motor thalamus",0 937,"middle temporal area 21","human","English",,"middle temporal area 21",0 6604,"middle temporal fissure (Crosby)","human","English","inferior temporal sulcus (H)",,0 2818,"middle temporal gyrus","Macaca mulatta","English","middle temporal gyrus",,107 2817,"middle temporal gyrus","human","English","middle temporal gyrus",,107 6608,"middle temporal sulcus","Macaca fascicularis","English","middle temporal sulcus (M)",,3 6609,"middle temporal sulcus","Macaca mulatta","English","middle temporal sulcus (M)",,3 -159017704,"middle temporal sulcus","Macaca fascicularis","English","middle temporal sulcus (M)",,3 661570873,"middle temporal sulcus (Krieg)","Macaca mulatta","English","anterior middle temporal sulcus (M)",,0 1693049094,"middle temporal sulcus (Martin-97)","Macaca fascicularis","English","anterior middle temporal sulcus (M)",,0 6602,"middle temporal sulcus (Szikla)","human","English","inferior temporal sulcus (H)",,0 953932792,"middle temporal white matter","Unspecified","English","middle temporal white matter",,0 5748,"middle thalamic peduncle","human","English","superior thalamic peduncle",,0 5886,"middle thalamic radiation","human","English",,"superior thalamic radiations",0 6012,"middle white layer of superior colliculus","human","English","middle white layer of superior colliculus",,0 3523,"midline nuclear group","human","English","MIDLINE NUCLEAR GROUP",,4 3524,"midline nuclear group","Macaca fascicularis","English","MIDLINE NUCLEAR GROUP",,4 3526,"midline nuclei of thalamus","human","English","MIDLINE NUCLEAR GROUP",,3 984250604,"minor root of trigeminal nerve","human","English","motor root of trigeminal nerve",,0 6170,"mixed-cell part of substantia nigra","human","English",,"mixed cell part of substantia nigra",0 2011,"MLF","human","Abbreviation",,"medial longitudinal fasciculus",0 708,"modified granular cortex","human","English",,"modified granular cortex",0 6035,"molecular layer of cerebellar cortex","human","English",,"molecular layer of cerebellar cortex",3 3019,"molecular layer of cerebral cortex","human","English",,"molecular layer",0 2410,"molecular layer of dentate gyrus","Macaca mulatta","English",,"molecular layer of dentate gyrus",0 2409,"molecular layer of dentate gyrus","human","English",,"molecular layer of dentate gyrus",0 -2049577174,"molecular layer of hippocampus","human","English",,"molecular layer of hippocampus",0 140480905,"monkey brain","Unspecified","English",,"monkey brain",536 803,"motor area","human","English",,"motor cortex",1135 802,"motor area","Macaca","English",,"motor cortex",1135 797,"motor area (Crosby)","human","English",,"primary motor cortex",0 3340,"motor branch of trigeminal nerve","human","English","motor root of trigeminal nerve",,0 801,"motor cortex","human","English",,"motor cortex",7686 795,"motor cortex (Carpenter)","human","English",,"primary motor cortex",0 153719626,"motor cortex (Noback)","human","English","precentral gyrus",,0 6738,"motor decussation","human","English","pyramidal decussation",,0 7126,"motor nucleus of spinal cord","human","English",,"anterior horn nuclei",0 5051,"motor nucleus of tegmentum","human","English",,"motor nucleus of tegmentum",0 -126458021,"motor nucleus of trigeminal nerve","rat","English","motor nucleus of trigeminal nerve",,2 1247251235,"motor nucleus of trigeminal nerve","human","English","motor nucleus of trigeminal nerve",,2 4284,"motor nucleus of VII","human","English","facial motor nucleus",,1 3341,"motor root of N. V","human","English","motor root of trigeminal nerve",,0 3333,"motor root of trigeminal nerve","rat","English","motor root of trigeminal nerve",,1 3332,"motor root of trigeminal nerve","human","English","motor root of trigeminal nerve",,1 1099,"motor speech area of Broca","human","English",,"Broca's area",0 800,"motor strip","human","English",,"primary motor cortex",69 3590,"motor thalamus","Macaca","English",,"motor thalamus",0 3589,"motor thalamus","human","English",,"motor thalamus",0 1567354112,"motor trigeminal nucleus","rat","English","motor nucleus of trigeminal nerve",,85 3024,"multiform layer","human","English",,"multiform layer",4 41,"Myelencephalon","human","Latin","MEDULLA OBLONGATA",,92 1924,"Myelon","human","Latin",,"spinal cord",41 1548,"myomeric efferents","human","English",,"general somatic efferents",0 4551,"N. septi medialis","human","Latin","medial septal nucleus",,0 388,"Nates","human","Latin","SUPERIOR COLLICULUS",,47 534,"Neocerebellum","human","Latin","POSTERIOR LOBE OF CEREBELLUM",,52 542,"neocerebellum (Crosby)","human","English",,"neocerebellum (Crosby)",0 3215,"neocortex","human","English",,"neocortex",6264 3216,"Neocortex","human","Latin",,"neocortex",6264 4221,"neodentate part of dentate nucleus","human","English","neodentate part of dentate nucleus",,0 4223,"neodentate portion of dentate nucleus","human","English","neodentate part of dentate nucleus",,0 3221,"neopallial cortex","human","English",,"neocortex",0 3217,"neopallium","human","English",,"neocortex",56 5675,"Neoruber","human","Latin","parvocellular part of red nucleus",,0 1711,"neostriatum","human","English","STRIATUM",,3760 3282,"Nerve I","human","English","olfactory nerve",,84 1471,"Nerve II","human","English","optic nerve",,42 276,"Nerve III","human","English","oculomotor nerve",,31 318,"Nerve IV","human","English","trochlear nerve",,8 3274,"Nerve IX","human","English","glossopharyngeal nerve",,26 5623,"nerve of Jocobson","human","English",,"vomeronasal nerve",0 3318,"Nerve V","Macaca mulatta","English","trigeminal nerve",,47 3238,"Nerve VI","human","English","abducens nerve",,13 2159,"Nerve VII","human","English","facial nerve",,41 3344,"Nerve X","human","English","vagus nerve",,29 3287,"Nerve XI","human","English",,"accessory nerve",0 3292,"Nerve XI (cranialis)","human","English","cranial part of accessory nerve",,0 3302,"Nerve XI (spinalis)","human","English",,"spinal part of accessory nerve",0 294,"Nerve XII","human","English","hypoglossal nerve",,25 310,"Nervi craniales","human","Latin",,"cranial nerves",0 311,"Nervi encephalici","human","Latin",,"cranial nerves",0 293,"Nervi hypoglossalis","human","Latin","hypoglossal nerve",,0 313,"Nervi spinales","human","Latin",,"spinal nerves",1 3365,"nervous system","human","English",,"nervous system",159396 3237,"Nervus abducens","Macaca nemestrina","Latin","abducens nerve",,5 3236,"Nervus abducens","human","Latin","abducens nerve",,5 3286,"Nervus accessorius","human","Latin",,"accessory nerve",4 3306,"Nervus accessorius, pars spinalis","human","Latin",,"spinal part of accessory nerve",0 3248,"Nervus acusticus","Macaca fascicularis","Latin",,"cochlear nerve",0 3247,"Nervus cochlearis","human","Latin",,"cochlear nerve",0 2158,"Nervus facialis","Macaca fascicularis","Latin","facial nerve",,12 2157,"Nervus facialis","human","Latin","facial nerve",,12 3268,"Nervus facialis (Genu)","Macaca fascicularis","Latin","internal genu of facial nerve",,0 3273,"Nervus glossopharyngeus","Macaca mulatta","Latin","glossopharyngeal nerve",,4 3272,"Nervus glossopharyngeus","human","Latin","glossopharyngeal nerve",,4 292,"Nervus hypoglossus","Macaca fascicularis","Latin","hypoglossal nerve",,2 291,"Nervus hypoglossus","human","Latin","hypoglossal nerve",,2 3277,"Nervus intermedius","human","Latin","intermediate nerve",,30 6069,"Nervus Lancisii","human","Latin","medial longitudinal stria",,0 3260,"Nervus octavus","Macaca mulatta","Latin","vestibulocochlear nerve",,1 274,"Nervus oculomotorius","human","Latin","oculomotor nerve",,1 275,"Nervus oculomotorius","Macaca fascicularis","Latin","oculomotor nerve",,1 282,"Nervus oculomotorius, radix inferior","human","Latin",,"inferior division of oculomotor nerve",0 279,"Nervus oculomotorius, ramus inferior","human","Latin",,"inferior division of oculomotor nerve",0 3281,"Nervus olfactorius","human","Latin","olfactory nerve",,1 1470,"Nervus opticus","human","Latin","optic nerve",,9 3255,"Nervus statoacusticus","Macaca nemestrina","Latin","vestibulocochlear nerve",,1 5619,"Nervus terminalis","human","Latin","terminal nerve",,109 5620,"Nervus terminalis","human","Latin","terminal nerve",,109 3335,"Nervus trigemini radix motoria","Macaca fascicularis","Latin","motor root of trigeminal nerve",,0 3316,"Nervus trigeminus","human","Latin","trigeminal nerve",,8 3317,"Nervus trigeminus","Macaca fascicularis","Latin","trigeminal nerve",,8 3326,"Nervus trigeminus radix sensibilis","human","Latin",,"sensory root of trigeminal nerve",0 3334,"Nervus trigeminus, radix motoria","human","Latin","motor root of trigeminal nerve",,0 3336,"Nervus trigeminus, radix motorius","Macaca nemestrina","Latin","motor root of trigeminal nerve",,0 3325,"Nervus trigeminus, radix sensoria","human","Latin",,"sensory root of trigeminal nerve",0 316,"Nervus trochlearis","human","Latin","trochlear nerve",,1 317,"Nervus trochlearis","Macaca fascicularis","Latin","trochlear nerve",,1 3343,"Nervus vagus","human","Latin","vagus nerve",,30 3361,"Nervus vestibularis","Macaca fascicularis","Latin",,"vestibular nerve",0 3360,"Nervus vestibularis","human","Latin",,"vestibular nerve",0 3254,"Nervus vestibulocochlearis","human","Latin","vestibulocochlear nerve",,1 5622,"Nervus vomeronasalis","human","Latin",,"vomeronasal nerve",0 3401,"neural crest","human","English",,"neural crest",4495 3396,"neural fold","human","English",,"neural fold",161 3395,"neural groove","human","English",,"neural groove",74 2886,"neural lobe","human","English","NEUROHYPOPHYSIS",,551 3394,"neural plate","human","English",,"neural plate",735 3397,"neural tube","human","English",,"neural tube",6665 3369,"Neuraxis","human","English",,"central nervous system",788 3388,"Neurofibrae associationes","human","Latin",,"cerebral association fibers",0 3390,"Neurofibrae commissurales","human","Latin",,"cerebral commissural fibers",0 3392,"Neurofibrae projectiones","human","Latin",,"cerebral projection fibers",0 2884,"neurohypophysis","Macaca fascicularis","English","NEUROHYPOPHYSIS",,1273 2883,"neurohypophysis","human","English","NEUROHYPOPHYSIS",,1273 2885,"Neurohypophysis","human","Latin","NEUROHYPOPHYSIS",,1273 6746,"nigrostriatal fibers","human","English",,"nigrostriatal fibers",0 6747,"nigrostriatal tract","human","English",,"nigrostriatal fibers",57 6748,"nigrostriate bundle","human","English",,"nigrostriatal fibers",0 6750,"nigrotectal fibers","human","English",,"nigrotectal fibers",3 6751,"nigrotectal tract","human","English",,"nigrotectal fibers",3 6752,"nigrotegmental fibers","human","English",,"nigrotegmental fibers",0 6753,"nigrotegmental tract","human","English",,"nigrotegmental fibers",0 6754,"nigrothalamic fibers","human","English",,"nigrothalamic fibers",4 6755,"nigrothalamic tract","human","English",,"nigrothalamic fibers",0 3275,"ninth cranial nerve","human","English","glossopharyngeal nerve",,12 3353,"ninth cranial nerve fibers","human","English","glossopharyngeal nerve fibers",,0 3416,"nodule","Macaca nemestrina","English","nodulus",,8633 3417,"nodule of cerebellum","human","English","nodulus",,0 3410,"nodulus","human","English","nodulus",,193 3411,"nodulus","Macaca fascicularis","English","nodulus",,193 3413,"nodulus","rat","English","nodulus",,193 3412,"Nodulus","human","Latin","nodulus",,193 -1945031827,"nodulus vermis","human","Latin","nodulus",,0 3591,"nonmotor region of ventral nuclear group","human","English",,"nonmotor region of ventral nuclear group",0 3592,"nonmotor region of ventral nuclear group","Macaca","English",,"nonmotor region of ventral nuclear group",0 818,"nonprimary motor cortex","Macaca","English",,"nonprimary motor cortex",0 817,"nonprimary motor cortex","human","English",,"nonprimary motor cortex",0 3496,"nonspecific thalamic system","human","English","INTRALAMINAR NUCLEAR GROUP",,5 616,"NTS","human","Abbreviation","SOLITARY NUCLEUS",,0 3420,"Nuclei anteriores (thalami)","human","Latin","ANTERIOR NUCLEAR GROUP",,0 3456,"Nuclei arcuati","Macaca fascicularis","Latin","arcuate nucleus of medulla",,0 3469,"Nuclei basales","human","Latin","BASAL GANGLIA",,0 3533,"Nuclei brachii pontis","human","Latin","pontine nuclei",,91 2471,"Nuclei centrales myelencephali","Unspecified","Latin","CENTRAL MEDULLARY RETICULAR GROUP",,0 510,"Nuclei cerebellares","human","Latin","DEEP CEREBELLAR NUCLEI",,0 508,"Nuclei cerebellaris","human","Latin","DEEP CEREBELLAR NUCLEI",,0 507,"Nuclei cerebelli","human","Latin","DEEP CEREBELLAR NUCLEI",,1 572,"Nuclei cochleares","human","Latin","COCHLEAR NUCLEI",,2 2070037226,"Nuclei cochleares - not otherwise specified","Unspecified","Latin","COCHLEAR NUCLEI - not otherwise specified",,2 393,"Nuclei colliculi superioris","human","Latin",,"Nuclei colliculi superioris",0 4043,"Nuclei conterminalis","Macaca mulatta","Latin",,"Nuclei conterminalis",0 2841,"Nuclei habenulares","human","Latin","HABENULA",,0 4765,"Nuclei intralamellares thalami","human","Latin",,"Nucleus intralamellaris ventralis (Hassler)",0 3493,"Nuclei intralaminares (thalami)","human","Latin","INTRALAMINAR NUCLEAR GROUP",,0 3506,"Nuclei intralaminares rostrales","Unspecified","Latin","ROSTRAL INTRALAMINAR NUCLEI",,0 2456,"Nuclei laterales myelencephali","Unspecified","Latin","LATERAL MEDULLARY RETICULAR GROUP",,0 3509,"Nuclei laterales thalami","Unspecified","Latin","LATERAL NUCLEAR GROUP",,0 3516,"Nuclei lemnisci lateralis","Macaca fascicularis","Latin",,"lateral lemniscal nuclei",0 3515,"Nuclei lemnisci lateralis","human","Latin",,"lateral lemniscal nuclei",0 3518,"Nuclei lentiformes","human","Latin",,"lentiform nuclei",0 394,"Nuclei magnocellularis colliculi superioris","human","Latin",,"Nuclei colliculi superioris",0 4368,"Nuclei mediales (thalami)","human","Latin","MEDIAL DORSAL NUCLEUS",,0 3525,"Nuclei mediani (thalami)","human","Latin","MIDLINE NUCLEAR GROUP",,0 172,"Nuclei metathalami","human","Latin","METATHALAMUS",,0 7179,"Nuclei motorii lateralis","human","Latin",,"lateral nuclear group of anterior horn",0 7181,"Nuclei motorii medialis","human","Latin",,"medial nuclear group of anterior horn",0 6814,"nuclei of habenulopeduncular tract","human","English",,"nuclei of habenulopeduncular tract",0 3895,"nuclei of horizontal and vertical limbs of diagonal band","rat","English","nucleus of diagonal band",,0 5205,"nuclei of stria terminalis","Macaca fascicularis","English","nucleus of stria terminalis",,5 4232,"nuclei of trapezoid body","human","English","trapezoid nuclei",,0 4233,"nuclei of trapezoid body","rat","English","trapezoid nuclei",,0 4723,"Nuclei parafasciculares thalami","human","Latin","parafascicular nucleus",,0 2467,"Nuclei paramedianes myelencephali","Unspecified","Latin","PARAMEDIAN MEDULLARY RETICULAR GROUP",,0 4777,"Nuclei parataeniales thalami","human","Latin","paratenial nucleus",,0 4793,"Nuclei paraventriculares","human","Latin","paraventricular nucleus of hypothalamus",,0 3531,"Nuclei pontis","human","Latin","pontine nuclei",,1 4675,"Nuclei posteriores thalami","human","Latin","POSTERIOR NUCLEAR COMPLEX",,0 4887,"Nuclei premamillaris","human","Latin","premammillary nucleus",,0 408,"Nuclei pretectales","human","Latin","PRETECTAL REGION",,0 3546,"Nuclei pulvinares","human","Latin","PULVINAR",,0 2459,"Nuclei raphae","human","Latin",,"raphe nuclei",0 2464,"Nuclei raphe (myelencephali)","Unspecified","Latin","RAPHE NUCLEI OF MEDULLA",,0 2461,"Nuclei raphes","Macaca mulatta","Latin",,"raphe nuclei",0 3556,"Nuclei reticulares (thalami)","human","Latin","thalamic reticular nucleus",,0 1257,"Nuclei septales","Unspecified","Latin","SEPTAL NUCLEI",,0 3569,"Nuclei tegmentales","human","Latin",,"tegmental nuclei",0 3568,"Nuclei tegmenti","human","Latin",,"tegmental nuclei",0 6815,"Nuclei tractus habenulopeduncularis","human","Latin",,"nuclei of habenulopeduncular tract",0 2100270388,"Nuclei trigemini","human","Latin",,"trigeminal nuclei",0 3571,"Nuclei tuberales (hypothalami)","human","Latin",,"tuberal nuclei",0 3575,"Nuclei tuberales laterales","Unspecified","Latin","lateral tuberal nuclei",,0 5416,"Nuclei ventrales posteriores","human","Latin","VENTRAL POSTERIOR NUCLEUS",,0 3585,"Nuclei ventrales thalami","Unspecified","Latin","VENTRAL NUCLEAR GROUP",,0 567,"Nuclei vestibulares","human","Latin","VESTIBULAR NUCLEI",,2 4575,"Nucleus mesencephalicus nervi trigeminalis","human","Latin","mesencephalic nucleus of trigeminal nerve",,0 4301,"Nucleus (motorius) tecti cerebelli","human","Latin","fastigial nucleus",,0 3616,"Nucleus abducens","Macaca nemestrina","Latin","abducens nucleus",,14 3615,"Nucleus abducens","human","Latin","abducens nucleus",,14 4054,"Nucleus accessorius","human","Latin","nucleus of Darkschewitsch",,4 3621,"Nucleus accumbens","Macaca fascicularis","English","nucleus accumbens",,6918 3620,"Nucleus accumbens","human","Latin","nucleus accumbens",,6918 3624,"Nucleus accumbens septi","human","Latin","nucleus accumbens",,190 3625,"Nucleus accumbens septi","Macaca fascicularis","Latin","nucleus accumbens",,190 4018,"Nucleus acustici accessorici","Macaca mulatta","Latin","VENTRAL COCHLEAR NUCLEI",,0 4245,"Nucleus alaris (Oertel)","Macaca mulatta","Latin","dorsal motor nucleus of vagus nerve",,0 3628,"Nucleus alaris (Olszewski)","Macaca mulatta","Latin",,"Nucleus alaris (Olszewski)",0 3636,"nucleus ambiguus","human","English","nucleus ambiguus",,603 3637,"Nucleus ambiguus","human","Latin","nucleus ambiguus",,603 3638,"Nucleus ambiguus","Macaca fascicularis","Latin","nucleus ambiguus",,603 469041362,"nucleus amygdalae","human","Latin","AMYGDALA",,12 3650,"Nucleus amygdalae basalis","human","Latin","BASAL AMYGDALOID NUCLEUS",,1 3660,"Nucleus amygdalae basalis accessorius","human","Latin","accessory basal amygdaloid nucleus",,0 3674,"Nucleus amygdalae basalis accessorius, pars lateralis","human","Latin",,"magnocellular division of accessory basal nucleus",0 3677,"Nucleus amygdalae basalis accessorius, pars medialis","human","Latin",,"parvicellular division of accessory basal nucleus",0 3684,"Nucleus amygdalae basalis, pars lateralis","human","Latin","lateral part of basal amygdaloid nucleus",,0 3681,"Nucleus amygdalae basalis, pars lateralis","human","Latin","lateral part of basal amygdaloid nucleus",,0 3687,"Nucleus amygdalae basalis, pars medialis","human","Latin","medial part of basal amygdaloid nucleus",,0 3688,"Nucleus amygdalae basalis, pars medialis","human","Latin","medial part of basal amygdaloid nucleus",,0 3699,"Nucleus amygdalae centralis","human","Latin","central amygdaloid nucleus",,2 3724,"Nucleus amygdalae corticalis","human","Latin","cortical amygdaloid nucleus",,0 3736,"Nucleus amygdalae intercalatus","human","Latin","intercalated amygdaloid nuclei",,0 3744,"Nucleus amygdalae lateralis","human","Latin","lateral amygdaloid nucleus",,0 3753,"Nucleus amygdalae medialis","human","Latin","medial amygdaloid nucleus",,0 3652,"Nucleus amygdaloideus basalis","Macaca fuscata","Latin","BASAL AMYGDALOID NUCLEUS",,4 3690,"Nucleus amygdaloideus basalis pars lateralis parvocellularis","Macaca fuscata","Latin","medial part of basal amygdaloid nucleus",,0 3683,"Nucleus amygdaloideus basalis, pars lateralis magnocellularis","Macaca fuscata","Latin","lateral part of basal amygdaloid nucleus",,0 3664,"Nucleus amygdaloideus basalis, pars medialis","Macaca fuscata","Latin","accessory basal amygdaloid nucleus",,0 3653,"Nucleus amygdaloideus basolateralis","human","Latin","BASAL AMYGDALOID NUCLEUS",,0 3667,"Nucleus amygdaloideus basomedialis","human","Latin","accessory basal amygdaloid nucleus",,0 3702,"Nucleus amygdaloideus centralis","Macaca fuscata","Latin","central amygdaloid nucleus",,18 3701,"Nucleus amygdaloideus centralis","human","Latin","central amygdaloid nucleus",,18 3731,"Nucleus amygdaloideus corticalis","Macaca fuscata","Latin",,"Nucleus amygdaloideus corticalis",0 3733,"Nucleus amygdaloideus corticalis anterior","human","Latin",,"anterior cortical nucleus of amygdala",0 3730,"Nucleus amygdaloideus corticalis posterior","human","Latin","cortical amygdaloid nucleus",,0 3746,"Nucleus amygdaloideus lateralis","Macaca fuscata","Latin","lateral amygdaloid nucleus",,3 3756,"Nucleus amygdaloideus medialis","Macaca fuscata","Latin","medial amygdaloid nucleus",,5 3755,"Nucleus amygdaloideus medialis","human","Latin","medial amygdaloid nucleus",,5 3794,"Nucleus annularis","Macaca fascicularis","Latin",,"annular nucleus",6 3449,"Nucleus ansae lenticularis","human","Latin","nucleus of ansa lenticularis",,4 3450,"Nucleus ansae lenticularis","human","Latin","nucleus of ansa lenticularis",,4 3451,"Nucleus ansae lenticularis","human","Latin","nucleus of ansa lenticularis",,4 3822,"Nucleus anterior dorsalis","Macaca mulatta","Latin","anterodorsal nucleus",,2 3825,"Nucleus anterior dorsalis thalami","Macaca fascicularis","Latin","anterodorsal nucleus",,0 3800,"Nucleus anterior hypothalami","Macaca fascicularis","Latin","anterior nucleus of hypothalamus",,8 3840,"Nucleus anterior medialis","Macaca mulatta","Latin","anteromedial nucleus",,7 3843,"Nucleus anterior medialis thalami","Macaca fascicularis","Latin","anteromedial nucleus",,1 3866,"Nucleus anterior principalis (Hassler)","human","Latin","anteroventral nucleus",,0 3426,"Nucleus anterior thalami","human","Latin","ANTERIOR NUCLEAR GROUP",,2 3824,"Nucleus anterior thalami dorsalis","Macaca nemestrina","Latin","anterodorsal nucleus",,0 3842,"Nucleus anterior thalami medialis","Macaca nemestrina","Latin","anteromedial nucleus",,0 3856,"Nucleus anterior thalami ventralis","Macaca fascicularis","Latin","anteroventral nucleus",,0 3855,"Nucleus anterior thalami ventralis","Macaca nemestrina","Latin","anteroventral nucleus",,0 3854,"Nucleus anterior ventralis","Macaca mulatta","Latin","anteroventral nucleus",,4 3821,"Nucleus anterodorsalis","human","Latin","anterodorsal nucleus",,4 3823,"Nucleus anterodorsalis (Hassler)","human","Latin","anterodorsal nucleus",,0 3826,"Nucleus anterodorsalis of thalamus","human","Latin","anterodorsal nucleus",,0 3832,"Nucleus anterodorsalis thalami","human","Latin","anterodorsal nucleus",,0 3865,"Nucleus anteroinferior","human","Latin","anteroventral nucleus",,0 3629,"Nucleus anteroinferior (Hassler)","human","Latin",,"Nucleus alaris (Olszewski)",0 3838,"Nucleus anteromedialis","human","Latin","anteromedial nucleus",,4 3841,"Nucleus anteromedialis (Hassler)","human","Latin","anteromedial nucleus",,0 3839,"Nucleus anteromedialis thalami","human","Latin","anteromedial nucleus",,2 254634033,"Nucleus anteroreuniens (Hassler)","human","Latin",,,0 3833,"Nucleus anterosuperior","human","Latin","anterodorsal nucleus",,0 3853,"Nucleus anteroventralis","human","Latin","anteroventral nucleus",,2 3864,"Nucleus anteroventralis thalami","human","Latin","anteroventral nucleus",,0 3858,"Nucleus anteroventralis thalami","human","Latin","anteroventral nucleus",,0 3458,"Nucleus arciformis pyramidalis","human","Latin","arcuate nucleus of medulla",,0 4399,"Nucleus arcuatus (hypothalamus)","human","Latin","arcuate nucleus of hypothalamus",,0 3455,"Nucleus arcuatus myelencephali","human","Latin","arcuate nucleus of medulla",,0 3457,"Nucleus arcuatus pyramidalis","human","Latin","arcuate nucleus of medulla",,0 5491,"Nucleus arcuatus thalami","human","Latin","VENTRAL POSTEROMEDIAL NUCLEUS",,0 1410,"Nucleus area H","human","Latin","nucleus of field H",,0 3871,"Nucleus area H1","human","Latin",,"Nucleus area H1",0 3872,"Nucleus area H2","human","Latin",,"Nucleus area H2",0 4945,"Nucleus area pretectalis","Unspecified","Latin","nucleus of pretectal area",,4 3908,"Nucleus basalis","Macaca fascicularis","Latin","basal nucleus",,1394 3911,"Nucleus basalis (Meynert)","human","Latin","basal nucleus",,20 3661,"Nucleus basalis accessorius amygdalae","Macaca fascicularis","Latin","accessory basal amygdaloid nucleus",,0 3675,"Nucleus basalis accessorius lateralis amygdalae","Macaca fascicularis","Latin",,"magnocellular division of accessory basal nucleus",0 3678,"Nucleus basalis accessorius medialis amygdalae","Macaca fascicularis","Latin",,"parvicellular division of accessory basal nucleus",0 3651,"Nucleus basalis amygdalae","Macaca fascicularis","Latin","BASAL AMYGDALOID NUCLEUS",,0 3682,"Nucleus basalis lateralis amygdalae","Macaca fascicularis","Latin","lateral part of basal amygdaloid nucleus",,3 3689,"Nucleus basalis medialis amygdalae","Macaca fascicularis","Latin","medial part of basal amygdaloid nucleus",,0 5579,"Nucleus Bechterew","Macaca mulatta","Latin","superior vestibular nucleus",,1 1416,"Nucleus campi Foreli","human","Latin","nucleus of field H",,5 1418,"Nucleus campus Foreli","human","Latin","nucleus of field H",,0 4604,"Nucleus caudalis centralis oculomotorii","Macaca mulatta","Latin","caudal central oculomotor nucleus",,0 5183,"Nucleus caudalis tractus spinalis nervi trigemini","Macaca mulatta","Latin","caudal part of spinal trigeminal nucleus",,0 115,"Nucleus caudatus","Macaca fascicularis","Latin","CAUDATE NUCLEUS",,279 3924,"Nucleus centralis (colliculi inferioris)","Unspecified","Latin","central nucleus of inferior colliculus",,0 3700,"Nucleus centralis amygdalae","Macaca fascicularis","Latin","central amygdaloid nucleus",,3 3992,"Nucleus centralis centralis","human","Latin","centromedian nucleus",,1 5095,"Nucleus centralis densocellularis","Macaca mulatta","Latin",,"Nucleus centralis densocellularis",0 3970,"Nucleus centralis dorsalis thalami","Macaca fuscata","Latin","central dorsal nucleus",,0 4388,"Nucleus centralis inferior","human","Latin","inferior central nucleus",,1 5098,"Nucleus centralis inferior thalami","Macaca mulatta","Latin",,"Nucleus centralis inferior thalami",0 5099,"Nucleus centralis inferior thalami","Macaca fascicularis","Latin",,"Nucleus centralis inferior thalami",0 3934,"Nucleus centralis intermedialis","Macaca mulatta","Latin",,"Nucleus centralis intermedialis",0 3935,"Nucleus centralis intermedius thalami","Macaca fascicularis","Latin",,"Nucleus centralis intermedialis",0 3957,"Nucleus centralis lateralis inferior thalami","Macaca fuscata","Latin",,"Nucleus centralis lateralis inferior thalami",0 3953,"Nucleus centralis lateralis of thalamus","human","Latin","central lateral nucleus",,2 4716,"Nucleus centralis lateralis superior (Kusama)","Macaca fuscata","Latin","paracentral nucleus",,0 3950,"Nucleus centralis lateralis thalami","Macaca fascicularis","Latin","central lateral nucleus",,0 5094,"Nucleus centralis latocellularis","Macaca mulatta","Latin",,"Nucleus centralis latocellularis",0 3960,"Nucleus centralis medialis","human","Latin","central medial nucleus",,21 3961,"Nucleus centralis medialis thalami","Macaca fascicularis","Latin","central medial nucleus",,2 5075,"Nucleus centralis medullae oblongatae","Macaca mulatta","Latin","ventral reticular nucleus",,2 4607,"Nucleus centralis nervi oculomotorii","Macaca fascicularis","Latin","caudal central oculomotor nucleus",,0 3938,"Nucleus centralis superior","human","Latin","superior central nucleus",,53 3939,"Nucleus centralis superior","Macaca fascicularis","Latin","superior central nucleus",,53 3971,"Nucleus centralis superior lateralis","Macaca mulatta","Latin","central dorsal nucleus",,0 3972,"Nucleus centralis superior lateralis thalami","Macaca fascicularis","Latin","central dorsal nucleus",,0 -255588521,"Nucleus centralis superior thalami","Macaca mulatta","Latin",,"Nucleus centralis superior thalami",0 -741510068,"Nucleus centralis superior thalami","Macaca fascicularis","Latin",,"Nucleus centralis superior thalami",0 3997,"Nucleus centralis thalami (Hassler)","human","Latin","centromedian nucleus",,0 3982,"Nucleus centralis thalami, magnocellularis (Hassler)","human","Latin",,"Nucleus centralis thalami, magnocellularis (Hassler)",0 3981,"Nucleus centralis thalami, parvocellularis (Hassler)","human","Latin",,"Nucleus centralis thalami, parvocellularis (Hassler)",0 3989,"Nucleus centri mediani thalami","human","Latin","centromedian nucleus",,0 3985,"Nucleus centromedianus","human","Latin","centromedian nucleus",,3 3995,"Nucleus centromedianus thalami","human","Latin","centromedian nucleus",,0 3986,"Nucleus centrum medianum","Macaca mulatta","Latin","centromedian nucleus",,27 3973,"Nucleus circularis","human","Latin","central dorsal nucleus",,34 4017,"Nucleus cochlearis anterior","human","Latin","VENTRAL COCHLEAR NUCLEI",,0 3999,"Nucleus cochlearis anteroventralis","Unspecified","Latin","anteroventral cochlear nucleus",,0 4007,"Nucleus cochlearis dorsalis","human","Latin","dorsal cochlear nucleus",,4 4008,"Nucleus cochlearis dorsalis","Macaca fascicularis","Latin","dorsal cochlear nucleus",,4 4009,"Nucleus cochlearis posterior","human","Latin","dorsal cochlear nucleus",,0 4002,"Nucleus cochlearis posteroventralis","Unspecified","Latin","posteroventral cochlear nucleus",,0 4016,"Nucleus cochlearis ventralis","Macaca fascicularis","Latin","VENTRAL COCHLEAR NUCLEI",,0 4015,"Nucleus cochlearis ventralis","human","Latin","VENTRAL COCHLEAR NUCLEI",,0 375,"Nucleus colliculi inferioris","human","Latin",,"Nucleus colliculi inferioris",0 376,"Nucleus colliculi inferioris","Macaca fascicularis","Latin",,"Nucleus colliculi inferioris",0 377,"Nucleus colliculus inferioris","Macaca mulatta","Latin",,"Nucleus colliculi inferioris",0 397,"Nucleus colliculus superioris","Macaca mulatta","Latin",,"Nuclei colliculi superioris",0 4407,"Nucleus commissura interanterodorsalis","human","Latin",,"Nucleus interanterodorsalis",0 4046,"Nucleus commissura posterior","Unspecified","Latin","nucleus of posterior commissure",,1 4021,"Nucleus commissurae anterior","human","Latin","nucleus of anterior commissure",,0 4022,"Nucleus commissurae anterioris","Macaca fascicularis","Latin","nucleus of anterior commissure",,2 4057,"Nucleus commissurae posterioris (Riley)","human","Latin","nucleus of Darkschewitsch",,0 3918,"Nucleus commissurae supraopticae dorsalis (Meynert)","human","Latin",,"Nucleus subputaminalis",0 4030,"Nucleus commissuralis","human","Latin","commissural nucleus of vagus nerve",,45 4031,"Nucleus commissuralis nervi vagi","human","Latin","commissural nucleus of vagus nerve",,0 970123475,"nucleus commissuralis posterioris","human","Latin","nucleus of posterior commissure",,0 3966,"Nucleus commissuralis thalami","human","Latin",,"commissural nucleus of thalamus",0 3795,"Nucleus compactus interfascicularis","human","Latin",,"annular nucleus",0 4263,"Nucleus compactus suprafascicularis","Macaca mulatta","Latin","dorsal tegmental nucleus",,0 4044,"Nucleus conterminalis","human","Latin",,"Nuclei conterminalis",0 7203,"Nucleus cornucommissuralis anterior","human","Latin",,"anterior cornucommissural nucleus",0 7205,"Nucleus cornucommissuralis posterior","human","Latin",,"posterior cornucommissural nucleus",0 178,"Nucleus corporis geniculati lateralis","Macaca mulatta","Latin","LATERAL GENICULATE BODY",,1 4091,"Nucleus corporis geniculati lateralis, pars dorsalis","human","Latin","dorsal nucleus of lateral geniculate body",,0 4100,"Nucleus corporis geniculati lateralis, pars ventralis","human","Latin","ventral nucleus of lateral geniculate body",,0 193,"Nucleus corporis geniculati medialis","Macaca mulatta","Latin","MEDIAL GENICULATE BODY",,1 4122,"Nucleus corporis geniculati medialis, pars dorsalis","human","Latin","dorsal nucleus of medial geniculate body",,0 4128,"Nucleus corporis geniculati medialis, pars magnocellularis","Unspecified","Latin","magnocellular nucleus of medial geniculate body",,0 4138,"Nucleus corporis geniculati medialis, pars ventralis","human","Latin","ventral nucleus of medial geniculate body",,0 4148,"Nucleus corporis mamillaris lateralis","human","Latin","lateral mammillary nucleus",,0 4161,"Nucleus corporis mamillaris medialis","human","Latin","MEDIAL MAMMILLARY NUCLEUS",,0 4175,"Nucleus corporis mamillaris medialis, pars lateralis","Unspecified","Latin","lateral part of medial mammillary nucleus",,0 4167,"Nucleus corporis mamillaris medialis, pars medialis","Unspecified","Latin","medial part of medial mammillary nucleus",,0 395,"Nucleus corporis quadrigemini anterioris","human","Latin",,"Nuclei colliculi superioris",0 378,"Nucleus corporis quadrigemini posterioris","human","Latin",,"Nucleus colliculi inferioris",0 4230,"Nucleus corporis trapezoidei","Macaca mulatta","Latin","trapezoid nuclei",,2 5342,"Nucleus corporis trapezoidei anterior","human","Latin",,"Nucleus ventralis corporis trapezoidei",0 5370,"Nucleus corporis trapezoidei anterior","human","Latin",,"Nucleus ventralis corporis trapezoidei",0 4228,"Nucleus corporis trapezoidei posterior","human","Latin",,"Nucleus dorsalis corporis trapezoidei",0 3727,"Nucleus corticalis amygdalae","Macaca fascicularis","Latin","cortical amygdaloid nucleus",,0 3976,"Nucleus cucullaris (Hassler)","human","Latin",,"dorsomedial central lateral nucleus",0 3977,"nucleus cucullaris of thalamus","human","English",,"dorsomedial central lateral nucleus",0 3978,"Nucleus cucullaris thalami","human","Latin",,"dorsomedial central lateral nucleus",0 4200,"Nucleus cuneatis externus","human","Latin","accessory cuneate nucleus",,0 4187,"Nucleus cuneatus","human","Latin","cuneate nucleus",,56 4188,"Nucleus cuneatus","Macaca fascicularis","Latin","cuneate nucleus",,56 4194,"Nucleus cuneatus accessorius","human","Latin","accessory cuneate nucleus",,1 4195,"Nucleus cuneatus accessorius","Macaca nemestrina","Latin","accessory cuneate nucleus",,1 4196,"Nucleus cuneatus lateralis","Macaca fascicularis","Latin","accessory cuneate nucleus",,2 4189,"Nucleus cuneatus medialis","Macaca mulatta","Latin","cuneate nucleus",,1 4218,"Nucleus cuneiformis","Macaca mulatta","Latin","cuneiform nucleus",,67 4052,"Nucleus Darkschewitsch","Macaca fascicularis","Latin","nucleus of Darkschewitsch",,9 4051,"Nucleus Darkschewitsch","human","Latin","nucleus of Darkschewitsch",,9 4053,"Nucleus Darkschewitschi","marmoset","Latin","nucleus of Darkschewitsch",,0 625,"Nucleus dentatus","human","Latin","DENTATE NUCLEUS",,33 629,"Nucleus dentatus cerebelli","human","Latin","DENTATE NUCLEUS",,2 630,"Nucleus dentatus cerebelli","Macaca fascicularis","Latin","DENTATE NUCLEUS",,2 5343,"Nucleus dorsalis (Hassler)","human","Latin",,"Nucleus dorsooralis (Hassler)",0 4227,"Nucleus dorsalis corporis trapezoidei","human","Latin",,"Nucleus dorsalis corporis trapezoidei",0 4242,"Nucleus dorsalis motorius nervi vagi","human","Latin","dorsal motor nucleus of vagus nerve",,3 4243,"Nucleus dorsalis motorius nervi vagi","Macaca mulatta","Latin","dorsal motor nucleus of vagus nerve",,3 4239,"Nucleus dorsalis nervi vagi","Macaca mulatta","Latin","dorsal motor nucleus of vagus nerve",,9 4238,"Nucleus dorsalis nervi vagi","human","Latin","dorsal motor nucleus of vagus nerve",,9 4250,"Nucleus dorsalis of Clarke","human","Latin",,"dorsal nucleus of Clarke",0 5512,"Nucleus dorsalis raphae","Macaca fascicularis","Latin",,"Nucleus dorsalis raphae",0 4738,"Nucleus dorsalis raphes","Macaca fuscata","Latin","dorsal raphe nucleus",,1 5288,"Nucleus dorsalis septi","Macaca fascicularis","Latin","dorsal septal nucleus",,0 4447,"Nucleus dorsalis superficialis (Hassler)","human","Latin","lateral dorsal nucleus",,0 4257,"Nucleus dorsalis tegmenti","human","Latin","dorsal tegmental nucleus",,3 4258,"Nucleus dorsalis tegmenti (Gudden)","Macaca fascicularis","Latin","dorsal tegmental nucleus",,0 4464,"Nucleus dorso-caudalis","human","Latin","lateral posterior nucleus",,0 4463,"Nucleus dorsocaudalis (Hassler)","human","Latin","lateral posterior nucleus",,0 5355,"Nucleus dorsointermedius externus (Hassler)","human","Latin",,"Nucleus dorsointermedius externus (Hassler)",0 5402,"Nucleus dorsointermedius externus magnocellularis (Hassler)","human","Latin","pars postrema of ventral lateral nucleus",,0 5356,"Nucleus dorsointermedius internus (Hassler)","human","Latin",,"Nucleus dorsointermedius internus (Hassler)",0 5357,"Nucleus dorsointermedius superior (Hassler)","human","Latin",,"Nucleus dorsointermedius superior (Hassler)",0 4384,"Nucleus dorsomedialis hypothalami","Macaca fascicularis","Latin","dorsomedial nucleus of hypothalamus",,11 4364,"Nucleus dorsomedialis thalami","human","Latin","MEDIAL DORSAL NUCLEUS",,9 5377,"Nucleus dorsooralis (Van Buren)","human","Latin","caudal part of ventral lateral nucleus",,0 5347,"Nucleus dorsooralis externus (Hassler)","human","Latin",,"Nucleus dorsooralis externus (Hassler)",0 5346,"Nucleus dorsooralis internus (Hassler)","human","Latin",,"Nucleus dorsooralis internus (Hassler)",0 5111,"Nucleus Edinger Westphal","Macaca mulatta","Latin","parvocellular oculomotor nucleus",,10 4270,"Nucleus emboliformis","human","Latin","emboliform nucleus",,0 4275,"Nucleus emboliformis cerebelli","Macaca fascicularis","Latin","emboliform nucleus",,0 4274,"Nucleus emboliformis cerebelli","human","Latin","emboliform nucleus",,0 4512,"Nucleus eminentiae teretis","Macaca mulatta","Latin","nucleus of medial eminence",,1 4511,"Nucleus eminentiae teretis","human","Latin","nucleus of medial eminence",,1 3466,"Nucleus endopeduncularis","human","Latin",,"entopeduncular nucleus",0 5086,"Nucleus endymalis (Hassler)","human","Latin","reuniens nucleus",,0 3465,"Nucleus entopeduncularis","Unspecified","Latin",,"entopeduncular nucleus",38 3464,"Nucleus entopeduncularis","human","Latin",,"entopeduncular nucleus",38 3463,"Nucleus entopeduncularis","human","Latin",,"entopeduncular nucleus",38 4277,"Nucleus externus (colliculi inferioris)","Unspecified","Latin","external nucleus of inferior colliculus",,0 4285,"Nucleus facialis","human","Latin","facial motor nucleus",,15 4286,"Nucleus facialis","Macaca nemestrina","Latin","facial motor nucleus",,15 3893,"Nucleus fasciculi diagonalis Brocae","Macaca fascicularis","Latin","nucleus of diagonal band",,1 4056,"Nucleus fasciculi longitudinalis medialis","human","Latin","nucleus of Darkschewitsch",,5 614,"Nucleus fasciculus solitarius","human","Latin","SOLITARY NUCLEUS",,2 4297,"Nucleus fastigiatus","human","Latin","fastigial nucleus",,0 4295,"Nucleus fastigii","human","Latin","fastigial nucleus",,15 4299,"Nucleus fastigii cerebelli","Macaca fascicularis","Latin","fastigial nucleus",,0 4298,"Nucleus fastigii cerebelli","human","Latin","fastigial nucleus",,0 4296,"Nucleus fastigius cerebelli","Macaca nemestrina","Latin","fastigial nucleus",,0 4797,"Nucleus filiformis","Macaca mulatta","Latin","paraventricular nucleus of hypothalamus",,1 4199,"Nucleus funiculi cuneatus externus","Macaca mulatta","Latin","accessory cuneate nucleus",,0 3943,"Nucleus fusiformis raphes","human","Latin","superior central nucleus",,0 184,"Nucleus geniculatus lateralis","Macaca","Latin","LATERAL GENICULATE BODY",,36 183,"Nucleus geniculatus lateralis","human","Latin","LATERAL GENICULATE BODY",,36 181,"Nucleus geniculatus lateralis","human","Latin","LATERAL GENICULATE BODY",,36 4112,"Nucleus geniculatus lateralis ventralis, pars caudalis","Macaca mulatta","Latin",,"Nucleus geniculatus lateralis ventralis, pars caudalis",0 4092,"Nucleus geniculatus lateralis dorsalis","Macaca mulatta","Latin","dorsal nucleus of lateral geniculate body",,5 4096,"Nucleus geniculatus lateralis pars dorsalis","human","Latin","dorsal nucleus of lateral geniculate body",,5 4104,"Nucleus geniculatus lateralis pars ventralis","human","Latin","ventral nucleus of lateral geniculate body",,11 4114,"Nucleus geniculatus lateralis ventralis, pars oralis","Macaca mulatta","Latin",,"Nucleus geniculatus lateralis ventralis, pars oralis",0 192,"Nucleus geniculatus medialis","Macaca","Latin","MEDIAL GENICULATE BODY",,1 191,"Nucleus geniculatus medialis","human","Latin","MEDIAL GENICULATE BODY",,1 190,"Nucleus geniculatus medialis","human","Latin","MEDIAL GENICULATE BODY",,1 4116,"Nucleus geniculatus medialis (Hassler)","human","Latin",,"Nucleus geniculatus medialis (Hassler)",0 4141,"Nucleus geniculatus medialis fasciculosus (Hassler)","human","Latin","ventral nucleus of medial geniculate body",,0 4124,"Nucleus geniculatus medialis fibrosus (Hassler)","human","Latin","dorsal nucleus of medial geniculate body",,0 4117,"Nucleus geniculatus medialis limitans (Hassler)","human","Latin",,"Nucleus geniculatus medialis limitans (Hassler)",0 4135,"Nucleus geniculatus medialis magnocellularis (Hassler)","human","Latin","magnocellular nucleus of medial geniculate body",,0 4123,"Nucleus geniculatus medialis pars dorsalis","human","Latin","dorsal nucleus of medial geniculate body",,0 4143,"Nucleus geniculatus medialis pars ventralis","human","Latin","ventral nucleus of medial geniculate body",,0 4130,"Nucleus geniculatus medialis, pars magnocellularis","Macaca mulatta","Latin","magnocellular nucleus of medial geniculate body",,0 4120,"Nucleus geniculatus medialis, pars parvocellularis","human","Latin",,"Nucleus geniculatus medialis, pars parvocellularis",0 4119,"Nucleus geniculatus medialis, pars parvocellularis","Macaca mulatta","Latin",,"Nucleus geniculatus medialis, pars parvocellularis",0 4999,"nucleus gigantocellularis","Macaca mulatta","English","gigantocellular nucleus",,69 4305,"Nucleus globosus","human","Latin","globose nucleus",,0 4306,"Nucleus globosus cerebelli","Macaca fascicularis","Latin","globose nucleus",,0 4318,"Nucleus gracilis","Macaca fascicularis","Latin","gracile nucleus",,103 4317,"Nucleus gracilis","human","Latin","gracile nucleus",,103 1839228484,"Nucleus habenulae","human","Latin","HABENULA",,0 4328,"Nucleus habenulae lateralis","human","Latin","lateral habenular nucleus",,4 4359,"Nucleus habenulae medialis","human","Latin","medial habenular nucleus",,6 1024892838,"Nucleus habenularis","human","Latin","HABENULA",,0 4326,"Nucleus habenularis lateralis","human","Latin","lateral habenular nucleus",,5 4327,"Nucleus habenularis lateralis","Macaca nemestrina","Latin","lateral habenular nucleus",,5 4329,"Nucleus habenularis lateralis epithalami","Macaca fascicularis","Latin","lateral habenular nucleus",,0 4333,"Nucleus habenularis lateralis interstitialis (Hassler)","human","Latin",,"Nucleus habenularis lateralis interstitialis (Hassler)",0 4331,"Nucleus habenularis lateralis magnocellularis (Hassler)","human","Latin",,"Nucleus habenularis lateralis magnocellularis (Hassler)",0 4334,"Nucleus habenularis lateralis mixtocellularis (Hassler)","human","Latin",,"Nucleus habenularis lateralis mixtocellularis (Hassler)",0 4332,"Nucleus habenularis lateralis, pars magnocellularis","Macaca mulatta","Latin",,"Nucleus habenularis lateralis magnocellularis (Hassler)",0 4337,"Nucleus habenularis lateralis, pars parvocellularis","Macaca mulatta","Latin",,"Nucleus habenularis lateralis, pars parvocellularis",0 4354,"Nucleus habenularis medialis","human","Latin","medial habenular nucleus",,4 4355,"Nucleus habenularis medialis","Macaca mulatta","Latin","medial habenular nucleus",,4 4358,"Nucleus habenularis medialis (Hassler)","human","Latin","medial habenular nucleus",,0 4356,"Nucleus habenularis medialis epithalami","Macaca fascicularis","Latin","medial habenular nucleus",,0 4588,"Nucleus hypoglossalis","human","Latin","hypoglossal nucleus",,0 4589,"Nucleus hypoglossalis","Macaca nemestrina","Latin","hypoglossal nucleus",,0 3919,"Nucleus hypolenticularis","human","Latin",,"Nucleus subputaminalis",0 4798,"Nucleus hypothalami filiformis","Macaca mulatta","Latin","paraventricular nucleus of hypothalamus",,0 4791,"Nucleus hypothalami paraventricularis","Macaca nemestrina","Latin","paraventricular nucleus of hypothalamus",,0 3799,"Nucleus hypothalamicus anterior","human","Latin","anterior nucleus of hypothalamus",,6 5932,"Nucleus hypothalamicus dorsalis","human","Latin","dorsal hypothalamic area",,0 4383,"Nucleus hypothalamicus dorsomedialis","human","Latin","dorsomedial nucleus of hypothalamus",,1 1172,"Nucleus hypothalamicus lateralis","human","Latin","lateral hypothalamic nucleus",,4 4875,"Nucleus hypothalamicus posterior","human","Latin","posterior nucleus of hypothalamus",,9 5540,"Nucleus hypothalamicus ventromedialis","human","Latin","ventromedial nucleus of hypothalamus",,3 -1520970831,"Nucleus inferior nervi trigemini","human","Latin",,"SPINAL TRIGEMINAL NUCLEUS",0 4396,"Nucleus infundibularis","human","Latin","arcuate nucleus of hypothalamus",,39 4398,"Nucleus infundibularis hypothalami","human","Latin","arcuate nucleus of hypothalamus",,0 4397,"Nucleus infundibularis hypothalami","Macaca fascicularis","Latin","arcuate nucleus of hypothalamus",,0 3639,"Nucleus innominatus","Macaca mulatta","Latin","nucleus ambiguus",,0 4406,"Nucleus interanterodorsalis","human","Latin",,"Nucleus interanterodorsalis",0 5096,"Nucleus interanteromedialis","human","Latin",,"Nucleus centralis densocellularis",0 5097,"Nucleus interanteromedialis","Macaca fuscata","Latin",,"Nucleus centralis densocellularis",0 4408,"Nucleus interanteroventralis","human","Latin",,"Nucleus interanteroventralis",0 3630,"nucleus intercalatus","human","English","nucleus intercalatus",,87 3632,"Nucleus intercalatus","Macaca fascicularis","Latin","nucleus intercalatus",,87 3631,"Nucleus intercalatus","human","Latin","nucleus intercalatus",,87 4208,"Nucleus intercalatus (Le Gros Clark)","human","Latin",,"Nucleus intercalatus (Le Gros Clark)",0 4209,"Nucleus intercalatus (Le Gros Clark)","human","Latin",,"Nucleus intercalatus (Le Gros Clark)",0 4211,"Nucleus intercalatus (Le Gros Clark)","human","Latin",,"Nucleus intercalatus (Le Gros Clark)",0 4210,"Nucleus intercalatus (Le Gros Clark)","human","Latin",,"Nucleus intercalatus (Le Gros Clark)",0 4213,"Nucleus intercalatus (Malone)","human","Latin",,"Nucleus intercalatus (Malone)",0 4212,"Nucleus intercalatus (Malone)","human","Latin",,"Nucleus intercalatus (Malone)",0 4151,"Nucleus intercalatus (Olszewski)","Macaca mulatta","Latin","lateral mammillary nucleus",,0 4214,"Nucleus intercalatus (Rose)","human","Latin",,"Nucleus intercalatus (Rose)",0 3737,"Nucleus intercalatus amygdalae","Macaca fascicularis","Latin","intercalated amygdaloid nuclei",,0 4183,"Nucleus intercalatus corporis mammillaris","human","Latin","lateral part of medial mammillary nucleus",,0 3633,"nucleus intercalatus of medulla","human","English","nucleus intercalatus",,0 4591,"Nucleus interfascicularis hypoglossi","human","Latin",,"Nucleus interfascicularis hypoglossi",0 4178,"Nucleus intermedius corpus mamillaris","Macaca fascicularis","Latin","lateral part of medial mammillary nucleus",,0 4931,"Nucleus intermedius hypothalami","human","Latin",,"sexual dimorphic nucleus",0 4413,"Nucleus interpeduncularis","Macaca fascicularis","Latin","interpeduncular nucleus",,59 4412,"Nucleus interpeduncularis","human","Latin","interpeduncular nucleus",,59 4414,"Nucleus interpeduncularis medialis","Macaca mulatta","Latin","interpeduncular nucleus",,1 1439009116,"Nucleus interpolaris tractus spinalis nervi trigemini","Macaca mulatta","Latin","interpolar part of spinal trigeminal nucleus",,0 4313,"Nucleus interpositus","human","Latin",,"interposed nucleus",113 4273,"Nucleus interpositus anterior cerebelli","Macaca fuscata","Latin","emboliform nucleus",,0 4309,"Nucleus interpositus posterior cerebelli","Macaca fuscata","Latin","globose nucleus",,0 4310,"Nucleus interpositus posterior cerebelli","human","Latin","globose nucleus",,0 4419,"Nucleus interstitialis Cajal","human","Latin","interstitial nucleus of Cajal",,2 4420,"Nucleus interstitialis Cajal","Macaca fascicularis","Latin","interstitial nucleus of Cajal",,2 4023,"Nucleus interstitialis commissurae anterior","human","Latin","nucleus of anterior commissure",,0 4047,"Nucleus interstitialis of posterior commissure","Macaca mulatta","Latin","nucleus of posterior commissure",,0 4423,"Nucleus interstitialis rostralis","human","Latin","rostral interstitial nucleus of medial longitudinal fasciculus",,0 5203,"Nucleus interstitialis striae terminalis","human","Latin","nucleus of stria terminalis",,23 5215,"nucleus intracuneiformis","human","English",,"nucleus intracuneiformis",0 5216,"Nucleus intracuneiformis","human","Latin",,"nucleus intracuneiformis",0 4762,"Nucleus intralamellaris (Hassler)","human","Latin",,"Nucleus intralamellaris (Hassler)",0 4767,"Nucleus intralamellaris caudalis (Hassler)","human","Latin",,"Nucleus intralamellaris caudalis (Hassler)",0 4766,"Nucleus intralamellaris interpolaris (Hassler)","human","Latin",,"Nucleus intralamellaris interpolaris (Hassler)",0 4768,"Nucleus intralamellaris oralis (Hassler)","human","Latin",,"Nucleus intralamellaris oralis (Hassler)",0 4764,"Nucleus intralamellaris ventralis (Hassler)","human","Latin",,"Nucleus intralamellaris ventralis (Hassler)",0 4630,"Nucleus juxtaolivaris","human","Latin","medial accessory inferior olivary nucleus",,0 4759,"Nucleus juxtasolitarius","human","Latin",,"Nucleus parasolitarius",0 4434,"Nucleus lacrimalis","human","Latin",,"lacrimal nucleus",0 3745,"Nucleus lateralis amygdalae","Macaca fascicularis","Latin","lateral amygdaloid nucleus",,1 4504,"Nucleus lateralis anuli aquaeducti","Macaca fascicularis","Latin",,"Nucleus lateralis anuli aqueductus",0 4503,"Nucleus lateralis anuli aqueductus","human","Latin",,"Nucleus lateralis anuli aqueductus",0 628,"Nucleus lateralis cerebelli","Macaca fuscata","Latin","DENTATE NUCLEUS",,0 4150,"Nucleus lateralis corpus mamillaris","Macaca fascicularis","Latin","lateral mammillary nucleus",,0 4438,"Nucleus lateralis dorsalis","Macaca mulatta","Latin","lateral dorsal nucleus",,5 4437,"Nucleus lateralis dorsalis","human","Latin","lateral dorsal nucleus",,5 4443,"Nucleus lateralis dorsalis of thalamus","human","Latin","lateral dorsal nucleus",,0 4440,"Nucleus lateralis dorsalis thalami","human","Latin","lateral dorsal nucleus",,0 4441,"Nucleus lateralis dorsalis thalami","Macaca fascicularis","Latin","lateral dorsal nucleus",,0 1346820870,"nucleus lateralis globi pallidi","human","Latin","lateral globus pallidus",,0 5469,"Nucleus lateralis intermedius lateralis","Macaca","Latin","oral part of ventral posterolateral nucleus",,0 5380,"Nucleus lateralis intermedius mediodorsalis situs dorsalis","Macaca","Latin","caudal part of ventral lateral nucleus",,0 5403,"Nucleus lateralis intermedius mediodorsalis situs postremus","Macaca","Latin","pars postrema of ventral lateral nucleus",,0 1297,"Nucleus lateralis intermedius mediodorsalis situs ventralis medialis","Macaca mulatta","Latin","area X",,0 5006,"Nucleus lateralis medullae oblongatae","Macaca mulatta","Latin","lateral reticular nucleus",,0 5054,"Nucleus lateralis mesencephali","human","Latin",,"Nucleus lateralis mesencephali",0 5059,"Nucleus lateralis mesencephali (Marburg)","human","Latin",,"Nucleus lateralis mesencephali",0 5350,"Nucleus lateralis oralis situs dorsalis","Macaca","Latin",,"Nucleus lateropolaris (Hassler)",0 4082,"Nucleus lateralis oralis situs principalis","Macaca","Latin","oral part of ventral lateral nucleus",,0 5055,"Nucleus lateralis pararubralis","human","Latin",,"Nucleus lateralis mesencephali",0 3445,"Nucleus lateralis pars caudalis of midbrain","human","Latin",,"Nucleus lateralis pars caudalis of midbrain",0 4453,"Nucleus lateralis posterior","human","Latin","lateral posterior nucleus",,43 4454,"Nucleus lateralis posterior","Macaca mulatta","Latin","lateral posterior nucleus",,43 4456,"Nucleus lateralis posterior thalami","Macaca fascicularis","Latin","lateral posterior nucleus",,3 4455,"Nucleus lateralis posterior thalami","human","Latin","lateral posterior nucleus",,3 5345,"Nucleus lateralis rostralis situs polaris","Macaca","Latin",,"Nucleus dorsooralis (Hassler)",0 4472,"Nucleus lateralis septi","Macaca fascicularis","Latin","lateral septal nucleus",,5 3512,"Nucleus lateralis thalami","human","Latin","LATERAL NUCLEAR GROUP",,10 4439,"Nucleus lateralis thalami dorsalis","Macaca nemestrina","Latin","lateral dorsal nucleus",,0 4457,"Nucleus lateralis thalami posterior","Macaca nemestrina","Latin","lateral posterior nucleus",,0 3815,"Nucleus lateropolaris","human","Latin","VENTRAL ANTERIOR NUCLEUS",,0 5348,"Nucleus lateropolaris (Hassler)","human","Latin",,"Nucleus lateropolaris (Hassler)",0 5325,"Nucleus lateropolaris (magnocellularis)","human","Latin","magnocellular part of ventral anterior nucleus",,0 5323,"Nucleus lateropolaris magnocellularis (Hassler)","human","Latin","magnocellular part of ventral anterior nucleus",,0 4480,"Nucleus lemnisci lateralis dorsalis","Macaca mulatta","Latin","dorsal nucleus of lateral lemniscus",,0 4479,"Nucleus lemnisci lateralis pars dorsalis","Macaca fuscata","Latin","dorsal nucleus of lateral lemniscus",,0 4485,"Nucleus lemnisci lateralis pars ventralis","Macaca fuscata","Latin","ventral nucleus of lateral lemniscus",,6 4486,"Nucleus lemnisci lateralis ventralis","Macaca mulatta","Latin","ventral nucleus of lateral lemniscus",,0 3519,"Nucleus lentiformis","human","Latin",,"lentiform nuclei",53 4491,"Nucleus limitans","Macaca mulatta","Latin","limitans nucleus",,20 4492,"Nucleus limitans","Macaca","Latin","limitans nucleus",,20 5513,"Nucleus limitans (Hassler)","human","Latin",,"Nucleus limitans (Hassler)",0 5514,"Nucleus limitans medialis (Hassler)","human","Latin",,"Nucleus limitans medialis (Hassler)",0 4496,"Nucleus limitans opticus (Hassler)","human","Latin","limitans nucleus",,0 5515,"Nucleus limitans portae (Hassler)","human","Latin",,"Nucleus limitans portae (Hassler)",0 4495,"Nucleus limitans thalami","Macaca fascicularis","Latin","limitans nucleus",,1 4494,"Nucleus limitans thalami","human","Latin","limitans nucleus",,1 4501,"Nucleus linearis","Macaca mulatta","Latin","linear nucleus",,28 4500,"Nucleus linearis","human","Latin","linear nucleus",,28 5009,"Nucleus magnocellularis","Macaca mulatta","Latin",,"Nucleus reticularis magnocellularis",198 4505,"Nucleus magnocellularis lateralis anuli aqueductus","human","Latin",,"Nucleus lateralis anuli aqueductus",0 4508,"Nucleus magnocellularis medialis anuli aqueductus","human","Latin",,"Nucleus medianus anuli aqueductus",0 4689,"Nucleus magnocellularis tractus optici","human","Latin","nucleus of optic tract",,0 4164,"Nucleus mamillaris","Macaca mulatta","Latin","MEDIAL MAMMILLARY NUCLEUS",,10 4162,"Nucleus mamillaris medialis","human","Latin","MEDIAL MAMMILLARY NUCLEUS",,4 4163,"Nucleus mamillaris medialis","Macaca fuscata","Latin","MEDIAL MAMMILLARY NUCLEUS",,4 3754,"Nucleus medialis amygdalae","Macaca fascicularis","Latin","medial amygdaloid nucleus",,1 4173,"Nucleus medialis corpus mamillaris (Shantha)","human","Latin","medial part of medial mammillary nucleus",,0 4361,"Nucleus medialis dorsalis","human","Latin","MEDIAL DORSAL NUCLEUS",,37 1330509986,"Nucleus medialis dorsalis - not otherwise specified","Unspecified","Latin","MEDIAL DORSAL NUCLEUS - not otherwise specified",,37 4362,"Nucleus medialis dorsalis (Hassler)","human","Latin","MEDIAL DORSAL NUCLEUS",,0 4534,"Nucleus medialis dorsalis caudalis (Hassler)","human","Latin","paralaminar part of medial dorsal nucleus",,0 4540,"Nucleus medialis dorsalis fasciculosis (Hassler)","human","Latin","parvicellular part of medial dorsal nucleus",,0 4541,"Nucleus medialis dorsalis nucleus fasciculosus (Hassler)","human","Latin","parvicellular part of medial dorsal nucleus",,0 4517,"Nucleus medialis dorsalis paralamellaris (Hassler)","human","Latin","densocellular part of medial dorsal nucleus",,0 4363,"Nucleus medialis dorsalis thalami","Macaca fascicularis","Latin","MEDIAL DORSAL NUCLEUS",,3 4532,"Nucleus medialis dorsalis thalami, pars multiformis","Macaca fuscata","Latin","paralaminar part of medial dorsal nucleus",,0 4531,"Nucleus medialis dorsalis thalami, pars multiformis","human","Latin","paralaminar part of medial dorsal nucleus",,0 4515,"Nucleus medialis dorsalis, pars densocellularis","Macaca mulatta","Latin","densocellular part of medial dorsal nucleus",,0 4516,"Nucleus medialis dorsalis, pars densocellularis","Macaca fuscata","Latin","densocellular part of medial dorsal nucleus",,0 4521,"Nucleus medialis dorsalis, pars magnocellularis","Macaca fuscata","Latin","magnocellular part of medial dorsal nucleus",,0 4519,"Nucleus medialis dorsalis, pars magnocellularis","Macaca mulatta","Latin","magnocellular part of medial dorsal nucleus",,0 4530,"Nucleus medialis dorsalis, pars multiformis","Macaca mulatta","Latin","paralaminar part of medial dorsal nucleus",,0 4527,"Nucleus medialis dorsalis, pars paralaminaris","Unspecified","Latin","paralaminar part of medial dorsal nucleus",,0 4536,"Nucleus medialis dorsalis, pars parvocellularis","Macaca mulatta","Latin","parvicellular part of medial dorsal nucleus",,0 4537,"Nucleus medialis dorsalis, pars parvocellularis","Macaca fuscata","Latin","parvicellular part of medial dorsal nucleus",,0 4522,"Nucleus medialis fibrosus","human","Latin","magnocellular part of medial dorsal nucleus",,0 4523,"Nucleus medialis fibrosus (Hassler)","human","Latin","magnocellular part of medial dorsal nucleus",,0 -1330868060,"nucleus medialis globi pallidi","human","Latin","medial globus pallidus",,0 4547,"Nucleus medialis septi","Macaca fascicularis","Latin","medial septal nucleus",,6 4507,"Nucleus medianus anuli aquaeducti","Macaca fascicularis","Latin",,"Nucleus medianus anuli aqueductus",0 4506,"Nucleus medianus anuli aqueductus","human","Latin",,"Nucleus medianus anuli aqueductus",0 4376,"Nucleus mediodorsalis thalami","human","Latin","MEDIAL DORSAL NUCLEUS",,2 2431,"Nucleus mesencephalicus profundus","human","Latin",,"deep tegmental gray",8 1692,"Nucleus minimus","human","Latin",,"Nucleus minimus",0 4198,"Nucleus Monakow","Macaca mulatta","Latin","accessory cuneate nucleus",,0 1301684875,"Nucleus motorii lateralis","human","Latin",,"anterior horn nuclei",0 396,"Nucleus motorius colliculi superioris","human","Latin",,"Nuclei colliculi superioris",0 5056,"Nucleus motorius dissipatus formationis","human","Latin",,"Nucleus lateralis mesencephali",0 5052,"Nucleus motorius dissipatus formationis reticularis","human","Latin",,"motor nucleus of tegmentum",0 1922157407,"Nucleus motorius nervi trigeminalis","human","Latin","motor nucleus of trigeminal nerve",,0 1561860532,"Nucleus motorius nervi trigemini","human","Latin","motor nucleus of trigeminal nerve",,8 378201858,"Nucleus motorius nervi trigemini","Macaca fascicularis","Latin","motor nucleus of trigeminal nerve",,8 5058,"Nucleus motorius tegmento-bigeminalis","human","Latin",,"Nucleus lateralis mesencephali",0 -313246555,"Nucleus motorius trigeminalis","human","Latin","motor nucleus of trigeminal nerve",,0 3613,"Nucleus nervi abducentis","human","Latin","abducens nucleus",,3 3614,"Nucleus nervi abducentis","Macaca fascicularis","Latin","abducens nucleus",,3 4280,"Nucleus nervi facialis","human","Latin","facial motor nucleus",,3 4281,"Nucleus nervi facialis","Macaca fascicularis","Latin","facial motor nucleus",,3 4586,"Nucleus nervi hypoglossi","human","Latin","hypoglossal nucleus",,16 4587,"Nucleus nervi hypoglossi","Macaca fascicularis","Latin","hypoglossal nucleus",,16 327,"Nucleus nervi oculomotorii","human","Latin","OCULOMOTOR NUCLEAR COMPLEX",,4 328,"Nucleus nervi oculomotorii","Macaca fascicularis","Latin","OCULOMOTOR NUCLEAR COMPLEX",,4 3929,"Nucleus nervi oculomotorii centralis","human","Latin","central oculomotor nucleus",,0 5112,"Nucleus nervi oculomotorii Edinger-Westphal","human","Latin","parvocellular oculomotor nucleus",,0 4601,"Nucleus nervi oculomotorii medianus anterior","Unspecified","Latin","anterior median oculomotor nucleus",,0 5107,"Nucleus nervi oculomotorii parvocellularis","human","Latin","parvocellular oculomotor nucleus",,0 5412,"Nucleus nervi oculomotorii ventrolateralis","human","Latin","ventral oculomotor nucleus",,0 4609,"Nucleus nervi oculomotorii, pars intermedius","Unspecified","Latin","intermediate oculomotor nucleus",,0 4595,"Nucleus nervi oculomotorii, pars dorsalis","Macaca fascicularis","Latin","dorsal oculomotor nucleus",,0 5407,"Nucleus nervi oculomotorii, pars medialis","human","Latin","medial oculomotor nucleus",,0 5411,"Nucleus nervi oculomotorii, pars ventralis","Macaca fascicularis","Latin","ventral oculomotor nucleus",,0 5301,"Nucleus nervi trochlearis","human","Latin","trochlear nucleus",,4 5302,"Nucleus nervi trochlearis","Macaca fascicularis","Latin","trochlear nucleus",,4 329,"Nucleus oculomotorius","Macaca nemestrina","Latin","OCULOMOTOR NUCLEAR COMPLEX",,7 -1194191653,"Nucleus oculomotorius accessorius","human","Latin",,"accessory oculomotor nuclei",0 3618,"nucleus of abducens nerve (VI)","human","English","abducens nucleus",,0 3448,"nucleus of ansa lenticularis","human","English","nucleus of ansa lenticularis",,0 4020,"nucleus of anterior commissure","Macaca fascicularis","English","nucleus of anterior commissure",,2 7043,"nucleus of basal optic root","human","English",,"nucleus of transverse peduncular tract",0 362,"nucleus of basis pedunculi","human","English","SUBSTANTIA NIGRA",,0 5580,"nucleus of Bechterew","human","English","superior vestibular nucleus",,11 3311,"nucleus of bulbar accessory nerve","human","English",,"nucleus of bulbar accessory nerve",0 4856,"nucleus of circumolivary bundle","human","English","pontobulbar nucleus",,5 4028,"nucleus of commissura anterior","human","English","nucleus of anterior commissure",,0 4203,"nucleus of corpus restiforme","human","English","accessory cuneate nucleus",,0 4050,"nucleus of Darkschewitsch","rat","English","nucleus of Darkschewitsch",,98 4049,"nucleus of Darkschewitsch","Macaca fascicularis","English","nucleus of Darkschewitsch",,98 4048,"nucleus of Darkschewitsch","human","English","nucleus of Darkschewitsch",,98 5561,"nucleus of Deiters","human","English","lateral vestibular nucleus",,13 803290142,"nucleus of descending root of trigeminal","human","English",,"SPINAL TRIGEMINAL NUCLEUS",0 -1206221497,"nucleus of descending tract of trigeminal","human","English",,"SPINAL TRIGEMINAL NUCLEUS",0 3891,"nucleus of diagonal band","Macaca fascicularis","English","nucleus of diagonal band",,13 3892,"nucleus of diagonal band","rat","English","nucleus of diagonal band",,13 3890,"nucleus of diagonal band","human","English","nucleus of diagonal band",,13 4513,"nucleus of eminentia teres","human","English","nucleus of medial eminence",,0 1409,"nucleus of field H","Unspecified","English","nucleus of field H",,0 1417,"nucleus of field of Forel","human","English","nucleus of field H",,0 1411,"nucleus of Forel's field","human","English","nucleus of field H",,0 1412,"nucleus of Forel's field H","human","English","nucleus of field H",,0 3926,"nucleus of inferior colliculus (Crosby)","human","English","central nucleus of inferior colliculus",,0 4032,"nucleus of inferior commissure","human","English","commissural nucleus of vagus nerve",,0 4432,"nucleus of Kolliker-Fuse","human","English","diffuse reticular nucleus",,3 3789,"nucleus of lateral olfactory tract","Macaca fascicularis","English","nucleus of lateral olfactory tract",,0 3790,"nucleus of lateral olfactory tract","rat","English","nucleus of lateral olfactory tract",,0 3788,"nucleus of lateral olfactory tract","human","English","nucleus of lateral olfactory tract",,0 5241,"nucleus of Luys","human","English","subthalamic nucleus",,6 7046,"nucleus of mammillary peduncle","human","English",,"nucleus of mammillary peduncle",0 4510,"nucleus of medial eminence","Macaca fascicularis","English","nucleus of medial eminence",,0 4509,"nucleus of medial eminence","human","English","nucleus of medial eminence",,0 332,"nucleus of oculomotor nerve","human","English","OCULOMOTOR NUCLEAR COMPLEX",,0 4686,"nucleus of optic tract","human","English","nucleus of optic tract",,4 3932,"nucleus of Perlia","human","English","central oculomotor nucleus",,4 4045,"nucleus of posterior commissure","human","English","nucleus of posterior commissure",,12 4944,"nucleus of pretectal area","human","English","nucleus of pretectal area",,0 5102,"nucleus of Roller","human","English","sublingual nucleus",,14 5103,"nucleus of Roller","rat","English","sublingual nucleus",,14 5568,"nucleus of Schwalbe","human","English","medial vestibular nucleus",,0 612,"nucleus of solitary tract","rat","English","SOLITARY NUCLEUS",,39 611,"nucleus of solitary tract","Macaca fascicularis","English","SOLITARY NUCLEUS",,39 249951312,"Nucleus of spinal tract of N. V (subnucleus interpolaris)","human","English","interpolar part of spinal trigeminal nucleus",,0 -1301950525,"nucleus of spinal trigeminal tract","Macaca fascicularis","English",,"SPINAL TRIGEMINAL NUCLEUS",0 3634,"nucleus of Staderini","human","English","nucleus intercalatus",,1 5201,"nucleus of stria terminalis","Macaca fascicularis","English","nucleus of stria terminalis",,114 5200,"nucleus of stria terminalis","human","English","nucleus of stria terminalis",,114 3915,"nucleus of substantia innominata","human","English","basal nucleus",,0 5248,"nucleus of tegmental field","human","English",,"subthalamic reticular nucleus",0 3894,"nucleus of the diagonal band of Broca","human","English","nucleus of diagonal band",,105 2462,"Nucleus of the raphe","Macaca mulatta","Latin",,"raphe nuclei",0 3792,"Nucleus of tractus olfactorius lateralis","Macaca fuscata","Latin","nucleus of lateral olfactory tract",,0 610,"nucleus of tractus solitarius","human","English","SOLITARY NUCLEUS",,22 7041,"nucleus of transverse peduncular tract","human","English",,"nucleus of transverse peduncular tract",0 5303,"nucleus of trochlear nerve","human","English","trochlear nucleus",,0 3774,"Nucleus olfactorius anterior","human","Latin","anterior olfactory nucleus",,16 4613,"Nucleus olivaris accessorius dorsalis","human","Latin","dorsal accessory inferior olivary nucleus",,1 4625,"Nucleus olivaris accessorius medialis","human","Latin","medial accessory inferior olivary nucleus",,1 4617,"Nucleus olivaris accessorius posterior","Macaca mulatta","Latin","dorsal accessory inferior olivary nucleus",,0 4616,"Nucleus olivaris accessorius posterior","human","Latin","dorsal accessory inferior olivary nucleus",,0 599,"Nucleus olivaris caudalis","human","Latin","INFERIOR OLIVARY COMPLEX",,0 4651,"Nucleus olivaris colliculi superioris (Fuse)","human","Latin","olivary pretectal nucleus",,0 4652,"Nucleus olivaris corporis quadrigemini anterioris","human","Latin","olivary pretectal nucleus",,0 4633,"Nucleus olivaris dissipatus","Macaca fuscata","Latin",,"Nucleus olivaris dissipatus",0 596,"Nucleus olivaris inferior","human","Latin","INFERIOR OLIVARY COMPLEX",,13 597,"Nucleus olivaris inferior","Macaca fascicularis","Latin","INFERIOR OLIVARY COMPLEX",,13 4615,"Nucleus olivaris inferior accessorius dorsalis","Macaca fascicularis","Latin","dorsal accessory inferior olivary nucleus",,0 4627,"Nucleus olivaris inferior accessorius medialis","Macaca mulatta","Latin","medial accessory inferior olivary nucleus",,0 4614,"Nucleus olivaris inferior dorsalis","Macaca nemestrina","Latin","dorsal accessory inferior olivary nucleus",,6 4626,"Nucleus olivaris inferior medialis","Macaca fascicularis","Latin","medial accessory inferior olivary nucleus",,0 4636,"Nucleus olivaris inferior principalis","Macaca mulatta","Latin","principal inferior olivary nucleus",,0 4620,"Nucleus olivaris inferior, lamina dorsalis","human","Latin","dorsal accessory inferior olivary nucleus",,0 4619,"Nucleus olivaris inferior, lamina dorsalis","human","Latin","dorsal accessory inferior olivary nucleus",,0 4628,"Nucleus olivaris inferior, lamina medialis","human","Latin","medial accessory inferior olivary nucleus",,0 4653,"Nucleus olivaris mesencephali","human","Latin","olivary pretectal nucleus",,0 591,"Nucleus olivaris metencephali","human","Latin","SUPERIOR OLIVE",,0 4646,"Nucleus olivaris pretectalis of Fuse","Macaca fuscata","Latin","olivary pretectal nucleus",,0 590,"Nucleus olivaris rostralis","human","Latin","SUPERIOR OLIVE",,0 589,"Nucleus olivaris superior","human","Latin","SUPERIOR OLIVE",,8 4656,"Nucleus olivaris superior lateralis","Macaca mulatta","Latin","lateral superior olivary nucleus",,0 4665,"Nucleus olivaris superior medialis","Macaca mulatta","Latin","medial superior olivary nucleus",,0 588,"Nucleus olivaris superioris","human","Latin","SUPERIOR OLIVE",,0 4259,"Nucleus opticus dorsalis","human","Latin","dorsal tegmental nucleus",,0 1004461060,"Nucleus oralis tractus spinalis nervi trigemini","Macaca mulatta","Latin","oral part of spinal trigeminal nucleus",,0 6830,"Nucleus pallidohypothalamicus","human","Latin",,"pallidohypothalamic nucleus",0 2515,"Nucleus pallidus","Macaca mulatta","Latin","GLOBUS PALLIDUS",,1 4691,"nucleus papilliformis","human","English",,"nucleus papilliformis",0 4692,"Nucleus papilliformis","human","Latin",,"nucleus papilliformis",0 1696,"Nucleus parabigeminalis","Macaca fascicularis","Latin","parabigeminal nucleus",,7 4701,"Nucleus parabrachialis","Macaca mulatta","Latin",,"Nucleus parabrachialis",0 4696,"Nucleus parabrachialis lateralis","Macaca fascicularis","Latin","lateral parabrachial nucleus",,10 4700,"Nucleus parabrachialis medialis","Macaca fascicularis","Latin","medial parabrachial nucleus",,29 4703,"Nucleus parabrachialis pigmentosus","Macaca mulatta","Latin",,"parabrachial pigmented nucleus",12 4704,"Nucleus parabranchialis pigmentosus","human","Latin",,"parabrachial pigmented nucleus",0 4708,"Nucleus paracentralis","human","Latin","paracentral nucleus",,9 4709,"Nucleus paracentralis","Macaca mulatta","Latin","paracentral nucleus",,9 4712,"Nucleus paracentralis thalami","Macaca fascicularis","Latin","paracentral nucleus",,0 4721,"Nucleus parafascicularis","Macaca mulatta","Latin","parafascicular nucleus",,48 4720,"Nucleus parafascicularis","human","Latin","parafascicular nucleus",,48 4722,"Nucleus parafascicularis (Hassler)","human","Latin","parafascicular nucleus",,0 4726,"Nucleus parafascicularis thalami","Macaca fascicularis","Latin","parafascicular nucleus",,12 4730,"Nucleus parafornicalis","human","Latin",,"parafornical nucleus",0 5033,"Nucleus paragigantocellularis dorsalis","Macaca mulatta","Latin","dorsal paragigantocellular nucleus",,4 5032,"Nucleus paragigantocellularis dorsalis","human","Latin","dorsal paragigantocellular nucleus",,4 5027,"Nucleus paragigantocellularis lateralis","human","Latin","lateral paragigantocellular nucleus",,66 5028,"Nucleus paragigantocellularis lateralis","Macaca mulatta","Latin","lateral paragigantocellular nucleus",,66 4733,"Nucleus paralemniscalis","Macaca mulatta","Latin",,"paralemniscal gray",0 4732,"Nucleus paralemniscalis","human","Latin",,"paralemniscal gray",0 4812,"Nucleus paramedianus (Hassler)","human","Latin","paraventricular nucleus of thalamus",,0 4755,"Nucleus paramedianus accessorius","Unspecified","Latin","accessory paramedian reticular nucleus",,0 4813,"Nucleus paramedianus caudalis (Hassler)","human","Latin",,"Nucleus paramedianus caudalis (Hassler)",0 4745,"Nucleus paramedianus dorsalis","Macaca mulatta","Latin","dorsal paramedian reticular nucleus",,0 4744,"Nucleus paramedianus dorsalis","human","Latin","dorsal paramedian reticular nucleus",,0 4752,"Nucleus paramedianus oralis","human","Latin","ventral paramedian reticular nucleus",,0 4815,"Nucleus paramedianus oralis (Hassler)","human","Latin",,"Nucleus paramedianus oralis (Hassler)",0 4747,"Nucleus paramedianus posterior","human","Latin","dorsal paramedian reticular nucleus",,0 4816,"Nucleus paramedianus principalis (Hassler)","human","Latin",,"Nucleus paramedianus principalis (Hassler)",0 4750,"Nucleus paramedianus ventralis","Unspecified","Latin","ventral paramedian reticular nucleus",,0 4757,"Nucleus paranigralis","Macaca mulatta","Latin",,"paranigral nucleus",0 5279,"Nucleus paraopticus","human","Latin",,"paraoptic nucleus",0 4758,"Nucleus parasolitarius","human","Latin",,"Nucleus parasolitarius",0 4772,"Nucleus parataenialis","human","Latin","paratenial nucleus",,2 4776,"Nucleus parataenialis (Hassler)","human","Latin","paratenial nucleus",,0 4761,"Nucleus parataenialis interstitialis (Hassler)","human","Latin",,"Nucleus parataenialis interstitialis (Hassler)",0 4760,"Nucleus parataenialis parvocellularis (Hassler)","human","Latin",,"Nucleus parataenialis parvocellularis (Hassler)",0 4773,"Nucleus parataenialis thalami","Macaca mulatta","Latin","paratenial nucleus",,0 4775,"Nucleus paratenialis thalami","Macaca fuscata","Latin","paratenial nucleus",,0 4774,"Nucleus paratenialis thalami","Macaca fascicularis","Latin","paratenial nucleus",,0 4783,"Nucleus paratrigeminalis","Unspecified","Latin","paratrigeminal nucleus",,2 4800,"Nucleus paraventricularis anterior","human","Latin",,"Nucleus paraventricularis anterior",0 4814,"Nucleus paraventricularis caudalis","Macaca mulatta","Latin",,"Nucleus paramedianus caudalis (Hassler)",0 4790,"Nucleus paraventricularis hypothalami","Macaca fascicularis","Latin","paraventricular nucleus of hypothalamus",,6 4789,"Nucleus paraventricularis hypothalami","human","Latin","paraventricular nucleus of hypothalamus",,6 4801,"Nucleus paraventricularis posterior","human","Latin",,"Nucleus paraventricularis posterior",0 4807,"Nucleus paraventricularis thalami","Macaca mulatta","Latin","paraventricular nucleus of thalamus",,7 4806,"Nucleus paraventricularis thalami","Macaca fascicularis","Latin","paraventricular nucleus of thalamus",,7 4805,"Nucleus paraventricularis thalami","human","Latin","paraventricular nucleus of thalamus",,7 5040,"Nucleus parvocellularis","Macaca mulatta","Latin","parvicellular reticular nucleus",,15 4817,"Nucleus parvocellularis compactus","Macaca mulatta","Latin",,"Nucleus parvocellularis compactus",0 5105,"Nucleus parvocellularis nervi hypoglossi","human","Latin","sublingual nucleus",,0 4823,"Nucleus pedunculopontinus","human","Latin","pedunculopontine tegmental nucleus",,3 4828,"Nucleus pericentralis (colliculi inferioris)","Unspecified","Latin","pericentral nucleus of inferior colliculus",,0 7216,"Nucleus pericornualis anterior","human","Latin",,"Nucleus pericornualis anterior",0 4205,"Nucleus pericuneatus lateralis","Unspecified","Latin","lateral pericuneate nucleus",,0 4207,"Nucleus pericuneatus medialis","Unspecified","Latin","medial pericuneate nucleus",,0 4831,"Nucleus perifornicalis hypothalami","Macaca fuscata","Latin",,"perifornical nucleus",0 4834,"Nucleus periolivaris","Unspecified","Latin","periolivary nucleus",,0 4838,"Nucleus peripeduncularis","Macaca mulatta","Latin","peripeduncular nucleus",,2 4839,"Nucleus peripeduncularis","human","Latin","peripeduncular nucleus",,2 4840,"Nucleus peripeduncularis thalami","Macaca fascicularis","Latin","peripeduncular nucleus",,0 4785,"Nucleus peritrigeminalis","Unspecified","Latin","peritrigeminal nucleus",,0 4844,"Nucleus periventricularis anteroventralis","Unspecified","Latin","anteroventral periventricular nucleus",,0 4926,"Nucleus periventricularis hypothalami","Macaca fuscata","Latin","intermediate periventricular nucleus",,25 4922,"Nucleus periventricularis hypothalami, pars dorsalis","human","Latin",,"dorsal periventricular hypothalamic nucleus",0 4924,"Nucleus periventricularis hypothalami, pars ventralis","human","Latin",,"ventral periventricular hypothalamic nucleus",0 4847,"Nucleus periventricularis posterior","human","Latin","posterior periventricular nucleus",,3 4918,"Nucleus periventricularis praeopticus","human","Latin","preoptic periventricular nucleus",,0 4917,"Nucleus periventricularis preopticus","human","Latin","preoptic periventricular nucleus",,0 437,"Nucleus pigmentosus pontis","human","Latin","locus ceruleus",,0 361,"Nucleus pigmentosus subthalamo-peduncularis","human","Latin","SUBSTANTIA NIGRA",,0 -597463936,"Nucleus pontinus nervi trigeminalis","human","Latin","principal sensory nucleus of trigeminal nerve",,0 619980462,"Nucleus pontinus nervi trigemini","human","Latin","principal sensory nucleus of trigeminal nerve",,0 3532,"Nucleus pontis","Macaca nemestrina","Latin","pontine nuclei",,557 4852,"Nucleus pontobulbaris","human","Latin","pontobulbar nucleus",,0 3540,"Nucleus posterior thalami","Macaca fascicularis","Latin","posterior nucleus of thalamus",,7 7168,"Nucleus posteromarginalis","human","Latin",,"Rexed's lamina I",0 5465,"Nucleus posteroventralis oralis","human","Latin","oral part of ventral posterolateral nucleus",,0 4108,"Nucleus praegeniculatus","human","Latin","ventral nucleus of lateral geniculate body",,0 4113,"Nucleus praegeniculatus fibrosus (Hassler)","human","Latin",,"Nucleus geniculatus lateralis ventralis, pars caudalis",0 4115,"Nucleus praegeniculatus griseus (Hassler)","human","Latin",,"Nucleus geniculatus lateralis ventralis, pars oralis",0 4892,"Nucleus praeopticus lateralis","human","Latin","lateral preoptic nucleus",,0 4903,"Nucleus praeopticus medialis","human","Latin","medial preoptic nucleus",,7 4913,"Nucleus praeopticus medianus","Macaca fascicularis","Latin","median preoptic nucleus",,0 4912,"Nucleus praeopticus medianus","human","Latin","median preoptic nucleus",,0 4937,"Nucleus praepositus","Macaca fascicularis","Latin","nucleus prepositus",,21 4940,"Nucleus praepositus hypoglossi","Macaca mulatta","Latin","nucleus prepositus",,17 409,"Nucleus praetectalis","human","Latin","PRETECTAL REGION",,9 4650,"Nucleus praetectalis anterior","Macaca mulatta","Latin","olivary pretectal nucleus",,0 4107,"Nucleus pregeniculatum","human","Latin","ventral nucleus of lateral geniculate body",,0 4886,"Nucleus premamillaris hypothalami","Macaca fuscata","Latin","premammillary nucleus",,0 4883,"Nucleus preolivaris","Unspecified","Latin","preolivary nucleus",,1 4891,"Nucleus preopticus lateralis","human","Latin","lateral preoptic nucleus",,2 4902,"Nucleus preopticus medialis","human","Latin","medial preoptic nucleus",,36 4911,"Nucleus preopticus medianus","Macaca fuscata","Latin","median preoptic nucleus",,12 4934,"nucleus prepositus","Macaca fascicularis","English","nucleus prepositus",,157 4936,"nucleus prepositus","rat","English","nucleus prepositus",,157 4933,"nucleus prepositus","human","English","nucleus prepositus",,157 4935,"Nucleus prepositus","human","Latin","nucleus prepositus",,157 4939,"Nucleus prepositus hypoglossi","Macaca fuscata","Latin","nucleus prepositus",,129 4943,"Nucleus pretectalis principalis","Unspecified","Latin","principal pretectal nucleus",,1 379,"Nucleus princeps colliculi inferioris","human","Latin",,"Nucleus colliculi inferioris",0 333,"Nucleus principalis nervi oculomotorii","Macaca mulatta","Latin",,"Nucleus principalis nervi oculomotorii",0 -1326116223,"Nucleus principalis nervi trigemini","human","Latin","principal sensory nucleus of trigeminal nerve",,0 7172,"Nucleus proprius cornu dorsalis","human","Latin",,"proper sensory nucleus",0 7176,"Nucleus proprius cornu ventralis","human","Latin",,"Nucleus proprius ventralis",0 7171,"Nucleus proprius dorsalis","human","Latin",,"proper sensory nucleus",0 7175,"Nucleus proprius ventralis","human","Latin",,"Nucleus proprius ventralis",0 3550,"Nucleus pulvinaris","human","Latin","PULVINAR",,4 4949,"Nucleus pulvinaris inferior","Macaca mulatta","Latin","inferior pulvinar nucleus",,0 4948,"Nucleus pulvinaris inferior","human","Latin","inferior pulvinar nucleus",,0 4951,"Nucleus pulvinaris inferior thalami","Macaca fascicularis","Latin","inferior pulvinar nucleus",,0 5019,"Nucleus pulvinaris intergeniculatus (Hassler)","human","Latin",,"intergeniculate pulvinar",0 4955,"Nucleus pulvinaris lateralis","Macaca mulatta","Latin","lateral pulvinar nucleus",,0 4954,"Nucleus pulvinaris lateralis","human","Latin","lateral pulvinar nucleus",,0 4960,"Nucleus pulvinaris lateralis (Hassler)","human","Latin","lateral pulvinar nucleus",,0 4958,"Nucleus pulvinaris lateralis thalami","Macaca fascicularis","Latin","lateral pulvinar nucleus",,0 4957,"Nucleus pulvinaris lateralis thalami","human","Latin","lateral pulvinar nucleus",,0 4963,"Nucleus pulvinaris medialis","human","Latin","medial pulvinar nucleus",,0 4964,"Nucleus pulvinaris medialis","Macaca mulatta","Latin","medial pulvinar nucleus",,0 5012,"Nucleus pulvinaris medialis (Hassler)","human","Latin",,"Nucleus pulvinaris medialis (Hassler)",0 5014,"Nucleus pulvinaris medialis dorsalis (Hassler)","human","Latin",,"Nucleus pulvinaris medialis dorsalis (Hassler)",0 5013,"Nucleus pulvinaris medialis internus (Hassler)","human","Latin",,"Nucleus pulvinaris medialis internus (Hassler)",0 4965,"Nucleus pulvinaris medialis thalami","human","Latin","medial pulvinar nucleus",,0 4966,"Nucleus pulvinaris medialis thalami","Macaca fascicularis","Latin","medial pulvinar nucleus",,0 5016,"Nucleus pulvinaris medialis ventralis (Hassler)","human","Latin",,"Nucleus pulvinaris medialis ventralis (Hassler)",0 5015,"Nucleus pulvinaris medialis zentralis (Hassler)","human","Latin",,"Nucleus pulvinaris medialis zentralis (Hassler)",0 4971,"Nucleus pulvinaris oralis","Macaca mulatta","Latin","oral pulvinar nucleus",,0 4970,"Nucleus pulvinaris oralis","human","Latin","oral pulvinar nucleus",,0 5021,"Nucleus pulvinaris oralis (Hassler)","human","Latin",,"Nucleus pulvinaris oralis (Hassler)",0 4972,"Nucleus pulvinaris oralis thalami","Macaca fascicularis","Latin","oral pulvinar nucleus",,0 5022,"Nucleus pulvinaris orolateralis (Hassler)","human","Latin",,"Nucleus pulvinaris orolateralis (Hassler)",0 5023,"Nucleus pulvinaris oromedialis (Hassler)","human","Latin",,"Nucleus pulvinaris oromedialis (Hassler)",0 5024,"Nucleus pulvinaris oroventralis (Hassler)","human","Latin",,"Nucleus pulvinaris oroventralis (Hassler)",0 5011,"Nucleus pulvinaris superficialis (Hassler)","human","Latin",,"superficial pulvinar nucleus",0 5020,"Nucleus pulvinaris suprabrachialis (Hassler)","human","Latin",,"Nucleus pulvinaris suprabrachialis (Hassler)",0 3549,"Nucleus pulvinaris thalami","Macaca fascicularis","Latin","PULVINAR",,1 4950,"Nucleus pulvinaris thalami, pars inferior","Macaca fuscata","Latin","inferior pulvinar nucleus",,0 4956,"Nucleus pulvinaris thalami, pars lateralis","Macaca fuscata","Latin","lateral pulvinar nucleus",,0 4967,"Nucleus pulvinaris thalami, pars medialis","Macaca fuscata","Latin","medial pulvinar nucleus",,0 5017,"Nucleus pulvinaris ventralis (Hassler)","human","Latin",,"Nucleus pulvinaris ventralis (Hassler)",0 5845,"Nucleus putamen","Macaca mulatta","Latin","putamen",,231 1596405628,"nucleus radicis descendentis nervi trigemini","human","Latin",,"SPINAL TRIGEMINAL NUCLEUS",0 2460,"Nucleus raphe","Macaca nemestrina","Latin",,"raphe nuclei",1032 4737,"Nucleus raphe dorsalis","human","Latin","dorsal raphe nucleus",,253 4981,"nucleus raphe magnus","rat","English","nucleus raphe magnus",,557 4978,"nucleus raphe magnus","human","English","nucleus raphe magnus",,557 4979,"nucleus raphe magnus","Macaca fascicularis","English","nucleus raphe magnus",,557 4980,"Nucleus raphe magnus","human","Latin","nucleus raphe magnus",,557 4984,"nucleus raphe obscurus","human","English","nucleus raphe obscurus",,113 4985,"nucleus raphe obscurus","Macaca fascicularis","English","nucleus raphe obscurus",,113 4987,"nucleus raphe obscurus","rat","English","nucleus raphe obscurus",,113 4986,"Nucleus raphe obscurus","human","Latin","nucleus raphe obscurus",,113 4991,"nucleus raphe pallidus","Macaca fascicularis","English","nucleus raphe pallidus",,110 4993,"nucleus raphe pallidus","rat","English","nucleus raphe pallidus",,110 4990,"nucleus raphe pallidus","human","English","nucleus raphe pallidus",,110 4992,"Nucleus raphe pallidus","human","Latin","nucleus raphe pallidus",,110 5902,"Nucleus raphe pontis","human","Latin","pontine raphe nucleus",,31 5903,"Nucleus raphe pontis","rat","Latin","pontine raphe nucleus",,4 4739,"Nucleus raphes dorsalis","human","Latin","dorsal raphe nucleus",,5 4982,"Nucleus raphes magnus","Macaca mulatta","Latin","nucleus raphe magnus",,2 4988,"Nucleus raphes obscurus","Macaca mulatta","Latin","nucleus raphe obscurus",,1 4994,"Nucleus raphes pallidus","Macaca mulatta","Latin","nucleus raphe pallidus",,0 5904,"Nucleus raphes pontis","Macaca mulatta","Latin","pontine raphe nucleus",,4 4190,"Nucleus restiformis","Unspecified","Latin","cuneate nucleus",,0 3558,"Nucleus reticularis","Macaca mulatta","Latin","thalamic reticular nucleus",,896 4430,"Nucleus reticularis diffusus","Unspecified","Latin","diffuse reticular nucleus",,0 4431,"Nucleus reticularis diffusus (Koelliker)","human","Latin","diffuse reticular nucleus",,0 4998,"Nucleus reticularis gigantocellularis","human","Latin","gigantocellular nucleus",,227 5004,"Nucleus reticularis lateralis","Macaca fascicularis","Latin","lateral reticular nucleus",,84 5005,"Nucleus reticularis lateralis (medullae)","human","Latin","lateral reticular nucleus",,0 5008,"Nucleus reticularis magnocellularis","Macaca fascicularis","Latin",,"Nucleus reticularis magnocellularis",37 4751,"Nucleus reticularis paramedianus","Macaca mulatta","Latin","ventral paramedian reticular nucleus",,8 4746,"Nucleus reticularis paramedianus myelencephali","Macaca fascicularis","Latin","dorsal paramedian reticular nucleus",,0 5039,"Nucleus reticularis parvicellularis","human","Latin","parvicellular reticular nucleus",,4 5038,"Nucleus reticularis parvocellularis","Macaca fascicularis","Latin","parvicellular reticular nucleus",,34 5043,"Nucleus reticularis pontis caudalis","human","Latin","caudal pontine reticular nucleus",,72 5048,"Nucleus reticularis pontis oralis","Macaca mulatta","Latin","oral pontine reticular nucleus",,69 5044,"Nucleus reticularis pontis, pars caudalis","Macaca mulatta","Latin","caudal pontine reticular nucleus",,0 5049,"Nucleus reticularis pontis, pars oralis","rat","Latin","oral pontine reticular nucleus",,0 5247,"Nucleus reticularis subthalami","human","Latin",,"subthalamic reticular nucleus",0 5068,"Nucleus reticularis tegmenti pontis","Macaca fascicularis","Latin","reticulotegmental nucleus",,163 3554,"Nucleus reticularis thalami","human","Latin","thalamic reticular nucleus",,96 3555,"Nucleus reticularis thalami","Macaca fascicularis","Latin","thalamic reticular nucleus",,96 5074,"Nucleus reticularis ventralis","human","Latin","ventral reticular nucleus",,20 3557,"Nucleus reticulatus (thalami)","human","Latin","thalamic reticular nucleus",,0 3642,"nucleus retroambigualis","human","English",,"nucleus retroambigualis",0 3643,"Nucleus retroambigualis","human","Latin",,"nucleus retroambigualis",0 3609,"Nucleus retro-olivaris","Unspecified","Latin","retro-olivary cell group",,0 5080,"Nucleus reuniens","rat","Latin","reuniens nucleus",,87 5079,"Nucleus reuniens","Macaca mulatta","Latin","reuniens nucleus",,87 5078,"Nucleus reuniens","human","Latin","reuniens nucleus",,87 5082,"Nucleus reuniens thalami","Macaca fascicularis","Latin","reuniens nucleus",,11 5081,"Nucleus reuniens thalami","human","Latin","reuniens nucleus",,11 5090,"Nucleus rhomboidalis","human","Latin","rhomboidal nucleus",,2 5093,"Nucleus rhomboidalis thalami","Macaca fuscata","Latin","rhomboidal nucleus",,0 5104,"Nucleus Roller","Macaca mulatta","Latin","sublingual nucleus",,2 5324,"Nucleus rostralis lateralis situs perifascicularis","Macaca","Latin","magnocellular part of ventral anterior nucleus",,0 5108,"Nucleus rostralis nervi oculomotorii","Macaca fascicularis","Latin","parvocellular oculomotor nucleus",,0 5117,"Nucleus rotundus","Macaca mulatta","Latin",,"Nucleus rotundus",0 417,"Nucleus rotundus subthalamo-peduncularis","human","Latin","RED NUCLEUS",,0 415,"Nucleus ruber","Macaca fascicularis","Latin","RED NUCLEUS",,84 414,"Nucleus ruber","human","Latin","RED NUCLEUS",,84 5664,"Nucleus ruber magnocellularis","Macaca mulatta","Latin","magnocellular part of red nucleus",,0 5671,"Nucleus ruber parvocellularis","Macaca mulatta","Latin","parvocellular part of red nucleus",,0 416,"Nucleus ruber tegmenti (Stilling)","human","Latin","RED NUCLEUS",,0 5657,"Nucleus ruber, capsula","human","Latin","capsule of red nucleus",,0 5665,"Nucleus ruber, Pars magnocellularis","Macaca mulatta","Latin","magnocellular part of red nucleus",,0 5672,"Nucleus ruber, Pars parvocellularis","Macaca mulatta","Latin","parvocellular part of red nucleus",,0 5120,"Nucleus sagulum","human","Latin",,"Sagulum",0 5119,"Nucleus sagulum","Macaca mulatta","Latin",,"Sagulum",0 5127,"Nucleus salivarius inferior","human","Latin","inferior salivatory nucleus",,0 5131,"Nucleus salivarius superior","human","Latin","superior salivatory nucleus",,0 5126,"Nucleus salivatorius caudalis","human","Latin","inferior salivatory nucleus",,0 -921314129,"Nucleus salivatorius cranialis","human","Latin","superior salivatory nucleus",,0 5123,"Nucleus salivatorius inferior","human","Latin","inferior salivatory nucleus",,1 5124,"Nucleus salivatorius inferior nervi glossopharyngei","Saimiri","Latin","inferior salivatory nucleus",,0 5130,"Nucleus salivatorius rostralis","human","Latin","superior salivatory nucleus",,0 5129,"Nucleus salivatorius superior","human","Latin","superior salivatory nucleus",,0 5487,"Nucleus semilunaris thalami","human","Latin","VENTRAL POSTEROMEDIAL NUCLEUS",,0 -1975435245,"Nucleus sensibilis superior nervi trigemini","Macaca mulatta","Latin","principal sensory nucleus of trigeminal nerve",,0 -758557352,"Nucleus sensorius principalis nervi trigemini","Macaca mulatta","Latin","principal sensory nucleus of trigeminal nerve",,0 -1238332006,"Nucleus sensorius superior nervi trigemini","Macaca fuscata","Latin","principal sensory nucleus of trigeminal nerve",,0 5290,"Nucleus septalis dorsalis","Macaca fuscata","Latin","dorsal septal nucleus",,0 5289,"Nucleus septalis dorsalis","human","Latin","dorsal septal nucleus",,0 4039,"Nucleus septalis fimbrialis","Cercocebus torquatus","Latin","septofimbrial nucleus",,1 4038,"Nucleus septalis fimbrialis","human","Latin","septofimbrial nucleus",,1 4474,"Nucleus septalis lateralis","Macaca nemestrina","Latin","lateral septal nucleus",,16 4473,"Nucleus septalis lateralis","human","Latin","lateral septal nucleus",,16 4548,"Nucleus septalis medialis","human","Latin","medial septal nucleus",,5 4549,"Nucleus septalis medialis","Macaca nemestrina","Latin","medial septal nucleus",,5 5296,"Nucleus septalis triangularis","human","Latin","triangular septal nucleus",,0 5297,"Nucleus septalis triangularis","Macaca fuscata","Latin","triangular septal nucleus",,0 4471,"Nucleus septi lateralis","human","Latin","lateral septal nucleus",,10 4041,"nucleus septofimbrialis","human","English","septofimbrial nucleus",,2 4040,"nucleus septofimbrialis","human","English","septofimbrial nucleus",,2 4554,"Nucleus septohippocampalis","human","Latin",,"septohippocampal nucleus",0 608,"Nucleus solitarius","human","Latin","SOLITARY NUCLEUS",,55 1757292749,"Nucleus spinalis nervi trigeminalis","human","Latin",,"SPINAL TRIGEMINAL NUCLEUS",0 -599632762,"Nucleus spinalis nervi trigemini","human","Latin",,"SPINAL TRIGEMINAL NUCLEUS",0 5182,"Nucleus spinalis nervi trigemini, pars caudalis","Macaca fuscata","Latin","caudal part of spinal trigeminal nucleus",,0 -964198678,"Nucleus spinalis nervi trigemini, pars interpolaris","Unspecified","Latin","interpolar part of spinal trigeminal nucleus",,0 -202330189,"Nucleus spinalis nervi trigemini, pars oralis","Macaca fuscata","Latin","oral part of spinal trigeminal nucleus",,0 3791,"Nucleus striae olfactoriae lateralis","human","Latin","nucleus of lateral olfactory tract",,0 5202,"Nucleus striae terminalis","Macaca fascicularis","Latin","nucleus of stria terminalis",,19 5211,"Nucleus subcaeruleus","human","Latin","nucleus subceruleus",,0 5209,"nucleus subceruleus","human","English","nucleus subceruleus",,13 5210,"Nucleus subceruleus","Unspecified","Latin","nucleus subceruleus",,13 5213,"Nucleus subcuneiformis","human","Latin","subcuneiform nucleus",,2 5219,"Nucleus subfascicularis","Macaca fuscata","Latin","subfascicular nucleus",,0 5218,"Nucleus subfascicularis","Macaca mulatta","Latin","subfascicular nucleus",,0 5221,"Nucleus subfascicularis, pars magnocellularis","Macaca mulatta","Latin",,"Nucleus subfascicularis, pars magnocellularis",0 5222,"Nucleus subfascicularis, pars parvocellularis","Macaca mulatta","Latin",,"Nucleus subfascicularis, pars parvocellularis",0 4336,"Nucleus subhabenularis (Hassler)","human","Latin",,"subhabenular nucleus",0 5224,"Nucleus sublentiformis","Unspecified","Latin","sublentiform nucleus",,0 5101,"Nucleus sublingualis","human","Latin","sublingual nucleus",,0 5227,"Nucleus submedius thalami","Macaca fascicularis","Latin","submedial nucleus",,0 4728,"Nucleus subparafascicularis thalami","human","Latin",,"subparafascicular thalamic nucleus",0 3917,"Nucleus subputaminalis","human","Latin",,"Nucleus subputaminalis",0 6145,"Nucleus substantia grisea dorsalis","Macaca fascicularis","Latin",,"grey commissure",0 6159,"Nucleus substantia nigrae","human","Latin",,"Nucleus substantia nigrae",0 5283,"Nucleus substantiae grisea ventralis","Macaca fascicularis","Latin","supraspinal nucleus",,0 5284,"Nucleus substantiae griseae ventralis","Macaca fuscata","Latin","supraspinal nucleus",,0 6155,"Nucleus substantiae nigrae, Pars compacta","Macaca mulatta","Latin","pars compacta",,0 6178,"Nucleus substantiae nigrae, Pars reticularis","Macaca mulatta","Latin","pars reticulata",,0 5235,"Nucleus subthalamicus","Macaca fascicularis","Latin","subthalamic nucleus",,21 5234,"Nucleus subthalamicus","human","Latin","subthalamic nucleus",,21 3944,"Nucleus superior raphes","human","Latin","superior central nucleus",,0 5253,"Nucleus suprachiasmaticus hypothalami","human","Latin","suprachiasmatic nucleus",,0 5254,"Nucleus suprachiasmaticus hypothalami","Macaca fascicularis","Latin","suprachiasmatic nucleus",,0 5262,"Nucleus suprageniculatus","Macaca mulatta","Latin","suprageniculate nucleus",,4 5263,"Nucleus suprageniculatus","Macaca","Latin","suprageniculate nucleus",,4 5270,"Nucleus supramamillaris hypothalami","Macaca fascicularis","Latin","supramammillary nucleus",,0 5269,"Nucleus supramammillaris","human","Latin","supramammillary nucleus",,1 5274,"Nucleus supraopticus","human","Latin","supraoptic nucleus",,48 5275,"Nucleus supraopticus hypothalami","Macaca fascicularis","Latin","supraoptic nucleus",,0 5282,"Nucleus supraspinalis","Macaca mulatta","Latin","supraspinal nucleus",,6 4266,"Nucleus supratrochlearis","Macaca fascicularis","Latin",,"supratrochlear nucleus",0 4267,"Nucleus supratrochlearis substantiae griseae","human","Latin",,"supratrochlear nucleus",0 5285,"Nucleus supravestibularis","Macaca mulatta","Latin",,"Nucleus supravestibularis",0 5277,"Nucleus tangentialis (Riley)","human","Latin","supraoptic nucleus",,0 4555,"Nucleus tangentialis (Winkler)","human","Latin",,"Nucleus tangentialis (Winkler)",0 3916,"Nucleus tegmentalis anterior","Macaca mulatta","Latin",,"Nucleus tegmentalis anterior",0 3920,"Nucleus tegmentalis anterior (Riley)","human","Latin",,"Nucleus subputaminalis",0 4392,"Nucleus tegmentalis centralis inferior","human","Latin","inferior central nucleus",,0 4261,"Nucleus tegmenti dorsale","human","Latin","dorsal tegmental nucleus",,0 4821,"Nucleus tegmenti pedunculopontinus","human","Latin","pedunculopontine tegmental nucleus",,52 4822,"Nucleus tegmenti pedunculopontinus","Macaca mulatta","Latin","pedunculopontine tegmental nucleus",,52 5521,"Nucleus tegmenti ventralis","Macaca fascicularis","Latin","ventral tegmental nucleus",,1 3425,"Nucleus thalamicus anterior","human","Latin","ANTERIOR NUCLEAR GROUP",,0 3831,"Nucleus thalamicus anterodorsalis","human","Latin","anterodorsal nucleus",,0 3844,"Nucleus thalamicus anteromedialis","human","Latin","anteromedial nucleus",,0 3870,"Nucleus thalamicus anteroprincipalis","human","Latin","anteroventral nucleus",,0 3859,"Nucleus thalamicus anteroventralis","human","Latin","anteroventral nucleus",,0 4377,"Nucleus thalamicus mediodorsalis","human","Latin","MEDIAL DORSAL NUCLEUS",,0 5431,"Nucleus thalamicus posteromedialis, pars inferior","human","Latin","ventral posteroinferior nucleus",,0 3566,"Nucleus thalamicus reticularis","human","Latin","thalamic reticular nucleus",,0 5326,"Nucleus thalamicus ventralis anterior, pars magnocellularis","human","Latin","magnocellular part of ventral anterior nucleus",,0 4251,"Nucleus thoracicus of Clarke","human","Latin",,"dorsal nucleus of Clarke",0 613,"Nucleus tracti solitarii","Macaca nemestrina","Latin","SOLITARY NUCLEUS",,1 -1367283799,"Nucleus tracti spinalis nervi trigemini","Macaca nemestrina","Latin",,"SPINAL TRIGEMINAL NUCLEUS",0 4572,"Nucleus tractus mesencephalici nervi trigemini","Macaca fascicularis","Latin","mesencephalic nucleus of trigeminal nerve",,2 4571,"Nucleus tractus mesencephalici nervi trigemini","Macaca fuscata","Latin","mesencephalic nucleus of trigeminal nerve",,2 4573,"Nucleus tractus mesencephalicus nervi trigemini","Macaca mulatta","Latin","mesencephalic nucleus of trigeminal nerve",,0 4687,"Nucleus tractus optici","Unspecified","Latin","nucleus of optic tract",,2 7042,"Nucleus tractus peduncularis transversus","human","Latin",,"nucleus of transverse peduncular tract",0 609,"Nucleus tractus solitarii","Macaca fascicularis","Latin","SOLITARY NUCLEUS",,765 1394163599,"Nucleus tractus spinalis nervi trigemini","Macaca fascicularis","Latin",,"SPINAL TRIGEMINAL NUCLEUS",14 4231,"Nucleus trapezoidalis","Macaca fascicularis","Latin","trapezoid nuclei",,0 5294,"Nucleus triangularis septi","human","Latin","triangular septal nucleus",,7 5295,"Nucleus triangularis septi","Macaca fascicularis","Latin","triangular septal nucleus",,7 3577,"Nucleus tuberis","human","Latin","lateral tuberal nuclei",,22 3572,"Nucleus tuberis hypothalami","Macaca mulatta","Latin",,"tuberal nuclei",0 3580,"Nucleus tuberis lateralis","human","Latin",,"lateral tuberal nucleus",5 3582,"Nucleus tuberis medialis","human","Latin",,"medial tuberal nucleus",0 5309,"Nucleus tuberomamillaris","human","Latin","tuberomammillary nucleus",,5 5310,"Nucleus tuberomamillaris hypothalami","Macaca fuscata","Latin","tuberomammillary nucleus",,0 4241,"Nucleus vagalis dorsalis","human","Latin","dorsal motor nucleus of vagus nerve",,0 3807,"Nucleus ventralis anterior","human","Latin","VENTRAL ANTERIOR NUCLEUS",,22 3809,"Nucleus ventralis anterior","Macaca mulatta","Latin","VENTRAL ANTERIOR NUCLEUS",,22 3808,"Nucleus ventralis anterior","Macaca mulatta","Latin","VENTRAL ANTERIOR NUCLEUS",,22 5338,"Nucleus ventralis anterior (Dewulf)","human","Latin","parvicellular part of ventral anterior nucleus",,0 3811,"Nucleus ventralis anterior thalami","human","Latin","VENTRAL ANTERIOR NUCLEUS",,4 3812,"Nucleus ventralis anterior thalami","Macaca fascicularis","Latin","VENTRAL ANTERIOR NUCLEUS",,4 5317,"Nucleus ventralis anterior, pars magnocellularis","Macaca mulatta","Latin","magnocellular part of ventral anterior nucleus",,0 5333,"Nucleus ventralis anterior, pars parvocellularis","Macaca mulatta","Latin","parvicellular part of ventral anterior nucleus",,0 5453,"Nucleus ventralis caudalis lateralis","Macaca","Latin","caudal part of ventral posterolateral nucleus",,0 5341,"Nucleus ventralis corporis trapezoidei","human","Latin",,"Nucleus ventralis corporis trapezoidei",0 5369,"Nucleus ventralis corporis trapezoidei","human","Latin",,"Nucleus ventralis corporis trapezoidei",0 4071,"Nucleus ventralis intermedius","human","Latin","VENTRAL LATERAL NUCLEUS",,32 4072,"Nucleus ventralis intermedius","human","Latin","VENTRAL LATERAL NUCLEUS",,32 5470,"Nucleus ventralis intermedius (Dewulf)","human","Latin","oral part of ventral posterolateral nucleus",,0 5468,"Nucleus ventralis intermedius (Walker)","Macaca mulatta","Latin","oral part of ventral posterolateral nucleus",,0 5462,"Nucleus ventralis intermedius thalami","Macaca mulatta","Latin","oral part of ventral posterolateral nucleus",,1 5461,"Nucleus ventralis intermedius thalami","Macaca fuscata","Latin","oral part of ventral posterolateral nucleus",,1 4061,"Nucleus ventralis lateralis","human","Latin","VENTRAL LATERAL NUCLEUS",,45 4152,"Nucleus ventralis lateralis (Walker)","Macaca mulatta","Latin",,"Nucleus ventralis lateralis (Walker)",0 4062,"Nucleus ventralis lateralis thalami","human","Latin","VENTRAL LATERAL NUCLEUS",,4 4063,"Nucleus ventralis lateralis thalami","Macaca fascicularis","Latin","VENTRAL LATERAL NUCLEUS",,4 5387,"Nucleus ventralis lateralis thalami, pars medialis","Macaca fascicularis","Latin","medial part of ventral lateral nucleus",,0 5399,"Nucleus ventralis lateralis thalami, pars postrema","Macaca fuscata","Latin","pars postrema of ventral lateral nucleus",,0 5374,"Nucleus ventralis lateralis, pars caudalis","Macaca mulatta","Latin","caudal part of ventral lateral nucleus",,0 5373,"Nucleus ventralis lateralis, pars caudalis","human","Latin","caudal part of ventral lateral nucleus",,0 5386,"Nucleus ventralis lateralis, pars medialis","Macaca mulatta","Latin","medial part of ventral lateral nucleus",,0 5385,"Nucleus ventralis lateralis, pars medialis","human","Latin","medial part of ventral lateral nucleus",,0 4078,"Nucleus ventralis lateralis, pars oralis","Macaca fascicularis","Latin","oral part of ventral lateral nucleus",,0 4077,"Nucleus ventralis lateralis, pars oralis","Macaca mulatta","Latin","oral part of ventral lateral nucleus",,0 5397,"Nucleus ventralis lateralis, pars postrema","Macaca mulatta","Latin","pars postrema of ventral lateral nucleus",,0 5405,"Nucleus ventralis medialis","human","Latin",,"Nucleus ventralis medialis",13 5330,"Nucleus ventralis oralis, pars medialis (Dewulf)","human","Latin",,"Nucleus ventralis oralis, pars medialis (Dewulf)",0 1296,"Nucleus ventralis oralis, pars posterior (Dewulf)","human","Latin","area X",,0 5420,"Nucleus ventralis posterior","human","Latin","VENTRAL POSTERIOR NUCLEUS",,26 5424,"Nucleus ventralis posterior inferior","Macaca mulatta","Latin","ventral posteroinferior nucleus",,1 5425,"Nucleus ventralis posterior inferior thalami","Macaca fascicularis","Latin","ventral posteroinferior nucleus",,0 5437,"Nucleus ventralis posterior lateralis thalami","Macaca fascicularis","Latin","VENTRAL POSTEROLATERAL NUCLEUS",,0 5448,"Nucleus ventralis posterior lateralis, pars caudalis","Macaca mulatta","Latin","caudal part of ventral posterolateral nucleus",,0 5460,"Nucleus ventralis posterior lateralis, pars oralis","Macaca mulatta","Latin","oral part of ventral posterolateral nucleus",,0 5486,"Nucleus ventralis posterior medialis thalami","Macaca fascicularis","Latin","VENTRAL POSTEROMEDIAL NUCLEUS",,0 5503,"Nucleus ventralis posterior medialis, pars parvocellularis","Macaca fascicularis","Latin","parvicellular part of ventral posteromedial nucleus",,0 5502,"Nucleus ventralis posterior medialis, pars parvocellularis","Macaca mulatta","Latin","parvicellular part of ventral posteromedial nucleus",,0 5455,"Nucleus ventralis posterior pars lateralis (Dewulf)","human","Latin","caudal part of ventral posterolateral nucleus",,0 5436,"Nucleus ventralis posterolateralis","human","Latin","VENTRAL POSTEROLATERAL NUCLEUS",,56 5452,"Nucleus ventralis posterolateralis (Walker)","Macaca mulatta","Latin","caudal part of ventral posterolateral nucleus",,0 5443,"Nucleus ventralis posterolateralis thalami","human","Latin","VENTRAL POSTEROLATERAL NUCLEUS",,1 5484,"Nucleus ventralis posteromedialis","human","Latin","VENTRAL POSTEROMEDIAL NUCLEUS",,33 5485,"Nucleus ventralis posteromedialis","Macaca mulatta","Latin","VENTRAL POSTEROMEDIAL NUCLEUS",,33 5494,"Nucleus ventralis posteromedialis thalami","human","Latin","VENTRAL POSTEROMEDIAL NUCLEUS",,0 5511,"Nucleus ventralis posteromedialis, pars principalis","Unspecified","Latin","principal part of ventral posteromedial nucleus",,0 5516,"Nucleus ventralis raphae","Macaca fascicularis","Latin",,"Nucleus ventralis raphae",0 5519,"Nucleus ventralis tegmenti","human","Latin","ventral tegmental nucleus",,4 5520,"Nucleus ventralis tegmenti (Gudden)","Macaca fuscata","Latin","ventral tegmental nucleus",,0 3810,"Nucleus ventralis thalami anterior","Macaca nemestrina","Latin","VENTRAL ANTERIOR NUCLEUS",,0 4065,"Nucleus ventralis thalami lateralis","Macaca nemestrina","Latin","VENTRAL LATERAL NUCLEUS",,0 5438,"Nucleus ventralis thalami posterior lateralis","Macaca nemestrina","Latin","VENTRAL POSTEROLATERAL NUCLEUS",,0 5368,"Nucleus ventrocaudalis anterior externus (Hassler)","human","Latin",,"Nucleus ventrocaudalis anterior externus (Hassler)",0 5367,"Nucleus ventrocaudalis anterior externus (Hassler)","human","Latin",,"Nucleus anteroreuniens (Hassler)",0 5366,"Nucleus ventrocaudalis anterior externus (Hassler)","human","Latin",,"Nucleus ventrocaudalis anterior externus (Hassler)",0 5497,"Nucleus ventrocaudalis anterior internus (Hassler)","human","Latin","VENTRAL POSTEROMEDIAL NUCLEUS",,0 5454,"Nucleus ventrocaudalis externus (Van Buren)","human","Latin","caudal part of ventral posterolateral nucleus",,0 5429,"Nucleus ventrocaudalis parvocellularis externus (Hassler)","human","Latin","ventral posteroinferior nucleus",,0 5481,"Nucleus ventrocaudalis posterior externus (Hassler)","human","Latin",,"ventral posterior lateral nucleus, posterior division",0 5471,"Nucleus ventrointermedius","human","Latin","oral part of ventral posterolateral nucleus",,7 5360,"Nucleus ventrointermedius externus (Hassler)","human","Latin",,"Nucleus ventrointermedius externus (Hassler)",0 5358,"Nucleus ventrointermedius internus (Hassler)","human","Latin",,"Nucleus ventrointermedius internus (Hassler)",0 4064,"Nucleus ventrolateralis thalami","human","Latin","VENTRAL LATERAL NUCLEUS",,5 5541,"Nucleus ventromedialis hypothalami","Macaca fascicularis","Latin","ventromedial nucleus of hypothalamus",,21 5351,"Nucleus ventrooralis anterior (Hassler)","human","Latin",,"ventrolateral anterior nucleus",0 4086,"Nucleus ventrooralis externus, anterior part (Van Buren)","human","Latin","oral part of ventral lateral nucleus",,0 1294,"Nucleus ventrooralis internus (Hassler)","human","Latin","area X",,0 1295,"Nucleus ventro-oralis internus (Hassler)","human","Latin","area X",,0 1298,"Nucleus ventrooralis internus, superior part","human","Latin","area X",,0 5393,"Nucleus ventrooralis medialis (Hassler)","human","Latin","medial part of ventral lateral nucleus",,0 5354,"Nucleus ventrooralis posterior (Hassler)","human","Latin",,"ventrolateral posterior nucleus",0 5353,"Nucleus ventro-oralis posterior (Hassler)","human","Latin",,"ventrolateral posterior nucleus",0 5549,"Nucleus vestibularis caudalis","human","Latin","inferior vestibular nucleus",,1 5548,"Nucleus vestibularis inferior","Macaca fascicularis","Latin","inferior vestibular nucleus",,0 5547,"Nucleus vestibularis inferior","human","Latin","inferior vestibular nucleus",,0 4428,"Nucleus vestibularis interstitialis","Unspecified","Latin","interstitial nucleus of vestibular nerve",,0 5557,"Nucleus vestibularis lateralis","human","Latin","lateral vestibular nucleus",,14 5558,"Nucleus vestibularis lateralis","Macaca fascicularis","Latin","lateral vestibular nucleus",,14 5560,"Nucleus vestibularis magnocellularis","Macaca mulatta","Latin","lateral vestibular nucleus",,5 5565,"Nucleus vestibularis medialis","human","Latin","medial vestibular nucleus",,12 5566,"Nucleus vestibularis medialis","Macaca fascicularis","Latin","medial vestibular nucleus",,12 5578,"Nucleus vestibularis rostralis","human","Latin","superior vestibular nucleus",,0 5577,"Nucleus vestibularis superior","Macaca fascicularis","Latin","superior vestibular nucleus",,5 5576,"Nucleus vestibularis superior","human","Latin","superior vestibular nucleus",,5 5110,"Nucleus Westphal-Edinger","Macaca fascicularis","Latin","parvocellular oculomotor nucleus",,0 5365,"Nucleus zentrolateralis caudalis externus (Hassler)","human","Latin",,"Nucleus zentrolateralis caudalis externus (Hassler)",0 5364,"Nucleus zentrolateralis caudalis internus (Hassler)","human","Latin",,"Nucleus zentrolateralis caudalis internus (Hassler)",0 5363,"Nucleus zentrolateralis intermedius externus (Hassler)","human","Latin",,"Nucleus zentrolateralis intermedius externus (Hassler)",0 5362,"Nucleus zentrolateralis intermedius internus (Hassler)","human","Latin",,"Nucleus zentrolateralis intermedius internus (Hassler)",0 5582,"Nucleus zona incertae caudalis","human","Latin",,"caudal nucleus of zona incerta",0 5583,"obex","human","English","obex",,578 5584,"Obex","human","Latin","obex",,578 68,"occipital cortex","human","English","OCCIPITAL LOBE",,1368 1124,"occipital eye centers","human","English",,"occipital eye fields",0 1123,"occipital eye fields","human","English",,"occipital eye fields",0 995476063,"occipital forceps","human","English","posterior forceps of corpus callosum",,0 2711,"occipital gyrus","Macaca mulatta","English","occipital gyrus (M)",,34 1647,"occipital horn of lateral ventricle","Macaca fascicularis","English","occipital horn of lateral ventricle",,0 1646,"occipital horn of lateral ventricle","human","English","occipital horn of lateral ventricle",,0 66,"occipital lobe","Macaca fascicularis","English","OCCIPITAL LOBE",,3473 65,"occipital lobe","human","English","OCCIPITAL LOBE",,3473 64,"occipital lobe (Ono)","human","English",,"occipital lobe (Ono)",0 63,"occipital lobe (Ono)","human","English",,"occipital lobe (Ono)",0 966442063,"occipital lobe white matter","Unspecified","English","OCCIPITAL LOBE WHITE MATTER",,0 2905,"occipital notch","human","English","preoccipital notch",,0 5741,"occipital peduncle","human","English","posterior thalamic peduncle",,0 5794,"occipital pole","human","English","occipital pole",,90 1048,"occipital region","human","English",,"occipital region",421 69,"occipital region","rat","English","OCCIPITAL LOBE",,420 5739,"occipital thalamic peduncle","human","English","posterior thalamic peduncle",,0 -956639434,"occipital white matter","Unspecified","English","occipital white matter",,0 1666282249,"occipital white matter - not otherwise specified","Unspecified","English","OCCIPITAL LOBE WHITE MATTER - not otherwise specified",,0 1125,"occipitoparietal eye fields","human","English",,"occipital eye fields",0 2204,"occipitopontine fibers","human","English",,"occipitopontine fibers",0 2206,"occipitopontine tract","human","English",,"occipitopontine fibers",0 922,"occipitotemporal area 37","human","English",,"occipitotemporal area 37 (H)",0 2663,"occipitotemporal gyrus","human","English","fusiform gyrus",,13 6589,"occipitotemporal sulcus","Macaca mulatta","English","occipitotemporal sulcus",,13 6588,"occipitotemporal sulcus","Macaca mulatta","English","occipitotemporal sulcus",,13 6587,"occipitotemporal sulcus","human","English","occipitotemporal sulcus",,13 6591,"occipito-temporal sulcus","Macaca fascicularis","English","occipitotemporal sulcus",,1 283,"ocular nerves","human","English",,"ocular nerves",0 272,"oculomotor nerve","human","English","oculomotor nerve",,2072 273,"oculomotor nerve","Macaca fascicularis","English","oculomotor nerve",,0 281,"oculomotor nerve (inferior branch)","human","English",,"inferior division of oculomotor nerve",0 285,"oculomotor nerve fibers","Macaca fascicularis","English","oculomotor nerve fibers",,3 284,"oculomotor nerve fibers","human","English","oculomotor nerve fibers",,3 280,"oculomotor nerve, inferior ramus","human","English",,"inferior division of oculomotor nerve",0 326,"oculomotor nuclear complex","Macaca fascicularis","English","OCULOMOTOR NUCLEAR COMPLEX",,33 325,"oculomotor nuclear complex","human","English","OCULOMOTOR NUCLEAR COMPLEX",,33 330,"oculomotor nucleus","Macaca fascicularis","English","OCULOMOTOR NUCLEAR COMPLEX",,364 331,"oculomotor nucleus","rat","English","OCULOMOTOR NUCLEAR COMPLEX",,364 5115,"oculomotor nucleus, parvocellular part","rat","English","parvocellular oculomotor nucleus",,0 4598,"oculomotor sulcus","Unspecified","English","oculomotor sulcus",,0 1140,"olfactory area","human","English",,"primary olfactory areas",38 -298107745,"olfactory area (Carpenter)","human","English","anterior perforated substance",,0 6196,"olfactory area (Mai)","human","English","anterior perforated substance",,0 3896,"olfactory area (Roberts)","human","English","nucleus of diagonal band",,0 5973,"olfactory brain","human","English",,"rhinencephalon",23 1364,"olfactory bulb","rat","English","olfactory bulb",,6180 1363,"olfactory bulb","human","English","olfactory bulb",,6180 1141,"olfactory cortex","human","English",,"primary olfactory areas",457 1154,"olfactory entorhinal cortex","Macaca","English",,"olfactory entorhinal cortex",0 3883,"olfactory fasciculus","human","English","diagonal band",,0 1566,"olfactory limb of anterior commissure","rat","English","anterior part of anterior commissure",,0 1565,"olfactory limb of anterior commissure","human","English","anterior part of anterior commissure",,0 5974,"olfactory lobe","human","English",,"rhinencephalon",101 1367,"olfactory lobe (Barr & Kiernan)","human","English","olfactory bulb",,0 3280,"olfactory nerve","human","English","olfactory nerve",,1157 1564,"olfactory part of anterior commissure","human","English","anterior part of anterior commissure",,0 3786,"olfactory peduncle","human","English",,"olfactory stalk",52 3885,"olfactory radiations of Zuckerkandl","human","English","diagonal band",,0 3785,"olfactory stalk","human","English",,"olfactory stalk",0 6473,"olfactory sulcus","Macaca mulatta","English","olfactory sulcus",,8 6472,"olfactory sulcus","human","English","olfactory sulcus",,8 3780,"olfactory tract","Macaca fascicularis","English","olfactory tract",,583 3779,"olfactory tract","human","English","olfactory tract",,583 6970,"olfactory trigone","human","English","olfactory trigone",,4 6190,"olfactory tubercle","rat","English","anterior perforated substance",,1234 763,"olfactory ventricle","human","English",,"olfactory ventricle",0 637,"Oliva","human","Latin","inferior olive",,1106 585,"Oliva superior","human","Latin","SUPERIOR OLIVE",,3 -402273866,"Oliva superior - not otherwise specified","Unspecified","Latin","SUPERIOR OLIVE - not otherwise specified",,3 638,"olivary eminence","human","English","inferior olive",,0 4648,"olivary nucleus of superior colliculus","human","English","olivary pretectal nucleus",,0 4645,"olivary pretectal nucleus","rat","English","olivary pretectal nucleus",,69 4644,"olivary pretectal nucleus","Macaca fascicularis","English","olivary pretectal nucleus",,69 640,"olive","human","English","inferior olive",,5674 6818,"olivocerebellar tract","human","English","olivocerebellar tract",,10 6819,"olivocerebellar tract","rat","English","olivocerebellar tract",,10 5716,"olivocochlear bundle","human","English","olivocochlear bundle",,136 5719,"olivocochlear bundle of Rasmussen","human","English","olivocochlear bundle",,0 7234,"olivospinal fibers","human","English",,"olivospinal tract",0 7232,"olivospinal tract","human","English",,"olivospinal tract",0 7233,"olivospinal tract of Helweg","human","English",,"olivospinal tract",0 2622,"opercular area 44","human","English",,"opercular area 44",0 2615,"opercular part of inferior frontal gyrus","human","English","opercular part of inferior frontal gyrus (H)",,0 -1032838534,"opercular part of inferior frontal gyrus (H)","human","English",,,0 2618,"opercular portion of inferior frontal gyrus","human","English","opercular part of inferior frontal gyrus (H)",,0 -1781725097,"opercular region","Macaca mulatta","English",,"opercular region",0 5586,"Operculum frontale","human","Latin","frontal operculum",,0 5590,"Operculum orbitale","human","Latin","orbital operculum",,0 5594,"Operculum parietale","human","Latin","parietal operculum",,0 5596,"Operculum precentrale","human","Latin","precentral operculum",,0 5599,"Operculum temporale","human","Latin","temporal operculum",,1 1474,"optic chiasm","Macaca fascicularis","English","optic chiasm",,2095 1475,"optic chiasm","rat","English","optic chiasm",,2095 1473,"optic chiasm","human","English","optic chiasm",,2095 1478,"optic chiasma","Macaca fascicularis","English","optic chiasm",,208 6018,"optic layer","human","English","superficial white layer of superior colliculus",,38 4685,"optic lemniscus","human","English","optic tract",,0 1469,"optic nerve","human","English","optic nerve",,14119 5871,"optic radiation","human","English",,"geniculocalcarine radiation",124 5876,"optic radiations","human","English",,"geniculocalcarine radiation",92 5919,"optic recess","Macaca fascicularis","English","optic recess",,21 5918,"optic recess","human","English","optic recess",,21 389,"optic tectum","human","English","SUPERIOR COLLICULUS",,1558 4682,"optic tract","rat","English","optic tract",,1405 4681,"optic tract","Macaca fascicularis","English","optic tract",,1405 4680,"optic tract","human","English","optic tract",,1405 4973,"oral nuclear group of pulvinar","human","English","oral pulvinar nucleus",,0 4977,"oral part of pulvinar","human","English","oral pulvinar nucleus",,0 -1785014033,"oral part of spinal trigeminal nucleus","Macaca fascicularis","English","oral part of spinal trigeminal nucleus",,0 1657937850,"oral part of spinal trigeminal nucleus","human","English","oral part of spinal trigeminal nucleus",,0 4076,"oral part of ventral lateral nucleus","Macaca fascicularis","English","oral part of ventral lateral nucleus",,1 4075,"oral part of ventral lateral nucleus","human","English","oral part of ventral lateral nucleus",,1 5458,"oral part of ventral posterolateral nucleus","human","English","oral part of ventral posterolateral nucleus",,0 5459,"oral part of ventral posterolateral nucleus","Macaca fascicularis","English","oral part of ventral posterolateral nucleus",,0 5046,"oral pontine reticular nucleus","human","English","oral pontine reticular nucleus",,23 5047,"oral pontine reticular nucleus","Macaca fascicularis","English","oral pontine reticular nucleus",,23 4974,"oral portion of pulvinar","human","English","oral pulvinar nucleus",,0 4968,"oral pulvinar nucleus","human","English","oral pulvinar nucleus",,2 4969,"oral pulvinar nucleus","Macaca fascicularis","English","oral pulvinar nucleus",,2 2568,"orbital area","human","English","ORBITAL GYRI",,66 2744,"orbital area 47","human","English",,"orbital area 47",0 2567,"orbital cortex","human","English","ORBITAL GYRI",,151 2562,"orbital gyri","human","English","ORBITAL GYRI",,10 5589,"orbital operculum","human","English","orbital operculum",,0 2740,"orbital part of inferior frontal gyrus","human","English","orbital part of inferior frontal gyrus (H)",,0 6477,"orbital sulci","human","English","orbital sulcus (H)",,3 6475,"orbital sulcus","human","English","orbital sulcus (H)",,7 2217,"orbitofrontal fibers","human","English",,"orbitofrontal fibers",0 2564,"orbitofrontal gyri","human","English","ORBITAL GYRI",,2 2565,"orbitofrontal gyrus","human","English","ORBITAL GYRI",,3 6483,"orbito-frontal sulcus","Macaca mulatta","English","fronto-orbital sulcus",,0 6268,"orbitoinsular groove","Macaca mulatta","English",,"orbitoinsular sulcus (M)",0 6267,"orbitoinsular sulcus","Macaca mulatta","English",,"orbitoinsular sulcus (M)",0 6266,"orbitoinsular sulcus","Papio","English",,"orbitoinsular sulcus (M)",0 5606,"Organum subcommissurale","Macaca fascicularis","Latin","subcommissural organ",,0 5611,"Organum subfornicale","human","Latin","subfornical organ",,5 5612,"Organum subfornicale","Macaca fascicularis","Latin","subfornical organ",,5 5626,"Organum vasculosum of lamina terminalis","human","Latin","supraoptic crest",,5 5614,"Organum vasculosum subfornicale","human","Latin","subfornical organ",,0 5997,"outer gray layer of superior colliculus","human","English","superficial gray layer of superior colliculus",,0 2995,"outer medullary lamina","human","English","lateral medullary lamina",,0 7237,"oval area of Flechsig","human","English",,"septomarginal fasciculus",0 5627,"OVLT","human","Abbreviation","supraoptic crest",,0 3551,"P (Carpenter)","human","Abbreviation","PULVINAR",,0 645,"Pachymeninx","human","Latin",,"dura mater",4 522,"Palaeocerebellum","human","Latin","ANTERIOR LOBE OF CEREBELLUM",,0 5631,"Palaeocortex","Cercocebus torquatus","Latin",,"paleocortex",3 5632,"Palaeocortex","galago","Latin",,"paleocortex",3 5630,"Palaeocortex","human","Latin",,"paleocortex",3 7260,"Palaeocortex I","human","Latin",,"semicortex",0 5815,"Palaeocortex II","human","Latin","prepyriform area",,0 521,"Paleocerebellum","human","Latin","ANTERIOR LOBE OF CEREBELLUM",,13 520,"Paleocerebellum","human","Latin","ANTERIOR LOBE OF CEREBELLUM",,13 524,"paleocerebellum (Crosby)","human","English",,"paleocerebellum (Crosby)",0 5629,"Paleocortex","human","Latin",,"paleocortex",57 5976,"paleocortex (Carpenter)","human","English",,"rhinencephalon",0 5633,"paleocortex (Zilles)","human","English",,"paleocortex (Zilles)",0 4224,"paleodentate part of dentate nucleus","human","English","paleodentate part of dentate nucleus",,0 4226,"paleodentate portion of dentate nucleus","human","English","paleodentate part of dentate nucleus",,0 -744578135,"paleopallium","human","Latin",,"rhinencephalon",0 5667,"paleoruber","human","English","magnocellular part of red nucleus",,0 2513,"paleostriatum","human","English","GLOBUS PALLIDUS",,157 5634,"Paleothalamus","human","Latin",,"Paleothalamus",1 3602,"pallidal channel of motor nucleus","human","English",,"anteromedial region of motor thalamus",0 3603,"pallidal channel of motor nucleus","Macaca","English",,"anteromedial region of motor thalamus",0 1381,"pallidohabenular bundle","human","English","pallidohabenular bundle",,0 6823,"pallidohypothalamic fasciculus","human","English",,"pallidohypothalamic fasciculus",0 6827,"pallidohypothalamic fibers","human","English",,"pallidohypothalamic fasciculus",0 6829,"pallidohypothalamic nucleus","human","English",,"pallidohypothalamic nucleus",0 6756,"pallidonigral fibers","human","English",,"pallidonigral fibers",0 6757,"pallidonigral tract","human","English",,"pallidonigral fibers",0 6758,"pallidonigral tract of Jakob","human","English",,"pallidonigral fibers",0 6759,"pallidosubthalamic fibers","human","English",,"pallidosubthalamic fibers",0 6760,"pallidosubthalamic tract","human","English",,"pallidosubthalamic fibers",0 2063,"pallidotegmental fasciculus","human","English","pallidotegmental fasciculus",,0 6761,"pallidotegmental fibers","human","English",,"pallidotegmental fibers",0 2065,"pallidotegmental tract","human","English","pallidotegmental fasciculus",,0 6762,"pallidotegmental tract","human","English",,"pallidotegmental fibers",0 6763,"pallidotegmental tract of Jakob","human","English",,"pallidotegmental fibers",0 6765,"pallidothalamic fibers","human","English",,"pallidothalamic fibers",8 6766,"pallidothalamic tract","human","English",,"pallidothalamic fibers",0 2514,"pallidum","human","English","GLOBUS PALLIDUS",,3179 2539,"Pallidum ventrale","human","Latin",,"ventral pallidum",0 2534,"Pallidus I","human","Latin","medial globus pallidus",,4 2524,"Pallidus II","human","Latin","lateral globus pallidus",,4 49,"Pallium","human","Latin","CEREBRAL CORTEX",,221 3115,"Papez circuit","human","English",,"Papez circuit",32 1205,"para-amygdaloid cortex","human","English","periamygdaloid area",,0 3619,"parabducens nucleus","human","English",,"parabducens nucleus",0 1173,"parabigeminal area","human","English",,"parabigeminal area",0 4219,"parabigeminal area (Mai)","human","English","cuneiform nucleus",,0 1695,"parabigeminal nucleus","rat","English","parabigeminal nucleus",,103 1694,"parabigeminal nucleus","Macaca fascicularis","English","parabigeminal nucleus",,103 1693,"parabigeminal nucleus","human","English","parabigeminal nucleus",,103 4702,"parabrachial pigmented nucleus","human","English",,"parabrachial pigmented nucleus",0 3129,"paracentral gyrus","human","English",,"paracentral lobule",5 3127,"paracentral lobule","human","English",,"paracentral lobule",22 4707,"paracentral nucleus","Macaca fascicularis","English","paracentral nucleus",,14 4706,"paracentral nucleus","human","English","paracentral nucleus",,14 4714,"paracentral nucleus of thalamus","human","English","paracentral nucleus",,0 4713,"paracentral nucleus of thalamus","human","English","paracentral nucleus",,0 4715,"paracentral nucleus of thalamus","rat","English","paracentral nucleus",,0 6496,"paracentral sulcus","human","English","paracentral sulcus (H)",,2 6495,"paracentral sulcus","human","English","paracentral sulcus (H)",,2 4710,"paracentral thalamic nucleus","human","English","paracentral nucleus",,2 4711,"paracentral thalamic nucleus","rat","English","paracentral nucleus",,2 1279,"paracommissural area","human","English",,"precommissural septum",0 4719,"parafascicular nucleus","rat","English","parafascicular nucleus",,168 4717,"parafascicular nucleus","human","English","parafascicular nucleus",,168 4718,"parafascicular nucleus","Macaca fascicularis","English","parafascicular nucleus",,168 4725,"parafascicular thalamic nucleus","rat","English","parafascicular nucleus",,24 4724,"parafascicular thalamic nucleus","human","English","parafascicular nucleus",,24 5635,"paraflocculus","human","English","paraflocculus",,195 5636,"paraflocculus","Macaca fascicularis","English","paraflocculus",,195 5637,"paraflocculus","rat","English","paraflocculus",,195 5639,"Paraflocculus","Macaca nemestrina","Latin","paraflocculus",,195 5638,"Paraflocculus","human","Latin","paraflocculus",,195 5641,"Paraflocculus (cerebelli)","Macaca fascicularis","Latin","paraflocculus",,0 5651,"paraflocculus (Crosby)","human","English",,"paraflocculus (Crosby)",0 6697,"Paraflocculus ventralis","human","Latin","cerebellar tonsil",,0 5643,"paraflocculus-1","human","English","paraflocculus",,85 5652,"paraflocculus-2","human","English",,"paraflocculus (Crosby)",76 4729,"parafornical nucleus","human","English",,"parafornical nucleus",0 5034,"paragigantocellular nucleus, dorsal part","rat","English","dorsal paragigantocellular nucleus",,0 5029,"paragigantocellular nucleus, lateral part","rat","English","lateral paragigantocellular nucleus",,0 2749,"parahippocampal gyrus","Macaca fascicularis","English","PARAHIPPOCAMPAL GYRUS",,432 2748,"parahippocampal gyrus","human","English","PARAHIPPOCAMPAL GYRUS",,432 2758,"parahippocampal gyrus (Insausti)","Old World monkeys","English","posterior parahippocampal gyrus",,0 6304,"parahippocampal ramus","human","English",,"parahippocampal ramus (H)",0 -1722902308,"parahippocampal white matter","Unspecified","English","PARAHIPPOCAMPAL WHITE MATTER",,0 2439,"parahypoglossal gray","human","English",,"parahypoglossal gray",0 2440,"parahypoglossal nuclei","human","English",,"parahypoglossal gray",0 947,"parainsular area 52","human","English",,"parainsular area 52 (H)",0 3765,"paralamellar basolateral nucleus","Macaca fascicularis","English",,"paralaminar nucleus of amygdala",0 3761,"paralaminar nucleus of amygdala","Macaca fascicularis","English",,"paralaminar nucleus of amygdala",0 4528,"paralaminar part of dorsomedial nucleus","human","English","paralaminar part of medial dorsal nucleus",,0 4526,"paralaminar part of medial dorsal nucleus","Macaca fascicularis","English","paralaminar part of medial dorsal nucleus",,0 4731,"paralemniscal gray","human","English",,"paralemniscal gray",0 1228,"paralimbic association cortex","Macaca mulatta","English",,"paralimbic association cortex",0 1227,"paralimbic association cortex","human","English",,"paralimbic association cortex",0 -1187896319,"paralimbic brain","primate","English",,"paralimbic brain",0 1432959534,"paralimbic region","primate","English",,"paralimbic brain",0 6622,"parallel sulcus","human","English","superior temporal sulcus",,0 2468,"paramedian group (medullary reticular formation)","human","English","PARAMEDIAN MEDULLARY RETICULAR GROUP",,0 3139,"paramedian lobule","human","English","gracile lobule",,156 3140,"paramedian lobule","rat","English","gracile lobule",,156 -806120658,"paramedian lobule (Carpenter)","human","English",,"paramedian lobule (Carpenter)",0 2466,"paramedian medullary reticular group","Macaca fascicularis","English","PARAMEDIAN MEDULLARY RETICULAR GROUP",,0 2465,"paramedian medullary reticular group","human","English","PARAMEDIAN MEDULLARY RETICULAR GROUP",,0 2452,"paramedian pontine reticular formation","human","English",,"paramedian pontine reticular formation",117 4753,"paramedian reticular nucleus","rat","English","ventral paramedian reticular nucleus",,54 3141,"paramedian zone of cerebellum","human","English",,"paramedian zone of cerebellum",0 4756,"paranigral nucleus","Macaca mulatta","English",,"paranigral nucleus",14 6515,"paraolfactory sulcus","human","English","anterior parolfactory sulcus (H)",,0 5278,"paraoptic nucleus","human","English",,"paraoptic nucleus",0 242,"Paraphysis","human","Latin",,"Paraphysis",18 243,"Paraphysis cerebri","human","Latin",,"Paraphysis",3 1546092137,"parasagittal section","Unspecified","English",,"sagittal section",7 3130,"parasplenial lobules","human","English",,"parasplenial lobules",0 6362,"parasplenial lobules","human","English",,"parasplenial lobules",0 1182,"parastriate area","human","English",,"parastriate area 18",6 1175,"parastriate area 18","human","English",,"parastriate area 18",0 5826,"parasubicular area","human","English",,"parasubicular area",0 5829,"parasubiculum","human","English",,"parasubicular area",116 5830,"Parasubiculum","human","Latin",,"parasubicular area",116 4771,"paratenial nucleus","rat","English","paratenial nucleus",,11 4770,"paratenial nucleus","Macaca fascicularis","English","paratenial nucleus",,11 4769,"paratenial nucleus","human","English","paratenial nucleus",,11 4779,"paratenial thalamic nucleus","rat","English","paratenial nucleus",,2 4778,"paratenial thalamic nucleus","human","English","paratenial nucleus",,2 1253,"paraterminal body","human","English",,"septal area",1 156798553,"paraterminal body (Noback)","human","English","paraterminal gyrus",,0 2761,"paraterminal gyrus","Macaca fascicularis","English","paraterminal gyrus",,3 2759,"paraterminal gyrus","human","English","paraterminal gyrus",,3 2760,"paraterminal gyrus","human","English","paraterminal gyrus",,3 4782,"paratrigeminal nucleus","human","English","paratrigeminal nucleus",,47 4810,"paraventricular gray","human","English","paraventricular nucleus of thalamus",,2 4794,"paraventricular hypothalamic nucleus","human","English","paraventricular nucleus of hypothalamus",,3435 4795,"paraventricular hypothalamic nucleus","rat","English","paraventricular nucleus of hypothalamus",,3435 4811,"paraventricular nuclei","human","English","paraventricular nucleus of thalamus",,757 4792,"paraventricular nucleus of hypothalamus","human","English","paraventricular nucleus of hypothalamus",,20 4786,"paraventricular nucleus of hypothalamus","human","English","paraventricular nucleus of hypothalamus",,20 4788,"paraventricular nucleus of hypothalamus","rat","English","paraventricular nucleus of hypothalamus",,20 4787,"paraventricular nucleus of hypothalamus","Macaca fascicularis","English","paraventricular nucleus of hypothalamus",,20 4802,"paraventricular nucleus of thalamus","human","English","paraventricular nucleus of thalamus",,2 4803,"paraventricular nucleus of thalamus","Macaca fascicularis","English","paraventricular nucleus of thalamus",,2 4804,"paraventricular nucleus of thalamus","rat","English","paraventricular nucleus of thalamus",,2 4809,"paraventricular thalamic nucleus","rat","English","paraventricular nucleus of thalamus",,78 4808,"paraventricular thalamic nucleus","human","English","paraventricular nucleus of thalamus",,78 540,"paravermal cortex","human","English",,"paravermal cortex",15 527,"paravermal zone","human","English",,"intermediate zone of cerebellum",5 530,"paravermal zone of cerebellum","human","English",,"paravermal zone of cerebellum",0 528,"paravermis","human","English",,"intermediate zone of cerebellum",20 70518903,"parietal area 7 (M)","Cercopithecus","English",,"area 7 of Brodmann-09",0 59,"parietal cortex","human","English","PARIETAL LOBE",,2703 57,"parietal lobe","Macaca fascicularis","English","PARIETAL LOBE",,5056 56,"parietal lobe","human","English","PARIETAL LOBE",,5056 5593,"parietal operculum","human","English","parietal operculum",,61 60,"parietal region","rat","English","PARIETAL LOBE",,436 1046,"parietal region","human","English",,"parietal region",436 714,"parietal type cortex","human","English",,"parietal type cortex",0 206513731,"parietal white matter","Unspecified","English","PARIETAL WHITE MATTER",,70 -129680406,"parietal white matter - not otherwise specified","Unspecified","English","PARIETAL WHITE MATTER - not otherwise specified",,70 89,"parieto-occipital cortex","human","English",,"parieto-occipital cortex",78 1889,"parieto-occipital eminence","human","English","parieto-occipital eminence",,1 6504,"parieto-occipital fissure","human","English","parieto-occipital sulcus",,7 6503,"parieto-occipital incisure","Macaca mulatta","English","parieto-occipital sulcus",,0 6507,"parietooccipital sulcus","human","English","parieto-occipital sulcus",,7 6500,"parieto-occipital sulcus","Macaca mulatta","English","parieto-occipital sulcus",,25 6499,"parieto-occipital sulcus","human","English","parieto-occipital sulcus",,25 2200,"parietopontine fibers","human","English",,"parietopontine fibers",0 2202,"parietopontine tract","human","English",,"parietopontine fibers",0 94,"parietotemporal association cortex","human","English",,"parietotemporal association cortex",3 2066,"parietotemporo-occipitopontine tract","human","English",,"parietotemporo-occipitopontine tract",0 1267,"parolfactory area","human","English","subcallosal area",,3 1275,"parolfactory area (Crosby)","human","English",,"precommissural septum",0 1277,"parolfactory area of Broca","human","English",,"precommissural septum",0 1276,"parolfactory gyri","human","English",,"precommissural septum",0 1258,"parolfactory nuclei","human","English","SEPTAL NUCLEI",,0 344773449,"pars anterior lobuli quadrangularis","human","Latin","anterior quadrangular lobule",,0 5699,"Pars anterior pontis","human","Latin","BASAL PART OF PONS",,0 354,"Pars basalis mesencephali","human","Latin",,"basal part of midbrain",0 5692,"Pars basilaris pontis","Macaca fascicularis","Latin","BASAL PART OF PONS",,0 -548389284,"Pars basolateralis - not otherwise specified","Unspecified","Latin","BASOLATERAL NUCLEAR GROUP - not otherwise specified",,0 1331,"Pars basolateralis (Corpus amygdaloideum)","human","Latin","BASOLATERAL NUCLEAR GROUP",,0 1664,"Pars centralis (ventriculi lateralis)","human","Latin","body of lateral ventricle",,0 1668,"Pars centralis ventriculi lateralis","human","Latin","body of lateral ventricle",,0 6150,"pars compacta","human","English","pars compacta",,1420 6151,"pars compacta","Macaca fascicularis","English","pars compacta",,1420 6152,"Pars compacta","human","Latin","pars compacta",,1420 1336,"Pars corticomedialis (Corpus amygdaloideum)","human","Latin","CORTICOMEDIAL NUCLEAR GROUP",,0 2868,"Pars distalis (hypophysis)","human","Latin","distal part of hypophysis",,0 6674,"Pars dorsalis pontis","human","Latin","PONTINE TEGMENTUM",,451 2872,"Pars intermedia (hypophysis)","human","Latin","intermediate part of hypophysis",,0 529,"Pars intermedia of cerebellum","human","Latin",,"intermediate zone of cerebellum",0 1935,"Pars lateralis fasciculi dorsalis (Burdach)","Macaca mulatta","Latin",,"cuneate fasciculus",0 6169,"pars lateralis of substantia nigra","human","English",,"pars lateralis of substantia nigra",0 5663,"Pars magnocellularis (ruber)","human","Latin","magnocellular part of red nucleus",,0 -2099120270,"pars marginalis sulci cinguli","human","Latin","marginal sulcus (H)",,0 1952,"Pars medialis fasciculi dorsalis (Goll)","Macaca mulatta","Latin",,"gracile fasciculus",0 4222,"Pars neodentata","Unspecified","Latin","neodentate part of dentate nucleus",,0 1741,"Pars neo-encephalica pedunculi","human","Latin","cerebral crus",,0 2877,"Pars nervosa (hypophysis)","human","Latin","pars nervosa of hypophysis",,0 2876,"pars nervosa of hypophysis","human","English","pars nervosa of hypophysis",,0 1567,"Pars olfactoria commissurae anterioris","human","Latin","anterior part of anterior commissure",,0 2617,"Pars opercularis gyri frontalis inferioris","human","Latin","opercular part of inferior frontal gyrus (H)",,0 2742,"Pars orbitalis gyri frontalis inferioris","human","Latin","orbital part of inferior frontal gyrus (H)",,0 4225,"Pars paleodentata","Unspecified","Latin","paleodentate part of dentate nucleus",,0 5670,"Pars parvocellularis (ruber)","human","Latin","parvocellular part of red nucleus",,0 -2032472417,"pars posterior lobuli quadrangularis","human","Latin","simple lobule",,0 2878,"Pars posterior of hypophysis","human","Latin","pars nervosa of hypophysis",,0 2619,"Pars posterior of inferior frontal gyrus","human","Latin","opercular part of inferior frontal gyrus (H)",,0 6678,"Pars posterior pontis","human","Latin","PONTINE TEGMENTUM",,5 5396,"pars postrema of ventral lateral nucleus","Macaca fascicularis","English","pars postrema of ventral lateral nucleus",,0 6174,"Pars reticularis","human","Latin","pars reticulata",,31 6173,"pars reticulata","Macaca fascicularis","English","pars reticulata",,1140 6172,"pars reticulata","human","English","pars reticulata",,1140 6182,"Pars reticulata, subnucleus lateralis","Macaca mulatta","Latin",,"Pars reticulata, subnucleus lateralis",0 6183,"Pars reticulata, subnucleus medialis","Macaca mulatta","Latin",,"Pars reticulata, subnucleus medialis",0 5679,"Pars retrolenticularis capsulae internae","human","Latin","retrolenticular part of internal capsule",,0 5677,"Pars retrolentiformis (capsulae internae)","human","Latin","retrolenticular part of internal capsule",,0 5684,"Pars sublenticularis capsulae internae","human","Latin","sublenticular part of internal capsule",,0 5682,"Pars sublentiformis (capsulae internae)","human","Latin","sublenticular part of internal capsule",,0 5688,"Pars thalamolentiformes (capsulae internae)","human","Latin","lenticulothalamic part of internal capsule",,0 2628,"Pars triangularis gyri frontalis inferioris","human","Latin","triangular part of inferior frontal gyrus (H)",,0 2629,"Pars triangularis of frontal operculum (Ono)","human","Latin","triangular part of inferior frontal gyrus (H)",,0 2870,"Pars tuberalis (hypophysis)","human","Latin","tuberal part of hypophysis",,0 3299,"Pars vagalis of nervus accessorius","human","Latin","cranial part of accessory nerve",,0 5693,"Pars ventralis pontis","human","Latin","BASAL PART OF PONS",,0 2352,"part of folium-tuber vermis","rat","English","folium",,0 6983,"part of folium-tuber vermis","rat","English","tuber of vermis",,0 7059,"part of vermal region","rat","English","VERMIS OF ANTERIOR LOBE",,0 7063,"part of vermal region","rat","English","VERMIS OF POSTERIOR LOBE",,0 3676,"parvicellular division of accessory basal nucleus","Macaca fascicularis","English",,"parvicellular division of accessory basal nucleus",0 3768,"parvicellular division of basal nucleus (Amaral)","Macaca fascicularis","English",,"parvicellular division of basal nucleus (Amaral)",0 4538,"parvicellular part of dorsomedial nucleus","human","English","parvicellular part of medial dorsal nucleus",,0 4535,"parvicellular part of medial dorsal nucleus","Macaca fascicularis","English","parvicellular part of medial dorsal nucleus",,0 5332,"parvicellular part of ventral anterior nucleus","Macaca fascicularis","English","parvicellular part of ventral anterior nucleus",,1 5331,"parvicellular part of ventral anterior nucleus","human","English","parvicellular part of ventral anterior nucleus",,1 5500,"parvicellular part of ventral posteromedial nucleus","human","English","parvicellular part of ventral posteromedial nucleus",,0 5501,"parvicellular part of ventral posteromedial nucleus","Macaca fascicularis","English","parvicellular part of ventral posteromedial nucleus",,0 5036,"parvicellular reticular nucleus","Macaca fascicularis","English","parvicellular reticular nucleus",,4 5035,"parvicellular reticular nucleus","human","English","parvicellular reticular nucleus",,4 5037,"parvicellular reticular nucleus","rat","English","parvicellular reticular nucleus",,4 5140,"parvicellular subnucleus of solitary tract","human","English","parvicellular subnucleus of solitary tract",,0 3802,"parvocellular nucleus of hypothalamus","primate","English","anterior nucleus of hypothalamus",,0 5106,"parvocellular oculomotor nucleus","Macaca fascicularis","English","parvocellular oculomotor nucleus",,0 5669,"parvocellular part of red nucleus","Macaca fascicularis","English","parvocellular part of red nucleus",,1 5668,"parvocellular part of red nucleus","human","English","parvocellular part of red nucleus",,1 5041,"parvocellular reticular nucleus","rat","English","parvicellular reticular nucleus",,38 5710,"peduncle of flocculus","human","English","peduncle of flocculus",,0 1348,"peduncle of inferior colliculus","human","English","brachium of inferior colliculus",,0 740,"peduncle of lenticular nucleus","human","English",,"peduncle of lenticular nucleus",0 743,"peduncle of lentiform nucleus","human","English",,"peduncle of lenticular nucleus",0 5708,"peduncle of mammillary body","human","English","mammillary peduncle",,0 6004,"peduncle of substantia nigra","human","English",,"peduncle of substantia nigra",0 5715,"peduncle of superior olivary nucleus","human","English","peduncle of superior olive",,0 5713,"peduncle of superior olive","human","English","peduncle of superior olive",,0 746,"peduncular loop","human","English","ansa peduncularis",,0 4826,"peduncular pontine nucleus","human","English","pedunculopontine tegmental nucleus",,2 5702,"Pedunculi cerebelli","Macaca fascicularis","Latin",,"cerebellar peduncles",0 5701,"Pedunculi cerebelli","human","Latin",,"cerebellar peduncles",0 255,"Pedunculi cerebri","Macaca fascicularis","Latin","CEREBRAL PEDUNCLE",,1 254,"Pedunculi cerebri","human","Latin","CEREBRAL PEDUNCLE",,1 -1167929913,"pedunculi pontis cerebelli","human","Latin",,"cerebellar peduncles",0 4824,"pedunculopontine nucleus","human","English","pedunculopontine tegmental nucleus",,204 4825,"pedunculopontine nucleus","rat","English","pedunculopontine tegmental nucleus",,204 4820,"pedunculopontine tegmental nucleus","rat","English","pedunculopontine tegmental nucleus",,196 4818,"pedunculopontine tegmental nucleus","human","English","pedunculopontine tegmental nucleus",,196 4819,"pedunculopontine tegmental nucleus","Macaca fascicularis","English","pedunculopontine tegmental nucleus",,196 472,"Pedunculus cerebellaris caudalis","human","Latin","inferior cerebellar peduncle",,0 1369531308,"Pedunculus cerebellaris cranialis","human","Latin",,"superior cerebellar peduncle",0 471,"Pedunculus cerebellaris inferior","Macaca mulatta","Latin","inferior cerebellar peduncle",,0 470,"Pedunculus cerebellaris inferior","human","Latin","inferior cerebellar peduncle",,0 484,"Pedunculus cerebellaris medialis","human","Latin","middle cerebellar peduncle",,0 482,"Pedunculus cerebellaris medius","Macaca mulatta","Latin","middle cerebellar peduncle",,0 481,"Pedunculus cerebellaris medius","human","Latin","middle cerebellar peduncle",,0 483,"Pedunculus cerebellaris pontinus","human","Latin","middle cerebellar peduncle",,0 1934930278,"Pedunculus cerebellaris rostralis","human","Latin",,"superior cerebellar peduncle",0 -2080869607,"Pedunculus cerebellaris superior","Macaca mulatta","Latin",,"superior cerebellar peduncle",11 -319453576,"Pedunculus cerebellaris superior","human","Latin",,"superior cerebellar peduncle",11 -447281896,"Pedunculus cerebellaris superior (mesencephalon)","Macaca fascicularis","Latin","superior cerebellar peduncle of midbrain",,0 1591004509,"Pedunculus cerebellaris superior (pontis)","Macaca fascicularis","Latin","superior cerebellar peduncle of pons",,0 -1313878417,"Pedunculus cerebralis","human","Latin",,"basal part of midbrain",0 1990976504,"Pedunculus cerebralis","human","Latin","CEREBRAL PEDUNCLE",,0 253,"Pedunculus cerebri","human","Latin","CEREBRAL PEDUNCLE",,5 1744,"Pedunculus cerebri, pars basalis","human","Latin","cerebral crus",,0 5706,"Pedunculus corporis mamillaris","Macaca fascicularis","Latin","mammillary peduncle",,0 5707,"Pedunculus corporis mammillaris","human","Latin","mammillary peduncle",,0 5712,"Pedunculus floccularis","human","Latin","peduncle of flocculus",,0 5711,"Pedunculus flocculi","human","Latin","peduncle of flocculus",,0 5724,"Pedunculus inferior thalami","human","Latin","inferior thalamic peduncle",,0 742,"Pedunculus lentiformis","human","Latin",,"peduncle of lenticular nucleus",0 741,"Pedunculus nuclei lentiformis","human","Latin",,"peduncle of lenticular nucleus",0 3787,"Pedunculus olfactorius","human","Latin",,"olfactory stalk",0 5714,"Pedunculus olivae superioris","human","Latin","peduncle of superior olive",,0 5732,"Pedunculus rostralis thalami","human","Latin","anterior thalamic peduncle",,0 6005,"Pedunculus substantiae nigrae","human","Latin",,"peduncle of substantia nigra",0 5726,"Pedunculus thalami caudalis","Macaca mulatta","Latin","inferior thalamic peduncle",,0 5725,"Pedunculus thalami caudalis","human","Latin","inferior thalamic peduncle",,0 5723,"Pedunculus thalami inferior","Macaca fascicularis","Latin","inferior thalamic peduncle",,0 5722,"Pedunculus thalami inferior","human","Latin","inferior thalamic peduncle",,0 5744,"Pedunculus thalami superior","Unspecified","Latin","superior thalamic peduncle",,1 5727,"Pedunculus thalamicus inferior","human","Latin","inferior thalamic peduncle",,0 5738,"Pedunculus ventrocaudalis thalami","human","Latin","posterior thalamic peduncle",,0 689,"periallocortex","human","English",,"periallocortex",12 691,"periallocortex","human","English",,"periallocortex",12 690,"Periallocortex","human","Latin",,"periallocortex",12 692,"Periallocortex","human","Latin",,"periallocortex",12 1198,"periamygdaloid area","human","English","periamygdaloid area",,3 1199,"periamygdaloid area","Macaca fascicularis","English","periamygdaloid area",,3 1202,"periamygdaloid cortex","human","English","periamygdaloid area",,60 1203,"periamygdaloid cortex","Macaca fascicularis","English","periamygdaloid area",,60 1204,"periamygdaloid region","human","English","periamygdaloid area",,1 6130,"periaqueductal gray","rat","English","central gray substance of midbrain",,2427 6129,"periaqueductal gray","human","English","central gray substance of midbrain",,2427 6125,"periaqueductal gray matter","human","English","central gray substance of midbrain",,425 6124,"periaqueductal gray of tegmentum","human","English","central gray substance of midbrain",,0 693,"periarchicortex","human","Latin",,"Periarchicortex",1 701,"periarchicortical cingulate areas","human","English",,"periarchicortical cingulate areas",0 4827,"pericentral nucleus of inferior colliculus","human","English","pericentral nucleus of inferior colliculus",,0 1985,"periependymal fasciculus","human","English",,"dorsal longitudinal fasciculus",0 4830,"perifornical nucleus","human","English",,"perifornical nucleus",31 4592,"perihypoglossal nuclei","human","English",,"perihypoglossal nuclei",46 4833,"periolivary nucleus","human","English","periolivary nucleus",,35 696,"Peripalaeocortex","human","Latin",,"peripaleocortical claustral region",0 694,"peripaleocortical claustral region","human","English",,"peripaleocortical claustral region",0 4835,"peripeduncular nucleus","human","English","peripeduncular nucleus",,56 4836,"peripeduncular nucleus","Macaca fascicularis","English","peripeduncular nucleus",,56 4837,"peripeduncular nucleus","rat","English","peripeduncular nucleus",,56 3372,"peripheral nervous system","human","English",,"peripheral nervous system",15761 1724,"perirhinal area","human","English",,"perirhinal area 35",16 1722,"perirhinal area 35","human","English",,"perirhinal area 35",0 1725,"perirhinal cortex","human","English",,"perirhinal area 35",314 1193,"peristriate area","human","English",,"peristriate area 19",6 1185,"peristriate area 19","human","English",,"peristriate area 19",0 1226,"perisylvian language area","human","English",,"auditory association cortex",0 4784,"peritrigeminal nucleus","human","English","peritrigeminal nucleus",,0 2224,"periventricular fibers","human","English",,"periventricular fibers",0 3437,"periventricular gray","human","English",,"periventricular zone of hypothalamus",148 5063,"periventricular hypothalamic nucleus","rat","English",,"periventricular nucleus of hypothalamus",40 3436,"periventricular hypothalamic zone","human","English",,"periventricular zone of hypothalamus",0 6033,"periventricular layer","human","English",,"periventricular layer",0 3527,"periventricular nuclei of thalamus","human","English","MIDLINE NUCLEAR GROUP",,0 4929,"periventricular nucleus at the tuberal level","human","English","intermediate periventricular nucleus",,0 5062,"periventricular nucleus of hypothalamus","rat","English",,"periventricular nucleus of hypothalamus",0 5061,"periventricular nucleus of hypothalamus","Macaca fascicularis","English",,"periventricular nucleus of hypothalamus",0 5060,"periventricular nucleus of hypothalamus","human","English",,"periventricular nucleus of hypothalamus",0 4849,"periventricular nucleus, posterior subdivision","human","English","posterior periventricular nucleus",,0 4920,"periventricular preoptic nucleus","Unspecified","English","preoptic periventricular nucleus",,40 3435,"periventricular zone of hypothalamus","human","English",,"periventricular zone of hypothalamus",0 3931,"Perlia nucleus of oculomotor nerve","human","English","central oculomotor nucleus",,0 -499776334,"Pes anserinus","human","Latin",,"Pes anserinus",93 5749,"Pes hippocampi","human","Latin",,"Pes hippocampi",16 5761,"Pes lemnisci profundus","human","Latin","lateral pes lemniscus",,0 5753,"Pes lemniscus lateralis","human","Latin","lateral pes lemniscus",,0 5767,"Pes lemniscus medialis","human","Latin","medial pes lemniscus",,0 1739,"Pes pedunculi","Macaca mulatta","Latin","cerebral crus",,3 1738,"Pes pedunculi","human","Latin","cerebral crus",,3 1740,"Pes pedunculi of midbrain","human","Latin","cerebral crus",,0 649,"pia mater","human","English",,"pia mater",1537 650,"Pia mater","human","Latin",,"pia mater",1537 1698,"pineal body","human","English","pineal body",,3625 1699,"pineal body","Macaca fascicularis","English","pineal body",,36 1704,"pineal gland","rat","English","pineal body",,9 1703,"pineal gland","human","English","pineal body",,1 5916,"pineal recess","human","English","pineal recess",,0 1717,"piriform area","human","English",,"pyriform lobe",5 1719,"piriform cortex (Noback)","human","English",,"pyriform lobe",0 5814,"piriform cortex (Price)","human","English","prepyriform area",,0 1716,"piriform lobe","human","English",,"pyriform lobe",14 235,"pituitary body","human","English",,"Hypophysis (Carpenter)",0 230,"pituitary gland","human","English","HYPOPHYSIS",,32822 232,"pituitary gland","rat","English","HYPOPHYSIS",,32822 231,"pituitary gland","Macaca nemestrina","English","HYPOPHYSIS",,32822 234,"pituitary gland (Carpenter)","human","English",,"Hypophysis (Carpenter)",0 2866,"pituitary gland, anterior lobe","rat","English","ADENOHYPOPHYSIS",,0 2882,"pituitary gland, posterior lobe","rat","English","pars nervosa of hypophysis",,0 237,"pituitary stalk","human","English",,"infundibular stalk (Crosby)",682 1999936970,"plane of section","Unspecified","English",,"plane of section",0 929661690,"planum polare","human","Latin",,"planum polare",0 1233,"planum temporale","human","English",,"planum polare",149 1231,"planum temporale","human","English",,"planum temporale",149 1232,"Planum temporale","human","Latin",,"planum temporale",149 6038,"plexiform layer of cerebellar cortex","human","English",,"molecular layer of cerebellar cortex",0 3022,"plexiform layer of cerebral cortex","human","English",,"molecular layer",0 5772,"Plexus choroidae","Macaca fascicularis","Latin",,"choroid plexus",0 5776,"Plexus choroidae ventriculi lateralis","Macaca fascicularis","Latin","choroid plexus of lateral ventricle",,0 5784,"Plexus choroidea (ventriculi quarti)","human","Latin","choroid plexus of fourth ventricle",,0 5785,"Plexus choroidea (ventriculi quarti)","Macaca fascicularis","Latin","choroid plexus of fourth ventricle",,0 5780,"Plexus choroidea (ventriculi tertii)","human","Latin","choroid plexus of third ventricle",,0 5781,"Plexus choroidea (ventriculi tertii)","Macaca fascicularis","Latin","choroid plexus of third ventricle",,0 5770,"Plexus choroideus","human","Latin",,"choroid plexus",0 5771,"Plexus choroideus","human","Latin",,"choroid plexus",0 5775,"Plexus choroideus (ventriculi lateralis)","human","Latin","choroid plexus of lateral ventricle",,1 5777,"Plexus choroideus ventriculi lateralis","human","Latin","choroid plexus of lateral ventricle",,1 5786,"Plexus choroideus ventriculi quarti","human","Latin","choroid plexus of fourth ventricle",,0 3375,"PNS","human","Abbreviation",,"peripheral nervous system",0 716,"polar type cortex","human","English",,"polar type cortex",0 5793,"Polus frontalis","Macaca mulatta","Latin","frontal pole",,2 5792,"Polus frontalis","human","Latin","frontal pole",,2 5765,"Polus insulae","human","Latin",,"Polus insulae",0 5796,"Polus occipitalis","Macaca mulatta","Latin","occipital pole",,0 5795,"Polus occipitalis","human","Latin","occipital pole",,0 5799,"Polus temporalis","Macaca mulatta","Latin","temporal pole",,1 5798,"Polus temporalis","human","Latin","temporal pole",,1 2413,"polymorphic layer of dentate gyrus","human","English",,"polymorphic layer of dentate gyrus",0 2414,"polymorphic layer of dentate gyrus","Macaca mulatta","English",,"polymorphic layer of dentate gyrus",0 3049,"polymorphic layer of hippocampus","human","English",,"Stratum oriens",0 418,"pons","human","English","PONS",,9825 421,"Pons","Macaca fascicularis","Latin","PONS",,9825 420,"Pons","human","Latin","PONS",,9825 419,"pons","Macaca fascicularis","English","PONS",,37 5694,"pons proper","human","English","BASAL PART OF PONS",,1 422,"Pons Varolii","human","Latin","PONS",,9825 3721,"Pontes striatales","human","Latin",,"striatal cell bridges",0 6138,"pontine central gray","rat","English","central gray substance of pons",,20 1513,"pontine cistern","human","English","pontine cistern",,27 2341,"pontine flexure","human","English",,"pontine flexure",16 3534,"pontine gray","rat","English","pontine nuclei",,557 2435,"pontine gray","human","English",,"pontine gray",91 3530,"pontine nuclei","rat","English","pontine nuclei",,557 3529,"pontine nuclei","Macaca fascicularis","English","pontine nuclei",,41 3528,"pontine nuclei","human","English","pontine nuclei",,20 5901,"pontine raphe nucleus","Macaca fascicularis","English","pontine raphe nucleus",,31 5900,"pontine raphe nucleus","human","English","pontine raphe nucleus",,8 2442,"pontine reticular formation","Macaca fascicularis","English","PONTINE RETICULAR FORMATION",,564 2441,"pontine reticular formation","human","English","PONTINE RETICULAR FORMATION",,1 5045,"pontine reticular nucleus, caudal part","rat","English","caudal pontine reticular nucleus",,0 5050,"pontine reticular nucleus, rostral part","Unspecified","English","oral pontine reticular nucleus",,0 7251,"pontine reticulospinal fibers","human","English",,"pontine reticulospinal tract",0 7250,"pontine reticulospinal tract","human","English",,"pontine reticulospinal tract",0 6671,"pontine tegmentum","human","English","PONTINE TEGMENTUM",,3 6672,"pontine tegmentum","Macaca fascicularis","English","PONTINE TEGMENTUM",,0 4855,"pontobulbar body","human","English","pontobulbar nucleus",,4 4851,"pontobulbar nucleus","human","English","pontobulbar nucleus",,1 6838,"pontocerebellar fibers","human","English",,"pontocerebellar fibers",14 6840,"pontocerebellar tract","human","English",,"pontocerebellar fibers",0 6972,"pontocerebellar trigone","human","English","pontocerebellar trigone",,0 536,"pontocerebellum","human","English","POSTERIOR LOBE OF CEREBELLUM",,5 4857,"pontomedullary junction","human","English",,"pontomedullary junction",78 2937,"ponto-medullary junction","human","English",,"medullary-pontine junction",17 3328,"Portio major nervi trigemini","human","Latin",,"sensory root of trigeminal nerve",0 3329,"Portio major nervi trigemini","Macaca mulatta","Latin",,"sensory root of trigeminal nerve",0 3327,"Portio major of trigeminal nerve","human","Latin",,"sensory root of trigeminal nerve",0 3338,"Portio minor nervi trigemini","human","Latin","motor root of trigeminal nerve",,0 3339,"Portio minor nervi trigemini","Macaca mulatta","Latin","motor root of trigeminal nerve",,0 3337,"Portio minor of trigeminal nerve","human","Latin","motor root of trigeminal nerve",,0 6241,"postcalcarine sulcus","human","English","posterior calcarine sulcus (H)",,0 2772,"postcentral convolution","human","English","postcentral gyrus",,0 6536,"postcentral dimple","Macaca fascicularis","English","superior postcentral sulcus",,2 2321,"postcentral fissure of cerebellum","human","English","postcentral fissure of cerebellum",,0 6529,"postcentral fissure of cerebral hemisphere","human","English","postcentral sulcus",,19 6530,"postcentral fissure-1","human","English","postcentral sulcus",,0 2324,"postcentral fissure-2","human","English","postcentral fissure of cerebellum",,0 2768,"postcentral gyrus","Macaca mulatta","English","postcentral gyrus",,186 2767,"postcentral gyrus","human","English","postcentral gyrus",,0 759734604,"postcentral opercular areas","Macaca mulatta","English",,"postcentral opercular areas",0 1029,"postcentral region","human","English",,"postcentral region",0 6537,"postcentral sulcus","Macaca mulatta","English","superior postcentral sulcus",,19 6527,"postcentral sulcus","human","English","postcentral sulcus",,0 6272,"postcentral sulcus of island","human","English","longitudinal sulcus of insula (H)",,0 -1970833257,"postcentral white matter","Unspecified","English","postcentral white matter",,0 2279,"postclival fissure","human","English","posterior superior fissure",,0 2226,"postcommissural fornix","human","English","postcommissural fornix",,33 2227,"postcommissural fornix","Macaca fascicularis","English","postcommissural fornix",,0 7016,"posteriomedian lobule","human","English",,"posteromedian lobule",0 6411,"posterior ascending limb of lateral fissure","human","English","posterior ascending limb of lateral sulcus (H)",,0 6412,"posterior ascending limb of lateral fissure","human","English","posterior ascending limb of lateral sulcus (H)",,0 6409,"posterior ascending limb of lateral sulcus","Unspecified","English","posterior ascending limb of lateral sulcus (H)",,0 6239,"posterior calcarine fissure","human","English","posterior calcarine sulcus (H)",,0 6237,"posterior calcarine sulcus","human","English","posterior calcarine sulcus (H)",,0 2773,"posterior central gyrus","human","English","postcentral gyrus",,0 1576,"posterior cerebellar commissure","human","English",,"posterior cerebellar commissure",0 2900,"posterior cerebellar incisure","human","English","posterior cerebellar incisure",,0 535,"posterior cerebellar lobe","human","English","POSTERIOR LOBE OF CEREBELLUM",,3 2596,"posterior cingulate gyrus","human","English","posterior cingulate gyrus",,0 2597,"posterior cingulate gyrus","Macaca fascicularis","English","posterior cingulate gyrus",,0 388968077,"posterior cingulate white matter","Unspecified","English","posterior cingulate white matter",,0 373,"posterior colliculus","human","English","INFERIOR COLLICULUS",,26 3536,"posterior column medullary relay nuclei","human","English",,"posterior column nuclei",0 3535,"posterior column nuclei","human","English",,"posterior column nuclei",11 1749,"posterior column of fornix","Macaca fascicularis","English","posterior column of fornix",,0 1748,"posterior column of fornix","human","English","posterior column of fornix",,0 618,"posterior column tracts","human","English",,"posterior white column",0 621,"posterior columns","human","English",,"posterior white column",208 1129,"posterior commissure","Macaca fascicularis","English","posterior commissure",,422 1130,"posterior commissure","rat","English","posterior commissure",,422 1128,"posterior commissure","human","English","posterior commissure",,422 4677,"posterior complex of thalamus","rat","English","POSTERIOR NUCLEAR COMPLEX",,0 7206,"posterior cornucommissural nucleus","human","English",,"posterior cornucommissural nucleus",0 372,"posterior corpus quadrigeminum","human","English","INFERIOR COLLICULUS",,0 3729,"posterior cortical amygdaloid nucleus","human","English","cortical amygdaloid nucleus",,3 1126,"posterior cortical eye fields","human","English",,"occipital eye fields",0 3728,"posterior cortical nucleus of amygdala","Macaca fascicularis","English","cortical amygdaloid nucleus",,1 3198,"posterior crescentic lobule of cerebellum","human","English","simple lobule",,0 1753,"posterior crus of fornix","human","English","posterior column of fornix",,0 6414,"posterior descending limb of lateral sulcus","Unspecified","English",,"posterior descending limb of lateral sulcus (H)",0 2369,"posterior forceps","human","English","posterior forceps of corpus callosum",,0 2364,"posterior forceps of corpus callosum","human","English","posterior forceps of corpus callosum",,0 620,"posterior funiculus","human","English",,"posterior white column",37 7105,"posterior gray column","human","English",,"posterior gray column",0 7107,"posterior gray horn","human","English",,"posterior gray column",0 7106,"posterior horn","human","English",,"posterior gray column",492 7127,"posterior horn nuclear group","human","English",,"posterior horn nuclear group",0 1652,"posterior horn of lateral ventricle","human","English","occipital horn of lateral ventricle",,2 4878,"posterior hypothalamic area","human","English","posterior nucleus of hypothalamus",,112 4876,"posterior hypothalamic nucleus","human","English","posterior nucleus of hypothalamus",,83 4877,"posterior hypothalamic nucleus","rat","English","posterior nucleus of hypothalamus",,83 216,"posterior hypothalamic region","Unspecified","English","POSTERIOR HYPOTHALAMIC REGION",,39 1981174929,"posterior hypothalamic region - not otherwise specified","Unspecified","English","POSTERIOR HYPOTHALAMIC REGION - not otherwise specified",,39 220,"posterior hypothalamus","human","English","POSTERIOR HYPOTHALAMIC REGION",,1220 3171,"posterior inferior lobule","human","English","inferior semilunar lobule",,0 6269,"posterior inferior sulcus","Papio","English",,"posterior inferior sulcus (M)",0 7104,"posterior intermediate septum","human","English",,"posterior intermediate septum",0 7102,"posterior intermediate sulcus of spinal cord","human","English",,"posterior intermediate sulcus of spinal cord",0 4308,"posterior interposed nucleus","human","English","globose nucleus",,32 4307,"posterior interpositus nucleus","Macaca fascicularis","English","globose nucleus",,31 4462,"posterior lateral nucleus of thalamus","human","English","lateral posterior nucleus",,1 1755,"posterior limb of internal capsule","human","English","POSTERIOR LIMB OF INTERNAL CAPSULE",,13 6403,"posterior limb of lateral sulcus","Unspecified","English",,"posterior limb of lateral sulcus",0 4497,"posterior limitans thalamic nucleus","human","English",,"posterior limitans thalamic nucleus",0 531,"posterior lobe of cerebellum","human","English","POSTERIOR LOBE OF CEREBELLUM",,0 553132494,"posterior lobe of hypophysis","human","English","NEUROHYPOPHYSIS",,0 2881,"posterior lobe of pituitary","rat","English","pars nervosa of hypophysis",,5 538,"posterior lobe-1 of cerebellum","human","English","POSTERIOR LOBE OF CEREBELLUM",,0 559,"posterior lobe-2 of cerebellum","human","English","FLOCCULONODULAR LOBE",,0 2880,"posterior lobe-3","human","English","pars nervosa of hypophysis",,0 1984,"posterior longitudinal fasciculus","human","English",,"dorsal longitudinal fasciculus",0 6446,"posterior marginal sulcus","human","English","posterior marginal sulcus (H)",,0 1905,"posterior median eminence","human","English","posterior median eminence",,10 7099,"posterior median septum","human","English",,"posterior median septum",3 7098,"posterior median sulcus of spinal cord","human","English",,"posterior median sulcus of spinal cord",0 7026,"posterior medullary velum","human","English","inferior medullary velum",,4 6614,"posterior middle temporal sulcus","Macaca mulatta","English","posterior middle temporal sulcus (M)",,2 6615,"posterior middle temporal sulcus","Macaca fascicularis","English","posterior middle temporal sulcus (M)",,2 4673,"posterior nuclear complex","human","English","POSTERIOR NUCLEAR COMPLEX",,15 4674,"posterior nuclear complex","Macaca fascicularis","English","POSTERIOR NUCLEAR COMPLEX",,15 4676,"posterior nuclear complex of thalamus","human","English","POSTERIOR NUCLEAR COMPLEX",,0 4874,"posterior nucleus of hypothalamus","Macaca fascicularis","English","posterior nucleus of hypothalamus",,1 4873,"posterior nucleus of hypothalamus","human","English","posterior nucleus of hypothalamus",,1 3537,"posterior nucleus of thalamus","human","English","posterior nucleus of thalamus",,4 3538,"posterior nucleus of thalamus","human","English","posterior nucleus of thalamus",,4 3539,"posterior nucleus of thalamus","Macaca","English","posterior nucleus of thalamus",,4 -1459428100,"posterior orbital gyrus","human","English","posterior orbital gyrus (H)",,0 3132,"posterior paracentral gyrus","human","English",,"posterior paracentral gyrus",0 2756,"posterior parahippocampal gyrus","human","English","posterior parahippocampal gyrus",,21 -2016839646,"posterior parahippocampal white matter","Unspecified","English","posterior parahippocampal white matter",,0 1273,"posterior parolfactory gyrus","human","English",,"posterior parolfactory gyrus",0 6516,"posterior parolfactory sulcus","human","English","posterior parolfactory sulcus",,0 1569,"posterior part of anterior commissure","Macaca fascicularis","English","posterior part of anterior commissure",,0 1568,"posterior part of anterior commissure","human","English","posterior part of anterior commissure",,0 6240,"posterior part of calcarine sulcus","human","English","posterior calcarine sulcus (H)",,1 2621,"posterior part of inferior frontal gyrus","human","English","opercular part of inferior frontal gyrus (H)",,1 2578,"posterior part of inferior parietal lobule","human","English",,"posterior part of inferior parietal lobule",0 5740,"posterior peduncle","human","English","posterior thalamic peduncle",,3 6202,"posterior perforated space","human","English",,"posterior perforated substance",0 6197,"posterior perforated substance","human","English",,"posterior perforated substance",2 4845,"posterior periventricular nucleus","Unspecified","English","posterior periventricular nucleus",,4 4846,"posterior periventricular nucleus","Macaca fascicularis","English","posterior periventricular nucleus",,4 4848,"posterior periventricular nucleus of hypothalamus","rat","English","posterior periventricular nucleus",,0 1752,"posterior pillar of fornix","human","English","posterior column of fornix",,0 2879,"posterior pituitary","human","English","pars nervosa of hypophysis",,1219 3194,"posterior quadrangular lobule","human","English","simple lobule",,4 3199,"posterior quadrangular lobule of cerebellum","human","English","simple lobule",,0 6407,"posterior ramus of Sylvian fissure","human","English",,"posterior limb of lateral sulcus",0 3605,"posterior region of motor thalamus","Macaca","English",,"posterior region of motor thalamus",0 3604,"posterior region of motor thalamus","human","English",,"posterior region of motor thalamus",0 3196,"posterior semilunar lobule","human","English","simple lobule",,0 6851,"posterior spinocerebellar tract","human","English","posterior spinocerebellar tract",,5 6577,"posterior subcentral sulcus","Macaca fascicularis","English","posterior subcentral sulcus",,0 6576,"posterior subcentral sulcus","human","English","posterior subcentral sulcus",,0 2277,"posterior superior fissure","human","English","posterior superior fissure",,4 3184,"posterior superior lobule","human","English","superior semilunar lobule",,0 4678,"posterior thalamic nuclear group","rat","English","POSTERIOR NUCLEAR COMPLEX",,6 5737,"posterior thalamic peduncle","human","English","posterior thalamic peduncle",,0 5892,"posterior thalamic radiation","human","English",,"posterior thalamic radiations",0 5890,"posterior thalamic radiations","human","English",,"posterior thalamic radiations",0 956,"posterior transverse temporal area 42","human","English",,"posterior transverse temporal area 42 (H)",0 2811,"posterior transverse temporal convolution of Heschl","human","English","posterior transverse temporal gyrus (H)",,0 2809,"posterior transverse temporal gyrus","human","English","posterior transverse temporal gyrus (H)",,0 5305,"posterior trochlear nucleus","human","English",,"accessory trochlear nucleus",0 617,"posterior white column","human","English",,"posterior white column",0 5400,"posterodorsal part of ventral lateral posterior nucleus (Jones)","human","English","pars postrema of ventral lateral nucleus",,0 5401,"posterodorsal part of ventral lateral posterior nucleus (Jones)","Macaca","English","pars postrema of ventral lateral nucleus",,0 7079,"posterolateral fasciculus","human","English","dorsolateral fasciculus of medulla",,0 2269,"posterolateral fissure","human","English","posterolateral fissure",,6 6317,"posterolateral sulcus","human","English","dorsolateral sulcus",,5 7100,"posterolateral sulcus of spinal cord","human","English",,"posterolateral sulcus of spinal cord",0 7080,"posterolateral tract","human","English","dorsolateral fasciculus of medulla",,0 5444,"posterolateral ventral nucleus of thalamus","human","English","VENTRAL POSTEROLATERAL NUCLEUS",,0 7167,"posteromarginal nucleus","human","English",,"Rexed's lamina I",0 6635,"posteromedial terminal branch of collateral sulcus","human","English",,"intralingual ramus of collateral sulcus (H)",0 5493,"posteromedial ventral nucleus of thalamus","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,0 4001,"posteroventral cochlear nucleus","human","English","posteroventral cochlear nucleus",,69 5678,"postlenticular portion of internal capsule","human","English","retrolenticular part of internal capsule",,0 2320,"postlingual fissure","human","English","precentral fissure of cerebellum",,0 2280,"postlunate fissure","human","English","posterior superior fissure",,0 1626,"postmammillary decussation","human","English","supramammillary commissure",,0 2276,"postnodular fissure","human","English",,"postnodular fissure",0 2327,"postpyramidal fissure","human","English","secondary fissure",,0 2771,"postrolandic gyrus","human","English","postcentral gyrus",,1 -285677664,"PPA internal feature","Unspecified","English","PPA internal feature",,0 1020961793,"PPA internal feature","Unspecified","English","PPA internal feature",,0 2453,"PPRF","human","Abbreviation",,"paramedian pontine reticular formation",0 5806,"Praecuneus","human","Latin","precuneus",,1 4111,"Praegeniculatum","human","Latin","ventral nucleus of lateral geniculate body",,0 5821,"Praesubiculum","human","Latin","presubiculum",,0 406,"Praetectum","human","Latin","PRETECTAL REGION",,3 1034,"precentral area","human","English",,"precentral area",0 2780,"precentral convolution","human","English","precentral gyrus",,0 6547,"precentral dimple","Macaca mulatta","English","superior precentral sulcus",,3 2317,"precentral fissure of cerebellum","human","English","precentral fissure of cerebellum",,0 844,"precentral gigantopyramidal field","human","English",,"gigantopyramidal area 4",0 2774,"precentral gyrus","human","English","precentral gyrus",,265 2775,"precentral gyrus","Macaca mulatta","English","precentral gyrus",,265 2781,"precentral gyrus of insula","human","English","precentral gyrus of insula (H)",,0 2783,"precentral gyrus of island","human","English","precentral gyrus of insula (H)",,0 -1976157723,"precentral motor area","human","English",,"primary motor cortex",0 794,"precentral motor cortex","Macaca","English",,"primary motor cortex",53 5595,"precentral operculum (of Rolando)","human","English","precentral operculum",,0 1032,"precentral region","human","English",,"precentral region",0 1035,"precentral region (Wilk)","human","English",,"precentral area",0 212337636,"precentral white matter","Unspecified","English","precentral white matter",,0 3541,"precerebellar nuclei","human","English",,"precerebellar nuclei",44 2315,"preclival fissure","human","English","primary fissure of cerebellum",,0 785,"precommissural archicortex","human","English",,"precommissural archicortex",0 2230,"precommissural fornix","human","English","precommissural fornix",,14 2766,"precommissural hippocampus","human","English","paraterminal gyrus",,2 1278,"precommissural septal area (Crosby)","human","English",,"precommissural septum",0 1535290343,"precommissural septum","human","English",,"precommissural septum (Crosby)",8 1274,"precommissural septum (Crosby)","human","English",,"precommissural septum",0 5805,"precuneate lobule","human","English","precuneus",,0 673243299,"precuneate white matter","Unspecified","English","precuneate white matter",,0 5801,"precuneus","Macaca fascicularis","English","precuneus",,115 5800,"precuneus","human","English","precuneus",,115 5803,"Precuneus","Macaca mulatta","Latin","precuneus",,115 5802,"Precuneus","human","Latin","precuneus",,115 1383,"predorsal bundle","human","English","predorsal bundle",,51 1387,"predorsal bundle of Edinger","human","English","predorsal bundle",,0 1385,"predorsal fasciculus","human","English","predorsal bundle",,0 891,"prefrontal area 11","human","English",,"prefrontal area 11",0 229548637,"prefrontal area 11 of Brodmann-09","human","English",,"prefrontal area 11 of Brodmann-09",0 1084,"prefrontal cortex (Crosby)","human","English",,"prefrontal cortex (Crosby)",0 1039,"prefrontal cortex (H)","human","English",,"frontal region",0 -741205926,"prefrontal cortex (M)","Macaca","English",,"prefrontal cortex (M)",0 1085,"prefrontal cortex (Zilles)","human","English",,"prefrontal cortex (Zilles)",0 1042,"prefrontal lobe","human","English",,"frontal region",46 1040,"prefrontal region","human","English",,"frontal region",0 4106,"pregeniculate nucleus","Macaca","English","ventral nucleus of lateral geniculate body",,22 4105,"pregeniculate nucleus","human","English","ventral nucleus of lateral geniculate body",,22 994,"pregenual area 33","human","English",,"pregenual area 33",0 2415,"prehippocampal rudiment","human","English",,"prehippocampal rudiment",0 1015609549,"prelunate gyrus","Macaca mulatta","English","angular gyrus",,21 4888,"premammillary nuclei","human","English","premammillary nucleus",,48 4885,"premammillary nucleus","human","English","premammillary nucleus",,86 -2031441821,"premotor area","human","English",,"premotor cortex",153 1092,"premotor cortex","Macaca","English",,"premotor cortex",470 1091,"premotor cortex","human","English",,"premotor cortex",470 2272,"prenodular fissure","human","English","posterolateral fissure",,0 2273,"prenodular sulcus","human","English","posterolateral fissure",,0 1196,"preoccipital cortex","human","English",,"peristriate area 19",3 1195,"pre-occipital cortex","human","English",,"peristriate area 19",0 1127,"preoccipital eye fields","human","English",,"preoccipital eye fields",0 2573,"preoccipital gyrus","Macaca mulatta","English","angular gyrus",,2 2907,"preoccipital incisura","human","English","preoccipital notch",,0 2906,"preoccipital incisure","human","English","preoccipital notch",,0 2902,"preoccipital notch","human","English","preoccipital notch",,0 4884,"preolivary nuclei","human","English","preolivary nucleus",,2 4882,"preolivary nucleus","human","English","preolivary nucleus",,4 5937,"preoptic area","human","English","PREOPTIC AREA",,5442 5940,"preoptic nuclei","human","English","PREOPTIC AREA",,98 4919,"preoptic periventricular hypothalamic nucleus","human","English","preoptic periventricular nucleus",,0 4914,"preoptic periventricular nucleus","human","English","preoptic periventricular nucleus",,16 4916,"preoptic periventricular nucleus","rat","English","preoptic periventricular nucleus",,16 4915,"preoptic periventricular nucleus","Macaca fascicularis","English","preoptic periventricular nucleus",,16 5923,"preoptic recess","human","English","optic recess",,78 5924,"preoptic recess of third ventricle","human","English","optic recess",,0 5939,"preoptic region of hypothalamus","human","English","PREOPTIC AREA",,2 207,"preoptico-hypothalamic area","human","English","HYPOTHALAMUS",,5 208,"preoptico-hypothalamic region","human","English","HYPOTHALAMUS",,1 897,"preparietal area 5","human","English",,"preparietal area 5",0 5812,"prepiriform cortex","human","English","prepyriform area",,99 4941,"prepositus hypoglossal nucleus","rat","English","nucleus prepositus",,42 4938,"prepositus nucleus","Macaca fascicularis","English","nucleus prepositus",,10 2281,"prepyramidal fissure","human","English","prepyramidal fissure",,4 2284,"prepyramidal sulcus","human","English","prepyramidal fissure",,0 5807,"prepyriform area","human","English","prepyriform area",,1 5808,"prepyriform area","Macaca fascicularis","English","prepyriform area",,1 5813,"prepyriform cortex","human","English","prepyriform area",,73 2779,"prerolandic gyrus","human","English","precentral gyrus",,2 1407,"prerubral area","human","English","field H",,6 1404,"prerubral field","human","English","field H",,8 1414,"prerubral field nucleus","human","English","nucleus of field H",,1 1413,"prerubral nucleus","human","English","nucleus of field H",,2 1415,"prerubral tegmental nucleus","human","English","nucleus of field H",,0 6771,"prerubral tract","human","English",,"prerubral tract",0 5818,"presubiculum","Macaca fascicularis","English","presubiculum",,210 5817,"presubiculum","human","English","presubiculum",,210 5820,"presubiculum","rat","English","presubiculum",,210 5819,"Presubiculum","human","Latin","presubiculum",,210 405,"pretectal area","human","English","PRETECTAL REGION",,123 410,"pretectal area (Crosby)","human","English",,"pretectal area (Crosby)",0 407,"pretectal nuclei","human","English","PRETECTAL REGION",,166 4647,"pretectal olivary nucleus","human","English","olivary pretectal nucleus",,26 398,"pretectal region","human","English","PRETECTAL REGION",,84 399,"pretectal region","Macaca fascicularis","English","PRETECTAL REGION",,84 1390010068,"pretectal region - not otherwise specified","Unspecified","English","PRETECTAL REGION - not otherwise specified",,84 404,"pretectum","human","English","PRETECTAL REGION",,436 427,"pretrigeminal level of pons","human","English",,"isthmus of hindbrain",0 1216,"primary auditory area","human","English",,"primary auditory area",0 1217,"primary auditory cortex","human","English",,"primary auditory area",523 2312,"primary fissure of cerebellum","human","English","primary fissure of cerebellum",,0 6460,"primary intermediate sulcus","human","English",,"primary intermediate sulcus (H)",0 793,"primary motor area","human","English",,"primary motor cortex",0 -1677420246,"primary motor area (M I)","human","English",,"primary motor cortex",0 792,"primary motor cortex","human","English",,"primary motor cortex",604 796,"primary motor cortex","human","English",,"primary motor cortex",604 1138,"primary olfactory areas","Macaca","English",,"primary olfactory areas",0 1139,"primary olfactory cortex","human","English",,"primary olfactory areas",0 -2085985374,"primary olfactory cortex (Carpenter)","human","English",,"pyriform lobe",0 1075,"primary sensory areas","human","English",,"primary sensory areas",0 1076,"primary sensory cortex","human","English",,"primary sensory areas",0 1071,"primary somatic sensory area","human","English",,"primary somesthetic area",0 1547050122,"primary somatosensory cortex","human","English",,"primary somesthetic area",663 1070,"primary somesthetic area","human","English",,"primary somesthetic area",0 1072,"primary somesthetic cortex","human","English",,"primary somesthetic area",2 2314,"primary sulcus of cerebellum","human","English","primary fissure of cerebellum",,0 813,"primary visual area","human","English",,"striate area 17",0 816,"primary visual cortex","human","English",,"striate area 17",1201 388799158,"primitive olfactory lobe","human","English",,"rhinencephalon",0 80737790,"principal auditory receptive areas","human","English",,"anterior transverse temporal area 41 (H)",0 4635,"principal inferior olivary nucleus","Macaca fascicularis","English","principal inferior olivary nucleus",,1 4634,"principal inferior olivary nucleus","human","English","principal inferior olivary nucleus",,1 2036,"principal mammillary fasciculus","human","English","mammillary princeps fasciculus",,0 4640,"principal nucleus of inferior olive","human","English","principal inferior olivary nucleus",,0 4643,"principal olivary nucleus (Martinez)","human","English",,"principal olivary nucleus (Martinez)",0 5510,"principal part of ventral posteromedial nucleus","human","English","principal part of ventral posteromedial nucleus",,0 4942,"principal pretectal nucleus","human","English","principal pretectal nucleus",,2 -1911484295,"principal sensory nucleus of trigeminal nerve","rat","English","principal sensory nucleus of trigeminal nerve",,0 -1561941759,"principal sensory nucleus of trigeminal nerve","human","English","principal sensory nucleus of trigeminal nerve",,0 1015292212,"principal sensory nucleus of trigeminal nerve","Macaca fascicularis","English","principal sensory nucleus of trigeminal nerve",,0 -821257402,"principal sensory trigeminal nucleus","rat","English","principal sensory nucleus of trigeminal nerve",,44 6549,"principal sulcus","Macaca mulatta","English","principal sulcus (M)",,74 4670,"principal superior olivary nucleus","human","English","medial superior olivary nucleus",,0 -1059883875,"principal trigeminal nucleus","Macaca fascicularis","English","principal sensory nucleus of trigeminal nerve",,40 5570,"principal vestibular nucleus","human","English","medial vestibular nucleus",,0 2035,"principle mamillary fasciculus","human","English","mammillary princeps fasciculus",,0 1390,"Probst bundle","human","English",,"bundle of Probst",0 5833,"Processus griseum pontis supralemniscalis","Macaca mulatta","Latin",,"supralemniscal process",0 5834,"Processus griseum pontis tegmentalis lateralis","Macaca mulatta","Latin",,"Processus griseum pontis tegmentalis lateralis",0 3224,"proisocortex","human","English",,"proisocortex",15 3225,"Proisocortex","human","Latin",,"proisocortex",15 96,"projection areas of cortex","human","English",,"projection areas of cortex",0 3393,"projection fibers of cerebral cortex","human","English",,"cerebral projection fibers",0 7173,"proper sensory nucleus","human","English",,"proper sensory nucleus",0 7246,"proprius bundles of cord","human","English",,"Fasciculi proprii",0 14,"Prosencephalon","human","Latin","FOREBRAIN",,3663 5840,"prosubiculum","human","English",,"prosubiculum",59 5841,"Prosubiculum","human","Latin",,"prosubiculum",59 3434,"prothalamus","human","English",,"prothalamus",0 1610,"Psalterium","human","Latin","commissure of fornix",,12 4781,"Pt","human","Abbreviation","paratenial nucleus",,0 4780,"Pt","Macaca mulatta","Abbreviation","paratenial nucleus",,0 3543,"pulvinar","Macaca fascicularis","English","PULVINAR",,656 3545,"Pulvinar","Macaca fascicularis","English","PULVINAR",,656 3542,"pulvinar","human","English","PULVINAR",,656 3544,"Pulvinar","human","Latin","PULVINAR",,656 3548,"pulvinar nucleus","human","English","PULVINAR",,98 3547,"Pulvinar thalami","human","Latin","PULVINAR",,7 6039,"Purkinje cell layer","human","English",,"Purkinje cell layer",0 5842,"putamen","human","English","putamen",,6357 5844,"Putamen","Macaca fascicularis","Latin","putamen",,6357 5843,"Putamen","human","Latin","putamen",,6357 5857,"pyramid of cerebellum","human","English","pyramis of vermis",,0 5846,"pyramid of medulla","human","English","pyramid of medulla",,0 5849,"pyramid of medulla","human","English","pyramid of medulla",,0 6734,"pyramidal decussation","rat","English","pyramidal decussation",,69 6732,"pyramidal decussation","human","English","pyramidal decussation",,69 6733,"pyramidal decussation","Macaca fascicularis","English","pyramidal decussation",,69 3046,"pyramidal layer of hippocampus","human","English",,"Stratum pyramidale hippocampi",0 6717,"pyramidal system","human","English",,"pyramidal system",52 6699,"pyramidal tract","human","English","pyramidal tract",,1072 6700,"pyramidal tract","Macaca fascicularis","English","pyramidal tract",,1072 6701,"pyramidal tract","rat","English","pyramidal tract",,1072 5858,"Pyramis","human","Latin","pyramis of vermis",,64 5847,"Pyramis (medullae oblongatae)","human","Latin","pyramid of medulla",,0 5848,"Pyramis (medullae oblongatae)","Macaca mulatta","Latin","pyramid of medulla",,0 5856,"pyramis of cerebellum","human","English","pyramis of vermis",,0 5852,"pyramis of vermis","human","English","pyramis of vermis",,0 5853,"pyramis of vermis","Macaca fascicularis","English","pyramis of vermis",,0 5854,"Pyramis vermis","human","Latin","pyramis of vermis",,2 5859,"pyramus","rat","English","pyramis of vermis",,0 1718,"pyriform area","human","English",,"pyriform lobe",2 1877175451,"pyriform area","human","English","prepyriform area",,2 2830,"pyriform area (Crosby)","human","English","uncus",,0 1715,"pyriform lobe","human","English",,"pyriform lobe",9 5804,"quadrate lobule","human","English","precuneus",,0 1512,"quadrigeminal cistern","human","English","superior cistern",,51 3408,"quadrigeminal plate","human","English",,"quadrigeminal plate",81 6929,"quintothalamic tract","human","English",,"trigeminal lemniscus",0 5863,"Radiatio acustica","human","Latin",,"auditory radiation",0 5864,"Radiatio acustica","Macaca fascicularis","Latin",,"auditory radiation",0 5861,"Radiatio corporis callosi","human","Latin",,"radiations of corpus callosum",0 5872,"Radiatio geniculo-calcarina","human","Latin",,"geniculocalcarine radiation",0 5873,"Radiatio geniculo-calcarina","Macaca fascicularis","Latin",,"geniculocalcarine radiation",0 5879,"Radiatio geniculotemporalis","Unspecified","Latin",,"Radiatio geniculo-temporalis",0 5878,"Radiatio geniculo-temporalis","Macaca fascicularis","Latin",,"Radiatio geniculo-temporalis",0 5877,"Radiatio geniculo-temporalis","human","Latin",,"Radiatio geniculo-temporalis",0 5870,"Radiatio optica","Macaca fascicularis","Latin",,"geniculocalcarine radiation",0 5869,"Radiatio optica","human","Latin",,"geniculocalcarine radiation",0 5895,"Radiatio thalamocorticalis","human","Latin",,"thalamocortical radiations",0 1794899296,"Radiationes thalamicae anteriores","human","Latin",,"anterior thalamic radiations",0 5884,"Radiationes thalamicae centrales","human","Latin",,"superior thalamic radiations",0 5891,"Radiationes thalamicae posteriores","human","Latin",,"posterior thalamic radiations",0 5860,"radiations of corpus callosum","human","English",,"radiations of corpus callosum",0 3291,"Radices craniales nervi accessorii","human","Latin","cranial part of accessory nerve",,0 5897,"Radices descendentes nervi vestibulari","Macaca fascicularis","Latin",,"Radices descendentes nervi vestibulari",0 3301,"Radices spinales nervi accessorii","human","Latin",,"spinal part of accessory nerve",0 1490,"Radices ventrales nervi spinalis","human","Latin",,"Radices ventrales nervi spinalis",0 1489,"Radix dorsalis nervi spinalis","human","Latin",,"Radix dorsalis nervi spinalis",0 6393,"Ramus anterior ascendens fissurae lateralis","human","Latin","anterior ascending limb of lateral sulcus (H)",,0 6417,"Ramus anterior horizontalis sulcus lateralis","Unspecified","Latin","anterior horizontal limb of lateral sulcus (H)",,0 6418,"Ramus anterior sulcus lateralis","human","Latin","anterior horizontal limb of lateral sulcus (H)",,0 292658603,"ramus ascendens sulci cerebri lateralis (Sylvii)","human","Latin","anterior ascending limb of lateral sulcus (H)",,0 6394,"Ramus ascendens sulcus lateralis","human","Latin","anterior ascending limb of lateral sulcus (H)",,0 -368185918,"Ramus horizontalis fissurae sylvii","human","Latin","anterior horizontal limb of lateral sulcus (H)",,0 6408,"Ramus horizontalis posterior of Sylvian fissure","human","Latin",,"posterior limb of lateral sulcus",0 6216,"Ramus inferior sulcus arcuatus","Unspecified","Latin","inferior ramus of arcuate sulcus (M)",,0 6436,"Ramus marginalis sulci cingulati","human","Latin","marginal sulcus (H)",,0 6410,"Ramus posterior ascendens fissurae lateralis","human","Latin","posterior ascending limb of lateral sulcus (H)",,0 208041927,"Ramus posterior fissurae sylvii","human","Latin",,"posterior limb of lateral sulcus",0 6404,"Ramus posterior sulcus lateralis","human","Latin",,"posterior limb of lateral sulcus",0 6220,"Ramus superior sulcus arcuatus","Unspecified","Latin","superior ramus of arcuate sulcus (M)",,0 -829483237,"Ramus verticalis fissurae sylvii","human","Latin","anterior ascending limb of lateral sulcus (H)",,0 -1677248961,"Raphe (mediana pontina)","human","Latin","pontine raphe nucleus",,0 4983,"raphe magnus nucleus","rat","English","nucleus raphe magnus",,62 5899,"Raphe medullae oblongatae","human","Latin",,"median raphe",0 2458,"raphe nuclei","human","English",,"raphe nuclei",4284 2463,"raphe nuclei of medulla","human","English","RAPHE NUCLEI OF MEDULLA",,0 4989,"raphe obscurus nucleus","rat","English","nucleus raphe obscurus",,25 5906,"raphe of pons","human","English","pontine raphe nucleus",,0 4995,"raphe pallidus nucleus","rat","English","nucleus raphe pallidus",,16 5905,"Raphe pontis","human","Latin","pontine raphe nucleus",,0 5907,"raphe pontis nucleus","rat","English","pontine raphe nucleus",,78 241,"Rathke's pouch","human","English",,"Rathke's pouch",0 5087,"Re","Macaca mulatta","Abbreviation","reuniens nucleus",,0 5928,"recesses of third ventricle","human","English",,"recesses of third ventricle",0 -701916874,"recessus chiasmatis","human","Latin","optic recess",,0 -908528171,"recessus epiphysis","human","Latin","pineal recess",,2 5910,"Recessus infundibularis","human","Latin","infundibular recess",,4 5911,"Recessus infundibuli","human","Latin","infundibular recess",,9 5913,"Recessus lateralis (ventriculi quarti)","human","Latin","lateral recess of fourth ventricle",,0 5914,"Recessus lateralis (ventriculi quarti)","Macaca mulatta","Latin","lateral recess of fourth ventricle",,0 5915,"Recessus lateralis ventriculi quarti","human","Latin","lateral recess of fourth ventricle",,0 5920,"Recessus opticus","human","Latin","optic recess",,0 5917,"Recessus pinealis","human","Latin","pineal recess",,6767 2478,"Recessus posterior prepontinus trigoni interpeduncularis","human","Latin","interpeduncular fossa",,0 5921,"Recessus praeopticus","human","Latin","optic recess",,3 2477,"Recessus prepontinus fossae intercruralis","human","Latin","interpeduncular fossa",,0 5922,"Recessus supraopticus","human","Latin","optic recess",,2 5927,"Recessus suprapinealis","human","Latin","suprapineal recess",,2 2790,"rectal gyrus","human","English","gyrus rectus",,8 2789,"rectus gyrus","human","English","gyrus rectus",,3 6551,"rectus sulcus","Macaca fascicularis","English","principal sulcus (M)",,1 1164628248,"rectus white matter","Unspecified","English","rectus white matter",,0 412,"red nucleus","Macaca fascicularis","English","RED NUCLEUS",,1454 413,"red nucleus","rat","English","RED NUCLEUS",,1454 411,"red nucleus","human","English","RED NUCLEUS",,1454 5666,"red nucleus, magnocellular part","rat","English","magnocellular part of red nucleus",,0 5673,"red nucleus, parvocellular part","human","English","parvocellular part of red nucleus",,0 5674,"red nucleus, parvocellular part","rat","English","parvocellular part of red nucleus",,0 244871796,"Regio cingularis","human","Latin",,"cingulate region",0 702,"Regio cingularis periarchicorticalis","human","Latin",,"periarchicortical cingulate areas",0 5950,"Regio diagonalis","human","Latin",,"Regio diagonalis",0 5951,"Regio diagonalis","Cercocebus torquatus","Latin",,"Regio diagonalis",0 1161,"Regio entorhinalis","human","Latin",,"Regio entorhinalis",0 -408568033,"Regio frontalis","human","Latin",,"frontal region",0 677466057,"Regio hippocampica","human","Latin",,"hippocampal region",0 211,"Regio hypothalamica anterior","human","Latin","ANTERIOR HYPOTHALAMIC REGION",,0 438857602,"Regio hypothalamica anterior - not otherwise specified","Unspecified","Latin","ANTERIOR HYPOTHALAMIC REGION - not otherwise specified",,0 3452,"Regio hypothalamica dorsalis","human","Latin",,"Regio hypothalamica dorsalis",0 215,"Regio hypothalamica intermedia","human","Latin","INTERMEDIATE HYPOTHALAMIC REGION",,1 -1014138963,"Regio hypothalamica intermedia - not otherwise specified","Unspecified","Latin","INTERMEDIATE HYPOTHALAMIC REGION - not otherwise specified",,1 217,"Regio hypothalamica posterior","human","Latin","POSTERIOR HYPOTHALAMIC REGION",,0 -517528706,"Regio hypothalamica posterior - not otherwise specified","Unspecified","Latin","POSTERIOR HYPOTHALAMIC REGION - not otherwise specified",,0 2408,"regio inferior of the hippocampus","Macaca fascicularis","English",,"regio inferior of the hippocampus",0 -199823958,"Regio insularis","human","Latin",,"insular region",0 1069,"Regio medioradiata","human","Latin",,"Area medioradiata",0 -1808397796,"Regio occipitalis","human","Latin",,"occipital region",0 595,"Regio olivaris inferior","Unspecified","Latin","INFERIOR OLIVARY COMPLEX",,0 -1596982607,"Regio olivaris inferior - not otherwise specified","Unspecified","Latin","INFERIOR OLIVARY COMPLEX - not otherwise specified",,0 580,"Regio olivaris superioris","Unspecified","Latin","SUPERIOR OLIVARY COMPLEX",,0 5828,"Regio parasubicularis","marmoset","Latin",,"parasubicular area",0 967243198,"Regio parietalis","human","Latin",,"parietal region",0 1200,"Regio periamygdalaris","human","Latin","periamygdaloid area",,0 695,"Regio peripalaeocorticalis claustralis","human","Latin",,"peripaleocortical claustral region",0 5953,"Regio periseptalis","Cercocebus torquatus","Latin",,"Regio periseptalis",0 5952,"Regio periseptalis","human","Latin",,"Regio periseptalis",0 -1939875844,"Regio postcentralis","human","Latin",,"postcentral region",0 702095921,"Regio praecentralis","human","Latin",,"precentral region",0 5810,"Regio praepiriformis","human","Latin","prepyriform area",,1 1162,"Regio praesubicularis","human","Latin",,"Regio praesubicularis",0 403,"Regio pretectalis","Macaca mulatta","Latin","PRETECTAL REGION",,0 3776,"Regio retrobulbaris","human","Latin","anterior olfactory nucleus",,1 3777,"Regio retrobulbaris","Cercocebus torquatus","Latin","anterior olfactory nucleus",,1 -605724851,"Regio retrocentralis","human","Latin",,"postcentral region",0 -1509509468,"Regio retrosplenialis","human","Latin",,"retrosplenial region",0 -1026733813,"Regio retrosplenialis","Cercopithecus","Latin",,"retrosplenial region",0 -109725456,"Regio rolandica","human","Latin",,"Regio rolandica",0 5945,"Regio septalis","human","Latin",,"septal region (Riley)",0 669316072,"Regio subfrontalis","human","Latin","INFERIOR FRONTAL GYRUS",,0 2394,"regio superior of the hippocampus","Macaca fascicularis","English","CA1 field",,10 83473721,"Regio temporalis","human","Latin",,"temporal region",0 475,"restiform body","human","English","inferior cerebellar peduncle",,45 3386,"reticular activating system","human","English",,"ascending reticular activating system",141 2416,"reticular formation","human","English",,"reticular formation",5608 2448,"reticular formation of medulla","human","English","MEDULLARY RETICULAR FORMATION",,6 2426,"reticular formation of midbrain","human","English","MIDBRAIN RETICULAR FORMATION",,6 2444,"reticular formation of pons","human","English","PONTINE RETICULAR FORMATION",,0 2421,"reticular formation-1","human","English",,"reticular formation",0 3559,"reticular nuclear group","human","English","thalamic reticular nucleus",,1 2473,"reticular nuclei","human","English",,"reticular nuclei",0 7155,"reticular nucleus of spinal cord","human","English",,"reticular nucleus of spinal cord",0 3561,"reticular nucleus of the thalamus","rat","English","thalamic reticular nucleus",,93 3560,"reticular nucleus of the thalamus","human","English","thalamic reticular nucleus",,93 3564,"reticular nucleus-2","human","English","thalamic reticular nucleus",,2 7154,"reticular process","human","English",,"reticular nucleus of spinal cord",0 3563,"reticular thalamic nucleus","rat","English","thalamic reticular nucleus",,159 3562,"reticular thalamic nucleus","human","English","thalamic reticular nucleus",,159 5057,"reticularis medullae pedunculi","Unspecified","English",,"Nucleus lateralis mesencephali",0 3565,"Reticulatum thalami (Hassler)","human","Latin","thalamic reticular nucleus",,0 6767,"reticulocerebellar fibers","human","English",,"reticulocerebellar fibers",0 6768,"reticulocerebellar tract","human","English",,"reticulocerebellar fibers",0 6841,"reticulospinal tract","human","English","reticulospinal tract",,25 5067,"reticulotegmental nucleus","Macaca fascicularis","English","reticulotegmental nucleus",,19 5066,"reticulotegmental nucleus","human","English","reticulotegmental nucleus",,19 5070,"reticulotegmental nucleus of pons","rat","English","reticulotegmental nucleus",,1 5069,"reticulotegmental nucleus of pons","Macaca fascicularis","English","reticulotegmental nucleus",,1 6915,"reticulothalamic tract","human","English","dorsal trigeminal tract",,0 6769,"retinotectal fibers","human","English",,"retinotectal fibers",0 6770,"retinotectal tract","human","English",,"retinotectal fibers",0 3775,"retrobulbar region","human","English","anterior olfactory nucleus",,14 5256,"retrochiasmatic area","human","English","retrochiasmatic area",,124 107,"retrocommissural hippocampus","human","English",,"retrocommissural hippocampus",3 3644,"retrofacial nucleus","human","English",,"retrofacial nucleus",80 5676,"retrolenticular part of internal capsule","human","English","retrolenticular part of internal capsule",,1 5680,"retrolenticular part of internal capsule","human","English","retrolenticular part of internal capsule",,1 3608,"retro-olivary cell group","human","English","retro-olivary cell group",,0 6554,"retro-olivary sulcus","human","English","retro-olivary sulcus",,2 1059,"retrosplenial area","human","English",,"retrosplenial region",30 -106918542,"retrosplenial cortex","Macaca mulatta","English",,"retrosplenial region",222 2602,"retrosplenial gyrus of hippocampus","human","English","fasciolar gyrus",,0 1056,"retrosplenial region","human","English",,"retrosplenial region",0 1249,"retrosubicular area","human","English",,"retrosubicular area 48",0 1247,"retrosubicular area 48","human","English",,"retrosubicular area 48",0 5077,"reuniens nucleus","Macaca fascicularis","English","reuniens nucleus",,26 5076,"reuniens nucleus","human","English","reuniens nucleus",,26 5085,"reuniens thalamic nucleus","rat","English","reuniens nucleus",,3 5084,"reuniens thalamic nucleus","human","English","reuniens nucleus",,3 7169,"Rexed's lamina I","human","English",,"Rexed's lamina I",0 7185,"Rexed's lamina II","human","English",,"Rexed's lamina II",0 7187,"Rexed's lamina III","human","English",,"Rexed's lamina III",0 7189,"Rexed's lamina IV","human","English",,"Rexed's lamina IV",0 7199,"Rexed's lamina IX","human","English",,"Rexed's lamina IX",0 7191,"Rexed's lamina V","human","English",,"Rexed's lamina V",0 7193,"Rexed's lamina VI","human","English",,"Rexed's lamina VI",0 7195,"Rexed's lamina VII","human","English",,"Rexed's lamina VII",0 7197,"Rexed's lamina VIII","human","English",,"Rexed's lamina VIII",0 7201,"Rexed's lamina X","human","English",,"Rexed's lamina X",0 7166,"Rexed's laminae","human","English",,"Rexed's laminae",0 6561,"rhinal fissure","human","English","rhinal sulcus",,43 6557,"rhinal sulcus","human","English","rhinal sulcus",,84 6558,"rhinal sulcus","Macaca mulatta","English","rhinal sulcus",,84 5971,"rhinencephalon","Unspecified","English",,"rhinencephalon",46 5970,"rhinencephalon","human","English",,"rhinencephalon",46 5972,"Rhinencephalon","human","Latin",,"rhinencephalon",46 5977,"rhinencephalon (Crosby)","human","English",,"rhinencephalon (Crosby)",0 5978,"Rhinencephalon (Nomina)","human","Latin",,"Rhinencephalon (Nomina)",0 24,"Rhombencephalon","human","Latin","HINDBRAIN",,1316 2480,"rhomboid fossa","human","English","rhomboid fossa",,27 5091,"rhomboid nucleus","rat","English","rhomboidal nucleus",,13 5092,"rhomboid thalamic nucleus","rat","English","rhomboidal nucleus",,3 5088,"rhomboidal nucleus","human","English","rhomboidal nucleus",,0 5089,"rhomboidal nucleus","Macaca fascicularis","English","rhomboidal nucleus",,0 6256,"Rolandic fissure","human","English","central sulcus",,30 513,"roof nuclei-2","human","English","DEEP CEREBELLAR NUCLEI",,0 4302,"roof nucleus-1","human","English","fastigial nucleus",,0 3404,"roof plate","human","English",,"roof plate",83 3244,"root of abducens nerve","rat","English","abducens nerve fibers",,0 2165,"root of facial nerve","rat","English","FACIAL NERVE FIBERS",,2 299,"root of hypoglossal nerve","rat","English","hypoglossal nerve fibers",,1 287,"root of oculomotor nerve","rat","English","oculomotor nerve fibers",,0 4502,"rostral and caudal linear nuclei of the raphe","rat","English","linear nucleus",,0 880,"rostral area 12","human","English",,"rostral area 12",0 1847578203,"rostral commissure","human","English","ANTERIOR COMMISSURE",,0 4422,"rostral interstitial nucleus of medial longitudinal fasciculus","human","English","rostral interstitial nucleus of medial longitudinal fasciculus",,1 4424,"rostral interstitial nucleus of MLF","Unspecified","English","rostral interstitial nucleus of medial longitudinal fasciculus",,1 3505,"rostral intralaminar nuclei","Macaca fascicularis","English","ROSTRAL INTRALAMINAR NUCLEI",,14 3504,"rostral intralaminar nuclei","human","English","ROSTRAL INTRALAMINAR NUCLEI",,14 5736,"rostral peduncle of thalamus","human","English","anterior thalamic peduncle",,0 1562509788,"rostral perforated substance","human","English","anterior perforated substance",,0 829,"rostral postcentral area 3","human","English",,"rostral postcentral area 3",0 1346135602,"rostral sulcus","human","English","rostral sulcus (M)",,3 6562,"rostral sulcus","Macaca mulatta","English","rostral sulcus (M)",,3 5983,"Rostrum corporis callosi","human","Latin","rostrum of corpus callosum",,0 5981,"Rostrum corpus callosi","human","Latin","rostrum of corpus callosum",,0 5979,"rostrum of corpus callosum","human","English","rostrum of corpus callosum",,0 5980,"rostrum of corpus callosum","Macaca fascicularis","English","rostrum of corpus callosum",,0 2505,"rostrum of corpus callosum (Mai)","human","English","genu of corpus callosum",,0 6773,"rubrobulbar fibers","human","English",,"rubrobulbar fibers",0 6774,"rubrobulbar tract","human","English",,"rubrobulbar fibers",0 6775,"rubro-olivary fibers","human","English",,"rubro-olivary fibers",0 6776,"rubro-olivary tract","human","English",,"rubro-olivary fibers",0 6777,"rubroreticular fibers","human","English",,"rubroreticular fibers",0 6778,"rubroreticular tract","human","English",,"rubroreticular fibers",0 6843,"rubrospinal tract","human","English","rubrospinal tract",,98 2138,"Russell's fasciculus","human","Latin","uncinate fasciculus of pons",,0 -2050193246,"S internal feature","Unspecified","English","S internal feature",,0 7213,"sacral autonomic nuclei","human","English",,"sacral autonomic nuclei",0 7115,"sacral parasympathetic cell column","human","English",,"sacral parasympathetic cell column",0 7162,"sacral segments","human","English",,"sacral segments",161 7163,"sacral segments of spinal cord","human","English",,"sacral segments",0 2303,"sagittal fissure","human","English","longitudinal fissure",,4 -6905592,"sagittal section","Unspecified","English",,"sagittal section",122 5118,"Sagulum","human","Latin",,"Sagulum",29 3490,"Scarpa's ganglion","human","English",,"vestibular ganglion",1 4042,"scattered nucleus of the septum","human","English","septofimbrial nucleus",,0 7047,"Schizocortex (Rose)","human","Latin",,"Schizocortex (Rose)",0 5567,"Schwalbe's nucleus","Macaca mulatta","English","medial vestibular nucleus",,0 213016989,"seahorse","human","English","HIPPOCAMPAL FORMATION",,7 1234,"second auditory area","human","English",,"second auditory area",0 1235,"second auditory cortex","human","English",,"second auditory area",0 1472,"second cranial nerve","human","English","optic nerve",,2 1896939440,"second part of root of facial nerve","human","English","descending fibers of facial nerve",,0 2703,"second posterior central gyrus","Unspecified","English","second posterior central gyrus (H)",,0 2554,"second short gyrus","Unspecified","English","second short gyrus (H)",,0 1080,"second somatic sensory area","human","English",,"secondary somesthetic area",0 6601,"second temporal sulcus","human","English","inferior temporal sulcus (H)",,0 2325,"secondary fissure","human","English","secondary fissure",,1 6461,"secondary intermediate sulcus","human","English",,"secondary intermediate sulcus (H)",0 1143,"secondary olfactory areas","human","English",,"secondary olfactory areas",0 1152,"secondary olfactory cortex","human","English","entorhinal area",,2 1151,"secondary olfactory cortical area (Carpenter)","human","English","entorhinal area",,0 1081,"secondary sensory cortex","human","English",,"secondary somesthetic area",0 1077,"secondary somesthetic area","human","English",,"secondary somesthetic area",0 6795,"secondary trigeminal pathways","human","English",,"secondary trigeminal tracts",0 6794,"secondary trigeminal tracts","human","English",,"secondary trigeminal tracts",0 1184,"secondary visual area","human","English",,"parastriate area 18",0 2380,"semiannular sulcus","human","English",,"semiannular sulcus",0 5199,"semicircular stria","human","English","stria terminalis",,0 7259,"semicortex","human","English",,"semicortex",0 7261,"semicortex (Rose)","human","English",,"semicortex (Rose)",0 3485,"semilunar ganglion","human","English",,"trigeminal ganglion",33 1208,"semilunar gyrus","human","English","periamygdaloid area",,1 3162,"semilunar lobule-1 (anterior)","human","English","anterior quadrangular lobule",,0 3197,"semilunar lobule-1 (posterior)","human","English","simple lobule",,0 3174,"semilunar lobule-2 (inferior)","human","English","inferior semilunar lobule",,0 3187,"semilunar lobule-2 (superior)","human","English","superior semilunar lobule",,0 5489,"semilunar nucleus","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,1 2003,"semilunar tract","human","English",,"comma tract of Schultze",0 1462,"semioval center","human","English","semioval center",,9 3142,"sensorimotor strip","human","English",,"sensorimotor strip",8 3331,"sensory branch of trigeminal nerve","human","English",,"sensory root of trigeminal nerve",0 1859,"sensory decussation","human","English","decussation of medial lemniscus",,0 5887,"sensory radiation","human","English",,"sensory radiation",0 3330,"sensory root of N. V","human","English",,"sensory root of trigeminal nerve",0 3324,"sensory root of trigeminal nerve","human","English",,"sensory root of trigeminal nerve",1 -1624563561,"sensory trigeminal nucleus","human","English","principal sensory nucleus of trigeminal nerve",,81 1252,"septal area","human","English",,"septal area",665 1280,"septal area (Crosby)","human","English",,"precommissural septum",0 1254,"septal area-1","human","English",,"septal area",0 5943,"septal area-2","human","English",,"septal region (Carpenter)",0 1013024762,"septal cortex","human","English",,"septal area",0 1256,"septal nuclei","Macaca fascicularis","English","SEPTAL NUCLEI",,2086 1255,"septal nuclei","human","English","SEPTAL NUCLEI",,2086 5960,"septal region","rat","English",,"septal region (Swanson)",356 5942,"septal region","human","English",,"septal region (Carpenter)",356 5944,"septal region (Riley)","Unspecified","English",,"septal region (Riley)",0 4037,"septofimbrial nucleus","rat","English","septofimbrial nucleus",,17 4553,"septohippocampal nucleus","rat","English",,"septohippocampal nucleus",22 4552,"septohippocampal nucleus","human","English",,"septohippocampal nucleus",22 1628,"septo-hypothalamo-mesencephalic continuum","human","English",,"septo-hypothalamo-mesencephalic continuum",0 7235,"septomarginal fasciculus","human","English",,"septomarginal fasciculus",0 5954,"septum","human","English","SEPTUM",,20157 5955,"septum","Cercocebus torquatus","English","SEPTUM",,20157 5956,"Septum","human","Latin","SEPTUM",,20157 1263,"Septum gangliosum","human","Latin",,"true septum",0 1450,"Septum gliosum","human","Latin","SEPTUM PELLUCIDUM",,0 1451,"Septum lucidum","human","Latin","SEPTUM PELLUCIDUM",,9 1445,"septum pellucidum","human","English","SEPTUM PELLUCIDUM",,2197 1446,"septum pellucidum","Macaca fascicularis","English","SEPTUM PELLUCIDUM",,2197 1448,"Septum pellucidum","human","Latin","SEPTUM PELLUCIDUM",,2197 1447,"Septum pellucidum","human","Latin","SEPTUM PELLUCIDUM",,2197 1449,"Septum pellucidum","Macaca mulatta","Latin","SEPTUM PELLUCIDUM",,2197 5958,"Septum pellucidum (BNA,PNA)","human","Latin","SEPTUM",,0 -1388553160,"Septum precommissurale","human","Latin",,"precommissural septum",0 5957,"Septum telencephali","human","Latin","SEPTUM",,3 1261,"Septum verum","human","Latin",,"true septum",4 2161,"seventh cranial nerve","human","English","facial nerve",,116 4930,"sexual dimorphic nucleus","human","English",,"sexual dimorphic nucleus",0 5220,"Sf","Macaca mulatta","Abbreviation","subfascicular nucleus",,0 5265,"SG","Macaca mulatta","Abbreviation","suprageniculate nucleus",,0 1310807249,"short arcuate bundles","human","English",,"short association fibers",0 5765648,"short association bundles","human","English",,"short association fibers",0 1380,"short association fibers","human","English",,"short association fibers",0 2551,"short gyri of insula","human","English","SHORT INSULAR GYRI (H)",,0 2549,"short insular gyri","human","English","SHORT INSULAR GYRI (H)",,1 1074,"SI","human","Abbreviation",,"primary somesthetic area",0 1083,"SII","human","Abbreviation",,"secondary somesthetic area",0 9,"simian fossa","Macaca","English","simian fossa (M)",,0 10,"simian fossa","Macaca fascicularis","English","simian fossa (M)",,0 5,"simian sulcus","Macaca","English",,"simian sulcus (M)",0 3189,"simple lobule","Macaca fascicularis","English","simple lobule",,19 3190,"simple lobule","rat","English","simple lobule",,19 3188,"simple lobule","human","English","simple lobule",,19 3195,"Simplex","Macaca nemestrina","Latin","simple lobule",,23023 3239,"sixth cranial nerve","human","English","abducens nerve",,104 1533627530,"sm internal feature","Unspecified","English","sm internal feature",,0 2056110213,"solitary cells of Meynert","Unspecified","English",,"solitary cells of Meynert",0 615,"solitary nuclear complex","human","English","SOLITARY NUCLEUS",,5 607,"solitary nucleus","human","English","SOLITARY NUCLEUS",,1107 604,"solitary tract","rat","English","solitary tract",,1757 603,"solitary tract","Macaca fascicularis","English","solitary tract",,1757 602,"solitary tract","human","English","solitary tract",,1757 1079,"somatic area II","human","English",,"secondary somesthetic area",0 799,"somatic motor I","human","English",,"primary motor cortex",0 1078,"somatic sensory area II","human","English",,"secondary somesthetic area",0 1073,"somatic sensory I","human","English",,"primary somesthetic area",0 1082,"somatic sensory II","human","English",,"secondary somesthetic area",0 1554,"special somatic afferents","human","English",,"special somatic afferents",0 1549,"special visceral afferents","human","English",,"special visceral afferents",0 1551,"special visceral efferents","human","English",,"special visceral efferents",0 3429,"specific sensory relay nuclei","human","English",,"specific sensory thalamic relay nuclei",0 3427,"specific sensory thalamic relay nuclei","human","English",,"specific sensory thalamic relay nuclei",0 3428,"specific thalamic nuclei","human","English",,"specific sensory thalamic relay nuclei",0 -1651943558,"spinal accessory nerve","human","English",,"accessory nerve",210 3305,"spinal accessory nerve-1","human","English",,"spinal part of accessory nerve",0 3289,"spinal accessory nerve-2","human","English",,"accessory nerve",0 3308,"spinal accessory nucleus","human","English",,"spinal accessory nucleus",0 1922,"spinal cord","human","English",,"spinal cord",68957 6865,"spinal lemniscus","human","English",,"spinothalamic tract",0 312,"spinal nerves","human","English",,"spinal nerves",2243 3310,"spinal nucleus of nerve XI","human","English",,"spinal accessory nucleus",0 -636842314,"spinal nucleus of the trigeminal","rat","English",,"SPINAL TRIGEMINAL NUCLEUS",0 3300,"spinal part of accessory nerve","human","English",,"spinal part of accessory nerve",0 3303,"spinal portion of eleventh cranial nerve","human","English",,"spinal part of accessory nerve",0 5152,"spinal root of trigeminal","human","English",,"spinal trigeminal tract",0 5147,"spinal tract of trigeminal nerve","human","English",,"spinal trigeminal tract",0 5148,"spinal tract of trigeminal nerve","rat","English",,"spinal trigeminal tract",0 748205753,"spinal trigeminal nucleus","human","English",,"SPINAL TRIGEMINAL NUCLEUS",889 911128392,"spinal trigeminal nucleus","Macaca fascicularis","English",,"SPINAL TRIGEMINAL NUCLEUS",0 1871878655,"spinal trigeminal nucleus","rat","English",,"SPINAL TRIGEMINAL NUCLEUS",0 5186,"spinal trigeminal nucleus, caudal part","rat","English","caudal part of spinal trigeminal nucleus",,0 404868397,"spinal trigeminal nucleus, interpolar part","rat","English","interpolar part of spinal trigeminal nucleus",,0 -1395112779,"spinal trigeminal nucleus, oral part","rat","English","oral part of spinal trigeminal nucleus",,0 5142,"spinal trigeminal tract","human","English",,"spinal trigeminal tract",127 5143,"spinal trigeminal tract","Macaca fascicularis","English",,"spinal trigeminal tract",127 5144,"spinal trigeminal tract","rat","English",,"spinal trigeminal tract",127 5159,"spinal trigeminal tract of medulla","Macaca fascicularis","English","spinal trigeminal tract of medulla",,0 5158,"spinal trigeminal tract of medulla","human","English","spinal trigeminal tract of medulla",,0 5156,"spinal trigeminal tract of pons","human","English","spinal trigeminal tract of pons",,0 5149,"spinal V tract","human","English",,"spinal trigeminal tract",0 5550,"spinal vestibular nucleus","human","English","inferior vestibular nucleus",,16 5551,"spinal vestibular nucleus","rat","English","inferior vestibular nucleus",,16 3028,"spindle cell layer","human","English",,"multiform layer",0 918142665,"spinobulbar tract (Noback)","human","English",,"spinoreticular tract",0 523,"spinocerebellum","human","English","ANTERIOR LOBE OF CEREBELLUM",,12 7146,"spinocervical fibers","human","English",,"spinocervical tract",0 7145,"spinocervical tract","human","English",,"spinocervical tract",93 7220,"spinocortical fibers","human","English",,"spinocortical tract",0 7219,"spinocortical tract","human","English",,"spinocortical tract",0 2938,"spinomedullary junction","human","English",,"spinomedullary junction",31 2939,"spino-medullary junction","human","English",,"spinomedullary junction",3 6845,"spino-olivary tract","human","English","spino-olivary tract",,2 7224,"spinopontine fibers","human","English",,"spinopontine tract",2 7223,"spinopontine tract","human","English",,"spinopontine tract",0 7144,"spinoreticular fibers","human","English",,"spinoreticular tract",0 7143,"spinoreticular tract","human","English",,"spinoreticular tract",21 7243,"spinospinal columns","human","English",,"Fasciculi proprii",0 7245,"spinospinal tract","human","English",,"Fasciculi proprii",0 7142,"spinotectal fibers","human","English",,"spinotectal tract",0 7141,"spinotectal tract","human","English",,"spinotectal tract",0 6860,"spinothalamic tract","human","English",,"spinothalamic tract",343 6861,"spinothalamic tract","rat","English",,"spinothalamic tract",343 6871,"spinothalamic tract","rat","English","spinothalamic tract of medulla",,343 6867,"spinothalamic tract of medulla","human","English","spinothalamic tract of medulla",,0 6868,"spinothalamic tract of medulla","Macaca fascicularis","English","spinothalamic tract of medulla",,0 6874,"spinothalamic tract of midbrain","human","English","spinothalamic tract of midbrain",,0 6872,"spinothalamic tract of pons","human","English","spinothalamic tract of pons",,0 7222,"spinovestibular fibers","human","English",,"spinovestibular tract",0 7221,"spinovestibular tract","human","English",,"spinovestibular tract",0 3480,"spiral ganglion","human","English",,"spiral ganglion",958 3933,"Spitzka's nucleus","Unspecified","English","central oculomotor nucleus",,0 6584,"splenial sulcus","human","English","subparietal sulcus",,17 5991,"Splenium corporis callosi","human","Latin","splenium of corpus callosum",,5 5987,"Splenium corpus callosi","human","Latin","splenium of corpus callosum",,0 5986,"splenium of corpus callosum","rat","English","splenium of corpus callosum",,16 5985,"splenium of corpus callosum","Macaca fascicularis","English","splenium of corpus callosum",,16 5984,"splenium of corpus callosum","human","English","splenium of corpus callosum",,16 1648727310,"spur of arcuate sulcus","Macaca","English","spur of arcuate sulcus (M)",,0 1555,"SSA","human","Abbreviation",,"special somatic afferents",0 3256,"statoacoustic nerve","Macaca fascicularis","English","vestibulocochlear nerve",,11 3257,"stato-acoustic nerve","human","English","vestibulocochlear nerve",,4 304,"statoacoustic nerve fibers","human","English","vestibulocochlear nerve fibers",,0 305,"statoacoustic nerve fibers","human","English","vestibulocochlear nerve fibers",,0 6636,"stem of lateral sulcus","Unspecified","English",,"stem of lateral sulcus",0 6637,"stem of Sylvian fissure","human","Latin",,"stem of lateral sulcus",0 2788,"straight gyrus","human","English","gyrus rectus",,4 -1385299435,"Strata (grisea et alba) colliculi cranialis","human","Latin",,"layers of superior colliculus",0 779434930,"Strata (grisea et alba) colliculi superioris","human","Latin",,"layers of superior colliculus",0 5993,"Stratum alba colliculi rostralis","human","Latin",,"Stratum alba colliculi superioris",0 5992,"Stratum alba colliculi superioris","human","Latin",,"Stratum alba colliculi superioris",0 6015,"Stratum album intermediale","human","Latin","middle white layer of superior colliculus",,9 6013,"Stratum album mediale","human","Latin","middle white layer of superior colliculus",,0 6011,"Stratum album profundum","human","Latin","deep white layer of superior colliculus",,8 5995,"Stratum cinereum","human","Latin","superficial gray layer of superior colliculus",,1 6027,"Stratum gliosum subependymale","Macaca mulatta","Latin",,"Stratum gliosum subependymale",0 6029,"Stratum granulosum (cerebelli)","human","Latin",,"granular layer of cerebellar cortex",0 6031,"Stratum grisea colliculi rostralis","human","Latin",,"Stratum grisea colliculi superioris",0 6030,"Stratum grisea colliculi superioris","human","Latin",,"Stratum grisea colliculi superioris",0 6114,"Stratum griseum centrale","human","Latin",,"central gray substance",53 6034,"Stratum griseum et fibrosum periventriculare","human","Latin",,"periventricular layer",0 6003,"Stratum griseum intermediale","human","Latin","middle gray layer of superior colliculus",,33 6001,"Stratum griseum mediale","human","Latin","middle gray layer of superior colliculus",,1 6032,"Stratum griseum profundum","human","Latin",,"Stratum grisea colliculi superioris",36 6009,"Stratum griseum profundum","human","Latin","deep gray layer of superior colliculus",,36 5996,"Stratum griseum superficiale","human","Latin","superficial gray layer of superior colliculus",,162 6006,"Stratum intermedium pedunculi","human","Latin",,"peduncle of substantia nigra",0 3045,"Stratum lacunosum-moleculare","human","Latin",,"Stratum lacunosum-moleculare",0 5999,"Stratum lemnisci","human","Latin","STRATUM LEMNISCI OF SUPERIOR COLLICULUS",,1 5998,"stratum lemnisci of superior colliculus","human","English","STRATUM LEMNISCI OF SUPERIOR COLLICULUS",,0 2451,"Stratum medullare superficiale","human","Latin",,"superficial medullary stratum",0 707386875,"Stratum moleculare","human","Latin",,"molecular layer",0 6036,"Stratum moleculare (cerebelli)","human","Latin",,"molecular layer of cerebellar cortex",0 6041,"Stratum neurium piriformium","human","Latin",,"Purkinje cell layer",0 6040,"Stratum neuronorum piriformium","human","Latin",,"Purkinje cell layer",0 6017,"Stratum opticum","human","Latin","superficial white layer of superior colliculus",,215 3050,"Stratum oriens","human","Latin",,"Stratum oriens",0 -561281248,"Stratum plexiforme","human","Latin",,"molecular layer",0 6037,"Stratum plexiforme","human","Latin",,"molecular layer of cerebellar cortex",0 1526,"Stratum profundum colliculi superioris","human","Latin",,"Colliculus superior, stratum profundum",0 1529,"Stratum profundum medullare","human","Latin",,"Colliculus superior, stratum profundum",0 1527,"Stratum profundum quadrigemini anterioris","human","Latin",,"Colliculus superior, stratum profundum",0 1528,"Stratum profundum tecti","human","Latin",,"Colliculus superior, stratum profundum",0 3047,"Stratum pyramidale hippocampi","human","Latin",,"Stratum pyramidale hippocampi",0 3051,"Stratum radiatum","human","Latin",,"Stratum radiatum",903 6020,"Stratum sagittale internum","human","Latin",,"internal sagittal stratum",0 -1255514230,"Stratum subcallosum","human","Latin",,"subcallosal fasciculus",0 3053,"Stratum superficiale pontis","human","Latin",,"superficial pontine stratum",0 6022,"Stratum zonale colliculi superioris","human","Latin","zonal layer of superior colliculus",,0 6023,"Stratum zonale of midbrain","human","Latin","zonal layer of superior colliculus",,0 6024,"stratum zonale of superior colliculus","human","English","zonal layer of superior colliculus",,0 6025,"stratum zonale of thalamus","human","English","stratum zonale of thalamus",,0 6026,"Stratum zonale thalami","human","Latin","stratum zonale of thalamus",,0 3876,"Stria diagonalis","human","Latin","diagonal band",,0 3878,"Stria diagonalis (Broca)","human","Latin","diagonal band",,0 6088,"Stria habenularis","human","Latin","stria medullaris of thalamus",,0 6095,"Stria intermedia olfactoria","human","Latin",,"intermediate olfactory stria",0 1315,"Stria laminae ganglionaris","human","Latin",,"internal band of Baillarger",0 6050,"Stria laminae granularis externa","human","Latin",,"Stria laminae granularis externa",0 1311,"Stria laminae granularis interna","human","Latin",,"external band of Baillarger",0 6051,"Stria laminae molecularis","human","Latin",,"Stria laminae molecularis",0 6052,"Stria laminae plexiformis","human","Latin",,"Stria laminae molecularis",0 1314,"Stria laminae pyramidalis interna","human","Latin",,"internal band of Baillarger",0 6068,"Stria Lancisii","human","Latin","medial longitudinal stria",,0 6055,"Stria longitudinalis externa","human","Latin","lateral longitudinal stria",,0 6065,"Stria longitudinalis interna","human","Latin","medial longitudinal stria",,0 6054,"Stria longitudinalis lateralis","human","Latin","lateral longitudinal stria",,0 6061,"Stria longitudinalis medialis","human","Latin","medial longitudinal stria",,5 6087,"Stria medullaris","Macaca fascicularis","Latin","stria medullaris of thalamus",,127 6081,"stria medullaris of thalamus","human","English","stria medullaris of thalamus",,0 6082,"stria medullaris of thalamus","Macaca fascicularis","English","stria medullaris of thalamus",,0 6083,"stria medullaris of thalamus","rat","English","stria medullaris of thalamus",,0 6085,"Stria medullaris thalami","Macaca fascicularis","Latin","stria medullaris of thalamus",,15 6084,"Stria medullaris thalami","human","Latin","stria medullaris of thalamus",,15 6086,"Stria medullaris thalamica","human","Latin","stria medullaris of thalamus",,0 1320,"stria of Gennari","human","English",,"band of Gennari",0 1304,"stria of Kaes","human","English",,"band of Kaes-Bechterew",0 1306,"stria of Vicq d'Azyr","human","English",,"band of Kaes-Bechterew",0 6090,"Stria olfactoria lateralis","human","Latin","lateral olfactory stria",,0 6091,"Stria olfactoria lateralis","Macaca fascicularis","Latin","lateral olfactory stria",,0 6099,"Stria olfactoria medialis","human","Latin",,"medial olfactory stria",0 5198,"Stria semicircularis","human","Latin","stria terminalis",,0 3905,"Stria sublenticularis","human","Latin",,"sublenticular stria",0 6058,"Stria tecta","human","Latin","lateral longitudinal stria",,0 5193,"stria terminalis","human","English","stria terminalis",,1657 5196,"stria terminalis","rat","English","stria terminalis",,1657 5194,"Stria terminalis","human","Latin","stria terminalis",,1657 5195,"Stria terminalis","Macaca fascicularis","Latin","stria terminalis",,1657 6043,"Striae acusticae dorsalis","Macaca fascicularis","Latin","dorsal acoustic stria",,0 6045,"Striae acusticae intermedius","Unspecified","Latin","intermediate acoustic stria",,0 6049,"Striae acusticae ventralis","Unspecified","Latin","ventral acoustic stria",,0 6104,"Striae griseae caudatolenticulares transcapsulares","human","Latin",,"transcapsular caudatolenticular gray striae",0 6076,"striae medullares","human","English","striae medullares",,7 6077,"Striae medullares (ventriculi quarti)","human","Latin","striae medullares",,0 6080,"striae medullares of fourth ventricle","human","English","striae medullares",,0 6079,"Striae medullares ventriculi quarti","human","Latin","striae medullares",,0 3720,"striatal cell bridges","human","English",,"striatal cell bridges",0 810,"striate area","human","English",,"striate area 17",41 806,"striate area 17","human","English",,"striate area 17",0 811,"striate cortex","human","English",,"striate area 17",1411 -1352418020,"striatonigral fibers","human","English",,"striatonigral fibers",15 -185891468,"striatopallidal fibers","human","English",,"striatopallidal fibers",0 2548,"striatopallidal system","human","English",,"striatopallidal system",0 1709,"striatum","human","English","STRIATUM",,27430 1710,"striatum","Macaca fascicularis","English","STRIATUM",,27430 112,"striatum (Carpenter)","human","English",,"corpus striatum",0 6779,"strionigral fibers","human","English",,"strionigral fibers",0 6780,"strionigral tract","human","English",,"strionigral fibers",0 6781,"striopallidal fibers","human","English",,"striopallidal fibers",0 6782,"striopallidal tract","human","English",,"striopallidal fibers",0 1321,"stripe of Gennari","human","English",,"band of Gennari",0 1305,"stripe of Kaes","human","English",,"band of Kaes-Bechterew",0 1307,"stripe of Vicq d'Azyr","human","English",,"band of Kaes-Bechterew",0 1309,"stripes of Baillarger","human","English",,"bands of Baillarger",0 5948,"stylus of septum pellucidum","human","English",,"septal region (Riley)",0 5947,"Stylus septi","human","Latin",,"septal region (Riley)",0 5949,"Stylus septi pellucidi","human","Latin",,"septal region (Riley)",0 1264,"subcallosal area","human","English","subcallosal area",,9 1265,"subcallosal area","human","English","subcallosal area",,9 2082,"subcallosal bundle","human","English",,"subcallosal fasciculus",0 2074,"subcallosal fasciculus","human","English",,"subcallosal fasciculus",7 2763,"subcallosal gyrus","human","English","paraterminal gyrus",,8 1281,"subcallosal gyrus (Crosby)","human","English",,"subcallosal gyrus (Crosby)",0 2083,"subcallosal stratum","human","English",,"subcallosal stratum (Mai)",0 2084,"subcaudate terminal island","human","English",,"subcaudate terminal island",0 834,"subcentral area 43","human","English",,"subcentral area 43",0 6573,"subcentral dimple","Macaca mulatta","English","anterior subcentral sulcus",,0 5603,"subcommissural organ","human","English","subcommissural organ",,288 5604,"subcommissural organ","Macaca fascicularis","English","subcommissural organ",,288 5605,"subcommissural organ","rat","English","subcommissural organ",,288 3474,"subcortical gray","human","English",,"basal ganglia (Crosby)",104 5214,"subcuneiform area of midbrain","human","English","subcuneiform nucleus",,0 5212,"subcuneiform nucleus","human","English","subcuneiform nucleus",,2 6147,"subependymal gray","human","English",,"subependymal gray",0 5217,"subfascicular nucleus","Macaca fascicularis","English","subfascicular nucleus",,1 5610,"subfornical organ","rat","English","subfornical organ",,858 5609,"subfornical organ","Macaca fascicularis","English","subfornical organ",,858 5608,"subfornical organ","human","English","subfornical organ",,858 1000,"subgenual area 25","human","English",,"subgenual area 25",0 4335,"subhabenular nucleus","human","English",,"subhabenular nucleus",0 5790,"subicular complex","human","English",,"subicular complex",111 6105,"subiculum","human","English","subiculum",,1190 6108,"subiculum","rat","English","subiculum",,1190 6106,"Subiculum","human","Latin","subiculum",,1190 6107,"Subiculum","Macaca fascicularis","Latin","subiculum",,1190 6109,"subiculum hippocampi","human","English","subiculum",,0 5230,"sublenticular gray","human","English",,"sublenticular gray",0 5681,"sublenticular part of internal capsule","human","English","sublenticular part of internal capsule",,0 5685,"sublenticular part of internal capsule","human","English","sublenticular part of internal capsule",,0 3904,"sublenticular stria","human","English",,"sublenticular stria",0 5223,"sublentiform nucleus","human","English","sublentiform nucleus",,2 5683,"sublentiform part (internal capsule)","human","English","sublenticular part of internal capsule",,0 5100,"sublingual nucleus","Macaca fascicularis","English","sublingual nucleus",,1 5225,"submedial nucleus","human","English","submedial nucleus",,8 5226,"submedial nucleus","Macaca fascicularis","English","submedial nucleus",,8 5228,"submedial nucleus of thalamus","rat","English","submedial nucleus",,0 5184,"Subnucleus caudalis","human","Latin","caudal part of spinal trigeminal nucleus",,233 6160,"Subnucleus compactus","human","Latin",,"Subnucleus compactus (Olszewski & Baxter)",0 6161,"Subnucleus compactus, pars alpha","human","Latin",,"Subnucleus compactus, pars alpha",0 6162,"Subnucleus compactus, pars beta","human","Latin",,"Subnucleus compactus, pars beta",0 6163,"Subnucleus compactus, pars gamma","human","Latin",,"Subnucleus compactus, pars gamma",0 5135,"Subnucleus dorsolateralis","Unspecified","Latin","dorsolateral subnucleus of solitary tract",,0 5137,"Subnucleus dorsomedialis","Unspecified","Latin","dorsomedial subnucleus of solitary tract",,2 5133,"Subnucleus medialis","Unspecified","Latin","medial subnucleus of solitary tract",,12 5141,"Subnucleus parvicellularis","Unspecified","Latin","parvicellular subnucleus of solitary tract",,0 6164,"Subnucleus reticulatus","human","Latin",,"Subnucleus reticulatus",0 4081,"Subnucleus rostralis","human","Latin","oral part of ventral lateral nucleus",,0 -1520660634,"Subnucleus rostralis","human","Latin","oral part of spinal trigeminal nucleus",,0 5139,"Subnucleus ventrolateralis","Unspecified","Latin","ventrolateral subnucleus of solitary tract",,1 4727,"subparafascicular thalamic nucleus","human","English",,"subparafascicular thalamic nucleus",19 6581,"subparietal sulcus","Macaca fascicularis","English","subparietal sulcus",,1 6580,"subparietal sulcus","Macaca mulatta","English","subparietal sulcus",,1 6579,"subparietal sulcus","human","English","subparietal sulcus",,1 1068,"Subregio medioradiata","human","Latin",,"Area medioradiata",0 386687503,"Subregio postcingularis","human","Latin",,"Subregio postcingularis",0 703992070,"Subregio praecingularis","human","Latin",,"Subregio praecingularis",0 1623995378,"Substantia alba myelencephali - not otherwise specified","Unspecified","Latin","MEDULLARY WHITE MATTER - not otherwise specified",,0 458,"Substantia alba myelenecephali","Unspecified","Latin","MEDULLARY WHITE MATTER",,0 454,"Substantia centralis medullaris cerebelli","human","Latin","CEREBELLAR WHITE MATTER",,0 1464,"Substantia centralis medullaris cerebri","human","Latin","semioval center",,0 -2006725565,"substantia corticalis","human","Latin",,"neocortex",5 441,"Substantia ferruginea","human","Latin","locus ceruleus",,0 7182,"Substantia gelatinosa","human","Latin",,"Rexed's lamina II",723 7183,"Substantia gelatinosa of Rolando","human","Latin",,"Rexed's lamina II",3 7136,"Substantia gelatinosa spinalis","Macaca fascicularis","Latin",,"central gelatinous substance",0 6149,"substantia gliosa (Mai)","human","English",,"subependymal gray",0 7135,"substantia gliosa (spinalis)","human","Latin",,"central gelatinous substance",0 6146,"Substantia gliosa centralis","Macaca mulatta","Latin",,"grey commissure",0 6148,"Substantia gliosa subependymalis","human","Latin",,"subependymal gray",0 6119,"Substantia grisea centralis","Macaca fascicularis","Latin","central gray substance of midbrain",,67 6118,"Substantia grisea centralis","human","Latin","central gray substance of midbrain",,67 6141,"Substantia grisea centralis","human","Latin","central gray substance of medulla",,67 6111,"Substantia grisea centralis","human","Latin",,"central gray substance",67 6134,"Substantia grisea centralis","human","Latin","central gray substance of pons",,67 6117,"Substantia grisea centralis mesencephali","human","Latin","central gray substance of midbrain",,5 3899,"substantia innominata","rat","English","substantia innominata",,1124 3898,"substantia innominata","human","English","substantia innominata",,1124 3900,"Substantia innominata","Macaca fascicularis","Latin","substantia innominata",,1124 3903,"Substantia innominata of Meynert","human","Latin","substantia innominata",,0 3901,"Substantia innominata of Reichert","human","Latin","substantia innominata",,1 3902,"Substantia innominata of Reil","human","Latin","substantia innominata",,0 -1065368541,"Substantia medullaris - not otherwise specified","Unspecified","Latin","PARIETAL WHITE MATTER - not otherwise specified",,7 -135573866,"Substantia medullaris - not otherwise specified","Unspecified","Latin","OCCIPITAL LOBE WHITE MATTER - not otherwise specified",,7 7318145,"Substantia medullaris angularis","Unspecified","Latin","angular white matter",,0 1210976560,"Substantia medullaris annectens","Unspecified","Latin","annectant white matter",,0 453,"Substantia medullaris cerebelli","human","Latin","CEREBELLAR WHITE MATTER",,1 7066,"Substantia medullaris cerebri","Unspecified","Latin","CEREBRAL WHITE MATTER",,0 1963646607,"Substantia medullaris cerebri - not otherwise specified","Unspecified","Latin","CEREBRAL WHITE MATTER - not otherwise specified",,0 1937741474,"Substantia medullaris cingulatus","Unspecified","Latin","CINGULATE WHITE MATTER",,0 775193863,"Substantia medullaris cinguli anterior","Unspecified","Latin","anterior cingulate white matter",,0 414325269,"Substantia medullaris cuneatus","Unspecified","Latin","cuneate white matter",,0 -782926258,"Substantia medullaris entorhinalis","Unspecified","Latin","entorhinal white matter",,0 1306346528,"Substantia medullaris frontalis - not otherwise specified","Unspecified","Latin","FRONTAL WHITE MATTER - not otherwise specified",,0 -278353831,"Substantia medullaris frontalis inferioris","Unspecified","Latin","inferior frontal white matter",,0 922813508,"Substantia medullaris frontalis medius","Unspecified","Latin","middle frontal white matter",,0 967832216,"Substantia medullaris frontalis superior","Unspecified","Latin","superior frontal white matter",,0 1295512734,"Substantia medullaris fronto-orbitalis","Unspecified","Latin","fronto-orbital white matter",,0 754875268,"Substantia medullaris fusiformis","Unspecified","Latin","fusiform white matter",,0 75221353,"Substantia medullaris isthmus cingul","Unspecified","Latin","isthmus cingulate white matter",,0 1087918918,"Substantia medullaris lingualis","Unspecified","Latin","lingual white matter",,0 -299756572,"Substantia medullaris lobus occipitalis","Unspecified","Latin","OCCIPITAL LOBE WHITE MATTER",,0 459,"Substantia medullaris myelencephali","human","Latin","MEDULLARY WHITE MATTER",,0 -1762502529,"Substantia medullaris occipitalis","Unspecified","Latin","occipital white matter",,0 -288155629,"Substantia medullaris occipitalis inferior","Unspecified","Latin","inferior occipital white matter",,0 1192166667,"Substantia medullaris orbitalis lateralis","Unspecified","Latin","lateral orbital white matter",,0 1961886372,"Substantia medullaris orbitalis medialis","Unspecified","Latin","medial orbital white matter",,0 2066122413,"Substantia medullaris parahippocampalis","Unspecified","Latin","PARAHIPPOCAMPAL WHITE MATTER",,0 -1093096965,"Substantia medullaris parahippocampalis posterior","Unspecified","Latin","posterior parahippocampal white matter",,0 -938873912,"Substantia medullaris parietalis","Unspecified","Latin","PARIETAL WHITE MATTER",,0 214399199,"Substantia medullaris parietalis superior","Unspecified","Latin","superior parietal white matter",,0 -2098733940,"Substantia medullaris postcentralis","Unspecified","Latin","postcentral white matter",,0 -496078917,"Substantia medullaris precentralis","Unspecified","Latin","precentral white matter",,0 -782635352,"Substantia medullaris precuneatus","Unspecified","Latin","precuneate white matter",,0 -106802887,"Substantia medullaris rectus","Unspecified","Latin","rectus white matter",,0 1138586242,"Substantia medullaris supramarginalis","Unspecified","Latin","supramarginal white matter",,0 1124547405,"Substantia medullaris temporalis","Unspecified","Latin","TEMPORAL WHITE MATTER",,0 -583492425,"Substantia medullaris temporalis - not otherwise specified","Unspecified","Latin","TEMPORAL WHITE MATTER - not otherwise specified",,0 -1354525058,"Substantia medullaris temporalis inferior","Unspecified","Latin","inferior temporal white matter",,0 -1404667239,"Substantia medullaris temporalis medius","Unspecified","Latin","middle temporal white matter",,0 129569643,"Substantia medullaris temporalis superior","Unspecified","Latin","superior temporal white matter",,0 425581770,"Substantia medullars cinguli posterior","Unspecified","Latin","posterior cingulate white matter",,53 358,"substantia nigra","rat","English","SUBSTANTIA NIGRA",,11569 357,"substantia nigra","Macaca fascicularis","English","SUBSTANTIA NIGRA",,11569 356,"substantia nigra","human","English","SUBSTANTIA NIGRA",,11569 360,"Substantia nigra","Macaca fascicularis","Latin","SUBSTANTIA NIGRA",,11569 359,"Substantia nigra","human","Latin","SUBSTANTIA NIGRA",,11569 6165,"Substantia nigra (Francois)","Macaca fascicularis","Latin",,"Substantia nigra (Francois)",0 6166,"Substantia nigra (Poirier)","Macaca mulatta","Latin",,"Substantia nigra (Poirier)",0 -730451550,"substantia nigra (Soemmerringi)","human","Latin","SUBSTANTIA NIGRA",,0 6156,"substantia nigra, compact part","rat","English","pars compacta",,0 6153,"Substantia nigra, pars compacta","human","Latin","pars compacta",,0 6154,"Substantia nigra, pars compacta","Macaca fascicularis","Latin","pars compacta",,0 6157,"Substantia nigra, pars compacta (Francois)","Macaca fascicularis","Latin",,"Substantia nigra, pars compacta (Francois)",0 6158,"Substantia nigra, pars compacta (Poirier)","Macaca mulatta","Latin",,"Substantia nigra, pars compacta (Poirier)",0 6177,"Substantia nigra, pars diffusa","Macaca fascicularis","Latin","pars reticulata",,0 4705,"Substantia nigra, pars dorsalis","Macaca mulatta","Latin",,"parabrachial pigmented nucleus",0 6167,"Substantia nigra, pars lateralis","human","Latin",,"pars lateralis of substantia nigra",0 6168,"Substantia nigra, pars lateralis","Macaca fascicularis","Latin",,"pars lateralis of substantia nigra",0 6171,"Substantia nigra, pars mixta","Macaca fascicularis","Latin",,"mixed cell part of substantia nigra",0 6176,"substantia nigra, pars reticulata","human","English","pars reticulata",,0 6175,"Substantia nigra, pars reticulata","human","Latin","pars reticulata",,0 6180,"Substantia nigra, pars reticulata (Francois)","Macaca fascicularis","Latin",,"Substantia nigra, pars reticulata (Francois)",0 6181,"Substantia nigra, pars reticulata (Poirier)","Macaca mulatta","Latin",,"Substantia nigra, pars reticulata (Poirier)",0 6179,"substantia nigra, reticular part","rat","English","pars reticulata",,0 3598,"substantia nigral channel of motor thalamus","human","English",,"anterolateral region of motor thalamus",0 6187,"Substantia perforata anterior","Macaca fascicularis","Latin","anterior perforated substance",,0 6186,"Substantia perforata anterior","human","Latin","anterior perforated substance",,0 6201,"Substantia perforata intercruralis","human","Latin",,"posterior perforated substance",0 6200,"Substantia perforata interpeduncularis","human","Latin",,"posterior perforated substance",0 6198,"Substantia perforata posterior","human","Latin",,"posterior perforated substance",0 6199,"Substantia perforata posterior","Macaca mulatta","Latin",,"posterior perforated substance",0 -1819199447,"substantia perforata posterior (Tarini)","human","Latin",,"posterior perforated substance",0 2420,"Substantia reticularis","Macaca mulatta","Latin",,"reticular formation",7 2419,"Substantia reticularis","human","Latin",,"reticular formation",7 2425,"Substantia reticularis mesencephali","Macaca mulatta","Latin","MIDBRAIN RETICULAR FORMATION",,1 2086,"substriatal terminal island","human","English",,"substriatal terminal island",0 2092,"subthalamic fasciculus","human","English",,"subthalamic fasciculus",0 5231,"subthalamic nucleus","human","English","subthalamic nucleus",,960 5232,"subthalamic nucleus","Macaca fascicularis","English","subthalamic nucleus",,960 5233,"subthalamic nucleus","rat","English","subthalamic nucleus",,960 5242,"subthalamic nucleus (of Luys)","human","English","subthalamic nucleus",,5 248,"subthalamic region","human","English","SUBTHALAMUS",,41 5246,"subthalamic reticular nucleus","human","English",,"subthalamic reticular nucleus",0 6906,"subthalamicotegmental tract","human","English",,"subthalamicotegmental tract",0 244,"subthalamus","human","English","SUBTHALAMUS",,142 245,"subthalamus","Macaca fascicularis","English","SUBTHALAMUS",,142 247,"Subthalamus","human","Latin","SUBTHALAMUS",,142 246,"Subthalamus","human","Latin","SUBTHALAMUS",,142 183910648,"subthalamus - not otherwise specified","Unspecified","English","SUBTHALAMUS - not otherwise specified",,142 -1851245671,"Subthalamus - not otherwise specified","Unspecified","Latin","SUBTHALAMUS - not otherwise specified",,142 2090,"subventricular terminal island","human","English",,"subventricular terminal island",0 6205,"Sulci cerebrales","human","Latin",,"cerebral sulci",0 6204,"Sulci cerebri","human","Latin",,"cerebral sulci",0 6361,"Sulci interlobares","human","Latin",,"interlobar fissures",0 935310932,"sulci occipitales superiores","human","Latin","anterior occipital sulcus (H)",,0 6478,"Sulci orbitales","human","Latin","orbital sulcus (H)",,0 6207,"Sulci temporales transversi","human","Latin","transverse temporal sulcus (H)",,0 2244,"sulcomarginal fasciculus","human","English",,"sulcomarginal fasciculus",3 7050,"sulcomarginal fasciculus","human","English",,"medial vestibulospinal tract",3 6467,"Sulcus angularis","human","Latin",,"angular sulcus (H)",0 1794319149,"sulcus anterior insulae (Reili)","human","Latin",,"anterior marginal sulcus of insula (H)",0 6643,"Sulcus anterolateralis","human","Latin","ventrolateral sulcus",,0 -1753129128,"Sulcus arcuatis","Macaca mulatta","Latin",,"arcuate sulcus",0 6224,"Sulcus basilaris","human","Latin","basilar sulcus",,0 6225,"Sulcus basilaris pontis","human","Latin","basilar sulcus",,0 6524,"Sulcus bulbopontinus","human","Latin","inferior pontine sulcus",,0 6228,"Sulcus calcarinus","human","Latin","calcarine sulcus",,2 6229,"Sulcus calcarinus","Macaca fascicularis","Latin","calcarine sulcus",,2 6235,"Sulcus calcarinus anterior","human","Latin","anterior calcarine sulcus (H)",,0 6243,"Sulcus calcarinus inferior","Unspecified","Latin","inferior calcarine sulcus (M)",,0 6238,"Sulcus calcarinus posterior","human","Latin","posterior calcarine sulcus (H)",,0 6247,"Sulcus calcarinus superior","Unspecified","Latin","superior calcarine sulcus (M)",,0 6278,"Sulcus callosomarginalis","human","Latin","cingulate sulcus",,0 6252,"Sulcus centralis","human","Latin","central sulcus",,1 -77147527,"Sulcus centralis","Macaca mulatta","Latin","central sulcus",,1 1027407161,"sulcus centralis (Rolandi)","human","Latin","central sulcus",,0 6253,"Sulcus centralis cerebri","human","Latin","central sulcus",,0 6260,"Sulcus centralis insulae","human","Latin","central insular sulcus",,0 1104322212,"sulcus cerebri lateralis (Sylvii)","human","Latin","lateral sulcus",,0 6277,"Sulcus cingulatus","human","Latin","cingulate sulcus",,0 6276,"Sulcus cinguli","human","Latin","cingulate sulcus",,8 6286,"Sulcus circularis insulae","human","Latin","circular sulcus of insula",,1 6302,"Sulcus collateralis","human","Latin","collateral sulcus",,0 6309,"Sulcus corporis callosi","human","Latin","callosal sulcus",,3 6311,"Sulcus cunei","human","Latin",,"Sulcus cunei",0 6639,"Sulcus diagonalis","human","Latin","diagonal sulcus (H)",,0 6314,"Sulcus dorsolateralis","human","Latin","dorsolateral sulcus",,0 6321,"Sulcus ectocalcarinus","Unspecified","Latin","ectocalcarine sulcus (M)",,0 6346,"sulcus f1","human","English","superior frontal sulcus (H)",,0 6333,"sulcus f2","human","English","inferior frontal sulcus (H)",,0 6338,"sulcus f3","human","English","middle frontal sulcus (H)",,0 6328,"Sulcus fimbrio-dentatus","human","Latin","fimbriodentate fissure",,0 668654385,"Sulcus frontalis","Macaca mulatta","Latin","principal sulcus (M)",,0 6331,"Sulcus frontalis inferior","human","Latin","inferior frontal sulcus (H)",,0 6632,"sulcus frontalis intermedius","human","English",,"medial frontal sulcus (H)",0 6340,"Sulcus frontalis intermedius","human","Latin","middle frontal sulcus (H)",,0 6336,"Sulcus frontalis medius","human","Latin","middle frontal sulcus (H)",,0 6337,"Sulcus frontalis medius (Eberstaller)","human","Latin","middle frontal sulcus (H)",,0 6345,"Sulcus frontalis primus","human","Latin","superior frontal sulcus (H)",,0 6332,"Sulcus frontalis secundus","human","Latin","inferior frontal sulcus (H)",,0 6343,"Sulcus frontalis superior","human","Latin","superior frontal sulcus (H)",,2 6389,"Sulcus fronto-marginalis","human","Latin",,"frontomarginal sulcus (H)",0 6482,"Sulcus fronto-orbitalis","Papio ursinus","Latin","fronto-orbital sulcus",,0 6481,"Sulcus fronto-orbitalis","human","Latin","fronto-orbital sulcus",,0 6349,"Sulcus habenulae","human","Latin","habenular sulcus",,0 6350,"Sulcus habenularis","human","Latin","habenular sulcus",,0 6353,"Sulcus hippocampi","human","Latin","hippocampal sulcus",,0 -177588952,"sulcus horizontalis cerebelli","human","Latin","horizontal fissure",,0 6358,"Sulcus hypothalamicus","human","Latin","hypothalamic sulcus",,1 229687292,"sulcus hypothalamicus (Monroi)","human","Latin","hypothalamic sulcus",,0 292374537,"sulcus inferior insulae (Reilii)","human","Latin",,"inferior marginal sulcus of insula",0 6523,"Sulcus inferior pontis","human","Latin","inferior pontine sulcus",,0 -1145157708,"sulcus insulae posterior (Reilii)","human","Latin","posterior marginal sulcus (H)",,0 6458,"Sulcus intermedius dorsalis","Unspecified","Latin","dorsal intermediate sulcus",,6 7103,"Sulcus intermedius posterior","human","Latin",,"posterior intermediate sulcus of spinal cord",0 1574851237,"sulcus intermedius primus","human","Latin",,"primary intermediate sulcus (H)",0 -811176613,"sulcus intermedius secundus","human","Latin",,"secondary intermediate sulcus (H)",0 -1785401619,"Sulcus interparietalis","Macaca mulatta","Latin","intraparietal sulcus",,2 1569461898,"sulcus interparietalis","human","Latin","intraparietal sulcus",,0 6365,"Sulcus intracinguli","Unspecified","Latin","intracingulate sulcus",,0 6306,"Sulcus intralingualis","Unspecified","Latin","intralingual sulcus (H)",,0 6369,"Sulcus intraparietalis","human","Latin","intraparietal sulcus",,2 2379,"Sulcus intrarhinalis","human","Latin",,"intrarhinal sulcus",0 6375,"Sulcus lateralis","human","Latin","lateral sulcus",,7 -890364159,"sulcus lateralis anterior","human","Latin","ventrolateral sulcus",,0 6376,"Sulcus lateralis cerebri","human","Latin","lateral sulcus",,0 6316,"Sulcus lateralis posterior","human","Latin","dorsolateral sulcus",,0 6419,"Sulcus lateralis, ramus anterior","human","Latin","anterior horizontal limb of lateral sulcus (H)",,0 6395,"Sulcus lateralis, ramus ascendens","human","Latin","anterior ascending limb of lateral sulcus (H)",,0 6405,"Sulcus lateralis, ramus posterior","human","Latin",,"posterior limb of lateral sulcus",0 6426,"sulcus limitans","human","English","sulcus limitans",,31 6427,"Sulcus limitans","human","Latin","sulcus limitans",,31 -142875285,"Sulcus limitans inferior lateralis","Unspecified","Latin","lateral inferior limiting sulcus",,0 6271,"Sulcus longitudinalis insulae","human","Latin","longitudinal sulcus of insula (H)",,0 -1821657786,"Sulcus lunatus","Macaca mulatta","Latin","lunate sulcus",,0 6429,"Sulcus lunatus","human","Latin","lunate sulcus",,0 6294,"Sulcus marginalis insulae","human","Latin","circular sulcus of insula",,0 6447,"Sulcus marginalis posterior","Unspecified","Latin","posterior marginal sulcus (H)",,0 6452,"Sulcus medianus","human","Latin","median sulcus",,8 6449,"Sulcus medianus (ventriculi quarti)","human","Latin","median sulcus",,0 6454,"Sulcus medianus dorsalis","human","Latin","dorsal median sulcus",,0 6455,"Sulcus medianus posterior","human","Latin","dorsal median sulcus",,0 101180543,"sulcus nervi oculomotorii","human","Latin","oculomotor sulcus",,0 6463,"Sulcus occipitalis anterior","human","Latin","anterior occipital sulcus (H)",,0 6465,"Sulcus occipitalis inferior","Unspecified","Latin","inferior occipital sulcus (M)",,0 6469,"Sulcus occipitalis lateralis","human","Latin","lateral occipital sulcus (H)",,0 6471,"Sulcus occipitalis transversus","human","Latin","transverse occipital sulcus (H)",,0 6590,"Sulcus occipitotemporalis","human","Latin","occipitotemporal sulcus",,0 4599,"Sulcus oculomotorius","human","Latin","oculomotor sulcus",,0 6310,"sulcus of corpus callosum","human","English","callosal sulcus",,0 6387,"sulcus of preoccipital incisura","human","English",,"sulcus of preoccipital incisura (H)",0 6474,"Sulcus olfactorius","human","Latin","olfactory sulcus",,1 6476,"Sulcus orbitalis","human","Latin","orbital sulcus (H)",,0 -1620403701,"Sulcus orbitalis externus","Macaca mulatta","Latin","lateral orbital sulcus",,0 2006342467,"Sulcus orbitalis internus","Macaca mulatta","Latin","medial orbital sulcus",,0 6486,"Sulcus orbitalis lateralis","human","Latin","lateral orbital sulcus",,0 6491,"Sulcus orbitalis medialis","human","Latin","medial orbital sulcus",,0 6494,"Sulcus orbitalis transversus","Unspecified","Latin","transverse orbital sulcus (H)",,0 6497,"Sulcus paracentralis","human","Latin","paracentral sulcus (H)",,0 610674835,"sulcus parietalis transversus","human","Latin",,"transverse parietal sulcus (H)",0 6502,"Sulcus parietoccipitalis","human","Latin","parieto-occipital sulcus",,0 6505,"Sulcus parietooccipitalis","human","Latin","parieto-occipital sulcus",,0 6501,"Sulcus parieto-occipitalis","human","Latin","parieto-occipital sulcus",,1 6510,"Sulcus parieto-occipitalis anterior","Macaca fascicularis","Latin","anterior parieto-occipital sulcus (M)",,0 7,"Sulcus parieto-occipitalis lateralis","Cercocebus torquatus","Latin",,"simian sulcus (M)",0 6506,"Sulcus parieto-occipitalis medialis","Cercocebus torquatus","Latin","parieto-occipital sulcus",,0 6514,"Sulcus parolfactorius anterior","human","Latin","anterior parolfactory sulcus (H)",,0 6517,"Sulcus parolfactorius posterior","human","Latin","posterior parolfactory sulcus",,0 6520,"Sulcus pedunculo-pontinus","human","Latin","superior pontine sulcus",,0 6525,"Sulcus pontomedullaris","human","Latin","inferior pontine sulcus",,0 6528,"Sulcus postcentralis","human","Latin","postcentral sulcus",,0 6532,"Sulcus postcentralis inferior","human","Latin","inferior postcentral sulcus",,0 6535,"Sulcus postcentralis superior","Papio ursinus","Latin","superior postcentral sulcus",,0 6315,"Sulcus posterolateralis","human","Latin","dorsolateral sulcus",,0 6556,"Sulcus post-olivaris","human","Latin","retro-olivary sulcus",,0 6526,"Sulcus postpontinus","human","Latin","inferior pontine sulcus",,0 6541,"Sulcus praecentralis inferior","human","Latin","inferior precentral sulcus (H)",,0 6546,"Sulcus praecentralis superior","human","Latin","superior precentral sulcus",,0 6521,"Sulcus praepontinus","human","Latin","superior pontine sulcus",,0 6539,"Sulcus precentralis inferior","human","Latin","inferior precentral sulcus (H)",,0 6544,"Sulcus precentralis superior","Macaca mulatta","Latin","superior precentral sulcus",,1 6550,"Sulcus principalis","Macaca mulatta","Latin","principal sulcus (M)",,25 462612117,"sulcus rectus","human","Latin","rostral sulcus (M)",,0 6564,"Sulcus rectus (Krieg)","Macaca mulatta","Latin","rostral sulcus (M)",,0 6555,"Sulcus retro-olivaris","human","Latin","retro-olivary sulcus",,0 6559,"Sulcus rhinalis","human","Latin","rhinal sulcus",,5 437158627,"Sulcus rostralis inferior","human","Latin","inferior rostral sulcus (H)",,0 967246656,"Sulcus rostralis superior","human","Latin","superior rostral sulcus (H)",,0 2381,"Sulcus semiannularis","human","Latin",,"semiannular sulcus",0 6431,"Sulcus simialis","Cercocebus torquatus","Latin","lunate sulcus",,0 6,"Sulcus simiarum","Macaca","Latin",,"simian sulcus (M)",0 401471101,"Sulcus subcentralis anterior","human","Latin","anterior subcentral sulcus",,0 1554114151,"Sulcus subcentralis medialis","human","Latin","paracentral sulcus (H)",,0 -954005346,"Sulcus subcentralis posterior","human","Latin","posterior subcentral sulcus",,0 6583,"Sulcus subparietalis","human","Latin","subparietal sulcus",,0 6582,"Sulcus subparietalis","human","Latin","subparietal sulcus",,0 1362357598,"sulcus superior anterior","human","Latin","precentral fissure of cerebellum",,0 1971339184,"sulcus superior insulae (Reilli)","human","Latin",,"superior marginal sulcus of insula",0 6519,"Sulcus superior pontis","human","Latin","superior pontine sulcus",,0 395725500,"sulcus superior posterior","human","Latin","postcentral fissure of cerebellum",,0 6624,"sulcus t1","human","English","superior temporal sulcus",,0 6606,"sulcus t2","human","English","inferior temporal sulcus (H)",,0 6600,"Sulcus temporalis inferior","human","Latin","inferior temporal sulcus (H)",,0 6594,"Sulcus temporalis inferior (Roberts)","human","Latin","occipitotemporal sulcus",,0 6610,"Sulcus temporalis medius","Unspecified","Latin","middle temporal sulcus (M)",,0 6603,"Sulcus temporalis medius (Roberts)","human","Latin","inferior temporal sulcus (H)",,0 6613,"Sulcus temporalis medius anterior","Unspecified","Latin","anterior middle temporal sulcus (M)",,0 6616,"Sulcus temporalis medius posterior","Unspecified","Latin","posterior middle temporal sulcus (M)",,0 6623,"Sulcus temporalis primus","human","Latin","superior temporal sulcus",,0 6605,"Sulcus temporalis secundus","human","Latin","inferior temporal sulcus (H)",,0 6620,"Sulcus temporalis superior","Macaca fascicularis","Latin","superior temporal sulcus",,2 6619,"Sulcus temporalis superior","human","Latin","superior temporal sulcus",,2 6626,"Sulcus terminalis","Unspecified","Latin","terminal sulcus",,50 -1504860170,"Sulcus unci","human","Latin",,"uncal sulcus",0 -1341289921,"sulcus unci hippocampi","human","Latin",,"uncal sulcus",0 6642,"Sulcus ventrolateralis","human","Latin","ventrolateral sulcus",,0 3116,"superficial features","human","English",,"superficial features",0 5994,"superficial gray layer","human","English","superficial gray layer of superior colliculus",,100 2450,"superficial medullary stratum","human","English",,"superficial medullary stratum",0 5768,"superficial pes lemniscus","human","English","medial pes lemniscus",,0 3052,"superficial pontine stratum","human","English",,"superficial pontine stratum",0 3762,"superficial portion of medial part of basal amygdaloid nucleus (Lauer)","Macaca fascicularis","English",,"paralaminar nucleus of amygdala",0 5010,"superficial pulvinar nucleus","human","English",,"superficial pulvinar nucleus",0 2242,"superficial transverse fibers of pons","human","English","transverse pontine fibers",,0 6016,"superficial white layer of superior colliculus","human","English","superficial white layer of superior colliculus",,0 1360,"superior brachium","human","English","brachium of superior colliculus",,0 6401,"superior branch of lateral fissure","human","English","anterior ascending limb of lateral sulcus (H)",,0 6246,"superior calcarine sulcus","Macaca fascicularis","English","superior calcarine sulcus (M)",,0 3936,"superior central nucleus","human","English","superior central nucleus",,24 3937,"superior central nucleus","Macaca fascicularis","English","superior central nucleus",,24 3946,"superior central nucleus raphe","rat","English","superior central nucleus",,0 3942,"superior central tegmental nucleus","human","English","superior central nucleus",,0 -797564486,"superior cerebellar peduncle","Macaca fascicularis","English",,"superior cerebellar peduncle",159 328272307,"superior cerebellar peduncle","rat","English",,"superior cerebellar peduncle",159 -404026051,"superior cerebellar peduncle","human","English",,"superior cerebellar peduncle",159 36521683,"superior cerebellar peduncle of midbrain","Macaca fascicularis","English","superior cerebellar peduncle of midbrain",,0 438172503,"superior cerebellar peduncle of pons","Macaca fascicularis","English","superior cerebellar peduncle of pons",,0 6210,"superior cingulate gyrus","human","English",,"superior cingulate gyrus",0 6209,"superior cingulate sulcus","human","English",,"superior cingulate sulcus",0 1507,"superior cistern","human","English","superior cistern",,1 1508,"superior cistern","Macaca fascicularis","English","superior cistern",,1 1359,"superior collicular brachium","human","English","brachium of superior colliculus",,0 382,"superior colliculus","rat","English","SUPERIOR COLLICULUS",,6331 381,"superior colliculus","Macaca fascicularis","English","SUPERIOR COLLICULUS",,6331 380,"superior colliculus","human","English","SUPERIOR COLLICULUS",,6331 -821361593,"superior colliculus - not otherwise specified","Unspecified","English","SUPERIOR COLLICULUS - not otherwise specified",,6331 2485,"superior fovea","Unspecified","English","superior fovea",,2 2651,"superior frontal convolution","human","English","superior frontal gyrus",,2 6344,"superior frontal fissure","human","English","superior frontal sulcus (H)",,0 2646,"superior frontal gyrus","human","English","superior frontal gyrus",,103 2647,"superior frontal gyrus","Macaca mulatta","English","superior frontal gyrus",,103 6342,"superior frontal sulcus","human","English","superior frontal sulcus (H)",,18 -425158087,"superior frontal sulcus","Macaca","English",,"superior frontal sulcus (M)",18 182905926,"superior frontal white matter","Unspecified","English","superior frontal white matter",,0 2079,"superior fronto-occipital bundle","human","English",,"subcallosal fasciculus",0 2078,"superior fronto-occipital fasciculus","human","English",,"subcallosal fasciculus",1 6445,"superior limb of the circular sulcus","Macaca","English",,"superior marginal sulcus of insula",0 6444,"superior limiting sulcus","Macaca","English",,"superior marginal sulcus of insula",0 2027,"superior longitudinal fasciculus","human","English",,"superior longitudinal fasciculus",6 6443,"superior marginal sulcus of insula","human","English",,"superior marginal sulcus of insula",0 3090,"superior medullary lamina","human","English","superior medullary lamina",,1 3092,"superior medullary lamina of cerebellum","human","English","superior medullary lamina",,0 7028,"superior medullary velum","Macaca fascicularis","English","superior medullary velum",,14 7029,"superior medullary velum","rat","English","superior medullary velum",,14 7027,"superior medullary velum","human","English","superior medullary velum",,14 4872,"superior nucleus of cranial nerve 5 (Goldberg)","human","English",,"superior nucleus of cranial nerve 5 (Goldberg)",0 2719,"superior occipital gyrus","human","English","superior occipital gyrus (H)",,9 -2024676784,"superior occipital gyrus (H)","human","English",,,0 2077,"superior occipito-frontal fascicle","Unspecified","English",,"subcallosal fasciculus",0 2076,"superior occipitofrontal fasciculus","human","English",,"subcallosal fasciculus",0 577,"superior olivary complex","human","English","SUPERIOR OLIVARY COMPLEX",,354 579,"superior olivary complex","rat","English","SUPERIOR OLIVARY COMPLEX",,354 578,"superior olivary complex","Macaca fascicularis","English","SUPERIOR OLIVARY COMPLEX",,354 586,"superior olivary nuclei","human","English","SUPERIOR OLIVE",,53 587,"superior olivary nucleus","Macaca fascicularis","English","SUPERIOR OLIVE",,161 581,"superior olivary nucleus (Barr & Kiernan)","human","English","SUPERIOR OLIVARY COMPLEX",,0 4662,"superior olivary nucleus, lateral part","rat","English","lateral superior olivary nucleus",,0 4672,"superior olivary nucleus, medial part","rat","English","medial superior olivary nucleus",,0 582,"superior olive","human","English","SUPERIOR OLIVE",,419 583,"superior olive","Macaca fascicularis","English","SUPERIOR OLIVE",,419 584,"superior olive","rat","English","SUPERIOR OLIVE",,419 317779625,"superior olive - not otherwise specified","Unspecified","English","SUPERIOR OLIVE - not otherwise specified",,419 902,"superior parietal area 7","human","English",,"superior parietal area 7",0 3155,"superior parietal gyrus","human","English","superior parietal lobule",,11 3150,"superior parietal lobule","human","English","superior parietal lobule",,104 3151,"superior parietal lobule","Macaca mulatta","English","superior parietal lobule",,104 6386,"superior parietal sulcus","human","English",,"superior parietal sulcus (H)",0 551163158,"superior parietal white matter","Unspecified","English","superior parietal white matter",,0 6548,"superior part of precentral fissure","human","English","superior precentral sulcus",,0 5746,"superior peduncle","human","English","superior thalamic peduncle",,3 6518,"superior pontine sulcus","human","English","superior pontine sulcus",,0 3156,"superior portion of parietal gyrus","human","English","superior parietal lobule",,0 6533,"superior postcentral sulcus","human","English","superior postcentral sulcus",,0 6534,"superior postcentral sulcus","Macaca mulatta","English","superior postcentral sulcus",,0 6543,"superior precentral sulcus","Macaca fascicularis","English","superior precentral sulcus",,9 6542,"superior precentral sulcus","human","English","superior precentral sulcus",,9 1358,"superior quadrigeminal brachium","human","English","brachium of superior colliculus",,0 6219,"superior ramus of arcuate sulcus","Macaca fascicularis","English","superior ramus of arcuate sulcus (M)",,1 6248,"superior ramus of calcarine fissure","Macaca mulatta","English","superior calcarine sulcus (M)",,0 2094855838,"superior rostral gyrus","human","English","superior rostral gyrus (H)",,0 6565,"superior rostral sulcus","human","English","superior rostral sulcus (H)",,1 5128,"superior salivatory nucleus","human","English","superior salivatory nucleus",,51 3176,"superior semilunar lobule","human","English","superior semilunar lobule",,8 3177,"superior semilunar lobule","Macaca fascicularis","English","superior semilunar lobule",,8 942,"superior temporal area 22","human","English",,"superior temporal area 22",0 6621,"superior temporal fissure","human","English","superior temporal sulcus",,1 2822,"superior temporal gyrus","Macaca mulatta","English","superior temporal gyrus",,353 2821,"superior temporal gyrus","human","English","superior temporal gyrus",,353 6617,"superior temporal sulcus","Macaca fascicularis","English","superior temporal sulcus",,273 6618,"superior temporal sulcus","Macaca mulatta","English","superior temporal sulcus",,273 1513446738,"superior temporal white matter","Unspecified","English","superior temporal white matter",,0 5743,"superior thalamic peduncle","human","English","superior thalamic peduncle",,3 5885,"superior thalamic radiation","human","English",,"superior thalamic radiations",0 5883,"superior thalamic radiations","human","English",,"superior thalamic radiations",0 1555873547,"superior transverse frontopolar gyrus","human","English","superior transverse frontopolar gyrus (H)",,0 748446860,"superior trigeminal nucleus","human","English","principal sensory nucleus of trigeminal nerve",,0 5575,"superior vestibular nucleus","rat","English","superior vestibular nucleus",,117 5573,"superior vestibular nucleus","human","English","superior vestibular nucleus",,117 5574,"superior vestibular nucleus","Macaca fascicularis","English","superior vestibular nucleus",,117 3093,"superior white lamina","human","English","superior medullary lamina",,0 1089,"supplementary motor area","human","English",,"supplementary motor cortex",0 1090,"supplementary motor area","Macaca mulatta","English",,"supplementary motor cortex",0 -268439223,"supplementary motor area (M II)","human","English",,"supplementary motor cortex",0 1095,"supplementary motor areas (Crosby)","human","English",,"supplementary motor areas (Crosby)",0 1088,"supplementary motor cortex","Macaca","English",,"supplementary motor cortex",69 1087,"supplementary motor cortex","human","English",,"supplementary motor cortex",69 2918,"supracallosal gyrus","Macaca fascicularis","English","SUPRACALLOSAL GYRUS",,1 2917,"supracallosal gyrus","human","English","SUPRACALLOSAL GYRUS",,1 2516,"supracapsular part of globus pallidus","human","English",,"supracapsular part of globus pallidus",0 5250,"suprachiasmatic nucleus","human","English","suprachiasmatic nucleus",,2842 5251,"suprachiasmatic nucleus","Macaca fascicularis","English","suprachiasmatic nucleus",,2842 5252,"suprachiasmatic nucleus","rat","English","suprachiasmatic nucleus",,2842 5255,"suprachiasmatic nucleus of hypothalamus","human","English","suprachiasmatic nucleus",,2 2921,"supracommissural hippocampal rudiment","human","English","SUPRACALLOSAL GYRUS",,0 2920,"supracommissural hippocampus","human","English","SUPRACALLOSAL GYRUS",,1 1452,"supracommissural septum","human","English","SEPTUM PELLUCIDUM",,5 5258,"suprageniculate nucleus","human","English","suprageniculate nucleus",,81 5259,"suprageniculate nucleus","human","English","suprageniculate nucleus",,81 5260,"suprageniculate nucleus","Macaca fascicularis","English","suprageniculate nucleus",,81 5261,"suprageniculate nucleus","rat","English","suprageniculate nucleus",,81 5264,"suprageniculate thalamic nucleus","rat","English","suprageniculate nucleus",,1 3056,"supragranular layers","human","English",,"supragranular layers",252 5832,"supralemniscal process","human","English",,"supralemniscal process",0 1619,"supramammillary commissure","human","English","supramammillary commissure",,2 1624,"supramammillary decussation","rat","English","supramammillary commissure",,5 1623,"supramammillary decussation","human","English","supramammillary commissure",,5 5267,"supramammillary nucleus","Macaca fascicularis","English","supramammillary nucleus",,102 5266,"supramammillary nucleus","human","English","supramammillary nucleus",,102 5268,"supramammillary nucleus","rat","English","supramammillary nucleus",,102 910,"supramarginal area 40","human","English",,"supramarginal area 40 (H)",0 2792,"supramarginal gyrus","human","English","supramarginal gyrus",,98 2793,"supramarginal gyrus","Macaca fascicularis","English","supramarginal gyrus",,98 -16275931,"supramarginal white matter","Unspecified","English","supramarginal white matter",,0 1805,"supraoptic commissure of Meynert","human","English","dorsal supraoptic decussation",,1 1796,"supraoptic commissures","rat","English",,"supraoptic decussations",5 1808,"supraoptic commissures, dorsal","rat","English","dorsal supraoptic decussation",,0 1816,"supraoptic commissures, ventral","rat","English","ventral supraoptic decussation",,0 5624,"supraoptic crest","human","English","supraoptic crest",,3 5625,"supraoptic crest","Macaca fascicularis","English","supraoptic crest",,3 1795,"supraoptic decussation","rat","English",,"supraoptic decussations",43 1794,"supraoptic decussation","human","English",,"supraoptic decussations",43 1793,"supraoptic decussations","human","English",,"supraoptic decussations",0 5963,"supraoptic level of hypothalamus","human","English",,"supraoptic region",0 5273,"supraoptic nucleus","rat","English","supraoptic nucleus",,2639 5271,"supraoptic nucleus","human","English","supraoptic nucleus",,2639 5272,"supraoptic nucleus","Macaca fascicularis","English","supraoptic nucleus",,2639 5276,"supraoptic nucleus of hypothalamus","human","English","supraoptic nucleus",,3 5925,"supraoptic recess","human","English","optic recess",,2 5961,"supraoptic region","human","English",,"supraoptic region",0 5962,"supraoptic region of hypothalamus","human","English",,"supraoptic region",0 6878,"supraopticohypophyseal tract","human","English","supraopticohypophysial tract",,4 6876,"supraopticohypophysial tract","human","English","supraopticohypophysial tract",,2 5926,"suprapineal recess","human","English","suprapineal recess",,12 22,"suprasegmental levels of nervous system","human","English","BRAIN",,0 21,"suprasegmental structures","human","English","BRAIN",,10 5281,"supraspinal nucleus","rat","English","supraspinal nucleus",,10 5280,"supraspinal nucleus","human","English","supraspinal nucleus",,10 6586,"suprasplenial sulcus","human","English","subparietal sulcus",,1 4264,"supratrochlear nucleus","human","English",,"supratrochlear nucleus",0 4265,"supratrochlear nucleus","human","English",,"supratrochlear nucleus",0 1550,"SVA","human","Abbreviation",,"special visceral afferents",0 1552,"SVE","human","Abbreviation",,"special visceral efferents",0 345,"Sylvian aqueduct","human","English","cerebral aqueduct",,66 6377,"Sylvian fissure","Macaca mulatta","English","lateral sulcus",,438 6383,"Sylvian sulcus","human","English","lateral sulcus",,8 6945,"Sylvian triangle","human","English",,"Sylvian triangle",2 3366,"Systema nervosum","human","Latin",,"nervous system",1 3381,"Systema nervosum (pars autonomica)","human","Latin",,"autonomic nervous system",0 3378,"Systema nervosum autonomicum","human","Latin",,"autonomic nervous system",0 3368,"Systema nervosum centrale","human","Latin",,"central nervous system",0 3373,"Systema nervosum periphericum","human","Latin",,"peripheral nervous system",0 3370,"Systema nervosum, pars centralis","human","Latin",,"central nervous system",0 3374,"Systema nervosum, pars peripherica","human","Latin",,"peripheral nervous system",0 1474491888,"T1","human","Abbreviation","superior temporal gyrus",,0 682882566,"T2","human","Abbreviation","middle temporal gyrus",,0 -1171545329,"T3","human","Abbreviation","inferior temporal gyrus",,0 -1494539356,"T4","human","English","fusiform gyrus",,0 1314560981,"T5","human","Abbreviation","lingual gyrus",,0 6651,"Taenia choroidea (ventriculi lateralis)","human","Latin","tenia choroidea of lateral ventricle",,0 6656,"taenia choroidea of fourth ventricle","human","English","tenia of fourth ventricle",,0 6663,"Taenia fimbriae","human","Latin","tenia of fimbria",,0 6666,"Taenia fornicis","human","Latin","tenia of fornix",,1 6067,"Taenia libera Lancisi","human","Latin","medial longitudinal stria",,0 6066,"Taenia libra","human","Latin","medial longitudinal stria",,0 6059,"Taenia obtecta","human","Latin","lateral longitudinal stria",,0 6652,"Taenia semicircularis","human","Latin","tenia choroidea of lateral ventricle",,0 6057,"Taenia tecta","human","Latin","lateral longitudinal stria",,30 6659,"Taenia thalami","human","Latin","tenia of thalamus",,0 6655,"Taenia ventriculi quarti","human","Latin","tenia of fourth ventricle",,0 1442,"tail of caudate nucleus","Macaca fascicularis","English","tail of caudate nucleus",,0 1441,"tail of caudate nucleus","human","English","tail of caudate nucleus",,0 229345669,"tail of dentate gyrus","human","English",,"tail of dentate gyrus",0 6667,"tapetum","human","English",,"tapetum",210 6668,"Tapetum","human","Latin",,"tapetum",210 6787,"tectal tracts","human","English",,"tectal tracts",0 6885,"tectobulbar tract","human","English","tectobulbar tract",,13 6884,"tectopontine fibers","human","English","tectopontine tract",,1 6881,"tectopontine tract","human","English","tectopontine tract",,0 6783,"tectoreticular fibers","human","English",,"tectoreticular fibers",0 6784,"tectoreticular tract","human","English",,"tectoreticular fibers",0 1388,"tectospinal fibers","human","English","predorsal bundle",,3 6892,"tectospinal pathway","rat","English","tectospinal tract",,5 6889,"tectospinal tract","rat","English","tectospinal tract",,13 6888,"tectospinal tract","Macaca fascicularis","English","tectospinal tract",,13 6887,"tectospinal tract","human","English","tectospinal tract",,13 6785,"tectothalamic fibers","human","English",,"tectothalamic fibers",0 6786,"tectothalamic tract","human","English",,"tectothalamic fibers",6 258,"tectum","human","English","TECTUM",,2789 259,"tectum","Macaca fascicularis","English","TECTUM",,2789 261,"Tectum","human","Latin","TECTUM",,2789 260,"Tectum mesencephali","human","Latin","TECTUM",,52 265,"Tectum mesencephalicum","human","Latin","TECTUM",,0 264,"tectum of midbrain","human","English","TECTUM",,2 6670,"Tegmen fossae rhomboidei","human","Latin",,"Tegmen ventriculi quarti",0 6669,"Tegmen ventriculi quarti","human","Latin",,"Tegmen ventriculi quarti",0 1406,"tegmental area H","human","English","field H",,0 2106,"tegmental area H1","human","English","field H1",,0 1969,"tegmental area H2","human","English","field H2",,0 5249,"tegmental field nucleus","human","English",,"subthalamic reticular nucleus",0 1402,"tegmental field of Forel","human","English","field H",,0 2434,"tegmental gray of pons","human","English",,"tegmental gray of pons",0 3567,"tegmental nuclei","human","English",,"tegmental nuclei",0 6676,"tegmental portion of pons","human","English","PONTINE TEGMENTUM",,0 2429,"tegmental reticular formation","human","English","MIDBRAIN RETICULAR FORMATION",,11 5071,"tegmental reticular nucleus, pontine gray","rat","English","reticulotegmental nucleus",,0 6788,"tegmentocerebellar fibers","human","English",,"tegmentocerebellar fibers",0 6789,"tegmentocerebellar tract","human","English",,"tegmentocerebellar fibers",0 268,"Tegmentum mesencephali","human","Latin","MIDBRAIN TEGMENTUM",,2033 271,"Tegmentum mesencephalicum","human","Latin","MIDBRAIN TEGMENTUM",,0 270,"tegmentum of midbrain","human","English","MIDBRAIN TEGMENTUM",,5 6677,"tegmentum of pons","human","English","PONTINE TEGMENTUM",,13 6673,"Tegmentum pontis","human","Latin","PONTINE TEGMENTUM",,451 6679,"tela choroidea","human","English",,"tela choroidea",47 6681,"Tela choroidea","human","Latin",,"tela choroidea",47 6680,"Tela choroidea","human","Latin",,"tela choroidea",47 6683,"Tela choroidea (ventriculi lateralis)","human","Latin","tela choroidea of lateral ventricle",,0 6688,"Tela choroidea (ventriculi quarti)","human","Latin","tela choroidea of fourth ventricle",,0 6686,"Tela choroidea (ventriculi tertii)","human","Latin","tela choroidea of third ventricle",,0 6687,"tela choroidea of fourth ventricle","human","English","tela choroidea of fourth ventricle",,0 6682,"tela choroidea of lateral ventricle","human","English","tela choroidea of lateral ventricle",,0 6685,"tela choroidea of third ventricle","human","English","tela choroidea of third ventricle",,0 6684,"Tela choroidea ventriculi lateralis","human","Latin","tela choroidea of lateral ventricle",,0 2072,"telencephalic medial fasciculus","human","English","medial forebrain bundle",,0 3473,"telencephalic nuclei","human","English",,"basal ganglia (Crosby)",33 26,"telencephalon","Macaca fascicularis","English","TELENCEPHALON",,3767 25,"telencephalon","human","English","TELENCEPHALON",,3767 27,"Telencephalon","human","Latin","TELENCEPHALON",,3767 29,"Telencephalon impar","human","Latin",,"Telencephalon medium",0 28,"Telencephalon medium","human","Latin",,"Telencephalon medium",0 2336,"telodiencephalic fissure","Macaca fascicularis","English","telodiencephalic fissure",,0 2338,"telo-diencephalic fissure","human","English","telodiencephalic fissure",,0 95,"temporal association areas","human","English",,"temporal association areas",0 1239,"temporal auditory areas","human","English",,"auditory cortex",0 73,"temporal cortex","human","English","TEMPORAL LOBE",,1817 2215,"temporal corticopontine tract","human","English",,"temporopontine fibers",0 1639,"temporal horn of lateral ventricle","human","English","temporal horn of lateral ventricle",,0 1574,"temporal limb of anterior commissure","rat","English","posterior part of anterior commissure",,0 71,"temporal lobe","Macaca fascicularis","English","TEMPORAL LOBE",,12999 70,"temporal lobe","human","English","TEMPORAL LOBE",,12999 62,"temporal lobe (Ono)","human","English",,"temporal lobe (Ono)",0 61,"temporal lobe (Ono)","human","English",,"temporal lobe (Ono)",0 655,"temporal loop","human","English",,"inferior optic radiation",0 5597,"temporal operculum","human","English","temporal operculum",,13 5598,"temporal operculum","human","English","temporal operculum",,13 654,"temporal optic radiation","human","English",,"inferior optic radiation",0 5730,"temporal peduncle","human","English","inferior thalamic peduncle",,0 5797,"temporal pole","human","English","temporal pole",,142 74,"temporal region","rat","English","TEMPORAL LOBE",,643 1050,"temporal region","human","English",,"temporal region",643 5728,"temporal thalamic peduncle","human","English","inferior thalamic peduncle",,0 97,"temporal vestibular area","human","English",,"temporal vestibular area",0 313435132,"temporal white matter","Unspecified","English","TEMPORAL WHITE MATTER",,0 193742670,"temporal white matter - not otherwise specified","Unspecified","English","TEMPORAL WHITE MATTER - not otherwise specified",,0 90,"temporo-occipital cortex","human","English",,"temporo-occipital cortex",0 1223,"temporoparietal area, Tpt of Galaburda","human","English",,"auditory association cortex",0 928,"temporopolar area 38","human","English",,"temporopolar area 38 (H)",0 2210,"temporopontine fibers","human","English",,"temporopontine fibers",0 2212,"temporopontine tract","human","English",,"temporopontine fibers",0 6654,"Tenia (ventriculi quarti)","human","Latin","tenia of fourth ventricle",,0 6650,"Tenia choroidea (ventriculi lateralis)","human","Latin","tenia choroidea of lateral ventricle",,0 6662,"Tenia fimbria","Unspecified","Latin","tenia of fimbria",,0 6665,"Tenia fornicis","Unspecified","Latin","tenia of fornix",,0 6661,"tenia of fimbria","human","English","tenia of fimbria",,0 6664,"tenia of fornix","human","English","tenia of fornix",,0 6653,"tenia of fourth ventricle","human","English","tenia of fourth ventricle",,0 6660,"tenia of thalami","human","English","tenia of thalamus",,0 6657,"tenia of thalamus","human","English","tenia of thalamus",,0 6658,"Tenia thalami","human","Latin","tenia of thalamus",,0 3345,"tenth cranial nerve","human","English","vagus nerve",,14 3348,"tenth cranial nerve fibers","human","English","vagal nerve fibers",,0 -2006262158,"tentorial hiatus","human","English",,"tentorial incisure",24 2893,"tentorial hiatus","human","English","anterior cerebellar incisure",,24 930238982,"tentorial incisure","human","English",,"tentorial incisure",4 2892,"tentorial incisure","human","English","anterior cerebellar incisure",,4 2894,"tentorial notch","human","English","anterior cerebellar incisure",,21 1481232143,"tentorial notch","human","English",,"tentorial incisure",21 6690,"Tentorium cerebelli","human","Latin",,"cerebellar tentorium",126 5617,"terminal nerve","human","English","terminal nerve",,223 5618,"terminal nerve","human","English","terminal nerve",,223 6625,"terminal sulcus","human","English","terminal sulcus",,4 6627,"terminal sulcus of thalamus","human","English","terminal sulcus",,0 982281589,"terminal velum","Macaca fascicularis","English","terminal velum",,0 1975606887,"terminal velum","human","English","terminal velum",,0 371,"Testes","human","Latin","INFERIOR COLLICULUS",,12078 -1431384085,"thalamencephalon","human","Latin","THALAMUS",,0 3432,"thalamic association nuclei","human","English",,"thalamic association nuclei",0 667,"thalamic commissure","Unspecified","English",,"thalamic commissure",2 2100,"thalamic fasciculus","human","English","field H1",,5 1916,"thalamic fiber tracts","Macaca fascicularis","English","THALAMIC FIBER TRACTS",,0 1915,"thalamic fiber tracts","human","English","THALAMIC FIBER TRACTS",,0 5495,"thalamic gustatory nucleus","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,1 3098,"thalamic medullary laminae","human","English",,"thalamic medullary laminae",0 -1410162938,"thalamic radiations","human","English",,"thalamocortical radiations",6 3553,"thalamic reticular nucleus","Macaca fascicularis","English","thalamic reticular nucleus",,289 3552,"thalamic reticular nucleus","human","English","thalamic reticular nucleus",,289 5894,"thalamocortical radiations","human","English",,"thalamocortical radiations",13 5896,"thalamocortical tract","human","English",,"thalamocortical radiations",3 -447750837,"thalamolenticular limb","human","English","POSTERIOR LIMB OF INTERNAL CAPSULE",,0 5689,"thalamolenticular portion of internal capsule","human","English","lenticulothalamic part of internal capsule",,0 1019930835,"thalamo-olivary tract","human","English",,"central tegmental tract",0 2251,"thalamoparietal fibers","human","English",,"thalamoparietal fibers",0 6790,"thalamostriate fibers","human","English",,"thalamostriate fibers",0 6791,"thalamostriate tract","human","English",,"thalamostriate fibers",0 164,"thalamus","Macaca fascicularis","English","THALAMUS",,16182 163,"thalamus","human","English","THALAMUS",,16182 165,"Thalamus","human","Latin","THALAMUS",,16182 166,"Thalamus","Macaca mulatta","Latin","THALAMUS",,16182 3499,"thalamus (Crosby)","human","English",,"thalamus (Crosby)",0 3500,"thalamus (Swanson)","rat","English",,"thalamus (Crosby)",0 1034697659,"Thalamus dorsalis","human","Latin","THALAMUS",,0 -1287147952,"thalamus opticus","human","Latin","THALAMUS",,0 249,"Thalamus ventralis","human","Latin","SUBTHALAMUS",,12 277,"third cranial nerve","human","English","oculomotor nerve",,117 6592,"third temporal sulcus","human","English","occipitotemporal sulcus",,0 754,"third ventricle","rat","English","THIRD VENTRICLE",,2867 753,"third ventricle","Macaca fascicularis","English","THIRD VENTRICLE",,2867 752,"third ventricle","human","English","THIRD VENTRICLE",,2867 -827732547,"third ventricle - not otherwise specified","Unspecified","English","THIRD VENTRICLE - not otherwise specified",,2867 7158,"thoracic segments","human","English",,"thoracic segments",290 7159,"thoracic segments of spinal cord","human","English",,"thoracic segments",0 6695,"tonsil","human","English","cerebellar tonsil",,4949 6694,"Tonsilla","human","Latin","cerebellar tonsil",,30 6693,"Tonsilla cerebelli","human","Latin","cerebellar tonsil",,1 2264,"total fissure","human","English",,"total fissure",0 1933,"tract of Burdach","Macaca fascicularis","English",,"cuneate fasciculus",0 5153,"tract of descending root of trigeminal","human","English",,"spinal trigeminal tract",0 1950,"tract of Gall","human","English",,"gracile fasciculus",0 7077,"tract of Lissauer","human","English","dorsolateral fasciculus of medulla",,32 5836,"Tractus amygdalofugalis ventralis","human","Latin","ventral amygdalofugal projection",,0 1841,"Tractus bulbo-thalamicus","human","Latin",,"medial lemniscus",0 2137,"Tractus cerebello-bulbaris","human","Latin","uncinate fasciculus of pons",,0 952423151,"Tractus cerebello-rubralis","human","Latin",,"superior cerebellar peduncle",0 503,"Tractus cerebello-rubro-thalamicus","human","Latin",,"cerebellorubrothalamic tract",0 551276036,"Tractus cerebello-tegmentalis mesencephali","human","Latin",,"superior cerebellar peduncle",0 500,"Tractus cerebellothalamicus","human","Latin",,"cerebellorubrothalamic tract",0 501,"Tractus cerebello-thalamicus","human","Latin",,"cerebellorubrothalamic tract",0 2175,"Tractus corticobulbaris","Macaca nemestrina","Latin",,"corticobulbar fibers",0 6706,"Tractus corticospinalis","human","Latin",,"corticospinal tract",0 6707,"Tractus cortico-spinalis","human","Latin",,"corticospinal tract",0 6715,"Tractus corticospinalis (pyramidalis) lateralis","Macaca mulatta","Latin","lateral corticospinal tract",,0 6713,"Tractus corticospinalis lateralis","human","Latin","lateral corticospinal tract",,1 6714,"Tractus corticospinalis lateralis","Macaca fascicularis","Latin","lateral corticospinal tract",,1 6720,"Tractus corticospinalis ventralis","human","Latin","ventral corticospinal tract",,0 6721,"Tractus corticospinalis ventralis","Macaca fascicularis","Latin","ventral corticospinal tract",,0 6731,"Tractus corticotectalis","Macaca fuscata","Latin","corticotectal tract",,0 6743,"Tractus cuneocerebelli","Unspecified","Latin","cuneocerebellar tract",,0 6798,"Tractus dentatothalamicus","Macaca fascicularis","Latin","dentatothalamic tract",,0 2199,"Tractus frontopontinus","human","Latin",,"frontopontine fibers",0 -180314139,"Tractus habenulointercruralis","Macaca mulatta","Latin",,"habenulo-interpeduncular tract",0 -1066053132,"Tractus habenulo-intercruralis","human","Latin",,"habenulo-interpeduncular tract",0 1568693096,"Tractus habenulo-interpeduncularis","human","Latin",,"habenulo-interpeduncular tract",2 -36060070,"Tractus habenulo-interpeduncularis diencephali","Macaca fascicularis","Latin","habenulo-interpeduncular tract of diencephalon",,0 987510329,"Tractus habenulo-interpeduncularis mesencephali","Macaca fascicularis","Latin","habenulo-interpeduncular tract of midbrain",,0 6880,"Tractus hypothalamico-hypophyseus","human","Latin","supraopticohypophysial tract",,0 2046,"Tractus hypothalamicotegmentalis","Macaca fascicularis","Latin","mammillotegmental fasciculus",,0 368845052,"Tractus hypothalamo-hypophysealis","human","Latin",,"hypothalamohypophyseal tract",0 2045,"Tractus hypothalamotegmentalis","human","Latin","mammillotegmental fasciculus",,0 2012,"Tractus longitudinalis medialis","human","Latin",,"medial longitudinal fasciculus",0 2013,"Tractus longitudinalis medialis","Macaca mulatta","Latin",,"medial longitudinal fasciculus",0 2044,"Tractus mamillo-tegmentalis","human","Latin","mammillotegmental fasciculus",,0 2050,"Tractus mamillothalamicus","Macaca fascicularis","Latin",,"mammillothalamic tract",0 2054,"Tractus mamillo-thalamicus","Macaca mulatta","Latin",,"mammillothalamic tract",0 2053,"Tractus mamillo-thalamicus","human","Latin",,"mammillothalamic tract",0 4562,"Tractus mesencephalicus nervi trigeminalis","Macaca mulatta","Latin","mesencephalic tract of trigeminal nerve",,0 4561,"Tractus mesencephalicus nervi trigeminalis","human","Latin","mesencephalic tract of trigeminal nerve",,0 4560,"Tractus mesencephalicus nervi trigeminalis","Macaca fascicularis","Latin","mesencephalic tract of trigeminal nerve",,0 4559,"Tractus mesencephalicus nervi trigemini","human","Latin","mesencephalic tract of trigeminal nerve",,1 -1346829716,"Tractus mesencephalicus trigeminalis","human","Latin","mesencephalic tract of trigeminal nerve",,0 2207,"Tractus occipitopontinus","human","Latin",,"occipitopontine fibers",0 6817,"Tractus olfactomesencephalicus","Macaca fascicularis","Latin",,"Tractus olfacto-mesencephalicus",0 6816,"Tractus olfacto-mesencephalicus","human","Latin",,"Tractus olfacto-mesencephalicus",0 3783,"Tractus olfactorium","Macaca fascicularis","Latin","olfactory tract",,0 3781,"Tractus olfactorius","human","Latin","olfactory tract",,8 3782,"Tractus olfactorius","Macaca mulatta","Latin","olfactory tract",,8 6097,"Tractus olfactorius intermedius","human","Latin",,"intermediate olfactory stria",0 6096,"Tractus olfactorius internus","human","Latin",,"intermediate olfactory stria",0 6093,"Tractus olfactorius lateralis","human","Latin","lateral olfactory stria",,1 6102,"Tractus olfactorius medialis","human","Latin",,"medial olfactory stria",0 6820,"Tractus olivocerebellaris","Macaca fascicularis","Latin","olivocerebellar tract",,0 5717,"Tractus olivocochlearis","human","Latin","olivocochlear bundle",,1 4684,"Tractus opticus","Macaca fascicularis","Latin","optic tract",,27 4683,"Tractus opticus","human","Latin","optic tract",,27 6821,"Tractus opticus, radix lateralis","human","Latin",,"Tractus opticus, radix lateralis",0 6822,"Tractus opticus, radix medialis","human","Latin",,"Tractus opticus, radix medialis",0 6825,"Tractus pallido-hypothalamicus","human","Latin",,"pallidohypothalamic fasciculus",0 6834,"Tractus paraventriculo-hypophyseus","human","Latin",,"tuberohypophysial tract",0 6832,"Tractus paraventriculohypophysialis","human","Latin",,"tuberohypophysial tract",0 2203,"Tractus parietopontinae","human","Latin",,"parietopontine fibers",0 2067,"Tractus parietotemporo-occipitopontinus","human","Latin",,"parietotemporo-occipitopontine tract",0 2222,"Tractus parieto-temporo-pontinus","human","Latin",,"Fibrae parietotemporopontinae",0 7045,"Tractus peduncularis transversus","human","Latin",,"basal optic root",0 1987,"Tractus periependymalis longitudinalis","human","Latin",,"dorsal longitudinal fasciculus",0 6772,"Tractus prerubralis","human","Latin",,"prerubral tract",0 6702,"Tractus pyramidalis","human","Latin","pyramidal tract",,0 6703,"Tractus pyramidalis","Macaca fascicularis","Latin","pyramidal tract",,0 6842,"Tractus reticulospinalis","Unspecified","Latin","reticulospinal tract",,0 -709538657,"Tractus retroflexus (Meynert)","Macaca fascicularis","Latin",,"habenulo-interpeduncular tract",0 6844,"Tractus rubrospinalis","human","Latin","rubrospinal tract",,1 605,"Tractus solitarius","Macaca fascicularis","Latin","solitary tract",,1363 5155,"Tractus spinalis nervi trigeminalis","human","Latin",,"spinal trigeminal tract",0 5146,"Tractus spinalis nervi trigemini","Macaca fascicularis","Latin",,"spinal trigeminal tract",0 5145,"Tractus spinalis nervi trigemini","human","Latin",,"spinal trigeminal tract",0 5160,"Tractus spinalis nervi trigemini (myelencephali)","human","Latin","spinal trigeminal tract of medulla",,0 5157,"Tractus spinalis nervi trigemini (pontis)","Unspecified","Latin","spinal trigeminal tract of pons",,0 1936,"Tractus spinobulbaris partis lateralis (Burdach)","Macaca mulatta","Latin",,"cuneate fasciculus",0 1953,"Tractus spinobulbaris partis medialis (Goll)","Macaca mulatta","Latin",,"gracile fasciculus",0 6858,"Tractus spinocerebellaris anterior","Macaca fascicularis","Latin","anterior spinocerebellar tract",,0 6857,"Tractus spinocerebellaris anterior","human","Latin","anterior spinocerebellar tract",,0 6848,"Tractus spinocerebellaris dorsalis","human","Latin","posterior spinocerebellar tract",,1 6850,"Tractus spinocerebellaris posterior","Macaca fascicularis","Latin","posterior spinocerebellar tract",,1 6849,"Tractus spinocerebellaris posterior","human","Latin","posterior spinocerebellar tract",,1 6852,"Tractus spino-cerebellaris posterior","Macaca nemestrina","Latin","posterior spinocerebellar tract",,0 6856,"Tractus spinocerebellaris ventralis","human","Latin","anterior spinocerebellar tract",,0 6846,"Tractus spino-olivaris","human","Latin","spino-olivary tract",,0 6863,"Tractus spinothalamicus","Macaca fascicularis","Latin",,"spinothalamic tract",0 6862,"Tractus spinothalamicus","human","Latin",,"spinothalamic tract",0 6866,"Tractus spino-thalamicus","human","Latin",,"spinothalamic tract",0 6875,"Tractus spinothalamicus (mesencephali)","Unspecified","Latin","spinothalamic tract of midbrain",,0 6869,"Tractus spinothalamicus (myelencephali)","human","Latin","spinothalamic tract of medulla",,0 6870,"Tractus spinothalamicus (myelencephali)","Macaca fascicularis","Latin","spinothalamic tract of medulla",,0 6873,"Tractus spinothalamicus (pontis)","Unspecified","Latin","spinothalamic tract of pons",,0 7148,"Tractus spinothalamicus anterior","human","Latin",,"anterior spinothalamic tract",0 7152,"Tractus spinothalamicus lateralis","human","Latin",,"lateral spinothalamic tract",0 7150,"Tractus spinothalamicus medialis","human","Latin",,"anterior spinothalamic tract",0 7149,"Tractus spinothalamicus ventralis","human","Latin",,"anterior spinothalamic tract",0 6907,"Tractus subthalamicotegmentalis","human","Latin",,"subthalamicotegmental tract",0 6879,"Tractus supraoptico-hypophyseus","human","Latin","supraopticohypophysial tract",,1 6877,"Tractus supraopticohypophysialis","human","Latin","supraopticohypophysial tract",,0 6886,"Tractus tectobulbaris","human","Latin","tectobulbar tract",,2 6883,"Tractus tectopontinus","Macaca fascicularis","Latin","tectopontine tract",,0 6882,"Tractus tectopontinus","human","Latin","tectopontine tract",,0 6891,"Tractus tectospinalis","Macaca fascicularis","Latin","tectospinal tract",,0 6890,"Tractus tectospinalis","human","Latin","tectospinal tract",,0 6896,"Tractus tegmentalis centralis","Macaca fascicularis","Latin",,"central tegmental tract",3 6895,"Tractus tegmentalis centralis","human","Latin",,"central tegmental tract",3 6905,"Tractus tegmentalis centralis (mesencephali)","Unspecified","Latin","central tegmental tract of midbrain",,0 6903,"Tractus tegmentalis centralis (pontis)","Unspecified","Latin","central tegmental tract of pons",,0 6897,"Tractus tegmenti centralis","human","Latin",,"central tegmental tract",0 2213,"Tractus temporopontinus","human","Latin",,"temporopontine fibers",0 6909,"Tractus trigeminalis dorsalis","human","Latin","dorsal trigeminal tract",,0 6932,"Tractus trigeminalis ventralis","human","Latin","ventral trigeminal tract",,0 6927,"Tractus trigeminothalamicus","human","Latin",,"trigeminal lemniscus",0 6910,"Tractus trigemino-thalamicus dorsalis","human","Latin","dorsal trigeminal tract",,0 6835,"Tractus tubero-hypophyseus","human","Latin",,"tuberohypophysial tract",0 2136,"Tractus uncinatus (Lewandowsky)","human","Latin","uncinate fasciculus of pons",,0 6939,"Tractus vestibulocerebelli","Unspecified","Latin","vestibulocerebellar tract",,0 6944,"Tractus vestibulospinalis","Macaca fascicularis","Latin","vestibulospinal tract",,2 6103,"transcapsular caudatolenticular gray striae","human","English",,"transcapsular caudatolenticular gray striae",0 2328,"transverse cerebral fissure","human","English",,"transverse cerebral fissure",0 2247,"transverse fasciculus of cuneus","human","English",,"transverse fasciculus of cuneus",0 2245,"transverse fasciculus of lingula","human","English",,"transverse fasciculus of lingula",0 2243,"transverse fibers of pons","rat","English","transverse pontine fibers",,1 2330,"transverse fissure of cerebrum","human","English",,"transverse cerebral fissure",0 -1451469987,"transverse frontopolar gyri","human","English","TRANSVERSE FRONTOPOLAR GYRI (H)",,0 947403987,"transverse frontopolar gyrus","human","English","TRANSVERSE FRONTOPOLAR GYRI (H)",,0 2248,"transverse occipital fasciculus of cuneus","human","English",,"transverse fasciculus of cuneus",0 2246,"transverse occipital fasciculus of lingual lobule","human","English",,"transverse fasciculus of lingula",0 6470,"transverse occipital sulcus","human","English","transverse occipital sulcus (H)",,2 929234374,"transverse occipital sulcus (H)","human","English",,,0 6493,"transverse orbital sulcus","human","English","transverse orbital sulcus (H)",,1 -741414886,"transverse parietal sulcus","Unspecified","English",,"transverse parietal sulcus (H)",0 2237,"transverse pontine fibers","human","English","transverse pontine fibers",,10 2238,"transverse pontine fibers","Macaca fascicularis","English","transverse pontine fibers",,10 6628,"transverse rhombencephalic sulcus","human","English",,"transverse rhombencephalic sulcus",0 -150457964,"transverse section","human","English",,"horizontal section",365 2798,"transverse temporal gyri","human","English",,"transverse temporal gyri",13 6206,"transverse temporal sulcus","human","English","transverse temporal sulcus (H)",,1 631,"trapezoid body","human","English","trapezoid body",,387 632,"trapezoid body","Macaca fascicularis","English","trapezoid body",,387 633,"trapezoid body","rat","English","trapezoid body",,387 4234,"trapezoid gray","human","English","trapezoid nuclei",,0 4229,"trapezoid nuclei","human","English","trapezoid nuclei",,7 7238,"triangle of Phillippe-Gombault","human","English",,"triangle of Phillippe-Gombault",0 1105,"triangular area (Wernicke)","human","English",,"triangular area (Wernicke)",0 2631,"triangular area 45","human","English",,"triangular area 45",0 5569,"triangular nucleus","human","English","medial vestibular nucleus",,14 2626,"triangular part of inferior frontal gyrus","human","English","triangular part of inferior frontal gyrus (H)",,1 5293,"triangular septal nucleus","rat","English","triangular septal nucleus",,14 5291,"triangular septal nucleus","human","English","triangular septal nucleus",,14 5292,"triangular septal nucleus","Macaca fascicularis","English","triangular septal nucleus",,14 3482,"trigeminal ganglion","human","English",,"trigeminal ganglion",2126 6921,"trigeminal lemniscus","human","English",,"trigeminal lemniscus",3 6925,"trigeminal lemniscus-1","human","English",,"trigeminal lemniscus",0 6937,"trigeminal lemniscus-2","human","English","ventral trigeminal tract",,0 3315,"trigeminal nerve","Macaca fascicularis","English","trigeminal nerve",,5255 3314,"trigeminal nerve","human","English","trigeminal nerve",,5255 3320,"trigeminal nerve fibers","human","English","trigeminal nerve fibers",,20 3321,"trigeminal nerve fibers","Macaca fascicularis","English","trigeminal nerve fibers",,20 174715429,"trigeminal nuclear complex","Macaca fascicularis","English",,"trigeminal nuclei",57 -1801198369,"trigeminal nuclei","human","English",,"trigeminal nuclei",1237 6930,"trigeminal tract","human","English",,"trigeminal lemniscus",0 7003,"trigeminal tubercle","human","English","trigeminal tubercle",,0 6792,"trigeminocerebellar fibers","human","English",,"trigeminocerebellar fibers",0 6793,"trigeminocerebellar tract","human","English",,"trigeminocerebellar fibers",0 878008842,"trigeminospinal nucleus","human","English",,"SPINAL TRIGEMINAL NUCLEUS",0 5154,"trigeminospinal tract","human","English",,"spinal trigeminal tract",0 6923,"trigeminothalamic tract","human","English",,"trigeminal lemniscus",17 6926,"trigeminothalamic tract-1","human","English",,"trigeminal lemniscus",0 6950,"trigone of lateral ventricle","human","English","collateral trigone",,1 6966,"Trigone vagi","human","Latin","vagal trigone",,0 6947,"Trigonum collaterale","human","Latin","collateral trigone",,1 6953,"Trigonum habenulae","human","Latin","habenular trigone",,0 6955,"Trigonum habenulare","human","Latin","habenular trigone",,0 6954,"Trigonum habenularis","human","Latin","habenular trigone",,0 6960,"Trigonum hypoglossale","human","Latin","hypoglossal trigone",,0 6957,"Trigonum lemnisci","human","Latin","lemniscal trigone",,1 6959,"Trigonum nervi hypoglossi","human","Latin","hypoglossal trigone",,0 6964,"Trigonum nervi vagi","human","Latin","vagal trigone",,0 6971,"Trigonum olfactorium","human","Latin","olfactory trigone",,0 6973,"Trigonum pontocerebellare","human","Latin","pontocerebellar trigone",,0 6965,"Trigonum vagale","human","Latin","vagal trigone",,0 6967,"Trigonum vagi","human","Latin","vagal trigone",,0 -386807461,"trigonum ventriculi lateralis","human","Latin","collateral trigone",,0 314,"trochlear nerve","human","English","trochlear nerve",,532 315,"trochlear nerve","Macaca fascicularis","English","trochlear nerve",,532 321,"trochlear nerve fibers","Macaca fascicularis","English","trochlear nerve fibers",,2 320,"trochlear nerve fibers","human","English","trochlear nerve fibers",,2 323,"trochlear nerve root","rat","English","trochlear nerve fibers",,2 5300,"trochlear nucleus","rat","English","trochlear nucleus",,106 5298,"trochlear nucleus","human","English","trochlear nucleus",,106 5299,"trochlear nucleus","Macaca fascicularis","English","trochlear nucleus",,106 3227,"true isocortex","human","English",,"true isocortex",0 1260,"true septum","Cercocebus torquatus","English",,"true septum",0 1259,"true septum","human","English",,"true septum",0 1394137857,"trunculus corporis callosi","human","Latin","body of corpus callosum",,0 470520736,"truncus cerebri","human","Latin",,"brain stem",0 144,"Truncus corpus callosi","human","Latin","body of corpus callosum",,0 143,"Truncus corpus callosi","human","Latin","body of corpus callosum",,0 6975,"Truncus encephali","human","Latin",,"brain stem",0 -1821811159,"Truncus encephalicus","human","Latin",,"brain stem",0 148,"trunk of corpus callosum","human","English","body of corpus callosum",,0 6977,"tuber cinereum","human","English","tuber cinereum",,166 6979,"Tuber cinereum","Macaca fascicularis","Latin","tuber cinereum",,166 6978,"Tuber cinereum","human","Latin","tuber cinereum",,166 6981,"tuber of vermis","Macaca fascicularis","English","tuber of vermis",,0 6980,"tuber of vermis","human","English","tuber of vermis",,0 -1476770196,"tuber olfactorium","human","Latin","anterior perforated substance",,0 6982,"Tuber vermis","human","Latin","tuber of vermis",,5 5968,"tuberal level of hypothalamus","human","English",,"tuberal region",0 3570,"tuberal nuclei","human","English",,"tuberal nuclei",0 3578,"tuberal nuclei (Mai)","human","English","lateral tuberal nuclei",,0 2869,"tuberal part of hypophysis","human","English","tuberal part of hypophysis",,0 5966,"tuberal region","human","English",,"tuberal region",46 5967,"tuberal region of hypothalamus","human","English",,"tuberal region",0 2088,"tubercular terminal island(s)","human","English",,"tubercular terminal island(s)",0 6986,"Tuberculum acusticum","Macaca mulatta","Latin","acoustic tubercle",,1 6985,"Tuberculum acusticum","human","Latin","acoustic tubercle",,1 6992,"Tuberculum anterius thalami","human","Latin","anterior tubercle",,0 6993,"Tuberculum anterius thalamicum","human","Latin","anterior tubercle",,0 5969,"tuberculum cinereum","human","English",,"tuberculum cinereum",0 7006,"Tuberculum cinereum","human","Latin","trigeminal tubercle",,0 6997,"Tuberculum cuneatum","human","Latin","cuneate tubercle",,0 7000,"Tuberculum gracile","human","Latin","gracilis tubercle",,0 6998,"Tuberculum nuclei cuneati","human","Latin","cuneate tubercle",,0 7001,"Tuberculum nuclei gracilis","human","Latin","gracilis tubercle",,0 6191,"Tuberculum olfactorium","human","Latin","anterior perforated substance",,141 6192,"Tuberculum olfactorium","Cercocebus torquatus","Latin","anterior perforated substance",,141 3071,"Tuberculum quadrigeminus","human","Latin",,"Corpus quadrigemina",0 7004,"Tuberculum trigeminale","human","Latin","trigeminal tubercle",,0 6833,"tuberohypophyseal tract","human","English",,"tuberohypophysial tract",0 6831,"tuberohypophysial tract","human","English",,"tuberohypophysial tract",1 6836,"tuberoinfundibular tract","human","English",,"tuberohypophysial tract",6 5311,"tuberomammillary hypothalamic nucleus","human","English","tuberomammillary nucleus",,2 5308,"tuberomammillary nucleus","rat","English","tuberomammillary nucleus",,121 5307,"tuberomammillary nucleus","Macaca fascicularis","English","tuberomammillary nucleus",,121 5306,"tuberomammillary nucleus","human","English","tuberomammillary nucleus",,121 2216,"Turck's bundle","human","English",,"temporopontine fibers",0 295,"twelfth cranial nerve","human","English","hypoglossal nerve",,17 707,"Type 1 of von Economo","human","English",,"agranular cortex",0 713,"type 2 of von Economo","human","English",,"frontal type cortex",0 715,"type 3 of von Economo","human","English",,"parietal type cortex",0 717,"type 4 of von Economo","human","English",,"polar type cortex",0 711,"Type 5 of von Economo","human","English",,"granulous cortex",0 699,"Typus 16","Cercocebus torquatus","Latin",,"peripaleocortical claustral region",0 2908,"uncal notch","human","English",,"uncal notch",0 2910,"uncal notch (Duvernoy)","human","English",,"uncal notch",0 1460104681,"uncal sulcus","human","English",,"uncal sulcus",0 2130,"uncinate bundle of Russell","human","English","uncinate fasciculus of pons",,0 2132,"uncinate fasciculus of cerebellum","human","English","uncinate fasciculus of pons",,0 2118,"uncinate fasciculus of cerebral hemisphere","human","English",,"uncinate fasciculus of forebrain",0 2114,"uncinate fasciculus of forebrain","human","English",,"uncinate fasciculus of forebrain",0 -1819905692,"uncinate fasciculus of pons","human","English","uncinate fasciculus of pons",,0 2129,"uncinate fasciculus of Russell","human","English","uncinate fasciculus of pons",,0 2127,"uncinate fasciculus of Russell","human","English","uncinate fasciculus of pons",,0 2119,"uncinate fasciculus-1","human","English",,"uncinate fasciculus of forebrain",0 2139,"uncinate fasciculus-2","human","English","uncinate fasciculus of pons",,0 2832,"uncinate gyrus","human","English",,"uncinate gyrus",1 2831,"uncinate gyrus","human","English",,"uncinate gyrus",1 6920,"uncrossed dorsal trigeminothalamic tract","human","English","dorsal trigeminal tract",,0 7228,"uncrossed lateral corticospinal tract","human","English",,"anterolateral corticospinal tract",0 2825,"uncus","human","English","uncus",,69 2826,"Uncus","human","Latin","uncus",,69 2827,"Uncus","Macaca mulatta","Latin","uncus",,69 2835,"uncus (Lockard)","human","English",,"uncinate gyrus",0 2829,"uncus hippocampi","human","English","uncus",,2 2828,"Uncus hippocampi","human","Latin","uncus",,2 6249,"upper calcarine sulcus","Macaca mulatta","English","superior calcarine sulcus (M)",,0 2584,"upper limbic gyrus","human","English","CINGULATE GYRUS",,0 7009,"uvula","rat","English","uvula",,1033 7007,"uvula","human","English","uvula",,1033 7008,"Uvula","Macaca nemestrina","Latin","uvula",,1033 7013,"uvula of cerebellum","human","English","uvula",,0 7010,"Uvula vermis","human","Latin","uvula",,0 2275,"uvulonodular fissure","human","English","posterolateral fissure",,0 3818,"VA","human","Abbreviation","VENTRAL ANTERIOR NUCLEUS",,0 3817,"VA","Macaca mulatta","Abbreviation","VENTRAL ANTERIOR NUCLEUS",,0 3346,"vagal nerve fibers","human","English","vagal nerve fibers",,22 4036,"vagal nerve nuclei","human","English",,"vagus nerve nuclei",0 4035,"vagal nuclei","human","English",,"vagus nerve nuclei",0 6963,"vagal trigone","human","English","vagal trigone",,0 3342,"vagus nerve","human","English","vagus nerve",,10862 4034,"vagus nerve nuclei","human","English",,"vagus nerve nuclei",0 7014,"vallecula cerebelli","human","English","vallecula cerebelli",,0 7015,"Vallecula cerebelli","human","Latin","vallecula cerebelli",,0 -541038343,"vallecula cerebelli (Reili)","human","Latin","vallecula cerebelli",,0 5329,"VAmc","human","Abbreviation","magnocellular part of ventral anterior nucleus",,0 5328,"VAmc","Macaca mulatta","Abbreviation","magnocellular part of ventral anterior nucleus",,0 5339,"VApc","Macaca mulatta","Abbreviation","parvicellular part of ventral anterior nucleus",,0 5340,"VApc","human","Abbreviation","parvicellular part of ventral anterior nucleus",,0 5628,"vascular organ of lamina terminalis","rat","English","supraoptic crest",,0 3379,"vegetative nervous system","human","English",,"autonomic nervous system",207 7017,"velum interpositum","human","English","velum interpositum",,27 7018,"Velum interpositum","human","Latin","velum interpositum",,27 7034,"Velum medullare anterius","human","Latin","superior medullary velum",,3 7035,"Velum medullare anterius","Macaca fascicularis","Latin","superior medullary velum",,3 7023,"Velum medullare caudale","human","Latin","inferior medullary velum",,0 1190948290,"Velum medullare craniale","human","Latin","superior medullary velum",,0 7022,"Velum medullare inferius","human","Latin","inferior medullary velum",,0 7024,"Velum medullare posterius","human","Latin","inferior medullary velum",,0 7025,"Velum medullare posterius","Macaca mulatta","Latin","inferior medullary velum",,0 7033,"Velum medullare rostralis","human","Latin","superior medullary velum",,0 7032,"Velum medullare superior","human","Latin","superior medullary velum",,0 7031,"Velum medullare superius","Macaca fuscata","Latin","superior medullary velum",,0 7030,"Velum medullare superius","human","Latin","superior medullary velum",,0 1150165532,"Velum terminale","human","Latin","terminal velum",,0 6048,"ventral acoustic stria","human","English","ventral acoustic stria",,9 5837,"ventral amygdalofugal pathway","human","English","ventral amygdalofugal projection",,27 5835,"ventral amygdalofugal projection","human","English","ventral amygdalofugal projection",,0 973,"ventral anterior cingulate area 24","human","English",,"ventral anterior cingulate area 24",0 3805,"ventral anterior nucleus","human","English","VENTRAL ANTERIOR NUCLEUS",,45 3806,"ventral anterior nucleus","Macaca fascicularis","English","VENTRAL ANTERIOR NUCLEUS",,45 3814,"ventral anterior nucleus of thalamus","human","English","VENTRAL ANTERIOR NUCLEUS",,1 5319,"ventral anterior nucleus, magnocellular part","Macaca fascicularis","English","magnocellular part of ventral anterior nucleus",,0 3813,"ventral anterior thalamic nucleus","human","English","VENTRAL ANTERIOR NUCLEUS",,8 5318,"ventral anterior thalamic nucleus, magnocellular part","human","English","magnocellular part of ventral anterior nucleus",,0 5334,"ventral anterior thalamic nucleus, parvicellular part","human","English","parvicellular part of ventral anterior nucleus",,0 3714,"ventral claustrum","human","English","claustral amygdaloid area",,8 4012,"ventral cochlear nuclei","Macaca fascicularis","English","VENTRAL COCHLEAR NUCLEI",,59 4011,"ventral cochlear nuclei","human","English","VENTRAL COCHLEAR NUCLEI",,59 4014,"ventral cochlear nucleus","rat","English","VENTRAL COCHLEAR NUCLEI",,321 4013,"ventral cochlear nucleus","Macaca fascicularis","English","VENTRAL COCHLEAR NUCLEI",,321 1207,"ventral cortical nucleus of amygdala","Macaca fascicularis","English","periamygdaloid area",,0 6719,"ventral corticospinal tract","Macaca fascicularis","English","ventral corticospinal tract",,5 6718,"ventral corticospinal tract","human","English","ventral corticospinal tract",,5 6936,"ventral crossed tract","human","English","ventral trigeminal tract",,0 1789,"ventral decussation of pons","human","English",,"ventral decussation of pons",0 4019,"ventral division of cochlear nucleus","human","English","VENTRAL COCHLEAR NUCLEI",,0 2148,"ventral external arcuate fibers","human","English","ventral external arcuate fibers",,1 7121,"ventral gray commissure of cord","human","English",,"anterior gray commissure",0 7119,"ventral horn","human","English",,"anterior gray column",1341 3406,"ventral lamina","human","English",,"basal plate",0 4083,"ventral lateral anterior nucleus","human","English","oral part of ventral lateral nucleus",,2 4084,"ventral lateral anterior nucleus","Macaca","English","oral part of ventral lateral nucleus",,2 4102,"ventral lateral geniculate nucleus","rat","English","ventral nucleus of lateral geniculate body",,197 4059,"ventral lateral nucleus","human","English","VENTRAL LATERAL NUCLEUS",,61 4060,"ventral lateral nucleus","Macaca fascicularis","English","VENTRAL LATERAL NUCLEUS",,61 5398,"ventral lateral nucleus (pars postrema)","Macaca fascicularis","English","pars postrema of ventral lateral nucleus",,0 4069,"ventral lateral nucleus of thalamus","human","English","VENTRAL LATERAL NUCLEUS",,0 5376,"ventral lateral nucleus, caudal part","Macaca fascicularis","English","caudal part of ventral lateral nucleus",,0 5388,"ventral lateral nucleus, medial part","Macaca fascicularis","English","medial part of ventral lateral nucleus",,0 4080,"ventral lateral nucleus, oral part","Macaca fascicularis","English","oral part of ventral lateral nucleus",,0 4068,"ventral lateral thalamic nuclei","rat","English","VENTRAL LATERAL NUCLEUS",,6 4067,"ventral lateral thalamic nuclei","human","English","VENTRAL LATERAL NUCLEUS",,6 4066,"ventral lateral thalamic nucleus","human","English","VENTRAL LATERAL NUCLEUS",,7 5375,"ventral lateral thalamic nucleus, caudal part","human","English","caudal part of ventral lateral nucleus",,0 4079,"ventral lateral thalamic nucleus, oral part","human","English","oral part of ventral lateral nucleus",,0 6442,"ventral limb of the circular sulcus","Macaca","English",,"inferior marginal sulcus of insula",0 5390,"ventral medial nucleus","human","English","medial part of ventral lateral nucleus",,26 2311,"ventral median fissure of medulla","human","English","anterior median fissure",,0 2310,"ventral median sulcus","human","English","anterior median fissure",,0 4533,"ventral mediodorsal nucleus","Macaca","English","paralaminar part of medial dorsal nucleus",,0 3584,"ventral nuclear group","Macaca fascicularis","English","VENTRAL NUCLEAR GROUP",,8 3583,"ventral nuclear group","human","English","VENTRAL NUCLEAR GROUP",,8 3587,"ventral nuclear mass","human","English","VENTRAL NUCLEAR GROUP",,3 3586,"ventral nuclei of thalamus","human","English","VENTRAL NUCLEAR GROUP",,0 4099,"ventral nucleus of lateral geniculate body","Macaca fascicularis","English","ventral nucleus of lateral geniculate body",,0 4098,"ventral nucleus of lateral geniculate body","human","English","ventral nucleus of lateral geniculate body",,0 4484,"ventral nucleus of lateral lemniscus","rat","English","ventral nucleus of lateral lemniscus",,2 4483,"ventral nucleus of lateral lemniscus","Macaca fascicularis","English","ventral nucleus of lateral lemniscus",,2 4482,"ventral nucleus of lateral lemniscus","human","English","ventral nucleus of lateral lemniscus",,2 4137,"ventral nucleus of medial geniculate body","Macaca fascicularis","English","ventral nucleus of medial geniculate body",,1 4136,"ventral nucleus of medial geniculate body","human","English","ventral nucleus of medial geniculate body",,1 4142,"ventral nucleus of medial geniculate complex","human","English","ventral nucleus of medial geniculate body",,0 4058,"ventral nucleus of posterior commissure","human","English","nucleus of Darkschewitsch",,0 4487,"ventral nucleus of the lateral lemniscus","human","English","ventral nucleus of lateral lemniscus",,88 2249,"ventral occipital fasciculus","human","English",,"ventral occipital fasciculus",0 5413,"ventral oculomotor cell column","human","English","ventral oculomotor nucleus",,0 5409,"ventral oculomotor nucleus","human","English","ventral oculomotor nucleus",,2 5410,"ventral oculomotor nucleus","Macaca fascicularis","English","ventral oculomotor nucleus",,2 2538,"ventral pallidum","human","English",,"ventral pallidum",470 6696,"ventral paraflocculus","human","English","cerebellar tonsil",,59 4749,"ventral paramedian reticular nucleus","human","English","ventral paramedian reticular nucleus",,2 5467,"ventral part of ventral lateral posterior nucleus (Jones)","Macaca","English","oral part of ventral posterolateral nucleus",,0 5466,"ventral part of ventral lateral posterior nucleus (Jones)","human","English","oral part of ventral posterolateral nucleus",,0 738,"ventral peduncle of lateral forebrain bundle","human","English","ansa lenticularis",,0 4923,"ventral periventricular hypothalamic nucleus","human","English",,"ventral periventricular hypothalamic nucleus",0 3715,"ventral portion of claustrum","human","English","claustral amygdaloid area",,0 5695,"ventral portion of pons","human","English","BASAL PART OF PONS",,1 961,"ventral posterior cingulate area 23","human","English",,"ventral posterior cingulate area 23",0 5426,"ventral posterior inferior nucleus","human","English","ventral posteroinferior nucleus",,5 5428,"ventral posterior inferior nucleus of thalamus","human","English","ventral posteroinferior nucleus",,0 5427,"ventral posterior inferior thalamic nucleus","human","English","ventral posteroinferior nucleus",,0 5451,"ventral posterior lateral nucleus (Ilinsky)","Macaca mulatta","English","caudal part of ventral posterolateral nucleus",,0 5475,"ventral posterior lateral nucleus, anterior division","human","English",,"ventral posterior lateral nucleus, anterior division",0 5474,"ventral posterior lateral nucleus, anterior part","human","English",,"ventral posterior lateral nucleus, anterior division",0 5478,"ventral posterior lateral nucleus, posterior divison","human","English",,"ventral posterior lateral nucleus, posterior division",0 5496,"ventral posterior medial nucleus","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,20 5419,"ventral posterior nucleus","human","English","VENTRAL POSTERIOR NUCLEUS",,37 5415,"ventral posterior nucleus","Macaca fascicularis","English","VENTRAL POSTERIOR NUCLEUS",,37 5414,"ventral posterior nucleus","human","English","VENTRAL POSTERIOR NUCLEUS",,37 5417,"ventral posterior thalamic nucleus","human","English","VENTRAL POSTERIOR NUCLEUS",,15 5423,"ventral posteroinferior nucleus","Macaca fascicularis","English","ventral posteroinferior nucleus",,1 5435,"ventral posterolateral nucleus","Macaca fascicularis","English","VENTRAL POSTEROLATERAL NUCLEUS",,57 5434,"ventral posterolateral nucleus","human","English","VENTRAL POSTEROLATERAL NUCLEUS",,57 5442,"ventral posterolateral nucleus of thalamus","rat","English","VENTRAL POSTEROLATERAL NUCLEUS",,0 5441,"ventral posterolateral nucleus of thalamus","human","English","VENTRAL POSTEROLATERAL NUCLEUS",,0 5450,"ventral posterolateral nucleus, caudal part","Macaca fascicularis","English","caudal part of ventral posterolateral nucleus",,0 5464,"ventral posterolateral nucleus, oral part","Macaca fascicularis","English","oral part of ventral posterolateral nucleus",,0 5440,"ventral posterolateral thalamic nucleus","rat","English","VENTRAL POSTEROLATERAL NUCLEUS",,14 5439,"ventral posterolateral thalamic nucleus","human","English","VENTRAL POSTEROLATERAL NUCLEUS",,14 5449,"ventral posterolateral thalamic nucleus, caudal part","human","English","caudal part of ventral posterolateral nucleus",,0 5463,"ventral posterolateral thalamic nucleus, oral part","human","English","oral part of ventral posterolateral nucleus",,0 5483,"ventral posteromedial nucleus","Macaca fascicularis","English","VENTRAL POSTEROMEDIAL NUCLEUS",,26 5482,"ventral posteromedial nucleus","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,26 5492,"ventral posteromedial nucleus of thalamus","human","English","VENTRAL POSTEROMEDIAL NUCLEUS",,0 5506,"ventral posteromedial nucleus of thalamus, parvicellular part","rat","English","parvicellular part of ventral posteromedial nucleus",,0 5504,"ventral posteromedial nucleus, parvocellular part","Macaca fascicularis","English","parvicellular part of ventral posteromedial nucleus",,0 5505,"ventral posteromedial thalamic nucleus, parvicellular part","human","English","parvicellular part of ventral posteromedial nucleus",,0 4156,"ventral premammillary nucleus","human","English",,"ventral premammillary nucleus",45 3764,"ventral principal nucleus of amygdala","Macaca fascicularis","English",,"paralaminar nucleus of amygdala",0 5526,"ventral raphe tegmental nucleus","human","English","ventral tegmental nucleus",,0 5072,"ventral reticular nucleus","human","English","ventral reticular nucleus",,14 5073,"ventral reticular nucleus","Macaca fascicularis","English","ventral reticular nucleus",,14 7253,"ventral reticulospinal tract","human","English",,"pontine reticulospinal tract",0 6935,"ventral secondary ascending tract of V","human","English","ventral trigeminal tract",,0 6853,"ventral spinocerebellar tract","human","English","anterior spinocerebellar tract",,26 6854,"ventral spinocerebellar tract","Macaca fascicularis","English","anterior spinocerebellar tract",,26 6855,"ventral spinocerebellar tract","rat","English","anterior spinocerebellar tract",,26 2540,"ventral striatum","human","English",,"ventral striatum",584 1814,"ventral supraoptic commissure (of Meynert)","human","English","ventral supraoptic decussation",,0 1809,"ventral supraoptic decussation","human","English","ventral supraoptic decussation",,7 1811,"ventral supraoptic decussation of Gudden","human","English","ventral supraoptic decussation",,0 5528,"ventral tegmental area","human","English","ventral tegmental area",,2580 5533,"ventral tegmental area (Tsai)","human","English","ventral tegmental area",,0 5532,"ventral tegmental area of Tsai","human","English","ventral tegmental area",,56 1874,"ventral tegmental decussation","human","English","ventral tegmental decussation",,3 1875,"ventral tegmental decussation","rat","English","ventral tegmental decussation",,3 1880,"ventral tegmental decussation of Forel","human","English","ventral tegmental decussation",,0 1282,"ventral tegmental gray","human","English",,"ventral tegmental gray",0 5518,"ventral tegmental nucleus","Macaca fascicularis","English","ventral tegmental nucleus",,54 5517,"ventral tegmental nucleus","human","English","ventral tegmental nucleus",,54 5527,"ventral tegmental nucleus (Gudden)","rat","English","ventral tegmental nucleus",,0 5536,"ventral tegmental nucleus (Tsai)","rat","English","ventral tegmental area",,0 5524,"ventral tegmental nucleus of Gudden","human","English","ventral tegmental nucleus",,17 5531,"ventral tegmental nucleus of Tsai","human","English","ventral tegmental area",,0 250,"ventral thalamus","human","English","SUBTHALAMUS",,227 3503,"ventral thalamus (Crosby)","human","English",,"ventral thalamus (Crosby)",0 257,"ventral thalamus (Martinez)","human","English",,"ventral thalamus (Martinez)",0 3588,"ventral tier thalamic nuclei","human","English","VENTRAL NUCLEAR GROUP",,3 6934,"ventral trigeminal pathway","human","English","ventral trigeminal tract",,0 6931,"ventral trigeminal tract","human","English","ventral trigeminal tract",,1 6933,"ventral trigeminothalamic tract","human","English","ventral trigeminal tract",,2 7138,"ventral white commissure of cord","human","English",,"anterior white commissure",0 5337,"ventralis anterior (Jones)","Macaca","English","parvicellular part of ventral anterior nucleus",,0 5336,"ventralis anterior (Jones)","human","English","parvicellular part of ventral anterior nucleus",,0 7052,"ventricles of brain","human","English",,"ventricles of brain",0 7051,"ventricular system","human","English",,"ventricular system",1000 750,"Ventriculus lateralis","human","Latin","lateral ventricle",,6 751,"Ventriculus lateralis","Macaca fascicularis","Latin","lateral ventricle",,6 1633,"Ventriculus lateralis, cornu anterius","human","Latin","frontal horn of lateral ventricle",,0 1634,"Ventriculus lateralis, cornu frontale","Unspecified","Latin","frontal horn of lateral ventricle",,0 1643,"Ventriculus lateralis, cornu inferius","human","Latin","temporal horn of lateral ventricle",,0 1651,"Ventriculus lateralis, cornu occipitale","human","Latin","occipital horn of lateral ventricle",,0 1650,"Ventriculus lateralis, cornu posterius","human","Latin","occipital horn of lateral ventricle",,0 1642,"Ventriculus lateralis, cornu temporale","human","Latin","temporal horn of lateral ventricle",,0 1666,"Ventriculus lateralis, corpus","human","Latin","body of lateral ventricle",,0 1665,"Ventriculus lateralis, pars centralis","human","Latin","body of lateral ventricle",,0 6951,"Ventriculus lateralis, trigonum collaterale","human","Latin","collateral trigone",,0 760,"Ventriculus quartus","human","Latin","FOURTH VENTRICLE",,2 761,"Ventriculus quartus","Macaca fascicularis","Latin","FOURTH VENTRICLE",,2 762,"Ventriculus quartuus","Macaca mulatta","Latin","FOURTH VENTRICLE",,0 1623935367,"ventriculus quintus","human","Latin","cave of septum pellucidum",,0 1457,"ventriculus septi pellucidi","human","English","cave of septum pellucidum",,0 755,"Ventriculus tertius","human","Latin","THIRD VENTRICLE",,2 756,"Ventriculus tertius","Macaca fascicularis","Latin","THIRD VENTRICLE",,2 1626404922,"Ventriculus tertius - not otherwise specified","Unspecified","Latin","THIRD VENTRICLE - not otherwise specified",,2 3816,"ventroanterior thalamic nucleus","human","English","VENTRAL ANTERIOR NUCLEUS",,1 5327,"ventroanterior thalamic nucleus, magnocellular part","human","English","magnocellular part of ventral anterior nucleus",,0 5418,"ventrobasal complex","human","English","VENTRAL POSTERIOR NUCLEUS",,278 5421,"ventrobasal nucleus","human","English","VENTRAL POSTERIOR NUCLEUS",,50 5742,"ventrocaudal thalamic peduncle","human","English","posterior thalamic peduncle",,0 3760,"ventrolateral division of lateral nucleus of amygdala","Macaca fascicularis","English",,"ventrolateral division of lateral nucleus of amygdala",0 2945,"ventrolateral division of midbrain central gray","human","English",,"lateral ventral subnucleus of midbrain central gray",0 6645,"ventrolateral fissure of medulla","human","English","ventrolateral sulcus",,0 6646,"ventrolateral fissure of midbrain","human","English","ventrolateral fissure of midbrain",,0 5352,"ventrolateral posterior nucleus","human","English",,"ventrolateral posterior nucleus",0 5138,"ventrolateral subnucleus of solitary tract","human","English","ventrolateral subnucleus of solitary tract",,0 6641,"ventrolateral sulcus","human","English","ventrolateral sulcus",,1 4073,"ventrolateral thalamic nucleus","rat","English","VENTRAL LATERAL NUCLEUS",,70 3679,"ventromedial division of accessory basal nucleus","Macaca fascicularis","English",,"ventromedial division of accessory basal nucleus",0 5543,"ventromedial hypothalamic nucleus","rat","English","ventromedial nucleus of hypothalamus",,1359 5542,"ventromedial hypothalamic nucleus","human","English","ventromedial nucleus of hypothalamus",,1359 5537,"ventromedial nucleus of hypothalamus","human","English","ventromedial nucleus of hypothalamus",,21 5539,"ventromedial nucleus of hypothalamus","rat","English","ventromedial nucleus of hypothalamus",,21 5538,"ventromedial nucleus of hypothalamus","Macaca fascicularis","English","ventromedial nucleus of hypothalamus",,21 5430,"ventroposterior inferior thalamic nucleus","human","English","ventral posteroinferior nucleus",,1 1785,"vermal region","rat","English",,"vermis of cerebellum",0 7083,"vermal zone of cerebellum","human","English",,"vermal zone of cerebellum",0 1783,"Vermis (cerebelli)","Macaca fascicularis","Latin",,"vermis of cerebellum",30 1782,"Vermis cerebelli","human","Latin",,"vermis of cerebellum",30 7057,"Vermis lobus anterior","Unspecified","Latin","VERMIS OF ANTERIOR LOBE",,0 7062,"Vermis lobus posterior","Unspecified","Latin","VERMIS OF POSTERIOR LOBE",,0 7056,"vermis of anterior lobe","Macaca fascicularis","English","VERMIS OF ANTERIOR LOBE",,0 7055,"vermis of anterior lobe","human","English","VERMIS OF ANTERIOR LOBE",,0 1781,"vermis of cerebellum","human","English",,"vermis of cerebellum",0 7061,"vermis of posterior lobe","Macaca fascicularis","English","VERMIS OF POSTERIOR LOBE",,1 7060,"vermis of posterior lobe","human","English","VERMIS OF POSTERIOR LOBE",,1 6217,"vertical arcuate sulcus","Macaca mulatta","English","inferior ramus of arcuate sulcus (M)",,0 2208,"vertical occipital fasciculus","human","English",,"vertical occipital fasciculus",0 7054,"vesicles of brain","human","English",,"vesicles of brain",0 1284,"vestibular area","human","English","vestibular area",,30 1287,"vestibular cortex","human","English",,"vestibular cortex",35 3364,"vestibular division of acoustic nerve","human","English",,"vestibular nerve",0 3488,"vestibular ganglion","human","English",,"vestibular ganglion",214 3489,"vestibular ganglion of Scarpa","human","English",,"vestibular ganglion",0 3359,"vestibular nerve","human","English",,"vestibular nerve",2179 568,"vestibular nuclear complex","human","English","VESTIBULAR NUCLEI",,133 566,"vestibular nuclei","rat","English","VESTIBULAR NUCLEI",,2359 564,"vestibular nuclei","human","English","VESTIBULAR NUCLEI",,2359 565,"vestibular nuclei","Macaca fascicularis","English","VESTIBULAR NUCLEI",,2359 581876338,"vestibular representation","human","English",,"vestibular cortex",0 6940,"vestibulocerebellar fibers","human","English","vestibulocerebellar tract",,4 6938,"vestibulocerebellar tract","human","English","vestibulocerebellar tract",,0 558,"vestibulocerebellum","human","English","FLOCCULONODULAR LOBE",,88 3253,"vestibulocochlear nerve","human","English","vestibulocochlear nerve",,3082 302,"vestibulocochlear nerve fibers","Macaca fascicularis","English","vestibulocochlear nerve fibers",,1 301,"vestibulocochlear nerve fibers","human","English","vestibulocochlear nerve fibers",,1 307,"vestibulocochlear nerve roots","rat","English","vestibulocochlear nerve fibers",,0 3250,"vestibulocochlear nerve, pars cochlearis","human","English",,"cochlear nerve",0 3363,"vestibulocochlear nerve, pars vestibularis","human","English",,"vestibular nerve",0 6941,"vestibulo-oculomotor fibers","human","English",,"vestibulo-oculomotor fibers",0 6943,"vestibulospinal tract","rat","English","vestibulospinal tract",,68 6942,"vestibulospinal tract","human","English","vestibulospinal tract",,68 1332,"vicarious cortex","human","English","BASOLATERAL NUCLEAR GROUP",,0 5361,"Vime (Hassler)","human","Abbreviation",,"Nucleus ventrointermedius externus (Hassler)",0 5359,"Vimi (Van Buren)","human","Abbreviation",,"Nucleus ventrointermedius internus (Hassler)",0 3380,"visceral nervous system","human","English",,"autonomic nervous system",12 5116,"visceral oculomotor nuclei","human","English",,"visceral oculomotor nuclei",0 814,"visual area I","human","English",,"striate area 17",0 1183,"visual area II","human","English",,"parastriate area 18",0 -1311373922,"visual area II","human","English",,"parastriate area 18",0 1194,"visual area III","human","English",,"peristriate area 19",0 1229,"visual parasensory association cortex","human","English",,"visual parasensory association cortex",0 1230,"visual parasensory association cortex","Macaca mulatta","English",,"visual parasensory association cortex",0 5875,"visual radiation","human","English",,"geniculocalcarine radiation",0 1323,"visual stria","human","English",,"band of Gennari",0 1240,"visual-auditory cortex","human","English",,"visual-auditory cortex",0 4074,"VL","human","Abbreviation","VENTRAL LATERAL NUCLEUS",,0 4154,"VL (Ilinsky)","Macaca mulatta","Abbreviation",,"ventral lateral nucleus (Ilinsky)",0 4153,"VL (Walker)","Macaca mulatta","Abbreviation",,"Nucleus ventralis lateralis (Walker)",0 5382,"VLc","human","Abbreviation","caudal part of ventral lateral nucleus",,0 5381,"VLc","Macaca mulatta","Abbreviation","caudal part of ventral lateral nucleus",,0 5395,"VLm","Macaca mulatta","Abbreviation","medial part of ventral lateral nucleus",,0 5394,"VLm","human","Abbreviation","medial part of ventral lateral nucleus",,0 4088,"VLo","Macaca mulatta","Abbreviation","oral part of ventral lateral nucleus",,0 4087,"VLo","human","Abbreviation","oral part of ventral lateral nucleus",,0 5404,"VLps","Macaca mulatta","Abbreviation","pars postrema of ventral lateral nucleus",,0 5392,"VMp (Macchi)","Macaca","Abbreviation","medial part of ventral lateral nucleus",,0 5391,"VMp (Macchi)","human","Abbreviation","medial part of ventral lateral nucleus",,0 1116,"Vogts' areas","human","English",,"Vogts' areas",0 1122,"voluntary eye field","human","English",,"frontal eye field",0 5621,"vomeronasal nerve","human","English",,"vomeronasal nerve",67 1372,"vomeronasal organ","human","English",,"vomeronasal organ",503 5615,"vomeronasal-terminal nerve complex","human","English",,"vomeronasal-terminal nerve complex",0 1815,"von Gudden's commissure","human","English","ventral supraoptic decussation",,0 5422,"VP","human","Abbreviation","VENTRAL POSTERIOR NUCLEUS",,0 5432,"VPI","Macaca mulatta","Abbreviation","ventral posteroinferior nucleus",,0 5433,"VPI","human","Abbreviation","ventral posteroinferior nucleus",,0 5445,"VPL","human","Abbreviation","VENTRAL POSTEROLATERAL NUCLEUS",,0 5477,"VPLa (Jones)","Macaca","Abbreviation",,"ventral posterior lateral nucleus, anterior division",0 5476,"VPLa (Jones)","human","Abbreviation",,"ventral posterior lateral nucleus, anterior division",0 5457,"VPLc","human","Abbreviation","caudal part of ventral posterolateral nucleus",,0 5456,"VPLc","Macaca mulatta","Abbreviation","caudal part of ventral posterolateral nucleus",,0 5473,"VPLo","human","Abbreviation","oral part of ventral posterolateral nucleus",,0 5472,"VPLo","Macaca mulatta","Abbreviation","oral part of ventral posterolateral nucleus",,0 5479,"VPLp (Jones)","human","Abbreviation",,"ventral posterior lateral nucleus, posterior division",0 5480,"VPLp (Jones)","Macaca","Abbreviation",,"ventral posterior lateral nucleus, posterior division",0 5499,"VPM","human","Abbreviation","VENTRAL POSTEROMEDIAL NUCLEUS",,0 5498,"VPM","Macaca mulatta","Abbreviation","VENTRAL POSTEROMEDIAL NUCLEUS",,0 5508,"VPMpc","Macaca mulatta","Abbreviation","parvicellular part of ventral posteromedial nucleus",,0 5509,"VPMpc","human","Abbreviation","parvicellular part of ventral posteromedial nucleus",,0 5616,"VTNC","human","Abbreviation",,"vomeronasal-terminal nerve complex",0 1102,"Wernicke's area","human","English",,"Wernicke's area",0 1103,"Wernicke's speech area","human","English",,"Wernicke's area",0 1053684900,"Wernicke's zone","human","English",,"triangular area (Wernicke)",0 3077,"white laminae of cerebellum","human","English",,"white laminae of cerebellum",0 456,"white matter of cerebellum","human","English","CEREBELLAR WHITE MATTER",,11 1467,"white matter of cerebrum","human","English","semioval center",,9 461,"white matter of medulla","human","English","MEDULLARY WHITE MATTER",,0 6071,"white striae of Lancisi","human","English",,"longitudinal striae",0 6828,"X-bundle","human","English",,"pallidohypothalamic fasciculus",3 7069,"zona incerta","Macaca fascicularis","English","zona incerta",,678 7068,"zona incerta","human","English","zona incerta",,678 7070,"zona incerta","rat","English","zona incerta",,678 7071,"Zona incerta","human","Latin","zona incerta",,678 7072,"Zona incerta","Macaca fascicularis","Latin","zona incerta",,678 28686489,"Zona intermedia","human","Latin",,"Rexed's lamina VII",0 1109,"Zona lateralis","human","Latin",,"triangular area (Wernicke)",0 7076,"Zona Lissauer","human","Latin","dorsolateral fasciculus of medulla",,0 7139,"Zona spongiosa","human","Latin",,"Zona spongiosa",5 6021,"zonal layer of superior colliculus","human","English","zonal layer of superior colliculus",,0 7075,"zone of Lissauer","human","English","dorsolateral fasciculus of medulla",,2 1108,"zone of Wernicke","human","English",,"triangular area (Wernicke)",0 voxbo-1.8.5~svn1246/dbmisc/000077500000000000000000000000001153177201300153655ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dbmisc/database_field.txt000066400000000000000000000041551153177201300210420ustar00rootroot00000000000000Admit date Contact Status Date of Injury Lesion Cause Lesion Side Lesion Site Neuroradiological Report Notes Record No. Six month date Special Testing Circumstances--See COORDINATOR (if checked) TMS viewexclude Aphasia Aphasia Description (if any) Appointment Date Appointment Notes Approach Notes Attending Clinic Patient Clinical Information Notes Current Age Date Date of Birth Date of Contact Date of Testing (grant info) Examiner Examiner1 Examiner2 Examiner3 Examiner4 Examiner5 Examiner6 Examiner7 Examiner8 Examiner9 Examiner10 Examiner 11 Examiner 12 Examiner 13 Examiner 14 Examiner 15 Examiner 16 Examiner 17 Examiner 18 Examiner 19 Examiner 20 Examiner 21 Examiner 22 Examiner 23 Examiner 24 Examiner 25 Examiner 26 Examiner 27 Examiner 28 Examiner 29 Examiner 30 Examiner 31 Examiner 32 Exclusionary Extinction Film Notes Films Approved Films Requested FU Date FU Phone Call Grant No. (grant info) Hemiparesis Hospital Hospital Record Obtained If Y, Hospital Record Obtained Last Date Coordinator Checked for Appt Last Date When Checked for Neuroradiology Reports Last Name Tester Lesion Cause 1 Lesion Cause 2 Lesion Cause 3 Lesion Cause 4 Lesion Cause 5 Lesion Side 1 Lesion Side 2 Lesion Side 3 Lesion Side 4 Lesion Side 5 Lesion Site 1 Lesion Site 2 Lesion Site 3 Lesion Site 4 Lesion Site 5 Location of Visual Defect MRI Possible? MRN Name of Control Neglect No Films Available Patient Outside of HUP Patient Says "OKAY" to Participate Protocol No. (grant info) Protocol Title (grant info) Reason, if N Record Notes REMOVED RECORDS Scheduled Appointment Scheduling Notes Scheduling Notes y or n Sex Side Side of Extinction Side of Neglect Subcortical Testdate1 Testdate2 Testdate3 Testdate4 Testdate5 Testdate6 Testdate7 Testdate8 Testdate9 Testdate10 Testdate 11 Testdate 12 Testdate 13 Testdate 14 Testdate 15 Testdate 16 Testdate 17 Testdate 18 Testdate 19 Testdate 20 Testdate 21 Testdate 22 Testdate 23 Testdate 24 Testdate 25 Testdate 26 Testdate 27 Testdate 28 Testdate 29 Testdate 30 Testdate 31 Testdate 32 tester exam 1 tester exam 2 tester examiner 1 tester examiner 2 Tests Administered Today Today's Date Visual Field Defect voxbo-1.8.5~svn1246/dbmisc/dbmakefile000066400000000000000000000015361153177201300174000ustar00rootroot00000000000000 # This is the master makefile for the database project # For best results, edit the following to taste. They are passed down # to the lower makefiles. # binary directory ROOTDIR ?= /usr/local/vbdb BINDIR ?= $(ROOTDIR)/bin PRODIR ?= $(ROOTDIR)/pros FFDIR ?= $(ROOTDIR)/etc/fileformats # the c++ compiler of choice CC ?= g++ # export stuff # export CC BINDIR ROOTDIR # Here are our targets MAKEDIRS=lib vbwidgets vbview client server brainBrowser db_import db_network db_print util INSTALLDIRS=client server OUT= # PHONY declaration makes life easier .PHONY: clean install subdirs $(MAKEDIRS) subdirs: $(MAKEDIRS) $(MAKEDIRS): make -C $@ install: mkdir -p $(BINDIR) for dir in $(INSTALLDIRS) ; do make -C $$dir install ; done clean: for dir in $(MAKEDIRS) ; do make -C $$dir clean ; done rm -f core *~ */*~ */core */*.o client: lib server: lib voxbo-1.8.5~svn1246/dbmisc/demo_field.txt000066400000000000000000000020231153177201300202120ustar00rootroot00000000000000Record No. -> demographics MRN -> demographics Gender -> demographics Date of Birth -> demographics Home Phone -> demographics Handedness -> demographics Education Yrs -> demographics Education Highest Deg -> demographics Occupation -> demographics English First Language? -> demographics Other Languages -> demographics Ethnic Group -> demographics Ethnic Group (3/02) -> demographics Racial Group (3/02) -> demographics Racial Group-2 (3/02) -> demographics Diagnosis -> demographics Vision Difficulties -> demographics Hearing Difficulties -> demographics Mobility -> demographics Other Health Problems -> demographics Current Medications -> demographics Past Psychoactive Medications -> demographics History of Learning Disabilities -> demographics Neuroradiological Report -> medical Scheduled Date for Behavioral Testing -> medical Today -> ignore! Age -> ignore! Current Age -> ignore! Date of History -> ? Total Flags -> ? viewexclude -> score_flags voxbo-1.8.5~svn1246/dbmisc/extranames.ods000066400000000000000000000312171153177201300202470ustar00rootroot00000000000000PKdv;7…l9Š..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKdv;7Configurations2/statusbar/PKdv;7'Configurations2/accelerator/current.xmlPKPKdv;7Configurations2/floater/PKdv;7Configurations2/popupmenu/PKdv;7Configurations2/progressbar/PKdv;7Configurations2/menubar/PKdv;7Configurations2/toolbar/PKdv;7Configurations2/images/Bitmaps/PKdv;7 content.xmlí]Írã6¾ïS°¼U9E#Q¢þœ™I9Ο«l+žlöæ‚IHBB\€´G{Ê;ìu÷åò$ È’MPEÓÌÁR Ðh|èþº‚ï¿ýøÖ¤ üáÄ~×;± v‰‡ðüÃɯŸìLN¾ýø·÷d6C.<õˆG—àˆÿßâOcvšþúá$¦ø”†Ø)d§‘{JBˆ×OÊ¥O“¶Ò;,Zú¹O ËOGðK”÷aQVyÜço9),?íQð˜÷aQ–+U~|Fò>ü…ùáZB¡-)¾øÿñádEái·ûøøøîqðŽÐyמN§Ýä×L`7+ÆÔOJynúP4ƺö;»».Àä•O”•EÂqpinÕ€<Uö0ψ‡ùÕ¸ @sc#)¬ïÀË?¼O~6ÑbϘLºWüÇäÏÕå 4ÈÛ–(«¨Ê¥(ÌÝÍ´´üûø>vÛJ¯Å ~89£ø'Çøº@€üåæ¾ü¨ø¥3‡RÄuÎcJ‰E.GåàÏò™rÒ}¾éKÄ'1ŸT[·³B|B¾Ù*—Þ4+Ú5 îc–4g]îL)U…XßÃßÁ?âçµ%•É#Ò’E08D¦Ï`A²Ÿˆ“ýphëÝ}¸^ÝqÄŠÛIêÉŸüUdu‰5¶’2qºÜ¼ûq€OÖOÊ7;!åf…F2kFNï)tî!Ÿü¼BÑôºÆUñGä ÓÌ]ݸp"¿$Îs²õ«“m¨+Û *ÙzïœÁÐÑΩN¸á¸gë 7¬nTGÃéDO¸QUÂõß Gý‘žpãê†u2íõ„›T¨¹ÞXS¸iuÂ9ýÞTO8»W•tƒwá3Ö”®2Ñ7èkYaºÏ{Qò¸%¿#K•þ$n. š/"ù~?±dÏK3Ø!a„àwäÇ#Ãü‚G`·àë›Ï í„`;k¢3±mõJêQ+{ˆ…>X®äYÕ&â wâñš|Ú‰î5÷?ô3:*’Éų‹‡žŽƒHt€æ¸ÃHLEfc†¾¬+§0„ Ë€ðŸ€Ï$ÆÛs ÂÅê6•rZñH3ÙÐ9ÂÎʧ`“„x"ZB±”À€W’Ü|\<æA¿¯¡Ð}´¦Uh¢Ð{â{:êÜÇÄÞ¦:5·%j*nK®C‡s=[@}|Ÿ’ŠäïŠ`¬Ôxvy²º!KœÐšôvHÑÆJ‰8Ái I3#nÌÖEW?†¡¿ìx “›Ò–̪J2­èæI’¼ÆŠ¥jLM»R†{ŽüõõsÔ7Ö¨oP²|NÉõ Kîï¨äúÆëúÒ¥UQÖI½1ôx8áLMµ¹·¾õœÝª“G ;*áËVÛ¼¾]- ¾Ny?†hBAø,›‹:Ä*[øQ8‘ô,Þ ³~Ydàh¡È‚ÜÆAjEÄš!ìY©5‹ ¿´0|´(œ#‚Ùûîª&þ-±r :|¢ÎgºôÒæ®kør]C;wmÓĆnßQ”€<@ëîkFI`^/»QL¡•¬9µ#V¯ûVügñ†\Þ –/øÏÌB–‡<œ.?DÖ˜ 󸑘ޱQ´h²^™XP10üWŒxI±ûãtÖYlAb3 Éú ŸKkø|%Ñ‚›Z ýdŽ-PØÎÓ ‡7ßZæi£ŸkÂð˜Àú%¡ÖßGû(w›×ü‰ÃÛË×ÇŸ(XVÕÖ9{ªÒãw}]’FóµüÉ„©åŠ vL1ÓsiOxðLGò–ì—h¡r¨o·…*W};Ð3ó ˆT\‰Žehêëa'>o(tù´àÎýàªw ßëÉòó«"ð×ôývÈ÷xA+Ì`Í—4.4;ŸÁQ¯dÿ•WïÃɦ¯ÃIù°!,2Š›‘‚›Q q³Ñ@£€cKÀ±ËÎ/Ä"x¼ûBjÈä ²ÉáWZíF—®.ò©BfýH Ž€wg_[Ù]‡¤Kj¯†»}{Ë*P]¼­av‡¥ÄeŽAñù|€*Ò‰¢ŧ„>z¹ûâÉ´;E9¥[* 9wßʈ!ãn+|Ò®/8pÕŒ$f6Ÿè½)ÐØ hì4¦AÓ—ŒM߬µ¹‚2¾Žs3jÍÍôå™G5£š:8¼B^½ø’“Küyž[¶´kêKqpùa°„›»K2^}Åxõ+1^»†p’ ŒOlZÁIUCoh÷¤¤JÏ(šÌ‘¨¾B¢úµ%Qõ‡M£]ážÕËæáY›:ØoÀ¤©¯;ñõ°c41¬øÃAmÉ|Á)TGÇ'…¶¹0Pàæ3E¦`£8¾Am_ƒ`#åœlsI§ÄÜãKƒ¾›~ ›WÍ—œ޼Þ¦±ùBÞzQÕ–§Û8 ï®HDèÝ… 2˜?í¨¸x§˜‹/J”’9iYY¾’vUÂH€ä9úšž£ø@e¡',€Üc…žŒŠÑ“â7´9¢5ålÅ|ÙiíÜ&~¤U#%ÃT:ïûäÏ€Ëý’æçÜÒç3Ôt>ùÀQš¸àqóŒP1ª‹ïÓ“äJ&vv Û/­ô 왃n¤›ŠÊ-úXÁì¸Ì&¹5‹èWåÍ«Èĵå§ø/0‹}M._tݽ¶1€ ô¨5PÅFØ‘·~•Ÿ†;¾ ø-Mw“{/»‚ÏaEøt×âÞÔwc§)@rÊO­ÇšòUÞ­à@3Ò)Šƒ=ªïèKLÅ)Ÿ©\ò«ØÔ^,Χ•á×  ¿ŸvÉÈæz3Þê¨ùÉWé‡=W凮‹BT(‘»ʶè¡î¶è‚s#ÛnOÖ=|Ó$·Re•ÈFd°ÐÞ±’¿ ,ªÙ¦“¢ÛÇ'÷eg+Žöî¥Ä¶‡å³í n´Wîr÷@Ù)1¬ßN‰fâF¢æC«Þ1Câô9CQVÞ†º+o1[õéUøÊéYî7|$þ3*ŸÿÜð0¥?#…þŒª¦?᪃ÂÅ~ݓ*«ÔÀÉkTób#…ýŒêÇ~²=§ft´%4*ŸÝŠ—߯V/¿›B­ ¨šŒ“ù·úfRäwIËg8gxûÀÐîáQ¿¯`¡šôH»Ô,HIÈ‘³i(,’³Í-½tc£‚8‹uªr <-ø*3‚c‰0b°:<èî²€ËÏﬖ”=Uõ¾cYt˜Ð+;…«!(ŸH(Ÿ”òŸ!s†˜ÙD‰ø&E|Ù^+ŽTÌÄ×9¡Á $¦€{,=‘•[~ì÷y¥3s‰räǤ~G~dÉ£ø9Vè7‘B¿Iù¡_†ŸâC“ ê+ ªÝ+< ‘-NÊ3[~›( ¨IýP«ó?š‰ùò£LÕ„âÇêwêB“!4•øñ´|~œAÈX|¢ä*&å*²´ö«¢Æ/6XÁêÜ“ýtWß]œ—¬¸á±vÈË›ÌË)ÎÅF=ÞÛ»3lè<%GÙ‡ìT´9‹9ݤƒ|_ÅtÊ )RØš¾F…1í(»’Ý]Éæ=´YÜË7¤à```û7â¤{SÀé+À©fAIœ[ßh{"ÑþAù´ÿg†ÄAhjyÉQ›NE‰ÍEÑnÕNOž[FVp2,˜Ú~à(ILG7‰YÔBð®-6]{ÖáÅ@ÞoýîüÓ/Ÿ/ÎÏ.Âàå3ø³`9÷€©·\%çè&㊲÷B}ª­UK*ˆá@ìñ.šÀX ߯•½Fštɱë×ûFn]JQÛ¸ü¨í&ޏ”ØlyÕ"]ªïøKÑ׸üèëø>òbC¯*Œ•Àk\Qà5{{™¦]kŒ!­±U–÷©Xk¬ÄZãŠb­¨PŸ*GÀ‹ ¶/ï^4’ 55@‘ …÷¼lÜó¸Ì633¦ WšÖïó‹n¦††ä3§£šȃ«°9—{`c+°©_.¼q°‘ˆØÔ@|›)ÈôÈÔnUó #Q¶iù”M‚Œs74šÝåä4º·{Ê'lÊO¨K°9ÜŒí£€F7ƒÙ‚F4ògCt9¤hƆŽñŸö† jt‚iQ£ù£!=£\øp÷·4#4º¯Ï· ÑüÉžQ&<5š±Ýõ•4ú ™È 1Ê…KøìßÔLÔè¾­Õ¢¦aùG»7•A}¸±ÚÙ@ vgß™J")±ÆT;ب Ñ€Z.¡üך;7r”Ï”øNé 9¦2IŠüSí´¸)Œ[ÆÍáK{pc.d÷äûVV‹œÈ‘>,ºBŽ©Œ’=Pp£û݇7…q3qs¸CÙƒ›±)Ü8 nt÷'·¸)Œ9µdàƒ´+ܘJ+ÙC7ºg•·¸)Œ›¡Œ›ÃiÈܘÊ,Ù#7ºg¼¶¸)Œ9+iàKÆëXÜTrÉ+ÀÑ= ímG­ž—“ë gP£}wú Êw”j×5&^ŠÆàd‡@È”òŽ8 ÏඉH»ž#“õã^š©K:ÔÙ•ÂÛÚþ:§ê´{&*µ T:Αììm÷Àt¬ §¹>ûןÿ…ÿŠÑÃ_þÏ ÀÌz„ð)ÞÒZ€~­¤ð!Ž,qðàÒB\! h]_[àm¿æå<Ë#ø+öMda=~o-x{ü걈µyÒ£õ]öë^iöúÓõB±Ä$‚â#ŽsD¸Š£ˆRåb"”(é÷¯?ÿcÍÄ)×2qƔ벯…— â™Èò‰ |ôoÞ`sÔúòGã{VJª^ÌÖJº™ç­ˆñ÷ßY×ü¡ÃG8_“ü/[b‚—…ÖŸŠ4ÊÑO¡"1/(ÔÛè_ç¡ÏÑ÷«ó³ÒIîꈩ„ë‰Ó„'z%|ÃùɰqËV2}T?7@:3¢ƒ½830›c€øÐv rŒA—#ë7.e ¨wúOÁ¸´ª»¹0jC²ãá¤à½…ò³P&&í ‚#—óÔ´ñL/LÌ $ÆA|çÅ”DÈkGàÙ©°Fíù‚P‚<®·3}}½ië¾Q¡2ñ[5j:ÉÌŸµzµzÓëÅ9¢®ÅÒoÈ÷Ñáš7£¹)Á‘æyw–d­YÚ ‰ïüÃÚ­>ôXþäOK6@ë3Ó«S`vˆy3˜}=¼: ýX÷10XäŸC4øúUvCp«. ^GÂ<¾8ü´íšïEÍ–‘ª›Ap®—è¨E«NÂmûOÏ}¤wÐéÛÖÛŠKwª$…»~ìA¦ðêo¬ìvÃèâZÅUÒÆ—TÜ0B¹Fïqt¬àõ (¹Rúþ¢–›Æì3í̪:›‹æm«Ü92¼óê}>²Á³aï0½šÁyýcP—)òÖçÂ9¡a̬ód¥Jó(“·åÜ (æ@¨fy*M8.–! K¦¹°SKõ;>çmc.}-®:À=$í‰õÄl[UCÌ^²¤I³ŸK9†ù+ðÝ·=yobÿa@[•åîÆOé·EnŠ|[ämkî·âÖ&7ÛZ¹õkE›¯¥2Wcñ^½m,®c½V‡%I[ý˜ýlXÐ S°¬PkÍXp¿å× ".Y,ö²¦/”·úËÛ‹‹Í $BƒÕÅj¯_u?|iUW<J0°(ðøä­dÓGSf«°r-Ðrw#{]Éå·¹êªLF'mùú1œn|pêo œ›õ¦gð¹8.(,DÄ 7ÕáqݤåB܈„ÁíÒ@[?"ÆbZ¡&Å\‘6Ÿnæ³x‹Ž¥ÊlgrÞ^üŒÂÇAØfLõ˜_$ÞØ!ÑW7q ­îtýé½[!n†Ò~Å,„.š¡¦Ç'ßáW+ÙX(Μf £ÍÍ{â-7Wqã€;IÞììãÿPKùžÇ[xA!PKdv;7 styles.xmlÝYmoÛ6þ¾_!¨CÑ“%9i»±ƒ ŰéPôe_ Z¢d.)”ô×ïHвdIŽÖ¬ëºH¢ãs/zîÈ;:W×wõvXHÂÙÊg‘ïa–ð”°|åüðkpé_¯¸âYF¼LyR˜©@ª{Š¥ÊL.íâʯ[r$‰\2T`¹TÉ’—˜9¥e½4®¬Ä›ªnÀmm…ïÔTeíè¢ÍtÏÜÖNÚOUÖXà´­žñ©Êw’^”H‘£(î(a·+«T¹ Ãý~?۟͸ÈÃx±X„fµ 8ipe%¨A¥Iˆ)ÖÎdÏâÐa ¬ÐÔø4¶«Š “©A õ²*wùäŠØå#Ô$[$&׆wÓ{–NOïYÚÖ-ÚŽää2|‹æÇ››C-ˆbª/íP•RN~M‹nësΛPµ‚Ý &Üy‡ö¹…ÞŸ„ïQX´àÉIx‚hÒ0΋!Ò‡€ðN—©ïÕGHçØZ»3*ãp>e(ÁAŠ*×W¶¶±gŸ5G+ÿgAõ=(!(½?ÈÛªz%È1ÂÀ+É=‘²ƒ(‰J é;ºPˆ~xÚõ =5Ë™÷19ÄSTrùêg…_7´ßI±©¤qçÝŒÖAýa½Æ¢?ªÓlµ0SBº— ‰éÚò „Ó,<Ö{8V׵ܶbeŠ3TѺA;ËuH¦ ¦Ôwðƒ((lO¡´ug*!‚ NåÊŸ¸(‘@¹@嶯Á9/ƒ”H…˜ž ¢Ù Âʺ ÷õÌë쌌/)by…rXÅÌ^1%à­>¾÷Mp "v\0ãì8ˆ¶fWjƒnaȬî2ß'·±Ù¬÷­6K`W'u [ë+Û7ëöÙIa½/õ1×yõSAX@˜Â9è¥$' òG6I%L{÷C®âèümäÞbÇ)äCJJTØ0p_l8uÑt“å°­„­l;21ò~ýZ<ýæn5¼*Í,koÒ}÷©”øcEl*’rzždY_ÚWmSc×AãÙ<~Ç Z T6%ÎR¢L#Þ!ZágÏŸæêÕª)T–´æ3è׉lXÍ~^Û ãŸlá¸ò;,OëzÍéÖÜq‚®ßé7ÇD}•! Q’8{\± ƱÃHNI:Ù“TϨR|Q›qjþö›ö˜ä[˜¡ÒÖYó³–œù±Ó%VÏó½tŸÊËoéûæ?“˜ ÍP‰ÉY y%tkÊÈ3.p‰‘&¶ú2D%~ åå£+?E}G;]S%ä3øŽ_–Ê«œÇ%³f4þ"J]:¦P*¸2:€óJ‡¿ˆúAê«/â#ó·½ßoÁ—ü4>A¨f ¦8¡îƒcŒÛkGðþ}4ò"oyg‘•ÃM­ˆAÄZ¶GŸÛ³“›‘êG½¯à†F’ ;<•º‰ƒw^©eû˜>úîÔOAŠ@mÕ ßãЂ;²Œs(œ£RÑçò¶N4›/^\;ú—9¬Qœé•®PÔø®tÕÒw«h-.Ïí0ŽGU‡ó-"…Éq0ÌnHa/§pþ?K¡^Ûp‘êZ@xvþ’0Ï4ïId¾ ¤D©ý00ÑEìQr«;;K]'y’Dú»!©…€¹!ǽŠé½ð÷QRÿ]Ú.ñpôüª $ò0©¡¶tj–jïŠþ±g£__™OPËú·ÜblÁëëëë«ðXXKÊ#Žò¯SéF{ú÷𝥦ñþV¿Jý £¶Cä:vþZ²^ÎT‡ó“!„=bö.¹8Iì¼G¬BrÝMu<“kï™Å)¢hbŸŸ÷xèxêˆÌ.:ò3ï`hl@¹ÀõvM-‚ù…¿ŽáüBŠwQG¡ëŸ<0DGËñ2ºl‚ªžn|߬¤¼° 4—²õbÑZÙW*½px¯‡Ãÿ¢YÿPK .<ÏËâPKdv;7˜ ‡-ÓÓmeta.xml OpenOffice.org/2.0$Linux OpenOffice.org_project/680m5$Build-90732007-08-15T15:49:41Dongbo Hu2007-09-27T10:51:08en-US51P2DT7H49M26SPKdv;7Thumbnails/thumbnail.pngu–{8Œǽ•2s©Þr}u™JåR4—\_r-³¹ÎýÎ0—%a ™bºR±æ²Qî 1„lc’•K²±"— ½~ïó¼Ïï÷{~ÏïsÎç9çó=ç<'Óþ’•¤¸‚¸ˆˆˆ$ÄÚÜa;&nÛ#±ÝÛ¾ÿ³Ø71 ÄÜÔ1ŽÀ+ä}Ñ“°0PŽþ¥êW'}$ û?­[‘wµÃ÷›_F3~ …B÷ÜŒùÙÙÙä¾ääIÓ8îD³‰,G<Å€Q?6ýgÖ?aR ²wøCl$÷íÌÁl¥°ÑU¤`‹PJ¢n$É3t€­ô*å7Ó‚§Ðغ7üÊV*E\€í\áD@àR§?Y#\1¬Î3]©PõD¶d~Ï·L‘%W‡Ž–AH}H4·²YDçyà¿[¢ÐNáŸ5biarûeÈ7ÂÏ+H)ô5–?vÿtÚN)ÕÞ•€Ú.…pûâ¾—$QÅÛÁ¯a¢Q?ûÖ$Ç)igïy8N¯CÛù^”zÇ·¨Ø5†n$Â÷™ý›-9|¥ç}ôª½ñÁ^ïJ føOÁÎxóŒF»o!¼fÐUÒbRçHž†SóMpѽ _÷λ‡áìSJÌBóæÄú)Ìúx=$jÖ×ì¼Çùæ[\ËãùTº§ø/1¬Öd ¥Ÿ´é¿l·c-éTPª%PV§$´6ÅcK±Ò€ó»¸;^B²6]å¦O)‘Ž E:6³¥×ßÔåDÞ³¥ŒëÕ$~æ¸P(€}:r–~õwÑìs¤k§:f,ï–°I0Tç¬,†÷2~Àê² ºrïS៎’&—>—…¥¯È¡'"]«mûdƒ–pŒiù9• ƒ2oÕ¸7jI³ÊЏ½Ï·nŠ.ªœu1}QËøBdY ·‡u¯ÐðDJF©ô¬ïÇ»gáÆj-1Ô #šx¿Ž #šDPýÊ~qÁqÂdP+çäØÍl°u%¸h®”¾ÒøLI®é+¾ØLAŒìºœ+å×É*!7ˆyƒX¸zž¿Hï»/E^ù‘Owkóì-z)¶\ÏÑ YwQ,…ä;{7… ;†|¹ |Ùfcæ{õk¬7Þ4£Iåè¡UŠOwÙYdï7”?§eÃ÷¹;ùîd[þåT•/APÅñ.,-ä´U ºC-?H6Æ´9Ï<¸®ÆÜlè8qô,ÿˆ¶TïžUmI.Ûrˆ EŒ½r¹íÑöWgžq+^ÏÅZÜ«ï~?Kw¼õ}*?åv\û­E_©VóÖ%¤IÑK±;',{3I¼`nDh3x“(¯´qï+ƶ·ý@ò´åj’ß=÷z܆^P1I’Ð!eôL~¹?‚rãkÞn¦óFÓ©¬öÛÀXz±XÕµ39UeЬÌ1¡>3gYQ•ö2ÆÞØ ó¯«) çWÎ/ÎS©A¢É»pß:Ž÷_‚ŽŽÖx´ÎWEømⶤ˜k¬¶çFú2·Â*yÆ[K*ƒkNP6çcZ¢´ç*ô†•Ò#}­žG+3?Se“Oýƒë¿´O—q^u7’WË{ŸzAmPS"XóXÌ/]–€¬«Œ#H™ƒ'å`×ëáñ'(afÀJDæirpîæ®®Ð8Ͳ;ØëS#Œ¿CeÙ=彚£vÿ-×¥ËÛÛRc>$_ØŠï?‡§{u©Væ{h¯°òÝ¿v(‹³lìú»K—Æ]7•ÃÛ_mÜ;;vzäò‹2:ìºÞQßEãú[¹¶_¨·4>€LñÁ4Ñì³ê4ÈÚÃÕöAçþ¡²þ,ýV£¸²IQèvcVd'éÃLš÷ó>uCåX\}‡Q¢žŽ=ì×DÖÒ:>Vä\¢ïÜe÷VÂΆòKn$hÍwí6šíà4qÑa‡ýÛØQÆQGă¤_E8f ReÁîTµ¡ô"ÿ¤Ž7óƒwÓ!@ábøZ“Œdÿ¤a”d øýP™/Í@•9„Ï)-˜[ðê™ ©“Äp6v;+©%†RIû Üß9—ëÉåQËñ°‚€é‚šåj¸ê@ã£ÿ«"/„p=Æ-¯Ê³¨ëùœðºY‚S‡ÆµQR:+½¦Þ¿;£×yËîq¼˜¥ûX´g]Kláý‡ÓÞ§Üq²ÏdŠ_ÜÞ›¸M€¢áª_1^ÀT¦$e^Y.”>whüsKìÀX¹vT%–àþº¦zŸ/Œ‰zPí3ž°«Ð‰h\MG¢â“ÀóƇÏJͯI.9‰±HÚyǸîÚÙ=|šQ1¨-‘¸³ø71Üšô—X¶Vßzs'§Ù%†Î°Ê>£¢X­)lâ®GÁˆäP ·œÃs*Á£—Ü飓ըݾÁ÷™W$kPIB*»Zøpk¾¶Õü½åÈB£ÜíQ˜•Õ …pëQ­"gñ«ïÿóüÛöŒæL@LöÞ]9·Ï%¼û⛋QÆ@Žh—Ùí§ƒ¤[ÝÃÚØ\·Zy3 Ö¢ýÅ nÙ»”.“x“Ûîð¯A~¾¬È‰Èj¦bÒ×4Â.×"øÒ—È0Þ(%°Ž7À¢ïk>478aFv©«€ÌS, Š> DXìÒ‚ÇÔÂä®Ë“qãósÍÚâD¹}~~öÔY»O£DaZBÆäÈj¡,ªDÖ³œÙúM +ómÿ""‹Kæ•f©PKœ#Å ²PKdv;7 settings.xmlíZ[Sê:~?¿Âéë¥ÔËFÙSª(nA,wÞÒ6@$M:IJÁ_¿S {´¶Š¥Ìœ}_°IÖ·VV²®íÕÏ…‹æqDɵRN$ãeØÂ‰œ_œÈÁ‰œH'’ü…I›^å-Ûü*£II™dê²³UØŒbl–ž¡þȨÖ¥nGâäjÏ!h`?Žùz5ë 柟¢_doOi2¨ÊD}Öb0¬|bø¥¢TÆs˜Í2º’Ÿ§1Ìß¿Iž ïŠW9 ‡¨ŔŠ1 í§¨]œjZÖÀøî\÷ •{À¥è¾KLÜCàÈÂ{/LÚS…t3{@¯ó'_`D`{éZó6ŒGƒ\˜´ ð:Ô\ÀøAçaYp¯ î½q0!—çš3{â8|b~¸+|Û·4G¶#+lÑ:¦~È)3}oÕÿŽÑíé«p‚ˆÌY²ïà–8ŸÒïÐêßUÿH26ô?;•J·±Wý·ŸÕ—uÔ—zÝXžA]A†ïÜ›”uþ 2¢s©ë–OlჄw¹ôüÀö¢2žˆ)ßG&Õ5FÝt½Ï’…˜è˪(ŒèÔ2±!ÞCeDcʲ…·¬möZ£>|SHû>¨òPKBÒïa$PKdv;7META-INF/manifest.xmlµ•KjÃ0@÷=…ÑÞVÛU1q-ôé&òØè‡f’ÛWäÓ6”¦X; HïFi±Ú[Sí0’ö®OÍ£¨Ð)ßk7vâcý^¿ˆÕòaaÁé‰ÛÓ ÊëÃN¤èZ¤©u`‘ZV­èz¯’EÇí×ùídZ>Tð  Öybì„`´ÎyÊ뛣«¹V4"BO[DÈŒ©ð¶RÈ»œ·)oÞ zLñ˜ =KbàDˆeð Ì¡R¥§æbw Æc!xð!…|R!|ôcD*wÒSêÅàì½)×F$ùªÙB ¢Ž;Ùߟ Jnêž&éF] þ–ÃrÆ=Ë©Wo³Ÿÿ×Ì¿s‰iv¬E†Ùžõ6ÙmHòiØ7Î Ÿ·°ÈœÿÅsiòÇ·¸üPKÌMfBQPKdv;7…l9Š..mimetypePKdv;7TConfigurations2/statusbar/PKdv;7'ŒConfigurations2/accelerator/current.xmlPKdv;7ãConfigurations2/floater/PKdv;7Configurations2/popupmenu/PKdv;7QConfigurations2/progressbar/PKdv;7‹Configurations2/menubar/PKdv;7ÁConfigurations2/toolbar/PKdv;7÷Configurations2/images/Bitmaps/PKdv;7ùžÇ[xA! 4content.xmlPKdv;7 .<ÏËâ åstyles.xmlPKdv;7˜ ‡-ÓÓèmeta.xmlPKdv;7œ#Å ²áThumbnails/thumbnail.pngPKdv;7BÒïa$ Ç'settings.xmlPKdv;7ÌMfBQ-META-INF/manifest.xmlPKî‹.voxbo-1.8.5~svn1246/dbmisc/history_field.txt000066400000000000000000000010751153177201300207750ustar00rootroot00000000000000Record No. Date of History Age at History Screening Notes Vision Difficulties Hearing Difficulties Mobility Notes on Vision, Hearing, Mobility Current Medications Past Psychoactive Medications Other Health Problems Health Problems Notes Previous Hospitalizations/Operations Family History of Serious Illness/Neuro Disease History of Learning Disabilities Learning Disabilities--Notes Head Injuries Accidents LOC Head Injury Notes Physical/Psychological Changes Explain All that are Checked Behavioral Changes Explain All that are Checked 2 Neurological History viewexclude voxbo-1.8.5~svn1246/dbmisc/networkdemo/000077500000000000000000000000001153177201300177235ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dbmisc/networkdemo/Makefile000066400000000000000000000010321153177201300213570ustar00rootroot00000000000000 CPLUS_INCLUDE_PATH=/usr/local/include:/sw/include LIBRARY_PATH=/usr/local/lib:/sw/lib export CPLUS_INCLUDE_PATH LIBRARY_PATH OBJS=connect.o tokenlist.o vbutil.o dbserver.o LIBS=$(LDFLAGS) -lgnutls-extra -lgnutls -lgcrypt -lz dbserver: $(OBJS) g++ -o dbserver $(OBJS) $(LIBS) connect.o: vbutil.h connect.cpp g++ -c connect.cpp tokenlist.o: tokenlist.h tokenlist.cpp g++ -c tokenlist.cpp vbutil.o: vbutil.h vbutil.cpp g++ -c vbutil.cpp dbserver.o: vbutil.h dbserver.cpp g++ -c dbserver.cpp -Wall clean: rm -f *.o *~ dbserver voxbo-1.8.5~svn1246/dbmisc/networkdemo/connect.cpp000066400000000000000000000154541153177201300220710ustar00rootroot00000000000000 // connect.cpp // safe, easy connection-related functions for VoxBo and beyond! // Copyright (c) 1998-2007 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include #include #include #include #include "vbutil.h" int safe_recv(int sock,char *buf,int len,float secs) { fd_set ff; struct timeval t_start,t_deadline,t_current,t_timeout; int pos=0,err; // buf is valid even if we fail utterly buf[0]='\0'; // before we do anything time-consuming, set a deadline gettimeofday(&t_start,NULL); t_deadline.tv_sec = (int)secs; t_deadline.tv_usec = lround(((secs - floor(secs))*1000000.0)); t_deadline=t_start+t_deadline; // THIS MYSTERY CODE WAS NEVER USED // if (checkfirst) { // FD_ZERO(&ff); // FD_SET(sock,&ff); // err = select(sock+1,&ff,NULL,NULL,&t_timeout); // if (!(FD_ISSET(sock,&ff))) // return 0; // } while(1) { // create socket mask for just the one socket FD_ZERO(&ff); FD_SET(sock,&ff); // timeout as specified gettimeofday(&t_current,NULL); t_timeout=t_deadline-t_current; // make sure there's data available err = select(sock+1,&ff,NULL,NULL,&t_timeout); if (err < 1) return err; err=recv(sock,buf+pos,len-pos,0); // break if we didn't get anything before the deadline // buf[pos+err]='\0'; // FIXME if (err<=0) { break; if (errno==EAGAIN) // FIXME not needed now that we're nonblocking continue; else break; } pos+=err; // break if we got something EOT-terminated if (buf[pos-1]=='\0') break; // break if we filled the buffer if (pos>=len) break; } // null-terminate if there's room, in case someone lazy uses it as a string if (pos > 0 && possa_family,SOCK_STREAM,0); if (s == -1) return (-1); fcntl(s,F_SETFL,O_NONBLOCK); if (addr->sa_family==AF_INET) sz=sizeof(struct sockaddr_in); else sz=sizeof(struct sockaddr_un); err = connect(s,addr,sz); if (err && (errno != EINPROGRESS)) { close(s); return(-2); } // set up for select() FD_ZERO(&ff); FD_SET(s,&ff); tv.tv_sec = (int)secs; tv.tv_usec = lround(((secs - floor(secs))*1000000.0)); // wait until socket is writeable err = select(s+1,NULL,&ff,NULL,&tv); if (err < 1) { close(s); return (-3); } socklen_t len=sizeof(int); if (getsockopt(s,SOL_SOCKET,SO_ERROR,&err,&len) == -1) err = -1; if (err) { close(s); return (-4); } else return s; } #define F_BUFSIZE 65536 // send_file() tries to send a file through a socket. it's presumed // that the process on the other end of the socket is already // expecting a file to be sent (i.e., is calling receive_file). int send_file(int s,string fname) { struct stat st; FILE *fp=fopen(fname.c_str(),"r"); if (!fp) return 101; if (fstat(fileno(fp),&st)) { fclose(fp); return 111; } int filesize=st.st_size; char buf[F_BUFSIZE]; // send filename sprintf(buf,"send %s %d",fname.c_str(),filesize); if (safe_send(s,buf,strlen(buf)+1,10.0)) { fclose(fp); return 102; } int bytestosend=filesize; int packetsize; while(bytestosend>0) { packetsize=(F_BUFSIZE>bytestosend?bytestosend:F_BUFSIZE); // read a chunk fread(buf,1,packetsize,fp); // send it if (safe_send(s,buf,packetsize,10.0)) { fclose(fp); return 103; } bytestosend-=packetsize; } if (safe_recv(s,buf,F_BUFSIZE,10.0)<0) return 55; buf[4]='\0'; if ((string)buf=="ACK") return 0; else return 66; } int receive_file(int s,string fname,int filesize) { FILE *fp=fopen(fname.c_str(),"w"); if (!fp) return 101; char buf[F_BUFSIZE]; int packetsize,cnt=0,total=0; while(1) { // read a chunk if ((cnt=safe_recv(s,buf,F_BUFSIZE,10.0))<0) { fclose(fp); return 103; } // write it cnt=fwrite(buf,1,cnt,fp); total+=cnt; } fclose(fp); if (total!=filesize) return 103; if (safe_send(s,buf,packetsize,10.0)) { fclose(fp); return 105; } return 0; } voxbo-1.8.5~svn1246/dbmisc/networkdemo/dbserver.cpp000066400000000000000000000314071153177201300222500ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include #include #include #include "vbutil.h" #include #include #include using namespace std; int main_server(); int main_client(); const int SERVERPORT=5556; const int BUFSIZE=1024; const int DH_BITS=1024; class dbpermissions { public: long data_id; // id of the thing to which permission is granted string permission; // r, rw, or b }; // temp class for server to keep track of multiple connections class DBSession { public: gnutls_session_t session; int sd; }; // db_sessions, includes all the major bits of state information you'd // want about a session. class dbsession { public: long userid; list groupids; long authtoken[4]; time_t logtime; time_t lastaction; string msg; }; list sessionlist; // static gnutls_dh_params_t dh_params; int main(int argc,char **argv) { if (argc!=2) exit(0); if ((string)argv[1]=="server") main_server(); else main_client(); exit(0); } // make_gnutls_verifier() -- this function generates a random salt // value and a password, and generates a verifier. the size of the // verifier will be in verifier->size, the data in verifier->data. // the calling function should declare the following: // char salt[4]; // gnutls_datum verifier; // the salt and verifier will be deposited appropriately. this function // allocates storage for the verifier using gnutls_malloc. when done with // the verifier, the datum should be de-allocated like this: // gnutls_free(verifier.data); int make_gnutls_verifier(string username,string password,char *salt,gnutls_datum *verifier) { // init salt structure for gnutls gnutls_datum mysalt; mysalt.size=4; mysalt.data=(unsigned char *)gnutls_malloc(4); if (!mysalt.data) return -1; // generate random salt, copy for calling function and to salt struct unsigned long st=VBRandom(); memcpy(mysalt.data,&st,4); memcpy(salt,&st,4); // FIXME here we generate a verifier using the password foo. what // we really need to do is copy the verifier from the database, and // init the verifier structure using the same method as above return gnutls_srp_verifier(username.c_str(),password.c_str(),&mysalt, &(gnutls_srp_1024_group_generator), &(gnutls_srp_1024_group_prime), verifier); } // srp_credfunction() -- this function takes a username argument and // fills out the salt, generator, prime, and verifier. the salt and // verifier come from the user record, the generator and prime are // hardcoded gnutls constants. note that we have to make copies of // the generator and prime because the calling function expects us to // do so. int srp_credfunction(gnutls_session session,const char *username, gnutls_datum *salt, gnutls_datum *verifier, gnutls_datum *generator, gnutls_datum *prime) { salt->size=4; salt->data=(unsigned char *)gnutls_malloc(4); if (!salt->data) return -1; memset(salt->data,'a',4); // FIXME get salt from database // copy stock generator generator->size=gnutls_srp_1024_group_generator.size; generator->data=(unsigned char *)gnutls_malloc(generator->size); if (!generator->data) return -1; memcpy(generator->data,gnutls_srp_1024_group_generator.data,generator->size); // copy stock prime prime->size=gnutls_srp_1024_group_prime.size; prime->data=(unsigned char *)gnutls_malloc(prime->size); if (!prime->data) return -1; memcpy(prime->data,gnutls_srp_1024_group_prime.data,prime->size); // FIXME here we generate a verifier using the password foo. what // we really need to do is copy the verifier from the database, and // init the verifier structure using the same method as above return gnutls_srp_verifier(username,"foo",salt,generator,prime,verifier); } int main_server() { int err,i; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; socklen_t client_len; char topbuf[512]; gnutls_session_t session; char buffer[BUFSIZE + 1]; int yes=1; gnutls_srp_server_credentials_t srpcred; printf("SERVER MODE\n"); gnutls_global_init(); gnutls_global_init_extra(); gnutls_srp_allocate_server_credentials(&srpcred); gnutls_srp_set_server_credentials_function(srpcred,srp_credfunction); // note that the reason we use the _function version above is that // the alternative is a _file version, which means we have to use a // special srp file. we want to keep the info in our database // generate and set diffie-hellman params // gnutls_dh_params_init(&dh_params); // gnutls_dh_params_generate2 (dh_params, DH_BITS); // gnutls_anon_set_server_dh_params (anoncred, dh_params); int s; // create the socket, make it reusable after exit s=socket(PF_INET,SOCK_STREAM,0); if (s < 0) return s; setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)); // create socket address, bind to our socket memset(&sa_serv,0,sizeof(sa_serv)); sa_serv.sin_family=AF_INET; sa_serv.sin_port=htons(SERVERPORT); sa_serv.sin_addr.s_addr=htonl(INADDR_ANY); err=bind(s,(struct sockaddr *)&sa_serv,sizeof(sa_serv)); if (err == -1) { close(s); return -2; } // express willingness to listen for up to 16 queued connections err = listen(s,16); // how much of a backlog should we allow? if (err == -1) { close(s); return -3; } printf("Now listening to port %d\n",SERVERPORT); client_len=sizeof(sa_cli); printf("server waiting for connection\n"); list sessions; while(1) { cout << 111 << endl; fd_set myset; FD_ZERO(&myset); FD_SET(s,&myset); struct timeval mytv; mytv.tv_sec=mytv.tv_usec=5; int ret=select(s+1,&myset,NULL,NULL,&mytv); // use select() to see if s is readable (we have a waiting // connection). if so, accept connection, do handshaking, and // create a mysession cout << 111 << endl; if (ret>0) { cout << "new connection " << sessions.size()+1 << endl; // create new session, push on back of list, get ptr to gnutls session struct sessions.push_back(DBSession()); gnutls_session_t *sptr=&(sessions.back().session); gnutls_init(sptr,GNUTLS_SERVER); gnutls_priority_set_direct(*sptr,"NORMAL:+SRP",NULL); gnutls_credentials_set(*sptr,GNUTLS_CRD_SRP,srpcred); int sd=accept(s,(struct sockaddr *)&sa_cli,&client_len); //printf ("- connection from %s, port %d\n", // inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, // sizeof (topbuf)), ntohs (sa_cli.sin_port)); gnutls_transport_set_ptr(*sptr,(gnutls_transport_ptr_t) sd); //printf("transport ptr set, about to handshake\n"); ret = gnutls_handshake (*sptr); //printf("handshook, or not\n"); if (ret < 0) { close (sd); gnutls_deinit (*sptr); fprintf (stderr, "*** Handshake has failed (%s)\n\n", gnutls_strerror (ret)); sessions.pop_back(); continue; } sessions.back().sd=sd; printf ("- Handshake was completed\n"); } for (list::iterator si=sessions.begin(); si!=sessions.end(); si++) { fd_set myset; FD_ZERO(&myset); FD_SET(si->sd,&myset); struct timeval mytv; mytv.tv_sec=mytv.tv_usec=0; int ret=select(si->sd+1,&myset,NULL,NULL,&mytv); if (ret>0) { cout << "found data" << endl; memset (buffer, 0, BUFSIZE + 1); ret = gnutls_record_recv (si->session, buffer, BUFSIZE); if (ret == 0) { printf ("\n- Peer has closed the GNUTLS connection\n"); break; } else if (ret < 0) { fprintf (stderr, "*** corrupted data(%d), closing connection\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ string foo=(string)"got "+buffer; cout << foo << endl; gnutls_record_send(si->session,foo.c_str(),foo.size()); } } } } cout << "shouldn't reach here" << endl; while(1) { int sd,ret; gnutls_init(&session,GNUTLS_SERVER); gnutls_priority_set_direct(session,"NORMAL:+SRP",NULL); gnutls_credentials_set(session,GNUTLS_CRD_SRP,srpcred); sd = accept(s,(struct sockaddr *)&sa_cli,&client_len); printf ("- connection from %s, port %d\n", inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, sizeof (topbuf)), ntohs (sa_cli.sin_port)); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); printf("transport ptr set, about to handshake\n"); ret = gnutls_handshake (session); printf("handshook, or not\n"); if (ret < 0) { close (sd); gnutls_deinit (session); fprintf (stderr, "*** Handshake has failed (%s)\n\n", gnutls_strerror (ret)); continue; } printf ("- Handshake was completed\n"); i = 0; while (1) { memset (buffer, 0, BUFSIZE + 1); ret = gnutls_record_recv (session, buffer, BUFSIZE); if (ret == 0) { printf ("\n- Peer has closed the GNUTLS connection\n"); break; } else if (ret < 0) { fprintf (stderr, "*** corrupted data(%d), closing connection\n", ret); break; } else if (ret > 0) { /* echo data back to the client */ string foo=(string)"got "+buffer; cout << foo << endl; gnutls_record_send(session,foo.c_str(),foo.size()); } } gnutls_bye (session, GNUTLS_SHUT_WR); close (sd); gnutls_deinit (session); } close (s); gnutls_srp_free_server_credentials(srpcred); gnutls_global_deinit (); } int main_client() { // GET LOGON INFORMATION LOCALLY printf("CLIENT MODE\n"); char buf[BUFSIZE+1]; // printf("server: "); // if (!fgets(buf,500,stdin)) // return 0; // else // buf[strlen(buf)-1]='\0'; // string server=buf; // printf("username: "); // if (!fgets(buf,500,stdin)) // return 0; // else // buf[strlen(buf)-1]='\0'; // string username=buf; // printf("password: "); // if (!fgets(buf,500,stdin)) // return 0; // else // buf[strlen(buf)-1]='\0'; // string password=buf; string server="rage"; string username="dan"; string password="foo"; printf("%s %s %s\n",server.c_str(),username.c_str(),password.c_str()); int ret; gnutls_session_t session; char buffer[BUFSIZE + 1]; gnutls_srp_client_credentials_t srpcred; // INIT GNUTLS gnutls_global_init(); gnutls_global_init_extra(); gnutls_srp_allocate_client_credentials(&srpcred); gnutls_srp_set_client_credentials(srpcred,username.c_str(),password.c_str()); // SET UP SERVER ADDRESS TO CONNECT TO struct hostent *hp; struct sockaddr_in addr; memset(&addr,0,sizeof(struct sockaddr_in)); addr.sin_family=AF_INET; addr.sin_port=htons(SERVERPORT); hp=gethostbyname(server.c_str()); if (!hp) { printf("couldn't find host\n"); exit(102); } memcpy(&addr.sin_addr,hp->h_addr_list[0],hp->h_length); int s=safe_connect(&addr,10); if (s<0) { printf("couldn't connect!\n"); exit(100); } fcntl(s,F_SETFL,0); // MORE GNUTLS SETUP and handshake gnutls_init (&session, GNUTLS_CLIENT); gnutls_priority_set_direct(session, "NORMAL:+SRP", NULL); gnutls_credentials_set(session,GNUTLS_CRD_SRP,srpcred); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) s); ret = gnutls_handshake (session); if (ret < 0) { fprintf (stderr, "*** Handshake failed\n"); fprintf (stderr,"fatal: %d\n",gnutls_error_is_fatal(ret)); gnutls_perror (ret); exit(999); // FIXME need to be more elegant about this } else { printf ("- Handshake was completed\n"); } while (1) { printf("your message: "); if (!fgets(buf,500,stdin)) return 0; else buf[strlen(buf)-1]='\0'; gnutls_record_send(session,buf,strlen(buf)); // FIXME check success? ret = gnutls_record_recv (session, buffer, BUFSIZE); if (ret == 0) { printf ("- Peer has closed the TLS connection\n"); exit(999); // FIXME } else if (ret < 0) { fprintf (stderr, "*** Error: %s\n", gnutls_strerror (ret)); exit(999); // FIXME } // FIXME print answer } gnutls_bye (session, GNUTLS_SHUT_RDWR); close(s); gnutls_deinit(session); gnutls_srp_free_client_credentials(srpcred); gnutls_global_deinit(); return 0; } void serve() { // get the request. if we're running as an inetd process, this will // include the authentication token, and we'll have to find the // session in our sessionlist. // string str=get_msg(); // find the relevant session // process the request. } string serve_logon(string msg) { // process msg, which should include name/pw, create session, and // return result + authtoken return ""; } void serve_search(string msg) { } voxbo-1.8.5~svn1246/dbmisc/networkdemo/tokenlist.cpp000066400000000000000000000155301153177201300224470ustar00rootroot00000000000000 // tokenlist.cpp // class for tokenization // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "tokenlist.h" tokenlist::tokenlist() { SetSeparator(" \t\n\r"); SetCommentChars("#"); SetTokenChars(""); SetQuoteChars("\"'"); clear(); blank=""; terminalquotes=1; } // the following two functions are a stupid way of adding c++ string // class support. should really just use auto-cast of char ptrs. tokenlist::tokenlist(const string str) { SetSeparator(" \t\n\r"); clear(); ParseLine(str.c_str()); } tokenlist::tokenlist(const string str,const string sep) { SetSeparator(sep); clear(); ParseLine(str.c_str()); } int tokenlist::ParseLine(const string str) { return ParseLine(str.c_str()); } int tokenlist::ParseLine(const char *line) { int i,count; size_t pos; clear(); fullstring=line; poslist.clear(); // list of all token start positions i=count=0; while (line[i]) { string tmp; // skip leading whitespace (or whatever separators we've set) while (line[i] && separator.find(line[i]) != string::npos) i++; // if we're done we're done if (line[i]=='\0') break; // if our character is a token character, grab it and we're done if (tokenchars.find(line[i]) != string::npos) { poslist.push_back(i); tmp += line[i++]; } // otherwise read to the next separator else { poslist.push_back(i); while ((line[i] != '\0') && separator.find(line[i]) == string::npos && tokenchars.find(line[i]) == string::npos) { if ((pos=openquotechars.find(line[i])) != string::npos) { i++; while ((line[i] != '\0') && (line[i]!=closequotechars[pos])) tmp += line[i++]; if (line[i]==closequotechars[pos]) i++; // skip over terminating quote if (terminalquotes) break; } else tmp += line[i++]; } } if (commentchars.find(tmp[0]) != string::npos) break; else { args.push_back(tmp); count++; } } return count; } int tokenlist::Transfer(int argc,char *argv[]) { int i,count; string tmp; clear(); count=0; for (i=0; isize(),c->c_str()); } string tokenlist::MakeString() { string s; if (args.size() == 0) return (string)0; for (CI c=args.begin(); c!= args.end(); c++) { s+=c->c_str(); if ((c+1) != args.end()) s+=" "; } return s; } tokenlist::tokenlist(const tokenlist &a) { *this = a; } tokenlist & tokenlist::operator+(const tokenlist &added) { for (int i=0; i<(int)added.args.size(); i++) Add(added.args[i]); return *this; } string tokenlist::operator[](const int index) { if (index > (int)args.size() - 1 || index < 0) { return blank; } else return (args[index]); } const char * tokenlist::operator()(const int index) const { if (index > (int)args.size() - 1 || index < 0) return blank.c_str(); else return (args[index].c_str()); } tokenlist::operator deque&() { return args; } string tokenlist::Tail(int num) { string ret=fullstring; if (num==(int)poslist.size()) return ""; if (num>0 && num<(int)poslist.size()) { int pos=poslist[num]; if (pos>0 && pos<(int)fullstring.size()) ret=fullstring.substr(pos); } size_t last=ret.find_last_not_of(separator); if (last!=string::npos) ret.erase(last+1); return ret; } void tokenlist::Sort(bool (*cmpfn)(string,string)) { sort(args.begin(),args.end(),cmpfn); } bool length_sorter(const string a,const string b) { if (a.size(). // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #ifndef TOKENLIST_H #define TOKENLIST_H #include #include #include #include #include // argument parsing stuff class tokenlist { deque args; string separator,commentchars,tokenchars; string openquotechars,closequotechars; string blank; string fullstring; vector poslist; int terminalquotes; // if set, mid-token quotes terminate token when closed typedef deque::iterator CI; public: tokenlist(); tokenlist(const tokenlist &a); tokenlist(const char *); tokenlist(const string str); tokenlist(const string str,const string sep); void clear(); int size() const; int ParseLine(const char *line); int ParseLine(const string str); int ParseFirstLine(const string filename); void SetSeparator(const string str); void SetCommentChars(const string str); void SetTokenChars(const string str); void SetQuoteChars(const string str); void TerminalQuotes(int flag); void print(); string Tail(int num=1); int Transfer(int argc,char *argv[]); void Add(const char *str); void Add(const string &str); void AddBack(const char *str); void AddBack(const string &str); void AddFront(const char *str); void AddFront(const string &str); void DeleteFirst(); void DeleteLast(); int Remove(int start, int end); int Truncate(int start, int end); void Sort(bool (*cmpfn)(string ,string )); tokenlist& operator+(const tokenlist &added); string operator[](const int index); const char *operator()(const int index) const; operator deque&(); string MakeString(); }; bool length_sorter(const string a,const string b); bool alpha_sorter(const string a,const string b); #endif // TOKENLIST_H voxbo-1.8.5~svn1246/dbmisc/networkdemo/vbutil.cpp000066400000000000000000000365301153177201300217430ustar00rootroot00000000000000 // voxbolib.cpp // VoxBo library of misc functions // Copyright (c) 1998-2003 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // code contributed by Kosh Banerjee and Thomas King using namespace std; #include "vbutil.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int touch(string fname) { return (utime(fname.c_str(),NULL)); } string xdirname(const string &str) { string res(str); // remove trailing slashes while (res.size() && res[res.size()-1] == '/') res.erase(res.size()-1,1); // remove trailing non-slashes while (res.size() && res[res.size()-1] != '/') res.erase(res.size()-1,1); // remove trailing slashes while (res.size() && res[res.size()-1] == '/') res.erase(res.size()-1,1); if (!res.size()) res="."; return res; } string xfilename(const string &str) { string res(str); // remove trailing slashes while (res.size() && res[res.size()-1] == '/') res.erase(res.size()-1,1); // chop off at last slash if (res.rfind("/") != string::npos) res.erase(0,res.rfind("/")+1); if (!res.size()) res="/"; return res; } string xrootname(const string &str) { string tmp=str; size_t pos=tmp.rfind("."); if (pos != string::npos) tmp.erase(pos,tmp.size()-pos); return tmp; } string xstripwhitespace(const string &str,const string whitespace) { string::size_type first,last; first=str.find_first_not_of(whitespace); last=str.find_last_not_of(whitespace); if (first != string::npos) return str.substr(first,last-first+1); else return ""; } string xsetextension(const string &str,const string newextension) { size_t pos=str.rfind("."); size_t slashpos=str.rfind("/"); if (slashpos!=string::npos && pos!=string::npos && slashpos>pos) pos=string::npos; string newname=str; if (!newextension.size()) { if (pos==string::npos) return newname; else { newname.erase(pos,str.size()-pos); return newname; } } if (pos==string::npos) return str+(string)"."+newextension; newname.replace(pos,str.size()-pos,(string)"."+newextension); return newname; } string xgetextension(const string &str) { size_t pos=str.rfind("."); if (pos==string::npos) return (string)""; pos++; return str.substr(pos,str.size()-pos); } void parentify(char *fname,int n) { char *slash; for(int i=0; i &mymap) { size_t pos; int cnt=0; map::iterator myiter; for (myiter = mymap.begin(); myiter != mymap.end(); ++myiter) { string tag = string("$(") + myiter->first + ")"; while ((pos = str.find(tag)) != string::npos) { str.replace(pos,tag.size(),myiter->second); cnt++; } } return (cnt); } int fill_vars(string &str,tokenlist &args) { size_t pos; tokenlist newvars; tokenlist var; var.SetSeparator("="); int cnt=0,dupfound,i,j; string v0,v1; // FIXME BROKEN? first go through, sort, and eliminate duplicates while (0) { // for (i=args.size()-1; i>=0; i--) { if (newvars.size()==0) { newvars.Add(args[i]); continue; } v0=args[i]; dupfound=0; for (j=0; j=0; i--) { var.ParseLine(newvars[i]); if (var.size()<1) continue; while ((pos=str.find((string)"$"+var[0])) != string::npos) { str.replace(pos,var[0].size()+1,var.Tail()); cnt++; } } return (cnt); } // varname() returns the variable name in an env var (aaa=foo returns "aaa") string varname(const string &a) { tokenlist aa; aa.SetSeparator("="); aa.ParseLine(a); return aa[0]; } // overloaded wrapper for the above void fill_vars(string &str,char **myenv) { // char **ee=myenv; int i=0; tokenlist envlist; while (myenv[i]) envlist.Add(myenv[i++]); fill_vars(str,envlist); } void replace_string(string &target,const string &s1,const string &s2) { size_t pos; while ((pos=target.find(s1)) != string::npos) target.replace(pos,s1.size(),s2); } string vb_getchar(const string &prompt) { termios tsave,tnew; tcgetattr(0,&tsave); tcgetattr(0,&tnew); tnew.c_lflag&=~(ICANON|ECHO); tcsetattr(0,TCSADRAIN,&tnew); string str; cout << prompt << flush; str=cin.get(); tcsetattr(0,TCSADRAIN,&tsave); return str; } int copyfile(string infile,string outfile) { const int BUFSIZE=4096; ifstream inf; ofstream outf; char buf[BUFSIZE]; struct stat sti,sto; int err,erri,erro; erri=stat(infile.c_str(),&sti); erro=stat(outfile.c_str(),&sto); if (erri) return 101; if (!erro) { if (sti.st_dev == sto.st_dev && sti.st_ino == sto.st_ino) return 0; // no error! } inf.open(infile.c_str()); if (!inf) return 102; outf.open(outfile.c_str()); if (!outf) { inf.close(); return 103; } while (inf.good() && outf.good()) { inf.read(buf,BUFSIZE); outf.write(buf,inf.gcount()); } err=0; if (!inf.eof()) err=104; if (!outf.good()) err=105; inf.close(); outf.close(); return err; // no error! } string textnumberlist(const vectornums) { string ret; if (!(nums.size())) return ""; int rangestart=nums[0]; int rangeend=nums[0]; for (int i=1; i<(int)nums.size(); i++) { if (nums[i]-rangeend !=1) { if (ret.size())ret+=","; if (rangeend==rangestart) ret+=strnum(rangestart); else ret+=strnum(rangestart)+"-"+strnum(rangeend); rangestart=rangeend=nums[i]; } else rangeend=nums[i]; } if (ret.size())ret+=","; if (rangeend==rangestart) ret+=strnum(rangestart); else ret+=strnum(rangestart)+"-"+strnum(rangeend); return ret; } vector numberlist(const string &str) { vector numbers; int thisnum,endpoint; tokenlist ranges; ranges.SetTokenChars(",-:"); ranges.ParseLine(str); for (int i=0; i>5; } } return foo; } unsigned long VBRandom() { struct stat st; int fd; unsigned long buf; if (stat("/dev/urandom",&st)) return 0; fd=open("/dev/urandom",O_RDONLY); if (fd == -1) return 0; read(fd,&buf,sizeof(unsigned long)); close(fd); return buf; } long strtol(const string &str) { return strtol(str.c_str(),NULL,10); } double strtod(const string &str) { return (strtod(str.c_str(),NULL)); } string strnum(int d,int p) { char foo[STRINGLEN]; char format[STRINGLEN]; sprintf(format,"%%0%dd",p); sprintf(foo,format,d); string tmp=foo; return tmp; } string strnum(float d) { char foo[STRINGLEN]; sprintf(foo,"%g",d); string tmp=foo; return tmp; } string strnum(double d) { char foo[STRINGLEN]; sprintf(foo,"%g",d); string tmp=foo; return tmp; } void stripchars(char *str,const char *chars) { for (int i=0; i<(int)strlen(str); i++) if (strchr(chars,str[i])) str[i]='\0'; } // long // memsize_core() // { // return(sysconf(_SC_PAGESIZE)*sysconf(_SC_PHYS_PAGES)/(1024*1024)); // } // long // memsize_avcore() // { // return(sysconf(_SC_PAGESIZE)*sysconf(_SC_AVPHYS_PAGES)/(1024*1024)); // } string timedate() { string tstr,dstr; maketimedate(tstr,dstr); return (dstr+(string)"_"+tstr); } void maketimedate(string &t,string &d) { char timestr[STRINGLEN],datestr[STRINGLEN]; struct tm *mytm; time_t mytime; tzset(); // make sure all times are timezone corrected mytime = time(NULL); mytm = localtime(&mytime); strftime(timestr,STRINGLEN,"%H:%M:%S",mytm); strftime(datestr,STRINGLEN,"%Y_%m_%d",mytm); t=timestr; d=datestr; } int appendline(string fname,string str) { FILE *fp = fopen(fname.c_str(),"a"); if (!fp) return(101); fprintf(fp,"%s\n",xstripwhitespace(str).c_str()); fclose(fp); return (0); // no error! } string uniquename(string prefix) { static int index=100; if (prefix.size()==0) { char hname[STRINGLEN]; if (gethostname(hname,STRINGLEN-1)) strcpy(hname,"nohost"); hname[STRINGLEN-1]='\0'; prefix=hname; } string name=prefix+"_"+strnum(getpid())+"_"+strnum(index); index++; return name; } string prettysize(long size) { string ret=""; char ps[STRINGLEN]; sprintf(ps,"%ld",size); float dsize=(float)size/1024.0; if (dsize>1024) { dsize/=1024.0; sprintf(ps,"%.1fMB",dsize); } if (dsize>1024) { dsize/=1024.0; sprintf(ps,"%.1fGB",dsize); } if (dsize>1024) { dsize/=1024.0; sprintf(ps,"%.1fTB",dsize); } return (string)ps; } struct timeval operator-(struct timeval &tv1,struct timeval &tv2) { struct timeval ret; ret.tv_sec=tv1.tv_sec-tv2.tv_sec; ret.tv_usec=tv1.tv_usec-tv2.tv_usec; if (ret.tv_usec<0) { ret.tv_sec--; ret.tv_usec+=1000000; } return ret; } struct timeval operator+(struct timeval &tv1,struct timeval &tv2) { timeval ret; ret.tv_sec=tv1.tv_sec+tv2.tv_sec; ret.tv_usec=tv1.tv_usec+tv2.tv_usec; if (ret.tv_usec>1000000) { ret.tv_sec++; ret.tv_usec-=1000000; } return ret; } bool operator<(struct timeval &tv1,struct timeval &tv2) { if (tv1.tv_sec(struct timeval &tv1,struct timeval &tv2) { if (tv1.tv_sec>tv2.tv_sec) return 1; if (tv1.tv_sec==tv2.tv_sec && tv1.tv_usec>tv2.tv_usec) return 1; return 0; } voxbo-1.8.5~svn1246/dbmisc/networkdemo/vbutil.h000066400000000000000000000124061153177201300214040ustar00rootroot00000000000000 // vbutil.h // prototypes, etc. for use by voxbolib // Copyright (c) 1998-2005 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // substantial code merged in from Kosh Banerjee using namespace std; #ifndef VBUTIL_H #define VBUTIL_H #include #include #include #include #include #include #include // For getopt(). #include // For definition of struct winsize. #include // For definition of struct winsize. #include #include #include "tokenlist.h" #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef STRINGLEN #define STRINGLEN 1024 #endif typedef unsigned long ulong; enum VB_datatype {vb_byte,vb_short,vb_long,vb_float,vb_double}; enum VB_byteorder{ENDIAN_LITTLE=0,ENDIAN_BIG=1}; enum VB_imagetype {vb_1d,vb_2d,vb_3d,vb_4d,vb_other}; //enum VB_loglevel {vb_never,vb_onerror,vb_always}; // flags for things to do with time series data static const long MEANSCALE= 1<<0; static const long DETREND= 1<<1; static const long EXCLUDEERROR= 1<<2; // some random constants static const double PI=3.14159265358979; static const double TINY=0.05; // used in resampling // util.cpp void dbasename(const char *str,char *res); void ddirname(const char *str,char *tmp); string xfilename(const string &str); string xdirname(const string &str); string xrootname(const string &str); string xstripwhitespace(const string &str,const string whitespace="\t\n "); string xsetextension(const string &str,const string newextension); string xgetextension(const string &str); int createfullpath(const string &pathname); ino_t vb_direxists(string dirname); ino_t vb_fileexists(string dirname); void deletesequence(int seqnum); int touch(string fname); void parentify(char *str,int n); void lockfile(FILE *fp,short locktype,int pos=0,int len=1); void unlockfile(FILE *fp,int pos=0,int len=1); FILE *lockfiledir(char *fname); void unlockfiledir(FILE *fp); bool equali(const string &a,const string &b); void glob_transfer(tokenlist &toks,glob_t &gb); bool dancmp(const char *a,const char *b); string vb_toupper(const string &str); string vb_tolower(const string &str); VB_datatype str2datatype(string str); void guessorigin(int &d1,int &d2,int &d3); int fill_vars2(string &str,tokenlist &vars); int fill_vars2(string &str,map &vars); void fill_vars2(string &str,char **myenv); int fill_vars(string &str,tokenlist &args); void fill_vars(string &str,char **myenv); void replace_string(string &target,const string &s1,const string &s2); string varname(const string &a); string vb_getchar(const string &prompt); int copyfile(string in,string out); void GetElapsedTime(long start,long end,int &hrs,int &mins,int &secs); string textnumberlist(const vectornums); vector numberlist(const string &str); string VBRandom_filename(); unsigned long VBRandom(); long strtol(const string &str); double strtod(const string &str); template string strnum(T d) { char foo[STRINGLEN]; sprintf(foo,"%ld",(long)d); return (string)foo; } string strnum(int d,int p); string strnum(float d); string strnum(double d); struct timeval operator-(struct timeval &tv1,struct timeval &tv2); struct timeval operator+(struct timeval &tv1,struct timeval &tv2); bool operator<(struct timeval &tv1,struct timeval &tv2); bool operator>(struct timeval &tv1,struct timeval &tv2); void stripchars(char *str,const char *chars); // long memsize_avcore(); // long memsize_core(); void maketimedate(string &time,string &date); string timedate(); int appendline(string fname,string str); string uniquename(string prefix); string prettysize(long size); // endian.cpp void swapn(unsigned char *uc,int dsize,int len=1); void swap2(unsigned char *uc,int len=1); void swap(short *sh,int len=1); void swap(unsigned short *sh,int len=1); void swap(long *lng,int len=1); void swap(unsigned long *lng,int len=1); void swap(int *lng,int len=1); void swap(unsigned int *lng,int len=1); void swap(float *flt,int len=1); void swap(double *dbl,int len=1); VB_byteorder my_endian(); // connect.cpp int safe_recv(int sock,char *buf,int len,float secs); int safe_send(int sock,char *buf,int len,float secs); int safe_connect(struct sockaddr_un *addr,float secs); int safe_connect(struct sockaddr_in *addr,float secs); int safe_connect(struct sockaddr *addr,float secs); int send_file(int s,string fname); int receive_file(int s,string fname,int filesize); // vbreports.cpp void vb_buildindex(); #endif // VBUTIL_H voxbo-1.8.5~svn1246/dbmisc/score.conf000066400000000000000000000061731153177201300173560ustar00rootroot00000000000000# This is a plain text configuration file for scores (aka. attributes) # in patient dababase. Each field is separated by commas. # Any field that includes comma character have to be enclosed by "". # Blank lines are ignored. Any lines that start with "#" are considered comments. # From left to right, each field corresponds to: # score_name, score_dtype, score_table, score_desc, score_flags # default scores in "identifying" srcID, long, identifying, record no. in FMP7, first_name, string, identifying, , middle_name, string, identifying, , last_name, string, identifying, , DOB, date, identifying, date of birth, address1, string, identifying, , address2, string, identifying, , phone1, string, identifying, , phone2, string, identifying, , # default scores in "demographics" MRN, string, demographics, UPHS medical record #, gender, string, demographics, , handedness, string, demographics, , education, int, demographics, education in number of years, degree, string, demographics, , occupation, string, demographics, , education, string, demographics, , degree, string, demographics, , english_first, bool, demographics, , languages, string, demographics, , ethnic_group, string, demographics, , Ethnic Goup (3/02), string, demographics, , racial_group, string, demographics, , racial_group_2, string, demographics, , exclusionary, string, demographics, , Diagnosis, string, demographics, , Vision Difficulties, string, demographics, , Hearing Difficulties, string, demographics, , Mobility, string, demographics, , Other Health Problems, string, demographics, , Current Medications, string, demographics, , Past Psychoactive Medications, string, demographics, , History of Learning Disabilities, string, demographics, , Date of History, string, demographics, , # default scores in "radiology" hemiparesis, string, radiology, , mri_possible, bool, radiology, , mri_reason, string, radiology, , subcortical, string, radiology, , visual_field, string, radiology, , neglect, string, radiology, , extinction, string, radiology, , aphasia?, string, radiology, , radiology_notes, string, radiology, , # default scores in "medical" Neuroradiological Report, string, medical, , Scheduled Date for Behavioral Testing, string, medical, , # default scores in "test" Screening Notes, string, test, , Vision Difficulties, string, test, , Hearing Difficulties, string, test, , Mobility, string, test, , "Notes on Vision, Hearing, Mobility", string, test, , Current Medications, string, test, , Past Psychoactive Medications, string, test, , Other Health Problems, string, test, , Health Problems Notes, string, test, , Previous Hospitalizations/Operations, string, test, , Family History of Serious Illness/Neuro Disease, string, test, , History of Learning Disabilities, string, test, , Learning Disabilities--Notes, string, test, , Head Injuries Accidents LOC, string, test, , Head Injury Notes, string, test, , Physical/Psychological Changes, string, test, , Explain All that are Checked, string, test, , Behavioral Changes, string, test, , Explain All that are Checked 2, string, test, , Neurological History, string, test, , voxbo-1.8.5~svn1246/dbmisc/screen_field.txt000066400000000000000000000072741153177201300205620ustar00rootroot00000000000000MRN, VIQ No. Corr. Scaled Span A1 A2 A3 A4 A5 A6 (retention) A7 (delay) Recog A1-A5 Tot "F" Animals No Cues Sem Cues Phon Cues Y/N 2.5 5.0 10.0 B1 B2 B3 B4 B5 B6 Recog B7 Delay Recall B8 Delay Recog B9 Immed Rep B10 Copy + B9 Categories Persev Err Loss of Set Part B BDI Hand Preference Left Eye Right Eye LO Score LO Categ Data Entry Date Notes Behavioral Testing Date Gender Age Handedness Date of History Date of History Copy Behavioral Testing Date Copy Handedness Copy Gender Copy Total Flags Record No. Observation of Pt Pt's Condition Count Backward (20) Recite Backward (Months) Speech Fluency Naming (High Freq) Naming (Low Freq) Naming (Total) Repetition Comprehension Reading Exception Words Regular Words Non-Words Pass/Fail Praxis Buccofacial Command Buccofacial Imitation Limb Imitation Limb Command List Attempts List Recall List Cues List Multiple Choice Digit Span Forward Write Name Write Sentence Draw Clock Copy Block Figure Copy Ramparts Copy 3 Squiggles Bisect Line Error Write name error Write sent error Draw clock error Copy block fig error Copy ramparts error Copy squiggles error Bisection error Oral Trail Written Trail-Part B Animal Fluency "F" Fluency "F" Fluency Repetitions "F" Fluency Rule Violations Animal Fluency Rule Violations Animal Fluency Repetitions Oral Trail Error Written Trail Error Referring Hospital Count Backward P/F Months Backward P/F Rating Scale Rating1 Rating2 Rating3 Rating4 Rating5 Rating6 Rating7 Rating8 Rating9 Rating10 Rating11 Rating12 Rating13 Rating14 Rating15 Rating16 Rating17 Rating18 Rating19 Rating20 Rating21 Rating22 Rating23 Rating24 Rating25 Rating26 Rating27 Duration of Testing (hours) Tests Administered Pt Cooperative Family Cooperative Additional Comments Name of Examiner Alert1 Hand Classification Pt Last Name Pt First Name Explanation of Ratings Albert Line Cancellation Line Canc Error Age at Screening Notes: Counting/Months Screening Notes MRI Screening MRI checklist Praxis Notes Body-Part-As-Object Errors Buccofacial Command2 Buccofacial Imitation2 Limb Imitation2 Limb Command2 Pt Rec'd Feedback for BPO Errors WAIS-R, Multiple Choice Avg Age Stdev Age Avg VIQ Stdev VIQ Avg Counting Stdev Counting Stdev Months Avg Months Avg Naming Stdev Naming Avg Digit Span Stdev Digit Span Avg Animal Fluency Stdev Animal Fluency Avg F Fluency Stdev F Fluency Total Pts in Subset DMS-Attention DMS-Initiation/Perseveration DMS-Construction DMS-Conceptualization DMS-Memory DMS-Total DMS-Att-%tile DMS-Init/Per-%tile DMS-Const-%tile DMS-Concep-%tile DMS-Mem-%tile DMS-Tot-%tile A1.Forward Digit Span A2.Backward Digit Span B.Two Successive Commands C.Single Command D.Imitation AD.Counting Distraction 1 AE.Counting Distraction 2 AH.Vebal Recognition--Presentation AJ.Visual Matching E.Complex Verbal Initiation/Perseveration F.SimpleInitiation/Perseveration G.Consonant Perseveration H.Vowel Perseveration I.Double Alternating Movements J.Double Alternating Movements K.Alternate Tapping L.Graphomotor Design 1 M.Graphomotor Design 2 N.Graphomotor Design 3 O.Graphomotor Design 4 P.Construction Design 1 Q.Construction Design 2 R.Construction Design 3 S.Construction Design 4 T.Construction Design 5 U.Construction Design 6 V.Identities and Oddities W.Similarities X.Priming Inductive Reasoning Y.Differences Z.Similarties--Multiple Choice AA.Verbal Recall--Sentence Reading AB.Verbal Recall--Sentence Initiation AC.Orientation AF.Verbal Recall--Reading AG.Verbal Recall--Initiation AI.Verbal Recognition AK.Visual Memory Screening Exam Type AMSS Att AMSS Init/Pers AMSS Const AMSS Concept AMSS Memory AMSS Total AEMSS Total Misses Left Misses Right Misses Center Misses BDI-II Greyscales Task Foveated Reaching Non-Foveated Reaching LE1 LE2 LE3 LE4 RE1 RE2 RE3 RE4 Visual Fields viewexclude voxbo-1.8.5~svn1246/dbmisc/tables.ods000066400000000000000000000475121153177201300173570ustar00rootroot00000000000000PKǬd9…l9Š..mimetypeapplication/vnd.oasis.opendocument.spreadsheetPKǬd9Configurations2/statusbar/PKǬd9'Configurations2/accelerator/current.xmlPKPKǬd9Configurations2/floater/PKǬd9Configurations2/popupmenu/PKǬd9Configurations2/progressbar/PKǬd9Configurations2/menubar/PKǬd9Configurations2/toolbar/PKǬd9Configurations2/images/Bitmaps/PKǬd9 content.xmlí}ÝvÛ¸’îýy ÷:Yé5–lÉ?±Îrü“x¶ÿ¶íNOŸYgeA$$¢Cl´­¾Úï0·3/·Ÿä¤$ËŽd)StõEÇ¢¨ðU¡ªP(þöñ> Ñ-’röa¥Õ\_A„yܧ¬÷aå×›ãÆÎÊÇ_þ×ßx·K=²çs/‰S 3¥ÿEú×Lîeß~XIÛãXR¹ÇpDäžòöxLØðW{ãoï¥meO¤ê‡¹ž¾<þkEîUÞ›wýwò·œ¾<þk_໼?6ïjPÇÞåy|/ÃF—kÔ£+ú¤÷!eß?¬JÅ{kkwwwÍ»&½µÖîîîZúí¨ÃÞè½8aú–ï­‘˜ÆäZ«ÙZ¾…óöϼ;Þ%–D"rCƒþ«± R¿¢‡k3¡ñß<’¯Û^néºíMÙ °È-géËEeÃÏ/*þøo#¬‚)üÝY;Ó_¦ÿ;;}+åm˼û*OÐ8÷0³·ÇÏ9uÕü ›ìiwÛëë›kÙç±·ïž}ýNPEÄØëÞ³¯{8ôFˆóhhú½Öš~£AnÈ&‘BNùA{-ûzô²ô§’þ³Ók/ ~x™Î~¹A™T˜= # ¦ŽtkM˜ 5¦›_ùjnµG­ø]f9Ú+¿ ÍD&rmô «ÍE£‹=Òð‰Ê_þ–M÷Ñc”}6ÿ°rJµîHç0:㌯ ='‡¯F4ìXyƒc.ß?y/{¸‚‘6ï7z„AµäDÜ'‚=z%¦ÊÓ“«K²ö|ÇöÅá„î ŸOoXÞQ)'µ{‹õoµ¢™ÕôØX¯1“y01ïåÀdî®’?ð×~>x¾kOÞËÓµ¾T$* oyúµ°>Ýà€íðCwF_ÌÛúÚ´Y7xŽ¥RÔk¤tFÓ1ýÿ£¾z¼5jlÐËÔ Ò&2L"¶2üåøÃF,´ÖЉº|¯#þÞè­@5AÓôâàõ;êó¶ÑÜXߨ¢,ÀXžë\{Qk5·¶×ÛvÛX rÛ;-»Îm.¹ÍÍm»Îm-­;­]»Îm/®símK®¾[TßÚÍVkÇ®s;‹êÜfsgskîs» äêú®%[[ë‹êÝzsgckÓ²w 3ëÍí-kìf#4v[Û–b×Z˜‘нÛygËÙ…Y ÍÙ–­ k-ÌL¬k3±miÃZ ³ëÍÍ­–mïf)Ö›ï¬çìÂL…æ¬þϲw ³ëÍv{Ã’³íÚŠö;KŸ¸½@[±³Û¶]N,p=±¾»k‹ÝmÅî»-ÛÞ-ÌVl6×ßYºží…™ŠvsscǺ…™Šf»µm;)f*ZÍw»›¶½[àªbwýmï¸¬Ø¶Žžl,ÐT¼ÛÙ°\go,ÌThelÛYàªb«µa©î6f)4tÖÑ®*6wÚï,{·ÀUÅæf˶w Œ>½kÛNŠ…YŠm­O¶­z'¦²¿{Ò3ýd¼[ÙWæa@h/P†q­,Þú|—IEš½Òø±Ãç­õõ•Ç/ òs ¡~ûÌ&ÓŒ. Gœ1&(ý0mü¦­8šnGMÞâͯeÈ4Ë[rä¥_ß „ªÃCߦßÓlò|ýžØ«ñÑd_4°¤˜MÿÚd¼„äÞ~TÓly¾Q Þ0ù?¾t¾!3.ô„·éô4¿ÀNÛâ<Íî/çéÂ5ý…‘xÙójšO±h^-pNM[Ò0äµçÚ¶X-VCÙ‹ÀÔí¯T§M·Ê±•ÓñzñÈ'f>ÍÒ#M›C›ÿöçÿýáÍŸ Wï..ÏþöÇqØÔÅä¿ÈH†;Xfƒh`ßDJ=°~Ldó eÏ|†:ßÌQüÑ–§¸âöXCòD˜ôä.½Ò$&xä&¹ˆ£ŽážÀqð„3D?¬H…Mž~aÑ£¬’®ñU­Mdêà¢ý™—QïS·-‡?QÌb{ß{‚'Ì7+N.>¬üäéÿºÝ^ä .Ð@LÝù,Ñ(.@Íç)•!P/+.7?š)Ý¿v~Ö¦f"¾èp¿ÿNë%¿/BÔ/Ë–ÒéÿËêlœ]JB_® žó6]ÏgcA´ýXv²ˆÌÈE4Ö¡.÷9|uðej=}"QÉÖë#»1Ö­AlkBOÒtÊA, ¸LĽCZôÚÓÛ(˜ÞfÁô¶†ô²¨ÆàUÙÈì9ñ?¬´ÖÍ}9N¥7TOh ~7 ‰E>i[ÓeÔã0! ãqCËkϼlŽ-Å¿ü„T@¹§R{-Ñ?A÷{ý½¿Õ³-3=ýZª¤#Ñ=ÂÌGýUÔé£Áã,M·ð·µAú'ÝšÐÑ™ ho¤3þ eCÓ qO"ʼ0ñ méy¬'5ýËÐ[EŒÜ5Ìéṁ[=†€úú }Ê+…Äcúú½qâíI@ÍîÐfÁ¬™0_Lˆ.ÇÌÛ.p»´e|óÍÂÚ#Ùí-ªÉTü il†µ·~Ô9dïÝöîⵂžØLÑnßZÇå mT«ÑI åh'ûW¦Øª›Ö_”{Rx'‡…s%ä%°Z _›Ì¦¶/èøìò]áMÔ•Ë]*¤úf¯ësM@Q´ï’OÕÖ•Wõý³–‚Y!†yµ$¬:¼øT8“´G[<çG 0ÔÍò±C… ÀÖåäó`¿¤3rI8ÕNUSqÀ)~F¥d«¢Ør­@J ÕU½ÅOC`oIìÝbÑÆ\Ѷˆ§»õÔ³Œ€•æÉQûe1Ú;»:¯„å³™s¿^~¹Fñ©‡C4ÈüT•)^I=ûˆå=Â|"*ÁuðwžcT€5£|¦½S`Vå™EüÄÃö»œBé9È+ëµL£*‹!×®½€øIH|”È»\ O$À·T³2D7DÚÖUj£XÆt®…4ØèÙ$IwÏÁƒ¨ªêK9yËÄ-È\*vA`åY”Ú'¤5`¦WÑ`Š­"`^å™I€ËÄ-Hþ[N¾AŠôrñë §` Vq~] rKy"Ñ.cªpHÿÊtâÚE<¸¼ ØW]ö§v¡±Ôèk"R~ž„¡©¶–F„Mž4Á²•ˆ€“'d·/+ë&ò«ÑÓWm¶iWÅG'ìD˜{Ñö=/­:,ÑéÅpm ¸Öç²â¼º úÒlp®e ïá–ôA€Ôõª2ãŽîãS†öM/¬D³xß ¤ÛV—mcI0Ǫάçæ‚‚QÕe\º¢Ú28ÉúRìšÝâ $çH—‘廘kDëT¥Ù0bÏþkNÊÂǾL¾TŠR)÷ÄÙ­.@å$¢›khk“¿Ÿâ”lõWõ—ñcOÒ¿ŠŸß”)Ò+ã¶ÝYså„—t¨‡¢¨h^´^–!/é2Œþ77ú%«”Çôõ{ãÄ··6·Ö«áß9·8þäÝ!É´UÃ8¹2¡; 0Š5WÕ‡•.%Ñ]0¾ËE$ͱ€h'ŠGšÅ^£Ë½D_|Ça¿ákQè±FÄ}2üú©FLÇ6¡'ßöÄ']œ„*E¦1þÎaö…Íw%ÐÜ)æn 4[ëem•A´]Ñ2ˆn–At« ¢eL§Vó©UÆ„j•1£ÚęöS+5!|²é<ëŠö(~B•R?ÚC’ú½5'ÆÈèüþÏ«ˆ§isA–Œ;¥ÍÍ‚ckkñ®ÔO¨“P ¼vSkª=E/L4Ù‹è-þŽ‘ ¸PÙDŒΞ?,¸ôcmfW‘9ハº!ÇúCz!ì*2 ×U¤h4øá Ù.“ˆ 5i©ÔÝAò»*ïYg±íà¶µ·¶Kñ)²‘+¸jž"óÄL_XT‹Á’)ÍäëÆâçÑøEGßx µ‡LµˆÂ‰Æz¾›k~PÚï¢í@Ùð…Ê›;’´a=5A!^0h/°7Q:hç\!Ρ_ÙwÆïz{Â|zKýD/Ú‘V¤H¤ÅŒg“õª¾åU] ÇsáÖØ–ëÅo®—£µ¹T5VÛeðáSˆ½ï«&/eU¦3]t!h}yET~¿Ô¬~?Güö%Å̘¾KìQý6:‘¡¹¬ÝrŸäUb7”6€j¶˜EDPOKšñ2Û±ü®ÿ<Çæp+`˜×ç¤f6pÈSƒð•ºáè[f»½JÐÒsËËS©—Ζâ5cýÚÈs^~—¹T<±#k™© );ãêFÏ„RAB_ð¦?%«çP?÷¸TÓemêåu³ù:œ¸€Ûìå,`ô,ñ3.ˆ9¢g'#H7€å Öêéø¢µ=÷êP8×BËHÔYh)ŽdZ±ï¾©DR8\!é*”Ñœž“YÚ ¨Ý?¹žYšÝ:Ó)__@ÏϱøŠ‚ôL-AÂìþŠ€¿WKþL¨þž0ÕP58â¶Èb,Tƒw¬\Ǩ µ¬Aa*'%\?r­ÿNÖNX ÏòVÜWÖoz`BĔϼr„MK/ÒÉÀ*º¨Zýðú-[oæ-heúSÚRÕ,¿4pûŒ$¢/‹­uXC˜¾žBy4Ö>ÓþIöÇKë&‰¸@WDPERéYâ§ØKC—¡aó…ÁÞè,ëçkåJ}–ÄÒKÌ|0÷fì˜mýD€{5Øú,×ðùfݬ0LÒÁ{ãÔG YùQósW—F +Ðí9TÀ”Ca1ÄÁª–*»Uâ|…`íAp!TÒóþ'•¶|¨gˆ²§rí—¿ÿòÌ fŠv¸o}£÷«ƒò:2¥\¾)Ièvý«ƒìŒ˜kÈ!ö7{1­ƒ¯.¥¦eZ²]n+‡yÄæ`ZhŠ\ÏÏÀã"2GÔhéN˜"LRsòyâWاé|DçÄ\B k¶G–DÖ"‹½Üõu?æ>LÂ|HPåò!úRQ:\ úê°úÒ÷ϼˆ: )W®f”+ÁÌñ©Ù®¤‚äÃ)‰U" 3«FS‰„…óLâ‡$ꓲâï-®#Vž0qP]ÑMÀ§šIüW&cb¢Xu¨}W2RyÛÕ³Äÿ‘i´•ùQm 27ÉŽ”©Ñ ={˜ÌT爞£Ý¡¡9ºd[¼áµÁäÓn×ZÛU¤€D4ÆBC%Ë9åÌjQi±t˜ê¡¼K‡©&¼tœj¤ÆÍÓo’ÜŽQ=Ê—O]ê+Ü€{Q<‰@5(ãQ6H—RŽ< )HkzÊ¡Q…€læä;ÁÊ#XPšID)W‘ ­›(è à‚S‡h_èGõÙ^t<Š–&IJÀ—WÕs øÍƒ_z×cr s67ýOXÒ À+'ý*¼è7Ño4 k”U\bÇ‚3ë‚Ò¯¨K,(¤ò”$"QÌk -© Ï£õÜ_#T7qT£„âÕ%ë•çY L™öèëS®°¼0<õ;-@*‡»®7Ÿ1ë…5::Y¶ïÙ×Ê1p±lÝv€Ì2pOí=y3geÖÁ+D€.oœäÎþq"ÑAÑO`5ÛªR•hÑ‚(~Ù"‚tô» V9 ƒ˜³NïÉQ*ñõð¨™z*Qº‡ìÉTxK€Ô,úŸCÞѾ¥ö¨!üÙô ¨"(ÂJ¯¼K t¨9¬~6;­?X+lVôG+kÀÍÎt ܰrÒ¿ÖŸ±ÒÔc™˜¬¹ì†SÀmfæ¹É 6åK3ä`‘4“þÑ= fGÿ€k/ #‘~…½ñsÒè0À)÷©O?NBñ䱓I‡²ÌDz\(Ûί²”H"$IDù-œÞÎ#eýð–b†Ž©”u*´Xê ™`Í¢ÿ…Ʊ¦ÅOÌå|)sø ʵõÙ;y& ¶„2hö<W,ôð˜â‚‚lå H|k\.ê7Ëã;`6€aA˜ô#˜¹ÀÂR¿ ‚•C×§8­¥*0ËðÀEÍI¬øðjN”þã}XÙØÈÆ»ÇŸ<";¤˜Â¨í8“avÕWú|eÖ ·†c=Võa¥‹CIôpt¹ˆ$2ÿßɹ~½ödàé0'ôÄãï†=ñI'¡JAjGwz ›Mýó¿÷qÿ_ÿüŸtâ ?¿Á1—ïeÊIýp¤ŽD\OÞEÖc\ôÑ@¯1®RUõñãØ”y«§QéÅ!ò“84E¾´›EòIÄ{ÇõäÏÀ§Rø$É­)¬=äOWð©@;”$ŠÍή™&¸£WUÈ3Ÿš+4Â="WÓ9exfXJ™&¾æškl85“S#F„¸Ïƒ9êFñ¬×$w¥+ÍÑì5©õÞi¶„±¶FXx¦ù>åæ‘kIlô`êèHí8«¯ ­\}|–©d~6¿Ðåk”‘»‚Úk­çeúë…5èS©=êz)žS›·TÃê~™£Uótq°é /t€Ý÷œöÚlm–^ØÜq× í¼za;ר÷ýH¯Ÿ\>mq’î´0·Åow_\þ^8ÑH{ffNØž y‚x„éõñˆÙzMPlus·:"k÷Ì­>Õ«”g/¤Ì~k"áçEïw¬WMÊÐჩBoiW»ûýÖÏ zóÎ>/¡ð½Ë)|1§LEF©b»ßÕ@àf1Ðuˆc&t ¦½D›hˆˆÔÜ"%8ö'§BäI)Â|G³þúDižàcÁœ;HÝÂ5_è˜PO¡k…•ÛI¨ªkŽëË£ƒ“ýÓj¸T¢4o½é©÷ÒÍé8SÚÃLŽÇÙ9ËDÌ)x‰f-´ß«åâÚIêrmÜ<¤‘XwH«T/=ïgéiÊï¢*¨­pÖ5äS)]˜¥|ÊAÎ'lŸS†¸þgAó!³j”nUk±3“ë“ë䪺ü•âú9«Är¶ gÉ[…œ¿¡¼ œÀ:J\)¯BKÇ! O؉[iðW¹\¬PŠÁê‹"Ó«‹ßjµËLòf—°%[=å¡=ŽŽ i£{QFÄ*þÕjl´ë¨E*åù˜ù¡^Q™$g’í+páËUÄYØG†i2º‘= ÞÑÄ ¾õ¡BÙDG÷^˜˜¯ŽW[T]ò–+ÜY딢£{m¶¼b’^AÐæ#l ™§³éqE­6Uñ;†\“ª—"\pLÃöþ+æxågDiÇmgkÀ>ÇÔ|.”+òg¢E”y$¥ÖKóã_!OäãYù¸ 8#é…‹u”’J-ð9kHOÂÐÌ„ÊT€UºÝßåaÈïIœm¥šƒÎ1–ŽO–ÂMýœ Ïy³öñ“ÏçWGÕÁ:@3¥cc,ˆt»¸ò1Ê©»¾pé|ŸsÕµÕ¢üª` —JHô2ÍÄñÑEÇÔ–ÅÚ=Ÿ2¨>xLIèC B;¢Õ©A˜ƒæé—/&›õÊüÃÂ~…¶ [ù$Z 'NBµâ¦¿gNÉÍ‚ƒ%û¾O#’Vÿ”ž ±ù$Íöî xì¨*̪»gŸ"Q_®~cñÈðÈ ‘›ÕH.©ò‚Ôg9»:ñGסþ‰DoÏ/·8ÂZ(ÑÍ`¸ògô¶ý3 \&€®ÕH®MæLz± H¦3v€›nfg¥VNÍqÿ+P‹E€Zdh22 ‡†ä Žâ÷hðiµvwvA:Ë€µV?5«Ôö€\Î@g5×e½›ÙàvÁqËé B¾™/ ^M}ÒÏJ¨~˯ˆ–O˜®Ø«¤±^He€Ž©Ðzé³^‚{–×{‚@A|  ç‘'0ê¡Ï‚'1ÑÂ{LRø¿õ üßxhòÉÝÒ¦‡ô¸ eA-Bß C± \˜صu§ójóÛÆd½5c²«"]¸Ho-W/¡#?æ[Þ™ ¢Tñž=ð• /XÃgD‚ã¿ønàWS6Ð!5ï&¡¢–%Ϋ(RU jÕ)ì9‹g °`™àHÜ¡!ÁÁ™.8<"è2àlù÷ý«$"$”$ÛÞ§]sL4ý{ù¥åŒ§ ¶ß@L+»«A6rê‘ås’.°OyÈ{æp-º"±mœäåUÚ ÏKbl]ý¿ŠÒ²|‹êìóò/¨/”ž H/«C KÁõo#XU%9ãÎp“sùùóü¥æù%– ]ʾpì)zK %¹$o£N+—+œ^IŠ/Úc‘r!ÛP\~M4.S6HHU!R5¼x½¹ô¢T%cV£PËÃMÚé± S”æ ð-åâá֥ƕIE/¸ÞÙK¬}ì‹ÄV‘uY‰Þpeê&†¸·ü«…J…­þ•f9ñ•¦õû +£$!©âš²u,“×ïÓÞÞÚ\ß>ÆrÊFZ§büÉ#²CŠi£æÞ¹2¡7 е8ª+]¬ÝAÝÃÄj*’Æ‘Šöp¢x„õ]î%røêàË8û ŸHÚcˆûdøõSާC›Tb—··†]ñ3yJ‘iL4 ¢­2ˆnÏ$ê‘§^>[Åq$sÎn´Ösß㢻œ;>Ë~½È»¦¤ôÂt=øcc3EkgÓµ\ÑÀÖí•rݬ“!-ù0~.g§ø‚J/ÈZ½Nµô_’·×ž $Í=/¥ßæŸúðö–Ú_ù‚ÌwñR¦ù«ƒ‰ò–†«sŸ¨d!¿eâ€S^, >'ÝÔ@!­Ï2µ¶Ša?^‚óV€ÌI·¸Ì`ÅœtçO6ÌëL£ÿÜ.ø.Mð·fú[ã\uY(ÁôšSÓ rKy"Ñ.cªp8¬v±v oñ9Æ ûhì ê5)‹NÂМÈ^K€˜S©Äú8`Μ«ÈãÁÀ9éNdA£fä%,¹N؉Ð@ûžG}s¹:½8F¼ #úàN½€;ô¥9’¹–-‡4ÌlÏâ/æ¤{t‡¦j÷¾Á20uvÑœ Þ÷¢o N–qwY,p½ÙjñÈÏjð™üÇ<i/1&ÇlV9̦(\¾žü£ÚRP9ÄÌ\»cS€ÛµVùUw=«ZŒ-Ó‚^=dû-̰ŠûÀÕl³l³l ³l½Df¶líj#xûïÐ[Ÿ„¸ÀÙQ6%Š®tTwÌö[ý-tËNî®;nÇ€—œ1á°â¡öÊ¡vÎÑARõ ŠÊ¡vM"€Íž²©¸ÙSþ}Í®:vÍû±Wiµ' Çßèá7·ú ?¶Åa;†,àZ ®­õ‡.´ÖY+ÊŸ Bl Dˆ-ƒ±%`!¶ Ì©%`ÛÂu°½C‡&4lÀÃaÑ·W×½ô@ôlÁÛE'QD|sÁ@g]kð¸þ }Úì¬( î=‡°”m8InÑ‘(úúåºwÊ¥ÌNºÂ¦˜¥Èa¡Ð'ÍÎ8žbV”ÍeìèR.„yO›¯z§¤«ÐQ`³£|E{àæ nèÚãEß¿ñ`K=_€ÍŠò!V1%úé%)€žå%8£_9Ì~¼‚$ÏžògÂ| U;Êû=3;Êfå@|S· €³µ«îµá½Ç襱`€°3 PΣ=WO³§ìz çx7,wÑ‘Dܦ…cý½„ ;Ê—ê Ž¹|o,ó©²¾åÕ#xÀ¦Ð'ì}¿Ãz ¿m¯Ã©NkåGµ£÷ág*£åë˜/Ь(믘Žžås™õÙÛ/´ cAþ„¹êà©àçŽ_ºâðlímL¸zö”x fyà«ÇîŠ`ßšî«GíèÞ#qº¸ý ¢*¶2×KB,; ËYp³§|‰¥\;ÆNîXâ&ð=a³£ü)ñ<ÞÅ5¥îyaõ^Ý<‰¨Âà[S>¥QÀ›<˜»nÐI…ö•"Q¬Àr8`GŒ]‘ƒ"Zn¸™[îãÐ\Ã)챤|H{T!S¢saöÊ@+Ê¿ ³Ñx®» À9wM˜‚óxöÓVà;trï;gE9­¨ðɇŽi/#f.ø]á(Ædì6ÐõŸ íõBðölã*TO¡SÊ`ÒÚQ>‚Ã9)÷Ät€Ï>©½;€Ïrêßy©›ð9ZÚN _—öBWÅÀÑ]”Cg t œ¹|&Wг§|‘|8àâ¼(Â2ìP Ìrvu‚\xÊÇ€Û|¸¡‡|dˆ²8c˜„}¥<Ā㼠À,L˜Ýs»„‚‚ö”9†€ å+S€ÕÆ û 3€û~v»Ñ R*aPÅ’²)›eÌÈѽ¹|îòµÀ;Êæ&Ktb)©~êË:YÝS,½s‚î˜ ÀÎ…òÑ}b6Zzd«7°¸¶&C<+¢…03?hOy„sÂAX¡k·^=|ç\¹‡²r-;¦ßXËŽ6šV”GRˆR\=+ÊgW'0çÀÎ ˆ÷=¤.™¶£œÝíSÖò'î÷Ó¢F}Ù¸èüaŠª¦^ i äW%Az;„£ë~D;Ê/KôЃéëκ"ÞsùÞGÇ„ølj®r>]^€Uq¡üÛþÉuãjîµ™/ÄpÛCû=@ÍŽòµòÉ-àæ$m_Oþ¨9Hàæ"mØ@ç rÞàAÙqÊpŽÀ›ä ˜¬.“ s”¹‡{1<¹øæY·Bíü¹—°á|2WÌ#~€žå®ô¬½TQ†®“Ž$°/nGùð캱oj”CRŸv'Œ*šî£­]!É-éågúqâ|®ðy$V é_ ‚nž‘ˆ 0ÂöÀ¥†ps1½ÿ£(ÔÅw4½Æè€ó\@o.{ ð¹›ZÀÎÝÚv”÷[Íc.Ò[| àìŠa»9º @tMcnÞÜqtx‘’Þ’a>)ìöÚQ>h^ëÏá?€ÏΖ4GYà€œŸ"Ü×`Gùbˆp{ƒåËæxÊ(E7Êÿ˜ˆ"hE;ÊWQµhGùz"Š í(ßLD.¹±£üëDáÎ;Ê_›'¾9 (‘ÈTB¿H/1€"z–”3a[bàÙSþ楠æ`2:a¾™Ï·],9µ¦ü{óv»DæZRþ¿ÃIlæp£·æs¿9ؼ"ÃFãZ#–fnû0³­ý4ЇÍBÀÔӃ慠CáÞñS„‰í„ãç§8Â|v…òd Êa¢`h‡áßG©Qp\ÒžòÃýæ;t£_íðìúí+(õàÛðÐ$,ýÀKŠœp¦6@gØXWä &pG9ÀÌŠrV„êŒJ UKʧ¤«9ÊW´tN”LTTv.”?ž4NN4+ÊŸéK‡D¢,¿zV”ùm:V³+ñì)ŸsÖ çôSŽ +Õ1È@µE ²MmƒÌR;ÊW Ç¬=f‹è1[Ä@ÙQì?SBÍ,KÊ·”Ü‘{/Lüí;?yDvH1EÏtK®L€UáÖðq¬G¢>¬tq(‰Ð`°]."iîöp¢x„õ]î%røêàË8û ?=Ј¸O†_?eQ:´ =ñx»=ìŠOº8 UŠLãÑK¤eCð]ÑwŠ&¸[0Áõ¢ ¶ &ØÚ*º‡E‹ÍÆFÑ7‹&X4†í—§k M§F§ióömžGÁfÿÊë¤Q½Ñ&BÆÄÜ_?P¾æ½_PD0“Hùôñ;‰Ó-ŽÌ|­*iÑ›ç[îf®,`z£Û[2PÞ„ê½"R™7ö¤ÇyÓSïXõE\*$ˆG˜BœôëÞPæëÞÈŸ«ÚSñÕïÓÞ˜„éÌþlë«äab„)ûfŒµ´Ž^f+>ʨ¶ŸWv¹ÜÅG:¥8ºŠû¸ÿÇ\¾—È×Ð^‚ &Á Ö~mõKUN…HstÃÛ3vÄäÜzTxI¤Vÿø[U¡¼9«x†PUÃ~DÕ«Ö¢óágÓ¯kçî¤ê)‘UÅPÒ{í13¼j9|Ikîiô±§aH"ÑÛ–Ä×+´=Ƙ¢.KÙù¤›‘Dp}$“( #æDQ‹Šgí—¨$fe®p ¥ŠCy6H31ð5³?/¤qÛ=‚ ͱëæh–áAX!³¤ä¬FAêáû/ºQcˆqU‡ÐÑBÑk6›UB¬VÞ'ï™2ÄÔ³“G0ô/ŸÏ;šu´$Âììj›à½VïrѸ™œ â3"k`æ÷¼$^‚ÒTUÄŽø‰‡úW½:Ke± h/ÐK䓞vnDkY/¤2@]*4Š!f½DÞ¤µT#a:ÛK¢ õPOð$Fë?„SE6Û—‚€Þ<èUý2•*â÷hþò°R7³×#ú#õòD{ÙË•ü0è´v2ªº¯$ËUâ÷—Œá¦ËUc÷³ `{Y¤Á ©V±eð¬$Y¨YüØ ÿWÉ[$f‘ (æÚÞèr¶È‰ô~Àͦ­€D4Æ‚HZƒÿ ‡$]ÔÁôº '“Ž6¬ÊÞxíÀÝfe$º¦ŒòI—x õ×@éÍ bȽšl-IFz¡F@s ̆u[úÿ”y0MÝq¡³n Ç–h ië*=Ac˜²®m!ÊL)¨Ô7©KïbUŸ&&€_±³uU+­â`§s˜•0ú¡DR®Þ—wj{kSS¯BˆÜµÁñ'È)¦‚àƒuÍàOôz¤/‰ V’EŸÒ|¡9ûD5§óD¹hdîÚî:×ü|Òêv|S±eW\z‘!•X¿¨œ)ñDV¶rIèÁ ²ÃuZÙ¡ÆãœÉØ·=“‘'q’iuJ»CiMÞAf¨C ú'ä–R´Y€…nU_I:þ]¦hã6£fnE× q¯ê³?¶†'H¶\¶·Eù|+ô¯þ÷1zÿúçÿ ¼mÊÐñÙåÕE•fø$ Nœˆùœ«í!ÏÜn+ÏÍD/‡w團ƒ¶^Ä!s½4²šN¤ ˆÜ㈲ÂxŠ6YååóYÁgšÈÀûø±è³'åé€í­­Ön…ô@1Íl*”5f="'?FÊQÙ£ö}¡çÁ‡•Ì…Sú© 3K’¾=nîï´÷žãäëî(ÖN£z4Á>¡–6\¨ñ¿f]ž~JíJ#ƒäÃÊCz=Œ8ŽB3cØdôÖ& yÊc ÐÚ@Öe¬-§/BÔÃÃ÷ûŸ|î%‘örf\úß_þ?PKk‹"{‘1ñ`PKǬd9 styles.xmlÝYmœ6þÞ_H%RY`ï’Ünn÷T5jûᮊòÒï>0¬c#ÛìK~}Ç6fa=š—¦iNJ‚ýÌÌãgÆfÌ]ßì êm±„³•Ï"ßÃ,á)aùÊÿî×àÊ¿YÿpͳŒ$x™ò¤*0STŠ¥ÆL.íäʯ[r$‰\2T`¹TÉ’—˜9£e½4¡ìˆq6ÕÜ€ÛÖ ïÕTcíØ¢ûé‘ ¸m ´›j¬± iÛ<ãS÷’^”H‘{J؇•¿Qª\†án·›í.f\äa¼X,B3ÛN\Y jPibŠu0Ƴ8tØ+4•ŸÆ¶)±ª¸Çb²4H¡^VK%@`¹º.§9jÛtêk›O®®m>"s²Abrp·T.Òé¥r‘¶m ¤6#ù½ ï`Òüuw{¬+QL¥±©AÊÉË´è¶=缡ª ìf7tçQtÚçzw¾DaÑ‚'gá ¢I£8/†D\"À[]ò-ô¢G=? .¹P ‘lúaêÌ›(i†š0€”3ã!І&VÛC¨wU¨Mù^}h¶깿v§rÆáDÎP‚ƒ'T®¯ínj†=û¬y®ü[[ÓlïŽ3î{PòZzXùQÉåËœô½Žkr̰ ˜‚§X°¤$*ÚÍȧ~xžØÏ‚ :@Ç–;"åPÜ-[ØÇ…n­õ-brŠ&7A“Ϧö ÿ…þ¬¼Ûß~9Oí7…ÚA*\|nSxýkœÞ¡ /Ðfâs£‡c»®·­‘c™â U´n˜œçš’i(‚Sê;øq((œBh³œ«„&(•+~Ô¢Då•›¾x„༠R"bºO‹fÏ;릨og–7²=2¾¤ˆåÊa33ðŠ)«zÿÖ?uÀ)‡ØiÁŒóã ÷{7U{t3Œ3Ü÷¬_ÖïOóÛ¸mæ7sƵNí@ÎÖ×¶›©›šN"­<Dþ È«Ÿ ÂÂÎÁ.%9QµØðÙøH*! ? …Š£Ëב[Ç–SÈŠn`•¨°?ààPÜsêØtSæ°­´­lˆ¸Y_¿"ϯÜÍæ‚W¥¹aâ-AºkŸ*‰?Vʦ.)‡VôQ–EðGǪ}jì:h"›ÇïXA+@ʦÈYJl÷¼E´ÂOž>ÎÕËUS<¨,i­gÐ)®3Ù°–ý¼²Æ?ßÂqã7Xž·õš3®¹yݸgÒoNŠú‚I¢$qþ ¸bгÀ ;Œä”¤#Iu'Ž*ÅGu±™ æÿ~Ãa‡I¾&j!m5(kÅ™’:]aõ-«—îsyù#ýàË$æÌkÍH‰ÉY y%ô úEçoŒ´˜°È—!*ñ/>üètå'`—ˆÑ÷]S%ä#ÄŽŸ—Ê«œÏKf­hüI’ºtL‘Tp{ à¼ÒôÑt’¸(7HK‘~­-éNd}_ESE OÚ«úQoF¸ “$èö]¥~ùStà•ê,ï®,bÔQß=Að@_kV>º?Öвq|qwÆ2ΡÜNÖ¬OóM½¾h6_<{AlÛT ‘ÃÅ™žéŠß½çJé»m4‹W—¶‘ ÇYÕt¾Sè:iv)…½\LÈáü–C=wÏEª¿šÁàÅåsÂ<ó.òÌ>‰ì>)Qj¿Ì&z;C”|Ð KÝ èQéŸF¤Ú÷J¦·àþ»²=\ãáè VOH6.ä±Á3ƒÚÓ¹¬½+>K}m¾‡—õ¿rƒ±E¯onn®ÃÓÁz¤<á¤t.]ËA$ôµ‡ÞKÛjÓD­×R?hÚ¶ù\Ç.^k¬GÁ¹êˆ~–BØÓñ!ißÔßþÎ(;ï)뺗\¿†5¡(¶÷ÄâQ´ ±ÏO{Bt"u†Ì>:‰Í í ¡Ûl@¹;À½^ÕAú®Çat©?‹^Õ,4pý“çûøùòâj_6¤‡Ê§Ëï›Õ”¶æ6·^,Ú@;ö•j/ÞíáðoÜÖPK¹WÀvõ±PKǬd9.7‘ ÎÎmeta.xml OpenOffice.org/3.0$Linux OpenOffice.org_project/300m9$Build-93582007-09-14T12:52:36Daniel Kimberg2008-11-04T16:38:1467PT05H09M01SPKǬd9Thumbnails/thumbnail.png¥•yPSWÆcÅ T¥‚v@@ë‚•b"FEVAÖ"%3‰B j„ÑÑ*R$„²()*;ɃÂЋ KDBC6·€šb ±¦¦Ó©âtêô¯÷͹¿{Îw¿{gÞ¥ @ïåækÌa0Ør_Ïè[ƒ-‚-…CêpV{+ gûzî ;]¤–ŠIl˜Éà¥<£Q¡zÞ¹RóÒ¶`Êr¶ˆ)ø}pgó2²ïæÒ˜˜Ú7Ši~'ƒy?¦U²uïtí`œ¬¢h‚📒êVׯ,~æ.ÔK0AQ“ÔêÆòkŒaá6æ ÄH~Æ(Òz‰tÄxºì.¿ÅÝ&yñ6‰Iáì3rƒ%²= –çá^Üù 'ç^½´ƒ?UWÈH¨Çòfd[9¯±ºÀ¶QÛW¡Käh$"9ꄜ.;{£ Tóûi­‚%–æT™ºYÖª7a—ÈUÀ#v Ïm¼åS,*e㟰F®ïfŠQÓ¥G@:º÷Væå"×Ûàc>)esÕËÆâU`wžîÍJïÚNÈ1ü‘ÔHH hÓ&%V“[lÁËSRj Éþ-È쑽£(íÌ"Ê•˜BqÄêr ’ A9‰1jCÜOd¡§GQ›”Ÿw5Z€ê~x‹^I›¿½»ýêÈÓU½Æ ó:å ÚrOYIpðë¸hé\fBß²hãÿ’7“…‰éÚD(0h'½¯¼­ÖË2:°Ày;iÚOòØWË„_ŠøöS^ûªèÁóc6ÓRÅs’ˆ³Gv-悜§oîD,"eµwÈÊ4ü|¶Òåº8%ënG'%Ô¤f¯|¢©p¿õmÁ¹•8OGì©5}Æaú.þ«k á†Íbì];”–‰Ê¬Rd G]ÆFc\Eï9Ù²†Dx“°ZT6L›æ UØêöYwcH“%'Õb,à ÚÑÚ¤ù… õ`oÐŒ²pÁšrBq¯$ùÌMBx“—#vuMpö÷eùšÎ6Ç©œ'bøÜëLž×6‚¶žÂ,º ó%ŠóÓcå\¶ª2} šQe/ðË+»¶å S0e>KH@Í>&Ö·ü7úaºÑÏÂkŽ@[Ïõ€¼ì¼øðÜʹ…Ž‹!Mš…4}y\Ú?Ù¦SÆó°DyÏÍé?púMT%¡FKB¥ˆPÈüï°Tf³0úä³ûIõ¿$cÉ <0 "š¦ŽAH›<ä td¨™{ø×õ,8)dÿ—Ù7³þTÐVˆøÂëS@Ô#knœÙ<óß$ˆÆeN7ç—fq2ûŽ:U/FäÔLÊn·íCC6 3¼W¢u½ùJ³C³ë5%âÕ“­ïLT=—±%EÉ[b6ø+v ”yí*RÀ‘SÒŸ©ñ¬cAD£¹Ýpó«ZCóñŽôüV†?œnZ˜22téHFô†'ýqá¦õîoÖ<»ºh:RƒAÚ8k,|¿X­KîÍÒo=µŽ¹ÌZwã£vô3­t;,îÊXúQÎËG´M­æÛCÏNB-˜ïÁ@ÏÚý¸³PKRŸr”sÜPKǬd9 settings.xmlí›]sÚ8†ï÷W0ÜÉGÍ$é˜ï4†ø¦#ÛTdÉ+Éøõ+›ÐI(N©1쎹a°¤÷IÏ‘…|ýeéâÜ2Ž(¹É—>ó9Hlê 2½ÉͳÏù/·]ÓÉÙ°âPÛw!g !«ðœlNxeS|“÷©PÀ¯àB^v…zl›U^×®DÆ6W–‘ùM~&„W)‚ ø”?Q6-”TU-D¥Ûª6%4=ÔÔ¦ökS”Ò†Âg"cJ±x^ØüÎç^œ|%»Ãööo¯_ l¾Î€n›ÜËåе›¼4YY üˆZ~_»·m Ä‘…¡Æ P/¿-+O""ò·ÅëÂÏ"¿%ü'â4Ê#äˆÙ>é’zu^:Z¾ Ñt¶×õrQ)+‡êŸ¹À;CÄKèìÚ‚Áþ^ŠÚÈñÅV‡x ƒ;gÇM.˜ùÛ°ðàHDVCÑ?@FäW޾m2A;‡ŒÀšÏ8eO”#!'Àxo´“õä[åç}Êçɔ۔¡5%྇‘èPî†FÙC2ìS©ïx¿ PšSôµÿ'Ð×l0RיƄçà úV|ëoÊØÚÊêqL9R7]|oU«Tê¦(lRê¤Jª#:5öwU7¹ ˜4` C|¾«~#¾çâûL)÷ ÎE@Íqßu[¥ÃÕ„q9€« soÆÕŒ«W3®þ ® ÈŇ_Ÿ–ÒAQÒ ¤H3ž¤ ŽAØ9n¤Õ„KÈ z¡fPÍ šA5ƒê†ª´•Òêô„OùÅ«Œ¤I3’&!éùç ¥¥‹Ø?Ù>Òš4û'*#iFÒD$-'ÜËH‘4®8:pè ˆNÄAØ8š6£[€Åú¸*eáÝð+ñþŒ¡*ƒ`þÄ`˜9wô-J1Dv*À&7cBF#ÿyœÁü#ô»TœJºÅÐîa›”CÕÅ”íHcN¡’rYV”‹ËúõQi.]÷]¢Ó  ÙiŒôg Iš¨ßñG_`D`åZó>ÜÍŒ©éà ¨¸€»ÆÌÚßñ—3l'³ C.û;~™¬\%$Юüþm‡#åû¾å â)¯òOódÄßÈkKÄû+bÏ%h €(ájàåüâþ ŠÃ¨n.ø,úÇàwΪfyã–7™=ÿd™pI—¥¤,%e)é?’’~eIó­lûX¢"}ù'ù˜*ï£+Ä<ÁÖ&Ýoåä¢%àßê㈹€Cv”Q9©ýÝÝKª^žW‰zJ~ý](vÝþ¼6cí4œ™Ó2Ö㢎­Ö²n)Ë…=_ÎlÅXiàÓ+½áÚ«›ó‹I§ä`»¬·ŸÇ:¶KjÃ-yOQ¹UþÚyîi#Mëh—½M›ZÓÊï¹%¯õ]é­fñ¹¯-k¤º£‹¢9¾S{Šù8^wÇæ¸[Ô•¦¼Öè-ƒ[îÂj©«A«¹–õî¥ Ï”m¤mÏRÎÕ¡,sÚ_g`Ü»VÔŒŒõÓ qoš+SÁ¾ÙjþãHMkdøN½<Ô5Þ©AÍÝèš-#pZSµó½wo·»Ü›Ø’õ^•+`ÔÅOí~ج6ä}ú²ŸÎ£{èyAC-9íjÉi”fkxÙý®°þtÚÓ¢Ö¬ÎLÅ€±‡çKì´e¼¦Õ5RNkæY®}©»Mn+CMo%uçzÉn-1l\,Œ¶!žÝ%–±»I8Å<¯†r4×éO±Ú 0`Ëñ^£®Ç Y”úŽË¿‡Œhòä[ø`Ïfo*`Í [¤†)?EZÛ,ŒšŒºèzï‘ï#Ær‰¢è+µj€ØŸ`™G£Ë5%xu‚{¸ãõ——ñúr”ÅçŸwLÄ>Ó~z¯÷Šâí¿PK ²Š|¨ä8PKǬd9META-INF/manifest.xmlµ•Anà E÷9…Åަͪ²âDj¥ž =À$ ˆ¢äöÅ‘’¸mT5•Ù…ßûŒ=°ÚS0v¶ÏÕ“(Ð*×jÛ7âcû^¾ˆÍz±Àê‰ëË HïYºNƒ­¦Ú€T³ªGÛ:´\]_¦õ¢¸;m°L é¸É°ÕPòÉc#À{£pÊ)¶­Î®jª¨È„–öˆ,nÉæ–“Ç]4¦ôÀûFH!ŠrŸòæl§ûÎi)‰#í äÁƒRh0M]*†0 Õ8»+‹ 33Á½óѧ$fÂפ|_zŒž ÎΙlp=@$_5à)«ãAö÷Ó„¢»§ŠºRSÁß2<(g<²{õ.<ùùÍü;—ødfÇÈ0ÛÁ³ÝÇagA’|VÞösÃç-,2§ëòZÚ•üq[®?PKATûCIhPKǬd9…l9Š..mimetypePKǬd9TConfigurations2/statusbar/PKǬd9'ŒConfigurations2/accelerator/current.xmlPKǬd9ãConfigurations2/floater/PKǬd9Configurations2/popupmenu/PKǬd9QConfigurations2/progressbar/PKǬd9‹Configurations2/menubar/PKǬd9ÁConfigurations2/toolbar/PKǬd9÷Configurations2/images/Bitmaps/PKǬd9k‹"{‘1ñ` 4content.xmlPKǬd9¹WÀvõ± þ3styles.xmlPKǬd9.7‘ ÎÎ+:meta.xmlPKǬd9RŸr”sÜ>Thumbnails/thumbnail.pngPKǬd9 ²Š|¨ä8 ØCsettings.xmlPKǬd9ATûCIhºIMETA-INF/manifest.xmlPKîFKvoxbo-1.8.5~svn1246/dbmisc/template_field.txt000066400000000000000000000006211153177201300211030ustar00rootroot00000000000000Template No. (Damasio & Damasio, 1989), Template No. (Damasio & Damasio, 1989) (2), MRN, Record No., Pt Last Name, Pt First Name, Scan Date, Scan Date (2), Type of Scan, Type of Scan (2), Slice No. (L to R), Slice No. (L to R) (2), Comments, Pitch for MRIcro Slices (NON-Damasio Templates), Pitch for MRIcro Slices (NON-Damasio Templates) (2), Additional Descriptions of Lesion Available, viewexclude voxbo-1.8.5~svn1246/dbmisc/types.csv000066400000000000000000000065611153177201300172560ustar00rootroot00000000000000#"type name","type value", t_custom (yes/y or no/n) "ethnic_group_old","pre 3/02 groups", "yes" "Hispanic or Latino", "Not Hispanic or Latino", "Unknown (Individuals not reporting ethnicity)", "ethnic_group_302","post 3/02 groups", "yes" "Black, Not of Hispanic Origin", "White, Not of Hispanic Origin", "Asian or Pacific Islander", "Hispanic", "American Indian or Alaskan Native", "Unknown", "Do Not Wish To Say", "Other", "racial_group","all post 3/02", yes "American Indian/Alaska Native", "Asian", "Native Hawaiian or Other Pacific Islander", "Black or African American", "White", "More than one race", "Unknown or not reported", "Other", "Do not wish to say", "handedness", "handedness", no "left handed", "right handed", "ambidextrous", "gender", Gender, no "male", "female", "other", "degree", Highest degree, yes "None", "High School Diploma", "Technical School", "Associate's College Degree", "College Degree", "Master's Degree", "Ph.D.", "M.D.", "hospital", Hospital names, yes "HUP", "VA", "Temple", "Moss", "Jefferson", "scan_type", scan types, yes "MRI", "MRI/MPRAGE", "MRI/FLAIR", "CT", "SPECT", "MRA", "region_relationship", region relationships, yes "equivalent-to", "part-of", "near-to", "lesion_cause", lesion causes, yes "Stroke/Infarct", "Watershed Infarct", "Venous Infarction", "Bleed (undetermined cause)", "Aneurysm", "AVM", "Venous Angioma", "Tumor Resection", "Emboli", "Lacunar Infarcts", "Lacunar Infact", "Adenoma", "Vasculitis", "Hemorrhage", "Edema", "Subarachnoid Hemorrhage", "Subdural Hematoma", "Hematoma", "Enceph, Herpes", "Enceph, ADEM", "Enceph", "Voltage gated K+ channel antibodies", "Small Vessel Disease", "Meningioma", "Atrophy", "Calcifications", "Encephalomalacia", "Abnormal Signal Intensity", "Radiation Necrosis", "Volume Loss", "Hypodensity", "Hyperdensity", "Cystic Lesion", "Hydrocephalus", "Craniotomy", "Craniectomy", "Resection", "Rupture", "Contusions", "Demyelination", "Decreased Perfusion", "Unspecified", "Undetermined", "Questionable", "lesion_side", lesion side, no "left", "right", "bilateral", "diffuse", "hemiparesis_type", hemiparesis type, yes "none", "left", "right", "bilateral", "type_sex", type sex, no "male", "female", "lesion_location", lesion locations, yes "MCA", "PCA", "ACA", "ACA/MCA Watershed", "PICA", "ACoA", "ICA", "Anterior Choroidal Artery", "Anterior Communicating Artery", "Posterior Communicating Artery", "Pericallosal Artery", "Basilar Artery", "Circle of Willis", "Frontal", "Parietal", "Temporal", "Occipital", "Thalamus", "Pons", "Brainstem", "Midbrain", "Basal Ganglia", "Frontal-Parietal", "Frontal-Temporal", "Parietal-Temporal", "Parietal-Occipital", "Occipital-Temporal", "Frontal-Temporal-Parietal-Occipital", "Frontal-Temporal-Parietal", "Temporal-Parietal-Occipital", "Corpus Callosum", "Pituitary", "Cerebellum", "Vermis", "Caudate", "Putamen", "Pulvinar", "Globus Pallidus", "White matter", "Frontal white matter", "Temporal white matter", "Parietal white matter", "Occipital white matter", "Gray matter", "Striatocapsular region", "Internal capsule", "External capsule", "Corona radiata", "Insula", "Anterior cingulate", "Subinsular cortex", "Centrum semiovale", "Sylvian Fissure", "Perisylvian", "Hippocampus", "Cortical", "Cerebral", "Hemisphere", "Supratentorial", "Intraventricular", "Periventricular", "Parenchymal", "Parasellar", "Sellar/Suprasellar", "Subcortical", "Unspecified ", voxbo-1.8.5~svn1246/dbutil/000077500000000000000000000000001153177201300154075ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dbutil/Makefile000066400000000000000000000101651153177201300170520ustar00rootroot00000000000000 # Makefile in util directory -include ../make_vars.txt include ../make_stuff.txt LIBS=$(LDFLAGS) $(LIBDIRS) -lm -ldbutil -lgnutls -lgnutls-extra -lgcrypt -lgpg-error -ldb_cxx -lvbprefs -lvbglm -lvbio -lvbutil -lgsl -lgslcblas -lz -lpng -ldl -lpthread ALLBINS=initDB initScoreValues # DYK: these binaries are not needed; this kind of functionality # should be in client/dbtool anyway ALLBINS= ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else ifeq ($(VB_TARGET),db) BINS=$(ALLBINS) else BINS= endif # main targets all: $(BINS) install: ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) initScoreNames: initScoreNames.o $(CXX) -o initScoreNames initScoreNames.o $(LIBS) initScoreValues: initScoreValues.o $(CXX) -o initScoreValues initScoreValues.o $(LIBS) initPerm: initPerm.o $(CXX) -o initPerm initPerm.o $(LIBS) showScoreNames: showScoreNames.o $(CXX) -o showScoreNames showScoreNames.o $(LIBS) showPerm: showPerm.o $(CXX) -o showPerm showPerm.o $(LIBS) showSessions: showSessions.o $(CXX) -o showSessions showSessions.o $(LIBS) showScoreValues: showScoreValues.o $(CXX) -o showScoreValues showScoreValues.o $(LIBS) showPatientScores: showPatientScores.o $(CXX) -o showPatientScores showPatientScores.o $(LIBS) showUsers: showUsers.o $(CXX) -o showUsers showUsers.o $(LIBS) showSystem: showSystem.o $(CXX) -o showSystem showSystem.o $(LIBS) showRegionNames: showRegionNames.o $(CXX) -o showRegionNames showRegionNames.o $(LIBS) showSynonyms: showSynonyms.o $(CXX) -o showSynonyms showSynonyms.o $(LIBS) showRegionRelations: showRegionRelations.o $(CXX) -o showRegionRelations showRegionRelations.o $(LIBS) showPatients: showPatients.o $(CXX) -o showPatients showPatients.o $(LIBS) delRecord: delRecord.o g++ -o delRecord delRecord.o $(LIBS) cpDB: cpDB.o $(CXX) -o cpDB cpDB.o $(LIBS) mvDB: mvDB.o $(CXX) -o mvDB mvDB.o $(LIBS) addPerm: addPerm.o $(CXX) -o addPerm addPerm.o $(LIBS) delPerm: delPerm.o $(CXX) -o delPerm delPerm.o $(LIBS) resetEnv: resetEnv.o $(CXX) -o resetEnv resetEnv.o $(LIBS) addPatientList: addPatientList.o $(CXX) -o addPatientList addPatientList.o $(LIBS) showPatientList: showPatientList.o $(CXX) -o showPatientList showPatientList.o $(LIBS) resetSystem: resetSystem.o $(CXX) -o resetSystem resetSystem.o $(LIBS) initSystem: initSystem.o $(CXX) -o initSystem initSystem.o $(LIBS) initDB: initDB.o $(CXX) -o initDB initDB.o $(LIBS) # object file generation initScoreNames.o: initScoreNames.cpp $(CXX) -c initScoreNames.cpp $(CXXFLAGS) initScoreValues.o: initScoreValues.cpp $(CXX) -c initScoreValues.cpp $(CXXFLAGS) initPerm.o: initPerm.cpp $(CXX) -c initPerm.cpp $(CXXFLAGS) showScoreNames.o: showScoreNames.cpp $(CXX) -c showScoreNames.cpp $(CXXFLAGS) showPerm.o: showPerm.cpp $(CXX) -c showPerm.cpp $(CXXFLAGS) showSessions.o: showSessions.cpp $(CXX) -c showSessions.cpp $(CXXFLAGS) showScoreValues.o: showScoreValues.cpp $(CXX) -c showScoreValues.cpp $(CXXFLAGS) showPatientScores.o: showPatientScores.cpp $(CXX) -c showPatientScores.cpp $(CXXFLAGS) showUsers.o: showUsers.cpp $(CXX) -c showUsers.cpp $(CXXFLAGS) showSystem.o: showSystem.cpp $(CXX) -c showSystem.cpp $(CXXFLAGS) resetSystem.o: resetSystem.cpp $(CXX) -c resetSystem.cpp $(CXXFLAGS) initSystem.o: initSystem.cpp $(CXX) -c initSystem.cpp $(CXXFLAGS) showRegionNames.o: showRegionNames.cpp $(CXX) -c showRegionNames.cpp $(CXXFLAGS) showSynonyms.o: showSynonyms.cpp $(CXX) -c showSynonyms.cpp $(CXXFLAGS) showRegionRelations.o: showRegionRelations.cpp $(CXX) -c showRegionRelations.cpp $(CXXFLAGS) showPatients.o: showPatients.cpp $(CXX) -c showPatients.cpp $(CXXFLAGS) initDB.o: initDB.cpp g++ -c initDB.cpp $(CXXFLAGS) delRecord.o: delRecord.cpp g++ -c delRecord.cpp cpDB.o: cpDB.cpp g++ -c cpDB.cpp mvDB.o: mvDB.cpp g++ -c mvDB.cpp addPerm.o: addPerm.cpp g++ -c addPerm.cpp delPerm.o: delPerm.cpp g++ -c delPerm.cpp resetEnv.o: resetEnv.cpp g++ -c resetEnv.cpp addPatientList.o: addPatientList.cpp g++ -c addPatientList.cpp $(CXXFLAGS) showPatientList.o: showPatientList.cpp g++ -c showPatientList.cpp $(CXXFLAGS) voxbo-1.8.5~svn1246/dbutil/cpDB.cpp000066400000000000000000000046741153177201300167360ustar00rootroot00000000000000/* This program duplicates a certain db table. * Note that we can do it by db utilities like this: * db_dump | db_load * but the new db file won't be able to keep the original key comparasion. * So if records in original db file has numerical keys and are sorted by key values, * keys in the new db file will be sorted lexically (default key comparision). * Before running this command, please also make sure the new db file does NOT exist, * otherwise the keys that already exists in destination db will be overwritten * instead of being created from scratch. */ using namespace std; #include #include #include #include #include "mydb.h" int main(int argc, char* argv[]) { if (argc != 4 && argc != 6) { cout << "Usage: cpDB [int | lex] [dup | nodup]" << endl; exit(1); } string envHome = argv[1]; string dbname_src = argv[2]; string dbname_dest = argv[3]; mydb::key_comp cmp_method = mydb::cmp_int; bool allowDup = false; if (argc == 6) { if (strcmp(argv[4], "int") == 0) cmp_method = mydb::cmp_int; else if (strcmp(argv[4], "lex") == 0) cmp_method = mydb::cmp_lex; else { cout << "Unknown argument: " << argv[4] << endl; cout << "Usage: cpDB [int | lex] [dup | nodup]" << endl; exit(1); } if (strcmp(argv[5], "dup") == 0) allowDup = true; else if (strcmp(argv[5], "nodup") == 0) allowDup = false; else { cout << "Unknown argument: " << argv[5] << endl; cout << "Usage: cpDB [int | lex] [dup | nodup]" << endl; exit(1); } } // open env myEnv env(envHome); if (!env.isOpen()) exit(1); // open source db in env mydb srcDB(dbname_src, env, cmp_method, allowDup); if (!srcDB.isOpen()) { //env.close(); exit(1); } // open destination db in env mydb destDB(dbname_dest, env, cmp_method, allowDup); if (!destDB.isOpen()) { //env.close(); exit(1); } Dbc *cursorp = NULL; srcDB.getDb().cursor(NULL, &cursorp, 0); Dbt key, data; int ret; DbTxn* txn = NULL; env.getEnv().txn_begin(NULL, &txn, 0); while ((ret = cursorp->get(&key, &data, DB_NEXT)) == 0) { destDB.getDb().put(txn, &key, &data, 0); } cursorp->close(); txn->commit(0); srcDB.close(); destDB.close(); env.close(); return 0; } voxbo-1.8.5~svn1246/dbutil/delRecord.cpp000066400000000000000000000017401153177201300200200ustar00rootroot00000000000000using namespace std; #include #include #include "mydb.h" #include "db_util.h" int main(int argc, char* argv[]) { if (argc != 3) { cout << "Usage: delRecord " << endl; exit(1); } string dbPath = argv[1]; string envHome; string dbName; if (!parseEnvPath(dbPath, envHome, dbName)) { exit(1); } int32 id = atol(argv[2]); if (id <= 0) { cout << "Invalid ID: " << argv[2] << endl; exit(1); } myEnv env(envHome); if (!env.isOpen()) exit(1); mydb currentDB(dbName, env); if (!currentDB.isOpen()) { env.close(); exit(1); } DbTxn* txn = NULL; env.getEnv().txn_begin(NULL, &txn, 0); Dbt key(&id, sizeof(id)); if (currentDB.getDb().del(txn, &key, 0) == 0) { cout << "Record " << id << " is deleted" << endl; txn->commit(0); } else { cout << "Failed to delete record ID " << id << endl; txn->abort(); } currentDB.close(); env.close(); return 0; } voxbo-1.8.5~svn1246/dbutil/initDB.cpp000066400000000000000000000015231153177201300172650ustar00rootroot00000000000000/****************************************************************************** * initSystem.cpp: initialize system table ******************************************************************************/ using namespace std; #include #include #include "bdb_tab.h" #include "dbdata.h" /* Main function */ int main(int argc, char *argv[]) { if (argc != 4) { printf("Usage: initDB \n"); return 0; } string db_dir(argv[1]); if (!vb_direxists(db_dir)) { cout << "Directory not exist: " << argv[1] << endl; exit(1); } uint32 start_id = atol(argv[3]); if (start_id <= 0) { cout << "Invalid start ID: " << argv[3] << endl; exit(1); } DBdata new_dbs; if (new_dbs.initDB(db_dir, argv[2], start_id)) cout << new_dbs.errMsg << endl; return 0; } voxbo-1.8.5~svn1246/dbutil/initPerm.cpp000066400000000000000000000115661153177201300177130ustar00rootroot00000000000000/* initPerm.cpp: populate permissions table from plain text file. * NOTE: This program updates database WITHOUT db environment. */ #include "tokenlist.h" #include "mydb.h" #include "bdb_tab.h" #include "db_util.h" #include #include #include #include #include using namespace std; string userDbName = "user.db"; string permDbName = "permissions.db"; string dirname; bool envFlag; myEnv env; mydb permDB, userDB; bool chkArg(int, char* argv[]); bool setEnvDB(); bool setDB(); void addRecords(char*, DbTxn*); /* Main function */ int main(int argc, char *argv[]) { if (!chkArg(argc, argv)) exit(1); DbTxn* txn = NULL; if (envFlag) { if (!setEnvDB()) { userDB.close(); permDB.close(); env.close(); exit(1); } env.getEnv().txn_begin(NULL, &txn, 0); } else if (!setDB()) { userDB.close(); permDB.close(); exit(1); } addRecords(argv[1], txn); userDB.close(); permDB.close(); if (envFlag) env.close(); return 0; } // Check input arguments on command line bool chkArg(int argc, char* argv[]) { if (argc != 4) { printf("Usage: initPerm [--env | --dir] \n"); return false; } string optStr = argv[2]; if (optStr == "--env") envFlag = true; else if (optStr == "--dir") envFlag = false; else { printf("Usage: initPerm [--env | --dir] \n"); return false; } const string inputFile = argv[1]; if (!vb_fileexists(inputFile)) { // Make sure input file exists cout << "File not exists: " << inputFile << endl; return false; } dirname = argv[3]; if (!vb_direxists(dirname)) { // Make sure db dir exists cout << "DB directory not exists: " << dirname << endl; return false; } if (dirname[dirname.size() - 1] != '/') dirname.append("/"); // don't let the trailing '/' mess up db file path // Remove original db file if it already exists if (vb_fileexists(dirname + permDbName)) { bool rmStat; if (envFlag) rmStat = rmDB(dirname, permDbName); else rmStat = rmDB(dirname + permDbName); if (!rmStat) { cout << "Failed to remove original db file: " << permDbName << endl; return false; } } return true; } // Open DBs in env bool setEnvDB() { if (env.open(dirname)) { cout << "Failed to open env" << endl; return false; } if (userDB.open(userDbName, env)) { cout << "Failed to open user db" << endl; return false; } if (permDB.open(permDbName, env, mydb::cmp_lex, true)) { cout << "Failed to open user db" << endl; return false; } return true; } // Open DBs w/o env bool setDB() { if (userDB.open(dirname + userDbName)) { cout << "db open error: " << dirname + permDbName << endl; return false; } if (permDB.open(dirname + permDbName, mydb::cmp_lex, mydb::sort_default, DB_CREATE)) { cout << "db open error: " << dirname + permDbName << endl; return false; } return true; } // Add records into db void addRecords(char* txt_file, DbTxn* txn) { FILE* ifp = fopen(txt_file, "r"); // Make sure file is readable if (!ifp) { printf("File read error: %s\n", txt_file); return; } const int MAXLENGTH = 5000; char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // if a line starts with "#", ignore the line if (strchr("#\n", line[0])) continue; // remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); tokenlist myRow; myRow.SetQuoteChars("\""); myRow.SetSeparator(" "); myRow.ParseLine(tmpStr); // Print out error message if the line is not blank but the number of field is not 7 if (myRow.size() != 3) { printf("%s line #%d: the number of fields is %d\n", txt_file, lineNo, myRow.size()); continue; } string userName = myRow[0]; userRec uRec; int32 stat = getUser(userDB, NULL, userName, uRec); if (stat < 0) { printf("%s line #%d: db error when getting user ID of %s\n", txt_file, lineNo, userName.c_str()); continue; } if (stat == 0) { printf("%s line #%d: user %s not exist\n", txt_file, lineNo, userName.c_str()); continue; } string accessID = strnum(uRec.getID()); string dataID = myRow[1]; string permStr = myRow[2]; if (permStr != "b" && permStr != "r" && permStr != "rw") { printf("%s line #%d: user %s not exist\n", txt_file, lineNo, userName.c_str()); continue; } permRec pRec; pRec.setAccessID(accessID); pRec.setDataID(dataID); pRec.setPermission(permStr); if (addPerm(permDB, txn, pRec)) { printf("%s line #%d: failed to add new record into permission db\n", txt_file, lineNo); if (envFlag) { txn->abort(); fclose(ifp); return; } } } if (envFlag) txn->commit(0); permDB.getDb().sync(0); fclose(ifp); } voxbo-1.8.5~svn1246/dbutil/initScoreNames.cpp000066400000000000000000000055161153177201300210450ustar00rootroot00000000000000/* initScoreNames.cpp: populate patient score (attribute) names from plain text file. * NOTE: This program updates database WITHOUT db environment! */ #include "tokenlist.h" #include "mydb.h" #include "bdb_tab.h" #include "db_util.h" #include #include #include #include #include using namespace std; void addRecords(char*, mydb&); /* Main function */ int main(int argc, char *argv[]) { if (argc != 3) { printf("Usage: initScoreNames \n"); exit(0); } const string inputFile = argv[1]; if (!vb_fileexists(inputFile)) { // Make sure input file exists cout << "File not exists: " << inputFile << endl; exit(1); } string dirname = argv[2]; if (!vb_direxists(dirname)) { // Make sure db env dir exists cout << "DB env directory not exists: " << dirname << endl; exit(1); } if (dirname[dirname.size() - 1] != '/') dirname.append("/"); // don't let the trailing '/' mess up db file path string dbname = "scorenames.db"; // Remove original db file if it already exists in env dir if (vb_fileexists(dirname + dbname)) { if (!rmDB(dirname + dbname)) { cout << "Faild to remove original db file: " << dbname << endl; exit(1); } } // open db in non-transaction mode mydb newDB(dirname + dbname, mydb::cmp_lex); if (!newDB.isOpen()) { cout << "db open error: " << dirname + dbname << endl; exit(1); } addRecords(argv[1], newDB); newDB.close(); return 0; } // Add records into db void addRecords(char* txt_file, mydb& inputDB) { FILE* ifp = fopen(txt_file, "r"); // Make sure file is readable if (!ifp) { printf("File read error: %s\n", txt_file); return; } const int MAXLENGTH = 5000; char line[MAXLENGTH]; int lineNo = 0; while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // if a line starts with "#", ignore the line if (strchr("#\n", line[0])) continue; // remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); tokenlist myRow; myRow.SetQuoteChars("\""); myRow.SetSeparator(" "); myRow.ParseLine(tmpStr); // Print out error message if the line is not blank but the number of field is not 7 if (myRow.size() < 2) { printf("%s line #%d: the number of fields is %d\n", txt_file, lineNo, myRow.size()); continue; } string scoreName = myRow[0]; DBscorename sData; sData.name = scoreName; sData.screen_name = scoreName; sData.datatype = myRow[1]; for (int i = 2; i < myRow.size(); i++) { string flag_str = myRow[i]; sData.flags[flag_str] = "true"; } if (addScoreName(inputDB, NULL, sData)) { printf("%s line #%d: failed to add %s into score db\n", txt_file, lineNo, scoreName.c_str()); } inputDB.getDb().sync(0); } fclose(ifp); } voxbo-1.8.5~svn1246/dbutil/initScoreValues.cpp000066400000000000000000000074501153177201300212400ustar00rootroot00000000000000/* initScoreValues.cpp: populate patient score values table from plain text file. * NOTE: This program updates database WITHOUT db environment! */ using namespace std; #include "tokenlist.h" #include "mydb.h" #include "bdb_tab.h" #include "db_util.h" #include #include #include #include #include void addRecords(char*, mydb&, mydb&); /* Main function */ int main(int argc, char *argv[]) { if (argc != 3) { printf("Usage: initScoreValues \n"); exit(0); } const string inputFile = argv[1]; if (!vb_fileexists(inputFile)) { // Make sure input file exists cout << "File not exists: " << inputFile << endl; exit(1); } string dirname = argv[2]; if (!vb_direxists(dirname)) { // Make sure db env dir exists cout << "DB env directory not exists: " << dirname << endl; exit(1); } if (dirname[dirname.size() - 1] != '/') dirname.append("/"); // don't let the trailing '/' mess up db file path string dbname = "scorevalues.db"; string secd_dbname = "patientscores.sdb"; string sysname = "system.db"; // Remove original db file if it already exists in env dir if (vb_fileexists(dirname + dbname)) { if (!rmDB(dirname + dbname)) { cout << "Faild to remove original db file: " << dbname << endl; exit(1); } } // open db in non-transaction mode mydb primDB(dirname + dbname, mydb::cmp_lex); if (!primDB.isOpen()) { cout << "db open error: " << dirname + dbname << endl; exit(1); } mydb secdDB(dirname + secd_dbname, mydb::cmp_int, mydb::sort_default); if (!secdDB.isOpen()) { cout << "db open error: " << dirname + secd_dbname << endl; primDB.close(); exit(1); } primDB.getDb().associate(NULL, &secdDB.getDb(), getPID, 0); mydb sysDB(dirname + sysname, mydb::cmp_lex); if (!sysDB.isOpen()) { cout << "db open error: " << dirname + sysname << endl; secdDB.close(); primDB.close(); exit(1); } addRecords(argv[1], primDB, sysDB); secdDB.close(); primDB.close(); sysDB.close(); return 0; } // Add records into db void addRecords(char* txt_file, mydb& inputDB, mydb& sysDB) { FILE* ifp = fopen(txt_file, "r"); // Make sure file is readable if (!ifp) { printf("File read error: %s\n", txt_file); return; } const int MAXLENGTH = 5000; char line[MAXLENGTH]; int lineNo = 0; time_t t_stamp = time(NULL); while (fgets(line, MAXLENGTH, ifp)) { lineNo++; // if a line starts with "#", ignore the line if (strchr("#\n", line[0])) continue; // remove the trailing "return" key stripchars(line, "\n"); const string tmpStr(line); tokenlist myRow; myRow.SetQuoteChars("\""); myRow.SetSeparator(" "); myRow.ParseLine(tmpStr); // Print out error message if the line is not blank but the number of field is not 7 if (myRow.size() != 3) { printf("%s line #%d: the number of fields is %d\n", txt_file, lineNo, myRow.size()); continue; } int32 pID = atoi(myRow(0)); if (pID <= 0) { printf("%s line #%d: invalid patient ID %s\n", txt_file, lineNo, myRow(0)); continue; } // dhu: should we also verify that this patient ID exists in patient table? DBscorevalue svData; svData.patient = pID; svData.datatype = "string"; // dhu: should we also verify this score name exists in score name table? svData.scorename = myRow[1]; svData.v_string = myRow[2]; svData.setby = "admin"; svData.whenset.setUnixTime(t_stamp); if (addScoreValue(inputDB, sysDB, NULL, svData)) { printf("%s line #%d: failed to add record into score value db\n", txt_file, lineNo); } inputDB.getDb().sync(0); } string statMsg; if (setSysUpdate(sysDB, NULL, t_stamp, statMsg)) cout << statMsg << endl; fclose(ifp); } voxbo-1.8.5~svn1246/dbutil/mvDB.cpp000066400000000000000000000016061153177201300167460ustar00rootroot00000000000000// Rename a db file in environment using namespace std; #include #include #include #include #include "mydb.h" #include "db_util.h" int main(int argc, char* argv[]) { if (argc != 3) { cout << "Usage: mvDB " << endl; exit(1); } string dbPath = argv[1]; const char* new_name = argv[2]; string envHome, dbName; if (!parseEnvPath(dbPath, envHome, dbName)) { cout << "Invalid db path: " << dbPath << endl; exit(1); } // open env myEnv env(envHome); if (!env.isOpen()) { cout << "Failed to open db env" << endl; exit(1); } DbTxn* txn = NULL; env.getEnv().txn_begin(NULL, &txn, 0); if (env.getEnv().dbrename(txn, dbName.c_str(), NULL, new_name, 0)) { cout << "Faield to rename db file" << endl; txn->abort(); } else txn->commit(0); env.close(); return 0; } voxbo-1.8.5~svn1246/dbutil/perm.txt000066400000000000000000000015241153177201300171150ustar00rootroot00000000000000# Sample text file used to initialize permission table # Each line includes three fields separated by space: access_ID, data_ID, permission # # If access_ID is the wild character of '*', then all users/groups are loowed to access # certain data with specified permission on lthat line. # If data_ID is '*', then user/group on that line is allowed to access any data # with specified permission on that line. # # So far only three permissions are allowed: b (browse), r (read), rw (read and write) # # Note that access_ID can be either user ID or group ID. But here we assume the first field # is ALWAYS user ID. In a real txt file, this permission to too bold to be true. So initPerm.cpp # has to be modofied to include both user and group ID. # Allows admin, dhu and kimberg to access any data with rw permission admin * rw dhu * rw kimberg * rw voxbo-1.8.5~svn1246/dbutil/scorevalues.txt000066400000000000000000000011271153177201300205040ustar00rootroot00000000000000# sample score value txt file # Each line includes four fields from left to right: patient_id, score_name, score_value # Note that this format is too simple to be used for any real socre value table. # It doesn't include score value parent ID, value index, setby and expiration date. # dateAdded field is always set to the current date, setby is set to user account "admin". 2217 demographics:firstname John 2217 demographics:lastname Smith 2217 demographics:phonenumber 215-662-4762 2258 demographics:firstname David 2258 demographics:lastname Smith 2258 demographics:phonenumber 215-222-3532 voxbo-1.8.5~svn1246/dbutil/showPatientScores.cpp000066400000000000000000000023331153177201300216000ustar00rootroot00000000000000 // Make a secondary db table, base on db1.db using namespace std; #include "db_util.h" #include "bdb_tab.h" #include #include int main(int argc, char* argv[]) { string patientScoreDbName, scoreValueDbName; if (argc == 1) { patientScoreDbName = "../env/patientscores.sdb"; scoreValueDbName = "../env/scorevalues.db"; } else if (argc == 3) { patientScoreDbName = argv[1]; scoreValueDbName = argv[2]; } else { printf("Usage: showPatientScores \n"); printf("Default db files are: ../env/patientscores.sdb and ../env/scorevalues.db"); return 0; } // open primary db mydb scoreValueDB(scoreValueDbName, mydb::cmp_lex); mydb patientScoreDB(patientScoreDbName, mydb::cmp_int, mydb::sort_default); // associate primary and secondary db scoreValueDB.getDb().associate(NULL, &patientScoreDB.getDb(), getPID, 0); // iterate secondary db Dbc *cursorp = NULL; patientScoreDB.getDb().cursor(NULL, &cursorp, 0); Dbt skey, pdata; int ret; while ((ret = cursorp->get(&skey, &pdata, DB_NEXT)) == 0) { DBscorevalue tmpRec(pdata.get_data()); tmpRec.show(); } cursorp->close(); return 0; } voxbo-1.8.5~svn1246/dbutil/showScoreNames.cpp000066400000000000000000000012441153177201300210540ustar00rootroot00000000000000/****************************************************************************** * Print out all records in score name table ******************************************************************************/ using namespace std; #include "db_util.h" #include "bdb_tab.h" #include #include /* Main function */ int main(int argc, char *argv[]) { if (argc > 2) { printf("Usage: showScoreNames \n"); printf("Default score name db file is: ../env/scorenames.db"); return 0; } string dbFile; if (argc == 1) dbFile = "../env/scorenames.db"; else dbFile = argv[1]; showEnvDB(dbFile); return 0; } voxbo-1.8.5~svn1246/dbutil/showScoreValues.cpp000066400000000000000000000013501153177201300212460ustar00rootroot00000000000000/****************************************************************************** * Print out all records in score value (test results) table ******************************************************************************/ using namespace std; #include "db_util.h" #include "bdb_tab.h" #include #include //#include /* Main function */ int main(int argc, char *argv[]) { if (argc > 2) { printf("Usage: showScoreValues \n"); printf("Default score value db file is: ../env/scorevalues.db"); return 0; } string dbFile; if (argc == 1) dbFile = "../env/scorevalues.db"; else dbFile = argv[1]; showEnvDB(dbFile, mydb::cmp_lex); return 0; } voxbo-1.8.5~svn1246/dbutil/showSystem.cpp000066400000000000000000000012441153177201300203010ustar00rootroot00000000000000/****************************************************************************** * showSystem.cpp: read all records in system table ******************************************************************************/ using namespace std; #include "db_util.h" #include "bdb_tab.h" #include #include /* Main function */ int main(int argc, char* argv[]) { if (argc > 2) { printf("Usage: showSystem \n"); printf("Default system db file is: ../env/system.db"); return 0; } string dbFile; if (argc == 1) dbFile = "../env/system.db"; else dbFile = argv[1]; showEnvDB(dbFile, mydb::cmp_lex); return 0; } voxbo-1.8.5~svn1246/dbutil/showUsers.cpp000066400000000000000000000012011153177201300201070ustar00rootroot00000000000000/****************************************************************************** * Print out all records in user table ******************************************************************************/ using namespace std; #include "db_util.h" #include "bdb_tab.h" #include #include /* Main function */ int main(int argc, char* argv[]) { if (argc > 2) { printf("Usage: showUsers \n"); printf("Default user db file is: ../env/user.db"); return 0; } string dbFile; if (argc == 1) dbFile = "../env/user.db"; else dbFile = argv[1]; showEnvDB(dbFile); return 0; } voxbo-1.8.5~svn1246/dist/000077500000000000000000000000001153177201300150675ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/elements/000077500000000000000000000000001153177201300167035ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/elements/filters/000077500000000000000000000000001153177201300203535ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/elements/filters/Eigen1.ref000066400000000000000000000020751153177201300221650ustar00rootroot00000000000000;VB98 ;REF1 ; ; This is the first Eigenvector from a principal components analysis of ; thirteen hemodynamic responses from different subjects. This ; component explained 0.74 of the variance. Note that the vector has ; been shifted and scaled to facilitate its use as a covariate. ; ; The values represent a 16 second response (i.e., 8 values at a ; TR=2000 msecs). ; ; This vector can be used in conjunction with the second and third ; vectors to create a near-basis set for the analysis of event-related ; fMRI data. See: ; ; Aguirre, Zarahn and D'Esposito (1998) The Variability of Human ; BOLD Hemodynamic Responses. NeuroImage ; ; This vector is also recommended for use as a general representation of ; the impulse response function of the BOLD fMRI system when a subject ; specific response is not available. It is very close in shape to the ; function reported by Boynton et al (1996) and used by Buckner and ; colleagues. ; 0.00000 0.356963 0.904650 0.908452 0.440000 0.0981926 -0.0208208 -0.0397777 voxbo-1.8.5~svn1246/dist/elements/filters/Eigen2.ref000066400000000000000000000014221153177201300221610ustar00rootroot00000000000000;VB98 ;REF1 ; ; This is the second Eigenvector from a principal components analysis of ; thirteen hemodynamic responses from different subjects. This ; component explained 0.22 of the variance. Note that this vector ; has been y-shifted and scaled to facilitate its use as a covariate ; ; The values represent a 16 second response (i.e., 8 values at a ; TR=2000 msecs). ; ; This vector can be used in conjunction with the first and third ; vectors to create a near-basis set for the analysis of event-related ; fMRI data. See: ; ; Aguirre, Zarahn and D'Esposito (1998) The Variability of Human ; BOLD Hemodynamic Responses. NeuroImage ; 0.00000 -0.604037 -0.162439 0.760761 0.993102 0.751719 0.404960 0.327180 voxbo-1.8.5~svn1246/dist/elements/filters/Eigen3.ref000066400000000000000000000014241153177201300221640ustar00rootroot00000000000000;VB98 ;REF1 ; ; This is the third Eigenvector from a principal components analysis of ; thirteen hemodynamic responses from different subjects. This ; component explained 0.017 of the variance. Note that this vector ; has been y-shifted and scaled to facilitate its use as a covariate. ; ; The values represent a 16 second response (i.e., 8 values at a ; TR=2000 msecs). ; ; This vector can be used in conjunction with the first and second ; vectors to create a near-basis set for the analysis of event-related ; fMRI data. See: ; ; Aguirre, Zarahn and D'Esposito (1998) The Variability of Human ; BOLD Hemodynamic Responses. NeuroImage ; 0.00000 0.782884 -0.542431 -0.372256 0.995737 0.0236621 -0.567163 -0.548150 voxbo-1.8.5~svn1246/dist/elements/filters/EmpiricalBlocked_IRF.ref000066400000000000000000000012361153177201300247440ustar00rootroot00000000000000;VB98 ;REF1 ; ; This vector is the putative impulse response function estimated by ; Zarahn et al (1997). The function was obtained by a shift-and-subtract ; approach performed the fMRI signal obtained from the Parietal cortex ; across subjects in a blocked "mentral rotation" experiment. ; ; See: ; ; Zarahn, E., Aguirre, G.K., D'Esposito, M. 1997. A trial-based ; experimental design for fMRI. NeuroImage 6: 122-138. ; ; The values are spaced at a TR=2000 msecs. Thus, the response spans ; 20 seconds ; 0.00000 0.332627 0.800392 0.998362 0.705407 0.167560 -0.178821 -0.184444 -0.0724648 0.00000 voxbo-1.8.5~svn1246/dist/elements/filters/FilterList.txt000066400000000000000000000005701153177201300231770ustar00rootroot00000000000000;VB98 ;TXT1 ; ; This list provides the names and paths of the filters available in the ; filters folder. If you wish to add filters to the matrix design program ; simply add the file to this folder and update this file. ; ; For each filter, the menu name and file name are listed ; First eigenvector Eigen1.ref Blocked IRF EmpiricalBlocked_IRF.ref Poisson Poisson_IRF.refvoxbo-1.8.5~svn1246/dist/elements/filters/Poisson_Deconvolved_IRF.ref000066400000000000000000000005601153177201300255340ustar00rootroot00000000000000;VB98 ;REF1 ; ; This is the vector contained in Poisson_IRF.ref deconvolved with a ; a Gaussian, signma = 1.9 seconds, to account for processing performed ; by Friston and colleagues (1994). ; 0.00000 0.283023 0.716515 0.978979 0.941944 0.710994 0.445827 0.248979 0.124759 0.0743449 0.0332370 0.0485041voxbo-1.8.5~svn1246/dist/elements/filters/Poisson_IRF.ref000066400000000000000000000012551153177201300232060ustar00rootroot00000000000000;VB98 ;REF1 ; ; This vector is a Poisson (parameter=8 secs) function presented by ; Friston et al. (1994) to model the hemodynamic response function. ; ; These values represent time points collected at a TR=2000 msecs ; ; Subsequent work has shown that it is a poor model of the actual response ; so it should not generally be used for the analysis of fMRI data. ; ; see: ; ; Friston, K.J., Jezzard, P., Turner, R. 1994. Analysis of functional MRI ; time-series. Human Brain Mapping 1: 153-171. ; ; 0.00000 0.299804 0.699542 0.966036 0.966036 0.752838 0.468584 0.224933 0.0624991 -0.0277417 -0.0710573 -0.0894336voxbo-1.8.5~svn1246/dist/elements/filters/highres.ref000066400000000000000000000030241153177201300225010ustar00rootroot00000000000000;VB98 ;REF1 ;TR: 100 5.55112e-17 0.00767224 0.0162726 0.025849 0.0364457 0.0481024 0.0608536 0.0747281 0.0897482 0.10593 0.123281 0.141801 0.161484 0.182312 0.204261 0.227297 0.251376 0.276448 0.30245 0.329315 0.356963 0.38531 0.414261 0.443716 0.473569 0.503705 0.534007 0.564352 0.594614 0.624665 0.654374 0.68361 0.712242 0.740139 0.767176 0.793226 0.818169 0.841889 0.864277 0.885229 0.90465 0.922451 0.938554 0.952889 0.965396 0.976025 0.984737 0.991502 0.996304 0.999136 1 0.998913 0.995897 0.990989 0.984232 0.975681 0.965398 0.953452 0.939923 0.924892 0.908452 0.890696 0.871725 0.851641 0.830549 0.808556 0.78577 0.7623 0.738253 0.713734 0.688848 0.663695 0.638375 0.61298 0.5876 0.562319 0.537218 0.51237 0.487844 0.463702 0.44 0.41679 0.394115 0.372016 0.350523 0.329666 0.309467 0.289942 0.271104 0.25296 0.235516 0.218771 0.202721 0.187361 0.172683 0.158674 0.145324 0.132616 0.120536 0.109067 0.0981926 0.0878945 0.0781552 0.0689569 0.0602817 0.0521123 0.0444312 0.0372216 0.0304668 0.0241507 0.0182571 0.0127706 0.00767572 0.00295715 -0.00140033 -0.00541187 -0.00909271 -0.0124583 -0.0155242 -0.0183063 -0.0208208 -0.0230841 -0.025113 -0.0269245 -0.0285358 -0.0299644 -0.0312277 -0.0323428 -0.0333269 -0.0341965 -0.0349674 -0.0356548 -0.0362724 -0.0368327 -0.0373465 -0.0378227 -0.0382678 -0.038686 -0.0390787 -0.0394442 -0.0397777 -0.0400708 -0.0403115 -0.0404842 -0.0405693 -0.0405433 -0.0403786 -0.0400439 -0.039504 -0.0387199 -0.0376493 -0.0362464 -0.0344627 -0.0322468 -0.0295455 -0.0263035 -0.0224645 -0.0179715 -0.0127673 -0.00679528 voxbo-1.8.5~svn1246/dist/elements/noisemodels/000077500000000000000000000000001153177201300212245ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/elements/noisemodels/NoiseModelsList.txt000066400000000000000000000007071153177201300250460ustar00rootroot00000000000000;VB98 ;TXT1 ; ; This list provides the names and paths of the noise models available in the ; noise models folder. If you wish to add models to the matrix design program ; simply add the file to this folder and update this file. ; ; For each model, the menu name and file name are listed ; unsmooth, no GSCV unsmooth_params.ref smooth, no GSCV smooth_params.ref unsmooth, with GSCV unsmooth__GCV_params.ref smooth, with GSCV smooth__GCV_params.ref voxbo-1.8.5~svn1246/dist/elements/noisemodels/smooth__GCV_params.ref000066400000000000000000000025631153177201300254420ustar00rootroot00000000000000;VB98 ;REF1 ; ; SMOOTHED GLOBAL SIGNAL COVARIATE INCLUDED ; ; These three parameters define the shape of a 1/f noise curve. They were ; derived from the square root of the grand average power spectrum from 13 ; subjects scanned under the null-hypothesis. This curve can be used ; as a model of the intrinsic autocorrelation present in BOLD fMRI data ; collected under the null-hypothesis. Typically, this representation is ; placed within the K matrix of the GLM of Worsley and Friston (1995). ; ; For these values, the data were smoothed 3 voxels FWHM, and the effect of ; the global signal was removed. ; ; The values (k1, k2, k3) correspond to steepness, y-offset, and x-offset, ; respectively. The equation that these parameters are used within is: ; ; 1 ; a(w) = ---------------- + k2 ; k1*( w + k3 ) ; ; For more details, see: ; ; Zarahn, E., Aguirre, G.K., DUEsposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. I. Spatially unsmoothed ; data collected under null-hypothesis conditions. ; Neuroimage 5: 179-197. ; ; and ; ; Aguirre G.K., Zarahn, E., D'Esposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. II. Spatially smoothed ; data collected under null-hypothesis and experimental conditions. ; Neuroimage 5: 199-212. ; 5981.0 0.01006 0.00289 voxbo-1.8.5~svn1246/dist/elements/noisemodels/smooth_params.ref000066400000000000000000000025441153177201300246030ustar00rootroot00000000000000;VB98 ;REF1 ; ; SMOOTHED NO GLOBAL SIGNAL COVARIATE ; ; These three parameters define the shape of a 1/f noise curve. They were ; derived from the square root of the grand average power spectrum from 13 ; subjects scanned under the null-hypothesis. This curve can be used ; as a model of the intrinsic autocorrelation present in BOLD fMRI data ; collected under the null-hypothesis. Typically, this representation is ; placed within the K matrix of the GLM of Worsley and Friston (1995). ; ; For these values, the data were smoothed 3 voxels FWHM, but no global ; signal covariate was included. ; ; The values (k1, k2, k3) correspond to steepness, y-offset, and x-offset, ; respectively. The equation that these parameters are used within is: ; ; 1 ; a(w) = ---------------- + k2 ; k1*( w + k3 ) ; ; For more details, see: ; ; Zarahn, E., Aguirre, G.K., DUEsposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. I. Spatially unsmoothed ; data collected under null-hypothesis conditions. ; Neuroimage 5: 179-197. ; ; and ; ; Aguirre G.K., Zarahn, E., D'Esposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. II. Spatially smoothed ; data collected under null-hypothesis and experimental conditions. ; Neuroimage 5: 199-212. ; 2527 .00899 .0101 voxbo-1.8.5~svn1246/dist/elements/noisemodels/unsmooth__GCV_params.ref000066400000000000000000000025531153177201300260040ustar00rootroot00000000000000;VB98 ;REF1 ; ; UNSMOOTHED GLOBAL SIGNAL COVARIATE INCLUDED ; ; These three parameters define the shape of a 1/f noise curve. They were ; derived from the square root of the grand average power spectrum from 13 ; subjects scanned under the null-hypothesis. This curve can be used ; as a model of the intrinsic autocorrelation present in BOLD fMRI data ; collected under the null-hypothesis. Typically, this representation is ; placed within the K matrix of the GLM of Worsley and Friston (1995). ; ; For these values, the data were NOT smoothed but did have the effect of the ; global signal removed. ; ; The values (k1, k2, k3) correspond to steepness, y-offset, and x-offset, ; respectively. The equation that these parameters are used within is: ; ; 1 ; a(w) = ---------------- + k2 ; k1*( w + k3 ) ; ; For more details, see: ; ; Zarahn, E., Aguirre, G.K., DUEsposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. I. Spatially unsmoothed ; data collected under null-hypothesis conditions. ; Neuroimage 5: 179-197. ; ; and ; ; Aguirre G.K., Zarahn, E., D'Esposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. II. Spatially smoothed ; data collected under null-hypothesis and experimental conditions. ; Neuroimage 5: 199-212. ; 113.557 1.92395 -0.000596094 voxbo-1.8.5~svn1246/dist/elements/noisemodels/unsmooth_params.ref000066400000000000000000000025311153177201300251420ustar00rootroot00000000000000;VB98 ;REF1 ; ; UNSMOOTHED NO GLOBAL SIGNAL COVARIATE ; ; These three parameters define the shape of a 1/f noise curve. They were ; derived from the square root of the grand average power spectrum from 13 ; subjects scanned under the null-hypothesis. This curve can be used ; as a model of the intrinsic autocorrelation present in BOLD fMRI data ; collected under the null-hypothesis. Typically, this representation is ; placed within the K matrix of the GLM of Worsley and Friston (1995). ; ; For these values, the data are unsmoothed and no global signal covariate ; was included. ; ; The values (k1, k2, k3) correspond to steepness, y-offset, and x-offset, ; respectively. The equation that these parameters are used within is: ; ; 1 ; a(w) = ---------------- + k2 ; k1*( w + k3 ) ; ; For more details, see: ; ; Zarahn, E., Aguirre, G.K., DUEsposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. I. Spatially unsmoothed ; data collected under null-hypothesis conditions. ; Neuroimage 5: 179-197. ; ; and ; ; Aguirre G.K., Zarahn, E., D'Esposito, M. (1997) Empirical ; analyses of BOLD fMRI statistics. II. Spatially smoothed ; data collected under null-hypothesis and experimental conditions. ; Neuroimage 5: 199-212. ; 76.9778 1.91129 0.000230495 voxbo-1.8.5~svn1246/dist/elements/templates/000077500000000000000000000000001153177201300207015ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/elements/templates/ch2_license.txt000066400000000000000000000012441153177201300236210ustar00rootroot00000000000000Copyright (C) 1993-2004 Louis Collins, 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. The authors are not responsible for any data loss, equipment damage, property loss, or injury to subjects or patients resulting from the use or misuse of this software package. voxbo-1.8.5~svn1246/dist/etc/000077500000000000000000000000001153177201300156425ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/etc/defaults000066400000000000000000000050421153177201300173750ustar00rootroot00000000000000 # If you're not running VoxBo in cluster mode, you can ignore this # file. The defaults file sets variables and parameters that are used # by the scheduler, by the servers, and by voxq. # server -- nickname and fqdn for each server server server1 server1.myinstitution.edu # sendmail -- full path to sendmail or similar sendmail /usr/sbin/sendmail # email address of sysadmin, in case of serious problem sysadmin nobody@nowhere.com # login names of those who should have big privileges within voxbo superusers root voxbo # how long should the scheduler sleep, in seconds, between checking the queue queuedelay 3 # the server port is the port your server listens to (defaults to # 6004), as specified in your services file # serverport 6004 # Each checkdir directive specifies a directory that *must* contain # something on each server for the machine to receive jobs. This # helps insulate the scheduler from NFS problems and things like that. # checkdir /critical/dir1 # checkdir /critical/dir2 # Each jobtypes line specifies the name of a jobtype definition # directory from VOXBODIR/etc. If you need machine-specific jobtypes # files (e.g., some executables have different paths on different # machines), you can do that here. Just make sure each machine # handles all the jobtypes it might be sent. jobtypes jobtypes # username for the voxbo user, defaults to "voxbo" #voxbouser voxbo # benchmarks (undocumented, but pretty cool) benchmark realign 3600 cp /jet/admin/run.tes /tmp;realign /tmp/run.tes #benchmark lstmp 60 ls -lR /tmp # environment variables under which all jobs run setenv IDL_PATH=+/usr/local/rsi/idl/lib:/usr/local/VoxBo/pros: setenv IDL_UTILS=/usr/local/rsi/idl_utils #setenv LM_LICENSE_FILE=/usr/local/rsi/license/license.dat setenv PATH=/usr/local/VoxBo/bin:/bin:/usr/bin:/usr/local/bin setenv MATLABPATH=/usr/local/spm2 # SPM2 setenv SPM2_PATH=/usr/local/spm2 setenv SPM2_MATLAB_CMD=/usr/local/bin/matlab12 -nodisplay -nojvm -c 27000@aleida.uphs.upenn.edu # SPM5 setenv SPM5_PATH=/usr/local/spm5 setenv SPM5_MATLAB_CMD=/usr/local/bin/matlab14sp3 -nodisplay -nojvm # FSL-related setenv FSLDIR=/usr/local/fsl setenv FSLOUTPUTTYPE=NIFTI_GZ setenv FSLMULTIFILEQUIT=TRUE setenv FSLTCLSH=/usr/local/fsl/bin/tclsh setenv FSLWISH=/usr/local/fsl/bin/wish setenv FSLGNUPLOT=/usr/local/fsl/bin/gnuplot setenv FSLDISPLAY=/usr/local/fsl/bin/display setenv FSLCONVERT=/usr/local/fsl/bin/convert setenv FSLBROWSER=$FSLDIR/tcl/fslwebbrowser # ITK-related setenv ITKBIN=/home/jasmuth/ITK/bin/ # PERL-related setenv PERLLIB=/usr/local/lib/perl5/site_perl/5.8.8 voxbo-1.8.5~svn1246/dist/etc/jobtypes/000077500000000000000000000000001153177201300175015ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/etc/jobtypes/assembleps.vjt000066400000000000000000000005601153177201300223650ustar00rootroot00000000000000 shortname assembleps argument name=stem argdesc=directory containing glm information type=string default=none low=none high=none end argument name=steps argdesc=number of steps in regression type=long default=1 low=none high=none end description Assembles partial ref files. invocation commandline command assembleps -m $(stem) -s $(steps) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/calcgs.vjt000066400000000000000000000004621153177201300214640ustar00rootroot00000000000000 shortname calcgs description Calculate global signal of a 4D volume invocation commandline argument name=infile argdesc=4D data file for which we'd like global signal calculated type=string end argument name=notused argdesc=unused argument type=string end command calcgs -i $(infile) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/calcps.vjt000066400000000000000000000005061153177201300214740ustar00rootroot00000000000000 shortname calcps description Calculate power spectrum for a 4D volume invocation commandline argument name=infile type=string argdesc=4D data file for which we'd like the power spectrum calculated type=string end argument name=notused argdesc=unused argument type=string end command calcps -i $(infile) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/comptraces.vjt000066400000000000000000000003621153177201300223670ustar00rootroot00000000000000 shortname comptraces description Make the traces file. invocation commandline argument name=stem argdesc=directory containing glm information type=string default=none low=none high=none end command comptraces -m $(stem) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/extractref.vjt000066400000000000000000000004321153177201300223740ustar00rootroot00000000000000shortname extractref description Extract Reference Cube invocation commandline argument name=tesname argdesc=tes file name for inout data type=string end argument name=cubname argdesc=output cub file name type=string end command tes2cub $(tesname) $(cubname) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/idl.vjt000066400000000000000000000004441153177201300210000ustar00rootroot00000000000000 shortname idl description An IDL job of unspecified nature invocation script requires cpu requires idl 6 argument name=commandline argdesc=full IDL command line type=string end command idl | @vsb | .run VoxBo_Jobs.pro | code=999 | code=runjob('idl',"$(commandline)") | exit,status=code voxbo-1.8.5~svn1246/dist/etc/jobtypes/makematk.vjt000066400000000000000000000003531153177201300220210ustar00rootroot00000000000000 shortname makematk description Make the K matrix. invocation commandline argument name=stem argdesc=directory containing glm information type=string default=none low=none high=none end command makematk -m $(stem) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/makematkg.vjt000066400000000000000000000003561153177201300221730ustar00rootroot00000000000000 shortname makematkg description Make the KG matrix. invocation commandline argument name=stem argdesc=directory containing glm information type=string default=none low=none high=none end command makematkg -m $(stem) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matadd.vjt000066400000000000000000000007151153177201300214630ustar00rootroot00000000000000shortname matadd description Efficient Matrix Operations in c (compute X+Y) invocation commandline argument name=in1 argdesc=first matrix type=string default=none low=none high=none end argument name=in2 argdesc=second matrix type=string default=none low=none high=none end argument name=out argdesc=sum of inputmatrix1 and inputmatrix2 type=string default=none low=none high=none end command vbmm2 -add $(in1) $(in2) $(out) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matf3.vjt000066400000000000000000000005571153177201300212470ustar00rootroot00000000000000shortname matf3 description create F3 matrix (V*KG*invert(KTtKG) invocation commandline argument name=vmatrix argdesc=first matrix type=string end invocation commandline argument name=kgmatrix argdesc=second matrix type=string end argument name=outfile argdesc=output matrix type=string end command vbmm2 -f3 $(vmatrix) $(kgmatrix) $(outfile) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matident.vjt000066400000000000000000000005431153177201300220350ustar00rootroot00000000000000shortname matident description Efficient Matrix Operations in c (create I) invocation commandline argument name=name argdesc=name of identity matrix to create type=string default=none argument name=size argdesc=size of identity matrix to create type=long default=none low=none high=none end command vbmm2 -ident $(name) $(size) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matimxy.vjt000066400000000000000000000006661153177201300217260ustar00rootroot00000000000000shortname matimxy description Efficient Matrix Operations in c (compute I-XY) invocation commandline argument name=in1 argdesc=first matrix type=string default=none low=none high=none end argument name=in2 argdesc=second matrix type=string default=none low=none high=none end argument name=out argdesc=I-XY in core type=string default=none low=none high=none end command vbmm2 -imxy $(in1) $(in2) $(out) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matinvert.vjt000066400000000000000000000005221153177201300222360ustar00rootroot00000000000000shortname matinvert description Efficient Matrix Operations in c (compute X^-1) invocation commandline argument name=in argdesc=matrix before inversion type=string default=none argument name=out argdesc=matrix after inversion type=string default=none low=none high=none end command vbmm2 -invert $(in) $(out) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matjoincols.vjt000066400000000000000000000004321153177201300225470ustar00rootroot00000000000000shortname matjoincols description Efficient Matrix Operations in c (join columns) invocation commandline argument name=out argdesc=assemble out from available parts type=string default=none low=none high=none end command /usr/local/VoxBo/bin/vbmm2 -assemblecols $(out) voxbo-1.8.5~svn1246/dist/etc/jobtypes/matlabcommand.vjt000066400000000000000000000007521153177201300230310ustar00rootroot00000000000000 shortname matlabcommand description execute any matlab function requires cpu requires matlab invocation script setenv MATLABPATH=$(SPM2_PATH) setenv HOME=/tmp argument name=command argdesc=the entire line to be run from the within matlab # type=compound means it aggregates all the provided arguments into one # type=compound end argument name=path argdesc=prepend to matlab path type=string default=none end command $(SPM2_MATLAB_CMD) | path('$(path)',path) | $(command) | exit voxbo-1.8.5~svn1246/dist/etc/jobtypes/matmerge.vjt000066400000000000000000000003751153177201300220340ustar00rootroot00000000000000shortname matmerge description Efficient Matrix Operations in c (join columns) invocation commandline argument name=out argdesc=assemble out from available parts type=string default=none low=none high=none end command vbmm2 -assemblecols $(out) voxbo-1.8.5~svn1246/dist/etc/jobtypes/matpinv.vjt000066400000000000000000000005371153177201300217110ustar00rootroot00000000000000shortname matpinv description Efficient Matrix Operations in c (compute pinv(X)) invocation commandline argument name=in argdesc=matrix before pseudo-inversion type=string default=none argument name=out argdesc=matrix after pseudo-inversion type=string default=none low=none high=none end command vbmm2 -pinv $(in) $(out) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matsubtract.vjt000066400000000000000000000007331153177201300225620ustar00rootroot00000000000000shortname matsubtract description Efficient Matrix Operations in c (compute X-Y) invocation commandline argument name=in1 argdesc=first matrix type=string default=none low=none high=none end argument name=in2 argdesc=second matrix type=string default=none low=none high=none end argument name=out argdesc=difference of inputmatrix1 and inputmatrix2 type=string default=none low=none high=none end command vbmm2 -subtract $(in1) $(in2) $(out) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matxtx.vjt000066400000000000000000000011251153177201300215520ustar00rootroot00000000000000shortname matxtx description Efficient Matrix Operations in c (compute X'X) invocation commandline argument name=in argdesc=first matrix type=string default=none low=none high=none end argument name=out argdesc=matrix representing (inputmatrix)'(inputmatrix) type=string default=none low=none high=none end argument name=col1 argdesc=first selected column type=string default=none low=none high=none end argument name=col2 argdesc=second selected column type=string default=none low=none high=none end command vbmm2 -xty $(in) $(in) $(out) $(col1) $(col2) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matxx.vjt000066400000000000000000000011211153177201300213620ustar00rootroot00000000000000shortname matxx description Efficient Matrix Operations in c (compute XX) invocation commandline argument name=in argdesc=first matrix type=string default=none low=none high=none end argument name=out argdesc=matrix representing (inputmatrix)(inputmatrix) type=string default=none low=none high=none end argument name=col1 argdesc=first selected column type=string default=none low=none high=none end argument name=col2 argdesc=second selected column type=string default=none low=none high=none end command vbmm2 -xy $(in) $(in) $(out) $(col1) $(col2) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matxxt.vjt000066400000000000000000000011231153177201300215500ustar00rootroot00000000000000shortname matxxt description Efficient Matrix Operations in c (compute XX') invocation commandline argument name=in argdesc=first matrix type=string default=none low=none high=none end argument name=out argdesc=matrix representing (inputmatrix)(inputmatrix)' type=string default=none low=none high=none end argument name=col1 argdesc=first selected column type=string default=none low=none high=none end argument name=col2 argdesc=second selected column type=string default=none low=none high=none end command vbmm2 -xyt $(in) $(in) $(out) $(col1) $(col2) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matxy.vjt000066400000000000000000000012461153177201300213730ustar00rootroot00000000000000shortname matxy description Efficient Matrix Operations in c (compute XY) invocation commandline argument name=in1 argdesc=first matrix type=string default=none low=none high=none end invocation commandline argument name=in2 argdesc=second matrix type=string default=none low=none high=none end argument name=out argdesc=output matrix type=string default=none low=none high=none end argument name=col1 argdesc=first selected column type=string default=none low=none high=none end argument name=col2 argdesc=second selected column type=string default=none low=none high=none end command vbmm2 -xy $(in1) $(in2) $(out) $(col1) $(col2) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/matzeros.vjt000066400000000000000000000007271153177201300221000ustar00rootroot00000000000000shortname matzeros description Efficient Matrix Operations in c (create empty matrix) invocation commandline argument name=name argdesc=file name of matrix to create type=string default=none low=none high=none end argument name=cols argdesc=number of columns type=long default=none low=none high=none end argument name=rows argdesc=number of rows type=long default=none low=none high=none end command vbmm2 -zeros $(name) $(cols) $(rows) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/mni_n3.vjt000066400000000000000000000011451153177201300214120ustar00rootroot00000000000000shortname mni_n3 description MNI's N3 tool for inhomogeneity correction in MRI images invocation script requires cpu argument name=infile argdesc=input file type=string end argument name=outfile argdesc=output file type=string end command vbconv $(infile) $(infile).nii command /bin/rm $(infile).mnc command nii2mnc $(infile).nii $(infile).mnc command nu_correct -clobber $(infile).mnc tmp_$(infile).mnc command /bin/rm $(outfile).nii command mnc2nii tmp_$(infile).mnc $(outfile).nii command vbconv $(outfile).nii $(outfile) command /bin/rm -f tmp_$(infile).mnc $(infile).mnc $(infile).nii $(outfile).nii voxbo-1.8.5~svn1246/dist/etc/jobtypes/newprep.vjt000066400000000000000000000004271153177201300217110ustar00rootroot00000000000000 shortname newprep description run the newprep script to prepare the anatomy directory invocation commandline argument name=adir argdesc=directory containing Anatomy directories type=string default=none low=none high=none end command newprep.sh $(adir) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/notify.vjt000066400000000000000000000001411153177201300215320ustar00rootroot00000000000000shortname notify description Notify user of status of job invocation internal requires mailagent voxbo-1.8.5~svn1246/dist/etc/jobtypes/orient.vjt000066400000000000000000000005541153177201300215320ustar00rootroot00000000000000shortname orient description Orient data invocation commandline requires cpu argument name=infile argdesc=input cub or tes type=string end argument name=outfile argdesc=output re-oriented file name type=string end argument name=orientation argdesc=orientation of output cub/tes file type=string end command vborient $(infile) $(outfile) $(orientation) voxbo-1.8.5~svn1246/dist/etc/jobtypes/realign.vjt000066400000000000000000000007621153177201300216540ustar00rootroot00000000000000shortname realign description Motion correction ported from SPM96 invocation commandline argument name=infile argdesc=file to be realigned type=string end argument name=outfile argdesc=output file after realignment type=string end argument name=tolerance argdesc=tolerance for in voxels type=double default=.5 low=none high=none end argument name=refimage argdesc=reference image type=string end command realign -r $(refimage) -o $(outfile) -t $(tolerance) $(infile) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/sample.vjt000066400000000000000000000027071153177201300215150ustar00rootroot00000000000000 # sample.vjt # sample VoxBo jobtype file # many things for which you might want to define a VoxBo jobtype can # be accomplished via the shellcommand jobtype. but if you create # your own jobtype, you can include some interaction with an # interpreter (e.g., MATLAB or IDL), and you can customize the jobtype # a little more, chain commands, and have the jobtype automatically # included in VoxBo's interfaces. # shortname is just the name of the jobtype, should usually match the filename # description is free text, best kept succinct # invocation is "script" except for internal jobtypes ("commandline" also ok) shortname sample description sample jobtype invocation script requires cpu setenv foo=bar # each argument should be represented with a paragraph like the below # name: the name of the argument # argdesc: a brief text description of the argument # type: a single token describing the role; "input" and "output" may # be treated specially, and "compound" indicates that all provided # arguments should be aggregated into one string # default: default value argument name=command argdesc=text description type=compound default=ls end # here's the actual command or commands # variable replacement is done with $(varname) # multiple commands can be listed, and will be executed in order # script lines (for text input to the command) follow the command # and are prepended with "|" command /bin/sh -c "$(command)" command matlab | spm | exit voxbo-1.8.5~svn1246/dist/etc/jobtypes/setorigin.vjt000066400000000000000000000004111153177201300222250ustar00rootroot00000000000000 shortname setorigin description set appropriate origin invocation commandline argument name=infile argdesc=input volume type=string end argument name=origin argdesc=origin (should be three numbers) type=string end command setorigin -c $(infile) $(origin) voxbo-1.8.5~svn1246/dist/etc/jobtypes/shellcommand.vjt000066400000000000000000000004601153177201300226740ustar00rootroot00000000000000 shortname shellcommand description execute any command line invocation commandline argument name=command argdesc=the entire line to be run from the command line # type=compound means it aggregates all the provided arguments into one # type=compound end command /bin/sh -c "$(command)" requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/shellcommand32.vjt000066400000000000000000000005011153177201300230350ustar00rootroot00000000000000 shortname shellcommand32 description execute any command line invocation commandline argument name=command argdesc=the entire line to be run from the command line # type=compound means it aggregates all the provided arguments into one # type=compound end command /bin/sh -c "$(command)" requires cpu requires 32bit voxbo-1.8.5~svn1246/dist/etc/jobtypes/shellcommand64.vjt000066400000000000000000000005011153177201300230420ustar00rootroot00000000000000 shortname shellcommand64 description execute any command line invocation commandline argument name=command argdesc=the entire line to be run from the command line # type=compound means it aggregates all the provided arguments into one # type=compound end command /bin/sh -c "$(command)" requires cpu requires 64bit voxbo-1.8.5~svn1246/dist/etc/jobtypes/slicecorrect.vjt000066400000000000000000000005541153177201300227130ustar00rootroot00000000000000 shortname slicecorrect description interpolate to correct for slice acquisition order invocation commandline argument name=infile argdesc=4D volums to correct type=string end argument name=outfile argdesc=output file type=string end argument name=notused argdesc=unused argument type=string end command sliceacq -i $(infile) -o $(outfile) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/smooth.vjt000066400000000000000000000007331153177201300215420ustar00rootroot00000000000000 shortname smooth description Gaussian smoothing invocation script requires cpu argument name=infile argdesc=input file type=string end argument name=outfile argdesc=output file type=string end argument name=fwhm_x argdesc=fwhm_x in voxels type=string end argument name=fwhm_y argdesc=fwhm_y in voxels type=string end argument name=fwhm_z argdesc=fwhm_z in voxels type=string end command vbsmooth -o $(outfile) -vox $(fwhm_x) $(fwhm_y) $(fwhm_z) $(infile) voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_import_dicom.vjt000066400000000000000000000013751153177201300236620ustar00rootroot00000000000000shortname spm2_import_dicom description SPM2 convert dicom to analyze with pose matrix invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=$(SPM2_PATH) setenv HOME=/tmp argument name=sdir argdesc=study root directory type=string default=none end argument name=dicomdir argdesc=input dicom from here type=string default=none end argument name=outdir argdesc=output analyze to here type=string default=none end command /bin/sh -c "echo sdir=$(sdir)" command /bin/sh -c "echo dicomdir=$(dicomdir)" command /bin/sh -c "echo outdir=$(outdir)" command $(SPM2_MATLAB_CMD) | cd $(sdir) | path('/home/jasmuth/scripts/spm',path) | path('/home/jasmuth/matlab',path) | import_dicom_4d('$(dicomdir)','$(outdir)') | exit voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_norm_apply3d.vjt000066400000000000000000000036031153177201300236000ustar00rootroot00000000000000shortname spm2_norm_apply3d description SPM2 Normalization invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=$(SPM2_PATH) setenv HOME=/tmp argument name=dir argdesc=directory type=string default=none low=none high=none end argument name=paramfile argdesc=file containing params type=string default=none low=none high=none end argument name=infile argdesc=input cub file name type=string default=none low=none high=none end argument name=outfile argdesc=output cub file name type=string default=none low=none high=none end argument name=vox_x argdesc=vox_x size type=long default=none low=none high=none end argument name=vox_y argdesc=vox_y size type=long default=none low=none high=none end argument name=vox_z argdesc=vox_z size type=long default=none low=none high=none end argument name=bb argdesc=bounding box type=string default=none low=none high=none end command cp -v $(dir)/$(infile) $(dir)/$(infile)_hdrsave.cub command mkdir -p $(dir)/$(infile)_imgdir command vb2img $(dir)/$(infile) $(dir)/$(infile)_imgdir/$(infile)_tmp.img command $(SPM2_MATLAB_CMD) | cd $(dir) | spm_defaults; | global defaults; | defaults.normalise.write.vox=[$(vox_x) $(vox_y) $(vox_z)]; | defaults.normalise.write.interp=7; | defaults.normalise.write.wrap=[0 0 0]; | defaults.normalise.write.bb=$(bb); | P=spm_get('Files','$(infile)_imgdir','$(infile)_tmp.img') | V=spm_vol(P); | for i=1:length(V) | spm_write_sn(V(i),'$(paramfile)',defaults.normalise.write) | end; | exit command /bin/rm -f $(dir)/$(outfile) command vb2cub -n $(dir)/$(infile)_imgdir/w$(infile)_tmp.img $(dir)/$(outfile) command vbhdr -c $(dir)/$(infile)_hdrsave.cub $(dir)/$(outfile) command /bin/rm -rf $(dir)/$(infile)_imgdir command /bin/rm $(dir)/$(infile)_hdrsave.cub command vbhdr -a "spm2_norm_date: {DATE}" $(dir)/$(outfile) command test -e $(dir)/$(outfile) voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_norm_apply3d_a.vjt000066400000000000000000000037351153177201300241060ustar00rootroot00000000000000shortname spm2_norm_apply3d_a description SPM2 Normalization invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=/usr/local/spm2 setenv HOME=/tmp argument name=dir argdesc=directory type=string default=none low=none high=none end argument name=paramfile argdesc=file containing params type=string default=none low=none high=none end argument name=infile argdesc=input cub file name type=string default=none low=none high=none end argument name=outfile argdesc=output cub file name type=string default=none low=none high=none end argument name=vox_x argdesc=vox_x size type=long default=none low=none high=none end argument name=vox_y argdesc=vox_y size type=long default=none low=none high=none end argument name=vox_z argdesc=vox_z size type=long default=none low=none high=none end argument name=bb argdesc=bounding box type=string default=none low=none high=none end command cp -v $(dir)/$(infile) $(dir)/$(infile)_hdrsave.cub command mkdir -p $(dir)/$(infile)_imgdir command vb2img $(dir)/$(infile) $(dir)/$(infile)_imgdir/$(infile)_tmp.img command /usr/local/bin/matlab12 -nodisplay -nojvm -c 27000@aleida.uphs.upenn.edu | cd $(dir)/$(infile)_imgdir | spm_defaults; | global defaults; | defaults.normalise.write.vox=[$(vox_x) $(vox_y) $(vox_z)]; | defaults.normalise.write.interp=7; | defaults.normalise.write.wrap=[0 0 0]; | defaults.normalise.write.bb=$(bb); | defaults.normalise.estimate.cutoff=Inf | P=spm_get('Files','$(dir)/$(infile)_imgdir','$(infile)_tmp.img') | V=spm_vol(P); | for i=1:length(V) | spm_write_sn(V(i),'$(paramfile)',defaults.normalise.write) | end; | exit command /bin/rm -f $(dir)/$(outfile) command vb2cub -n $(dir)/$(infile)_imgdir/w$(infile)_tmp.img $(dir)/$(outfile) command vbhdr -c $(dir)/$(infile)_hdrsave.cub $(dir)/$(outfile) command /bin/rm -rf $(dir)/$(infile)_imgdir command /bin/rm $(dir)/$(infile)_hdrsave.cub command vbhdr -a "spm2_norm_date: {DATE}" $(dir)/$(outfile) voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_norm_apply4d.vjt000066400000000000000000000035111153177201300235770ustar00rootroot00000000000000 shortname spm2_norm_apply4d description SPM2 Normalization invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=$(SPM2_PATH) setenv HOME=/tmp argument name=dir argdesc=directory type=string default=none low=none high=none end argument name=paramfile argdesc=file containing params type=string default=none low=none high=none end argument name=infile argdesc=input 4D file name type=string default=none low=none high=none end argument name=outfile argdesc=output 4D file name type=string default=none low=none high=none end argument name=vox_x argdesc=vox_x size type=long default=none low=none high=none end argument name=vox_y argdesc=vox_y size type=long default=none low=none high=none end argument name=vox_z argdesc=vox_z size type=long default=none low=none high=none end argument name=bb argdesc=bounding box type=string default=none low=none high=none end # command tes2cub $(dir)/$(infile) $(dir)/$(infile)_hdrsave.cub command vbconv $(dir)/$(infile) $(dir)/$(infile)_hdrsave.tes -i 0 command vb2imgs $(dir)/$(infile) $(dir)/$(infile)_tmp command $(SPM2_MATLAB_CMD) | cd $(dir) | spm_defaults; | global defaults; | defaults.normalise.write.vox=[$(vox_x) $(vox_y) $(vox_z)]; | defaults.normalise.write.interp=7; | defaults.normalise.write.wrap=[0 0 0]; | defaults.normalise.write.bb=$(bb); | P=spm_get('files','$(dir)/$(infile)_tmp','$(infile)_tmp*.img'); | V=spm_vol(P); | for i=1:length(V) | spm_write_sn(V(i),'$(paramfile)',defaults.normalise.write) | end; | exit command vb2tes -n $(dir)/$(infile)_tmp/w$(infile)_tmp $(dir)/$(outfile) command vbhdr -c $(dir)/$(infile)_hdrsave.tes $(dir)/$(outfile) command /bin/rm -rf $(dir)/$(infile)_tmp $(dir)/$(infile)_hdrsave.tes command vbhdr -a "spm2_norm_date: {DATE}" $(dir)/$(outfile) command test -e $(dir)/$(outfile) voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_norm_apply4d_a.vjt000066400000000000000000000036141153177201300241030ustar00rootroot00000000000000 shortname spm2_norm_apply4d_a description SPM2 Normalization invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=/usr/local/spm2 setenv HOME=/tmp argument name=dir argdesc=directory type=string default=none low=none high=none end argument name=paramfile argdesc=file containing params type=string default=none low=none high=none end argument name=infile argdesc=input 4D file name type=string default=none low=none high=none end argument name=outfile argdesc=output 4D file name type=string default=none low=none high=none end argument name=vox_x argdesc=vox_x size type=long default=none low=none high=none end argument name=vox_y argdesc=vox_y size type=long default=none low=none high=none end argument name=vox_z argdesc=vox_z size type=long default=none low=none high=none end argument name=bb argdesc=bounding box type=string default=none low=none high=none end # command tes2cub $(dir)/$(infile) $(dir)/$(infile)_hdrsave.cub command vbconv $(dir)/$(infile) $(dir)/$(infile)_hdrsave.tes -i 0 command vb2imgs $(dir)/$(infile) $(dir)/$(infile)_tmp command /usr/local/bin/matlab12 -nodisplay -nojvm -c 27000@aleida.uphs.upenn.edu | cd $(dir) | spm_defaults; | global defaults; | defaults.normalise.write.vox=[$(vox_x) $(vox_y) $(vox_z)]; | defaults.normalise.write.interp=7; | defaults.normalise.write.wrap=[0 0 0]; | defaults.normalise.write.bb=$(bb); | defaults.normalise.estimate.cutoff=Inf | P=spm_get('files','$(dir)/$(infile)_tmp','$(infile)_tmp*.img'); | V=spm_vol(P); | for i=1:length(V) | spm_write_sn(V(i),'$(paramfile)',defaults.normalise.write) | end; | exit command vb2tes -n $(dir)/$(infile)_tmp/w$(infile)_tmp $(dir)/$(outfile) command vbhdr -c $(dir)/$(infile)_hdrsave.tes $(dir)/$(outfile) command /bin/rm -rf $(dir)/$(infile)_tmp $(dir)/$(infile)_hdrsave.tes command vbhdr -a "spm2_norm_date: {DATE}" $(dir)/$(outfile) voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_norm_calc.vjt000066400000000000000000000034621153177201300231310ustar00rootroot00000000000000 shortname spm2_norm_calc description SPM2 Normalization -- calculate parameters invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=$(SPM2_PATH) setenv HOME=/tmp argument name=dir argdesc=directory type=string default=none low=none high=none end argument name=paramfile argdesc=file containing params type=string default=none low=none high=none end argument name=infile argdesc=your volume type=string default=none low=none high=none end argument name=refvolume argdesc=reference volume type=string default=none low=none high=none end argument name=vox_x argdesc=vox_x size type=long default=none low=none high=none end argument name=vox_y argdesc=vox_y size type=long default=none low=none high=none end argument name=vox_z argdesc=vox_z size type=long default=none low=none high=none end argument name=bb argdesc=bounding box type=string default=none low=none high=none end command vb2img $(dir)/$(infile) $(dir)/tmp_spm2norm.img # for fun, add -logfile /jet/kimberg/test/spmnorm/matlab.log command $(SPM2_MATLAB_CMD) | spm_defaults; | global defaults; | cd $(dir); | defaults.normalise.write.vox=[$(vox_x) $(vox_y) $(vox_z)]; | defaults.normalise.write.interp=7; | defaults.normalise.write.wrap=[0 0 0]; | defaults.normalise.write.bb=$(bb); | VG=spm_vol('$(refvolume)') | V=spm_vol('$(dir)/tmp_spm2norm.img') | params=spm_normalise(VG,V,'$(dir)/$(paramfile)','','',defaults.normalise.estimate); | msk=spm_write_sn(V,params,defaults.normalise.write,'mask'); | spm_write_sn(V,params,defaults.normalise.write,msk); | exit command vb2cub $(dir)/wtmp_spm2norm.img $(dir)/n$(infile) command /bin/rm $(dir)/tmp_spm2norm.img $(dir)/tmp_spm2norm.hdr command /bin/rm $(dir)/wtmp_spm2norm.img $(dir)/wtmp_spm2norm.hdr command test -e $(dir)/$(paramfile) voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_norm_calc_a.vjt000066400000000000000000000035561153177201300234350ustar00rootroot00000000000000 shortname spm2_norm_calc_a description SPM2 Normalization -- calculate parameters invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=/usr/local/spm2 setenv HOME=/tmp argument name=dir argdesc=directory type=string default=none low=none high=none end argument name=paramfile argdesc=file containing params type=string default=none low=none high=none end argument name=infile argdesc=your volume type=string default=none low=none high=none end argument name=refvolume argdesc=reference volume type=string default=none low=none high=none end argument name=vox_x argdesc=vox_x size type=long default=none low=none high=none end argument name=vox_y argdesc=vox_y size type=long default=none low=none high=none end argument name=vox_z argdesc=vox_z size type=long default=none low=none high=none end argument name=bb argdesc=bounding box type=string default=none low=none high=none end command vb2img $(dir)/$(infile) $(dir)/tmp_spm2norm.img # for fun, add -logfile /jet/kimberg/test/spmnorm/matlab.log command /usr/local/bin/matlab12 -nodisplay -nojvm -c 27000@aleida.uphs.upenn.edu | spm_defaults; | global defaults; | cd $(dir); | defaults.normalise.write.vox=[$(vox_x) $(vox_y) $(vox_z)]; | defaults.normalise.write.interp=7; | defaults.normalise.write.wrap=[0 0 0]; | defaults.normalise.write.bb=$(bb); | defaults.normalise.estimate.cutoff=Inf | VG=spm_vol('$(refvolume)') | V=spm_vol('$(dir)/tmp_spm2norm.img') | params=spm_normalise(VG,V,'$(dir)/$(paramfile)','','',defaults.normalise.estimate); | msk=spm_write_sn(V,params,defaults.normalise.write,'mask'); | spm_write_sn(V,params,defaults.normalise.write,msk); | exit command vb2cub $(dir)/wtmp_spm2norm.img $(dir)/n$(infile) command /bin/rm $(dir)/tmp_spm2norm.img $(dir)/tmp_spm2norm.hdr command /bin/rm $(dir)/wtmp_spm2norm.img $(dir)/wtmp_spm2norm.hdr voxbo-1.8.5~svn1246/dist/etc/jobtypes/spm2_realign.vjt000066400000000000000000000032271153177201300226140ustar00rootroot00000000000000shortname spm2_realign description SPM2 Realignment for 4D invocation script requires cpu requires matlab retry_tag Try again later setenv MATLABPATH=$(SPM2_PATH) setenv HOME=/tmp argument name=dir argdesc=directory type=string default=none low=none high=none end argument name=refvolume argdesc=full path to reference cube type=string default=none low=none high=none end argument name=infile argdesc=input tes file name type=string default=none low=none high=none end argument name=outfile argdesc=output tes file name type=string default=none low=none high=none end # command tes2cub $(dir)/$(infile) $(dir)/$(infile)_hdrsave.cub command vbconv $(dir)/$(infile) $(dir)/$(infile)_hdrsave.tes -i 0 command vb2img $(refvolume) $(dir)/$(infile)_ref.img command vb2imgs $(dir)/$(infile) $(dir)/$(infile)_tmpspm command $(SPM2_MATLAB_CMD) | cd $(dir) | spm_defaults; | global defaults; | P=spm_get('files','$(infile)_tmpspm','$(infile)_tmpspm*.img'); | P=strvcat('$(infile)_ref.img',P) #| V=spm_vol(P); | rflags=struct('quality',1,'fwhm',5,'interp',7,'graphics',0,'rtm',0); | spm_realign(P,rflags) | rflags=struct('interp',7,'which',1); | spm_reslice(P,rflags) | exit command /bin/rm -f $(dir)/$(outfile) command vb2tes -n $(dir)/$(infile)_tmpspm/r$(infile)_tmpspm $(dir)/$(outfile) command vbhdr -c $(dir)/$(infile)_hdrsave.tes $(dir)/$(outfile) #command mv $(dir)/$(infile)_tmpspm/*.txt $(dir) command /bin/rm -r $(dir)/$(infile)_tmpspm $(dir)/$(infile)_hdrsave.tes $(dir)/$(infile)_ref.[hi]* command vbhdr -a "spm2_realign_date: {DATE}" $(dir)/$(outfile) command vbhdr -a "spm2_realign_ref: $(refvolume)" $(dir)/$(outfile) command test -e $(dir)/$(outfile) voxbo-1.8.5~svn1246/dist/etc/jobtypes/tesregfinish.vjt000066400000000000000000000007301153177201300227200ustar00rootroot00000000000000 shortname tesregfinish description Finishes GLM analysis. invocation commandline argument name=stem argdesc=matrix stem name type=string default=none low=none high=none end argument name=steps argdesc=number of steps for the regression type=long default=none low=none high=none end argument name=flags argdesc=exclude error norm flag type=string default=none low=none high=none end command tesregfinish -m $(stem) -s $(steps) $(flags) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/tesregstart.vjt000066400000000000000000000005241153177201300225760ustar00rootroot00000000000000 shortname tesregstart description Initiates GLM analysis invocation commandline argument name=stem argdesc=matrix stem name type=string default=none low=none high=none end argument name=flags argdesc=exclude error norm flag type=string default=none low=none high=none end command tesregstart -m $(stem) $(flags) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/tesregstep.vjt000066400000000000000000000030111153177201300224060ustar00rootroot00000000000000###################################################################### # $0 - the matrix stem name. # # $1 - the number of steps in the regression. # # $2 - the step index. # # $3 - mean norm flag. Will be the literal "-n", passed by vbmakeglm.# # $4 - exclude error norm flag. Will be the literal "-e", passed by # # vbmakeglm. # # $5 - driftcorrect flag. Will be the literal "-d". # # NOTE: It's certainly possible that the exclude error flag is used, # # but the mean norm flag is not. In such a case, $3 will be the # # exclude error flag (and $4 will not be used). It does not matter # # to tesregstep in which order it gets its options. # ###################################################################### shortname tesregstep description Carries out one of the regression steps. invocation commandline argument name=stem argdesc=matrix stem name type=string default=none low=none high=none end argument name=steps argdesc=number of steps for the regression type=long default=none low=none high=none end argument name=index argdesc=step index type=long default=none low=none high=none end argument name=flags argdesc=misc flags, including drift correction and mean normalization type=string default="" low=none high=none end command tesregstep -m $(stem) -s $(steps) -i $(index) $(flags) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/threshold.vjt000066400000000000000000000007351153177201300222270ustar00rootroot00000000000000 shortname threshold description Threshold a circular flying 4D volume invocation commandline argument name=infile argdesc=input 4D data file type=string default=none low=none high=none end argument name=outfile argdesc=output file name type=string default=none low=none high=none end argument name=threshold argdesc=threshold value type=double default=none low=none high=none end command vbthresh -i $(infile) -o $(outfile) -c $(threshold) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/vb2cub.vjt000066400000000000000000000004131153177201300214070ustar00rootroot00000000000000shortname vb2cub description convert a 3d image to CUB format invocation commandline argument name=infile argdesc=3D file/dir type=string end argument name=outfile argdesc=output file name type=string end command vb2cub $(infile) $(outfile) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/vb2tes.vjt000066400000000000000000000004071153177201300214340ustar00rootroot00000000000000shortname vb2tes description convert a 4D image to TES format invocation commandline argument name=infile argdesc=3D file/dir type=string end argument name=outfile argdesc=output file name type=string end command vb2tes $(infile) $(outfile) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/vb_auditglm.vjt000066400000000000000000000003421153177201300225220ustar00rootroot00000000000000 shortname vb_auditglm description audit a voxbo glm invocation commandline argument name=glmdir argdesc=the full path to the glm directory to be audited end command glminfo -r $(glmdir) > $(glmdir)/audit.txt requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/vb_makefilter.vjt000066400000000000000000000017521153177201300230450ustar00rootroot00000000000000shortname vb_makefilter description create exogenous data filter invocation commandline requires cpu argument name=outfile argdesc=filter file name type=string default="/tmp/my.exofilt" end argument name=lowflag argdesc=flag for low frequency filter, e.g., -lf 10 type=string default="" end argument name=middleflag argdesc=flag for middle frequency filter, e.g., -mf 10,20,30 type=string default="" end argument name=highflag argdesc=flag for high frequency filter, e.g., -hf 1 type=string default="" end argument name=kernelflag argdesc=flag for convolution kernel, e.g., -k /path/to/kernel.ref type=string default="" end argument name=ndata argdesc=number of data points type=integer default=100 end argument name=tr argdesc=TR in milliseconds type=integer default=3000 end command vbmakefilter -e $(outfile) $(lowflag) $(highflag) $(middleflag) $(kernelflag) -t $(ndata) $(tr) #command vbmakefilter -e $(outfile) $(lowflag) $(highflag) $(middleflag) -t $(ndata) $(tr) voxbo-1.8.5~svn1246/dist/etc/jobtypes/vb_makenoisemodel.vjt000066400000000000000000000010711153177201300237100ustar00rootroot00000000000000shortname vb_makenoisemodel description create noise model file invocation commandline argument name=outfile argdesc=noise model file name type=string default="/tmp/my.noisemodel" end argument name=noisemodelflag argdesc=flag for noise model to include, e.g., -n /path/to/noisemodel.ref type=string default="" end argument name=ndata argdesc=number of data points type=integer default=100 end argument name=tr argdesc=TR in milliseconds type=integer default=3000 end command vbmakefilter -i $(outfile) $(noisemodelflag) -t $(ndata) $(tr) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/vb_makepermmat.vjt000066400000000000000000000006111153177201300232160ustar00rootroot00000000000000 shortname vb_makepermmat description create exogenous data filter invocation commandline requires cpu argument name=outfile argdesc=output file name end argument name=ndata argdesc=number of data points end argument name=nperms argdesc=number of permutations end argument name=permtype argdesc=either "sign" or "data" end command vbpermmat $(outfile) $(nperms) $(ndata) $(permtype) voxbo-1.8.5~svn1246/dist/etc/jobtypes/vb_volregress.vjt000066400000000000000000000002661153177201300231140ustar00rootroot00000000000000 shortname vb_volregress description do volume regression invocation commandline requires cpu argument name=flags argdesc=flags (includes vars) end command vbvolregress $(flags) voxbo-1.8.5~svn1246/dist/etc/jobtypes/vbmerge4d.vjt000066400000000000000000000006071153177201300221100ustar00rootroot00000000000000 shortname vbmerge4d description merge a 4D file created in parts invocation commandline requires cpu argument name=stem argdesc=stem for multi-part 4D files to be merged type=string end argument name=ext argdesc=extension for multi-part 4D files to be merged type=string end command vbmerge4d $(stem).$(ext)_part_* -o $(stem).$(ext) command /bin/bash -c "rm $(stem).$(ext)_part_*" voxbo-1.8.5~svn1246/dist/etc/jobtypes/vborient.vjt000066400000000000000000000005561153177201300220640ustar00rootroot00000000000000shortname vborient description Orient data invocation commandline requires cpu argument name=infile argdesc=input cub or tes type=string end argument name=outfile argdesc=output re-oriented file name type=string end argument name=orientation argdesc=orientation of output cub/tes file type=string end command vborient $(infile) $(outfile) $(orientation) voxbo-1.8.5~svn1246/dist/etc/jobtypes/vbregress.vjt000066400000000000000000000007671153177201300222420ustar00rootroot00000000000000shortname vbregress description 4D regression invocation commandline argument name=stem argdesc=stem of GLM directory type=string end argument name=steps argdesc=number of steps to break regression into type=string default="1" end argument name=index argdesc=index of piece to execute type=string default="1" end argument name=flags argdesc=flags (e.g. -d for detrend and -m for mean norm) type=string default="" end command vbregress $(stem) -p $(index) $(steps) $(flags) requires cpu voxbo-1.8.5~svn1246/dist/etc/jobtypes/vbse.vjt000066400000000000000000000003361153177201300211670ustar00rootroot00000000000000 shortname vbse description estimate smoothness from a 4D (residual) file invocation commandline requires cpu argument name=stem argdesc=stem name for GLM directory type=string end command vbse $(stem).res $(stem).se voxbo-1.8.5~svn1246/dist/etc/jobtypes/vbstatmap.vjt000066400000000000000000000005511153177201300222300ustar00rootroot00000000000000 shortname vbstatmap description Generate VoxBo Stat map invocation script requires cpu argument name=dir argdesc=glm directory type=string end argument name=outfile argdesc=output statmap file name type=string end argument name=contrast argdesc=contrast values for covariates type=string end command vbstatmap $(dir) -o $(outfile) -c "$(contrast)" voxbo-1.8.5~svn1246/dist/etc/jobtypes/vbsubresids.vjt000066400000000000000000000003751153177201300225660ustar00rootroot00000000000000 shortname vbsubresids description create 64(max) element subset of residuals invocation commandline requires cpu argument name=stem argdesc=stem name for parameter estimate file (.prm) type=string end command vbmakeresid $(stem) $(stem).res -n 64 voxbo-1.8.5~svn1246/dist/etc/maps.txt000066400000000000000000000023651153177201300173510ustar00rootroot00000000000000 # maps.txt # The file describes which templates may be found by VoxBo's vbview # (and maybe later, other programs). You can specify a path for # searching for templates, something like this: # path /usr/lib/templates:/usr/share/templates:/tmp # Note that VOXBO/elements/templates is always searched, you don't # need to specify it. # # You can also specify actual templates (and you should, otherwise # there's no point to this file. Each template line looks something # like this: # template 1 ch2.nii.gz the colin27 brain # Where "ch2.nii.gz" is the filename, "1" is the template ID, and the # rest of the line is a brief text description. You can have multiple # lines for the same template ID, and the first one that's found is # used (this is helpful if you're not sure exactly what the filename # will be). path /usr/share/data/mni-colin27 template 1 ch2.nii.gz colin27 (181x217x181) template 1 ch2.cub.gz colin27 (181x217x181) template 1 colin27_t1_tal_lin.nii.gz colin27 (181x217x181) template 2 avg305T1.cub MNI 305 T1 (181x217x181) template 3 avg305T2.cub MNI 305 T2 (181x217x181) template 4 avg152T1.cub MNI 152 T1 (181x217x181) template 5 avg152T2.cub MNI 152 T2 (181x217x181) template 6 single_subj_T1.cub the old SPM single-subject template voxbo-1.8.5~svn1246/dist/etc/servers/000077500000000000000000000000001153177201300173335ustar00rootroot00000000000000voxbo-1.8.5~svn1246/dist/etc/servers/README000066400000000000000000000053501153177201300202160ustar00rootroot00000000000000 # If you're not running VoxBo in cluster mode, you can ignore this # file. # Here is a quick tutorial on how to set up servers. Skim it, then # use the example file to get started. # Each server gets its own file. Files named "README" or containing # the characters ~, #, $, or % are ignored. Each server file has a # bunch of fields, some optional, which describe what that machine can # or can't do. # speed - currently unused, but we set it anyway, so that we can tweak # prioritizing. # avail - specifies when the machine is available for batch jobs. # Each line takes a range of days, a range of hours, a priority, and a # number of cpus for that time period. Note that priority 3 means # only jobs of pri 3 or greater can run at that time. So if you want # stuff to run more, set the priority lower. # provides - lists what services the server provides. These services # correspond to the "requires" lines in your jobtypes files. You can # no longer use "all" -- you must name every service. # Limited resources (like software licenses) are slightly more # complicated. Here's the way the food chain works. In the jobtype # file, a particular jobtype might have a line like "requires idl 6". # That means it always requires 6 IDL licenses. Or it might have a # line like "requires idl", which would mean it requires IDL, without # saying how many licenses. # There are three forms for the provides line in the server config: # provides idl -- provides idl no matter what resources are required # provides idl license-idl -- provides idl as long as some host has a # resource called "license-idl" in enough quantity to satisfy the job # provides idl license-idl 6 -- same as the above, but requires 6 # licenses no matter what the jobtype says. # If you have one central license server, then all your servers' # "provides" lines should have a resource listed (not just "provides # idl" but "provides idl license-idl" or "provides idl license-idl # 6"), but only the license server gets a "resource" line. If each # machine runs its own license server, then you need a resource for # each machine (use different names for each, something like # idl-hostname). If you have unlimited licenses, then you don't need # any resource lines. # We use this mechanism mainly for licenses. You could in principle # use it for any limited resource, either to make sure jobs only run # on machines with available cpu power, or with no active users logged # in. name myhost hostname localhost.localdomain speed 500 avail 1-5 8-17 2 1 ;; 1 cpu at pri 2 weekdays avail 1-5 18-7 1 2 ;; 2 cpus at pri 1 weeknights avail 6-0 0-23 1 2 ;; 2 cpus at pri 1 weekends provides idl license-idl 6 provides cpu provides tapedrive resource license-idl /usr/local/VoxBo/bin-Linux/idlfree voxbo-1.8.5~svn1246/dist/etc/servers/sample000066400000000000000000000025011153177201300205350ustar00rootroot00000000000000 # Don't worry about this file unless you're trying to configure a # cluster. A server file must be present in the servers directory for # each server in the cluster (typically in # /usr/local/VoxBo/etc/servers). # "name" is the short name by which this server will be known # (defaults to the first part of the actual machine name. "hostname" # is the fully qualified domain name, the name the scheduler will use # to contact it. name sample hostname sample.university.edu # speed and rank are used to decide which servers to use next. # currently only rank is used. speed 1800 rank 1 # each avail line describes a period of time during which this machine # is available. each line has fields for day (0-7), hours (0-23), # priority, and ncpus. avail 1-5 8-17 2 1 ;; pri 2 weekdays avail 1-5 18-7 1 1 ;; pri 1 weeknights avail 6-0 0-23 1 1 ;; pri 1 weekends # provides lines describe resources provided by this CPU and can be # limited to restrict which jobs may run here. provides cpu provides mailagent provides idl idl-license 6 # resource lines describe cluster-wide resources, and should generally # only be specified only on one machine each. They can either # described a fixed quantity: resource idl 20 # or an excutable that will print the available amount to the terminal: resource idl /usr/local/VoxBo/bin/idlfree voxbo-1.8.5~svn1246/dist/etc/tips.txt000066400000000000000000000147031153177201300173670ustar00rootroot00000000000000# tips.txt # This file contains tips for use with "vbtool tip". Tips are # separated with lines that begin with at least three dashes (I also # like to separate them with some space for clarity). New releases of # VoxBo may update this file. If you want to maintain your own local # tips separately, you can put them in a separate file called # localtips.txt. User-specific tips can go in HOME/.voxbo/tips.txt or # HOME/voxbotips.txt. # Note that the first line of a new tip cannot be all whitespace and # cannot begin with a #. Thus, this is a comment. ------------------------------------------------------------------------ VoxBo programs that can use 3D files can also use special syntax to access subvolumes of 4D files without having to first extract them. For example, foo.nii.gz:7 is short for the 8th volume in foo.nii.gz (the first volume is 0), and foo.tes:mask gives you the mask of all voxels that have non-zero data at any time point in foo.tes. ------------------------------------------------------------------------ vbbatch can help you run repetitive commands in parallel. Specify a command with the string FILE in it and a list of files. That command will be run separately for each file, using multiple CPUs if available. For example, vbbatch -c "myscript.sh FILE" /mydir/data/subjects/* -r will run myscript.sh on all your subjects. ------------------------------------------------------------------------ vbbatch is often useful for things that have nothing to do with imaging. ------------------------------------------------------------------------ vbbatch works just fine with filenames that don't exist, and you can even use the -d flag to generate new filenames. The following will create 100 new files with random data: vbbatch -c "vbsim -d 20 20 20 0 randIND.nii.gz" -d 100 The result will be 100 files with names like rand87.nii.gz ------------------------------------------------------------------------ If you're on a VoxBo cluster and you'd like your job to run right now on the machine you're sitting at, instead of going to the queue, you can set the VOXBO_CORES environment variable to the number of CPU cores you'd like to use. ------------------------------------------------------------------------ For help with just about any VoxBo command, run it with no arguments. If the help scrolls by too quickly, pipe it through less: vbim | less ------------------------------------------------------------------------ See your tip here! Post it to the mailing list or send it in by private email and enjoy the adulation of future generations of grateful VoxBo users (anonymously if you wish). ------------------------------------------------------------------------ You don't need a "cluster" to run VoxBo anymore. For more information, visit: http://voxbo.org/index.php/Desktop_mode ------------------------------------------------------------------------ Want to flip back and forth between two overlays (stat maps, masks, whatever) in vbview2? Select one layer. Then select the other layer. Then use CTRL-L to flip back and forth. ------------------------------------------------------------------------ VoxBo's realign and norm commands were written in 1998 and haven't been updated since. Realign may still do a decent job most of the time, but norm doesn't. We recommend replacing both, e.g., FLIRT for realign and ANTS for norm. VoxBo also includes scripts called spm8_realign, spm8_segment, spm8_coreg, and spm8_warp that will automate using SPM8 to realign and normalize. ------------------------------------------------------------------------ Want to test some new analysis strategy using random noise? You can use vbsim to create files with Gaussian noise. Similar functions are available in vbim (using the -newvol and -addnoise flags). In combination with vbim's mask-related functions, you can create useful fake data. ------------------------------------------------------------------------ Enjoying these tips? Then make your own! Create a text file in your home directory called voxbotips.txt, and add as many tips as you like. Separate your tips with lines that have at least 3 dashes. (You can also call the file .voxbotips to hide it, or .voxbo/etc/tips.txt.) ------------------------------------------------------------------------ If you're running a program in a shell and you want to get the shell back, hit CTRL-Z to suspend the process and then type "bg" to run the suspended process in the background. ------------------------------------------------------------------------ vbi can give you useful information about vector, matrix, 3D, and 4D files. To get information about the VoxBo-readable files in your current directory, just type vbi *. Fore more info, use vbi -l *. ------------------------------------------------------------------------ You can re-run any VoxBo GLM by running vbmakeglm with the .glm file inside the GLM directory. Edit that file (or preferably a copy you put somewhere else) to tweak the analysis. ------------------------------------------------------------------------ Please post questions, suggestions, concerns, and tips about using VoxBo to the mailing list. To subscribe, visit: http://www.voxbo.org/mailman/listinfo/voxbo-general ------------------------------------------------------------------------ All VoxBo programs understand NIfTI, Analyze, DICOM, and VoxBo's own formats. You don't need to vbconv your file and then run a second command on the converted file. Just run that second command directly. ------------------------------------------------------------------------ Duck! ------------------------------------------------------------------------ How to do functional connectivity analysis in five commands: vbim -newvol 20 20 20 200 float -tr 2000 -addnoise 10 4 -smoothvox 3 3 3\ -write4d data.nii.gz -include 0 -mult 0 -add 1 -write anat.nii.gz vbfilter -lp 0.08 data.nii.gz -o data.nii.gz vbxts -t data.nii.gz -p 10 10 10 -o seed.ref vbvolregress -dv data.nii.gz -iv seed.ref -int -c "foo t vec 1 0"\ -mapfile map.nii.gz vbview2 anat.nii.gz -s map.nii.gz ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ voxbo-1.8.5~svn1246/docs/000077500000000000000000000000001153177201300150545ustar00rootroot00000000000000voxbo-1.8.5~svn1246/docs/dbguide.odt000066400000000000000000000454731153177201300172040ustar00rootroot00000000000000PK½•X:^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPK½•X:Configurations2/statusbar/PK½•X:'Configurations2/accelerator/current.xmlPKPK½•X:Configurations2/floater/PK½•X:Configurations2/popupmenu/PK½•X:Configurations2/progressbar/PK½•X:Configurations2/menubar/PK½•X:Configurations2/toolbar/PK½•X:Configurations2/images/Bitmaps/PK½•X:Ï£€ï[[-Pictures/10000000000000200000002000309F1C.png‰PNG  IHDR D¤ŠÆPLTE€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ3f™Ìÿ333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌÿ3ÿfÿ™ÿÌÿÿÿ333f3™3Ì3ÿ333333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌffÿff™f3™ff™f™™fÌ™fÿ™fÌf3ÌffÌf™ÌfÌÌfÿÌfÿf3ÿffÿf™ÿfÌÿfÿÿf™3™f™™™Ì™ÿ™3™33™f3™™3™Ì3™ÿ3™f™3f™ff™™f™Ìf™ÿf™™™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌ™™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿ™Ì3ÌfÌ™ÌÌÌÿÌ3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌffÌ™fÌÌfÌÿfÌ™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÌÿ3ÿfÿ™ÿÌÿÿÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÿ™fÿÌfÿÿfÿ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿÿÿ3ÿÿfÿÿ™ÿÿÌÿÿÿÿÿ¸ÿ¸ÒOIDATxœcà'FŒ*U0RËU<4àðIEND®B`‚PK½•X: layout-cachecd`d(0b``àd``†1ÔaŒ:£Æè2PKM_06PK½•X: content.xmlí]ý’Û¶ÿ¿Oª3§£oétÉÇŽ'nÚsêÉ9g:D‚r$ÀàéÔ¿ú íËõIº %‘¥“j]Ìäl‚‹Åâ·‹]`<ýò1 ÉSšKqÝèµ» „'}.&×?|Ûºh¼¼ùÍ×2¸Ç®|é%¦åIaàO½…¾ro¯‰W’j®¯˜¾2Þ•Œ™Èz]©¯ìX®E›yX»»%.ö6ìÑÔ팴K}é¸þÈ–¸ØÛWtV·3Ò¨Åî¬ÛùQ‡­@êQL _‘â1äâþº15&¾êtf³Y{6hK5éô.//;öm.°—Óʼn -•ïuXÈp0Ýéµ{Œ6b†Ö•i‹"‰$3UjèšVõä¶EŠÐ| ÔmË¡…íXE\™ìò»IoÁÛ÷7™kwf¡;yC.¾Pµ|æ…úæk·DófâžQðëÆ¡êneØ °3ªˆ‡ó¥—Íl>ЩŒè „‡{³­ÿ72Qœ)ò=›õJ˜|Ac©¿*¹†Y≴­ Lq°ÜHúL‰z‚—™ ¾i=ãZï0µþa§V$‰¹ñÀoü‘ù;H´§@Ô—JØÈsÝøM’ªc ü†ýLÿ’Û·ß;*4y'…¬”¼ŒxË^Ky_CÑûŠÿƒ‹@$É`Q¢Ròº† R~kr=PÅqÓ³M´[ᯬJÑVè`•Ö=_Ÿ{/Ü' ¾bdu±†Jõ\=˜2_S™ZÃwªBMÚNîµ,Ÿ<ÙŸ+ÂË^>^*¨Ý°7²^ö©+ˆÊpX"®yÆ}ܪ·Ï8¬·Ç§!Ÿ@€Œ¨š@·¢FÞ&FûU© °G “H¬Èã×ÅJÛSézíáùhÈóEªXØZ¡è_v»¿ßYÔ×uÔîö£M¢žõGƒ³ÝE}U®ß–ÇÂpURh*ÊÈ«˜úîPÛmw}”ZÇRAHi…,0öM·{ÎÑ2ä>ù]×þW¤S|2B!+6×é=–Æà·‚rgÕ ƒ‰øªÒ*[m<´‚NföÛ ÇèXÞ9£„c'àÕÂMâu#„)w•ð޻߾öÎ7yÃþðb0ØÕŽŽà¸‡íÑÙÅ`“¨Ãîy·¿»¨‡sÜÝËógï¸GtÜ«xLÄÃ9츎ꀎû©³ÿÄŽûýš¥ÆTщ¢ñ4{ X°-×댂9Py—œ0ßJ}¹63c®Ãω6<˜·4 Lg0'8"ÓP»9.ð-ƒvнÍèbõ¦)Rgiï‚52Ö« LRsc³nçíáåeáfÍ<̬˜Åøuªa¬­Ç5ƒ®£Ço¥4;êÑLýÏY¥°uÕºî%Ь¿&û`i=ËßûÝ¿ã*gú(Ë£þ$†{MDÂ9Œ¥?ÏÈB®—‰~úéâû$ê-Ò %£Ÿí3z†JÐÛß>‹ò¬|Ef³´.͉sÝðÁ˜˜¿òΕ!ÛÇ[Ãkè]Aë´Awpú¸ÿ?¬×‹“žDª7ì¼ÌÏföfÌ¹î± så^´¨æTT¿ÆÒnÈS‚ú{¹õ]6Èר¶Ðš°Ë –Ù­*r’ôh„©Ê 8CIØ™Û)ٿןÃóÌÚ444ÂúËg’>¯O†ù<½ßà•up‡:«Ÿô|çÉD€‚zBÛ„Æ.2¤]iu"ÊÌmúCGþ€@{%#Ѷ @#tÂZcÅè½…©„5 I¡Ð**°¤—è¦_Æq8oùLƒ§Ù€ÜPí`šý’0±È6¯7:¡|®ãÎ[21V‘!{`!`Òp¯Š¾ CX®¨Q>ÂÌ>d™ñ§qA;*“7Õ~5jî$ƒüB#-ø Ô„m;ØG槪]›:‘É|†øÒ1ÀPå1×yeƒ¬‡å÷Ø2Ü@WÃÀPÃÖ…+FG<µà„oÖ$I(cY%"ü¯æ+¯ˆš²i‹S×qô¦4† v§ä6”¶/‡ïê ÷_Ò@¼ÆÄ.Kw«'7ˆ-“~4ý-Ðô?_h[ |¾Ð ·@3ü|¡9ÛÍÙç Íh 4£Ïšó-М¾Ð\læâó…ær 4—Ÿ/4½î¶=_÷ÙƒSAæöìKƒ¸£àêÖzó ¢ê¬`wïvñ7úñÍúŽ¿šõ{ž½6ùp~bȹ…tnú ž• ÄüÙL™"p Ö;ö…ÁûmòʸàÙ1´ÀbPoø ákö~CšjL](à‘(¶‚fªwïûÓ2|•¼\&Mð‹¦„Ü3»rHmr—Äx[›ù„G°HÀÁV0¿@—ŸpÞ ÎÌ s`x/ÒÝžp.Šqö$1êô1ÎÚäuÂC\<„ Ÿ¸L`B°ÀjTO[>VT͉Ïð²:_šÎ¨|%:QîaÒñ¦ëã¥ëÝ©+ŽâËȸ¦ÕS ‰™JÕ¸‘àR¹ a8'xýä ã9yCùG·9ÙŽÆV¨©tjÒÝ|˜2'*–Ú:0ðä¯o^“XÉŸÁ[þpMŒÄÇî3B‰ ÀK˸»:ìz©w¶m¦ÔC2eaLêñŒb¨fmx”ؘ†_Ø 3ÇÎ>,QRƒæ„Ç`ͨò¦m’¦:7ßÃåá€äÑL=02–fJ¨&¸B£(ÜÌ"½À©ÜƒºÉ\&$ˆ…n{G”ƒùsSAÝ`a"?[}üÒJm€Áï1 îÄÞ:d(…(€ø`£_æ÷³]¹±Ä8«öŽê¶jteZtg¸Hþ@ÑIQ‚u6$ЇÕÎ@§jcèè4¨Y¯@y4ÄéXf203ª˜»/¬QÜ ÓzWIkfŠN K`ÖÙˆGÇh^ó,¯´7;#·uæ%êØƒ¼‡Q6™…|XRiq-¨t.ÈO`‹r¦›äÏw›Öpo¹H——‘žÊ$“µ$cFÕ<ÖE (ùÎVíâÇï¿ûØ ù=,UX°6a•Ì,è»ÉxŽ"̤º‡e«QÌÑØgS™’Y@B}íµ}ðûédRC£<8ª° ø$Q›‘=¸Ápˆ°Ü;¶É|«< Üd0é²µ^€¢ÿ~ <´›U[U²Ð¿ýþGò>ƒÈ`1‡Y3ûŽ— È‹·ïoEoõN‚ÿ€9¢É ΛÀù3ü¸¡"ü˜Dað5ZDÝ«0B†àe«xZ邏1$ëüeÄPÂ9#-…„ £¸º`©™œÍRf3ýžôav‘ôy0_rlθkù¸ùåãÄ üû:·Í{‡~ùÞ¡¿´yߺsX¶–W!ì#’ÉÔN*REOÁUÂzG­”Æ\„Æn4 Å-8„?° €r]Óï2Žåõ?5ݾ›¾•cÓ²òöµ† ;É}Y–°Ç8=uíh¹…À¦ÝII[#dJ,:¶ÖhÎB…X2ó«‚1ÚkÝögzÅ{ù«×¶v³ÁVÈ]ÓËÊ•ÔíWÖ`vèðzµƒ’³ 6ÍÕöÝÒ0a-—‡AW…ù‡êÒEãÿÖ¡!§KY‰•¡wæõ„wd?^˜t¹4`íŠ^OGÔ¦ýû¡P|‚P”XyȘ[g4M‰=?âþ WgÓîÈ`©Ú¬cæqØÐ#«m“8ðóËE'y(ÅÂst·5q‡¿)}H¯ÜøîÝ ¼eÔ„HJÃ&É/ñ4‰½¹óåóPdÌùàÇkcîç\Ê-¢þ [‰¸Ò™á¯ð>œ„.ËDP"—Â#/¦¡<)üß>“ÅŒ38<­I:<Ÿn'b‡)n[¥9Ül¹ã€£"­¼¼`íI»I&~ü¸Óª”K1Ø„çF•ÿd,KïÚÔ¾âƒ)ß—Þþ8 àm‰W„jãW}{f_üJ/íˆã_äãké—-¶ú+¥Ø·ïo åWp\6®V8'p7F#Ìðºb¨+” —iZË£ˆù<»+깋ŽÚ^ïAmÝ’¸­È°¶DˆTÙåW©G ðÛÀ$³)÷¦ÄMÊÁRåHñ¾P7+8–rg8~&B‰Ç 7ZÐ6E¶0 "ý1Ÿßïv/öq›‹½àzQhTYíTíZ=±(4Ú»(d»/Ý_ï'Ôær$í]#Z—-]&ÿ«Sùhï3V.úâéÀb9 ‡“ Líí èÞ"¼ývïÙ¬#Ÿ6¼¸¶“:»š†:>Ðu“ƒ"ýúîý>† óòåËg ­„3Í[œSín»{zHƒI?süöî–ôÚ½Þ¯Ø Ûü`„ÕósfŠÕ‚Súÿâ'˜ñüàT Íå:z©ñ  FÂ{¶–Tmõí1 ¯¸ÝÀ‡Ñ`8ºì˾ÉÎ~‡a¡k‹m¨r¿)©@¾h¨›h|2¬sÔ) Й3@¡û_¡›Rê Í­Ù%þ1N²œ‘mû´cå_Ùl½ü3€2¢tø"ú[à ¶„|囉F\­ÉkI·1ˆ¢[oí릯¿Ã- ¬áßÏ»ÉÇÌK>>îãp¢o§T‡ |*ÎÄÕ|òöñÁ³kêÀ%MÀO´÷þƒYSÉ?zÇ8ýg†?˜h¥:!­¾ó#? €câŸDí¯û&a\ô‰ô!HS Ѭ~EcIŽA¶aa<ú Žò6q¡À~7ù«¿;…^2$Ã?øŸ½¿´·?}¯}ô¢T{G1—ó:âÞÄñ—†VeÿS"Ô¤öWàQ—ó ] GHH}g|}õ’bŠ&ÖÞ 7½[!eqY«Ðõà\•¶e=oŸÊ ·ÃÇ+NÖÖ[˜4}J3ÿÐ]1u±¦fZ}~ÆëjÈsŒá_¡é«]âmàú…yü‰<ûÍ2~[LpÉ&H¡÷¤—)4ZL <>t-ò +€ÐÂ@Âo ô)=g^°Eÿ•Þ ¢ÌÒ Z1 ã[æ¥ú/ÚÁ¯ÓÚïãda((Ÿ1÷P+ãÏðЬkfYº4€ß!Ïjå•d^ÇDÆ€;ˆHAg¨B&›y²SyáŹrE\¹×âj.âj~-®êÛ ájq-®–"®–×âj%âju%®lCÀU^xq®DáʾV¼²-WÖµ¸²E\Ù×âJÛíkÅv[ÛíkÅv[ÛíkÅv[ÛíkÅv[ÛíkÅv[ÛíkÅvGÛkÅvGÛkÅvGÛkÅvGÛkÅvGÛkÅvGÛacû6C=8x;ŸeíM¼£Ï~8C¯ö‰¿½›|ÖÙ)ñÓ™i°ÿYÌß¶±úÑü~zŒvôÕìéˆä:¡\øYº‡Élÿpïoè#Tíe€2ŽÞÆÞ&—àà%_ü„åþ_’$&¹¹¯ÿð&~k†fÂç›»ÉÁÏt>Û[Æïy}i–Ä_ÀÜKKÖúüF`¸V°T«´µÄ_g”8ÎRŒˆÙŸzèG;8Q±,´Ê´—öÜÔmŨ÷9,‡{K‚ÔC,Èü–©G-XÅ- Rt° Ë[¤aAV7$g¨Œ©Ž”Ç-H}o„1oIA7R[zœ‡±oIzhˆqnIAÏ^MŒ[AÏ^Í-Œ[AÏ^MGŒ[AÏ^Í`Œ[AÏ^MzŒZN¢ RÍ“Œ[AÏ^M­Œ[AÏ^ÍÆŒ[AÏ^MàŒ[AÏ^ÍùŒ[AÏ^MRƒå” Ç0±S# $ÑJåÒ™¦í´¨LËD òÅ"ëB²¾š®ï Cv‰wÜë ¥%¿õcý$ ü”H²÷6ñƒo·©Ÿéø3K3ÿ~¹üé¼­½€K8ôôè­ƒh§ïã$ø=Ž2/ÄÔ¦#¢þ ¹Y×Еmë=£­«•((â<Ù^ÇkÁ·^˜2 pŽ^â!]±šÂE^÷NY ? lü“záqŸ/ÂA|Ü'¾÷ån|.€.‚KàbWÈ\;w7 =»/-Ë ¢ׇÂ5ó¬4”IÊcæÝ›ÇÇ®Û᳓C¾Ï¤9¥>PC‹>NÒ¶Yrò'Ú6Æ¥Áï€SÓ:fèYèE»“·ü=Xǧ(K€Wüò±$ |O÷ÒÀ‹èÛD7¤Zæçf!5Ñ‚ºúà²íÐäÔ˜—ž×™Z ••ZO›&•ëx"t –ýÓqïG(¯­‡Þfã':âånÅÀ²‡ g¿¥OOÊ4à @ñÝdä`¾ºÉ騳èl$qV–[4‰²_6‹ö à<ŒÝ8«%»º¬–zÊùº½áÜ}7÷¦bUÞŽÊú‘O#@Õ¹ÿà‘w#P³ÎˆŽ§t_!éÐ ÐÆ6…>ëxß ^L‡ „`à¡w„“D?¬ÃY”òÇÁ“JóûâûG=‹w~¶‡+ú`ójú0ûÁ|}´ñ’Í„¨ñB/M{ ¡LÄ­†ig«tkšDÁr«ŸÀ× „¹7O”«2‚[Ì•<È·léõš`&^š{ÃÐA^jŒ‘/ Àž-ðH#À žû”8rõ1òäêCÆ• cDZ‡ÁFË×*…£œy»m]r)ô¬ 9x¡¬§Uƒ#V=) 2ÐèÖO¤ßÇÎóúórþº{«-öV{|ÞjËvÓ ÃlŸ2p’‹]œ·½ámö 9CXeK€SE¶œû‰ ïœà4ñÄþ…ΠÀ=J ¦yψJ§ÒŽÑ8OVPã4À‹.í¢ÆK×€w ä¬ñÍyõM‡m2L($)Ëma)5ŠãìÅNã·Ó÷Þ²xYClfìÄWÉY·K|¯é|yIÌVØ >äµËX ÀTjJÅÀß(Ùw&hú ø öëîùÍò!h%É´*MO½Q#“?$ètŸ¾ÕÒW*nºpÛ'dtJŽ¿ =ŽëiJ«Ò²Œ©+D<Eµöâ?a{ŒSª¯Ç¥mz§úùž´èõÈ]n\”Pë[«¼Ú^m]r‹-Üx˜Ž`.Ÿ˜wBôœ·=ëœüZîJ ¶Ró‹/Èc8#B4º 8`0ˆ¿©”á Sì&oHN^)7¤Rb©/Cæ³W´¦;]¶{=“¶†˜J혓¨Éͯ”©á›¿7ìb¯¬U¿!¿5riá1scaŽÜc0tjïƒ,ôU|¡)k÷ñtŸ±uwYïãÞ&·`§'ÈP™T$˜¡hÛ_/åûëe§þšó¶b]Uí…’­£0]]–¾iÌ-›WJ··¶Þ¿ÈŽi¥q+g@²Ï¡|¨µõ¡¶¦H<¯Ètç²ñ¹µÞþrÿÙ_#ß„³ãðolÉ®éç0±)µ™’®¹€s®ðäS3[eºaùŠOèŸp_~#c€Vc ûæŒ0ðo‚¢Ÿä¬|ÒΕ8“‰^m Éõ¶JC(%þe¢¯„JC‡ÖT¢”±Xr>ÔÑ”°½ZrSÂE™’ªq¤wÖCªË’\‡Ÿ>·x¾SŠý‹øÇìÿà1“qÃÒÛ òë#RN¦±4}‡Éðtöo ÿ··ŸàŸ?… ôùÉI¸мõ÷·Ÿþ^Ћ’6’­ÑYXÝW!ñЂ€‡ëØ­ÇtÕµ÷âåøi‹…ïèE²Š î‹(I˜í“ø´ÛÓúQíÂyrºkÄÚ&Noó— ï”V±° œ€2¼¿„ýzu@S³„]ëWsò,‹š)“<Ü\S{ã:–º ¶ysYÈ)øLpHþüÃqïaSP—i Äm’“r«o“JA²1(H6ç•ãö°ªÐtÜölº-V[2‰dUݬw׿NcI̓7X…“Š«w ¥¼\£_J¹…9uÌEnA¶Ö¸…eÏ­k¹ÅÙpžu‹ÚÂÂ-¤V-7XÅ‘q g·h½2ŽºÅrY…ÕjksÔ>&·0DnQ[X¸…Ñ£[¸2náàŽœ[XS`´ynQ— xk.c®ùære͵´±¹nIý õ/Pÿ\rÇÔ&SHÏBýKõ/PÿBVý‹bÌí«%£þÕê_ʩߙZ®80ní 2Ÿ“@gt^¢’ϸ¨e%Œsƒ§aóÍò!Žpñ٣Ʌü]5kÕBÎI»&&›ƒJç<ëhtãmÑnض4‚¶h WÑ_"3Ù°ÊþÚmñ}œj¢Æ†X¡ë<=@HÏýû·(œ>u‹:Ïp\¸EqM‹úÞA—ìðÝÄ÷Ÿý/or°h\üW$Û™Øû» $#ÉEøõW½aµâ ´~ÖÏZ¿ñÖ_vÀâÑޱc´4‹³® Õ*tWh 3Wd@_U /€æÐ5¬ü`g|˜øù)âKþO¿WN©n¹W3Ôü„á-8î»\÷ňïãSø véJ<þ‡9Ú›“â G{+¥8†=Ú»T‹ Kxv?'pVóàÂS€–•Kš¢¥Ô!Aõ•_äTwNòƒš^)ù1¬é]Ó+Ù¸“ {³'KB-¤”%ÖBó–ZH[hÑÅBœ—»[ˆ“~¡RJ¿ k¡ÅÌBœ¼µR^gX -ÿ`â$Œ¨…”FÃZhõ³iˆMT”ÇF¦ñG0{ø+Ê燿*aùÞÎþu›æ.ËcãaÎþuLƒMêŒò8ç÷ñŸ•/xT=nÍ”l /ˆMT?RÏ/J1óƒ¢ËM}%˜b^IŸ ¯°…mŽ6.N& ’iUš1^mÓö V©‰ö\K‹°’:Ü:À5†Ôõ2j»zÖ2·ûièbºu" ç<ž.ošr~"Ñ<¼ò¯H×Õ'ÈÎÓè¢Õ%r^ 琢bѶž!šsMÌ–:L_o{ï€C¨>bR:xÅ„½—â&ÔXª±úÿ0ތ۾ÒÑ£å°qßI±äŒÿºd™3=sïc%‹6 :dº‘vì¶ßã‚’}|:€ ÏÁ9¥V!£š@¢Ž!}s C?kü&~¤õôhJ ®¨»«¨êdß»³×óà"ª '’†ó’†)u4Oðb'_Ê;L±K‚ñP7#Vn×ÞÅQÌ™¬Ò˜*Ïv+”^š‡`“íé\`- Ŭ{Óœ!Ç»Da |¨D&q;À˜ne€ë/õMŒRi,I[—ª‡Lõ*G“¡=j\z2PÃTáãˆ3‹MÞÐrr¥mã>$1xùðü¨}•ßG9–lá͉§†v_32h­úÒÇ. »ÌðF½U½×P:­î”›}šg¡Ò(ÖÜå·"ž¢5|ù#|v!ƒÑرÝâ;ÖÁ£Ð‹v'o*ýýñq‚‰NQ–<ñ¶—±v¦/S#£*¾Âµ»Â*å:yGú×PTÚvÛ¢}÷åú^´f /ÇõËD}|>œÔZ¤VÐèkä÷Y ó­ã„- ã¿î^=Òl1ø÷ÓÙ誸P‚—á¬)¢J,V¢Ká™;Á;˜1ˆóÐBѰðèoôœïú8[‚Œ­@‡7Û(QÙPú*bí…PýÀVññ¬ óÅ€„\KÉ€â‚ßÁ#ZC9¹Å”òªiLâ’ª¢¢týŸñíÙº,wÕ´.Ë0pä!Å®Ë$‰iH O‡ˆ¶HðOÀË„y¶óŽÕå¹¶uðŸð›gà¡|œõ¼Íà¡×q¼Ž'±ëí¿^CÉl¿4ZÝ[ª‹U²1üóWP Kcz¸T6ÖX²ªfù]%ŽìÍC…’!„g±DÔ½Oð‹ÿ¤¦+²SŽËœ.,{Þkè_ B?3÷•œ"ºÓŽ¿|J“ëàj/Ò‡ å•(Ί:ú˜]m-eç‚y ¥D4L3±¦ ×vkš‰5µxAóy3Yã$6n!öÔrHºŸ„³Ÿ.¦ ñ¦½AGo°‰ÝYÁ–è‡xô³=×Ûõ¿K‹^ÞYÃC^JWæÔôä¸dR!DKx9žt"kzÑÓÓvOŸjìÓ-œÐA¬Sé ÍHU4[Vè݃ÐÖ3И||Â’ÇSKn­:¾®Ï–=N¶œq²åŽ“­ù8ÙZŒ“­å8ÙZ“­b5çÅø*±Ì¢¯w¥¹PÎÑfÅ,¨9akc¾L2T;ô“Ån¢©×R_ÔCWD `¾^#ׇy Ѭ«ˆ†¶Ìê÷>ÄX.¼³örrÛ£›^¯}9¹QÈí®ŒÕeåvG!÷b¹p.+÷|r¯–ø,ËɽÜæÔ\¢žî‚r/G!· ý²r¯F!·K2™—“"³¾XXý6¦Xóq×,0Ÿ54æ;&>Òké‡\u#| rÑ ½$Ó¿záɇ_QBsa´”ׄ­† -!>(”ׄ£†˜æBä0˜(¯ W%ÄZdyÁ…4¡å51WÑÄr¾²/¨ ()¯‰…¼&,€7–—Ô„ ¸”×ÄR^öÔYÚ—Œ˜*pS^+yM8S×X\²U òª`ön·Ö…;“ͽÝtÑ“rÎ/0©=4&í?ÑÖ¼>m›ø!Õ1úNªB›†ìCèC‡6@ÎÞôQœ?}9}¨ ÑàÙ›>ì©ë86„>T0iüìMÎta‰RCèC™6€ÐÞôáNWÆ\ɆЇ >m€¢½éc15–‹åeõ¡‚RioúXN­ùRT‡Ð‡ Vm€¥½éc5u.ÜÛ*áÕ&hÚþ0¦s»'Ò¶rÎ *`«ó2}®ŒeDë/›ú æÔûK¨>ƒ‰ö¾rªÏbö½Ÿ´ê3™’ï'³úLæéûI®>“Éû~ò«ÏdF¿Ÿës™æï)Ë:ŽÉÎÉåbuo±â«5o±ö6$‚{‘ÄHÖrQÊe$HöŸê”äõ†dÛNe©*ãŸß¤†d®A‡[Ïî&ÿ÷ïÿ«"$‹ªëº¢³ÑðÓú£¤øšÁœKh¦=¬íM3pušiq{ÓÌʯ™‰fÚÞž4cNÕR‚fÚ£ßÞ4c‘‹ãG®™öP¸7Í8Æê|F÷¦wî^1Ëaä·à±`?,l…ªSøðúÂà«z[{ìÜ[¯$oèÕF¡™ö€¹7ÍØfC®jš¹zvšÆããÐÌÐóÜZÝBkºz^§éG£™‹£g8®MQF3W@Ϧqqæ èÙr›Ðó(4s ôì˜ ñD ªQCÏœe=ó7•õŽžÿS=›KsÞÖ =·þ =cÉÇ®™nèYI3–=OaC3Ýг’flW¼“d$šé†ž•4ã4,(‡bºg%Ÿ+ñ6“‘h¦xVÒÌÂoZ‰fºg%Í,­›hMÝÀ³’fVŽ+NÊC3Á³‚jÌ©poÁКQÃΜp;ó7¿õÿû?”3Ï£˜çè„ÿëÔ2ÏnCÞcšé„oÝ-:Áãgíàñ­»E'ü¬Ý¢¾u·è„rŸµ[tB¹·îÝ€ì-ú…’ý%Ê‚,ô7²GÆ’:9PÑjÏêÍðÂ\T{XYÄg¯ô-Œ3¤0ÂÄMß’¸ƒJráö2V˜‹Ê²V–˶—åÂ4ìQè}wÔ€’\¸½”—ï_š>„‘à ¿þºJ1PqÅÒÕÅ_üë  Õ‹^üë ׉ ÕU]üë —ƒ Õ\üë W}¼„\ø^[›Â‹¼¶Áî”xðúY-/Ðס—¦ðf1|¿-abdˆ~éºk¢ËÔ÷ñæ‰ûJùæÜÆ-‘t”M9K™ËsÞÎ/½Ñá·ëÛÄëÓ^ 6“Qm°Î êœåùuŸA…:¤Kó+BQI¼Ý¦~ÆžæÌW©¥P¼|Ž”Ñ:ñ¡Ì0@BWkr‰Xúú;òÞ?ê Ö:-ÀŸ;ï‘ß}È;XzAßÙUn5Wôýì{?É[@qÿ"Ó¶1ÎOxa°ƒ7!C¥Ò*?ŸÒ,Ø'š•>ÄÉ&Wÿê6_×_¡Mž’+øªÑ|Õ‡Ìý{²WèfÞ=ÐA|L«¨šrƒ-¦ÎjeVÆ·âðfùÅoL}3¾Û^Ðøîƒ¥bHØr% Y¾Cób–äYìܶÜûýfõÊ„aÄâ§ø”•Uz<˜“¢ŠnP âË)½‹=¥—Qš&·É“ÚAHÉô8 €n=üâ$K¼ «¹VÒ8wJV è­•nùq~©+ˆà» ªá C óûÜHdÖÞcq -x•ª&'H}Úò>Í0Œìô²+Ò#‘×Wˆ¼-ð³zoýBñó¤èO-÷[ú”½jÞ07¨7*•k‚œ^òòl‹šMÅÊ·ôšŽaÕš£Þ<“²ÚÃwWëT 6…›Y!NÄÓkA¼UF‚2·çV*z¼ó.޼4¯"7%yk*5ñÀÓ6^²)"dá5A+ŽÀãùôìM_ÿðFûÄŸýu¦½ó¢“brî)Xï½cF‘'YB¨‚Âöê75ßœ‚R ð«…@Î\‚I}+Qv÷ùªm¤§~B =À)AW±¾žÓ/䯵x«1•  RË„øÑ³”½Ù™É «WŒKS$H þPK¬¼ƒu`É?PK½•X:8 gÉÉmeta.xml OpenOffice.org/3.0$Linux OpenOffice.org_project/300m15$Build-9379Mjumbe Poe2007-05-08T12:12:16Daniel Kimberg2009-02-24T13:45:58Mjumbe Poe2007-05-10T13:10:53117PT313H50M23SPK½•X:Thumbnails/thumbnail.pngí•ë7ÛÇã®*­]ºEÇ´ÇÚjë‘ kûkguIuŽK¢IÑ•þp(J\ÖÕµ'­^†V‰ãPŽ9%"Øäˆ¶Ñ !­CNFÜBS³7Û‹ý{±Wßç|_|ÏçÅó<ßÒ juÐ @/œ?ƒÝU.b±4ßæq{ü!ó´ gÂnU/Êq©ÏÎÊކ^ÞP8£#žÆß ¸»À–êݶ<ã†7Ë0LHµƒ@µæð~'œg’ üì³±41&øÚsgW>¤Ùªu9˜Æ!-ŠÌkT$¼+݇"þ€ÚÄ:µ½®Õ„4Xœ©âaC4ÞšýxÉ]‰Ê]TKVy¸?ªàÎ&ájÝm¶ºÄ¨ö"Ò²Àè¶û!sS9AoØ–86-‹ÅYáÏó zJÓŸ·­•­÷êÄT_I™#*½%wÄu_|ǽõêzS–q'y±õJã•‚™Mx…² õ©hÓ”ó°×¶¨è3 gÅrñƦõ:›ÃvófHÝ×Fñ(6çàwÅÝð(k&ü™‹H6w’Þ¶Á)ÒPúß||TxVQÇÉÔ¥g³×eUZ{ûyøºyŒî(¶.Þô\—– ß•B— `nʽmjÛÙ’ý§iQ|C1–¢ý´2ÏãïÊ"æ;¬wlfª.5H°UJuçRþ°¸…ï(½ŽûQ¹ }^+ÑÕjðØYVFOÔÕ/¦3Ý ‘ô ÛE¤G¯4‹=>ï°Hã܇¡=ÀÞJQ3lŒØz¢QWä¯3â—Pd6d›lº4çXw}Fð?dý÷©ÿóQþ7ÿs&|rvå–AJ†É lÃPÍʹ¾ŽUÁxí 2;ïýÍ♦©—J $ËÆP=”z1é ËŠÿc0+æ£"ü~óÝm!È…³AgÚN_ùåOPK¬V 7¬PK½•X: settings.xmlÍZ[oê8~ß_QñºêB/tÚU¸zá P^VNl ÇÎÚþú¨ºβ@¤­TÑÆöÌx<ó}3?þXôjA„ô9{Èä¿å2W„yûlúô­ëï™?ûÁ'ß#%̽( L]K¢L‘W°œÉÒzø! VâHú²ÄP@dIy%¶]Vú<»”([?YRŸÍ23¥ÂR6Çñ·¸ð‹i6_,³ÉèvªÇÙÄŸ«j=û³*Îù‡"½`mL¢ÌÈån²ëÿ3W#?¹ÆÈѹóÄ}¬fûä…û»ûód7ˆ?í5Ú0rÅï§ ïÍxl 1F*3ĦDî(p9§±Ì£9MÇ+ KÒ䘒>AT-þ:@áµÏ0YüÕWû,Y©!VÇyü ï˜*•€èÍ<êX6N?ÉCW¼ËÝœ.õP¢Üß?ÙVé»”\˜"·g‰.s¥x°÷ènó…½<æ<胤ÝX›q‚ g„ZñHU8¶›Òéùs¥—9Ÿ_,§¿úÅBžââ€íù­’=B‰§¶<8Áô=?cË¡á \íŸÔx<™®D) æÿª&Æ$PA4÷Bäi8»8Øw%•Mtå@v!ô‘ÑŽ”&«WÐ@ß|B±lEKÄ/6s†¶W¨½!Fjyý×<:L[®1aÀÁœw6‰½›GhúÅè všG*<ÒúHôN$|Äv‘{#5ûïëËdê38¬»=BBá_®?7íÊ›ZªU¥S…MÄò…Tz£O`SO,Íìùˆæ BA¤î%³Ý‰%Eâ¸l€’gîtÜÛX€%€ªIRø;%É6:($B+êí–H—Ðð^{2âHÃYÉ>tÕ˜Roš•Žà hê…ì‚‘‹$¹»)û N‘ú‰É +¦`¯ÎeFН£(%­p€!NS°?OÄÞ€üìçÇBÜø=›k}úýÝ1œw\Ã3\wÞG9›ºõeÕ5– o¾œy†³2ÿ?ݼÓ¼‡ÕñüvÒÌcêìÆÛȦ^¾X—²k¥[xn¾uÍ¡i6Íçnm»Ô2­ñ>çn×4{AÑ·ëVî­g.+¬¼BÃÛÜxôTìãöè½5Z9Û°àYkb×éÖZ ·^\õëÖ;Ì{áÖ€îÐ5nŠÃçu_\æÄžQ™N„A£ŽS^xÌ^½ i®´^Rï=·„¿ó^£Ylša„Gå÷Nß|q‡ÖjlÐh\·þÂ`‡«åTsñkÕ”ÍJëõÚ–q݉q}Zlþì¾x–ÆÔ…yŸÆ 4lQ-s`•kà°Ç¹IöÝ Ÿ]VÎc«þêÞuGNÎÍ·àÌŸØ,w߆˜ z7î‡ÍñÈÖ¾1íÚ²ƒGv ¿-×°iûç[ÜlLfµ|Ó2Ë}wX\àú,tïÎ,éÓn81ȼiÏí¼W_RR»]8 G½K gñp+BòK“á2El.¡ÓYAÔ‹hRd§“&c\%W—'²â+GØ&sF¿ÀãexD·›.¢Ïô¬š®Ú ˆ!ú ;J¥k1î’ˆ*Rèòâ-ݨ¤I=´ Îú²¶Í*”Ë4J­¤N¹‹husϬۣ4Šˆ'ùçmJè :óT”VšÔŸ2Þžâa‡KÿWjΨ¨šò£6™¹MðPÀTaÑUR’¥áÇJ$“jMÖú³Ç#áÞ&¯Ì¤¼[÷€•¦…3ù˜Üíá.±*oqUA¡Š© ·ÝŸ²Í:_›ÛK(K Ìæñ !iTà›zªõõòiÛCW&­? C"U BþYT­p ¤'(ÎPj¡åa­G=Ô˜ÒÇDôÉR áÀÛ Î’&ŽK’6ÅW5 ˜è¥UÚ&7ÆiµÜò¹ä-Óq¤`@’Šå_îôΧûÏ7‡¦ê)èl.ï´-mã,LgO ¨ØÚ`½5S)¡+¿VX<•£Z7ø‚ËúÖ´ä×5§’,&¥ýM 1£øl:lóÁ÷iú²™­‹1FL¯ŠÿˆâNjpÝ}¾‚Îʈ>(ÑsÞ×µ»àxVô·Â÷3×S§ÐŽm‘`´"½=„v§A*ÏéÒ-#ðq‹DñMq í‚{R,?PKq7ÈØ{PK½•X:^Æ2 ''mimetypePK½•X:MConfigurations2/statusbar/PK½•X:'…Configurations2/accelerator/current.xmlPK½•X:ÜConfigurations2/floater/PK½•X:Configurations2/popupmenu/PK½•X:JConfigurations2/progressbar/PK½•X:„Configurations2/menubar/PK½•X:ºConfigurations2/toolbar/PK½•X:ðConfigurations2/images/Bitmaps/PK½•X:Ï£€ï[[--Pictures/10000000000000200000002000309F1C.pngPK½•X:M_06 Ólayout-cachePK½•X:‚‡È¶AÖn *content.xmlPK½•X:¬¼ƒu`É? ¤styles.xmlPK½•X:8 gÉÉ<3meta.xmlPK½•X:¬V 7¬+8Thumbnails/thumbnail.pngPK½•X:¼!Õ$ ¨=settings.xmlPK½•X:q7ÈØ{äDMETA-INF/manifest.xmlPKƒ¢Fvoxbo-1.8.5~svn1246/docs/dbschema.odt000066400000000000000000000722231153177201300173400ustar00rootroot00000000000000PKJÚ<^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPKJÚ< content.xmlí}ÛŽÛH²àû~Q{`HU¢T÷™¶Qv{¦½p{]žís°X)2%eEªy)YóÔïû°Ø}éöÛü%™É‹îS*Ò¥ÅÙ—HfFFDFFDÆåϯ¿Œ=둇‘üïNìÓΉÅ}'p…?üîäïŸþÒ¾>yýê¿ü9 „ÃoÝÀIÆÜÛNàÇð¿|íG·òéw'Ièß,Ñ­ÏÆ<ºÛ`Â}ýÕmþí[šKþÅ3oëÏéåü×1ÿoû1¾[ø–õ·Ÿ™^Îí†lºíÇø. 5ÿù Øöã/‘×€õñ„ÅbŠ/žð¾;Åñäöìl:žN{§A8<³onnÎèi °“¾7IBÞr3îqœ,:³Oí3ýî˜Çl[øðݲßü̇‰Çµˆ¦"Š6~¶ŠáÕï,‰ÜeN›ÆIwýw‡0d÷&P­Ž4žýýÕžÀ~ça,x¤^ž Ϻ«Ó #•$æ‰!lí1 ‡ÂO×1f³v?äì¡Ýçñ”s¿S@È€y‘\P¾ÀžÞ-T/ûsPËW¿«5Ø"åù{íâÃë«ÞÕ¿•‡òy(O;ÎÕzPÏ{;€úÖ8¨§ç77½u ž_w..v€õÎ^,÷¼yPá§< ƒàvÂ\iâtN;Ý‘~í¡‹jkG!ØŠO¸Ö¿tèÿícw_0¶=>ˆWš{/üè>Ïÿ“ÅûA£fjùok³üÍ/î!öyƒ¤«}Þé P6Eº¨‘®HüºKW„±6âåðÒÙ©6˯ƒtí5H¸öš [{­½æHÖ^ýkïYËÕÞQ¬µø‹}ÉÕ²pìAföN¯.Ömñ^÷겼űÁ¹ ¤×;@jNõ®»æ·úæ¯ 3û雽!ÄŒæäó^ˆ¶gytú¦6˯…€¾jâÛ½j‚æ P6EõP£û"ñë®ü"ŒµÑÿž@º^Õߢ›¥AÂÕn‚lµ#ZíæHV»þ‚Õ~ÖrÕ>ŠÕâ9Ói\ívš XʦHVµ1¢‰_wÙŠ0ÖF¼<ÒÚ9J×"B–c£¦ÒµÛéÚmŽtí6Hºv ]»Ï[ºvÒµ¨Ë7)HÖnD¬Ýœ Y»AA²v‚díç$kƒd‹iRŒl#Bd›!Û ÙÄÇ>ïðØctl— «—M«—«—Í«—{«MŒGÒÕý˜¹|ÖÇÌåñ˜)š3M F³Œf7'ÍnP0š½Ï`´&ž5H¼º6öóŽÎ³ÑyE„4é´iÄaÓœ³¦AGMžŸ·\=ŠÕ">zãGÎo.®D+â¡4û™§öÅ5nòÒ°˜—§½åõ•Ç‹9‰ruý”º+}^žû^þüªÊíÎ}/ß °ÞõW §i½ïÅV£µÙÅÞ-/cQwÊ:vNßì{ùû¡µ™åï-ר,{9u//nÖiÖöùùÍeéjûÈ&êœ^^]¯M¶¿¸é–εïí#¨szuu±Ö´º¼ºÚÔïƒz~Ú»¾¼^[Âàº×+_úeŸ©OMtã!ñênmöžw2’¨6˯ÃÉg7)_ÁnD¾‚Ýœ|»Aù vòìç¯`óŠé6©†A·E ºÍ©bÐmPƒnêtŸ·îÚ=V2˜S柪’A&¥ý‹(dÐkN!ƒ^ƒ ôª2è3ça‰ï"8Aˆ,ÈühÂBîÇ';‹_=onx1fCž­n)D¥×^IjU[ûSˆõ¡µÚapX´îç¸8¢kRƒw%xû¨¾»ŸÓã¢9‡‡ÉBÁ{RÌM–Å­ƒ/ÍKµY}ÔòîÞÞÊÂÑ™ÙmN6[·AélÝ}æ³Û(ÏZnv\E„Ø5‰B±á¶›ã¶ä¶à¶Ÿ·#Ø>:‚çN’½U®) Gg·9eiº ªKÓm@ašîó®LÓ=–¦)"äºróº bóº1Róº9Bóºþ2óúY‹Ìë£Ä,àcohK‚щٜʲ *,Û€º²Ï»¬ì±ªìœÒ]‰¹Ÿ|öÎeç|Ý¿é^–7$÷’XwÓ»^›xÝ휗‡tbóbƒ€±yY:]±ÉÏ;wà˜:°€å^Ímð!Ÿ=â_óÚJpJøÛUÒ%¾·Pà²p4A1·›æk7(Ì×n@¿2ûy÷+³ýÊæŽ™åU?¯ž÷š£Ÿ÷š£ ÷¤¡÷ê/=ÆÚˆ'ÐÑ{Gé¹€£–¾ýéÛ¤Vv#Â‡íæ„Û ¶>l?ïðaû><‡½¥ªíCº6"¡ÍnNF›Ý ”6»9möóNj³Ymsª~Mbåºû–Sà­Úä—½òn“±]½ëî^ìy“Á]ó06‘ËíªîÀNïB!A²·FBñGµâ6ÂÜ3v÷²âÅùUwÝæèvËW¤µ÷áB¼8½¹¸\{X__\•WLºåªn‘:TyEÚÕ]®Ù&ý”{!Úž¥˜ÁÊõ ë?-ðê„…l²ÉH?5_ÚôG;‡ÆÏÝÎç8CL¤(K?žÃXÌ¿ÄÚƒÅ,Œõà¿&Q,³v£ÀðSX]ÎbTtÀ‹ã „Hü`±í‰,HC¿M¹Dk?ðÜteúå6‹óõ'¹‡ò+ýxù·N0žxüËê¯Óèûí)°ÀŠ•(° ²¶EË’uo¿¬U¡™Œu\-\ÔWò×$‚×…ïÓ6aÁѵ¢~²Õ>õƒp̼]wꪯ·ß«j„íIµàE«©¶\ÃÂ=K©5¼<Âè~"g¡é`µu}Û2gÁaa– r`ÊOßI(xh}äÓyÑp³fÑKŸ¥k¾)µä…ìœ'^rIa8Š’²pÅ绋ÂŨÊ}Ê‘¥[«æ­Ç×-o¶J*y‹Å[ö*s;åuâN%xÅ×;£k7¥‚Øêîl#¦Vbeë®l7½¸ÌÊèér@C®ô¼‚DØM‘Ý…lK ß(«K¼Ý´¿üúÔkžˆŠ/}°3aÙÌ»él[ÍÜ]?ónZÕV3÷êÌË{VžZíYz2½¶{P­äÛ°j?-z¬aÕ5eÝO‹¾Ûm€U’DÄ`¹9«%ÉÊç)´êíá]¼4+ïá%ß§ÅÕ2̰σçÎ#°áÍ¿àñGîé-žŒû`†É‡ø;l¡ùg^|¤×ÀvG9p?[¦ÁM0,š@÷"ÿc” èÇ—ùŒ³h¬å`ÊáN‚0ao÷9|Äѡߕ7žøhŒ7¤¬¥y]Ý”zÝRK ¢»l1§Æsеôö»–«ƒ.æ|Ÿ‹±¹’‹½®äÀûår¿‹9èZ®ö»–Ãî—ë}.¦{È•Üìu%Þ/™“p?«1±˜Üãmî¾*X2«4ô^sA?o.èÍý²¹ _5ôëæ‚~Ó\ÐñH®ì%OàÞʸŸx7žÀoèµÍK¥å˜mgÄÂïN¾þßÿ½?£^»ñ^ù>f¡„{r#¡.§eÇ}<ý¯½ù žMËT‹ hú?ÿo®ˆ'ÅÓ2=æÀÛn+/Ç“"i™Ætà=·­åIñ´L=;ð¦ÛÒ7ó¤hZ¦ zÏ5A6-Ó;¼í¶ò(=)’–i¸ÞsÛ:«žOKÕéïº-ý`ûÀÓ¢ê~Àò~Ë’8ó@8òAôêÏê…¤àçp &‚ÀƆ\–ÐÝÔÓ·ÑâÀ;Çpœ~8IZh@=œL¼YÛå‘úíqàò\ ®Äÿ-á> ÐåŽ-ûQåŠhâ±Y;HbOø¼­ˆ®i.öÞó’(˜À_>C‰Á(¡ú(ðÏʃ|²)†«§\°k£EöWqîÈÿÚüš›LFæ,#n 0‡%|‹YnßrEÈ8gÖ qÊO[–~Ò±¢— ’LNI¡ô_• :—ª*ÌÃ¥>Vi«_?½#L–ùâÍüa0‚ãºVO xS<ÿȼ„·ãÙ„c¼y(ó “EÌcÜÒ+V!j‚´››·$oª@;ÐY ÈÙZ$•ÆZw7X—„ÿ8ð/æÄ§À’¯_¿6†LsF£ ñ\Ø"²úÜŠ8Æ9ÅÜ BK=šrK`DÅ>°Dl±¶XäÀ‰±~=µ¥É$,ü hRCz(àäd-kD±7³„ÛPTóp,¢´¨–è>k:C>T~ÆçµD§ÐÂç(4‚0¶@Etx5“s'Uùˆõb=äéÂõß*Ö£™Ä÷!ðM*IÔϬøK\C¬TwEÌ]«?³FÌw[ ûò—MZm½ÑOƒÔT¾Jÿ‡Vk_ å¤ÖTÄ£Ô˜¥5X.‹YCiÀI7¬'þÑcY ȦJ™8qgµDpÃtïhÅ||ĤÁ_F§õ<îP²úÁXøÌ#¹J°¶æN@ ÿÈýñð‘‡Í _KŽ&È„ ˜W4 Aìœ6Ë‚OëÊïðMâÄ hpÒ æ™=ÿKEgÀcØ¡1×çñhÍzy>%ü#‡Eź:ý‹õatkâQYÓ L¹5Æ 2kÊÐÀò9ú:90¡Ë™õÀgø;è¿a@mçHÁ}g–cÎíàyË|œrˆ Ëý:áÃÈ„°<ü“õðAR¨Ï"þÚR·0gó_¡’Àò8**Vô{eÄ£×síŠtXŠxVáŸP0ØX%c¼u±˜Ô×÷ßÓe i±t²‚f ?÷¹•øâ·„[/¯Ý€f^hÀ±CF/?£ w 2ƒ_/ÁX(0ZÖ0 ’IËRNÔ–ÖÝZjËÿÂ7QÌ|‡·ˆ³#©^³@âœfhþ„°©µ[“ÀÎÌò‰"ä”aÄK' ŸZƒÄwÈe?Lµ^Ü( ¢átœE€Ì8ÄÆÌNàJ%Ùs„á W§¿Fg*L<9 ⨿Œ¸ŸÁ h‡ Kø!K!*éÌAs™k"X€±áˆ¸·6| BhàKÖGÙ0fl^šÅïä|0•vk#7Kø~KD(Áà_`–qÍBä[B ü®.ÏPÍ àKY•ÃÀ[Bæ õ"ÉP¢‹ÁÀó¼€”îTz!!òCq'Ní/5UÎËMà#äGZˆ~—X“p1 ‡@›!s·r|<ô‚>lå¼ã<Ï‘¸£äµ Š Ñ8Ñ ˜‹l[TIʊŘç¹DUàÿ+†üSœRÿÁ¦òJNÿAÿW\\ ¡ZL9¹ GB ær¬Œv/ õ^-ÎðnNn‰ ©‚¨ ]œrŠGÃÞSÇ ‚A2 ð2(¹e¾àõ”€ vŠ^¥“òI ÖDš3"GÍø®Z0m¶T„ç’ÐÒ†á<Ù¥ÎÒV_ ïÐhšÂ/˜?ËÏKbÏ ^âs`_à (˜8*B ¸^TáRš“>ȵâÜQÐÊXXŠG^t9€á]b*#R¸´[`ƒ`pBJ:H 6Æã¿“{^H¹%GØ Lg^–(à& »(% ³ƒ·{þT±^À¹é«­É<üxÂä©ûßdŸ¶Œ »IH‘ [œ³Ï³‡¢ØšT’”­%QBÀê ©Â`ÀŠpp_¼Ä·Æì(–HÝf(ðÓJó/bœŒs¥I’àA^=î–Æ Zf1çìÕGÐØäÆ4å©*µ­( àlGýSû]Pœ—ˆ÷…Ñh/9è°·uHÐUvz´à-7('‘8r'Õ¬Né"¡X” $!µpK:4ˆ&8¡•êÑÇÎ&yö†~°ÆœùJ Í‚$ÝH:ýpØ(†£@NÒ—4i·‚Œ‘ì¥Î Ky:s=–ÀY ¢®0°8jI¤±@)9•CGO_Ã,ñbz—u `žÚŒ_ÿOT¬}âu)n™ ›¤'èq°I¥N œ‹r«de0EѾ®—:·ÌÜúD€¥¼`úAWmïœ2èAîèãø©{òj ¸·>`æ@€à«¦àx»;{÷W@Ó2,qk~Þõô4СÁöÔ4]á0M K¸$¥ÿMžÍJpÊ{jߨò9¡Ìõ ©U« ´A#ÿBóA¸‘ÔøÖ9ãZ©ç*³m& ² š áéñ²™Ü•‰5d0ùM Y ”Fº|oša8•Ÿ‘qó’x®o½ö Ù¤¬“U€š®Äʪ(Ë5¯ä×ý x³ð!Ÿ¯ðùóÏ| ÇøÜ;ï]^öº—pŠJsM7чhst[n1Ly?:W¢¯ ¸Yÿú÷÷h¬ƒ5!|yc£ P2—Œj«»(†o½Zû¨Ž9[äsFdRÓœÒ9«¼ßYÜ8FZ·tq'| ç2Bé˜0È­äzóþl´kƒ ÷—˜Uøˆì\œ¯@Èö‹ôep„ž!L: |WÙ<¸€9'¿¤+<ÃDæßP:‰µ5¢ìÅ[¾­°›Ç’v+NÁÖÆWË\ã¿%ÛÒ´Cò£;¬¯IA›ƒ<ËùuÞa´È¥IrÃèaäú]$š@’ F!¹ýS°eÑ/+¿>l;Icñœ°è¬³™cîÂÿâ]™p‘VT>ÛK.B :O øÚlÎØ€¶On wÄ"oàQE†pž;\´‡eì±éEŸyØ¥1êÜp ƒ²/ž“ä®ÈSæ¤ß_ÏŠàPé=~˜§Œ‡—=Ѳ©Éû†~†×Ò‰MèRI4^î aÞƒ–h­lDGÜÌ¿•^Ãå}ás½“ž‚1z.ç>Gð´+†fBð±I4t%“ùû ÅMê†*çñD4†‡I°LlƒA¬ø ŠÁ¤óB'Dô=æ?À@qt£—¨„—`rR×üvî•mœCÄ^xÐ$íýÈI¯ô‚–6iVäñU~홤’ _tÅ`À±L°%}:_’ûކ¥ K蓘ì_ÒÒKV"æUYé-¥/+¦]ä÷‚ å9ÖÀw-ë”Èo­¸¯Wð²¥8Vo%ü<ž©NÊÄHºY¬oSQHÃö˜’SP‰*ëîÍ[ø¿ÑøîîÍ›·owð¨¢A'”\”hîÂ&”{T )Åx¥ayÝw;Å ã øêg4Œ&^©‹s½Ý~Îÿ-E¡¾b›L8 —ŸI!%ÑdZG$»­a@‰ˆF*aJ¢ è}Z’—x¾:/ñ¼\^âyé¼Äó²5ø¢šC ܧCMŠçA°7-—ôèWoâ¯þ´Š€ó§!GÖØŸVMK¬5’Xøô©I¸_·M—yQ@ÔÓÑ¡®ÑB8‹QÿݸÛëÍE1wäƒM€eõR!§óXÿ¤J‘¥Uݱœû˜aÜ¡›V`ØôÎ:•au%ƒr… J×1XRÆ`Óo³šó»o¦Þþuˆ-¯ãš§@ìmV¨‡1õ¡WkíÁxðº9åÁpj“±3cw‚.ÂÕ@úº^3 ˜±Ûµ§ ívç{)“¿{±:†æ¢\ ÍEéš‹Š¥ˆpÊ uN^ý@ÁáRL¹WÉ÷~kæ²ì¢B¹¢ÎÂ-.v?o°š^ÒlcøÚžëÚ£‹¹®ôóþ«ÿ ÿñ¯ÃøOÖÿ@gcÈ`ÃÿyDâVH”׈Eú×»¡ï ƒÁVYéG¤‘¦’IH+ƒ4º¶:bl;'3­8pÙ,rYl(üóÙ nxÞŒ³0’j…â¨|‰‰:n0ÅûõÓ᩼ÁòƒÕ1ɦbÌë‰è †Ö®a4Fé¬òOTz6õ¥%fΠ³ o£™7@žã>k©[™v'|Šãš¿^zw9èÝ“Wc&”íVþVçÕj«óªœÕyUÚê¼*¹qU5sãj¿Nb]»—XEâæ¢=ZÖ$˜$eÇÑÕâa*p"ÖêíEFìÖÂ\siWµv$WBSGÌœó¸*8&é«î¢ ¨ºÔ„£Ïžœr—µ!Ü¥a÷ozu+ñMá‘*Áo­Í§ÄÖw¿öêh±rÁb¥cÅJ‡ŠUÛsæ¥ Üòž—BX³Àn ¾Ô–­y ¦]“£ºæÆj}PW@ÒeÊÔ¦n+³U ÒöÂý©¨$K<=‰^õƒÀ{êM`ˆ¬Ðò!•d‘ù*T÷'-õ³¢¾¾‘L_ÿ¸­ngµÞ)gwJ[àÒx§ªÞ9È þY&vlwŽëJÌËr9’J¡PÕk"ú¯“±uæ‘L˜Ìen¨JёʟEU{Ó‘ÕÖ?“ÅšÒŠ€Ùs æ˜`-/ý{È< ™—þ°±†æ“«HþZè1ç"èÔúL«‚&<Ôˆ3¥÷W¦šêñmÓic®ÁaÒP‰`»´${ å¡»Zyè–Sº¥•‡niå¡»ŸÈo„ýp:Åç1Ç¢‘˜”P/$Óòw©‚ª ™Ê¡sJCúÕ†~¡pžT6ü™%—Jµ¿æ´ZýݺýÕ1wôwkít¨‚&ó^‡jÐT<û+êgEB™ÕѪc®æR%š½J-;º‡-rÊÃ(»F èH¸™š‹I’ÿ¤`#š "°W—´Ë•´K—´K—´«–´÷\þq1ŠqKíBVHIU‹65Øã®î±!c陞,ñ’S80P×rBcoÖÂ"ªd)ÕëëúõYI,2ÎùD¶kÀz¼éD¤¢h&?I®pmêæ5¨ð„Ë™'?Î\|ZRETÓU|½~.–¶PS+ÔÜ b×¥þeE@Ì]¿Ô»þe4Ñ÷K{F»©gÑà $]«aFÑz$ï7K^ÓªG ×ÂZD‹ð7 žI°ž-C>8îà`a§/7ñ²ÎT«@bIÅ¡õBµÂ˜Yhu¨ú†t“ú °:'¨ý€òÒ%akÂ-ù–tub“…už±0#’»Gqÿ SØåyå½¹x+£òÞç²_ •q•ØK½,è»iÉ®ÔïFÔ$Ðj›w²‰=™«Ën–«ºYºèféš›UKnî³âfO¶%|kfZ6mÊ>ÿ}Ýxu©ºY“¢›&ëòíýp1\Ý0qg¦Œ‰ Ô¬zÑY¡jêî9÷@2||$Zcˆ6Gb=rµNqº\©8]–Rœ.Ë*N—e§ËŠŠÓåî•κòfÀŒ¡Õ˜Phzjƒç²&ZY58Œie—µ¾YÝIKŽ“×nF3æÑݘ‹P5¶Æ´5£ôÀš$/0ÝPø”t.›µx lræèFຠÕF¼Ö•)&,ЦAXÃ_S¦hÖž?î÷2pé,Æogw65µ=Ò?_é›yÂ¥xOBœÊi$åù˜ 3W"ÏŒò„8Œˆ yt°‚…FqŒ°)¿-\HnŒ½PÇX aÃ5g]i¿uÛ‘ú® sx[·æu Õ tRµ{•ý©Ç'v3ò‡Í” ca(Kù9pÇÅÙKrVµËµKµKµ¯ö“‘l_Uò„Õ ©X®éªÖŽb».åJ+b. §ÞåJ+ i•²a,Ø(hæ€w'èîJèk̃d6“A»&I\ð!E£ TÕ¯¤9c…Ø0çÒJ|ñEÕ¿:¤ƒÉ,Žì±{Œ±Ñ'x±æ™Îì%¶h&GSƒÏìx$Ì Yíh¦.hd–$½a dµRÎþ(m~”¶>ªv3Øg3ƒžºN§؈j$ê^`¨.ê|M´ùz+óF¥#0©)MÞ$\Õ¬çFéîFÉi2ŽçHϧ§gþ 9uÍ…·L å ÝZ?½oY?ßµ¬’ U=¨€)pÜÆëq¤ ,1KgPNõëê ô®uÃtÛÑ–Em!eÕkjWºsÚ½ÎÇ‘rQò *E¥+[cëç 2_üƒ»–ð〠ÉA€9äxÁIk‹ríŸsK^4z«Ë¢öÊ•Eí•.‹Ú[RµÔ&ìuwöØ/á0B9>5s€«3Ò8i‰§BPrÝBáS*¼.Y*㘑à! ‘¬]v(qÙÛ½Öá2J™ìø‹t2é÷YHÐ$rpsn¹a¼ïh×®Ú!òÄ5†zsÐémÁœ8až” µ€­¡xä¾Ú$Y½´AYªlç)ˆú5 DÅ#áN"Bÿño ÷f–pHÖ7•q¤B–'p&ø°á»üK®„à'Ð*8ñ(äÜ¢&œÂW1Ù‘‚G+Õ '^,&©V¥‹  8Õ|“Nâð/cïV¸ßàÝNïúææò¼ws²¸ÀöIî»¶ˆùxam_ÈŽ¢ñ4Ðò ë;œ® 8®Y-ß>wCÈ3+pœ$ éx̽«÷ê ð€åõCæJ”S6ôÛ…òˆË`/³ÙÜ,]Îõõ÷?4Ö¿þþOY" âqŽŠw¾$,±–—„?…Y›Æ~Ãxd`Iúà>‡­3\âÁVÆJ“˜·Ò#4cJTf$üS[ ·[Ÿ§h.r+•Ö"ö³¢dÂC‡»ÔB$ôàÜR|¹n‰Ù[úG·ÚŸòk‹Ò3tF¨ñ‚à!W܇œýèþ'Iµ û–n­‘­nQ×+×£®WºI]¯t—ºÞ’6u¿ø¾šÖgï§aÛê3s~U„$äÎâh½s(`<Ζ¸Ü8ßWgs)“jÒîmÀ–ªIÌ7FRs`ýG aúhŒ×ÌzŠêTVj&½A©ÍeÎ[c7'5å†:îƒJ†}$ù«‰ƒm€i,©Zo¦ôøÆ]Õp¨ãVÙ«à”$]ôL1kãÙ^½À$ÿ–™£Ž›È´•¤T’ÎúM$mcz™ô#_Ö…/¢t3Ü|Þœ°p} ̆3Ba2ÈœÑêò˜ <¬èÛ"δX?H°­ÌÎ|1žÀ؇˯4‹y—ƒaÈ&#áDä«!wÅi="€öÈyÛä§™ïÈ|{a>sUEެwd½½†šA© ;í3*⽟]3«š§e)—(ꦓ@`Ä8  yå>Ødâ _Ÿ»uƒ ¦›/ð@wÐhwýƒ‡A~‡Ãä>¼ÏÀ 1΂Z ªë€òÍ·É$P÷~à·óÏ[òº8/v_‚Níx‰«.ÉåË‚bð‡…®ÛaîíHx.-2mÉ< ‘‘ƒ8¶u<…žL7žlYQ W9å.ò~‚âKÙmx1R±?³&aàà0,1 'н7aøßBgÍ»'–L%x“¯¨ëóiÃÆÌÞΡa! ž¹¸é]ØçWWËRº¥R.õÛ ÕX6ÕÏ“˜ŽøçëïÿI7úiÉþ|”hµ@ javÍ­Ã$Š ô1 HF[ £¨pç²lJãì°L– ó¬1ˆ2‹ŒB–uB¢ä!SD/60e2HŽxHÄÖ qÊO[z3b¬"l ¯¿ÿ¡÷˜_ÿçËïü"Uø#¬<¡âSæSÛÓ'ÂAÕDÞ¬ôö¹—H´~Éÿxs/CZd›U!üê'µþ=  I˜…꤬`Í»Gd|̘xq*â0t†è›Æ()6{ÁòÐ&Ï#æ½ A¤¹Ó¸#úž ¦öµcŽ7œ1Œ‰Ü•£bx`µ Ë’‰,Ÿ%#Êb1æQqª8 :£ uÉœKàš_tðÛ ެÞË…¹Óïpâ¨%×ëjÚ•SaXG'W"´øƒ­~X: ¾ æÀ÷IÀä×ò³ùÖûX´•H#~(â4‹–[%ƒñÔ«tä x@L \M¯Ñ(/`Ž’¾$ŒzC’¾M#ÂhƒIÙ™øþ‡âÇsaoò¨—a ÒÛâ=f±jéžêÈ6¸Þû$³hùn`u$ný4f9*¤G*"‰„ÏTž¸}ÃÑ3³04Qç(œDä¢# DÂ2bþŽùq¾Ë7Îö…áSlö­aÆ­"M$TÕ¼™<¶ÚØÆWMqŸXûA>¦@Ô!òáÞ„0¶q¦|€±ô*âßø¼"œX”^d (¥`•¤v{Ñ¥—SDZJ;ɵ/…G•»€ Á±‹:’¿,ÍYˆËGŠ ‰RT·2íØÒ™‰Œà¥ðM­ ;׌#ߦ{yí-P-º=Xä‹Û—È#!s0l…5Öݼ…Œ¦-¸R~­_ÊÊæc5e{îYú< #Iú4ð ~:„£NýiKxí—Eh‰œÀÇë©P#Ÿ–®NÕ\ñ>6¤šÉxÄd’bJ„x–ÔªrEº²y•Ë#úΈ / .ÕàŠzYÁê`v`k_5K÷Ø X¥4?i ¤Õ°eŒ¤½:kÅ.—µb—ÎZ±—d­lü¢ZöºÝÝoú:I˜Í”ÃTZ(¡—³¸è[¸?ž²‹üîé'†ëWUÄ\ýªn“Rl+`m‰«N†OMÏ%™+]òŒÉkì²Î,X&+™¤.e¬‘΢M J"ƒÞµÐ^jI3WëCèÅÂ×¥þ‚Î9 |Ò öê¡®}MSÉ`{ºç ^‘%&5þT¡åÒGµÅ9{¤EžXÿ`‰§fi«àUC©«ˆiØÅ`D9f²`ÌBf®ý±Q€a.O™ƒ^b±™Û|’ô½#”K»5e½ éÀÒcIdâIàÐ]PyÝ`Ÿ7ŠŸmX·Ñ1ÝX“`’xtx= –pÑiü%FÏùù(»} éaVÎßÜYÑR»Ò{¥LbEæûÂÔ™ÛsJv—^.­.!7g Ò£ç݇„ä<êÝ0ÝÕ©ªÝr©ªÝÒ©ªÝÒ©ª]{?Ì»öž„/©K²òý«ÌEã ¬9áÄ9¢Þ¾›îîñf}71æ»A>nŽnVkËt3deSö™YÐŒÙgFéû*»$.9êédÞœ_[0é¾{tϹv²&7">t‹›}Ècî>ÃÀ™³ÅÍrƒ¼lüúû#PC¹ëƒJþõ÷6™\“'«Ig~º¹äÿS²üïôc>Äë{yV&ÅGäb³p-dÙatþu`?ï^8‡ê’õLdGßc# ÿÓL¢/FE ¾­ê†ú”f¥û@¤ñ‰ /:2RJÇSG/›É(caƽÿL¸Ð%+³5”ÚìˑڥÐÕdj»|Àïx ”GY“©.õ=ô¶›É¥}&”—iÛAY,áb‰X†ÉCÜÍÝ••c,P%phù¯8d~ÿP®ÚO¥ãW¹ïf…^1¦_ G±¾z[Å ¤ß›Ål'p"Ž—(ø;ÁD!²ðYµ5{¸ÛZ} Éý<*T—)c¯¹"N!C%+o˜E`¸MÔÝ‹gÒfÃ< ˜Á@©|sÕ=]Ÿ™âË×”Ò'¦Ë®« !F2(>-ë+ÛºÌjgu™ÕN¹2«ÒeV;¥Ë¬v*†#{»¤º([ü ¯“U¤êaòrÉ(XæÊ;vštÕd‡ù³E©›³°»i0J` %Õ.)aË,8¶Ó4½BJ¨r%膪:ßëpÕƒŒÒÇè5å³`–V¹×m¢RšÉ ŽÏ‚’H&oÏ3Dæg”NÆ8˜ÈÜ´%ÙôÍá%莢¢ŒS:c }N8CÅÚ5™-h‰GŽ(….ÙÎ[‘D˜-«"Ru1,粬½M1o¿™Ü²Ù/÷DÂÍœ[˰²áéVHø˜¦¤¬ú&~«*'”?ßxȬ-lÜÚ2 ÿ2áæ*²O†ÔWf´*qwÔ'¾Y ã6ùñ:ZõÜÁä•ÀBEg²´ŽnZ–»_ÀÂ?Øtmÿrªk’;Z¨¤ VÑÊÜ!Ö Pl‡aL,掅_(³fÏcÆËms4.Vº¹/Jy¹/Ê:¹/Êú¸/*º¸/öìá^hÝY‚±d“, $«ayëQDBvÕjj½]çµôœ›„ʘãü¢I” îÍ£a6c Èó%¯aóHÞz‘×hý‹#qëE\ÔÏP®u*cæÃó¥°®ÃX?×rû¾b+µIÞÕ•Ú²†@ýhm¬H…YZ‡…Šê2þlIqвqrõà…Íí’ŸHŸ0v`”pÛ·Ó˜JBž.„¼[wß%¾ Ñ"$ÊÐDXºª }ÄX½¸MwÙߨBš”£mýJŸ0µW‡Lú®,­b,šoêK1¬¥Û§ÂoºÔ.Í]¬qk@E‘å=<†“:0Ø0¼º…7¤ç›Dxq3‡(…P·:ÀãAg!F2 vË„DJt.?å}>R6Q-qÂü%ßÛ \±‹“¤ø< æ³8 ÆÃw5pœWù¨ÔMÃëVT‰Û)Ž3W‹×c1Ö%fºµåŠ;1È-€¥Å)+KVANÉÌ–FÝzICWF«Ø,'‰b,ð?µæ Édi¡¹5¼Ã:#™¬ˆÓG Y iËK{ô‰®(͂î,³Í³Û¹!÷]8Í Ø1󸪙ý8àøó\AõB¼ÝÓ»¹ïT€š·ÈXU=}d½ÀàsÕù鑸XS›»å‹^*â1ž Jë‚Ë=šU ’ØaQb9ÁxŒ §šèNà?ò0.T‘£"è™ÂVý@ú\FX3—&—¢bΙÑIFÄS•?lØ`\~Ø×gîdN*ïf—ìŒÂþTÒ1óâõ˜²KMË{Ö>W•öñCgEÀeWÅiª±HnU?¨Ö4W&Nœ„YMËcné7ï^®®mtY®¶ÑeéÚF—¥k].:ÏG@I8å`çE´„~¯µ§s§Ý†ÂFi¹{%È©B_ ·”¿T÷ŸíÁõ¨oT sU.›d¿WÁڥ̱j6•@©Öj¬ÑVÎ]3*™dð†Ò‰ú8+ˆÇNÙ ó'%þy$Ÿ"ßwãPœ9ñÚ ñÙëLz:³Wø¿&!5æA(ád;«Ò–p^¤>³(æcPj)M5;ÃyÎTÓ,T„Ë›GdÏwËÑ QYŒØwŠTå©¶–TsÕÚUI35„ÒI4ºöºR|£ *èшó4óU¨n0ô9´¼‰Œ†6|±tPYÊ—ùófþFVVËûØcQ%Ýz¡Á€KC~é(©Ù–†åŠ1}ù†\ôMÇÈÖ±^ \ÌÁþnê!Î[ÞÐú›ç¶é©•#?YØ|#¨ ™Ò_ÿ±‚­™T:Řy;2ΖƒÆØ¥K½…c€ws CÅU.+±ÄþÓU%–r&v”ÕìSm¬räÏé§éßžoµzêóE_oýøó{IÝ–YcŽ-³D4N£“°h\>à Î!o~‚ê­&W;P!WrÉ©Ó#s­Ì{UÔ¦-Ì%³Ãæ*R½@ ”}ò§~ÞÑTšCÖd2ÿ„†²I`¤{5a*²æJ¦Ë…”eP-Äd ;PÁ œd,û·)ï6·äfÆyý) âp!MóVÎ 8×ÄE£îIEÆzðÀ_¶dÓ¹Ðëv…˜Þ'±j *?•óçßÎ6Â’Îdj>ü½°ø¥Žc‹¼FSâ`#1‘©á^€[“âÓ¯¢| ¯Eç'zKPØä eZ *¨ù¡Ä‡Ež8XL^\ÜGrÀmÝ öêÒÉv¹ÒÉvéÒÉvéÒɶ]µƒÕžk$ëM°#ai45­wž]—RÈ1fIÙ*…\k—ŠÇÍ5§©Œ¹n4»“áH}Ň2E+âÍpüÜ·AźïY¶K7ºÁ¢a¡;§®/¹à<_}Áy^î‚ó¼ôçyé Îóйß.-l›Ü •æG?Dÿ9µ¨}³'Ù´hæbÓçÇ JŽüå);µœ×Ä<©ˆ¹‹žó&™'°¶­¼j0u±i2sm:L’÷ð–ŒY¬6lžÉ›¸£MÊF³qƵ$ñ+µ—…ŸI/ýf4Ö› Œ¢fa3 ÖlsÊ`_BótÇKØÒÝdýl³»ð…IÏÏ.¬)¬vÊÓK¦`r°~؆7œ4K>£”«!_ÔóØ×ª1…¨v*žð¸ŒiYé--±Â±¾¢³IÙêS†×+ý×¥Ü×e½×e×}×ûuœ68 ² ˜Ùås$ã+²‹|ºUç"´†®£¿àº&î‚jpÓˆ¯›dZ쎳erš›,b4SGˆIêÞW`§†]ß>½›µ›Mzþ¾}Ú¾ &ÑÆ<Œžu…CÇ:y d̤ ÍL#U±VEÊ5rëcÌj-yà i”;ýG¹è߆²€{dC,à6“ÌF²=ƒ3b;„Õ•Üæj“<‡ý¾ÇpªžŸ›•žŸ›RžŸ›²žŸ›²žŸ›}¥ÃßÂ%ô™²g*û…Ò¤é²<QNSȇ”!bKŒ'±  ”`jM¸öµå{ë{8Ë_j™XS÷R58Œ¹—nšd%‚w“)eÃ$`Õ‚MÒóð%£6ë?ü6Iܬ-+ž#E×"‰rbU]$YL¦6ÂÓp¦Æ%&%<ÅÊWS.³1‹2qfY '™qÎÒoG,M|ä,¢¢c2ùSwfþøÑ  ¡3šQµ,ëîîƒÅbE-KuYzî4$ùs¾U[ãTO‹H®.^Ö™h¯Ë“ˆÊs‚Q¦Sðsü#}§ª÷M’¥x4÷O8T@>™ßQ2 *W@e®ðeñAâù ëÓ )ô.Ÿpߥ¢­zqªÊB™€I€QëÍr£ÿ\xA—BüŽ3†‹ØP†¥ ŒXŽA °¼ª'Ћÿ–àÄ,‘œêy®ý Œ~”Bt^.ÌùÒÒqcm\µk½XþUÖ¸îüW mM$~ïúñîãݧeãÎa:\À‡*ŸîÄã1ÔÇØ‹ –[À2˜yÈôaLÈ `ö¾t8Èz7_ÿ#à –R!)½M ‹”Ð8¯, ÂÃwb½¢ÓB7{FlÀë½&èbÙ”÷ŽªNI dEI´Jƒ{C2¶fº¼útÊOUšŽ*bS¥Íé¾ô©@N~nxO9W.ÞÜå UR­ ü œþLõM‡AZšåãÇù’(#îÁ’`žÎ'x¾ŠD¡ƒ©"H䦢h3Ô¼`ACô¬lQ“„°ø Ö>0~K0MI+…Z, ¶•È# yÄC8îvn"rC}{·Âýîÿ°¯¯ÏíN÷ºw²‡ÞIî³¶ˆùx¼ªJd´œòÀS© PEKäjòÇø²¹¶; óTÛáÖbî¯ÌÁM3§­Êz¨H=N^9dСfÚÎT_GÖFÆB6ð!úû1h;É\7Ý9вÖóÓ?tñØú4WQÇÂ…íšLdÝ yXÅìØ3­K'š_ص(λN÷ô‹ ª•CJ·Ã£‡*0½T„Ä?d!/W ò(«UÃÓe͘âÌEÐú3z‹‹¿ˆ^j…r‰øø”fŸ£ ´¤®ä *Å•7ÜP p×’<ÒÉÚQb šù?#9,5åËS,-r„5鄤s*Úa…0|Èè²@×ý–ÖÄKè#,<2ðçTëø‰k¬ý”•SÒ ¤=™'!ˆ28op°Ü’îqÒ£%å \Áê@Ì…„"Ž=dûì`2öUÝkÙš^V|Ï<,ª7Ë•ÙC9&±Â­_a§#I-¹f¥,¬n7>Åbæ~0%ô"÷¤“ɲhX«ˆ†±¨-¢¹rès ˽¢«5¡lbiÓ¶¦×ùÚ1"qt&à£Ô•ƒÕµ@ÞJá¤æÉ€Ê?ÝQ&E4&ª³§„Š" üèd˜d9ä»x¦j”®0—úªÂüp† ÒÃë†Í<‡ÖT€ ·âæ¡ëù}#2Jà8ÀBò²ò9lOå_Ès3)º[W _Ÿ_.=¿tv~éäüª¹ùû½TÍŸ.Û]ªÊ/Î2¾¢o[r§dg„,‚›ñ Ù=šÖ‹šå OÇSfì×䊴ærRw/ãÑ=@6o}/XL‚V±@²áö`¾»×ªRu2!̵´Î&ÏÆCù÷ÁøüÛã‚ssw3J “®„¶²Ô”³” ?´*µK 5™¤v䈵rA¶ l©Fíø¯¼Z åÄdàroCõ¯šóðÿ£±Äúo•!SV-²†ô¤iÊŒ(zOH|(+!õXICÞv—¼- ÿ9=3óa0oÊfè&£KÐÙ:bèc™ùÃ5g0Ú;R»9>£›ãÈs«1EžíûYçm$(Ù³à ¯,,`TQ‘ÝexN†¾´Ü‹>÷‚éúxÞšòCÕ}WHÌÑ»Qç‘€»p™¯ð¬X—`/õ›åúœ¦ñé5J¦–H=bq¤|gi“9ZN«QpÔšr5Ó°ê3©ýóoîZxSÞÊõº¥+&U8úbSÝH,™ŸÝCè.YŽ3 Ýk„ÂyHƒA¬ª»íˆkúòJ+ßvîæݽÔ(J]Æ[øÉ·NDZ;«{HtÊõè”î!Ñ)ÝC¢³¯œ„þþãôVa[2]Ù"—ÍÅŸŒúm8E…irÒFPÌÒÐDþÛ¬Ukàó6èþ­ì~:N¯á}§™÷_¬7 ä/µLæA×ÂU]s­/:MJ¨‚µKÜKrk›P œŠÅÂw'¢Bö{}(%¾2áPÙÏœhõß^H¥î‘J5§R¦ YÔXp“QÐÌ]íNÐe[êDh<\lÓX× L¬ï=Å• e°UÁHòÁ‘òõñîƒÄ&Çg@ãW“0è³¾ðD‰X…Y°…*VèVÓ%*2ÿ£G(p¥F˜B.ÓšEˆñ ðT&JRôlqÙýÙ\ª²®Ô¤œmm£e<&Œ‰ó«„ߘð-kð„ÂÅ…;ŸhXhã"sO•SM§Hê@šV®œƒæz 8±ˆÃéºèïc^`)L¢G¢¨¯¿ÿ¦N|µHt¢ö“8.”b!*Ï‚Ärƒ„Ä‚‡Q1¸QtÁ1 1¾BÂ@rß…í#syYº"JØ$‡nZh ó*åpµr\”ÛLôªD.þ+ÂxF¡×Š‹,µšÕkȯfË—(Õìã‚t^é”û¡;—«Cw.Ë…î\–ݹ,ºsYÑ¡‰@îÓ¡YØ”Ûù3e.æ°»˜? 8­Â¬·ƒQZ gE@ÌÄ\6* fw¬-Qè]ÅÆ˜„¬âu¢I’3€øî$,fn½hÕ˜ñš¬^ é¾ÎÇ2\Tí3'ËŽBa‡œìƒ%æßÅjóùwQÚü»(mþ]T5ÿ.gþ}s¿$¹ÎÔOÒ[ïléMÊjsS^RÁTsñ¢.6b5@ÌÙˆ²wÇÚ2…¤h2c6Ä3&¯áG ×Â])µ¥…û×ßYÚËï,m™:9!ç~þÆ2~IøòõêðåëráË׋ê^¹û÷kRÅ íëûëû[\,“àEeòBg¢h„3ÙºF[Iþåç¿}ü´¨ñMÈ©B8vµaÃm²— ¤ÆÀk°dâc¼¯Œœwo[ùx·aÕ%\ȣċ×Ç|×–:?¾»¿¿ûë»ûÝU Gñ”ã->fÂkc›"+šE€ÓfâãþýÇ¿~xg)´4s ßýbýt÷éý»ü¾kÚ>½»ÿÔ²ð_÷Ÿ`-o­û·ûùݽþéïßÿ‡üçÏï>Àã¿}¼ÿáýOÖ‹×/wbd ]ÝH?À8‡R‘óhÇP š óþÝÝÏo<Ýÿýç{ëÇ»÷;ò¼]b°Ô€-n>˜%ÂI£r–Äb¸\E£ød‰áK™ Âz¤ˆö­\ø‰ŠÛØQNCÁšÉÈJ¤Iþïïßý²Û¡'ƒAz BÝ$Ÿî4–$I據¯®Ã£ã%v> ÿá[En¬!r˜ßPª“¨Ÿ#w“à×g„û{8§¹Šýg@<´í^)£©yK2ÆŠBeãuû3Ý’\·—+½ #<ðYÑNÜúK1ÊÙák©î¬à]ÛúÓ4­ÝzÁ|OŠ‘Å÷Qçx1¶ðL1¾˜ý…O³¿ÜÀIÆÀ+mGòÌ«ÿPKô>…ûýAûPKJÚ< layout-cachecd`d(èa``àd``É2Bx8ŽÿÿC9“‘8‹˜ °úÍÌPQ&¨(#¡ÌÊÀ3i ÃÆ•)²`2¼ì@`œ}@1PK SÛXRPKJÚ<æÆOô manifest.rdf¥‘ANÃ0E÷=…å®ãiœ ±’tAÕ5‚ÇI#OäqH{{Lˆ  ±´ýõÞŸq±?={µž:t%OÅŽ3ë ÖkK>…&¹ãûjSøºQ‡#‹iG*žJ~ aTó<‹9è[Hó<‡)“˜Hèâ‚>'޶¼Ú0V8JÕS¸ô–Ž]oWT¼¼¢j4$PSG ŽÖ-LG€MÓ ©0Ø ëfËÙ{#ýŒS(9-PV“T4Ó`]¸zä_=ãK{ëYÆXñ'MÚ‡åÙ[ÂɃ.Dçg•_Ó?zÃ×âë$™ºÿ€Þ,-û÷Ò¾U-`ýâjóPKJÚ< styles.xmlí[K“Û¸¾çW¨èJn”DiÆ–´o%®¤²UãMUÆ»×-ˆ%Ä$ÁA=üë·¤H‰ÒŒí9ć] ý@£ûëF„ßÿ|H“ÑŽŠ‚ñìÁ ÆSoD³G,Û‰s?äiN$kYqHXöåÁÛJ™¯&“ý~?ÞÏÇ\l&Ár¹œ(jepXñå¥HWNhBq²bŒƒ‰åM©$CíC^פ¬L×T v ‘ä$ªÅn3»MkÂ-ƒ±¡˜›áGÃÃ;\Ù”ÈmOL“O@TÿùôXcA¤CçBÞ†«BÁòÁËÔÜ®<ç¼2t‚*sgÓéÝDÿv¸÷gÙ÷‚I*öð,{H’°ò8O»œ|Á8|ºC˜Zn‹îÕ|?4çBV†Äà xgV¥×V¦Iz!Õ²nDu²‚9ó ¤Ýß1ºãLt*/̨¬¤ YA@#Éè+‹±²ÞG£•b­òv6!'<Šg"ŠÇðÃû`‹vÌ¡`Ç$¤~Däøð^'[5<Ò¿Ñ%Þß#° È)˲ähÇ'ç…Ÿ$OÇtÍ»48Ä j>“-OIСCS.Éä¥`TŒ~¥û#9/~rxô€7j¨D^C3*à7åYƒ%g2„ÙF— z,lôQí5§âè0ÆÌ´#(pü×ï¼g¨~dPÖ*/¬¦É×±&q‘©MçÁû/Ý” gPìYQ\2}Òx3®›»ÄˆÆ¤LL+c5›elÉ·,ô,¯ùíçROH­nè«b Ùû ¿ Ò?z’Yiã£ÀÒh£Éºôa‡”ÐCÆŠzª³"ÖÚeì’R•½³`·lù–fª|ø ‰ òúÊ–/ãÙ”UæÄT^f¡,µÂ=aK…u4.ƒÎ‚Åd_†“LÇwËÙ²N‰&.sðf7€Ç‰[cG~.¨P™Å‡»};Ø©+ôtì>/‡K6Ô&|K‚¦„e>öùP³¦¼,¶-–g€^ÝÊ“PúD¹æ1ŽøŠ `HH^ :Ÿ;±/ø¾59Œ´²í ¥¹/ù†Ê-Ù0›.MìNX5~YDDäõ&½ ^B Øò1/¼óIâd@»í¨Í»`ÖgÐüÇlúÇšGGk$rž£_sŒ\r¯å0P]|øÝ«îZ\_‘K‰€ އj4e:uÍØšK‰¡éxº˜ßí¦õâÿ™Ú /¬|ÔäºÆ]þ½Á ¥j5–oï›®l³•µƒR´¹fPëGÐú bÕ— sÜÛ@þ—‚~W¨Û(}W¢:–¢ª\Š¢v%{•2¾˜OÊw$aä‡Ç4ß¿»Ÿý˜˜þ›’ÈÙãŸÑ ÍøNÒÙ?Þ¶qRªJ­zïLõÞ$Ù“cq©Ù¸ØIÜÕÛî-B§ø»>Ê_St}Ð]Ö Ç(¸%î-È »Ý!y)UÂ&t‡Ûxp ,Ö$ü²ÐwD¶'|Ÿ8VAË¡Vç@ÅlTèîA N§ – ž°hôfªþX+ôA;è¬îGœéX ÝÖm¢œ‚û¿ÖÛSìkžDýR"QKYr·l  éŠAÉß‚°Ùy„Í~0Âf]3C))$l*x1Н-I5ÀNKÒýrQ×i=‡Ù¥T÷¨P‰‡)Mc.èÉ0‰e“ùö1ü Ã× {=zÍ=À9²é1GÃDªî[ë9À.*ô†åÉèµ)Õ®Êc†Ê$4á™”kZÕWµOõWôþžŸ–óói9ÿÁi9?Wø/ÔÎBn ôuµ³GúÆ =²â¥ ª¼¶Á¹ÐW¨ðÐŒ¦}eúÛSöÛ¨ÍógX° /|ˆ„Äé5]Yå¥Vu9é]yo0†;Ëž7 :m =BÐB«ÿ+ Éâ£w/0év˜¦/_ÄËv‡Ãmj1íÝ.WgWôo\²?’¯l¾o6œ42Îù©÷lõBÁí+G=7·nÔ;œßw;(øÝeoØÝëp Žý/ÐÃ^0òLéûuðÛï)¿*#L3£?ˆ÷l+ç¨ÅVÝòbo1éŸêe’PyqÍvv’ÁîrŸ4¿Æô}ÿQ–™ôl~rM<ý„Ó!WÑ”äàØüÎ &i„¡qÃôØ�ªÂõøŒp-Ìóÿá®ÿ<þ³íë,TÙ&Y¸å—ǜ67Ýfu°÷Åð÷cãîXäu—g_4ø9Ç3ÏOo'[TýjBK6;F‡Ú?ñZ=*v¸HS¼£:Sv½µnaGóõS1çŠMF´íϯæÉ(îíÀ~eê›| Y³×iÖüušu÷:ͺf½}f½{f-^§YË×iV0ýîv5I®±—´€­6‹Ù¦4Ï*‚oD1çwÙ˜#~.¸#I‰F™A+Xà~ÆôcõfÉ•ÉìÁÃG}öy4®h¸…4‹ú dÝZõè‘Ú‚®izOyú¡¥û– ß=FKíüdmh, …ú7X—¥J[ý Û3|¥ú–`¨ÐHA÷ ámìòŸò4ð:˜Z¦¢˜p1¶×jtk®ƒ‚ wqF;8OúПÀ"Ì;r| /“Þé-IïI‹`_jô<Óß³žgq­çšƒ~JÕŠ°}«_†‚æVv~îyç¬ÝfùÔ„Šiî~¢ª˜Ô‡§náõŸ¹‚‡¾Î†bVhtOnS÷iFwPíº¶”àK/õcâ.Ö OpenOffice.org/3.2$Unix OpenOffice.org_project/320m18$Build-9502Dan Kimberg2006-06-12T15:10:26Dan Kimberg2010-06-26T14:02:21196PT34H39M08SPKJÚ<Thumbnails/thumbnail.png•Xw4ÞÖ5¢÷5Q£QF5ˆÞ’¨Q†Ñ;a&ˆÞ¢†ŒšÑ{ï½3ÚèD-Ñu‘—ß{ëûþ~ïþsïÙk»Ö½ûì{ÖÝ1z:jä$Ì$888ä/ÔU þÎHîß•½<‚‡vü…Š¢‘ö‘…kýV9…mùñGÈŸÇérYímSC? ‰—ܽ=ÿu}2ã0¿™ãÇ2íϼ\Ä<äæDW`Q®÷¶LUô¿Â¼ÊØåƒ²]Õ¶ kµjÁöe–=w´绉ò‹?kÜ0%· Óêå”@[l·­î2íS:Ø.O>¼¹zº/Mp`0¾ëg.²ª9\Þ/‘ø0´…ÇaI8ǾböÑ0®8xŸÿZˆ:½èîbÝ{œ®Ì=Õ»`v>ÃQHÁÂùeψæº,ûN·œ6 t–lŸ¶^RYzª&#ãÑõ“—x6†ì‡º\}EèDï¼»+vîÜÌê0;L»ìñ#S¼Îdº].ue_–x¸b1·>·O6Vôs¨’ q-ÍiP¯YäòãåpKBϻȶV…ç\ä/âÖyÍo·×…%  ÿ¼Õƒ°$ù­Ž ў⊆¦§N}íóŸÎ++vK•í9ŸÆþ“ꉼeÿÚÏËv¥Ï§>5é$¡9g>fä“Ê kzá½Ò–Iõ½)3LonKn™÷'§à| Ã6–X.Pœ’Àç”°xõýYÆŽCÔÈØSŒëïTj-â%8d[÷ôùt’Ý>ê4Ü*dêÃs„ÖTÍZÚlh8oZÀ¸È_wE:Ûþ§ ŸõÕÜöÎL|sy"ì­Þ‹)O§–©þôÓ©ì"Õ­_è->-Jg,!‰·Ì956æéo0´+—l}D2Ùsš‡!4A %ì,jŽïævŸmÑÁÜ£d¾Iœ‚jX¶C7ß̽¹Mwä}9ûã«í ×V0É›­‚B±xsQ͈Ðn/ÎõdEŽ}®î3?eóüš!µ»±vaD™ÅYÆü†§×¸¢å²fÏPÙü1ªuá˜Üœe¸'uh˜éÎÐMÚê#,ò²ÅSr­3ÆCd(âÑŠ/Çàõé¨ÐðÞž‰X¿¿;ë}ž1‘]l+ê zœ­9øD°£=%ÏŒ/b±Zþi±ù3Zì"D«€ÑZxH’ýŠ[ïý $·H“‰ØÕc: É™(c2Òžr°uooݼÒIë^¸¸o EìN_Ü*Ï\têÇÑRÚæŸ Y«~* ›[´eg@IX‡y•7®úóiêõª¿»Å`>óvÍÛDŸPüø+¢ê ÀQ0¤üéë';(߯Þ/žLÊ “‡ñGçÞž_ŽÛàÎwή¼ç­£?,é½g…› ’àF¸v òPß ŽÀð²Ï_³sDÉ/pø:†h/H%›ÜàL -¾1Ë%ÄjYð¸Z.ÏmŽöðUÎy~*ëÇÕG»3õ%Çz(}bM\#(–䡞 è{Öcw¶ñ`BUúajÀoQ|¼.a°ùƒ³ç¾€ø-wJ«rèGOœt"Ó¦©¼]9è7¼O„bÜ„ ¡¼vmô±{mj^žM^8âËGÇÁOä®eËà-™AXÛ#^à¥í[ÂpPŸ½T†tÁ¸aùÉãà™$Góà]•€ø¬‡µ§{•ykRëR¥ØéÏúLg{%‚¼ä.²Ô£eâÆÐ-&ØŸêܹªèGÒœú2gÕ™‹ÛIéÇ–šVkî=½KD½'—’¹pî¬õ}x¯¿¹˜ÿo}¼Wy¬‡˜¥Óxu¶fù0^Ô2xbÃ{(-ÙE<Þ)\‘ó–6·ìt¨}j9©›ˆZHíƒÅ—™‘?©A¸xGxßEqÞÁ鯲üG³Û=<(#§dÌLjåxNñÕuÁXB§20¥5ôµö7 ˆ; ˜CózK{–(Pc8t1·d³*í.¸Rù»iCŸ‰­N–’YÚŒ¶˜ˆµ¨ôЊs“5 é3òÇSî¨ûî)ðËQ,×·Jn…sËö›}þ¾ÀMuo’j€„¯‘(e—%|Öä3pW¦XÆÚɇ åö~€þúDï ’œ—£VDÂh˜¦Ž¾÷Ò+ý8}ý—]E`Rþ fÂ!AÑÞ_—.L¸8ã›ÎÓJEÆäMêÌAhÝ›ðC©–M´ŸVè{æK¾âݶm£Íï#|%LjM3Üg±3 |ªFŒGÿá{¦&RÒÆXµX¢&rÒ¿ë|É=DsY ;9†ºo69pR± ÞÒ/wŸ¿Âöö=2ƒ¸+<¢Šz#°ug®Ò× Óˆ®nªßNÿaRSr1AÒ”’ñ…ÆšðF›Â0ÎÈ>¶´JXæÖºdë"¨=ú§T§xª±-&òJJÖv¿Áydç85ÍV¶¡„š7ºÙœÙ¥/ç>=Ÿôœ¬#ÍÑ© «‰÷E¢¼‰Öœ¡jòüÄ72âH² :³1L©¿å»íòË[yUâ3šãþV½µ˜Ž á) mö¬“W¨–‹‡<…PG[¿õôÒEjŽá¾Iu‘«ÀÎ0ï<é”é,Á$úž6„3šà]Y`®.þÚólu³B,¥m²…Œ¯9‚6â)ßÜ5þŸaº3/âÄKÒlïZ< Æaiå¢[d*îcÀÜåù±î¯Sª*c™iswÓÙQZ&«§^nÕë™÷’QÈ‚/ÕQ›¹þ–$.¡¹²yÑö†ÚØ“Áãº:>ÀQ08aãgo'wMªdþ×ÏEÕrñ”ýö¬#OAD!iÕpZ‚Ò0¿wøM¼Úºø‘oHçíëÁħY5·¦8t˜‘ð$©á+aÞ;@ã‰!¦öj=ã«v”W;£•†¸]¬ð½îV@é»JD¿çkú'º~K©¬Ï]6iï¹&tà0½tfÎVÞ®%SO+˜ ˜¨5èâÅ]~vÌU î1h< [©Ûzç¬åî ¤SnI¬cu jôß 3°²JO—nô#¤¢=0b?oŸ„¿'S¯äg›ÃcŠýÅu^3­÷EsñoÇáÿ.HÆòÿ?l­ZãvsþÚ1=*oƒ÷Ñ,Ÿ:{­Áƒx)©²íˆ ¸*ò  ½Sjf¬m¨X#%q_%…h•þMEÇ–´³cÎw–mMåÀrZÉOÈZ•ÞEû~¢Ä­Á!l"X™°j\ÁþmñŽRYºÛ‡”k^`F ’Ã)xïA‡{ÃyјyÔâO¢©¡oãÒŒCkHÊ´¾© vŸÞÀ– ÿ&´Š™]o±€!ÌüœK¢ØÏðâúŠ"FÙ6ÕÅ• ¹º×¿›s”KaåmQ¨í2†›6ào\SðØ5ŠQžðpA…HšXÐ2Ýûä¼ÅØV»-c¼@šÂõp¤@ãEyðE<½foØžþŸSɃ9i-Å‚­6øç›QŠôóìñ7²¼ò?Gà4ŒFl#é+ÝÝTÖZÿ]Êâˆñ°â0‹Ì ^#Ñdrï|Ü«¾4.‰ >¡Ú²Éj.CÉbͽ lObÝIž×w-UœSµüòM¥/$ÎoñÕ“oBÁ¿…Ö2²Åà1‘혤Ò—.$ÎbíhÌ•øuIŒßD%j³]˜å¯”¿Óé‘È{¦œl¥Ÿ $ý`‡öß<^AÂÌ´ éç—xy:f‘þ>$‹ Ì—«ß*eåufDz!O mÕÆÉ]™è‚ù­Z-ÇX¶z¶víÌ8†OΔ€J“ Šüª,0Ám®k©~Gzõ1'£8–µ÷Uˆ—9î™ú$)úÅA猖Tç-©¶ ÒEW_8U=÷ L‘ëôEþ´¤h ¦‹{nGûiJDÛÇ213Ð'ÔÌ/¶Olv5®ˆvô"ª_D@ú`0= ÀWÈDH£³ÔqoÕ“ “nr3y‚ÆGìé$§Þîô;$ú]k¢-l16—®‹Ó?´Âÿíÿ;BŽœâòy;Bœ¿ãÅs•j%«ÐPK¤ÏzÕPKJÚ<'Configurations2/accelerator/current.xmlPKJÚ<Configurations2/progressbar/PKJÚ<Configurations2/floater/PKJÚ<Configurations2/popupmenu/PKJÚ<Configurations2/menubar/PKJÚ<Configurations2/toolbar/PKJÚ<Configurations2/images/Bitmaps/PKJÚ<Configurations2/statusbar/PKJÚ< settings.xmlµZ[sÚ:~?¿"ãwÂ%mÒ0 CJKC¤™Ó7a/ ƒ¬õHr€ß• 99`rFOLlywµ—o¿•róu‰³Pš£¼õªçï d€!—Ó[ïiÔ.}ñ¾6þºÁÉ„P1H"¦¤ÁZ¢Ïès©ëÙë[/Q²ŽLs]—,]7Ac›ÏêoW×SeÙ“¥àr~ëÍŒ‰ëåòb±8_\œ£š–«×××åôífi€r§‡ªÊV¿U…ˆ¯Šì™1©²Z¥ò©œýí­|ãšš×Øøa³ýÆÍZAöSâ"뛳õckÚ­G*ë/¯^óò¾ûï7¿h½¯€0ö6oÌ*¦7åÔk|®T+µ›ò®˜ÃEwabreWŠÉ}æ¡™å ®]\]|.&üðé,ßìZµòåú8éÃ.RžAkÆäô–†1¢&½†Q §£#› 0„}Ò'LèƒÅ—"—¸ a ᮳ò“,ý†ÊC­sy'Ü2UÅ­³m>È¿½¹W»¬È}Õry]»º8V¬æc§/–T¬“òN%ö× Ua1g4ÑŒr…_U«ÇáoÄhD¢¶3n†Êx£-¦dc+LL EÉíÂ^K/y™ô&âüd•½ë—6 ª|Û«•ꑈ¤‡ 0¶=8Âôœ‡ofßë5hå/ &yx[Í$ŠjÒ鯾¸è–™Ÿ8n1€8=ä§òû,ÕV Á$ÛÕ~ŠüðÃ,~½É„°·sÐîÃ"`Ÿ¹iú”ô5g²ŸÈÀ$i8]md–ÔÁvg;™ü#ˆtॾBCÕÚFµ ½§0½Kû)™É#(¤)à•& pâ*·¼˜†ËOM.™ZyåE}‹b³r”é©‚!a”µÚJ”"ø½c†ÙÝ·0Š˜ÜÃâð…MóÔ–æY±¸'{ãúèÂr?ŽÅêIƒ²¶ŸÞõ“}¦XZØÖ'WBÓƒ2~b0+%P9•¨ Í•6T±Ð¡N*MG>&ÑÔ;[:]FÙß!&*؉ƒ“ª‹, QŠ•›†¸iß Eæôñhs¡Ë€Ó.ôuÄš²x»J+«Ë—aS09×Ôgl†µ˜á´!ûR¢I5ìo=Gô4¸¸pA½RóÛlù¸KŸ¯†Œ4¾ö `†‚àÖ­wøˆæg¢ Ÿ¬l`õ37³&&š ØÜJsËVþí±„êè.ƒ¸[Ÿý¹ÙIO„k¦ñÛÀ;ÈïÝ931™qtI¬7Q(eŸä’ÀoPømI£ ´Ól€R¨c"¾Îæ{RâˆïY>@£;(Še¬@Û³äýgE"úÊkæ$+}Á§’€th0&æÇßkCýƒ‡Ôß,Z¸ÀÐŒlÙoŒ²=Ž˜S]aF†~mÿ‡qÍa›¾M̧ “¶òLuNC:Ί½—{ߥñ\ümi•vÉj_£Có Ë&±Ý(²ø.pÌ^{”·Õls0꺘}ýŠl¾ ½ |V´TµÅ*=Œr¶7P–Û›>ëÅôìuÏÅŒp½D˜‹"±‘=NçúVh}öBbîagdùà!CÆ%\ævê(bñÁÜB›“Y=±Ö¨6”g·@8;ß¹Sl‘íž\|ÚZ,6‰«…ð@÷¤T~#?ùéIj6ÈY7NmïÖÙåÚE#²èó+»ÇîÉ–@íbgÙükϹGÅâYøƒ÷ é}@yçâ½¼ï_PK°–Î!/Ô PKJÚ<META-INF/manifest.xmlµ•ÝNà €ï}І[SÐ]™fÝM|‚ùgô´#¡@à°¬o/]ÜVuWÛ; ‡ï;‡ßåúÐêl>(kJöÈX†FÚJ™¦do›×ü‰­WwËŒª1Pqjdiž çnÉ¢7…… Ba ÅP,¬CSY[4T|Ž/zÓê.»€k¥1O¾Ë.2¬äÔ9,8§•Jyн©øÑŇ Nx v™=¨j1®£Ö¹Ú•L0qS½@¤B®Ó¤5Ô§ÑÜÆÖ¶U|wÝ ¡³‘r r‡ÿPøª¾ÿ±ŠÓOQ“.O Nc±:¿c[$½Ûìb»5 ttjrgš©á“ð^¬©UýqSÃB€”¨1u­2z?î,ÞîšEà¼m<†°…™µ¶@8WöÖE—Þ¤8¾'϶0d­ž ®Zh0ˆgE-¸™îÁ‡cv  8æP~ý¾B4ýåäQq9tü-if$Jßýùi^Šo¿ýêPK•'dh(PKJÚ<^Æ2 ''mimetypePKJÚ<ô>…ûýAû Mcontent.xmlPKJÚ< SÛXR ƒBlayout-cachePKJÚ<æÆOô Cmanifest.rdfPKJÚ<,{þª M6 -Dstyles.xmlPKJÚ<1T=ççNmeta.xmlPKJÚ<¤ÏzÕSThumbnails/thumbnail.pngPKJÚ<'7gConfigurations2/accelerator/current.xmlPKJÚ<~gConfigurations2/progressbar/PKJÚ<¸gConfigurations2/floater/PKJÚ<îgConfigurations2/popupmenu/PKJÚ<&hConfigurations2/menubar/PKJÚ<\hConfigurations2/toolbar/PKJÚ<’hConfigurations2/images/Bitmaps/PKJÚ<ÏhConfigurations2/statusbar/PKJÚ<°–Î!/Ô isettings.xmlPKJÚ<•'dh(pnMETA-INF/manifest.xmlPKbpvoxbo-1.8.5~svn1246/docs/vbrateimage_rc.odt000066400000000000000000000350761153177201300205510ustar00rootroot00000000000000PK¨Œf;^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPK¨Œf; content.xmlí\_sã¶ï§À(3»Ö%Ù>ÛjìÌ]ÓL2s7I{n{o7 JˆA€@ÑêS?K?Z?Iw’"õǦl_#;òƒ%»ØÅþö úú›ÛT9Ó†+yÙö=Âd¤b.§—½¿_œ÷¾¹úÝ×*IxÄÆ±Šò”IDJZx%À-ÍØ÷^ör-ÇŠnÆ’¦ÌŒm4V“׸I=v²|‹± Ñ™Ý7¹-»µ]™‘¶ÅK'Ý%;â&w¬iÑ•iÁ¨MöDue¾5"HX=ͨå+ZÜ .o.{3k³qEÑ/ŽûJOÃáÅÅEèzk…£š.˵pTq2ÁP˜ ‡ýaXѦÌÒ®ú!mS%™§¦;›†Zº†ª™O;{Ä|ºÅ4ÑŒêξáˆÛðÇÝá=Ž›¼)µ³-˜œ‡ Óýûð~é :í* i[¦Š4Ï:OÓS7ù•RµªÈàÔ©; NBÿÜ .î$/4·L7È£;É#*¢Úâ*Ýd4 †@°9ºiíøh³…aúîšØÄ[‡þôáýÇhÆRº$æ÷\KåÒ2AØ:ÓÓP³Li[&éž0­Q-%Nh-(Mß £“Õ!ÄÈ ‘å«ÚÓ8•[×J–òÙmÆ4GF*¹ 50K@Seã·wž’³QæÒjqï…Í ŒyÙ ýÕU•ã±y ÍÆùns–æk‡8ä]øí€îè€nîÙ®ðží?¾Ç|K|‡;;Ü{dOÈVÈ.1ì®oßo|OøÖøî ïþ£ûæ€nîŽuwøêîÙßßÑNàŽöÙó²²»ÖÝÑs¨»|k|w…wÿÑðÖðîXxG¿bámtw9áN¸'\‡®Ã ×o ßà ׋EöpÂõÂñ=œp½dt'\/ßà ׋EöpÂõÂñ=œp½hxŸõ W¸õbCÙ1Qñ¢~@öÒM û%gryAb½ÑÛ-æ&t¨Ü .YPzPå@~?‘ëï½à45Øuu™ãq£ÀÛGò­¿ÁºDf£Õ²õXª¿¤Y)Q¹Nu=ì]Í'`6ÆS:e•  ½›mÔ»"¯è %9¼ ¾‹„×MbòלG7äo,aç_öe,6òÞÇóØÇæðþF£Ñù¦=ÞÊ÷¹eévY?º×ŠL!Ë'Ëâ#¢s˜×Œˆ½©¦)mˆa‚EÖ5GJ&|J.à=…è‚^•2;¸‰à7Œt±g‡iÚ©OÞ&–iBI ý±9" •û+NB@#ƒnp«XðbgÄŠ€pIœ˜1Q^wL8G@ “_µÌ“ShÇë‡$Ñtê2 ÉÝFÓ€a4'\Žã¾&|x]è½*†(hç’‚J•ýjÂáÕ;f Æ<«×ˆpƒsÐ$Ê5~7˜@IÀkYÀ‹b‘`ôƒí^q ™,º ƒ0—èÜñkÐÆ‚ÁìáôçÖ‚Ý©fÕ-f<šáø€H]dŒHe™i¨ô£×Æc¨Ä=™H£š‡4‚Ç`÷Di7U„Æø]c¯v©êJaèP®3¤jÎÀ¦0¾›46¹7 5®Ñ"1jm°;7 ÿZ¡èøJ朮’>3æD‚(N…ÙÖØÁH¾<€Á¸ŒD{ ˜Ý–N)ï|}áÆé2ïÕ(*åˆáŒ–ª­z—³/þúŸæ*76€2(ŽhÒðôg %7!üæL·©ñ1Æk_ô.Zú+‹§ìAC rB^I–Cu¯Ÿjæÿœª;BµqÖG(¹àà±Kv¹Å±•z¦ ŒKȉࢷcI@¡]zõ5B³ Þ4ÉIåõÞ Ö'¹(Y\â )]ÉÀ À£¦àt™wwBÁÖë—EŠ˜oH.ý1RZa¼@AHÅ @˜\3Çšp sª–G>UjeÌŒBN|Us@F,Öå 墥>Æt(ä{H±ä†-È+PÁÏYù—רŸf6×ß!ñ2=eÊ>ò™3½ –§~º°~•Ó*Ë‘F1vpAòn%ÌuVô¦†zH\¢)”¾Aå&@[¥¥S-jºK}>‚‚åT03•‹\¦æ!@U0Øšõ/ÒÔ@ª">ßi€=‚ZÈÏrkÔ"@Iâeø6€ÛRåi£Î#v‹(Pš¶‚ÀÙò—œÛ–ö“‰`jHˆÍ¾z6pVäo£i蜕ylµîßN4cÑÍçOŸ>­Uû#Lí0èóYÒÿˆÏ׃Ááââb¥€Ì Õ1c+b!„=–”*§haREó âq³8CrP4®,Ñ$wŠfŠÃ[œß2ü2\»AÞðÚºH…•þš[QÀ˜”Æu®Adøx¸Ú]óTñ‡ž^º*”[í~8ÜZz—„eà ÎÇÒ8°üŽMik¢ ãMÛ£ÆÕl²åm¯ª¼=ô\æA™Pk=Ÿo_ëiw÷Ûý/ï·ï£û¶–úžkyåy+uÿ­3Á ïV´*VFÀõÝvÃåÏgP‘³×y—=Ø5âë§™åY蔫zM7Y‘¾‹>ï¨Ï†›p•zTƒMÌý[£ C@VþWxûPVŸ°ÈB„3q§…Â;1ÜÔÑÃA÷— ƒ¼ÚѾ͖/³ÛM[2wÚK2A¥dqs—ZíÇÛŸè¼NÏONÏ6}Ÿzåûö÷÷®&îLX2cB<}Ö¤¹7J´–¹=8n® ý‰åS ë?[À}ó|x¸„)Ì™ÄÏaÜçxüjð°™Q³pk:n žüt< [톭O}«§Õß0¾úPKPì×¾± YPK¨Œf; styles.xmlÝZKÛ6¾÷W Ú›,Ëû²Ýl 4EÑI{HÒkAK”ÅF"’ZÛùõ’¢DË”­Í&>x ˜3œÇ7¾ôú—]YLž0„ÑÇ žÎ‚ ¦ K Ý<Ÿ>þ.‚_ÞüðšeIð*eI]b*C!÷˜LÅʃšÓC‚ˆE%+™¬X…©´r¹WZ•ÑÂÆN×Ìîl‰wrìdÅ{0­ÇkÖÌî씣íØÉŠ0u§glìä(ÂŒ… ++$IÏŠ]AèçÇ —²ZEÑv»no¦Œo¢x¹\FšÚœ´|UÍ Í•&.°R&¢xG–·ÄµOñº&Ѻ\c>$ÑQTÅÓftF ïM:>¼7©;·D2ˆÉ"zDýïý».x9V—â=€*á¤í¦ávç3ÆZSÕS ÚÜùlv™ß÷ö$û–‰¹ÃžœdOP‘´ˆ³ÒðÅp„øI¥©åæÊéAÉwÇã²5$ß y«%ÍP«8ÅTKÕD­Ë•©JˆÔ”WÁ¤itNsol'ÍtÑ %8LqRˆ7¯M´Ãó[Ùù|ˆØ—kVÈvËU’bß#vBT: íBa¨Ñi%ïXNääBS{Ôü„*&~v˜ÌÀ9©:ƒ¦;ÄsÆh(PàŒN>`N²a{Œ•“ájB¸Á 99+=ਈL |Ÿ'ªç?Ç8DÅ(Û€o„ibK„x‰i¿áÿÐ?õi³ž1&í…Äå‹àêrèyör›¢¡ÒkÆÍžÆÚžâ ÕE³Ó±’7U9IËÛü+Í€K;#µÞ¯DŽR¶ A>Tb¸{ fÓ8^IJÍCßÓ¡´e+8E…Ø?„9ãä 8€ Ãßžâ~RÖ$^hY£åñú¤6àΖÈ<4»² Âɇ q¤±r‘2$Å¢Z2¥’„¤˜VTT9² ´kŽìx„„àKKQËŽ2®d)L/x(× ©„U§V»W×k¤µvysV •1Ãf·ìÊî#ojª‚kš1+ì‡$¯a͘±H/`i<¯¤+ÝÔhC˜ê„ÕTrÈŠOZ÷±„µ5üŒ9զޗJfë¢Vr3±ni_rKi´XÂÛ¿Žå©ÍUw[jNú2[ÒŸœ•5¦ÜZüƒ“‰åû*ÇT·Ø°@i Xi[Ê ê%iÍ™oUMY[ ƒ—à7`>!m"…)ʤJÉlz»œßuår˜³ ÙÕÊW$–·¡Uó{æžÒiÓèpÝù~ù©u¶iv¸²|,v“ ÛÖÑÏ<ŽKD¨ÞÙô›1UµÈ{,/(}6u{XÝä1G×5ãª"T¶Aï†Ô)P%T.¿TqÈÙ¶§Fzµùã*”lƒe®Î†ªöÎ)v¶;aš"žƒ-¯@B€yPE]MËû£Ô©æAq0Ð^{„~S¨*X—á# ü;Ÿý»féÞgÖ¹fV" «ôB{¯;GGX3)Õi6-n,M£¬W`ªW`TlÑ^œk+=CWo¯eÜvÅóuUïðÜVBºä9“4¾@@S® ´wB5qÉ/I„¯Žñ™ðŽö÷,8_ãȉ„-”È‘9ä f<Þü·¨Ré÷ CörôÌzsjj°Þôu¢¹ìÒ{JÑ®š¢÷ö.l6\ƒ‹²S3`{s8pŒYJ»i–ê™|"NãNGKKoôŒôŸ°ß}Ã0-ïd˜¿QľqÆTK¦ª¼· Ñ\qy»”b›ôy.SÏnœç¿Öì+•ëæhÀsÃ6éñ´{·Óž]àn¤üëØ)–6Ô‡—W‡îjLX-ÍAóÈë¿ %è1ø  »AU @ݵ[Œº Õí/‚…½uXµæfj?^.‰ ¢÷úè‹íI­ …»¡êÓ'¶ÇÒÈÖƒl"Ù§ázo ØýŽòödõ«öyÓôU*¢äAØ7ý¶À™´ìÂ^w:„äHŒçW†ñíÆ·~Œo/ñÍ•a|7€ñã»K`|{eß`|ïÇøþß]Æ?ø1~¸Æ÷W†ñbã…ãÅ%0~¸2Œ—/ý//ñâª0޽Ç>|ãK »¼.t§øNýO/‚q<»2ç Ïý Ï_ò!ÉEž2‰(iF6usçÚÂælž1&Õo_âÆWóòû„ŠZ=25ƒv¢pœ×OLîsdWoPJžýŒEù;ÞBLÓ!‰ß@+^!ÒYàS3xá`ÞÌõÅøòÞyRóÁÓHé`P¡mh„&\ý¦¶uÎGZZ÷m€z­™$ -ÁÞ•l Ühá=8`Ê8ð0õ®ý4eKRõ±Ø¢=7èÑ“M®œˆk¤x2dœ€¨ 3ã’#"ƒãk͇ÅCïØ]kÓÚ-ß…ë:’1æä+¼ÉǰD»Ö;uçÝ}-Ò0\YqšÙt6{pp°/ªáz‚fºY.ç/¤ÈC,PK¨Œf;Šü4‚µµmeta.xml 2009-11-04T10:02:572009-11-06T12:37:17PT01H00M42S32OpenOffice.org/3.1$Unix OpenOffice.org_project/310m19$Build-9420vbrateimage refcardDan KimbergPK¨Œf;Thumbnails/thumbnail.png¥Wy4lÛÉ!aD„¢ cß[lER²$˜bÈ61cF– ÍX)²ŒÈCÖFc ƒ!;™‘]Ög,cËç}¿óžó}|}÷9¿s/ç\×õ»×}îë\q÷îš òŸåçàà´´¸uÿh¦ppãà=q´šwá3áàÃ[Þºnš¹œµ\¶qéTÌV*ëÀ? áœ7 ´§©®‹ä<èÁd½P;®T–´±³ú$bSV®¥agÕ'FG„û•0Çÿ/.F2çzð =x/’Ãßmªtcw²@¯4ÄijÓÏÆ-!ÆŠÃ[ú(§¹Óaå*)´­]è<Á³žwŽmè[  †÷ý)¼ðuÅ‚—<ßx‹rßw>!ò”kyGrúë¶©¨2Õô·ú˜gi•Súˆ¢eõYæöpŒ¨Ò³Çn¼œürÿ3˜5)éã?“{Žð•¶hÕ÷™Zÿé||NZ¸™.ß}SÖÉ•‡ì%‡Ä—X­ÖZTMfUO¤šîS}¡Ë(4a† á/ ï1?¹F[Ô®lRÝÈÕ+æ„„¹ÙI³͵¾Ùï«r˜å-ãkË Ò¼/~¸Ðµ›TmKþ²rMG®òæ·P‹)ÃvTg !%ÞiÚ‡gü®E¹5ïÛÿe9ݱ`ž‚_ö7›ób¼ïzÝ~w`jTÆ›¤ÐºµPl’?¶ð#®ßôZLZ l)JÚÛCWþ¸½£Ô|gí‚B§Ë­à¥ß¼¯Üþ8Ê`´ñj”ûjlÏ«ò2Y(E¿> äEÛjÿI ¿Ð¿ ›¶AŒHt:Ì«ø‡¾qv •×ÓC}Ü'ClÏ9“j¤w¯Ì:Fä®ÊЦ»ÝÖY ?—o"Þ©ô$´ ¹OèG*Ë3£ŸkÒ¦1ДèjÍ›ÁÈÈî‘7TÏ)=åó ¤¡”1^çr€²^žl¢•¦eÖ ¶"³ÒKšU÷¿¸„›omŠøÆÿµLˆH¶VLLXƒx¾î¨±MïzuÚor Ü]ÒAÀ¦š6 4Ìî˜Úa:Q°êÛw¿Õ`bïÌÀÀ0ÌpÃ|L/ÖqáGGY%1ó9(§JAàš2Õ­zåH©ÑÔY†ëáÑ•¿j•Ñg¤ø ¹”@÷¼ß§TEqÀ¾ËNPžú]L#R럛âó(D!_^Ã7XÜy¸7ÏÌ€óв5ïÚ|²`üTÈűÂ<º‹;ßzïß`ôó©1÷¨–¿[ZÚ®mS%_&Z)„mÂA -nˆÆ…µ¼@Û[°ŒüË<ÅÝ^ÿÉ•ïY¥úýZÔqQùúªõ.+èbReNûÂCºãnÌ€z$ˆ l3 áaòƒü[ÁÖíe—‹Wξ:‡Ï†ƒüΗœJÂÿ¸Ž€lˆ°¡TàÓNÆðbsÙž‘Ï_CÂÀWƵDFºÊôlÇÜéR]ãÛyµç½}Ôâ«N|Ï:(O~G{Céý+ÿ¥Wô‹ Øó[Áóßðo=O‚“„ZÂõeçñ:"È݇á^%2`cþñE÷ô™TŠV¦V¤ôöïób*M#eƒîÀ}p›²´«>'å~–ð{uHÊpæŠt¹bú뤿}ÂþŸ¶”ÛFlÇ&óÅ{qú>±¨Ò3h Ç*y(7`ƒvùÔþ}nƒ\?‚ÌÆeE\Âó2[;RYŸ‘<êÿ¨ÐZX Àú‡»-DoÐÉ–¾¸ø~BvÉÑG€Mþ ´5=jeHqUTu:4ÀݯhÞÖÔÃhóâógû©LTìÇ€ yfSï–€I”4ÍËÈ—0òÀK°™b ŒQ´b•°}À¶—N¯—žcÿ¤ÿ oÛ4®ÓDIp]">Y¦xÛ§í$.qÓp1ÈG¡_yŒY­dm3X.£p`lfºg»Ò^ƒ@z*Éþj£ƒ£AÎ5ðkÂÙh³E`yW9z ÀÄÕ¢›G ðʨ/Ii¬Ü[©׸à±ÌjµÀÑ4Ìj/¤-Î?8謹ÍÓ7ÔEU ¢‹L/CO2Z·$2À•;¨·7óu¦Úþ®I2,¿æÊp}X2b@ÿFdÓ”ZtIP­¤þçX{zõ˾c… s?B¿ÌŒKK;x JÿòwXgŽQëþ²µWXÓK »s8é€Öí‹P›KÖÆ¾²ÑäÖo¹pvz)á;¾çɰq©ÐFÞUvü¨&$²‡ß¦êÒ4Ú,Çäæ$mW }@g²ÔŒrê¡S/o…i` ý´0CR\}_s1ahoq&—é¾E©¦¹ü£ 3}, G((cIÜ_¾bIJiø&$ï÷}iSl§y!«ýÄ®T5³%õ(_íŠÁºtñTwøV<¼ /ª!C„±ÓÌ4u…eX[™J‘Á5…áR^™Œm4¹˜…ʵgŸ&¹2ô¹| l»r÷«4a V¦ÈO¼¢Ö@È{£©.þÇ2ÉF·Ž–ÄŽøÎÓ}Sí+ê²; » ¸“•[–“±GdÏW"á4« HD._cUÏî²7®½fúÐ<,T)òê{óÍCç§É,Т2ýÐó™tòmˆÇµŒO鼸2T¢¤ˆSÖ3§ÈþÍc"_Åš[ÂiàN»]hÎ)¾lF—×›oü¹Ê½KƒÊøyÍßO~Œ+º¿ X_kŽ™v× ¢õ‡-ɵ¨åÓ=×2³=0”!Ñc´Z¡ê’¬_m6ë×ÛTî‚=„ޱwÌHÓÐð@¨b–[øfxñpbøKc䯣[ÃPÄoÿ,f[¦#’6jØ™{[¼Ë”Ó›O þ¬.3$ñ,Qž4dOjž²CÞå· ŒÒÿj¬•½g6óÔI¦ò) +ÐÁ14ý ¯Û‹¤$¬ ò“H_óè ý®wò”Mc†äA'îU ‰ìÞ‘°ùœ¯óÄíúÔ›[!òº6•EºOÞ¼‡ù¥ µñ)¾ ä( >åwV~ÜŠIÖCmÊç¦P‹r¶jêò í>ÉdÇË4(ÑÉ=¾;ô!ó‘ÊbuÏ`âî÷Áb~è°Ýl‡Æ3eþÜo©¯¿B jxNP­5?¶øÖ]~)µˆúþ,ø£u^.~u=³=ùó ¾lqh_õùÌ–?ñ0ü.ñwªÊ?áË9µVÎÙçzÄk_z3N² ãÊzSx Ànwe>ÞØu•” ¥jÔ-j">zÏéÜPfqëz«sPÇBÑ6löj·ÕÛ¢ý§´ùîIlHfAÙ#ó¸Uˆp^bˆI¯ü"Úù,±ŠDÇŠØ}·:3Êž‚ÖH°@´Ò%ÜŠ©ãcq»Ô*cºþ‘¨~õ…îš_3fwo|¦.™Û#u&.¿•@í;h0_yèÚsmعZŠ÷HKéi·×H—tù½Ù9 I”¥iÝ îª›Z'8(Ú@:a!†R^7ì¢Ôž.:¿¶>fVnàôëöBÛö}¦f¿fúêöÇËüÊQÝ~ξ¦î¥Ê4>¿r+[½Æ ¹¢æ·à¨ó BRƒ®º³KÙ››îZmÇÍ( ³T©ðLAÐÿé^îªå*vÍîîÕÙ£ûÂ0n1m%•-@ÎNRéÙÌ–JóÌædc<Ø}%(ªEºJ$hÕ郳ÑÜm;ÒEò讃Âý®r„l­°ÿZÀ)‡§Ø½]ˆÆ.R*Á¸‘sÕë@èßÒGš0ê8âñÑ9{ÇG¢‹þ‚iT3žeTš½øB›*‰á7µJuz‚SkpŸ¥pÇSÌ5̈.Å?҂ܽû-Æ%»÷œÎ™‡ø&AfœFêÅ+ÃÙÏß_õ°rbÏ›qå5ä>\+\ñ=ª=-oÅŸï¦B¢ãíK ê}Eá UþOO#Òô}ƈ]毦eœUоf¢Õت§ ájv÷û™»;ö¼¼ [¡£2¾µGû3`Ü'ù‡›Tþ…Z†~®1fI¥¿¬œÏ³>ˆrÛmÐè”ï‹ÎùÖvJwÈdaï¤ö±KæOÔz_äp½bå©§Ÿß¢ÚiZ"z+ƒßxß±vĕܧ•2Æ*›^„ÿéƒ*Ô¯eåŸvºëjéŒ\Ÿô•7 ›–eˆ×ÞGjÑ òÊ  {¸ïäaOŰ­=›Iò#–¯¯ûPO8 ~¯}¯¼vC IÙÑ ¯Ï´ÛQùi,PP:kmªä±¦¬ÙÁÈn;âí÷°Zîj ÜisÆû«¿ºb«b‡^K5b¨9w$GöE•]E4Ú*¦zunN7ûf”â»$5õÿû!"’%|¯Ñž‚$ª¢v©-7cÆêL¾ðøA1¸pˆ’ÞZLOôr®®ÛÒ]¼óð}ém…„’ß-™,ëQà7¥0Ö,ì@Ô(ámç¼¶Óù A@Ó—t1 ý5É?t+GYî5èš¼µÒ,âãà‚‹O áñ»5ÎÆy£ãlé‘?ñc°¶¾]žØ'x‚1ûÀ·ÁãËNÞsá£/àÄsu­†`NÿŽ ¾×£†vOÌM%õ£¦ÌVIó¦Ï1$8ÙIô Í}Å`k^^Nû¥ªM‰ï<Ü-é`)S®"yü<iµ6²ƒJÛ­FÕÒÕê¹c•tâ'Jséð%УÊç7qù|Ë©„Zp[`ì/_!l>R÷—PÀ æâ…Góâ{¹ì šáê|öŽhñÔd8ñPÈ1¡˜ñ©oÏwfä8û’XÃ€É §ÇEªWp%£ñÏ+]À¼òÿ³ßû¿0ÀÕŒªà5Üv;“7WÔ{-ktдÝ]D r$c6°ËñSñì%“ÜU^4Öuc–’ÃHàØ){5ûG¡ÕŒ*Þ7О,È6@Ç×ÔµÆlæoÕ/…r#½¯< ÐAb÷Øéßn„2Ò ‚ú¦æÆÔ×ÜÎè;¾¾„¤ˆÄÉhm[š2Ç@[¬’ëólízgvøfþSr |öó¨$;½àu1ü£C /Ý/LˆØäƒ±³>7¨‹eœ(KjòüŠ£Lû—Õzxê~Öþb® h)µÄf׹Ċ~óˆL$;Ë­LlˆÎŠE2'¦#=( QÓÎJAÍq+uŽA™ÂðU§“’peçí:ïöy€FgˆÙ›Ô<Ñ O*åuQÍæ‘¶ÖW¶EJÂЪVÕÞ¸ˆ¼Æùß–ù|u<Ü”¦X ½„f‡œ¼—Ãý#Àþld§4û±Q˜3§ñklúÑÊü%Ù3žhWµlWâ }µ°ödÇ9uc„PKæÌÛFdÝlb Ùº‹ó¢L¿eÇ$|SŽj¡îÛÌ}hÜÎ'¤+ŽËcüy|8§Ä+ñM×!äóLVÜæ% ø÷ƒáD—ëküØ»ûŸD>^Îm å°^bUú û‚BÿÛ‹#z·ÂKC‘Ì c|²*üÚÇ5#™ÇÇØ}ãèÂ’_sdÐľ£ÚÔŸŸÃC¨³>¡h7Oãú=•©eŸ†<Ù— c­e®ù÷HÙØŸ…·ùX௣”ðŒ,/ð+wý<êYHÇ|øñ^¡,Hâ«[)|䈉}âÇ“m–¬yìX²NnV“ú´¢É´¡k®¬ ÜêŒ6B;¯1-Fi„×<*^BÖ¼NŽ-·š­1"æ6Žtñmúˆnz—ñaŸtºŽõ÷ éæ§ÏÅ¥UÜ8‹>àöû·`ž¹$CÄi;™“;Õ/¾òqSÎ[úGEþbUÚŸv¿Z$ºp·¯QמÎÿ`_™%ºk˜—-[®G˜¬š{&ZlðÿóädlÆ=·àÆhžÞÃc~‹±s÷ÜÎ0oh„™Ë´Þ»·4qd)w-«Éy7Lïçq v7οK°)ÂÚ-“½þ{ìvëMÈ% ž‰ÿ°idï»Ïñ«Dr˜¡°$?öÔÒt·âÊÚC´£Šþê»…ÍÖ)ýã4ùxOõ¨÷³¶àdpE[¾îÍxjå"‡¤]©‡KÎòt—X_{6"«)ÊYaz4é¬J//~íØ„`fñÍ/(ga¿ˆËõJ“·ˆ;NîsêÅ~›?_6Ž4úOˆæ‹ýfŸ7®.Kš>^àr!¥tLÌAmi˜"r`»Õ2…r:z¢-q©àC(’>c\,¾³¤‰Vî:kŽÙ=Tr}˜Ë{á–©JËÈ8Û¤óyùPæ^³yv„Ø¢bi|j6.ËŠUÑ”CõÅbź¨n+xT\&T„Ÿ’ÝF­1Þ/üâò⪜ð_ˆñ„Dm'Ü¥> “úl©î Oc±]×¹ôƱÒÛˆ/•ö®_º,Ð( lo”ôMOC !ìJzPÂô=ßLÑë³ö/ yxSͤ’ijÑÿ§» Åô% »ã1èt»«f®Ìfd[aO9Bƒ=‡Á¦!sÒ´¬üÛ­ 2û'Œ@ʼnñ¨)¿»(·Áª ÓûÄIŸ’é}ý8\±^é UrWA¹7뙂«‹v$˜\{õ0d.PPù"ls&^¹»oxãAÊmaºÊ›oq¢×Ž?;X7’J›Óô²„î‰Ç4ž‚e@ÕŸ‰˜§$œÙÁ8‘ ÌØQyC´ŽÓ8üÀ© HÊjÂÀêâ„2 °³”ëœ5NX@G™ EpÕBº¾­(*‚ñ>°ðƒØ—בÏ9`QÜïa}deúIÂ×O äÓ¬z‹Çì~f£ñ@t8*ÔÇT„öSYN¹9ÅwŽSÆïòkƒêε/j ‰Å-£d]÷‘…#JO|'sªˆ_½!”/²ÂgIKe—¯-Íqá·næ‚ o¬1¢Š>RSÞA[G¸¼pÁ‘matÙêqw9Üåd£oipÖ§‰‚˜ö0—,Y¨žèGj{®Âòžê³)¼!‡ wøˆºÃJ¸“l9˜þ­Â0WyT¨ß¶ r+ýLîOQ%* ÿQ3ä*tFÁ€‡¹s€\8ëÔÿUBÀ•|{)ärRün*î•ÿ–Y†ç¼ÏÍÄnÃb^®Å×cM4ıä—ÖmÄÄ;LÀ«Wb!d ´9—¯µ41]tY?R¥£ÙÚ„J=GzñÀDÊx[{q ÒLŸ#0£æ+L0ë†JtÓoݤa7æ,æ“–á¥öš±à2~Au]£‰yjlª„Ñ3î@É´Ò45CS—S´u]›³àÅd¸“Ž V” ü‰4þÇPxtO ¸nÓiæSQxWÿÍÃ^šìPG½Æ"{Û[¹øAªÍ4Þ‡Wà™ùC“°…—ÜõoÉõ¢¯ì·¿PK¥¿M§PK¨Œf;META-INF/manifest.xmlµ•Ánà @ïýŠˆ{ÂÖÓ5´Iû‚î(qR$0›ªýû%ÕÚf[kn™÷ Áfõzp¶ØC$ã±ÏÕ“(µo öøÜ|”/âu½X9…¦âú<(†uH—i#RÄÚ+2T£r@5ëÚÀÖëä¹þ_¦õ¢¸‚;c¡㱸ʠ5ªäc€F¨¬ÑЇ<åÛêäª¦ŠŠáÀâºz²«åäs—¬-ƒâ]#¤wå0 ä°‘Û4í‘Ç4Æ€9¹ÄG 4;Ö« ·a›]r[TÆ’äó° ØÏ Ÿ…÷î±3}ЧËDK©´ ÃÔG©SŒýÄû]Y!ú>ÑVetÖ+†\ÙûÂPÌ)~$g;öÞfƒ§z ùfØ©©¾YØÄŠÓ#—òwß§„cqVÉTzêø_ó6f`ÞÉKk^É?Ïäú PK`3fEaPK¨Œf;^Æ2 ''mimetypePK¨Œf;Pì×¾± Y Mcontent.xmlPK¨Œf;>ç/¤ÈC, 7 styles.xmlPK¨Œf;Šü4‚µµ7meta.xmlPK¨Œf;oÝÖ:ØThumbnails/thumbnail.pngPK¨Œf;'’-Configurations2/accelerator/current.xmlPK¨Œf;é-Configurations2/progressbar/PK¨Œf;#.Configurations2/floater/PK¨Œf;Y.Configurations2/popupmenu/PK¨Œf;‘.Configurations2/menubar/PK¨Œf;Ç.Configurations2/toolbar/PK¨Œf;ý.Configurations2/images/Bitmaps/PK¨Œf;:/Configurations2/statusbar/PK¨Œf;¥¿M§ r/settings.xmlPK¨Œf;`3fEa²4META-INF/manifest.xmlPKî:6voxbo-1.8.5~svn1246/docs/voxboguide.odt000066400000000000000000001506611153177201300177500ustar00rootroot00000000000000PKZGŸ=^Æ2 ''mimetypeapplication/vnd.oasis.opendocument.textPKZGŸ=Ï£€ï[[-Pictures/10000000000000200000002000309F1C.png‰PNG  IHDR D¤ŠÆPLTE€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ3f™Ìÿ333f3™3Ì3ÿ3f3fff™fÌfÿf™3™f™™™Ì™ÿ™Ì3ÌfÌ™ÌÌÌÿÌÿ3ÿfÿ™ÿÌÿÿÿ333f3™3Ì3ÿ333333f33™33Ì33ÿ33f33f3ff3™f3Ìf3ÿf3™33™3f™3™™3Ì™3ÿ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌ3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿ3f3fff™fÌfÿf3f33ff3f™3fÌ3fÿ3fff3fffff™ffÌffÿff™f3™ff™f™™fÌ™fÿ™fÌf3ÌffÌf™ÌfÌÌfÿÌfÿf3ÿffÿf™ÿfÌÿfÿÿf™3™f™™™Ì™ÿ™3™33™f3™™3™Ì3™ÿ3™f™3f™ff™™f™Ìf™ÿf™™™3™™f™™™™™Ì™™ÿ™™Ì™3Ì™fÌ™™Ì™ÌÌ™ÿÌ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿ™Ì3ÌfÌ™ÌÌÌÿÌ3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÌfÌ3fÌffÌ™fÌÌfÌÿfÌ™Ì3™Ìf™Ì™™ÌÌ™Ìÿ™ÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÌÿ3ÿfÿ™ÿÌÿÿÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿ3ÿfÿ3fÿffÿ™fÿÌfÿÿfÿ™ÿ3™ÿf™ÿ™™ÿÌ™ÿÿ™ÿÌÿ3ÌÿfÌÿ™ÌÿÌÌÿÿÌÿÿÿ3ÿÿfÿÿ™ÿÿÌÿÿÿÿÿ¸ÿ¸ÒOIDATxœcà'FŒ*U0RËU<4àðIEND®B`‚PKZGŸ=S4èâï0ï0-Pictures/10000201000000F00000011412BABACD.png‰PNG  IHDRð÷»²sBIT|dˆtEXtCREATORgnome-panel-screenshot—7w IDATxœíÝy|õýøñ×ì½¹DC7˜‚\r)ʪ‹ýV1P* /øú•jQ[ô'ˆ\Ú¦ˆ-B=  J5\Ñ"‘C ˆäÚMvö÷GÜ5B²Ùl²³›Ïó¡egw>óž™}ç3×{F¢)))Öº† ‚à9“'O–js`KÜ{ï½·¥bÁ Ÿ~ú)P›¡¡¡ö¼µÿ#%%Å:räH„&‚³öìÙüÜKP¼#FŒð\T‚ 4ÊçŸÎäÉ“%m€,ËžŒGM–eJJJ)**¤¸¸I’ö "0,„€#*•ÚåvKKJ(,* ¸¸ €  ?B‚Cñ@¥R¹ÜnqI %E\/. 0ÈH@p(A.¶+¥¤¤X‡ æR@‚à)׋Køú« Žíÿ‚’¯¾FS\Šdµ` % O_z Aïwظv¯_'ãë¯øtÿ¾º˜ÉóUÚèÂé×!Ž{‡Ž¤ß~6²Ýâ2þ{˜ÿî=HÞ±o©üþ{´íÛs[¯žô‰Lÿ> pª½}ûö?%ð!CŒ7ˆŒŒ 77·Î÷îl»%xbšJUTTÄ'©ÿæ\Òz†ÆÜJ¯1÷Ö5 VŠÎ]ähÚgú.N3óË‚ƒCnwÛöX¹{==tdtü½t‹ˆàìåvíý”Ó‡/ðø¨ÜÿËI;ÝîŽíÿ&ãoïÑ»]{úÄ¥mÇöä_øžÿîÝÏÑKßÓæÃŒûå§Ú½téÙÙÙh þÍçãÇ“••Źsç(((@«Õ:õ×§sçÎtëÖ;î¸Ã©™l.µçÍ» žØípvšQQÕ?¼œœœæ §Å§Wa2±g×'ä®[ÉÜ'¤C¯$5R… «¤%°Gg:I¯mò嫨mð#!a„7þù.ÃÚ¦Ys¹ÙÆQkýh{{qÓú‡óòð^$å\'aã—¼=øV®ž~6Üe6G?{Öåù©oš5ãïØ±cóV{œ†–‰ÅœË›Ï>Ë–O¿âšYCô€1¼¸üOÜn¨wzîT%W‘¹ï ½Œ¿-œëçŽ`‘ªÐH*$ 5j*-*ó5ÜQFœöÿ=pˆèè;P«ë>¨%Ë2_|ù £Jˆ0s4ï²EB¥–@eùéKjd‹• %VÛUr5²˜ÏîáŽ;¢ozðÉb±ðÕþ/è|á{Û·£ìè7XU*¹IRcµZ°H¬V+Áå%t¾ð={Óëm·¦›&pff¦}X­Vc6™A]…$Y¡ú?$  °ZA²Z±X­H€¤Rqýúubbb¸víû÷ïç®»îj0˜¦ØðÐ|ÒO_cƆtùÃzºæÍö~æóïc áÍ÷‘w[ß±!DÕßþ?gÁÃ8²}VmdeepýR½ã§ðÇYO2åëõÌzm4I¿ù‡^݃üÑŽþ¿½L]>«ÞÞÊ™ù¹Ù4³²²èÚµ«ÃwlãÝlœ†–É¿›ÌªôË,ÞºŸI!Géwïï™õ@ÿÝó¿õNϪ*Müxò4ƒzh©*<‰å»Q‡µÃjP!i XK¥©L¦´(UñeºEë9uò[*+ÍHRÝ›»•f3G.#ªW—®_¤Â’Oh½ÆªzKÓ,Wbª*£ ØÄµ² :ÄòUf&•f3Z]ݛ畕•äù5wJz¬ß£XªÂ¯m&£­JÈTZÍHefÌ?b9C'Œ=ò5æGÌènÒnM7MàË—/Z­"ÿÇ|üŒF$IB²JX%+’U©:YUÈ?uÕÃU*eee´oßžŒŒŒfß´zçLóÜFóúX/¥ò /ün ïÇöæ×ó^`R¯0‡ïV·5ø;EgÞA–ël+wÏ»<õú?ùöÜeL–êaæâýȲÌ-w½Ä€ ídœø3—*îçõ/óñ˜Â˜àz—ICóSß4ëŠÑ™qê[&9˜ÀÒ_eéOí]ÏyY^tÓé¹›UV!ž&¬»ÉO‹UeÂÊ$«® •dk²ªµÊ„Õ` ì6kÎy,?íÞÕ¥ÊZÅ¥ë9tºÍ?£…2©µ¬ÁOe¢©NúŠ*ereR?5"üÉÝw‹,£¾I»«Œ|é¡þ~ø‡…@Eòµôþþ¨u&$IÊT©¬©¼ ÿð‚+*‘/]ª׉eyÓV«ÕøùùŒlµb4P«Ô ÉÕç×$©:Ym ×Ö-Û^­Vü©¬¬¤²²²Ùض•)Ë22?Oëf?èõï¿Áë«þNjú7ùü{2–ñ«Ck¾k©ÙV?ÛûYOü?ΖW±bÇ!ÆtÔ}G_¬ö áÅù½HøS‹¶ý™“e•LY7¯ÁåÑÐüÔ?Íctfg–É'ßœ “A]gûu½w'FE•΀*Àu°)Èmpê TF=•ŒTZ‰¥DUk@.-FSUŽV«E§Ñ#Ë–:ÛÕ«õ´VŒF+þFµAþáêýÑ««w›L– ®ëJ1ª¯Rn1S^jE§΀üÓ©Út*  !üBø‡‡að7  B£ÓVªÌUè‹‹)7”ƒ¦CéuÔX1h5Xš’À111X­V‚‚‚Ðh´h´ôZ’Z…Z$ $?e­ã‹***(¯(§ª²Š»îº«Ùxf· –*à­C¹¸ø-w÷îˆÆèÏ­!hý1ꪸ\­Ç Öbµ”S…–ü‹?ð«èa¨Ð"˦:ÛU#Ñeð`.}wž®èÃC ŒGí€ÚϯúKeå¨ :¬¨‘M¥\.«¤Ë°¡¨Q;•3RJJŠ5::ºÎ¿þúk, ½zõ¢sç΄……Õù½ºìÛ·ììl, ýúõsz<%ˆ‹‹ª乃\UŸ9Š]ïÅþôuè]»¯ÕÓjµ˜L&6.›Ç´ÉV:ÄtÁØ&YkD­ÕJ“Œ\YBùÕk\<žEò¿ÔüÏÂåèôF*+ëîµZ-æ ¯šMŸI0<¶­‘@½?Zmõ¤ÊJ3×M¥TU–óù‰¯øæ_°jî´FC=íê(/»Îߦÿ–¹wt§ýí]Ð…‡¡ Ik¥™ªâëT^½JΩ³¬9y–YÉ0oÚ.Toá6x!GïÞ½¹|ù2‡"99Ù¥ 9n»í6¯½ÎÚ-qË&îì3c›ÛyfÝ«h‘ñÒÅáq&“‰Ð°p†N~’ÔÝ/0±]QmP«tXUd¬H’ zòŠ*HÝ}•a“_%4ô®\­·Ý°ðpžHx†å»Ÿ':<·FFBúiëÇ 6ìÈáïrlw! Æ¿LH›6\»V_»´¹å6âÿ÷E6þéÿ˜Ýã-m@­•+ ë4èôZŠ®^aÓ‰ïˆá%ÂÛDÔÛnMRJJе[·nZ‚{ôéÓ§Îáÿýï[8ïÁѯ¾äë}«è34ˆÈ.ÝñóÓ£¶ê()+ ÷Â92Ò‹¹+þ âúö燼ËNµ{kD‡¿:Hòþ•Ü9 €¸nwP}YcaI™g¿á›Ã%L:ýóÃeçÚˆhOúgiì[½šñ½{ÑñŽnþtygIaÙ'Ï’vôÃæÎeؽãùáÒ÷ ¶YUUEvvvuwéÒÅ©@A)""ÚQVRÂÁßpõÇ# *Ä*ƒD·´¹‹ÁÆ`Ôqùr~#Û½•ë×KI?ügóaâzÂèÖv ÃÜC`@—ó.5®Ýväÿø#{>ú˜¼cß@eõqYg¤}ÜŒøÕýÜÒæòœü£ ËòÏ Ü©S§F#JàïçGhXþþþèt:¬V+•••”••qõêUÊÊʚܮV«E’$L&åååMn7,,ÿ€ÔšŸÎ TURzý:× ®QÚÈvíûÀ‚àJËÊý£÷µvÅñPAðb€Í›7{:AiàÀ?oBûbQ¿ øª8î<Ø#Á‚༃Úÿ-öÁ‹‰/&X¼˜HàV ;;›Ûn»ÍÓaMp³u(X¼˜H`Aðb"Ÿ±hÑ¢†¿äc¼:-Zĺuëê.x#GŽœœ|ÓÏ“““9räH Fä=¼:t:]³Ü¾Eh9}úô!;;›‚‚‚>+(( ;;û¦µÓ­×W#;–M›6]ç» HMMåìÙ³X,ºvíʯýkª"µhÑ"FÍÞ½{Q«ÕüêW¿"??ßþþÁÄvÃY–Ù½{7˜Ífî¸ã&NœèÔý{…›Óh4 4ˆàðÙþýû«¯ùÕh\—5-Z´ˆW^yå¦Ã|e]z}AÇŽ9|øpŸoذ!C†°xñb/^LÛ¶mIMMuøNii)Ï>û,£GfË–-ïk~÷‹/¾ 77—yóæ±hÑ"Ôj5;wîlÖùk-È7ß|CEE…}XEEÇŽcРA€sëÒY¾².½>Fž}ûV¾Í‚ èÒ¥ Z­ƒÁÀ¨Q£8{ö¬ÃwFމN§£OŸ>˜Íf‡÷?þø£ý{GŽ!!!   ôz=cÇŽåÛo¿möùk üüüèÙ³'‡²;rä±±±øýtGgÖ¥³|e]zý&4@`` ýúõcïÞ½Œ5Ê᳋/²sçN.]º„ÙlªoOZ“ÑX}ëPÛ&xÍ÷5olW\\ÌÊ•+ìs«Ý–àºaÆñî»ï2lØ0$IâË/¿$1ñç§a8³.å+ëÒ' >>ž•+WÞðµ72~üxzôè^¯Çd2ñÒK/¹4ÀÀ@æÌ™CPP;Bj #**Šo¾ùµZMDDáááöϳ.U*•••ö§hÖ¾ ޝ¬KŸØ„†ê{ûŽ1‚Ý»w; ¯ªªB£Ñ Õj),,ä£>ry àƒ>àêիȲÌ?ü n†àfñññìÛ·}ûöïðYcÖeDD{÷²’âââ¾ë+ëÒgz`¨>Q³Và --7ÌðáÃ9vì˜Kí1‚/¾ø‚¿ýío\¿~¶mÛò‹_ü¡ ?‰ŠŠÂ`0 ˲ýQ¥6Y—“&MbëÖ­ìÙ³‡ÀÀ@î¾ûn‡}\_Y—RJJŠõСC 2Dôû¨ììl D^^ž§C\Ts}ú0cÆ ôzýM§)ž¦ˆk¡û÷ïÏ™3gìïW¬XÁ¨Q£X±b+V¬ ]»vlÚ´ ø9y’’’©¾q:uêÄG}Ä•+WêŒ!55•ììl–,YÂòåËÑh4¤¤¤Ô;MAð4E$p`` Ã-O^~ùe¢££ÑétF&NœØà½Ÿgîܹ”––²téRüqÞyç ퟧ§§3mÚ4BCC1 Lž<™ŒŒ ÷Ϭ ¸Q£bÕ¼Á˜MÍÉv~¸±ç‰¯_¿Ž¿¿¿ý}VV)))\¸p“É4|󲆯 å‘G ¨¨ˆÔÔTÖ¬YÃóÏ?TäzñÅï¾É™Ðº4*Ú|´%mcRgddн{wûûÕ«W3eÊzöì‰Ñh¤¢¢‚ßÿþ÷õ¶Ñ˜q‚ƒƒyàxüñÇíÃBBBX¼x1¡¡¡Š]<Éc›Ð¶£ÐŸ}öü1÷ÝwŸý³ÊÊJ4 :Ž«W¯òÞ{ï9ŒëççwÃ) ³|ùr¾ûî;*++)))!--ÍáÔÕˆ#X¿~=ùùùȲLnn®Ãs—ꚦ xšGnj—˜˜ˆJ¥"00=zðôÓOåðù¦M›X½z5aaaŒ7ÎáÉ cÇŽåü#&“ɾUÐÐ8#GŽäÃ?äܹshµZzôèÁc=fÿ‹/¦¬¬Ìáj-o§ôäß_MQ×úSD‡……5zœ¨¨(^{í5‡Š!I’øóŸÿLTTmÚ´aÞ¼y¬Y³†wÞy‡'Ÿ|ÒáiìIIIŒ5Š×_¿þõ¯¼ñÆdffb2™(..fË–-uþÕóV¶yi겫©®ÍéšÃT*¿þõ¯Y±bk×®å±ÇC¯×ß4F__MáS=pNNDGGÛ‡ÅÄÄPZZJNN ,`÷îÝ,X°€ péÒ%¦NêÐF—.]X²d ³fͪs±±±œ={¶Ñ±)•í/¸;–³èÔ©K–,á‰'ž ªªŠÉ“';=¾¯­ƒ¦ð©`ïÞ½ >Üþ>>>ž}ûöð /pêÔ)Ìf3ååå|øá‡ÄÆÆ:Œ¿iÓ&JJJêl»S§NL™2…õë×»›Õü ÞÔeç¬áÇ“œœLAA¤¤¤Ð¿§ÆõÅuÐuõÀŠ8ˆuíÚ5û¬†^kúòË/™4iþþþH’D\\ï¿ÿ>]»veòäÉtìØÑ¾ÉfµZÆ/**ª3žèèhfΜɪU«ÈÏÏo†9öŒšÁ›ºìœÊÿøG z3]’$§ÚòÕuÐ^qº¡×šJKKùöÛo2dÇŽ³ßšgîܹlÞ¼™o¿ý–òòr «V­j0–0eÊÞzë-.\¸Ðô™SšG¡ÝµìdYF§Óa6›pø¼°°¥K—RPPàtœ¾¼šÂ§öml›‚Ç·ohµZªªª0›Í„‡‡óðÃ7ØÖ˜1c˜ÿüsf̘AÛ¶mQ©TDFFÖ{TÙ××ASxEÜXÇÇh4"Ë2'Ož´OJJbêÔ©Ì;—k×®±cÇ Po[S¦L`éÒ¥ÃçÌ™c¿Ï–7«}ØËnýúõ$&&rß}÷QXXHZZšÃ>njj*ãÇçé§Ÿ&$$„ÜÜ\þýïß4F__MQW¬ˆK)ApÎ+¯¼¢¼K)]= -4Ž8ŸêÝ|rXpž7\‰%ÜœÏGôÀÞMôÀ­œ­®¯^øêÔQhO”Š5öI‚ÐZÕ¾7¹"z`‘¼‚àE$°+'”OÜž©ù)âB¥ôÀ™™™¤¥¥‘••…^¯'66–)S¦ˆç% Š%zàvìØÁ¨Q£X¾|9Ë–-£}ûö¬^½ÚÓa ÂM)"]ésrrxî¹ç*[¬V+Ï>û,999\¹r…•+W2gÎ}ôQÞ|óM‡Û²$&&²{÷n.\h¯~æ™gèÛ·/~~~ ÆŽËÅ‹›>ƒ ôÆopêÔ)ûû'N°|ùr‡ï4u×T׿tÍa²,³uëV,XÀìÙ³Y·n]«¿tÒŠH`Wzਨ( ƒÃðäÉ“øûûÅŠ+5j+V¬`ÅŠ´k׎M›69´qîÜ9–,Yb¿#GM&“‰]»vÓøò“'O&99Y–±X,lÞ¼™iÓ¦9|ÇËØY©©©dgg³dÉ–/_ŽF£!%%¥IóØ("]ÝŽ'==Ýþ~ïÞ½ 6 €—_~™èèht:F£‘‰'rüøq‡ñ§NzCùT÷ sæÌa×®]LŸ>ݥؔ®C‡DFFòÙgŸñé§ŸË­·ÞzÃ÷šºŒ•žžÎ´iÓ Å`00yòd222\›¹VD±lçz­mРA|ðÁ”––bµZÉÌÌä·¿ý-YYY¤¤¤páÂû¦XÍ{@Aõƒ¾ë’””Dyy9Ÿ~ú)III<÷ÜsnžceèÛ·/}ô&“‰?üáu~§©ËØY¼øâ‹@õfºÕju¹­ÖD lKΆ^kó÷÷§gÏž8p€^½záççÀêÕ«™2e ={öÄh4RQQÁïÿ{§c2Œ3†íÛ·»6S^`÷îÝŒ3³ÙÌŽ;êÜOu×2V©T˜Íft:À ·2 añâÅâˆ#)bº)G¡m›xéééöM;€ÊÊJ4 :Ž«W¯òÞ{ï5ØÖ»ï¾ËåË—‘e™¢¢">üðCºuëærlJvâÄ JJJ:t(¿øÅ/¸xñ"ßÿ}ßuÇ2îС;wîÄl6SPPÀ† >1bëׯ'??Y–ÉÍÍeݺuî™Y¦¨Ø±±±”——£R©8%&&²iÓ&V¯^MXXãÆãðáÃõ¶Õ»woÖ¬YÃ¥K— ..ŽÙ³g»›’mÛ¶I“&¡RUÿ Ÿ:u*[¶l©sSÚËxÆŒ$%%±mÛ6BBB?~¼Ã>nBBiii,[¶ŒÂÂB"##™0a‚›çÚ÷ÜPÐÛm·µxâZhApN^^žò úEò ‚k‘ÀJ¹K¼"XôÀ‚àE$°èÁ5ŠH`Ñ ‚k‘À¢×("E,®QD+­¶Z­¼úê«âŽ‚â)"•ÖïÛ·Y–=† 4H ìJÜýPýÔ¾?þ˜™3g6m¦¬´´”ùóç;X,,XÀõë×=™ÐXŠH`Wzàæ*èߺu+÷ÜsG.)m)þþþ 4ˆÿüç?öa'Ož¤K—.z02¡±‘À®î»» ÿüùóäää0fÌ—âñ&£Gæ‹/¾Àb±ðõ×_ÛŸ,xE$°­hhðµ¦AƒqìØ1JKK)))!33“AƒÕÅæ¯½ösæÌ!11‘Ù³gßPƒZ» ãÆ<òÈ#ö _Ö¦MºvíE>]³pIDATÊáDZZ­œ:uŠÞ½{{:,¡‘QNX³©1Eýî.èÏÊÊâ…^p–˜˜è‘§U´„qãÆ±aÃÚ´iC÷îÝÑjµžIh$E$pSŽBÇÇdzyóf‡›²Õ.6ߺukƒmÕNT_N^€N:¡×ëIIIáðt8‚ ±­Ø”óÀ¶bs“ÉtC±ù–-[˜={6ùË_¸ýöÛݪÏ;v,ôèÑÃÓ¡.PDA¿à9{öì¡°°I“&y:Á Š,èWÚ•X­Eyy9Ÿ}ö#GŽôt(‚‹¼~XpMbb"*•Šßüæ7„„„x:ÁEŠH`qO¬–çËçZElB‹ä×("Å>° ¸F ,z`Ap"XôÀÞEÔI+‡"b)¥®ùÃyœSW2FV­ZåhZE$°RŽBÛ’Vô0Ϋý‡î«¯¾"++ËCÑ´>ŠØ„v%y›« ¿5h겫OZZ£Fj®Ð…Z‘À®ì7WAkàŽeW—£G)Ú‚‘À®n>»» ¿5i겫ËöíÛ7n\³Å,ÜH ìJ1?¸¿ ¿5i겫-33“àà`"""Z"|á'Š8ˆåJ1?¸¿ ¿5q÷²Û¶m>ø`³Ç-8RTì w<=¾µrײ;qâ’$ѽ{÷æY¨EQ=°+ÜñôøšãÔþ·/Ÿvײ۶m›Ø÷õEô+å<° (" úEò ‚k‘ÀâZhAp"XôÀ‚àE$°èÁ5ŠH`Ñ ‚k‘À¢×("Eì]D¹¥r(âB¥œ®ë‡éËr¸C^^ÿüç?9sæ Ý»wç7¿ùx@@ QD+!ymDÂ6ÎÚµkéÓ§sæÌÁjµ²k×.Ö®]Ë’%K<Z« ˆMhWöEA¿ëÜYÐùòeðóóÃßߟ &——×R³Òê)"]雫 Þ¼yüîw¿cÑ¢E¤¦¦"˲ë3¦Pî,èïÕ«;vì ¼¼œ²²2ÒÒÒˆ‹‹k©Yiõ± íê>°­šÆv!~í¢ôš&NœÈÓO?í0¬vA¿móY–erssINN¦¸¸Øá±¥¾¢©ËÎfúôé¼òÊ+|øá‡@õƒÃ/^ÜŒ‘ 5)¦v¥¨¿¹ úU*QQQ<öØcìß¿ß=3©0î*èOJJbÈ!¼ýöÛ¼ýöÛ <¸Õݢȓ×7¦¨¿¹ ú%IrØOô%îZvß}÷ ,@£©þ)M˜0AÜ8¡)¦v•; ú×­[Gnn.²,“ŸŸORRýû÷w96¥sDz‹ŒŒ$55•²²2û>pûöí["|öÀå΂þ¾}û²víZ._¾Lpp0 `âĉ.Åå ܱì}ôQþñ°cǺvíÊ£>Ú"ñ )èÁ9Š,è×B ‚k‘ÀJºK¼‰"XôÀ‚àE$°èÁ5ŠH`Ñ ‚k‘À¢×("=Õ‹ÂtÁÛ)âB¥öÀ5\Ô Jä‘v¦ÇUBRÛ’VôÔ‚Ry¬®/A³I™™É–-[ÈËË#$$„ &p÷ÝwÕ‰W»ç¬=,--]»vQQQÁ€x衇ìæ ‚Ò)b¸)Þ}÷]î¿ÿ~Ö¬YÃsÏ=Çùóç5þéÓ§y饗øË_þBQQ‘½®U¼×'°^¯§  €¢¢"ÂÃÙ1cF£ÆŸ>}:AAA1mÚ4¾üòËæ TšG·º ¤­J©¾j¥¹sç²}ûv¶oߎN§cúôéôíÛ×éÚ´icÿwÛ¶m)**jÄ‚gy4:²[_1¿MçΙ?>P½?œ””dO`•J…ÙlF§ÓÔyW‰+W®Ð¶m[òóóoz—AP"¯ß„^·n—.]¢ªª «Õêpº:°sçNÌf3lذá†ñ7nÜHqq1ÅÅÅ$''3xðà– _šÄë·öîÝ›·ß~›üü|"""ŠÉg̘ARRÛ¶m#$$„ñãÇ“‘‘á0þí·ßÎÿýßÿQQQÁ]wÝÅý÷ßoÿ¬æ&¾íßâ|° $)è÷–óÀ‚ 4µ ú=Ò‹ä÷ðú}`AhÍD ‚ ,^L$° x1ŸL`q‡¡µðÉG¹›—(¯T¯¿£.MyÒƒ;µ†dff’––FVVz½žØØX¦L™Bhh¨§CkDÜŒ’’’|6qmvìØÁ¨Q£X¾|9Ë–-£}ûö¬^½ÚÓaµ>™À®ì7õ©õ‰‰‰ìÞ½›… 2kÖ,·ÌGsiê¼ÖôÌ3Ïзo_üüü0 Œ;–‹/¶Ô¬´z>™À®ôÀîxjý¹sçX²d‰âŸëŽy­‹Édb×®]Jš—O&°«G¡mÛ´©ýÔúèèht:F£‘‰'rüøq‡ñ§NJ@@€ë· ¦Îkm‰‰‰Ì™3‡]»v1}úôf]ø™O&°í&@ƒ¯55õ©õÞTKÜÔy­-))‰U«VqÏ=÷øü~¿’øüQè†^kr×Së½AsÌ«Ñhd̘1lß¾½Yc~æ³=°«ÜñÔzoáŽy}÷Ýw¹|ù2²,Ûo Ø­[·–_ ôÀ厧Ö×§ö¿•´yéŽyíÝ»7kÖ¬áÒ¥KÇìÙ³[jZ=ô ‚àšÚý>¹ -®…Z ŸL`¥\‰%ÍÍ'XôÀBká“ ,z`¡µðÉ=°ÐZød‹Xh-|2EܼDA¿røä…Jé?ÎÎ;9}ú4:ޏ¸8¦NJPP§Cs;«ÕÊk¯½Æ™3gu±Š¯=p3Ú¹s'£Gæ­·ÞbéÒ¥øùù±nÝ:O‡Õ,öíÛçð\*¡eød»Ò7GAÿSO=E\\z½ž   |ðAΜ9Óôl"wô”––òñÇ3sæÌ–_¨Á'Ø•¸% ú?®ˆ ýÝ]пuëVî¹çq®ød»ºÜœýÙÙÙlÞ¼™3f¸›»¹« ÿüùóäää0f̘‰[pä“ ìJ1?4_Aÿ©S§Xµj³g϶?LÜÓÜUпqãFyäT*Ÿü))žO…nL1?4O‘ûáÇټy3óçϧcÇŽM›17r×¼feeñ /8 KLLG¢[ˆO&pSêãããÙ¼y3Ó¦M³¯]ä¾uëÖÛúä“OøôÓOY¸p!.ÅÓœÜ1¯µU$oËòÉnÊy`wôÛ’cñâÅÃ׬Yƒ^¯w9Fwqç¼ žá“ýJy2ƒ ¸[«(èÉ+´>™ÀJ¹Kš›O&°è…ÖÂ'XôÀBká“ ,z`¡µðÉ=°ÐZød7¥vg±ú¡C‡xâ‰'D¼Ðl|òB¥œNIIáñÇ·W ÕLdqµ’à>‘Àum2×扄.(( k×®ö÷¶¤=²à.>‘ÀP‚ººO,Ë2|ð{÷îÅd2ѧOf̘a¿ òÊ•+$''sâÄ , 111Ìœ9“   {’ÚŠÜE+4ŸÜv—ÔÔT²³³Y²d Ë—/G£Ñ’’bÿ¼¾Âw[Â&%%‰äšHàz¤§§3mÚ4BCC1 Lž<™ŒŒ ûç®<É^ÜÉg6¡¡î}K[ïg;°Uûµ>¼øâ‹@õ=£¬V+’$Ù?ÏÊÊ"%%… .`2™>„ææS \ߦª³Eý5…„„°xñbBCCëüÜÕ"Ap± ]#F°~ýzòóó‘e™ÜÜ\‡ÛÂ6æIö‚Ð|ªv·„„ÒÒÒX¶l………DFF2aÂûç-|¯¹‰oû·8À%4…Oô;sšH vBSÕ.è÷‰X$§ÐZ‰}`Aðb"Á‹‰/&Ø ¢¾XP*‘ÀNÉ¥ ìÑ;åÊá§‘š›Rz`%Þ ¾ëÏ…æ'Ø J¹Ã‡Ro ÖsÄ&´\IÞœœž{î9¬V«}˜ÕjåÙgŸ%''‡+W®°råJæÌ™Ã£>Ê›o¾Iqq±ý»‰‰‰ìÞ½›… 2kÖ,·Ì‡»b”C$°\ÙŽŠŠÂ`0pêÔ)û°“'OâïïOTTT½7°9wîK–,á¯ýk“çÁݱÕ4oÞ<~÷»ß±hÑ"RSS‘eÙ­ñ 7'6¡Ð”G•¦§§ÛŸü·wï^† Tß  ¦‰'òôÓO; ›:u*.M»¹c³±m>Ûªµ’““)..vx\©Ð|Dì[ÜÐkmƒ âØ±c”––RRRBff&ƒ ªoðÚk¯1gΙ={6%%%ã7Ëü¸#¶ÚT*QQQ<öØcìß¿¿Ùâ‰Ø 7»@C7ð÷÷§gÏž8p€^½záççxþfÍ›$IûÖBó=°šrض©šžžnßDeÜ À±­[·ŽÜÜ\dY&??Ÿ¤¤$ú÷ïßá ˆØ)M9…Kyy9*•ʾ¿ ¿€mœÚÿnÊ)wÄÖ·o_Ö®]ËåË— fÀ€Lœ8Ñ嘄Æñ‰‚þ榔óÀ‚P» _lB;A$¯ T" ®…”J$°D,(•H`'ˆXP*‘ÀN=° T" z`A©D;AôÀŽ”VÎØš‰ 9œ ”óÀÇgçΜ>}NG\\S§N%((È£qåä䒒™3gìOiŒ÷hL­…è „äعs'£Gæ­·ÞbéÒ¥øùù9<«Éòòòxë­·¸ûî»Y±b‹/æôéÓ©5 ìWö›£ ÿ©§ž"..½^OPP>ø gΜiñØjúøã¹ï¾ûèׯ:ŽððpfΜÙè˜׈v‚+=pKô?~œnݺy$¶šãñä“O2{ölÖ¬YCiii£c\#Ø ®…¶UûØÔ.šŽŽF§ÓÙ÷?î0~}ýÙÙÙlÞ¼™3fx$6›’’òòòxùå—yã7Ðét¼ÿþû.Å$4žH`'¼þúë.õ7WAÿ©S§Xµj³gϦmÛ¶.Í“» úõz=Ó¦M# ¦NÊ7ß|ãRLB㉣ÐNr¥¨¿9Šæ>ÌæÍ›™?>;vty~Ü[ddä Ã$Ir9.¡qDÜÌÜYÐÿÉ'Ÿ’’ÂÂ… ›”¼îŒmèСlÚ´‰ÒÒRÊÊÊØ²e wÞyg“cœ#zàfæÎ‚þÍ›7°xñb‡ákÖ¬A¯×{$¶áÇsõêUžþyÌf3½zõâá‡nt,‚kDA¿ xQÐ/>D$° x1‘À‚àÅD ‚ ,^L$° x1‘À‚àÅD ‚ ,^L$° x1‘À‚àÅD ‚ ,^L$° x1‘À‚àÅD ‚ ,^L$° x1‘À‚àÅD ‚ ,^L$° x±î ——ç‰8ApC_KÓ–©&™ÜrUWÉjU§ºJªQe·ºûØ1HIt…%3©kc¦‡y¿·ïÌK³±û óIú€ù†ñ%"XH$²*Sb·©ª 6ww_þðåÝܳnD¹ÿä ×éXÂŽëOŸüùúuûüà˧ÿÛ‚ÉÄ‹K''sáÇíqàÇð·­ýè’ß>9HBÿ2°#7ºôí¹ˆ.ãñe°¾jui~}Icñ“(^z•›ÓÇfëXÜÅUã·™¶ö¨úÈô±ÙÚ íÛªñ[ªÙ|Tm|yíIPŸ/ìØÍÍâÎsýOfq¼¸<>¾½½íÜ:A8=î]\\Ó[=á±þn‘„}包'p°è¸×é«oç"¶«Î¿5§ä'ó‘+ƒÆŽí®F7ÓÊq3]šñÌ+ã}œÝÞS}{ŽÙvndz{r~ü^Òoߤ¸Î«Ž…ßf@5ÝEåeò×fû ôT±(M·ßíù·ñõíÚÏoC7¡ñùxíçcÛkˆó2 Áw½cø¢-nM5â# ¢ úÇüZ9+»þëÛ7ïÇ31·ÓÝÍ·]?Šm?…Lˆ›°r¥'Ç¡Xa¬3©Î0a·úzn³xî­&w|«>†ŽSú)Lgp ¤„×¾qÅíg~¸.Žé#¸®ð•èoårÄÝB„.®ÄöÚó€È,.ÖYžÎïªu‡8“|9âGÑ .ƒÁõwÇø®G0=‚ÕeÚ~„]/ÁQ6ƒ ‰:´Qmœµç©ËL‹¼ø¦ÒI~'üÆaƒÖzøÁÊIç¾»H¾ÿ°ÿ’Xo¾za½¾²~veo€íó øP·þ5ðÚ·ØúPÝ_9óÜwàÊþVs­ê[ŽÀª²åø]¸º¤U§®ÇÖe—Á³[µš™ÖßÓçö:¶_Êlå«2~Åá?:ÞäøCU>Reç–Q,æ»ãtÙùU©+ ¼J€’Ïí$Pj·©-YÑŸ¹ÉB—==žœ( µªýj/@¬aì%ðã[×Aµî¬sâûb{€í¹Sçv8…€¦jŒ¼ig¥}ÖKæ~n>ü°8-ù\ή׹¸89w5 …×Î}q6\|^{ªÏŸêIç¤;쯛êð¼{qZªÏÊ÷·=ž—Ÿ)<2ç9 .GöøÃ4 ßÁÙ!´F½`a‡@ïøÅÂvØDÖítûÝ®Û!È mOLbzÓíž¹¾žëXŸuéæw¡;Á‡~à óq,ª´qŒêòŠ/Õ"µ¸s{*RH–.¿.JìçuP\¹°Ú¨Ð¿¯)6²Ñù‡¶µ6Í>˜Õoþð#À£Ùþiçt8J 0¿—@hÃìNO g¾T¢U @ÙF•ÞÀjGµ'‡E·s~†‡Yí©4ô:Ãaw°Í\^ÜË\zÛLåÕ½Låìb›¹¬àÍap››<)Î⃠ɩˆg‚NÀ„é2÷å®-yûsƒßÝ௱íµ%©ï0æ”9v›oRvTxÅ'oî¡f@«¸ßéÅ.‡üúÖ÷ë J¾l·¼ú­mÉæÞ&í Ì<ÎMª-3•õÚ$•üÖ6 "•|Â-ìtÌÍAˆÃ3¡×{qf¨¤÷{ ®˜û¯›v?ïÀû–|( ›¦¹óÁàcÐÜé}™ýîé=(yýÎù°w¶ÎÌÖÂÔ5³Þƒ8윞œÖMuØ=ëöëOu7‹ ióáÚûjoݽÁ£±)6g¹»—-»WKÕiƒ–»]Wÿ‰-wï ˜º°C{Ú‹™zÁ–y¾ùis«? &¡¥›äà„Þ?ꤎb;Ôöº$QìN–í ÞšžLl/¹ €2ÐæA±5¯:Å£™í µ6°`,¢ü¦ rÙ¯é¬3¼¸0¤Üx¹˜Ñ427ª¿ãÕ`¬¼„®²¯ƒ ®¹cá“âGÞÈUVÜZn^²‘Õi¢ ¥Vå J~èwxﻋ…ˆS¼AàeáI׬ôöÉ`Ç™ ZîÕŽ\Û_ór=q§¿¨¾¼‚|yË»j7ùu¢ãWj«?Ð+”ŸT_áÉGÜÀ’ùg6påûí—W´«,ï–ËÎÿnãè†öp×yöQ×ùI1ö|×¥>àm¼Øjm(|}CCá_Ìì ç”Þ·Q‹m{ö2Hâö4tõTC&ê~”o}²6¹Ô­ä?Z*-’C•¢{W¡´›+œT5Ò»?Áë‹EœEhxªð½ôÆu|[˜[ a˜xæ: oä§Å]h”Ûö¶”ðxp¯zk7iá¤\a<Ò¸w@ÖNî‡êuîOÅèm)8¦P4µ^÷¬÷ð·¥<š®ß8àÝÁ#À¸%]=c7Ê~ô¦Ÿ²Ä²‘w–=W#–ÙÈý“„.˜÷ñlj/ ê{a¤üBHOm1™Å¼îé=lô”ÄîMFY'‘ÀìÂ7ÂS(Oßq{zN³•Ý'ó6ç•¢‡ô Ý‹µolÚÖÔ|nô›· ã´gàãrî1äÕ=À¹nZ5&Ý×óK ùr?¡¤OQùÚÌ2eó{8Ó>ìé<ìé>ìé=ìé?ìé]<ì饾7u~Æë*'Y¿æ9U›å/B1qA:4FÉ„•È­£hÉ}Fe@„NŸƒn²àÓÙ úÍŸ}ÅÅt¶>éò‹ù¨kÜïZÎ>êb†÷¹˜ÞÇ\Éɽ®ä#ÓËéý.森åì~×òqéåü>Óÿ˜+¹¸×•|dzÉÊͯ¦‰ÅÔ4+Qây"Þ(h<§ÏVHˆ¨!÷I™ŒŸüòÿ÷û)¸ÛòÜŸÍ‚¼´<ëp*ÓÁ·‡Óÿ÷?ÿß{“V>)˜Í¢ÓÿõÿÜŸ ôIá4üôdWIÆú¤@:ùô4WU|û¤p:ýôDWQ2ü¤`:{4÷xÓù§'»Jòì'Òŧ§¹ª¢ò'…Êןšê*Já÷§š¢ûðŠî?ÿ¯*5_Éжí;m†¸L³Cð%gVLÈ^ÖmîÙ7=œžÜ §=ZBWÐ$¶GÆà*^¤†¦HÉ8ï/ÛVšEÑ=#›bµt½[ Dïáj{{ÏêîïÙ#Øà†u¥G¼Á½Z»Û{ø[Û°z÷˜·6ÝÄŠ»›ZÅð7«š>î ®»¿`{Ö¨õöÖ<{{âìmØðˆ7¸_kwûk›5_<ê­­{ööÅÙÛ°éåQopÝý}ÛÛ´ÅèQïoÍ÷ÿ)ߢ­‹;,Ú¹¦«ƒpn\‚Y ü7uh~ÂA!’ç¹ñÜ^NÅß jØ¡°Ûʤ2WþÃ|öû¹ë8žZ)&l‡Ù™ß yXulÚðBIŠ…t÷e/uÜÅù0÷* „“ïãd$å &(²ÛÁdC¿+ìdöýrÕ{µuç]üÿ¦ º4·2«9š;ÝÓ\ó4w²§¹GKs…¬ÍÓÜÙžæš§¹Ó=Í=Zš+äÀhžæÎ÷4×<ÍíiîÑÒ\!×Kó4w±§¹æiî|Os–æ ÉŠ§¹AwOsÍÓÜÅžæ-ÍrW ¹ûIÎù‰ Ì•ß|2s!Ùsó"Éž;6Î{{æøh™c±¬LóÉþV§yšìou1Ñms;]“èö×:÷@tûkGLt;û/ …•ÑÜk×§GÚ£z4{ºk˜îê\íè„—':ßåRT:Q5Jü•ÓZ¦mŒÍQáý{4 ö·«÷@‚û›žG|ôÝ¿KÃ`½zD·¿êyÄDwÿ> ƒýýê=Ýþ®çÝý;5 ÷¬Íݰ»'ºÇKt÷ïÕ0ì퉮y¢kèânoC¹ªÚÆo¡&UíoÃïªú{ªzÀTuÿ.&ÃÁžªš§ªÁžª.Uõïß‹d8ÜSUóTÕÉžªî…ªîßMd¸÷ͺªjÈMdOUÛSÕ1ôïŽwæ6ŒS†DOÿ _Œg© p9S V†Ž‚IÜ^à®à"]R~õ:ÐE<œÝO‚q¦#|¹Xx˶#"Ø'™áE{Dsñ#;W;bìEeyRŽ-<{©ÊQ·e"•džqëÊó W›Êp–ŽP£³k,ѹ{/ðÏ;yR™Ý4?L)Ô¨¦( •ª’[Ìð#Ë–æië·‰z+z”HÂ±àÆ¹Ùêj(˜<ç®»14ÅV‹â4ÔXÈþ(l¤®ƒ§…™È¥–u¹jŠ‚*ÔgÎMµ,¡³9Ÿ^v)Üãxf/€ —¼Â¥Ïe¦!I´ñr QtìÁÊ_s¥ÎAY'D€\¡Foý†Eïš²dÈ&hú¿]Д¥6A3øí‚¦, ¯ šáo4e lMМüvAS–üÕÍéo4eiSMМývAS–vÔÍùo4e ;MÐ\üvASšì2#óu=pV|Æ2{fVúò¢õvºIï v‹ýÅӢĿºëw=¹zë 8ÉU>"ÇOûi§k{èw¬ë™°þÜ=,¬Oº£$×× J_p–¿va]oì% ß­y ïìñ{ pªÛ¬eб^ŠèâjÚ–í;ÖbÒ£ËaÅI9F[4ßqôP0þFuÛ0†¼±ßˆ[úïý8t1ÀÕz¿„)ÍO*ÎæOÜñëÁ­ut:-zøöF„7®¸Ý¢)ÏÚúsÌÁh~Z¥9Hà/íØŽDmÑôÕ'ÄX¬wîB c~ùùŸï¥Âìò¬~—Ï×C¶`ýÙwcì÷ë`d]ß4û=¯ºJ1q}ììE0§@}a¥CaçϽ`üÁìù¢bÏï“ÑÜ bÀ*µx£§^·ÞN¾C`ZIÈdú:ñó¬Z‡8·’¨ÜØØ †Î"ÓS¯âº¯¢(ÑQí¶@¬'‹˜'W¶¢d±B“‰öª²ŒÇAµöCj/Bßö¬l‹‡û Uä Þ'_Åb«¹½¼zñíÛm~s5¹¾Ú¦!Ÿ)“´Ñ60A>zýê½ÙÙM%&»ùîÕk‚ãõ_¯WN«j¯|ǵý6°£LóJ| wà A ¥„SÛw²ó8S©'ÀÞÓ0bbQ ‹³C'¢EBÿÁ|.àI¨*q´5è\½=N D)šâ²ëO@þ:A¢°£HD—Û¶\˜€PópŽ5‘ÜoûNÍÞæ"žÎ}ÁVžu¬7îXøQVëWeîoÜQhJ9b!0üØÍÚìÇ”uY&/—á刳âˆR¢–7iôº`ìÎb0[½;Ø…OPZ\`ƒÞÒº áà¾5ZZ/mßú“‹ŠÉt3<®áN צõœMß“p#Ë Æ eöñä¶‘ˆ¬ˆ]ñ VY·Aø1Ëì‹;ŽŽŸ^Å¿³áÔÿ"²ü ,°ñ$°FÀ¹­$B)ÔöÛkY àƒDŠ'/èD„xxâ—3á-¬B,€z—/h$:ä`ÖÅêq„w !Ç݇ÎlÏ—-ËÕ3A_lpsL¼¦ep<'™/Hœ¸±C7HhÝ‘uGÏhYQ0'-évæŽgðô6 b>„òo×ñyÀ¸“Û—m±f…NTbÜÆHÖUàõ3í—Ï´ŸUº6N/k¸'X0‚ä:‚RŒ›°uÈ0ñ+$²` ³çÁ’èmP- yÒ DhcÍÑ`ÝJ|šÄ"¿QU'Èì'kªå¸•ô,Ó¿É4ÅKådî¯üºó,7ÖÆÏó Âà6׃ˆ­æ.o•ol/m6› 4Ñ\°†áö¥„c2Õܰu&ò|ë‰ôã…F™¤€îÐixêq…Ç ‹ØÞ1èÂÏÜÑñMp7Z¿¤ãµÐ® þþ®à?¹~S[°õd` lìYƒ&lÈÖsoðöP<*˜ OÌóƱOØã‡ °^`ÇÀ¬AIÛ®6à¼`ìÁVl~àF-œÞxµ—ª£{ÐU]<~°b ßÑ6”þ„³tÖ‰;MØÅæÎ" •Îcÿ ¸v¬CзAAJõ&èçð:±=ü–º…‚L° ÞØúè1œèæÆ;bb'ÞþT¯4D#e'Üí:ÜþŒbºIÙ­:Ð@Ú¬.À˜wàŸ{ÐÕÝÜ^Dø.Þ­Ð"Þˆ+ îÁVl{ÖVf±û`è“ì‹8¾6M"á =ý—Ÿÿu3ŠƒÀÃw¿üü_V›,Îcm/RÆfº©¡+­í¡mÊÜ‚òó80x>kÎSoAýغzù†/Ððj(˜‹ØS•‘ÔÃÇbžÕÀý1Éú$è"ä”Ö|‹?¤ù[*äÈ6h®tû˜ñÇ{LàŽÈ}ï! sUÚ7ŸìxÅ™÷ ­wÍy\iôÕWÁÏdxçý^ÿ6æ@ÀÀÞwã:xùÄ]ÉÁIñªÖøcÐsÂ[_8-CºçÏ8XN IÑ ïm@ôe/ûáä5c[xøº1u…WNðª~i@¡¥>Ä Ú[H4½v‚[ß l‡ŒdpªC¿ÿƒ^ënܲæör$¬EãÈ;‰Ò[º< |¾psøN„…Ùš´O³ÅQ¦%C‰Ù«Z„6¬:ŠFlăF ‚…ºÏfx‘Œ‘–;†ó&QCdLàûIÆð @K`Œ®ç#—nMmkfG‘G®‘ˆ­dÑ2àÉèA<;œ¦]â\@·Hõ0¹x©ç ±šú2.Ð5= þã?k¢ùÓ«Iêf¢œ‡HšA4-à¹S¢tñ,”¯ÀUÆ-4µþ’3£òú_JGiꓨ…«bJ Ë#FÀn·bd‘ï![‚pzÔÔ¢RÏò-|FTc+bW^]Hø¨µ¹ë»‚Ž €È 1v'K8šxô¨–°Ç3 êñ ¦e’³ˆÆæ#¤¦í²VÒªgùB8&OúN&™)@TèÇ‚L‡§â í·Â*!©-|¦×E>ÞF××Úq! öˆ]·e·cö«š _ɦ}ŠÎ´Ó²8žqÔ#ÿ:ìáÆv=<­ỈÐ9¯£Ü¤™l~‚·öTúàG  †â¾<µP€„´s3Ol‡.±gåä£](¹Á¥D ìýis§Õ @rüî½ï."NQÐ!p(¨sË1Á'ÐÝg–³è÷­ ì|2YLûSD¡-f0õ‚‘íaÐXW´$ ¹'ùˆ9³}ÀbtRT\D‹‘·'pëñÅÖ1ªÚ`Jy2ž}ì¯É™¤"¤iÍálÞ;8­PÒC‰È'BñÈ ¼/'æž2ñU`t'I„!0NÒ¡ÈQõ’[ñÛg×ož=/Y8ãN4ž 'ñà[¢Ì8DçVã ž§èkå¢Ëë4 Íã8Ð9zðÎQ&Æu¤ 5Näp. Ï´\åº+…DÐ×p;ƒñØŽÈÃÒ&Ô ‘âõ³ÆjþÀ¦(NÃýãga‹h$ÇzžÊý˜dûïž½%tzñîÏ„«N «F'玚AÎש2ì9#•^/¨Ô™ :ÓÈö=J\/FN°Wès(gM× µ¯‘gA Á¼V¨ž@é[‰V|ÕO£òÚ¿›Æ_”ˆ’üïJC=ÃZÖË òPs+X°b…ò3Nt­$OÞxSfÝͽK×yr€?zƒîÉy·Û–¥'y£óá§mP¿æÆïF_•Ó»þjâL<ÇÔ6Ê5M±3^c°cc"÷ôr¦*êhþ?èÙ× ÞƒzóÝ´Q+ø‘(¸ éè”3©´ßG£íìÂÊzB¯ÿѨpܰb?ëøÉ‰F½z8êõêMt0­_5…Œ´Õ2:‰ô‘‚’ªáÕ†Ö àR °QA½B®Éb“œÀ.›Ç{·jÅ"QV9dna{GÀí\qw6(ÖÆfS˜VãïW)±*r¥DÈØOq‡1Â$]¹Ñ‡#“1h~¸’ç¿xÀìžq<Ã竵¤Á_\ÌæG•Ήm%&Ô ¦Tó=k4v,8²žn¥œÄ]¾Ú¢tk! u²‚-#ò*µ&o¿»"LÏ("íJj„d§ÃõϱËÃÞ %Åá£öúrr ÿõè_=þÉí¾œ ù‘ú©Šš¡X»Šx<£¾0Co¯{®G)~°Ì~@ûŠ™ˆ#œ(Ž.ÓÏØžŒtBçÀA±#„'C݆Žøäà-/¢o½±T¯}þWOýõåd Ç²þn}cÉ6Ð$÷1}#?Ñ-ÞèùNáC…Ý€|acôD§ ÂyâÙOþ­k¡´¶ºE/ß"¿ÿr²©Y?ß S2Wh7È·ã<ÏíÍ-‡ù–”±«BÓU ûžæ~99±Žûëõ­ß#¾¯ow¾0½ -/Š#žoœf¯€)8Ìób¾†3§­oT@^nEy\$“æ·)5tĨeý›š°|ݺ1Z:eÊëÌ»Ðö§¢½lã-ß<™SžæÒ÷ö¿gæ…N#åLO½0O”Š‡Ì Î!sv^vÈœ‡L¯sv2<3OšÝ§h´hèˆÁƒb¾ìÏ—ýù²?_öçË}œ/Ãç˰¿Y‰tNº½{Ðd”Ö}§Ì4q÷GÌþˆÙ1û#fÄÔ:bøÙôéˬpÊ2«ïîðW(&’׿ä‡å…oø™P·—òÝïu…0?™·9Nœ ˆ*ù¨óé%ç…õsiuRv8 îÔo²tÖuû{ºÁJª6Ú°’öˬ¤†Y2c*íž•ÙJ»›m¥'›ÎYçml¥Škmi+=©.fôOºÃ¢˜‹®²•î.\èT¿ ‹27¼Ç@oº{ÉiÚ…›gº±Ò¿»tòï ê6¼ýÎy8lv#Ðÿáý*S¯dÎÞ‡^gØëŸ6»_#ÌÏýX÷aÛs©×عÔ/žKWs¼³Å‘‘J i/}í2™.sN.¼ÿÙãÂwÈ“Ôó”ã•qùçF`s.Q¼dÇN•S9¤þòó¿ò“øåçÿÊ_¶æ¾)p)š#7`,.wï(ý/È«“¢xln˜6X„ⓤzKKÜ¡ç#Œ$!Ä9„ÓŠÃèÈÀ’[ºõ 8e}lƒ( GÉ(Jæ©·tµ~KX{Ç&Fq ›Ê]K÷@^ß‹‚Óñ¶^râÙªœÇÙ²YŒ¢ß_o88éŸ*¡îú‰Åf`J_(̱i·ÀRß¿.Ä£|Å}{ùU#û—ä‚$D^Ü0O™Û×&xä[‰³Tn'#‘ÅoílÄ…§ˆ<÷Õ'8R!.åÆ{Onl¯Bñ…²¶ý'ÀÜ),Úêÿ¶ëd€ÜYÔ ÆmÀ£á“eý¾êR­o³äK¯ evJ÷±q…Z »® kGMvZብ¦[¡´Á.ÓUV(SÖöÛVHÙŸ¥ÊWIÞWòIýä‰ú"ïŸ`*v £ÂÔënbÊìÝÂÂQ82™\%sÝÆpz×cï«›uåš¿ÈùÔLý~&|`²%k&4E2£ <ðá'OÐÂjÓ~UWÃLt$:”ÚnÃÚZrÅe–qÈN ´ÌáìQp#Ž8²ˆfD³…ÏÔôuJ«M;ÀÈxúÆÚÓív†¡Ã0=tµV³Ó]2£­UõŒs ¡ÏvHµµY€ø1 d$3–Z¯O”uÉ{›‰áÓ;†±L# 'Ý.Sv ,'°¢ Å•4à˜hš‘Á\fœ+…ÿ–Âa§©_™PK%IŒ4´¥’«yt>ªjDˆÒiÇAÛ³Ô´ÿJð%ôPˆa£Y)F“ª(†®#do8¯÷¾š$¯ü›€Ü ¥ða}ƒø tP›6ß^¤`ë0XQ²$  ¼^•𞬠<.9ƒ˜ÏýÏ)¿.;}F,S ŽÅ)¡Vò´¬œ>I0 ÔïÔ}˜Rº¶R/Š^@I‹`ØŒê±,å± ¹N%"ê”@`ES¥'ÍX{c|‘,bólɽ48Zš¨ÌRðkW¦ÊÀÁcàƒ¤ „)œ¹xÖÅ–×ävû#¢E¶a¢ã™ÀU?§€ÎÇ!¡×âÐÛÊjN.,£F‘ãõáøì§·Txòc<ä(«èøf¤&Ú¹ÿhyµ‘¶vú ‰8FLàïšW¾2pìÆ€ìTN‘ ß1„GžQ€‹ÌéR%Xçtã5À s @6uw•úK—ßô;…Ûö~ç¼ôr`¨fãÎÑ‹ý“/_™<™ºl®8îuáý.ýÕí¾æ¿@[ìõŸ?{þìÅËÎ-]ÜTfJ¢Nêè9·OèŽz4˜—yrøoÛIqò^¥\›Ý¹vq~úëEïâÑi°«(> ÍVÅ`k=4£T1Òô3.%ˆgÌ .Z”¯„Xnà/Ai#õ+H!f\û¤?á׳-:)‹f’iU^5ÛÝëf»ûj‹î„ï4É»fSq?éË míófwÕPw÷„y_ʽmoõÿϪò³°3ŒÝÚmEÚa>†-ʼœá—!à or0N">1¤äË~1Ào¼‰Îv–9 ²Iïè=}|HèF–_~þ—Bž_~þ/P3å‡ÂLSwIÑ•DAõ¤`d#+KzíÇ9åŸAÈì0Ó¼ãnŸóÝq'(ºr®êníŸ0–‹· †áx Î9(42W¦S €Â$µHdÇc^*!Ç÷?3Y‰ƒ´%Oè{ =mþŒ'ÏÓHFm a¬„„ñn†²Òð3 vz$•:ÒTñ2¹LbœT?„9KŸ­ó¤‘6¥>ùƒèÒû5:ãÐ §všƒIÝUeYK“è¨ðgËŽ¹ô[ñ¨ ØžôN»½³ó³O/×Öy+UâëÊŠh^“³>ˆåm:÷.7"1+‹#gÁº ¶é8Eæ*5J—D|›åU°Z~k|fv,ƒz‘Ù…p&Fϱâ,U–iåÛEô-%—bŒ¶ÑÑW(l8P‡â‰u3 Y¿·SzÀo"mÑLêžœÙx7öF©V£<áRfIdt|À(cvEßüL©['Y†÷¼’wC’`Í ã ÅMðøˆñä`F1¼ü/Ìäq3Œþw ßFž-ÓðŽq@Y—<]}¤R Jƒ¨Ãé‘8gbu‹Ð*BÌ¥S n7LZìë@É«HZï6è÷‘%µ…ƒpñ!^°IH“‹Ïaß[œ~[Ú,ÙÀMŒ ÷-Í¡›Å>™#&blŠ2|@æ XÎffî9ñ;B“®áÊ´a¥t˜ÙæGUïä¬wÖïÏ€Á§8«ÊÀ÷ˆŽ«¯³ªuhàg\ÅÞc®=ÁËy^±ë‚¢ô¼¤-ÏF|K]e#•Eî#0I#’ãæJƒÁ^_,&"fÙÔ´Èéð¤+Lf‚6ÅÜ3Ðnð2` ^¸f£W²Ã ßãKOý%'¹EîqYçX(šË«äýõéšyž ÛŽ%ÞåER{4¿åYšÇõJŒËósmt,PÃr¤P†ªÒ¬1Á‹]7s¦G£O¤J×2¶2sQ” ÐI}:I|t³óà³Î´³bî>ôJ³k™rOz^ý‰Ï7a ¿ x5iî"è<Ã!œ1¦L ä•8U¼ÕÌmJ­ŸQÙ8Z/&^%±ä¥1Ý Šn[t›ì¯ ßm“DñùV˜MˆÙK¹Ž""g– Lr,È…## ÒÌâDjý ‡¼¯9Þ@B+›\XBŒ“ÎãNà ãsáåÀö¸ËÒ¹ÍWÁö a¹—¨Ëª²»¢¬I:±nqKRÂÈô[ƒ¯ 'é¥næå,½üMn ¥I«w÷›92üÄÌZOØ—%¶Ô©‘̬7E0u™ª‚C·²¦ìãvèœ"¯®a".ŒÏÐQܾʓï OT? KhúXÁ-_šçMAÜqÓ²ðÑŒ€À¸ °4µÕD^¾ÇÜ4Ëb9½’-+ñ=ÊG6n¸Ýêó¥.­jîæNd?ÞeQn“;À_3^ë>eUŸ 1 Â:óü[Ö¡¼Ö²´‹”©%iÔr#hòÚ<™Ô׸X”Ã~ï óÊž z¿MåtŒÇªfŒˆÀOJlkùÂh«ÄJ¿Lâ;±¶ÄÇ:Þ à¬ö#'Ë(+}pŽú4‚‚ú•ƈ³²}:µº>O+wÈä®TŒœ4XÓ/  G•G2…&"tÄNq.]Ä|b*Fà Òõ;C€âJ/Cw `$6Åòä°Ç”²~Ý,E·ÅHIÑ™0¶*/Dî[h\‚cLK|ªÞŠÉÙùîsþËp=,ÚoO53Ù'K˜8%@JP©¦Í$BåïeXêh‘hJÌ—ËèP¬{f¯6›±úý^÷´;xœj{W¢ç lnÓŸ}@Á_~þç×pê_5¿?µ?‘qí oÒNï3Ë,÷†4¥ïïÌDíÒÇ{¶R‘C4–æþ·Ã¿|û×çßeÊ ¯‹·1º.F>³Ôd0·-ºWönº¯ÞʧFÆ‚Žõ>à¾Ès§~_uâ?>³ž…Sªü¥®r·˜»-»hÈ͆ïm}Üè†z,×õ1Õ5eó6nRv† «'÷å ´ÛNcæ»Üà~`W®ÄÏ»\á’±R·¼«Í÷Ê|!²îîî¬år‹à¸Ò~ê&u)S·ë•wàaƒÝãY C`×OîcŒ†º­)B¢¹ýÂîË!±Ýâ_p劈^Ö¾°Æ¶T ³×ÃO ‰<¡•Ä3Ÿ†ýÞIoøéE¸æ”M Üûàî®|ÃÏŠËHÊ ´»|–ÚQ¥¡:TòiÝ6ofTQ³™ð¼2|¿Ûžžœ÷Ï@8@s $§Ç‚Úx‡µ—¨Æ©Ä°0¼ UšœÂ©ófP„ux%îUpA8ƒ=ïžtû@wknßQŽz{þV[¬a Ýeœ,ù·nÄ¥ëXIcÍÌ…— !¯{ò—NØ|ƒm°–5“ŽOÖæHaG.^æ§<‡Jÿ™v娒©@ŸYÛ×ÁØYâFTZ.¡F5_]@„îuHØs²¦ÃšÆ§£È´àÏ\”5ÏÔâÃãDyK뎷¦4Rˆñʤ’zö\òg@“@,$K¶Ø?¥7ùåçj£Š-[¥äCMY`…¯äCÒ¨p¥ÚÌ•ÍHe½kúa°T_~óM<ì‚J¬ÃwKYiSÊæ,Ó[Fš˜¬%žš)p¥’kG¶r“4É“o‡yïOa·©LÙ!r.èÆõ ù¸‘ !Þ êiÛ<ÌÈXl6@1 n¿¥ÉÓi×D¦ý¶ü I²—·Ú^¨ ½¦ov<+úâOÌyÈ<²Qi«Ô×»Úì˱#.KKÅ¥K™ë¤dqÚÄ[ù›ÚÄìØ21Ÿ/Ê—aºŒ0´SbËZa³[¿ùðë]`õ¾“îð¯›ÅG%¹ 4œTÚ=µe¢õò9ù¤=Óe©c7ºaî •„§ÀÙ™€ì]öTHç9J$Ã:¼`J¹´0$ÇqØ ”†d & Xs1žÁiÍ)i›,ðž¡:`T^ˆg#H_05ŒÚ‡=T; /Q0VÁˆ÷8j©ª½²h-Ê@®h+ûE~IkÍ‹d4gÕÈ”çéRÒ«*Ó¶ÅÃ|%ø€’°L¤¹‹‹¨!OëÖÜg¨ ð´M'üÔ¥wJð†§¹¼uw ÏcÔOˆÙÕèß«L(+ Gï ¼}Û³§èIÐáû—È’Yʾ ï ÉQ"*0LnÔ„p üÙ=(Hçf®Æ5Ýæ{~ß ÐQñP-Î+áþrÎ9ù¤é~UêáX&œí#¶ låþ™ÕÆÿY=þû~­¿øã‚Jï'^³ÔÇk{N`õŒdŒ“ý“ÍwGÀþ ðº!d)=VŽU¾Ð<×cASòj)÷±Ôyöà+K )Ñ9C•öBqOñ-æ^Š©À%G—ŠqsüН•2/å1 ô¯MCX2išÒvyFÄ…óJº[Òq%Ï„K²wòÝ•¼Eew}Ê“ª“+Y$—¨»rºk]U655 E*®ãV’«ÊœÑGê¤Ò9Ú9—NI}èµKèQ%H㮚«Ö®ú½ÎØSk¬]g¼6<'WlÃ(ÿ¹Æ»mE¡+Jº8Ã5_}m"¡Á[û€ÕðÖMSDéè‹Ù²°¬“V¨§B¯,ßÒg²ú4~jÔ§ÆjÇ$k£Ý-DAµBÔÖéIp2¼ßܯ3˜­×)‡ÝrjÆʬž¿×V,Ãk™\·T%T£5¯÷­‹Ðƒ@œ¦q–.J˜Ü:¨Mþ¤]Väe•¢ n¡ëRGŒ:ÕÚ—dÓßlx??=évO.N?Õ}ËfüZm|XŸi©6.5€hõ‹…¨‹ÎŠ…œ|âb!§¥ÅBΫ ¹X[ Aáªë¨:<ú—šl•„tÝfE…;zÐ2åʆ½Ó“Ý (<+?s¶/Ðl1°´<× V"Ë–gÀd¨í|‘£0Øàtua0®uöWªØu.ëƒ]X£ç¼¨7f±³¿¦EÏtÅlø7þ¨[¿Ü×ð¤fµ¯ëZŸƒÈ{ˆe´>?\¸Ç½óîÑQÍÚ_X:êóAïtp|v:8­YLÛTŒ«Pþ‹ë”mjÖ\ñ/]kSËB0ZáÆBl…`¸À­ Å¿ä47×}+àCÆl¸¶*|3¬[”ënCQ®»´(Sï½Ô}ìu+2Ù~†Éö·c²'9&Ûo€Å>ß³Ø=‹Ý³Ø=‹}¨,¶W‘Å2,vЋ==mBŽ}±g²{&»g²{&û‰˜,’o)síWd®Ã s昫Y½TNz²–“¦µúNÿªÏdûÓ~÷¢qƒðë=‹Ý³Ø=‹Ý³Ø‡ÊbO+²ØÓ ‹ÝJŽtg÷Àb¿Ú³Ø=‹Ý³Ø=‹ýT,6ð}òœ.å¯gkù«Á ÐmP²Ê|Mû.=9öÎ4;í.ØèÉÀt¾‹b;Œy®¦ošž£Jï €â¼wv~aõg§Öéà¤=ìŠe½ÖJk?ÿ¸k?»ào*¯}°bíøß®k_ï0¸rí½Îð$¿vµ§jí9Û¿Ü÷ápÕÚûek§^‚Äz¬j˜ N/†ÖÅɀС¿#@úë{V¤Ÿzæb@rºÛFBf›«/E““$§Ý~@Ò#,Ù$ë/ãW‚dÐéõ‹ ÉâHNÖÚ’“²…Ÿ¦ ?»èŸ!.Ì6‘?˜>}’¯®ò WQ!ô+¹Pø—ü°/]Œ³ž¾üLŸAÜ^Êw¿GçZ„Ù¥ŸÌÛœ"7ðé@Ƀŗ—Ö«»\QYOšŠ‹ÇéNŒ‚»lÕàg;8Ö¯ðà¯Ö!…Ìf\åkxÚŒr^ú”`ç,4•æÀ¤"{óLêÓ\ÌÀ€9ì#¬Ñîb|™eSÅ÷] aLŒJûq¸ºÌó‰é9(Š òyhÉôœÞR•Û·œ,Uò¸žGé(ö}kÈÌK&ÎÅt«Hw@•¯9]Î’÷^gjç9ä¿‹1< %ÖE8ä^%eáLòUKcçT–þÃŽ(~ߣ”L9†©•".2aR¢êØŽ>è9e‚6UUiJIà~;Ý@@Li¢rLld\…ð’¤_ Œ]€Þ4,‹2ÑgA>”¤L«í®Œøÿ^íSÉ…°Ä† ,^ÜZ¾àì¼o#ùr‘ï«!´*'œ/àObP«’L[Ñc+…óƒr«êŠÉä%Fuš-§ùö³$Ò 46rÊ?y6Ðw¹„A‰ÌxA™ ª^Lç}H)ÈP9—IrŽjðj™c⸤:F˜PÒa úúS‰6ˆZ+V¼~×Ç8·€3UQbÌþpÂ+|¤:W)¢x/Ó±·+âúqIûºQKEÖ±ÃYÄñreg‰TÆ'à¢>“±¸…#S×í¤H}”«¼B^ñóá°?<=9}xùwŒÄá/uøöCI·ó $1¦ÁÛ à,KJ.£:órNÙ§À Çp~àÙ@<–¹4RN9î,''äH™pOŸBB%¸Ôi‡¡KÂXÓr—ùQ6ó€Üš*ñÖp±@Á:W:W'QQý][ʶT‡âk¬þS¯ô„¬H›a*sÏ'=‘áPUp6ÆB¡a”O®·ó c®V’UË•œ—“ ùâvSž~Îl†ÏA£ˆ¹ð®ž6â¢cÙBÒ†ê'£ÓÁHPö ºã`±4“è§°* ªäC¶g–– 6¬ü„ªêŸ\þеLT²2yJ¥5Èu¢¯´Ï @0Mœ>ÙÆ°bW½Mqá¶1'2Më‰%ýëk,»q`þþ÷ò1e°;<:ú¢fV›§oÑ6‹™"çØƒdƒqh[·Aø·ðßÁ´#qJ)HÙÜšô†K†l­žéz; 7×Ú–óä\ßéciäÈÌŠ»åõ(ˆ“0"F$1Wˆtxé¦:€ÊX³¥e¹Ô½Ì‡ùRåwz¼Ý8V¶4JJº 4׎¡ÌjiæÑŠ™ ¢v{´¶G£ œ¤L÷'áÔMyåçÄõ‰Ìº°C¤ö˜×ÓÁíBYSez—ë(JDt”jåúÓéÉùÙðbpò«Êéÿ. #æÖ/?ÿë&ý¡Ê8òÂ’MH+÷®‡5 ¤}O¹Œ•º¢OSÍÄgç¨\dž¸ˆÊjDh(¿åD§FðÙ—)RW ±‚dn‡ù&mj;⬦Jn uDëü»<c€]8î£J=Æ“¡M¥µ2›êÂSLЏÍ2µø&Âà¢vrÑžþZi€X-¿Si]Eæ{ÌW/k\̃(&>+<+ÏGBÖ´…C`ì%RhB ­ëi¾m•þÏ72œËd´œ¿‘äÌÿns¥/ü‰ÝÚ|ÀØÞ-V•®Tº×(TÛÂbÔ¨mÔyÝX%6# P(%âä숦©9ÖØ¢X,ˆLq& Hpã˜'åÒ¼²%¼y"Frb´¿‡0/“Fo•$v…_fwì±ê·C2Ñ>÷P!MäªÜË-z¨dY9óSøï[ta$ /G†>×PšÏþw®Q«¨ÕFÔ®Z¹¹ÖpçºHøßõ¿Šc7<èECým‡•²¢fÙàÕÄÈ0}KZ®)yâ½%_³K¡Xß÷ëô+r•p—º š•…•À9éÉ"ìÕù»ÙgKçx³4ƒœu„)UerâN¶øÓÍ÷ç½á ;èýªj½¼de>ÆvX?Ks¨{.ªUx"nC!œl×:N¢ðz´½c ´c™4õñ~™… î;óø$ò"äŽ,¨×0Gk¶»Á}qµfòÀÛá Ô¸ß ÐÙøW}RÁز0þk›ãÖB}þm«Æ?U$ÞaÔ«ô‚ªÆ¨a¹YV]­¬(çTùj Ö“µV*3¥pkø^(<ÉÚ炪Í% äîÇlYrdñPªÓú$¤C õhy&-Á0½ BÜÈ,Å¡Põ)lPÜùâ]š©Õ}†[õ°^Í iÎÆ¢`'øKà„QŒ.䘟x5\Ö5û”±g#-2Ý3@9™’9á/L?¼Ý¨Ò ˜'=Ô…9àWµ¥”8­˜µÆ¤¸†ŠVà×00—h¤º>;õilî7AìŽIC†S× „ôòÆU×1 ÂÉÐ6eëoq]zž+¡rúÚu@ÏdIyÝT1ŒR"©ÕcB4 æ®TÈå5ÏX,¸ö$ÞáÄKFöÔi£ÛY¯{2<ö.~U†É×T‰¥,,ižy ‚Ýû …ÚŸ.¬&oÙ§”t§k˜ÌAÞQºÑQìNÕ¡ãK;v*^â$¡2ôMZ ÷•Säy•ºþVéú÷Šû^q¯†ï†U+ó +âU–ªFB¹™¹¯ŠUò uÛŠ„˜“Í~ À!fg®_ìÿyãžfù 7tc£°Õ—™#CùùŸØ’¼'ˆù:”K¥Q5 C:{r•ß'ìL™¶ÅcGώψÍ{ïôX|÷ü×ÄáM³û÷@ÈÉ8 ÇÐN˜߿ΔËùãfŠîQU鬽ùž¬É“@*jÞwê³.«æ0r}c"½dÚôÃÀéx&£G1µ½°Çè:„Jn±Ž¡XIî6(Nƒ²BBDsÃõÝ®£(^e5°}¶[NB‚4욢cR ä t„ŽßâPrRºÿÚ÷›Ì…ê”#SáSö!Ør¤4ßÄ Üp tÐ_I6?Î N½P¹ÊÝ€¨†Ñ–’dÊÈŒÈ \€ƒÞ,u)J¢ó/ÿçÿR <„L">¬&o¿»‚£xüè,:’1$p’Q6(à¥7hÓ"ºùåçEcÛœ±é—Ÿÿ‹¦E4¢:ÆÖÔ–q”òÙÆ(á™\FKÑËS*¹¾ “)En/‘Èßtr;=üávg €í¡ü¢-øÈ7ÊôíMp'<`^‚;šÄ(2Gé¶û''Ülÿ¨àA ɼQ ‚ž3ƳˆBá:ˆ\ÄZ¬ÃPU‘AûC¾rg}”Vhu;]¸ãb6‚HžpTP˵j‹˜ÐÒÛPìA«ünásêMò‘ÄÇfG­tU¨éÃu^XÂ<E4@NN¦…tx8è·aÏŽr `+!(ÕðÈuý²¡;u‘TÔfÐ=×’•7Á0 Ǭ-סì0mbGÚ¢¯z•ñÈzFîV›N•PfSA³tàÔ%sjÄXˆ÷µÇdÐÖ›'•U&ål›­eÝÞùÅÙàì¢Wf-Öºþ>GŸÞPG¤»BºaÍ/v1”Dåš:ÍŠ=æ0Ä™…ã°Ûí:v{ý#2K`n?ÂDi} }‚ ^Ò& _ÒÖй(º/}K:ÉêS^½º¡vn2ÈZsëfã†/S`îp.¡„Ä>"XN^£ëT°OKGŽ;G‡'’ ¯„Ámt<¼ˆÀtŽ`b‚V¿zGÆ*pœ²1‚ILüˆVM{gÞ ×5ZŠ;â š;G.J,‘ìT.|Cg g$³­PL#ü”ZB‹%þ™ q_‘c|u#Öö¢€ààÆiÚudø–É Õ¼f@{é­|¥›øm)˜NÅíD_í>;NB´££;FˆR!@XQÄsC Ô|ºF‰–QŒ’ùoIƒ`; ’ã9å!”ež(@$v$à‰ýÿL&¨kg›úÊW'¢8ÛVñGL‘â:,+*åß^âzЉ 7MûÌì>8¢LÐJkÎ…jäxFg3[w@І˜-CÝè¶Û7³$I?Ø”@)E\æA¯™æŒ˜zVÉõ ä%õa|ðÝ«×ú~º#JÐã·pK¥)¥1ê„"Ðû)¡ ®:@·8;ŽAƒ$íÑãÏN?8÷,Λ FÙ}që™zêFÒŠJ? ûJÌ6w˜mæª#©­áÑ|ˆÓAñܹË×lG’™k¾¤®Q†ÈA'?yôš–1š“Lñ’‹–%âq‡AÚ ¿¸R[5mÛT¤EnƒKÌ;Îó ü8xŠ˜ S ì"›B<2ˆ¹=΄°ÈJö2±ÆÚ€læxÉi[¡aAÓ¤7t¤I¯ƒsŽ,½&{ ‘=ÁL"‰VNñv=Yd£„Ôê(¾J&ñýÍñF9ŽIK™ó¦-$–2覶ªºÂ-°f7k|Eòš1ÅLpü q’Ô­REHdÌÄMº¶ú-kÀBUJ£RG’‹ ”4¨j"|ðØEtɪ% °PÕ¦ý“ŽdÊ‘BâÏm?˜[Ϋ堄"Ãkd¹'õõ’-|FÖÀC¤i|íÞÁ¿þHó;jiÎ@¾‚j&æ÷Æäç©%Ö1Œ×ÍꎴUÑ#!“/·xi63 ¼ö<ÙBЩq¦€Ùo€’'€r¸H`2¥¾IÀ¦¹ðäÏŒÎ\¥Úk3|\ ¨Aúò"‰u´t(ø‘‘6<»“+îBÀ¤é[3hô»“ þâGþ‹Ù<]¡ï7ZxleÅæÊ4U(|âNÉœi‹¯(u¶¦Gy«,yì« 'všÂƒ3ÕÓõMMYüâR¿YŸoxÎÁÓˆú¹$ ›m¸åŸ\í%§6Α ’²O?“îxS—¨äжàÕ_ž_œNùKãD×B)-)Õ„ñ[¦X5óO&MJ'ž¡c5O g­Í“Ê ÅºÚ>'K\Bæ(Ìïÿ wâ2L1—ƒ¢|zj±‡€J€B.Ú-ní ˜¨®;¦W&/ž2h!vœÏK âkC–Y-ÅHH¾tAÚ'{Oš•R°½˜´¾4Q¬Y­ÑC{ ªßñYöŽ wJ#ýÌ##˜xfú>:VP@¬ãŒ)B¢Øµ•ùãXFü!R„Â×.¬ˆX‰¯¥ÍrÙ†þ ~­î$ºpÒ9螌)ì(U„ Lä­o7–Æ8dÃÚ+.lIÐLS†°¸!(Kk`ퟕX¤ÊÈ0FÞ(c!úh$‰©‡…IïbnÉÖ:2󿄦ŽË’ ßâô”¢$«Äµ•î†öÎ dý@®‰¥(Z;I—(y™j΀€³ AÇ(”Ù|KãS¯H‘íDÈiªJ3 ¹Ze}›Ä@[K‘tCÃÉ`‘”û’n7ÂJI6ßˉ$.!^Êšôo‰]øïjŽô0ƒxòU¦q{Œ"õçg¹á6·x^»Å‹0Æ«|‹ã2W~ÞËÉÌu«¡Ô;|æ!.ÉŒÝæ*<|¯¿®\áEæ $OnÔ3^÷àéK­¼>ˆé0m=ˆ©<fÝÔD^í´Eʆ°v6™G€ç÷‰øýíÿúÕû^cÛ»í<ªÃ1 |ú &ÂLcø¾ËTXV\ÏvÁöAMllí/þü¼9lßvÓÁƒ˜E£Ø¾ËDÆö]¦rߨ>üxØþöÙõÃÀöþƒ˜ÅÛÕØþÝ«×ÛÆ, ¶79‘ëQ޹þëáìc{\ÏO„¿ª‹ë擽Rшº¥yYR×?B5WOÃs‰ѽ+L­­Þíáôõm`ÙTŒ Ñi7”â0ãÙR† ˆŽõš]÷ËÆbgtž¼¾zûªeýµeý­eýíáVÒõ· _¡‚GʅЖne±;íH·_Š’GìÔÅÊìRŠsZÌ–Êûö§©#Fòµ³¤Ó•²æÍ‰ÍÈÁéÞW…"J<Ž?`snDîÒ\ŒvS*ãú1&¤Ÿ¡tÛ)Ÿ"ÞfçH·ú±@WmeÅ«néäª+ÐÐÒ¾«÷ÞUBkANþäB¢‚¯á ¹ôý§Tò\‰†pÑ}î=d Ãi˜ÐE¬\S´ eòÃFìz€·Ò² ƒÞ^9…Ü—˜PŠÊ–ì·‡H@ÅÉÔ¦ äu¶Œêþ´Ê'X…»@õJn‡RË1 ,^†(—buâ}9{ê¤$ìJ!W =ѽ¥ Îa·}Úý÷, ‰4`qæ%X}wø E¤O@Ù°£bùYvþ0®'4Z+?{ól ï|`š`Sô€Z>_C)À•_Ïà4Ô¥7yQqYdv½žGeØÏ—sX §Ž‰g¡0vËž1ñOÈqHn~‹CÔÔ…žú yøyÍäïÙ!Ð @A.¤2(ykq}*›Ë»¨•’'.¤¡0‚ké-†“ñb'϶ëå‚ùY˼ÃèQé–sãŠ[ ïy'2m:©¢Ä Y—¨°DÏx÷(ƒxª\–cj ´×*0&ƒ¶‡©›\¢/Ÿ)®*#BŽZV”pÑ>ºŽ•9vó»Ù7¨֨üÔõ[»€W[äw4±Ç®çÆLµÍ·~7h›îˆvÞ}F_õÁ‘‹|2€Èô=Ý»MñÚ-õ–cÿ²î[씨ÜsL1y¹l:f÷m…w’v¤}’LM‡<Ñ%³Š{ÒÕ6e¡q y6Ò‰-Ýð„v‹È!F€”ÎýÕ=uCSª0}>Ôª¦áêÄÒ_Ñ£ŒÁ*R1´Wdå?“ÒzÝqM #Š!¨SŠÀÉá’—’¿=á$»ú(!  ¥$.¥izVQ0RžÈe][E²2ïÝã8åÅM(^AºÏi'JôÕ#· ¿-…%Ã÷oÕHŠívDXˆŒ¦ý‚]ʬÊ« ú£7+ÉÒá,õyŠÒüub¾H½4e Z³?;Rl¢¤} *˜š3ÂHz"s K‰¥™-OŠm0‰c‚ÑŸ¯´ÑÿàW„“¬!·Æ?Dfr0|_Ò5âkªkI!7#•¼B!H ¤ÙŸÕVX¢<—w£l DFÈš*dzÇWïàéèéSõ{øR[>û£K ŽÑJât¸9JÞè$ÕlA†ºÓ¶ ‘Kr8D² :C¨g8˜Ç²ö–+OB8áQN‘!׳—t±S¸‹­åÄ8 ˜©8NÊxÖÉ<¢ˆ>¥Ã«:éÇÒˆÃ/á̽;—E²S´ðmZ VÕ7Òj39CQ|6«:¹XN~…0´w)ÛMùWt’c¹²×2ÝœA‚r9¯-ã£T€›ÂVÄBVSœ Ù- Fíè´çl )‡qⓦ•Ïr”F>/sÝ*Ñ3·½jÕ){ RW- N‚¤€I‚½ÒèÂ5⊉¼«jÆÔ07«L † ¯± ¥/Um\À§©íËâuu)ñ{ ©êANÆŒ@Ð[`½N¨–:]Ò©>±ç 1Ø¡`ªÊ÷šSÒJ‹’H¤Ï$z:K—?AïDÝÂvœëB+›áïkªºÊg2J$IȻф€¼l“gdÕ#]<¹€Ä¡Kîzœi_Æœû¨òà8†)Èó$9R@ŠTè`È"®¶÷ØÆ\•È—F¬TžxhßfuÈM >´)ÆÎlt”n’2éh°õJY7AEHuëÞi·Ýïvex;¹/ÓÒcàšì§ms[r§d“pFä¬âo"•m…"JXp'KŠ„¤/“(H„vDåæIõ<;µ{H{j­²ZŠ 2‹tKÝY¿"\h›X]bàkûj©·> nà WzÍÒ²Úª©ñQÿÎtq« _²¼;A1›­IeøY¬V†€C\†#æKµFúy#`˜Hî£Ã–%²DµØ'½eâÉ–ÑA+;7ô’™4è¢e\çOˆu>>…4R•‹¢`ìÊzßr_óÀüÛS‰T ¤|œ\•õ[~S[ÌFIc«|¦2*ÌÈ€iò¹ qC—j’Êø”èÔbØ,¢3ÏÅ3s˜õ¼Så¼ÇßOøê}'Ù¤fwÓ,=‘EÖZáðàéÔ FÅ<õíêyÉ è¶ác ºq‚…:±ó‡‚<+dÉG‘(õ7 ¸’ô5ž-瘇ÂÌ·¡,£|˜Ë-ëXß’H§N5¶ÿÕ’¹;ï »³J„臙íaÛ0·)ÁÄ(Û Aš‚æ´  â†o‡ÉzÛ 54óHú»¬KçW†ý´ª¬g&޹À8Xÿ Æez!%¼âF¿óâ/®7+\Óz¤F[4{»|Ãâø4òåå$¯á¬œmÑÝÛ¢MÙõ:ªN ÿÃɤ?€kxÛèÿ¨MülžñÓdËÈD€ Qá”Â%áfP]#…Ê5‚¼.˜¤©¦¶©þ«EŽhlëǸyÀ’;ÓÈx‘2 ö5‰Ü¬µ@y˜úe¤qÄb8]ˆ2¿lÊ“ñ5唤ªôälŒ¸‚ËzyËGIÊ@¸#;Ú½»»{8´ “y@´‹ º¶W¦ß]0Á¢Ds¼-¸|ö D¤8”õtp§j-ÞrQ¦7YêSåUñ—·,饺`“i’¢<k¢Ìs¤„-‘}·dçðÚ( jR°‘ÐJ”Ìjb^anŽÆñúC2puäÞØÞ§$Ûãc†'bÎC#ÑR9Rnr3¤šßÚaPˈZñ´=uiµj&ÆÊ¿ bCeHÍéa?¤ø­T ø"’ôɦ/ù¥µg¥ÕÈ´~hö½2þ‘‹¹;œ•3ÍuMÕÉ0K¦ tLœê“4fŠÔh’Gñµ¼LG“£t£:Ñó'†ð§þn[kÐwŒ~þºR“ÏKØý?5jòyÃåX˜éÍ»õÍ,2ù^>áŠ2±_}ógë«woÔ•‘5@„¤2:Ù¢`ªt‰²(ÎÑ›OJeÀ° ª/¨î,ýµg‘üÚp û3G¨y Ö-èŽc3[)—¤Á ’d¡oe2UK´b®XÅ€›ÎÐO-/Áôiêbζ"ß^D3t6£‹³¯ ×~·{¾ ý¤‘¢Åäg§+sŸÖJ}vZ7óÙi1)Y!ˆ{]ØíéÖ)ª¨9HâüÁÓŇé±Ä¹FB‚amÍM’Én¡ðµÀºe"=õ2—çÁÓŸ€Xšhs³ÓN=\%`Œ›ÉJÔ4\ûȰ-Œç•þټͤ8Ûƒ·t%S$‹f’&6 aCäx” †;‡ËE3©-…îo¿Ó{ôŽæñâaƒ—b#©úd©æƒzáO¤Ÿ¿Iñá qùå—´è47"ÕSn§ûð (ýÈùñWïßX½N¯™ÜK{ØšŠš˜(¸)dÁ#öx( þUhp¾ˆÇÎä¡€TÏëøQqî-KòŒŠG»ƒóó“þ°¤vä÷ߟ“Ì{µ H^è’Hë*÷m45¾ã(7XY’lw·bdE‚¨î¼1°KJ’%ß@N¢I'§Gœ9DÄ69 9n4N"íͮ턭lO-éªÇ±6äàUÛ5éìÏÇsðÃô¾M9Á8A×ɶ,ÈòôÿPKRSbb¿\RƒPKZGŸ= layout-cachecd`d(P`d`àd``Ñe€2 aŒ0Æy ÃMH°u008s10Dh00x…6±À¥@ ˆ‡AhÀ1†ÌPí/`æ03B³3µ1<``øÊÄÀ ÀÇÀ #U£s ŒÓŶd…­Ä I6¨šZ˜â>c'ŒqƸbð20H¸í¼a‚2aŒcPKAh‘ñœ$PKZGŸ=ß=<1ó manifest.rdf¥‘±nƒ0Ew¾Ârfü‚YŠdh”¹j¿ÀCPÀù™’ü}]ŠÒ¢UÕÑöÕ¹÷Èùá:ôìÍ8êÐ<{ÎŒ­°îl[ðÉ7ñ?”QîêF=O,¤-©p*øÙûQÌó,æT k!ɲ ö¤ŒC"¦›õú[Úñ2b,·”¨#VÓ`¬_Aáꪱ"š:Šq4v!Zlš®2 ƒñÆK»ãìc~ÅÉ|¯ø³¦'íüòì áä*Sð ­"trø5MþÖú çð}øj"Õã'ôÔõæ.#ÿ*ƒu³•ù15t¥êe™´©Jÿ]µõÌaýâ2zPKZGŸ= styles.xmlí=Û®ã¶vïý Á)ÐÙÖÍ—iöt’&9ÀÌœ43Im‹¶•‘%C’gó E¢¯í§õKÊ«DÉ"%R²­½;`&&©uçââíë??"ã3H³0‰ï&Öt>1@¼I‚0ÞÝM~þø¹šüùõ?|l·á¼ ’ÍéâÜÌò§dlg¯HåÝ䔯¯? ³W±Ù«|ó*9‚˜5zÅC¿ÂŸ"%¸³®Í10ß:yׯ¶ÒÖ¿ïþe Ì·Rÿ¡kc yÊ7ß&]?f‘¹MÌMr8úyXÃâ1 ãOw“}ž_ÍfÓg𤻙µ^¯g¸¶@xSÀOi„¡‚Í D},›YSkÆ` ÷»â‡`y”âÓá¤Yãçþ™T³Ï»Îñy'`Ífï§uWÅëÝÅë|ÛƒŸï2YÍÞÁJü×»·¥.¤‡®ßB°VmÒðØ™LÍ·O’¤@5 ŠÑµçswF~sÐRð‡4ÌAÊo¤à?ÚOMLƒpÖ B˜à3RS"¢…={³“4/ÙvwP;va^ûü‰Í Õ2Ð] gM *ºù9ªø9ÿ×3 T¨t–9yÓ7>þ4Cu&rqЈ1.¯òÔ3¤/Ð6§Í ÁÙ3ÂDÄíÉW¡ °gÐÝä³$ØÚi°Â“×Ìÿoèû·þ˜ØDÙ믉ÝÅù¸{7ùû釧Ã}Y);„Ñ_;1¸^Ža¾–óÙOCB6W‡,4úG3#-g]1#ÐÒÍGŸ|§¡RÓÖþ›ä”† 5Þƒ‡&Nü£L²æ€HA…tkî@ ÒÔ! @wC¼é›qÙ'²‡0ËH³‡%­A)¶á#0ÒDÈ’4ÆâÝä'°;E~zI„߆p¬Äöi¼KâDˆt îòœüüîÿr2Þ~ÿñº9vMÀ-¼}“$Ÿ:h .úCè⑈Ÿ ªÇBÌkpøšÒþÄ^«»È³ºˆÁ  «B–vE½pÚ¥ÏÇ«¢;Su™öÆí~ÜèliÕU¾ßñóW×›šèêGºHî)ËÁ¡¿N7_]”ºÓçg¢Š–“ùôë¯Ñ4Æ‘~BÙøÁñ{Zö›=ÿm9!5A˜#ÿɬB¬šN«á éÒ28ɳ¥(Ó³?ÍñZãà¢b‹ÿTÚ„qâ,Ì!W¬ùü+®QsïÐ×Yï÷I )!¬ŸQ2÷>dOã¨h5ˆ« «J]¢ïвFº`'¹£üÄ| 'NÓŠ4ÉiX<íJ**¯Ž•'ÃÊ»V V‹[aÕl7«å­°ZɰZÝ «µ «õ°r權ʫc%sWέü•c˰²o…•#ÃʹV2ßîÜÊ·;2ßîÜÊ·;2ßîÜÊ·;2ßîÜÊ·;2ßîÜÊ·;2ßîÜÊ·»2ßîÞÊ·»2ßîÞÊ·»2ßîÞÊ·»2ßîÞÊ·»2ßîÞÊ·»2ßî^Ö·oÃ(2ÿÁ)¹ŸU¤õ-üƒáF~ Z£fk)Øä 8É3 ΈùŸfâZ¬I UÚUX[{.ê®d4ë¡Ã{N„4‡ „Ås"¤9j!„,Ÿ!Í!dõœiŽ!ëgDˆ`ªŒ ©Ï”ÇMHóhD±ž!’a¤>7!Íq!ÄyN„4‡†„÷9"Ù뉂q"Ùë¹…q"Ùëéˆq"ÙëŒq"ÙëIQ"H”`Bêy’q"Ùë©•q"ÙëÙ˜q"Ùë œq"Ùë9Ÿq"Ùëi¢Qò]ãœÂ%vˆA F¥^™ ËrÜ®Ua9‚hE±Y$[ÿѳlݲKýã>ÜL,ýmÓäÒ<¥dïɃ™l·ÈÍGò™•U|¿Zÿt^÷^ -fvô7a¼3÷Iþ‘ĹhË•AFØl`ÑήýžÁ6õJArÂ|o’s[?ʸ 8G?õ1¯xN‘*oú§£æ”Ȇ —ì]&iÛ<=‰±MFYøÄÔ²9.‹üxwòw°ĸ`“œâ<…Zñó‡ %¨ég¡³Ö”7´V ±ÐžXESèE=µç}U°×’eëébR'RelÙ?÷ Æym3òƒ¤&Æån'P²‡°@¿£NO1Î4£`õÝdéQ¾ºM防˜¼'q×¶WšDU/›¥=h('7ÁF׾ꅺešr¾oïrjˆ¿[hS¹+ïŠÊë` ®\)8øaŒÏ0 ³Ï€Ž§l_éaä°çŠ"Àë9ƒF6Óa…‚.jGäÑ"Qï›h¥úqXR3¿OÍ<Ù|vô!ójû0ÿÁâhFøi0z&¼ÈÏ2ˆ4”‰Üj8“8Û`Ý`%Ê-¨~„_C!Ì}<1¬ª ‚0øj!5° 8>i6s‚'˜ü,‡òF®ƒ6jõ‘?… †=[¨‘ó<-LÃÝþ¼:±³²û$ÏÑ™,VLüiîbäý´Àð÷S–‡Û'“,UšPAy£JRèm㌙ÏC][ñ wâq;ÏÒs"Õ2+Õ´KF;â=kÈÔ°YCúÈÿ»0ͰD4–%È4«6¤QSQ‰&k²ƒ„_c¾µ^xíüï̺€pÃh³ˆ`Qû©µ „7èþt¾rXö}8¼qxëGþSÖ6ž+x&·ÒôÇâÆNTVWÅ>¨éÎ&£ †¥£5ê¤lJN9Ý"ð”Ö}¬ÝÛÇNçËõºÁÑÂ)KG7[5æ~u†Ã]ól“´5l­*±íÒˆ—=Šû$ Ä*ky_U*I+VÝܶÔWAë·×Qh[®ÐöÚÖq|G8eÂÓ^¦ˆ4œ$z'1àK©"׋±&× 9UžÏWaldIF±W‰2ç¹Åj|™`¡žXôŠè­5#z^3ùµB'´ló‹.¨Çp‚HŒExvÁâ€Æ ¨Õ‘ SØM]‚¼R!H­ÄÒP‚,Vn(Moºš;ÞíDÚ9ÄÔ²cA¢¦¿V¦F,þÁbgm¯‡uù#—³˜/­‘k ºÇ÷aÎÝ8`ÖîÃé>çû¦ê²ÙÃÎ{ÛÔ‚_ž SeÚ‘d…¢ëx½R¯W½ÆkAkÍñºÎÚK'[Ç$º¦,}Ûœ[5¯•nï,½;ÑÓZóVÁ„_«ìje³«m¨’¯+rùªîÌ·¿Þÿ6X7Ñê8ú×§G²Æ9l H£¦ÅkI.à+²øÔŽVî²x%'ü¿è\~+bÖà‡ÆŒ÷0è_âÂrœì|2ε0Sñ^]7 ©¶ZS(-üU¼¯ZS‡ÎÔ¼Ô|¹r^꼊¥„õJ˜.ë´XuQGGçËjH}[’çŠÓçö’¬w*¡ý¸ú߆tÍd#·ô6ŒA³G*À fh7ù-Yáþm ~{ûýý}]HOd!~%À´úÛÛ+á•I%kt¦ËrQ·ä²í,lÙ{[¹£@å<\«ðp­#èV!*±ßÚž|ظ¹ ˆ?8žW ÔVÏ©SÔsÈ÷‘Ò')pCºS¥é‹8ëœïÓä´Û—ûDâÆ“ôºàê¬ÈmÙ»„¿RÙÅþ•!%Ç•øo×çÇ û’ø­£ ó“0W: kè»uSTÓrˆd'@ ¨£ Á¼‡ãÞ'B`Ê¢i?#UÍ;YÈ9hO¿Þ!±Þ;Lêìž¹-:-»¾F`‹ŽtÂlQ€Àhlñ}’ÃnâVC¬ÁõµÂÂ@ߟ¹EÙóÑ[Añ†%@`4õºÂ?ÝÁÀ7HîŸrÑܪ4.qE;“k‚T(¹! ¿þj¶,ö| ­¿„Ö/ ´~ão>í ÄãͱœÙì#,AÜ ´Dæ†HÀè2áK@ó% y¡Í_‰:HvÈQÙ9Eãq—œø­ÌB[s<×yñ¶æXd+ñ¨­!yC{¢0‹led§µÜT1hEÃ\»ž`IRÉ2½¥Ð2-¯ÃÙzo×·*UF…ÆÊÒg+â$ جȬµW±¢?J¶¦®µBÀôšµë­ËtðY°Î ¸±²°Ò­ œ\¹€ÝžvT¼ZÕ7èݦPì?“€Ï"'i\wu験 Øë)`Wñ¦Œ)dÿb×öŠŒee•ãÌBÎøEOÆ{ªŒ_9®œñceäRÎÈeOF.TwZ8t«ù³c¤`g c¤d/J'F._ö–ŽRÁöÆH­ )9½äÍ'﫳•!i̓0)U¼W³qÊzv„[a&Ùܶû4PíÀѺ…—?$^K°¢»ò3äJûý„±6M–|‘\7ÉmÚ®nPÜ…y–«ºµh,á%µ-'GÎEfu—qµj·94tÑÛø½÷&úë=œV(·Þ›¤}ÍÂÅûN;Œ3 §(<>~ˆÃãü2j*|9?¤t²õZUÖKã|Å¢3«?ú×–¹Mçvq/¹‹íü¶ÕýǾWM©n…7[6¤„à ?&Ùç¶tÎA|“œÒ¤D¥ûžänF¤8ØÍhZ)ŽoF+¾ßå¶ã*SVèêCãT:D¹ªÝ¡Øæ-•ÎX6w~•KñÉ&z­äÇ€¢÷½–Œ{Ép0 ²$LBZY’%´Ð—ÐRYBË>4î/!Aú…IH+ý2 „–_$$Èë0 iåu”Ðê‹„ #&!­„Ñ€Z‘5—‹¨¬¿Õýåóÿ§Bâï΄òÅÝ9Z±ü`W'ymk—ª§“u.Âq­9ŸÔåmXï“¿h¿¡{ZÝR]l` ä"jž©ç©gù‹Ï¢«¦¾–,1¯•®B/!›cÆ%ÈD!0£3Æ›»Þc£´Ð^pIzo#aRK…ÂPºWï”ÀÀ\?-CL¿A¦ÇÓUüM[ÎOÆ –çC/&”éºæÙy]¶»DM«Ñ5ßq";Ös snðÙJwš]Ÿ0º ãò_1i8²ŒŠ}ÂÞO%~‡<ÔXõÿ2ÚLl_ëæ–ªÛ8 ßiµê½(ÂצT®DʽO´$Ú4éPy•ƒFº½OÔ™(]§ÓDzº¢¤| ›’ëé²a¿yUg ÿl6«:’§u®t2ôW‹Æ¾ûé&ìnédüÃÓ¶Dœ¤Q+^³DJ,¹¿çÍ)Š@Þú&ýHç…-èDSÒQ}Ô®Çëü"7ßJÒŸ5/†YÒ¬à? ñ+¥*ìh_Ú'f*¹÷×÷X\‡’„3á~B¬=Ág¼KâD°Lip]žS©N¹k0a€ž*'«ÀÔîÊým«ÅíâbI[¢C0…kýáì"ìéÌOÍ&Æ  ¤«J5ËÍ,Çs@Ž+ŸN‡lø‘¹Wôã»Dôˆ(maàÛÕÇý˜¢·®ïáÆ¦â¡Tб¢…·§[ì¾aNØ™õ•]v•‰­òL¬­šµ†Á5wAºùÒ"ÿ˜`µá­¾R =À@eWXz±KùBúDŸHo>XÈ˹þê9î‚FÖÕgÏÏŽHöÒŽ0·`bÚvÛÁ¾‡R}?Þp“êWÆøt8mp´˜­Ð¡±fô÷Y“àm’T=?Ûù¼{õÈÖ àÿ?ͫ˛XE¹í†*vër-{M‘»Lÿ¢CƒqáZhúUA`xgHÇÍ(<„9߉ž„‚¡Dí(ñgĈ!öCY%dzŠ-~•Sú²ƒŒ ÿ€E¬‡jZ“«uÓš¾§]q@eíæ E|ó¯ÎænÞz€¹[ÃL¹”ètˆ™EÂÿ5±“Áo—e;ÿXO)œk`Wÿž´<›]JÇyÍ ž e`pÅë©p G÷Þþë-˜ÌK£å }Þ­Ü ¿…bi6I'Vç¬x¨$ž]ÂyÄP:…p¡ã,Oâ@ºÌ {Øø'Ýä4]Ó3’TXÖti;‹A]ÿZâú¹UÏô³;Ðü'Õ[pÚT‡t{—~W^óâ<©£÷Ùukù‰ß 2” ÐeÌÄž.½òaPÎLì©MŸx>7“ Y¾ âLm—.ôPwÖ ÓåÂýÙhÙã¡c°°‰?SÃט‡$€üÙžÊw!†òß•m#_ ïÌð°–²mZ #9©™Ôñ~. N–é/NEÌì´Ý†PÓ§_ºEKyuF^ä =Ö£dY‘k ­çИ¹Û„)©#¶v^·GË'Zî8ÑòƉÖbœh-ljÖjœh­Ç‰V¹öjxU«xdË%jñZ¨àR»rÔšð½q_¦[Xêƒ þÉÇn²¥×ÊX4ÀPDCÀb§NÁ9ò ¤Ù7! –6ïŠÿ]äLõõèvFA7{—îzt»£ Û[Ï××¥ÛÝËÕÒ½.Ý‹Qн^‘[”®G÷rt[Sk…Gº+Ò½ÝTôëÒ½ÝÍd^n™€ðåÒƱqÕª1ŸàZÕ2æ³/óS€ù:Dú¡`ݾºX‡~š›ŸýèÐW´¢À…Ô[Ž Tç„£ÚÒøhA¡:'\½ˆi!F&ªsÂÓq±6Ý^p%NèŽêœXèpbµX;Wä„N(©Î‰¥:'lo¬®É àR+uN8Swå\Ócê„›êœX«sÂzóå5GQ­Tð3ʼð¦ z¬»/zĤ‚›à˘ԹtLÚ/üÄSXëöhK°I ñw2­ ´mÊ~ ~èÄ¡-!ç`ü(o¿?t¢Ñ–Às0~8SÏu%aØ%ø¡“¶„ŸƒñÃ.mYÊãüЉL[‚ÐÁøáM×ó…$$»?tâÓ–Pt0~,§óÕru]~èD©-é`üXMíÅJ¨^‚:±jKX:?ÖS÷Ê£­V¼Úş̌ g ¤GØ*¸1ª [Ý/ËçÚ±l iÃeS_Àšúp Õ°Ð>TNõE¬¾“V}!KòÃdV_È:ý0ÉÕ²x?L~õ…¬è“b})ËüeYDZø/¸³¾ŒX½ç±’GUŸaÄ:Ø”E’G²¶‡S.#‰dÿ©‰Iþ`‘¬ë8Òe`Ê,]fÜ“û›ô"Y Fz0Ñѳ»Éÿþýtˆ„s`y„êyÔ,H×®ëURbÎÌ8Ó=¬Œ3­áê88Ó=ÆŒ3kW¾gf$œéðÄk:_¯$)ØÑp¦{ô;glÏ•îŸ gº‡ÂƒqƯŸƒÎ(ÄѱÆ[x7tÁj1ò[X,9…ª%G¡š~y~KÃà›j[÷Øy°Q RÞ2ª‚3ÝæÁ8ãX-¹ªqpæѳÛ6gn=/ìõs°¦DÏKé2ýh8sõèÍ+dKÔ£áÌ ¢gkþ,üÌ ¢gÛk‹žGÁ™[DÏ®µ”/$\”5zѳàdŽžÅ‡ÊžÿC7z¶VÖ´­_ô܉ø³è™P>vÎô‹žµ8c; ùÖ88Ó/zÖâŒãÉO’Œ„3ý¢g-θ-ŠÆÁ˜~Á³c¼µü˜ÉH8Ó/xÖâÌr.?´8Îô žµ8³²Ÿ…5õ žµ8³v=yR~œéÁW/ÆoðÕ ¹÷÷TŸÐÍý{ȃä˜Õ › -§îzm—R&¯’ðfÅÃo\31»>ÐøîG[GÈrY}Cój’Iì\¶Â÷ýfÍÌDnúâ§ä”WYzçÔ Y¨Œ®=vrfEWhÙ›MMª¯ôZîÜnG³0D"å¹GÞ®6QPmŠ˜YINÂÓ[AµU…‚*¶çR*G¼ó!ŽVü¬è¢%-D=ULüÔ´ÀOƒÒC– Ñàãh8p<_@£éë_’Ç7‰ñlö1zÕxçÇ'?"m ÏgÑÄfïs~Ò] ÐOÁ~XÌÀ¿ÿ†ãÍ·¾9ZÒ.XHx¬)BUdX»µ1ý|\œlrÌ8èùO)~‚õµ=gŸ,á_ÉÖàzÁ/£Ö IÙº ÁÙ™°Jy×ÄÊŠY È*þPK'¹™’fˆ6PKZGŸ=*˜ÍŸŸmeta.xml LibreOffice/3.3$Unix LibreOffice_project/330m18$Build-42010-11-27T08:08:155PT7M18S2010-12-31T03:58:53Dan KimbergPKZGŸ= Ä J® ® Thumbnails/thumbnail.png‰PNG  IHDRÆg?ž uIDATxœíÑ’£8 EÝUû_Og¾¬wjSK¹%Y &çÝ¢…Ü* kƒ¯¿9ñ™± s|­Ó”ª&îÇÅKmðņù‘]N¦—Ф Sv‘I@˜…àèÍRÝ–Ò›«ñ§t"'… hÏ÷¹ìÑì${)³wó4ºò !¹.%ºöݺó’é¥jÌÒ¥h¤¼ù<ÎðR¢±>«9îb§¦f¸—jÕŸüßi!¸›3ÊKEêO"]Õ¬y奊[2=–Þ6J¸3½T Žò`vöL›ëéâö­ôR¨YMíµ5 vð÷½Íù~©bå•טÖJ[¨¢ü–(¾‹.yùÿ£ª‘Î!‹ ?‰JJ'Œuû`UÓyl)îÌžic̦ »™9‚ŽÞ/®¶:‡DFÞ¼Ôœ±Hc«Ó‘é¥D¿EÕ0ņ¨…âu@²—2Áâ€æP©³¸.Ê„é8ÏK‰—¸¨3ÄKù£¢þ‹r]¨jRz)*Fà°/R¦Úz¸!c½@ $kÏß,jñ¶V |Ï`x©Ó1æë.Ìû²Óž×Ûþ„.)ê1äÛs½ÂIW;ͲSwW÷t;!—ø›¼a½”ÓX—4ÅçïZÔb:ç¤N¼Ž þ]Næ_}§EkíêZ{ˆ/aÏi3šý …Íó”Ý]"F_ºH‡æŒf`©S©¢>ƒÐRtDé-½Â…ä{)9HÕªZ[êCêÈ‚PÊÑï=³ô ž¨gvò½T·wÓm²\ps†|û„Ç“fÏáÙ\cÏÍ”÷i²çŽ+GOc¸=7·õKx£>³´íT5™Ó}ñagç·ài/å¢ÌQ2x}pâ7ëЪήI¯Ã˜ßš±YªÞp¦oÍš'¶}Rf)H×i!¦Ç“¶^J¬D([Šc0‹æÉœÓ£­â¨¤üÉcó2vBfÅÏ@­uyþ">§7}œÆ©_i‘µ^—'y£cÌGÈw1Â,qÕÕ/dw!™ߦYË¢¥S«Ö9œ‡ƒAœ4ðµÎy)2J+ÆìD‚þá4.óRµbZ³Z7âÀº‘âÅh&óR/õ-Å:'uÏÞe!iÈ5^Êñ×´Á2cÄJö:‡k¼T·Eä<§·V?úXôt“ì¹ïZ'V•Þ=DòŠ_å2#» ï÷yȯ3´Î×òL"m˜õm6 tdW((é As2jàÓÄs‰9Tuû¯ÛV³‰äWgëI­Ê*¯ZBOf‡f‹Vž©E±žâˆÿ¨> O|âùß/˜žf‰Í´RË äØó”Njy½Û# îFZ]*r³[ZÑcå&£ÙdNýÞóÈ5! Ùþ9¾M‡˜”¶Î°VçPÛ›üºÔ¢–賾ÖßS¹­«Ô\´÷‰CW ¶þE$øÐ7ðs|­]~­¨uȦ~àB†ŽÏßåGú/ýS@"›Þçä9>x$µ»>ÇW—:ÅHD•ò3I+uêB¥a} u©H¡òõ{5{mYPr†—ZÑ*Y7Zu„Ö^êSsÙ‡®v7çÊ]µ^:p ¢`äÃoC2;¿÷Ü,ûaˆ§+Ÿ2Ì„@‹C_¥¯«PÌ»AÚ_€ªF¾=ƒ¨¹ªÞÖçÞ´@ v7ê;>jޝ®dUá…J¬!±MAð…$¥Ý~\ñõUð öü\¶9²ŠÆÖà%ÊU© vwfl©Ó4Rzo+`ßUµ ÷Rþ”0ÀO%ÓKíÛô±ì¯KÅIN³sê´±o­J{zH/ÖÛÔ­l¾t"!Èu)q¾úÄ¢j ÂD€¬GLæÇ3ŸI¦—ÊMfFÑ1M›.p ªãœdÏ[w]¼Ôe-A+·­‡;>­‘Þ ƒœê¥²è^îAA §Ó8ôö7b02Í8LÍp{¾üþ̧n‡G2ÐK­ÏSúé=~bx*G—àévxcí¹ž¶ó‹–ðΛ6†b —†ƒÃN/Õ-]“8ÃKéÆú”zªØ¯TQǺ9gx©ÈÜmQRÓ‹ú°Úº-£¼TkšvŸ»êNÃtì´çb£ôt9=<†­OHû–¨e}DEjGÿp+êÛ}R¡{5ðQ$4´¼;.gˆ=o¦vmKã ºæ$¼ž?8"¸ËbÏ}‚…ÊB—X±;0Üž;6­eØ»ÓÆ­NHQw`ˆ=ÿþþ>rMÝўĩ_¬Ÿ’‚d$ƒ¤ $É )HIA2H ’AR ’‚d$ƒ¤ $É )HIA2H ’AR ’‚d$ƒ¤ $É )HIA2H ’AR ’‚d$ƒ¤ $É )HIA2H ’AR ’‚d$ƒ¤ $É )HIA2H ’AR ’‚d$ƒ¤ $É )HIA2H ’AR ’‚d$ƒ¤ $É )HIA2H ’AR ’òøúúúùùY·×öµ4!IÕïæ§aþíŸü†tÿ;…$õ±ÿ)ÉR;`à󨥃Œ‚ )HIA2H ’AR ’‚d$ƒ¤ ™> $U¶¤ªIEND®B`‚PKZGŸ='Configurations2/accelerator/current.xmlPKZGŸ=Configurations2/progressbar/PKZGŸ=Configurations2/floater/PKZGŸ=Configurations2/popupmenu/PKZGŸ=Configurations2/toolpanel/PKZGŸ=Configurations2/menubar/PKZGŸ=Configurations2/toolbar/PKZGŸ=Configurations2/images/Bitmaps/PKZGŸ=Configurations2/statusbar/PKZGŸ= settings.xmlÍZÙsâ<ß¿"ÅëV†+“/P¾2‡2ÉæH›°ãA–\’̱ý¶l’Íœa ªÚ¼l©»ÕǯñãïMH/V dÀÙm¡ü­T¸ær/`þma<²/o 7þñƒÏç u»qL]JP —È ÜÎd=}}[ˆ«s"Yg$YWnGÀÞ¶Õ?®®'ÌÒ'°åma¡TT/×ëõ·uõ~±\«ÕŠÉÛ·¥.góÀ?–Uºú#+Îù;#½!&aV)•®Šé÷ÂÅNȪ©ozx;~ãÇŽAúq(µn.vµh·dY_°~×ZáоÿÞ3Áõ–2âQáíÚFø†ræ7×W××?ŠûdŽ'ýsuvé4ºÏ§ Wª×W'¿‡À_ÍWÉI}¸àk<ô3h-óA~â0ãœa…†1äãÑeMÁמ¸YÔç„Ê£É_†$º ˜ðö•uØÉ’=b{œÊ»Þ'Q¥V¶öçJ~Sfú^ùæúû_ùéf†Kí¯ïßó’•ÁŒÂù£%!k$¾ÊNv T¯«7'Ñnr¥xxØ€¥ë«›«|Ô§œ‡#¤õÙç\¨B£z‚»‘-U‹Ó8dŸC{G½|*õ&ç˳Åö¾^lâ*.2d/åt•®Wg |Cô?bLÖël^€iòøÄš>ˆQ˜¦ÿ— kQÊ×}D3õÀg-Â\ çý„~ŸD lÁÃ!¨øs¸ŸÃ?,/µ_o>Gdæ®8$çÐØ'f’£ü ‚Y2 ¬3Wʼn9MÄ]ÖÁçÜv6ú#‚i@K}ÁF«ÍÅgì=‡èXe#¨C%Êi(™h¥Å85¢$â`x ×WÍ€±-4üõý?‹¥‡í¬êðéK×úÿ”'ƒñ¿¢–ÖJän²ýbé³e=YÑ`÷Í·º–=ãË>†µÀ¹³K¯CkÓbÍ-yþ^Âó×ìaåÝ-¨ëG+7¤tÆœ…wGW³ßåÁ¬úPrC;ò¬è÷¬ÚŒ¦/Oµ§A¤^_î_¾>Ge·ê¨)Òê,ùÔZ¯ÛÖÏ×JMâÞåô¥Y"íÒö—­ÝʆzáDâºï§Ñke\ÓR;N{VÑ2-:¯/΢µ¤±{?)+›•׎Þ‹³²ìæbZ™ŒÈKD{K¤wï Ü–Õñ›íQ©<Lœ¹cO£Îäõ¥Tî;qÏê8“qgc?ÛµÉh©z£²×;ÁÅ:a¤¶_"à©È1ÄäE’ ­XÌËm¢ˆ‹CÂ2 üâä8“bõ,HÔc½Ùï>7!¹Et;– ´ìçÇÌŸ}"HÛȸZgg‚¥PV¬xб´Ôõ`B*ÄrèbÅT—ýŠÃˆ/Ît>—ÒŸC w/}íUœx3º5S*}6µ¥† Ms~‹ÛPïÏÏÏO! X+­°‘Lím 6KÜJó²˜×¤„-%V ÚÃZ„º15ZªYŒq•pÈ.Jrvà‰8|ýÀDQžˆo“ͯýÆêøhHËIØ>%.,8E¼5 k›ÿâê!–*˜oµaås O„Å„6¥–ˆæºŽýOúˆÌ TW>’Ðön.læ$=êíjÐ'@ÛºjÜÃÉûÀ´ÅÈ»Cd»l£‰-ÈDÞ(ö]ªÉzñòì)ö`ô,¦ xgƒ]+ñŒ$ô´·\FØ“kUõÏPÓ­+⢽љ"R_tdßNq©;Œï…‘°°hà3Dò¡âÖžÁW¹èDSß&X W¦Ø J—'–RB'Y,Ýln ´RøÕpo.wó/šÄ]ú‚Ç{ýÆyÊwŒsŒPcÁÞ‹•¾z„ÐW]×I“eõ»u°£Bpysìs1˾9B®³ÄÍß±áô{¤GÂü] #£Ë‰^èLÈ?ƒêx˜sžOD@ö"îø‚­ ~ÀtLå¦ÐaÞ—ûO¸ÿ‰ÿ¬àŽòy¯™ô`ÐØÄã-:£Gý) "K¾;³Å\Lfà= \*lºMÆæFf-œRIHFF- Tú±É§nýô´±’˨Œ¨ð©›/³Ý ùn xôöZôãÖ#œ=­MBi¢!ìZݥΤF†SéHa—DG<é+µÉMMºÛ‚¬“K®³“Oª‰T,@sÁô#{¬¿ÞçÐêÉJî”ÒÁ¦­F_—в‹*MÔ=Ý&éozz¬E¹4q²tÞ£oüFF4×ì'ób´¸÷¤bÖ¯³ÿPKKï?&¨ß%PKZGŸ=META-INF/manifest.xmlµ–ÍnÛ0 Çï} Ã×ÁVìíÐqŠ&CÎ;tÀÈ´#@–‰*ê·Ÿœ5»emãF¾èÔÿGI¤ÅåÝS/“G´NhU§E¾HT\7Buuúëa›Ý¦w«›eJ´è¨:v’°N¹—az«* N¸JA®"^iƒªÑÜ÷¨¨zm_¤ÕMrn…Ä,Ú!9Á°Ñ`°NÁ)8Pð“=ª&?°ò)"'|¢ô´z²«r2Ýz)3´¯S–²‹|=tÈŒêÎËýœ¼EÇŠÅô+'í×Å÷m±ÉG‰ˆèrñìÁöOSߊr}¿¾ßü˜~‡x¡ÚxI,ÃyU®W9\¦;P`‡ó ƒö”qà{üÂ6í—ÿîâ8—««£A¢›q:oËöH0Cô˜|Øû~§@HÇèØ½ZøMį¢·Ñª·‡Ûu%ÎQbj˸·v^P^Ί0Vw!UÝ"Z©0–÷Úx~ð>Ž. // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" extern "C" { #include "analyze.h" #include "nifti.h" void analyzeinfo_help(); void analyzeinfo_version(); int main(int argc,char **argv) { tokenlist args; args.Transfer(argc-1,argv+1); if (args.size()==0) { analyzeinfo_help(); exit(0); } if (args[0]=="-h") { analyzeinfo_help(); exit(0); } if (args[0]=="-v") { analyzeinfo_version(); exit(0); } IMG_header ihead; NIFTI_header nh; Cube cb; for (size_t i=0; i\n"); printf("\n"); } void analyzeinfo_version() { printf("VoxBo analyzeinfo (v%s)\n",vbversion.c_str()); } } // extern "C" voxbo-1.8.5~svn1246/fileformats/dcmsplit.cpp000066400000000000000000000133041153177201300207630ustar00rootroot00000000000000 // dcmsplit.cpp // split a DICOM file into identifying and non-identifying parts // Copyright (c) 2009-2010 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" #include "dcmsplit.hlp.h" using namespace std; using boost::format; extern "C" { #include "dicom.h" int32 hextol(const string &str); int do_dcmsplit(string infile); void dcmsplit_help(); void dcmsplit_version(); // argh! globals! string outfile,outpat,anonfile,anonpat; set stripgroups; set stripges; set stripvrs; bool f_checkfirst=1; int main(int argc,char **argv) { if (argc<2) { dcmsplit_help(); exit(0); } vectorfilelist; bool f_recursive=0; tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; i hitlist; vbforeach(string s,filelist) hitlist.push_back(s); while (hitlist.size()) { string ff=hitlist.front(); hitlist.pop_front(); if (vb_fileexists(ff)) { do_dcmsplit(ff); continue; } if (!vb_direxists(ff)) continue; // okay, we are a directory vglob vg(ff+"/*"); for (size_t ii=0; ii200) { cout << format("[E] dcmsplit: %s is not a well-formed DICOM file (%d)\n")%infile%err; return 180; } else if (err) { cout << format("[E] dcmsplit: error %d checking %s\n")%err%infile; return 180; } } if (removed==0) { cout << format("[E] dcmsplit: skipping %s\n")%infile; return 0; } if (outfile.empty()) { if ((err=anonymize_dicom_header(infile,infile,anonfile, stripgroups,stripges,stripvrs, removed))) { if (err==222) cout << format("[E] dcmsplit: %s is not a well-formed DICOM file\n")%infile; else cout << format("[E] dcmsplit: %s: anonymize error %d\n")%infile%err; } else if (removed==0) cout << format("[I] dcmsplit: skipping %s (no identifying fields)\n")%infile; else cout << format("[I] dcmsplit: anonymized %s\n")%infile; } else { if ((err=anonymize_dicom_header(infile,outfile,anonfile, stripgroups,stripges,stripvrs, removed))) { if (err==222) cout << format("[E] dcmsplit: %s is not a well-formed DICOM file\n")%infile; else cout << format("[E] dcmsplit: %s: anonymize error %d\n")%infile%err; } else if (removed==0) { cout << format("[I] dcmsplit: skipping %s (no identifying fields)\n")%infile; } else { cout << format("[I] dcmsplit: splitting %s\n")%infile; cout << format("[I] dcmsplit: de-identified data are in: %s\n")%outfile; if (anonfile.size()) cout << format("[I] dcmsplit: identifying data are in: %s\n")%anonfile; } } return 0; } int32 hextol(const string &str) { string tmp=xstripwhitespace(str); stringstream ss(tmp); int32 res; ss >> hex >> res; if (ss.fail() || (size_t)ss.tellg() ...] [] flags: -g additional groups to strip -e additional elements to strip -d specific datatypes (VR's) to strip # -m multi-file mode -o output filename for stripped file -- the substring FILE will be replaced with the original filename, and BASE will be replaced with the original filename stripped of extensions. -s filename for storing the identifying data -r recursive mode -dc don't check first -h show help -v show version notes: dcmsplit takes one or more DICOM files and strips it of elements likely to contain identifying data. The original file is left untouched if you specify the output file with the -o flag. The identifying data can optionally be stored in a second file, using the -s flag. The following fields are always stripped: all of groups 0010, 0012, 0032, and 0038 any element with value representation of PN (person name) In addition, if you know what you're doing, you can strip additional whole groups with -g, specific elements with -e, or specific VRs with -d. For example, if you want to strip all dates stored as such, you could use -d DA. Note that all groups and elements are specified in hexadecimal, as is the convention. Note that elements embedded inside SQ (sequence) elements are not stripped, unless the SQ itself is stripped. dcmsplit also creates a unique (30 alphanumeric character) identifier for each file at runtime, and places it in group/element 1119.0002. This is intended to be useful for matching up files later. If the -r flag is provided, and the argument is a directory, we process all files in the directory recursively. dcmsplit does not overwrite files that don't contain identifying information. However, it does write temporary files by default. This can be inefficient when checking a large number of files, if many of them may already be de-identified. To avoid this problem, it does a first-pass read to make sure the file has identifying information. To skip this check, use the -dc flag. Note that dcmsplit also handles older-style ACR/NEMA files, which are a lot like DICOM. Finally, note that dcmsplit does not remove elements, but overwrites them with zeros or the string "ANON", as appropriate. voxbo-1.8.5~svn1246/fileformats/dicominfo.cpp000066400000000000000000000037301153177201300211150ustar00rootroot00000000000000 // dicominfo.cpp // dump DICOM headers // Copyright (c) 1998-2006 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" extern "C" { #include "dicom.h" void dicominfo_help(); void dicominfo_version(); int main(int argc,char **argv) { tokenlist args; args.Transfer(argc-1,argv+1); if (args.size()==0) { dicominfo_help(); exit(0); } if (args[0]=="-h") { dicominfo_help(); exit(0); } if (args[0]=="-v") { dicominfo_version(); exit(0); } // dicominfo dci; for (size_t i=0; i\n"); printf("\n"); } void dicominfo_version() { printf("VoxBo dicominfo (v%s)\n",vbversion.c_str()); } } voxbo-1.8.5~svn1246/fileformats/ff_xxx.cpp000066400000000000000000000050421153177201300204460ustar00rootroot00000000000000 // ff_nifti3d.cpp // VoxBo file I/O code for nifti-1 format, 3D n+1 files // Copyright (c) 2005-2006 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" extern "C" { #include "nifti.h" vf_status xtest_n13d_3D(unsigned char *buf,int bufsize,string filename); int xread_head_n13d_3D(Cube *cb); int xread_data_n13d_3D(Cube *cb); int xwrite_n13d_3D(Cube *cb); #ifdef VBFF_PLUGIN VBFF vbff() #else VBFF nifti3d_vbff() #endif { VBFF tmp; tmp.name="NIfTI 3D"; tmp.extension="nii"; tmp.signature="n13d"; tmp.dimensions=3; tmp.version_major=vbversion_major; tmp.version_minor=vbversion_minor; tmp.test_3D=xtest_n13d_3D; tmp.read_head_3D=xread_head_n13d_3D; tmp.read_data_3D=xread_data_n13d_3D; tmp.write_3D=xwrite_n13d_3D; return tmp; } vf_status xtest_n13d_3D(unsigned char *buf,int bufsize,string filename) { string xt=xgetextension(filename); if (xt!="nii" && xt!= "img" && xt != "hdr") return vf_no; NIFTI_header nn; if (nifti_read_header(filename,&nn,NULL)) return vf_no; if (nn.dim[0]==3) return vf_yes; return vf_no; } int xread_head_n13d_3D(Cube *cb) { int err=nifti_read_header(cb->GetFileName(),NULL,cb); return err; } int xread_data_n13d_3D(Cube *cb) { if (!cb->header_valid) { if (nifti_read_header(cb->GetFileName(),NULL,cb)) return 101; } int err=nifti_read_3D_data(*cb); return err; } int xwrite_n13d_3D(Cube *cb) { if (!cb->data_valid) return 101; int err=nifti_write_3D(cb->GetFileName(),*cb); return err; } } // extern "C" voxbo-1.8.5~svn1246/fileformats/ffinfo.cpp000066400000000000000000000033061153177201300204140ustar00rootroot00000000000000 using namespace std; // #include #include #include #include "dlfcn.h" #include "vbprefs.h" #include "vbio.h" int main(int argc,char **argv) { stringstream tmps; string thisdir,prevdir; VBFF::LoadFileTypes(); if (argc>1) { tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; i types=EligibleFileTypes(args[i]); for (size_t j=0; j::iterator ff; for (ff=VBFF::filetypelist.begin(); ff!=VBFF::filetypelist.end(); ff++) { if (ff->getSignature()=="NONE") continue; // following commented out while we're using all built-ins // if ((thisdir=xdirname(VBFF::filetypelist[i].getPath())) != prevdir) { // prevdir=thisdir; // tmps.str(""); // tmps << "In directory " << thisdir << ":"; // printErrorMsg(VB_INFO,tmps.str()); // } printf("[I] %s (%s) id=%s ext=%s support=", ff->getName().c_str(), ff->getPath().c_str(), ff->getSignature().c_str(), ff->extension.c_str()); if (ff->read_1D) printf("read1d "); if (ff->write_1D) printf("write1d "); if (ff->read_data_3D) printf("read3d "); if (ff->write_3D) printf("write3d "); if (ff->read_data_4D) printf("read4d "); if (ff->write_4D) printf("write4d "); printf("\n"); } exit(0); } voxbo-1.8.5~svn1246/fileformats/vbrename.cpp000066400000000000000000000110631153177201300207430ustar00rootroot00000000000000 // vbrename.cpp // rename dicom files that have appropriate fields, etc. // Copyright (c) 2003-2005 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vbrename.hlp.h" class VBRename { public: int forceflag; bool f_anon; int Go(tokenlist &args); int Rename(string filename); }; extern "C" { #include "dicom.h" void vbrename_help(); void vbrename_version(); int main(int argc,char *argv[]) { tokenlist args; args.Transfer(argc-1,argv+1); if (args.size() <1) { vbrename_help(); exit(0); } VBRename vbr; int err=vbr.Go(args); exit(err); } int VBRename::Go(tokenlist &args) { int bad=0,good=0; struct stat st; tokenlist filelist,targetlist; forceflag=0; f_anon=1; for (size_t i=0; i stripgroups; set stripges; set stripvrs; int removed=1; err=anonymize_dicom_header(newname,newname,"",stripgroups,stripges,stripvrs,removed); return err; } void vbrename_help() { cout << boost::format(myhelp) % vbversion; } void vbrename_version() { printf("VoxBo vbrename (v%s)\n",vbversion.c_str()); } } // extern "C" voxbo-1.8.5~svn1246/fileformats/vbrename.hlp000066400000000000000000000022711153177201300207450ustar00rootroot00000000000000 VoxBo vbrename (v%1%) summary: sorts DICOM files into separate directories usage: vbrename [flags] [ ...] flags: -n don't remove identifying fields # -f change permissions to 775 if needed -h show help -v show version notes: vbrename will take a heap of mixed DICOM files and sort them into directories based on the series and protocol, and rename the files according to instance, date, and time, as in the following: 0001_localizer/0001_20101019_091004.170008 By default, vbrename de-identifies each file in the process, using the default behavior of dcmsplit, removing: all of groups 0010, 0012, 0032, and 0038 any element with value representation of PN (person name) Note that elements embedded inside SQ (sequence) elements are not stripped, unless the SQ itself is stripped. If you don't want to de-identify your data, use the -n flag -- the files will be sorted and renamed, but not modified in any way. If you want more control over how files are stripped, use dcmsplit. Note that vbrename will also attempt to make the file and its containing directory user-readable and user-writable if possible. voxbo-1.8.5~svn1246/gdscript/000077500000000000000000000000001153177201300157435ustar00rootroot00000000000000voxbo-1.8.5~svn1246/gdscript/Makefile000066400000000000000000000016711153177201300174100ustar00rootroot00000000000000 # Makefile for gds -include ../make_vars.txt include ../make_stuff.txt VBLIBS=$(VBLIBS2) # place to search for includes and targets ONEOVERFDIR=../utils # object files (including moc files) for the executables GDS_OBJECTS = gds_main.o gds.o # miscellaneous flags and such LIBS = $(LDFLAGS) $(LIBDIRS) $(DLLIB) -lm -lvbprefs -lvbglm -lvbio -lvbutil -lz -lpng $(GSL_LIBS) ALLBINS=gds ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else ifeq ($(VB_TARGET),spm) BINS=$(ALLBINS) else ifeq ($(VB_TARGET),vlsm) BINS= endif # the main targets all: $(BINS) install: ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) $(VBLIBS): +make -C ../lib $@ gds: $(GDS_OBJECTS) $(VBLIBS) +make -C ../utils fitOneOverF.o $(CXX) -o gds $(GDS_OBJECTS) $(LIBS) gds.o: gds.cpp gds.h $(CXX) -c -o gds.o gds.cpp $(CXXFLAGS) gds_main.o: gds_main.cpp $(CXX) -c -o gds_main.o gds_main.cpp $(CXXFLAGS) voxbo-1.8.5~svn1246/gdscript/gds.cpp000066400000000000000000005204071153177201300172340ustar00rootroot00000000000000 // gds.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu using namespace std; #include "gds.h" extern VBPrefs vbp; const int BUFLEN = 1024; int lineNum; gSession mySession; /********************************************************** * Covar class: holds a single covariate's information **********************************************************/ /* Covar constructor */ Covar::Covar() { init(); } /* Destructor */ Covar::~Covar() { } /* Simple initialization */ void Covar::init() { varname = "undefined"; group = ""; type = 'u'; cpCounter = 0; } /********************************************************** * Contrast class: holds contrast covariate's options * It includes three paremeters: * scale flag, center-norm flag, contrast matrix **********************************************************/ /* Constructor */ Contrast::Contrast() { init(); } /* Desctructor */ Contrast::~Contrast() { init(); } /* Initialization */ void Contrast::init() { scaleFlag = true; centerFlag = true; if (matrix.size()) matrix.clear(); } /********************************************************** * diagonalSet class: holds diagonal set's options * It includes only two paremeters: * scale flag, center-norm flag **********************************************************/ /* Constructor */ diagonalSet::diagonalSet() { init(); } /* Desctructor */ diagonalSet::~diagonalSet() { init(); } /* Initialization */ void diagonalSet::init() { scaleFlag = false; centerFlag = true; } /********************************************************************* * scriptReader class: reads the whole input gds file and build the * corresponding G matrix, could have multiple gSessions *********************************************************************/ /* Constructor */ scriptReader::scriptReader() { validity = true; validateOnly = false; gcounter = 0; } /* Desctructor */ scriptReader::~scriptReader() { } /* build G matrix files for each session */ void scriptReader::makeAllG() { for (int i = 0; i < (int) sessionList.size(); i++) sessionList[i].writeG(); } /* Parse the input file */ bool scriptReader::parseFile(string filename, int inLineNum) { ifstream infile; char buf[BUFLEN]; tokenlist args; //stringstream tmps; infile.open(filename.c_str()); if (!infile) { printf("GDS I/O ERROR: couldn't open %s\n", filename.c_str()); return false; // error! } lineNum = 0; // Make sure line number is always counted in local file while (infile.getline(buf,BUFLEN,'\n')) { lineNum++; args.ParseLine(buf); // ParseLine() already takes care of comment lines ("#" or ";" lines) if (!args.size()) continue; // "include will combine another script file if (args[0] == "include") { if (args.size() == 2) { int orgLineNum = lineNum; validity = parseFile(args[1], orgLineNum); lineNum = orgLineNum; mySession.inputFilename = filename; } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- include needs one and only one argument: \n"); mySession.validity = false; } continue; } // "gsession" is followed by a brand-new G matrix design session if (args[0] == "gsession") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { mySession.gsessionFlag = true; printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- gsession is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n"); mySession.validity = false; continue; } // If there is previous session before this one if (gcounter) { mySession.chkEnd(); // Final check of condition function (in case it has never been used) if (mySession.condfxn.length() && !mySession.doneCondition) mySession.chkCondition(); // Make sure previous session does include covariate(s) if (mySession.validity && !validateOnly && !mySession.covList.size()) { printf("GDS ERROR in %s [line %d]: %s session doesn't include any covariates\n", filename.c_str(), lineNum, mySession.dirname.c_str()); mySession.validity = false; } validity = (validity && mySession.validity); // Take care of the previous session if (mySession.validity && !validateOnly) // sessionList.push_back(mySession); mySession.writeG(); } mySession.reInit(); mySession.startLine = lineNum; mySession.gsessionFlag = true; mySession.inputFilename = filename; mySession.validateOnly = this->validateOnly; if (args.size() != 2) { printf("gds syntax error in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- gsession takes exactly one argument\n"); mySession.validity = false; } else { int gFileStat = mySession.chkSessionName(args(1)); if (gFileStat == 0) { printf("gds error in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- Parent directory not exist: %s\n", xdirname(args[1]).c_str()); mySession.validity = false; } else if (gFileStat == 1) { printf("gds error in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- Parent directory not writeable: %s\n", xdirname(args[1]).c_str()); mySession.validity = false; } else if (gFileStat == 2) { printf("gds error in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- Directory exists: %s\n", args(1)); mySession.validity = false; } else if (gFileStat == 3) { string pregStr = xrootname(args[1]) + ".preG"; printf("gds error in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- Directory exists: %s\n", pregStr.c_str()); mySession.validity = false; } } gcounter++; } // Make sure all other tags have a "gSession" tag before it else if (!mySession.gsessionFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- gsession line not found before %s\n", args(0)); mySession.validity = false; continue; } // openG opens an existing G matrix file else if (args[0] == "openG") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- openG is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n"); mySession.validity = false; continue; } if (args.size() != 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- openG needs one and only one argument: \n"); mySession.validity = false; continue; } if (mySession.chkG(filename.c_str(), args(1))) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- openG is reading a G matrix file that already exists.\n"); printf(" Previous covariates will be deleted.\n"); printf(" It may also clear previous scan definition and overwrite TR/length/sampling values.\n"); mySession.readG(filename.c_str(), args(1)); } } // Read tes files else if (args[0] == "scan") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- scan is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n"); mySession.validity = false; continue; } if (mySession.doneCommon) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- scan lines must be before newcov/modcov/modcov+ section\n"); mySession.validity = false; continue; } if (args.size() == 2) { if (!mySession.chkinfile(args(1))) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid scan file: %s\n", args(1)); mySession.validity = false; continue; } mySession.teslist.Add(args[1]); mySession.tesReal.push_back(true); mySession.lenList.push_back(-1); } else if (args.size() == 3) { mySession.teslist.Add(args[1]); mySession.tesReal.push_back(false); mySession.fakeTes = true; mySession.lenList.push_back(strtol(args(2))); } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- scan line should be written as:\n"); printf(" scan or: scan length\n"); mySession.validity = false; } } // Read TR else if (args[0] == "TR" || args[0] == "tr") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (mySession.doneCommon) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- TR is being reset, covariates defined before this line will be cleared\n"); mySession.resetTR(); } else if (mySession.TR) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- TR is being reset, previous value will be overwritten\n"); } if (args.size() == 2) { if (strtol(args[1]) > 0) mySession.TR = strtol(args[1]); else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid TR: %s\n", args(1)); mySession.validity = false; } } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- TR needs one and only one argument: \n"); mySession.validity = false; } } // Read upsampling rate else if (args[0] == "sampling") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (mySession.doneCommon) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- sampling is being reset, covariates defined before this line will be cleared\n"); mySession.resetSampling(); } else if (mySession.samplingFlag) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- sampling already exists, previous definition will be overwritten\n"); } if (args.size() == 2) { if (strtol(args[1]) > 0) { mySession.tmpResolve = strtol(args[1]); mySession.samplingFlag = true; } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid sampling rate: %s\n", args[1].c_str()); mySession.validity = false; } } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- sampling needs one and only one argument: \n"); mySession.validity = false; } } // Define total number of time points (images) else if (args[0] == "length") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (mySession.doneCommon) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- length is being reset, covariate(s), scan file(s) and condition function\n"); printf(" defined before this line will be cleared\n"); mySession.resetLen(); } else if (mySession.totalReps) { printf("GDS syntax WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- length line already exists, previous definition will be overwritten\n"); } if (args.size() == 2) { if (strtol(args[1])) mySession.totalReps = strtol(args[1]); else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid length: %s\n", args[1].c_str()); mySession.validity = false; } } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- length needs one and only one argument: <# of images>\n"); mySession.validity = false; } } // Define condition function else if (args[0] == "condition") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (args.size() != 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition needs one and only one argument: \n"); mySession.validity = false; continue; } if (mySession.chkinfile(args(1))) { if (mySession.condfxn.length()) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition line already exists, previous definition will be overwritten\n"); } mySession.condfxn = args[1]; mySession.doneCondition = false; } else { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid condition function file: %s\n", args(1)); mySession.validity = false; } } /* Define condition label file, it needs one and only one argument as filename */ else if (args[0] == "condition-label-file") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (!mySession.condfxn.length()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition function not defined\n"); mySession.validity = false; continue; } if (mySession.condLabFile.length()) { printf("GDS WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition-label-file line already exists.\n"); printf(" Previous definition will be overwritten\n"); } if (mySession.userCondKey.size()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition-label-name line already exists\n"); mySession.validity = false; } else if (args.size() != 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition-label-file needs one and only one argumentas: \n"); mySession.validity = false; } else if (!mySession.chkinfile(args(1))) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid condition label file: %s\n", args(1)); mySession.validity = false; } else { mySession.condLabFile = args[1]; mySession.doneCondition = false; } } /* Define condition label strings */ else if (args[0] == "condition-label-name") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (!mySession.condfxn.length()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition function not defined\n"); mySession.validity = false; continue; } if (mySession.condLabFile.length()) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition-label-file already exists\n"); mySession.validity = false; } else if (args.size() == 1) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition-label-name takes at least one argument\n"); mySession.validity = false; } else { for (size_t i = 0; i < args.size() - 1; i++) mySession.userCondKey.Add(args[1+i]); mySession.doneCondition = false; } } /* modify a certain condition label's name */ else if (args[0] == "mod-condition-label") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (!mySession.condfxn.length()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition function not defined\n"); mySession.validity = false; continue; } if (args.size() != 3) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- mod-condition-label needs two and only two arguments:\n"); printf(" \n"); mySession.validity = false; } else { if (!mySession.doneCondition) mySession.chkCondition(); if (mySession.validity) { if (mySession.chkKeyName(args[1]) == -1) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition label name not found: %s", args(1)); mySession.validity = false; } else mySession.condKey[mySession.chkKeyName(args[1])] = args[2]; } } } /* save condition labels as a txt file */ else if (args[0] == "save-condition-label") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; continue; } if (!mySession.condfxn.length()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- condition function not defined\n"); mySession.validity = false; continue; } if (args.size() != 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- save-condition-label needs one and only one argument: \n"); mySession.validity = false; } else { if (!mySession.doneCondition) mySession.chkCondition(); if (mySession.validity) { int fileStat = checkOutputFile(args(1), false); if (fileStat == 0) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s already exists, parent directory not writeable\n", args(1)); mySession.validity = false; } else if (fileStat == 1) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s already exists\n", args(1)); mySession.validity = false; } else if (fileStat == 2) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- parent directory not writable: %s\n", args(1)); mySession.validity = false; } else if (!validateOnly) mySession.saveLabel(args(1)); } } } /* save a certain covariate as a ref file */ else if (args[0] == "save-cov") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; } else if (args.size() != 3) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- save-cov needs two and only two arguments: \n"); mySession.validity = false; } else if (!validateOnly) { int selection = mySession.getCovID(args[1]); int fileStat = checkOutputFile(args(2), false); if (selection == -1) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- covariate name not found: %s\n", args(1)); mySession.validity = false; } else if (selection == -2) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- more than one covariates match the name: %s\n", args(1)); mySession.validity = false; } else if (fileStat == 0) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s already exists, parent directory not writeable\n", args(2)); mySession.validity = false; } else if (fileStat == 1) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s already exists\n", args(2)); mySession.validity = false; } else if (fileStat == 2) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- parent directory not writable: %s\n", args(2)); mySession.validity = false; } else if (mySession.validity) mySession.saveCov(selection, args(2)); } } // mean-center-all else if (args[0] == "mean-center-all") { if (mySession.newCovFlag || mySession.modCovFlag || mySession.modPlusFlag || mySession.effFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- %s is NOT allowed in the middle of newcov/modcov/modcov+/chkeff section\n", args(0)); mySession.validity = false; } else if (args.size() != 1) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- mean-center-all does NOT need any arguments\n"); mySession.validity = false; } else mySession.meanAll = true; } /**************************************************** * gds syntax lines that start with "newcov" keyword ****************************************************/ else if (args[0] == "newcov") { if (!mySession.doneCommon) mySession.chkCommon(); mySession.chkEnd(); if (args.size() < 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- newcov needs at least one argument\n"); mySession.validity = false; } // Add single covariate else if (args[1] == "single") { mySession.newCovFlag = true; mySession.singleFlag = true; if (args.size() != 3) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- newcov single takes one and only one argument: \n"); mySession.validity = false; } else if (!mySession.chkinfile(args(2))) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid covariate file: %s\n", args(2)); mySession.validity = false; } else { // Default name is "undefined" mySession.newVar.varname = "undefined"; // Default type is 'I' mySession.newVar.type = 'I'; mySession.singleFile = args[2]; } } // Old tag for adding single covariate, (obsolescent, kept for compatibility) else if (args[1] == "add-new") { printf("GDS SYNTAX WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-new is an obsolescent tag, recommended format to add single covariate:\n"); printf("\tnewcov single \n"); mySession.chkEnd(); mySession.newCovFlag = true; mySession.singleFlag = true; // Default type is 'I' mySession.newVar.type = 'I'; if (args.size() == 2) mySession.newVar.varname = "undefined"; else if (args.size() == 3) mySession.newVar.varname = args[2]; else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-new takes one and only one argument: \n"); mySession.validity = false; } } // Add intercept else if (args[1] == "intercept" || args[1] == "Intercept") { mySession.newCovFlag = true; mySession.interceptFlag = true; // Default type is 'K' mySession.newVar.type = 'K'; // Default name if (args.size() == 2) mySession.newVar.varname = "Intercept"; // Use the argument as name else if (args.size() == 3) mySession.newVar.varname = args[2]; else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- intercept takes an optional argument (covariate name)\n"); mySession.validity = false; } } // Obsolescent tag for intercept, kept for compatibility else if (args[1] == "add-intercept") { printf("GDS SYNTAX WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-intercept is an obsolescent tag, use intercept instead\n"); mySession.newCovFlag = true; mySession.interceptFlag = true; // Default type is 'N' mySession.newVar.type = 'K'; // Default name if (args.size() == 2) mySession.newVar.varname = "Intercept"; // Use the argument as name else if (args.size() == 3) mySession.newVar.varname = args[2]; else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-intercept takes an optional argument (covariate name)\n"); mySession.validity = false; } } // "trial effect" takes one argument else if (args[1] == "trial-effect") { mySession.newCovFlag = true; mySession.trialFlag = true; if (args.size() != 3) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- trial-effect needs one and only one argument\n"); mySession.validity = false; } else { int tmpInt = atoi(args(2)); if (tmpInt <= 0) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid trial effect value: %s\n", args(2)); mySession.validity = false; } else { mySession.trialLen = tmpInt; // Default type is 'I' mySession.newVar.type = 'I'; } } } // Add diagonal set else if (args[1] == "diagonal") { mySession.newCovFlag = true; mySession.diagonalFlag = true; // Default type is 'I' mySession.newVar.type = 'I'; if (!mySession.doneCondition) mySession.chkCondition(); if (!mySession.condKey.size()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- diagonal requires a valid condition function\n"); mySession.validity = false; } if (args.size() > 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- diagonal doesn't take any argument\n"); mySession.validity = false; } } // Obsolescent tag to add diagonal set else if (args[1] == "add-diagonal") { printf("GDS SYNTAX WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-diagonal is an obsolescent tag, use diagonal instead\n"); mySession.chkEnd(); mySession.newCovFlag = true; mySession.diagonalFlag = true; // Default type is 'I' mySession.newVar.type = 'I'; if (!mySession.doneCondition) mySession.chkCondition(); if (!mySession.condKey.size()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-diagonal requires a valid condition function\n"); mySession.validity = false; } if (args.size() > 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-diagonal doesn't take any argument\n"); mySession.validity = false; } } // Add contrasts else if (args[1] == "contrast") { mySession.newCovFlag = true; mySession.contrastFlag = true; // Default type is 'I' mySession.newVar.type = 'I'; if (!mySession.doneCondition) mySession.chkCondition(); if (!mySession.condKey.size()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- contrast requires a valid condition function\n"); mySession.validity = false; } if (args.size() > 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- contrast doesn't take any argument\n"); mySession.validity = false; } } // Obsolescent tag to add contrasts, kept for compatibility else if (args[1] == "add-contrast") { printf("GDS SYNTAX WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-contrast is an obsolescent tag, use diagonal instead\n"); mySession.chkEnd(); mySession.newCovFlag = true; mySession.contrastFlag = true; // Default type is 'I' mySession.newVar.type = 'I'; if (!mySession.doneCondition) mySession.chkCondition(); if (!mySession.condKey.size()) { printf("gds syntax error in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-contrast requires a valid condition function\n"); mySession.validity = false; } if (args.size() > 2) { printf("gds syntax error in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- add-contrast doesn't take any argument\n"); mySession.validity = false; } } // Add var length trial effects else if (args[1] == "var-trialfx") { mySession.newCovFlag = true; mySession.varTrialFlag = true; if (args.size() != 3) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- newcov var-trialfx needs one and only one argument: \n"); mySession.validity = false; } else if (!mySession.chkinfile(args(2))) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid var length trialfx file: %s\n", args(2)); mySession.validity = false; } else { // Default type is 'I' mySession.newVar.type = 'I'; mySession.trialFile = args[2]; } } // Add scan effect else if (args[1] == "scan-effect") { mySession.newCovFlag = true; mySession.scanFlag = true; // Default type is 'N' mySession.newVar.type = 'N'; if (args.size() > 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- scan-effect doesn't take any argument\n"); mySession.validity = false; } else if (mySession.teslist.size() == 1) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- only one tes file available, scan-effect line is illegal\n"); mySession.validity = false; } } // Add global signals else if (args[1] == "global-signal") { mySession.newCovFlag = true; mySession.gsFlag = true; // Default type is 'N' mySession.newVar.type = 'N'; if (mySession.fakeTes) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- fake tes files defined, GS file not exist\n"); mySession.validity = false; } if (args.size() > 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- global-signal doesn't take any argument\n"); mySession.validity = false; } else if (!mySession.teslist.size()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- tes file(s) must be defined for global signal design\n"); mySession.validity = false; } } // Add movement parameters else if (args[1] == "move-params") { mySession.newCovFlag = true; mySession.mpFlag = true; // Default ype is 'N' mySession.newVar.type = 'N'; if (mySession.fakeTes) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- fake tes files found, movement parameter file not exist\n"); mySession.validity = false; } if (args.size() > 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- move-params doesn't take any argument\n"); mySession.validity = false; } else if (!mySession.teslist.size()) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- tes file(s) must be defined for movement parameter design\n"); mySession.validity = false; } } // Spike covariate(s) is a new functionality else if (args[1] == "spike") { mySession.newCovFlag = true; mySession.spikeFlag = true; // Default type is 'N' mySession.newVar.type = 'N'; if (args.size() == 3) mySession.chkSpike(args[2], -1); else if (args.size() > 3) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- spike only takes an optional argument: absolute spike position\n"); mySession.validity = false; } } // Add multiple column txt file else if (args[1] == "txt-file") { mySession.newCovFlag = true; mySession.txtFlag = true; // Default type is 'N' mySession.newVar.type = 'N'; if (args.size() == 3) mySession.txtFile = args[2]; else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- txt-file requires a multiple column txt file\n"); mySession.validity = false; } } // Copy a certain covariate else if (args[1] == "cp") { mySession.newCovFlag = true; mySession.cpFlag = true; if (args.size() == 3) { if (!mySession.validateOnly) { mySession.singleID = mySession.getCovID(args[2]); if (mySession.singleID == -1) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- covariate name not found: %s\n", args(2)); mySession.validity = false; } else if (mySession.singleID == -2) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- more than one covariates match the name: %s\n", args(2)); mySession.validity = false; } } } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- newcov cp requires exactly one argument: covariate name\n"); mySession.validity = false; } } // unknown tag after newcov else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- unknown tag in newcov line: %s\n", args[1].c_str()); mySession.validity = false; } } /********************************************************* * gds syntax lines between "newcov xxx" and "end" tags *********************************************************/ // type: interest / NoInterest / KeepNoInterest else if (args[0] == "type") { if (!mySession.newCovFlag && !mySession.modCovFlag && !mySession.modPlusFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- newcov/modcov/modcov+ line not found before type\n"); mySession.validity = false; continue; } char foo = mySession.chkType(args[1]); if (args.size() == 2 && foo) mySession.newVar.type = foo; else if (args.size() == 2 && !foo) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid covariate type: %s\n", args(1)); mySession.validity = false; } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- type needs one and only one argument: \n"); mySession.validity = false; } } // "varfile" is obsolescent, kept for compatibility else if (args[0] == "varfile") { printf("GDS SYNTAX WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- varfile is an obsolescent tag, recommended format to add single covariate is:\n"); printf("\tnewcov single \n"); if (!mySession.singleFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- varfile is valid only for add-new\n"); mySession.validity = false; } else if (args.size() == 2 && mySession.chkinfile(args(1))) mySession.singleFile = args[1]; else if (args.size() == 2 && !mySession.chkinfile(args(1))) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- invalid covariate file: %s\n", args(1)); mySession.validity = false; } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- varfile takes exactly one argument\n"); mySession.validity = false; } } // Geoff's requst: customize new covariate's name in script else if (args[0] == "cov-name") { if (!mySession.newCovFlag && !mySession.modCovFlag && !mySession.modPlusFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- newcov/modcov/modcov+ before cov-name\n"); mySession.validity = false; continue; } if (args.size() > 1) { for (size_t i = 1; i < args.size(); i++) { if (mySession.chkCovName(args[i]) == -1) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- \"->\" is not allowed in covarite name string\n"); mySession.validity = false; } else if (mySession.chkCovName(args[i]) == -2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- same covariate name not allowed in one section: %s\n", args(i)); mySession.validity = false; } else if (!mySession.validateOnly && !mySession.chkUniName(args[i])) { printf("GDS ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- Covariate name already used in same gSession: %s\n", args(i)); mySession.validity = false; } else mySession.covName.Add(args[i]); } } else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- cov-name requires at least one argument\n"); mySession.validity = false; } } // group is an optional keyword for new covariate // dhubug: when "group" tag is met, check the new group name plus new or // existing covariate name to make sure the combination is unique. // (Similar to the name check for cov-name. This step is not done yet.) else if (args[0] == "group") { if (!mySession.newCovFlag && !mySession.modCovFlag && !mySession.modPlusFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- group must be in newcov/modcov/modcov+ session\n"); mySession.validity = false; } else if (mySession.newVar.group.length()) { printf("GDS syntax WARNING in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- Redundant group line: group already defined in this section\n"); } else if (args.size() == 2) mySession.newVar.group = args[1]; else { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- group needs one and only one argument: \n"); mySession.validity = false; } } // "option" is simulating "modify" menu else if (args[0] == "option") { if (!mySession.newCovFlag && !mySession.modCovFlag && !mySession.modPlusFlag) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- option must be in newcov/modcov/modcov+ session\n"); mySession.validity = false; } else if (args.size() < 2) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- option takes at least one argument\n"); mySession.validity = false; } // "convolve" option is special because it takes at least two arguments else if (args[1] == "convolve") { for (size_t i = 2; i < args.size(); i++) mySession.convolOpt.Add(args[i]); int convStat = mySession.chkConvol(mySession.convolOpt); if (convStat == 0) mySession.option.Add("convolve"); else { mySession.convolOpt.clear(); mySession.validity = false; } } else if (args[1] == "time-shift") { if (args.size() != 3) { printf("GDS SYNTAX ERROR in %s [line %d]:\n", filename.c_str(), lineNum); printf("--- option time-shift needs one and only one argument: .SH DESCRIPTION .B vbrename is part of the VoxBo suite of tools for brain image analysis. .P .B vbrename takes a directory containing DICOM files and sorts the files into separate directories for each series. The directories are renamed using the series and protocol, while the files are renamed using the instance, date, and time. .P By default, vbrename tries to remove identifying data from each file by wiping out various fields, including all of groups 0010, 0012, 0032, and 0038, and any element with a VR of PN (person name). This is not guaranteed to be helpful or complete. For more de-identifying options, see .BR dcmsplit (1). You can disable this behavior using the -n flag, in which case the files are renamed and moved around, but not otherwise modified. .P To get a complete list of available flags, run the program with no arguments. .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For information about file format support in VoxBo, see .BR voxbo-fileformats (7). For general information about VoxBo, see .BR voxbo (7). See also .BR dcmsplit (1). voxbo-1.8.5~svn1246/man/vbsim.1000066400000000000000000000022741153177201300161060ustar00rootroot00000000000000.TH vbsim 1 "January, 2011 (v1.8.5)" "VoxBo" "The VoxBo Manual" .SH NAME vbsim - create random data for neuroimaging .SH SYNOPSIS .B vbsim ... .SH DESCRIPTION .B vbsim is part of the VoxBo suite of tools for brain image analysis. .P .B vbsim allows you to create 1D vectors, 3D volumes, or 4D volume series filled with Gaussian random data. The supported output file formats are described in voxbo-fileformats(7). .P For detailed information on usage and options, run the program with no arguments. .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For information about file format support in VoxBo, see .BR voxbo-fileformats (7). For general information about VoxBo, see .BR voxbo (7). voxbo-1.8.5~svn1246/man/vbtmap.1000066400000000000000000000026551153177201300162620ustar00rootroot00000000000000.TH vbtmap 1 "January, 2011 (v1.8.5)" "VoxBo" "The VoxBo Manual" .SH NAME vbtmap - create a t-statistic map for VLSM .SH SYNOPSIS .B vbtmap ... .SH DESCRIPTION .B vbtmap is part of the VoxBo suite of tools for brain image analysis. .P .B vbtmap takes as input: a 4D lesion file containing 0/1 lesion maps for a series of subjects; and a 1D file containing a score for each subject. It carries out a separate t-test for each voxel comparing the scores of those subjects with a lesion in that voxel with the remaining subjects. .B vbtmap can optionally calculate a Welch's t-test, and can calculate FDR-controlling thresholds. .P To get a complete list of available flags, run the program with no arguments. .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For information about file format support in VoxBo, see .BR voxbo-fileformats (7). For general information about VoxBo, see .BR voxbo (7). voxbo-1.8.5~svn1246/man/vbview2.1000066400000000000000000000023161153177201300163470ustar00rootroot00000000000000.TH vbview2 1 "January, 2011 (v1.8.5)" "VoxBo" "The VoxBo Manual" .SH NAME vbview2 - image viewer for 3D and 4D volumes .SH SYNOPSIS .B vbview2 ... .SH DESCRIPTION .B vbview2 is part of the VoxBo suite of tools for brain image analysis. .P .B vbview2 is an image viewer for to 3D and 4D images. It displays slices, not projections or surface renderings. It allows an arbitrary number of layers and graphs time series data. .SH OPTIONS To get a complete list of available flags, run the program with the -h argument. .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For information about file format support in VoxBo, see .BR voxbo-fileformats (7). For general information about VoxBo, see .BR voxbo (7). voxbo-1.8.5~svn1246/man/vbvolregress.1000066400000000000000000000030411153177201300175020ustar00rootroot00000000000000.TH vbvolregress 1 "January, 2011 (v1.8.5)" "VoxBo" "The VoxBo Manual" .SH NAME vbvolregress - carry out linear regression in 1D and 4D data .SH SYNOPSIS .B vbvolregress ... .SH DESCRIPTION .B vbvolregress is part of the VoxBo suite of tools for brain image analysis. .P .B vbvolregress carries out linear regression, using an arbitrary combination of 1D and 4D variables. If only 1D variables are included, it's just a single regression. If a 34D dependent variable or at least one 4D independent variable is included, then a separate regression is carried out at each spatial location. .B vbvolregress optionally permutes the data, and can produce as output a statistical map, parameter estimate maps, and residuals. It will also carry out FDR thresholding if requested. .P To get a complete list of available flags, run the program with no arguments. .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For information about file format support in VoxBo, see .BR voxbo-fileformats (7). For general information about VoxBo, see .BR voxbo (7). voxbo-1.8.5~svn1246/man/vecview.1000066400000000000000000000032431153177201300164330ustar00rootroot00000000000000.TH vecview 1 "January, 2011 (v1.8.5)" "VoxBo" "The VoxBo Manual" .SH NAME vecview - graphical viewer for 1D (vector) or 2D (matrix) data .SH SYNOPSIS .B vecview [ ...] ... .SH DESCRIPTION .B vecview is part of the VoxBo suite of tools for brain image analysis. .P .B vecview allows you to view and explore one or more 1D vectors, or a single 2D matrix. Command line options allow you to concatenate vectors. Options in the graphical interface allow you to switch among multiple vectors or to view them all simultaneously. You can also view the power spectrum of the vector. .P The following keys are recognized by the grapher. The up arrow and down arrow let you zoom in or out. The tab key lets you switch between vectors when more than one is displayed. The shift key lets you see interpolated values (otherwise, clicking on the graph snaps to the nearest point). F1 through F4 select view modes. .P To get a list of command line flags, run the program with no arguments. .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For information about file format support in VoxBo, see .BR voxbo-fileformats (7). For general information about VoxBo, see .BR voxbo (7). voxbo-1.8.5~svn1246/man/voxbo-fileformats.7000066400000000000000000000063331153177201300204420ustar00rootroot00000000000000.TH voxbo-fileformats 7 "January, 2011 (v1.8.5)" "VoxBo" "The VoxBo Manual" .SH NAME voxbo-fileformats - general information about file format support in VoxBo .SH DESCRIPTION The VoxBo suite of tools for brain image analysis supports a variety of formats for 1D (vector), 2D (matrix), 3D (volume) and 4D (volume time series) data. .P File format support in VoxBo is modular - most of the tools can read and write any supported file format transparently, with output file formats usually determined by the file extension. .P The i/o library supports several special access methods. For 4D files, filename:mask is used to access the inclusion mask of a 4D file. The mask is treated as a 3D volume. Similarly, filename:n accesses the nth volume of the 4D series in filename, where n is an integer and the first volume is numbered 0. .P When writing, VoxBo honors filename tags that can be used to specify the fileformat or byteorder. Tags are specified in square brackets at the end of the filename, and multiple tags can be separated within the brackets by commas. For example, foo[imgdir] can be used to specify the imgdir file format (useful because imgdir format doesn't have a standard extension). foo.nii[little] forces little-endian storage for file formats that allow it. .SS "VoxBo native file formats" VoxBo's native file formats, all supported for read and write, include .ref (1D), .mat (2D), .cub (3D), and .tes (4D). Although these formats are not widely supported in external software, they offer some useful features, including user-editable text headers. gzip-compressed cub and tes files are supported transparently. .SS "NIfTI" VoxBo supports 3D and 4D NIfTI files (compressed or not) for read and write. VoxBo does not currently make intelligent use of the qform/sform orientation information. .SS "Analyze" VoxBo supports SPM-style Analyze(TM) files, including 3D and 4D files, as well as 4D time series composed of directories containing 3D files, for read/write. All individual files are stored in .img/.hdr pairs. .SS "DICOM" VoxBo supports DICOM (as well as some DICOM-like files in the older ACR/NEMA format) for reading only. VoxBo supports a corner of the DICOM standard frequently encountered in brain imaging research, including mosaic format volumes. Files containing single slice data are read as 3D volumes. Directories containing multiple files are generally parsed as 3D or 4D data, as appropriate, as long as no extraneous files are in the directory. .SS "Text Matrices and Vectors" Plain text files containing just numbers (or comment lines beginning with #, %, or ;), can be parsed as matrix or vector data. .SH EXAMPLES .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For general information about VoxBo, see .BR voxbo (7). voxbo-1.8.5~svn1246/man/voxbo.7000066400000000000000000000030641153177201300161270ustar00rootroot00000000000000.TH voxbo 7 "January, 2011 (v1.8.5)" "VoxBo" "The VoxBo Manual" .SH NAME voxbo - general information about the VoxBo toolbox .SH DESCRIPTION VoxBo is a suite of tools for brain image analysis, especially fMRI analysis and lesion-behavior mapping. VoxBo includes over 100 tools, including many for general-purpose image munging (e.g., vbim(1)), many that implement specific statistical procedures (e.g., vbtmap(1)), and some that would likely be just as useful for non-imaging applications (vbbatch(1)). .P VoxBo has supported cluster parallel processing since 1998. Although cluster installation is a little tricky, it's worth the effort if you'd like to speed up your analyses by an order of magnitude or two. As of 2010, VoxBo also supports desktop parallel processing on multi-core systems. We do not yet support GPU parallel processing. .P All VoxBo tools support a common set of file formats. See voxbo-fileformats(7) for more information. .SH AVAILABILITY Pre-built VoxBo binaries are available for Linux, OSX, and Cygwin, and via the NeuroDebian project (neuro.debian.net) for Debian derivatives. .SH CAVEATS VoxBo is provided with no warranty whatsoever. .SH AUTHOR For an historical roster of the VoxBo development team, visit www.voxbo.org. .SH SEE ALSO For detailed help on any VoxBo command-line program, run it with no arguments. For graphical programs, use the -h flag. For more help with VoxBo, for information about the mailing list, or to report bugs, visit the web site at www.voxbo.org. .P For information about VoxBo file formats, see .BR voxbo-fileformats (7). voxbo-1.8.5~svn1246/munge/000077500000000000000000000000001153177201300152375ustar00rootroot00000000000000voxbo-1.8.5~svn1246/munge/Makefile000066400000000000000000000127271153177201300167100ustar00rootroot00000000000000 # Makefile for munging functions -include ../make_vars.txt include ../make_stuff.txt VBLIBS=$(VBLIBS2) # miscellaneous flags and such LIBS =$(LDFLAGS) $(LIBDIRS) $(LIBPATHS) -lvbglm -lvbprefs -lvbio -lvbutil -lz -lpng $(DLLIB) $(GSL_LIBS) CONVERTERS=tes2cub vb2cub vb2img vb2imgs vb2tes vb2vmp vbconv MUNGERS=vbmunge vbcmp vbshift vbsmooth vbmaskmunge vecsplit vbinterpolate vbthresh DESIGNERS=vbprep vbbatch STATTERS=sumrfx calcperf MISC=cub2pngs setorigin fillmask vbhdr vbsim vbregion vborient MISC+=vbi vbmerge4d vbvec2hdr vbse vbmaskinfo MISC+=vboverlap vbimagemunge vbim vbfilter vbmaskcompare vbtool XXOUT=vbmakerfx extractmask # the main targets ALLBINS=$(CONVERTERS) $(MUNGERS) $(DESIGNERS) $(STATTERS) $(MISC) ifeq ($(VB_TARGET),spm) BINS=$(CONVERTERS) $(MUNGERS) $(MISC) else ifeq ($(VB_TARGET),vlsm) BINS=vbbatch else ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else BINS= endif all: $(BINS) install: ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) # rule to build the libvoxbo libraries $(VBLIBS): +make -C ../lib $@ %.hlp.h : %.hlp $(VBRC) $@ -myhelp $< vbtool.hlp.h : vbtool.hlp contrast.hlp priority.hlp $(VBRC) $@ -myhelp vbtool.hlp -contrasthelp contrast.hlp -priorityhelp priority.hlp vbprep.hlp.h : vbpsample.hlp $(VBRC) $@ vbpsample vbpsample.hlp -myhelp vbprep.hlp vbim.hlp.h : vbim.hlp vbim_examples.hlp $(VBRC) $@ -myhelp vbim.hlp -myhelp_examples vbim_examples.hlp # THE EXECUTABLES vbmunge: vbmunge.cpp vbmunge.hlp.h $(VBLIBS) $(CXX) -o vbmunge vbmunge.cpp $(LIBS) $(CXXFLAGS) vbthresh: vbthresh.cpp vbthresh.hlp.h $(VBLIBS) $(CXX) -o vbthresh vbthresh.cpp $(LIBS) $(CXXFLAGS) fillmask: fillmask.cpp fillmask.hlp.h $(VBLIBS) $(CXX) -o fillmask fillmask.cpp $(LIBS) $(CXXFLAGS) vbi: vbi.cpp vbi.hlp.h $(VBLIBS) $(CXX) -o vbi vbi.cpp $(LIBS) $(CXXFLAGS) vbconv: vbconv.cpp vbconv.hlp.h $(VBLIBS) $(CXX) -o vbconv vbconv.cpp $(LIBS) $(CXXFLAGS) tes2cub: tes2cub.cpp tes2cub.hlp.h $(VBLIBS) $(CXX) -o tes2cub tes2cub.cpp $(LIBS) $(CXXFLAGS) vb2cub: vb2cub.cpp vb2cub.hlp.h $(VBLIBS) $(CXX) -o vb2cub vb2cub.cpp $(LIBS) $(CXXFLAGS) vb2img: vb2img.cpp vb2img.hlp.h $(VBLIBS) $(CXX) -o vb2img vb2img.cpp $(LIBS) $(CXXFLAGS) vb2imgs: vb2imgs.cpp vb2imgs.hlp.h $(VBLIBS) $(CXX) -o vb2imgs vb2imgs.cpp $(LIBS) $(CXXFLAGS) vb2tes: vb2tes.cpp vb2tes.hlp.h $(VBLIBS) $(CXX) -o vb2tes vb2tes.cpp $(LIBS) $(CXXFLAGS) vbmerge4d: vbmerge4d.cpp vbmerge4d.hlp.h $(VBLIBS) $(CXX) -o vbmerge4d vbmerge4d.cpp $(LIBS) $(CXXFLAGS) vb2vmp: vb2vmp.cpp vb2vmp.hlp.h $(VBLIBS) $(CXX) -o vb2vmp vb2vmp.cpp $(LIBS) $(CXXFLAGS) vbcmp: vbcmp.cpp vbcmp.hlp.h $(VBLIBS) $(CXX) -o vbcmp vbcmp.cpp $(LIBS) $(CXXFLAGS) cub2pngs: cub2pngs.cpp cub2pngs.hlp.h $(VBLIBS) $(CXX) -o cub2pngs cub2pngs.cpp $(LIBS) -lpng -lz $(CXXFLAGS) setorigin: setorigin.cpp setorigin.hlp.h $(VBLIBS) $(CXX) -o setorigin setorigin.cpp $(LIBS) $(CXXFLAGS) extractmask: extractmask.cpp extractmask.hlp.h $(VBLIBS) $(CXX) -o extractmask extractmask.cpp $(LIBS) $(CXXFLAGS) vbinterpolate: vbinterpolate.cpp vbinterpolate.hlp.h $(VBLIBS) $(CXX) -o vbinterpolate vbinterpolate.cpp $(LIBS) $(CXXFLAGS) sumrfx: sumrfx.cpp sumrfx.hlp.h $(VBLIBS) $(CXX) -o sumrfx sumrfx.cpp $(LIBS) $(CXXFLAGS) calcperf: calcperf.cpp calcperf.hlp.h $(VBLIBS) $(CXX) -o calcperf calcperf.cpp $(LIBS) $(CXXFLAGS) vbmakerfx: vbmakerfx.cpp vbmakerfx.hlp.h $(VBLIBS) $(CXX) -o vbmakerfx vbmakerfx.cpp $(LIBS) $(CXXFLAGS) vbbatch: vbbatch.cpp vbbatch.hlp.h $(VBLIBS) $(CXX) -o vbbatch vbbatch.cpp $(LIBS) $(CXXFLAGS) vbtool: vbtool.cpp vbtool.hlp.h $(VBLIBS) $(CXX) -o vbtool vbtool.cpp $(LIBS) $(CXXFLAGS) vbhdr: vbhdr.cpp vbhdr.hlp.h $(VBLIBS) $(CXX) -o vbhdr vbhdr.cpp $(LIBS) $(CXXFLAGS) vbperminfo: vbperminfo.cpp vbperminfo.hlp.h $(VBLIBS) $(CXX) -o vbperminfo vbperminfo.cpp $(LIBS) $(CXXFLAGS) vbregion: vbregion.cpp vbregion.hlp.h $(VBLIBS) $(CXX) -o vbregion vbregion.cpp $(LIBS) $(CXXFLAGS) vbshift: vbshift.cpp vbshift.hlp.h $(VBLIBS) $(CXX) -o vbshift vbshift.cpp $(LIBS) $(CXXFLAGS) vbsmooth: vbsmooth.cpp vbsmooth.hlp.h $(VBLIBS) $(CXX) -o vbsmooth vbsmooth.cpp $(LIBS) $(CXXFLAGS) vbsim: vbsim.cpp vbsim.hlp.h $(VBLIBS) $(CXX) -o vbsim vbsim.cpp $(LIBS) $(CXXFLAGS) vborient: vborient.cpp vborient.hlp.h $(VBLIBS) $(CXX) -o vborient vborient.cpp $(LIBS) $(CXXFLAGS) vbmaskmunge: vbmaskmunge.cpp vbmaskmunge.hlp.h $(VBLIBS) $(CXX) -o vbmaskmunge vbmaskmunge.cpp $(LIBS) $(CXXFLAGS) vbimagemunge: vbimagemunge.cpp vbimagemunge.hlp.h $(VBLIBS) $(CXX) -o vbimagemunge vbimagemunge.cpp $(LIBS) $(CXXFLAGS) vbim: vbim.cpp vbim.hlp.h $(VBLIBS) $(CXX) -o vbim vbim.cpp $(LIBS) $(CXXFLAGS) vbfilter: vbfilter.cpp vbfilter.hlp.h $(VBLIBS) $(CXX) -o vbfilter vbfilter.cpp $(LIBS) $(CXXFLAGS) vbmaskcompare: vbmaskcompare.cpp vbmaskcompare.hlp.h $(VBLIBS) $(CXX) -o vbmaskcompare vbmaskcompare.cpp $(LIBS) $(CXXFLAGS) vbmaskinfo: vbmaskinfo.cpp vbmaskinfo.hlp.h $(VBLIBS) $(CXX) -o vbmaskinfo vbmaskinfo.cpp $(LIBS) $(CXXFLAGS) vboverlap: vboverlap.cpp vboverlap.hlp.h $(VBLIBS) $(CXX) -o vboverlap vboverlap.cpp $(LIBS) $(CXXFLAGS) vbprep: vbprep.cpp vbprep.hlp.h $(VBLIBS) $(CXX) -o vbprep vbprep.cpp $(LIBS) $(CXXFLAGS) vbse: vbse.cpp vbse.hlp.h $(VBLIBS) $(CXX) -o vbse vbse.cpp $(LIBS) $(CXXFLAGS) vbvec2hdr: vbvec2hdr.cpp vbvec2hdr.hlp.h $(VBLIBS) $(CXX) -o vbvec2hdr vbvec2hdr.cpp $(LIBS) $(CXXFLAGS) vecsplit: vecsplit.cpp vecsplit.hlp.h $(VBLIBS) $(CXX) -o vecsplit vecsplit.cpp $(LIBS) $(CXXFLAGS) test: test.cpp $(VBLIBS) $(CXX) -o test test.cpp $(LIBS) $(CXXFLAGS) voxbo-1.8.5~svn1246/munge/calcperf.cpp000066400000000000000000000054641153177201300175330ustar00rootroot00000000000000 // calcperf.cpp // calculate perfusion maps // Copyright (c) 2009 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #include "calcperf.hlp.h" void calcperf_help(); void calcperf_version(); int main(int argc,char *argv[]) { double TR=4000; string maskname; vector filelist; tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; i1) { calcperf_help(); exit(5); } Cube perfmap,wmask; perfmap.ReadFile(filelist[0]); if (!perfmap) { cout << "[E] calcperf: couldn't read " << filelist[0] << endl; exit (100); } wmask.ReadFile(maskname); if (!wmask) { cout << "[E] calcperf: couldn't read " << maskname << endl; exit (101); } if (perfmap.dimx != wmask.dimx || perfmap.dimy != wmask.dimy || perfmap.dimz != wmask.dimz) { cout << "[E] calcperf: volumes have inconsistent dimensions" << endl; exit (102); } double sum=0.0; int cnt=0; for (int i=0; i [] flags: -t specify TR in ms -m specify white matter mask -h show help -v show version notes: None yet. voxbo-1.8.5~svn1246/munge/contrast.hlp000066400000000000000000000030051153177201300175770ustar00rootroot00000000000000 In each VoxBo GLM folder, there is a contrasts.txt file that defines statistical contrasts of interest. You can edit that file manually to define and name which contrasts interest you. A contrast specification just defines how to weight and scale the parameter estimates associated with the covariates of interest for a GLM. In VoxBo programs that take contrasts (e.g., vbstatmap, vbdumpstats, etc), you can specify a contrast either as the name of a constrast that's already defined in your contrasts.txt file or you can just provide the contrast definition you want. The general form for a contrast is: vec 1 0 0 0 0 0 with one value for each covariate of interest. To check the list of covariates of interest for your GLM, run "glminfo glmdir" (where glmdir is the directory containing your glm). Right now you have to edit contrasts.txt manually to specify a new contrast. is whatever name you'd like for the contrast. If you put the specification in contrasts.txt, that name can be used in programs like vbstatmap to select your contrast. is one of the following: t - t value map i - intercept term percent change map beta or rb - raw beta values map f - F value map tp t1 tp1 - p map from a 1-tailed t-test t2 tp2 - p map from a 2-tailed t-test fp - p map for F values tz - Z-transformed t statistics fz - Z map for F values voxbo-1.8.5~svn1246/munge/cub2pngs.cpp000066400000000000000000000042561153177201300174750ustar00rootroot00000000000000 // cub2pngs.cpp // turn a cub file into a directory of PNG files // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #include "cub2pngs.hlp.h" void cub2pngs_help(); int main(int argc,char *argv[]) { tokenlist args; Cube *cub; args.Transfer(argc-1,argv+1); if (args.size() == 0) { cub2pngs_help(); exit(0); } if (args.size() != 2 && args.size() != 3) { cub2pngs_help(); exit(5); } if (args.size() == 2) args.Add(xfilename(args[1])); cub = new Cube; if (cub->ReadFile(args[0])) { printf("cub2pngs: couldn't read cub file %s\n",args[0].c_str()); exit(109); } if (!cub->data_valid) { printf("cub2pngs: couldn't validate cub file %s\n",args[0].c_str()); exit(100); } if (createfullpath(args[1])) { printf("cub2pngs: couldn't find/create containing directory %s.",args(1)); exit(101); } chdir(args(1)); char name[STRINGLEN]; printf("Writing PNG files"); for (int i=0; idimz; i++) { printf("."); fflush(stdout); sprintf(name,"%s%03d.png",args(2),i); if (WritePNG(*cub,i,name)) printf("\ncub2pngs: error writing PNG file %s.\n",name); } printf("done\n"); exit(0); } void cub2pngs_help() { cout << boost::format(myhelp) % vbversion; } voxbo-1.8.5~svn1246/munge/cub2pngs.hlp000066400000000000000000000002021153177201300174610ustar00rootroot00000000000000 VoxBo cub2pngs (v%1%) summary: convert any 3D image to a directory of PNG images usage: cub2pngs [stem] voxbo-1.8.5~svn1246/munge/extractmask.cpp000066400000000000000000000130321153177201300202700ustar00rootroot00000000000000 // extractmask.cpp // extracts a mask from an atlas // Copyright (c) 1998-2004 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbio.h" #include "extractmask.hlp.h" class value { public: double val; int cnt; }; class Extractor { public: Cube original; Cube newcube; int xval,xvflag; void init(tokenlist &args); void Go(); double regioncode(int x,int y,int z); int newdim[3]; }; void Extractor::init(tokenlist &args) { // defaults xvflag=0; newdim[0]=41; newdim[1]=51; newdim[2]=27; newcube.voxsize[0]=3.75; newcube.voxsize[1]=3.75; newcube.voxsize[2]=5.00; newcube.origin[0]=21; newcube.origin[1]=31; newcube.origin[2]=10; original.ReadFile(args[0]); if (args.size()==1) newcube.SetFileName((string)"m"+original.GetFileName()); if (args.size()==2 || args.size()==3) { newcube.SetFileName(args[1]); if (args.size()==3) { xval=strtol(args[2]); xvflag=1; } } if (args.size()==11 || args.size()==12) { newcube.SetFileName(args[1]); newdim[0]=strtol(args[2]); newdim[1]=strtol(args[3]); newdim[2]=strtol(args[4]); newcube.voxsize[0]=strtod(args[5]); newcube.voxsize[1]=strtod(args[6]); newcube.voxsize[2]=strtod(args[7]); newcube.origin[0]=strtol(args[8]); newcube.origin[1]=strtol(args[9]); newcube.origin[2]=strtol(args[10]); if (args.size()==12) { xval=strtol(args[11]); xvflag=1; } } newcube.SetVolume(newdim[0],newdim[1],newdim[2],original.datatype); } void extractmask_help(); int main(int argc,char *argv[]) { tokenlist args; // extent relative to origin and voxel sizes of new file args.Transfer(argc-1,argv+1); if (args.size() < 1) { extractmask_help(); exit(0); } Extractor ee; ee.init(args); // FIXME check for small (close to 0) voxel sizes ee.Go(); exit(0); } void Extractor::Go() { double val; for (int i=0; i valuelist; double x0,x1,y0,y1,z0,z1; int xx0,xx1,yy0,yy1,zz0,zz1; double val; int added; // xyz are the newcube coordinates of the voxel we'd like. subtract // the origin of the new cube and divide by newvox to get that in mm // relative to the origin. x0=(double)(x-newcube.origin[0])*newcube.voxsize[0]; x1=(double)((x+1)-newcube.origin[0])*newcube.voxsize[0]; y0=(double)(y-newcube.origin[1])*newcube.voxsize[1]; y1=(double)((y+1)-newcube.origin[1])*newcube.voxsize[1]; z0=(double)(z-newcube.origin[2])*newcube.voxsize[2]; z1=(double)((z+1)-newcube.origin[2])*newcube.voxsize[2]; // cout << "x: " << x0 << ":" << x1 << endl; // cout << "y: " << y0 << ":" << y1 << endl; // cout << "z: " << z0 << ":" << z1 << endl; // now then divide by oldvox and subtract from original origin to // get original cube voxel. xx0=original.origin[0]+(int)(x0/original.voxsize[0]); xx1=original.origin[0]+(int)(x1/original.voxsize[0]); yy0=original.origin[1]+(int)(y0/original.voxsize[1]); yy1=original.origin[1]+(int)(y1/original.voxsize[1]); zz0=original.origin[2]+(int)(z0/original.voxsize[2]); zz1=original.origin[2]+(int)(z1/original.voxsize[2]); // cout << "coords: " << xx0 << ":" << xx1; // cout << ", " << yy0 << ":" << yy1; // cout << ", " << zz0 << ":" << zz1 << endl; for (int i=xx0; i=original.dimx) continue; for (int j=yy0; j=original.dimy) continue; for (int k=zz0; k=original.dimz) continue; val=original.GetValue(i,j,k); added=0; for (int m=0; m<(int)valuelist.size(); m++) { if (valuelist[m].val==val) { valuelist[m].cnt++; added=1; break; } } if (added==0) { value tmp; tmp.val=val; tmp.cnt=1; valuelist.push_back(tmp); } break; } } } // cout << "voxels: " << (xx1-xx0)*(yy1-yy0)*(zz1-zz0) << " "; // cout << "vals: " << valuelist.size() << " "; int commoncnt=0; double commonval=0.0; for (int i=0; i<(int)valuelist.size(); i++) { if (valuelist[i].cnt > commoncnt) { commonval=valuelist[i].val; commoncnt=valuelist[i].cnt; } } // cout << "common: " << commonval << "(" << commoncnt << ")" << endl; return (commonval); } void extractmask_help() { cout << boost::format(myhelp) % vbversion; } voxbo-1.8.5~svn1246/munge/extractmask.hlp000066400000000000000000000001651153177201300202740ustar00rootroot00000000000000 VoxBo extractmask (v%1%) usage: extractmask takes a whole bunch of arguments try extractmask in.cub out.cub num voxbo-1.8.5~svn1246/munge/fillmask.cpp000066400000000000000000000053431153177201300175520ustar00rootroot00000000000000 // fillmask.cpp // fill in missing slices in a mask (e.g., lesion) // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #include "fillmask.hlp.h" void fillmask_help(); int getsampleslice(int start,int interval,int slice,int dimz); int main(int argc,char *argv[]) { tokenlist args; string infile,outfile; int start,interval,sampleslice; double val; args.Transfer(argc-1,argv+1); if (args.size() == 0) { fillmask_help(); exit(0); } if (args.size() != 4) { fillmask_help(); exit(5); } start=strtol(args[2]); interval=strtol(args[3]); printf("fillmasking %s to %s beginning slice %d and every %d...\n",args(0),args(1),start,interval); infile = args[0]; outfile = args[1]; Cube mycube,newcube; mycube.ReadFile(infile); if (!mycube.data_valid) { printf("\nCouldn't make a valid cube out of %s.\n",infile.c_str()); exit(5); } // cout << mycube.GetFileType() << " " << t_img3d << endl; newcube=mycube; for (int k=0; k=0 && slice-i =0 && slice+i voxbo-1.8.5~svn1246/munge/priority.hlp000066400000000000000000000022601153177201300176250ustar00rootroot00000000000000 Here you will soon find help on setting VoxBo scheduler priorities. Note that priorities are only relevant in cluster mode. A priority can be specified in one of several ways. The simplest is just a single integer from 0 to 5, which specifies a single priority. But you can also use a more complicated specification to get more control over how your jobs run, including the maximum number of jobs that can run at a time and the maximum number of jobs that can run on one machine. Note that jobs at priority 0 will not run at all, no matter what. Here are some examples: 3 run an unlimited number of jobs at priority 3 2 3 run no more than 2 jobs at a time, at priority 3 2 3 0 1 run 2 jobs at pri 3, then unlimited additional jobs at priority 1 (zero means unlimited) 2 3 0 1 2 same as the above, but no more than 2 per server The following shortcuts can also be used: default set to current default offhours set to configuration for off-hours processing nice set to colleague-friendly policy xnice set to very colleague-friendly policy hold set not to run until further notice voxbo-1.8.5~svn1246/munge/setorigin.cpp000066400000000000000000000225271153177201300177560ustar00rootroot00000000000000 // setorigin.cpp // set the origin of one image to correspond to that of another // Copyright (c) 1998-2004 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbutil.h" #include "vbio.h" #include #include #include "setorigin.hlp.h" enum {m_strip,m_center}; int setorigin_map(tokenlist &args); int setorigin_copy(tokenlist &args); int setorigin_new(tokenlist &args,int mode); int setorigin_guess(tokenlist &args); int setorigin_set(tokenlist &args); void setorigin_help(); int main(int argc,char *argv[]) { tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs setorigin_help(); exit(0); } tokenlist args; args.Transfer(argc-1,argv+1); int err; if (args[0]=="-c") err=setorigin_copy(args); else if (args[0]=="-m") err=setorigin_map(args); else if (args[0]=="-g") err=setorigin_guess(args); else if (args[0]=="-s") err=setorigin_new(args,m_strip); else if (args[0]=="-x") err=setorigin_new(args,m_center); else err=setorigin_set(args); exit(err); } int setorigin_set(tokenlist &args) { stringstream tmps; // FIXME maybe handle x,y,z syntax if (args.size() !=4) { setorigin_help(); return(101); } Cube cb; Tes ts; int err=0; float o1=0.0,o2=0.0,o3=0.0; if (args.size()==4) { o1=strtod(args[1]); o2=strtod(args[2]); o3=strtod(args[3]); } if (cb.ReadFile(args[0])==0) { cb.SetOrigin(o1,o2,o3); if (cb.WriteFile()) { printf("[E] setorigin: error writing %s\n",args(0)); err=100; } else { printf("[I] setorigin: origin set for file %s\n",args(0)); } } else if (ts.ReadFile(args[0])==0) { ts.SetOrigin(o1,o2,o3); if (ts.WriteFile()) { printf("[E] setorigin: error writing %s\n",args(0)); err=100; } else { printf("[I] setorigin: origin set for %s\n",args(0)); } } else { tmps.str(""); tmps << "setorigin: couldn't read " << args[0] << " as 3D or 4D data"; printErrorMsg(VB_ERROR,tmps.str()); } return(err); } int setorigin_guess(tokenlist &args) { if (args.size() != 2) { setorigin_help(); return(101); } Cube cb; Tes ts; int err=0; int o1,o2,o3; stringstream tmps; if (cb.ReadFile(args[1])==0) { o1=cb.dimx; o2=cb.dimy; o3=cb.dimz; guessorigin(o1,o2,o3); cb.SetOrigin(o1,o2,o3); if (cb.WriteFile()) { printf("[E] setorigin: error writing %s\n",args(1)); err=100; } else { printf("[I] setorigin: origin set for file %s\n",args(1)); printErrorMsg(VB_INFO,tmps.str()); } } else if (ts.ReadFile(args[1])==0) { o1=ts.dimx; o2=ts.dimy; o3=ts.dimz; guessorigin(o1,o2,o3); ts.SetOrigin(o1,o2,o3); if (ts.WriteFile()) { printf("[E] setorigin: error writing %s\n",args(1)); err=100; } else { printf("[I] setorigin: origin set for %s\n",args(1)); } } return(err); } int setorigin_map(tokenlist &args) { Cube mycube,refcube; stringstream tmps; if (args.size() < 3) { setorigin_help(); return(101); } if (refcube.ReadFile(args[1])) { tmps.str(""); tmps << "setorigin: invalid 3D file " << args[1]; printErrorMsg(VB_ERROR,tmps.str()); exit(5); } if (mycube.ReadFile(args[2])) { tmps.str(""); tmps << "setorigin: invalid 3D file " << args[2]; printErrorMsg(VB_ERROR,tmps.str()); exit(100); } double ourxpos,ourypos,ourzpos; double refxpos,refypos,refzpos; mycube.GetCorner(ourxpos,ourypos,ourzpos); refcube.GetCorner(refxpos,refypos,refzpos); // first do the z, which is complicated int refx=refcube.origin[0]; // for convenience int refy=refcube.origin[1]; int refz=refcube.origin[2]; if (refx==0 && refy==0 && refz==0) { refx=refcube.dimx; refy=refcube.dimy; refz=refcube.dimz; guessorigin(refx,refy,refz); } // first calculate the absolute position of the origin in mm double xposition=refxpos+(refx*refcube.voxsize[0]); double yposition=refypos+(refy*refcube.voxsize[1]); double zposition=refzpos+(refz*refcube.voxsize[2]); tmps.str(""); tmps << "setorigin: x position " << xposition << " refx: " << refx; printErrorMsg(VB_INFO,tmps.str()); tmps.str(""); tmps << "setorigin: y position " << yposition << " refy: " << refy; printErrorMsg(VB_INFO,tmps.str()); tmps.str(""); tmps << "setorigin: z position " << zposition << " refz: " << refz; printErrorMsg(VB_INFO,tmps.str()); // now figure out what voxel that is on the reference brain xposition=(xposition-ourxpos)/mycube.voxsize[0]; yposition=(yposition-ourypos)/mycube.voxsize[1]; zposition=(zposition-ourzpos)/mycube.voxsize[2]; // now do the x and y, which is just a matter of converting voxel // sizes, since we assume the images are aligned mycube.origin[0]=lround(xposition); mycube.origin[1]=lround(yposition); mycube.origin[2]=lround(zposition); int err=mycube.WriteFile(); if (err) { tmps.str(""); tmps << "setorigin: error writing the origin-corrected cube " << mycube.GetFileName(); printErrorMsg(VB_ERROR,tmps.str()); return (102); } else { tmps.str(""); tmps << "setorigin: wrote origin-corrected cube " << mycube.GetFileName(); printErrorMsg(VB_INFO,tmps.str()); return(0); } return (0); } int setorigin_copy(tokenlist &args) { if (args.size() < 3) { setorigin_help(); return(101); } int origin[3],err=0; stringstream tmps; Tes ts; Cube cb; if (ts.ReadFile(args[1])==0) { origin[0]=ts.origin[0]; origin[1]=ts.origin[1]; origin[2]=ts.origin[2]; } else if (cb.ReadFile(args[1])==0) { origin[0]=cb.origin[0]; origin[1]=cb.origin[1]; origin[2]=cb.origin[2]; } else { printf("[E] setorigin: data must be in a recognized 3D or 4D format\n"); exit(10); } for (size_t i=2; itfiletypes=EligibleFileTypes(args[i]); if (ts.ReadFile(args[i])==0) { ts.origin[0]=origin[0]; ts.origin[1]=origin[1]; ts.origin[2]=origin[2]; if (ts.WriteFile()) { tmps.str(""); tmps << "setorigin: error writing to 4D image " << args[i]; printErrorMsg(VB_ERROR,tmps.str()); } else { tmps.str(""); tmps << "setorigin: copied origin to 4D image " << args[i]; printErrorMsg(VB_INFO,tmps.str()); } } else if (cb.ReadFile(args[i])==0) { cb.origin[0]=origin[0]; cb.origin[1]=origin[1]; cb.origin[2]=origin[2]; if (cb.WriteFile()) { tmps.str(""); tmps << "setorigin: error writing to 3D image " << args[i]; printErrorMsg(VB_ERROR,tmps.str()); } else { tmps.str(""); tmps << "setorigin: copied origin to 3D image " << args[i]; printErrorMsg(VB_INFO,tmps.str()); } } else { tmps.str(""); tmps << "setorigin: file " << args[i] << " is not a recognized 3D or 4D file type"; printErrorMsg(VB_ERROR,tmps.str()); err=190; } } return(err); } int setorigin_new(tokenlist &args,int mode) { if (args.size() < 2) { setorigin_help(); return(101); } Cube cb; Tes ts; int err=0; stringstream tmps; for (size_t i=1; i set the origin of A to x,y,z setorigin -g A guesstimate the origin for A setorigin -m A B maps the origin of A onto B setorigin -c A B [C ...] copies the origin from A to B, C, ... setorigin -s A [B ...] strips the origin from A, B, ... setorigin -x A [B ...] sets the origin to the dead center for A, B, ... notes: setorigin will set non-integer origins for nifti files only voxbo-1.8.5~svn1246/munge/sumrfx.cpp000066400000000000000000000163231153177201300172740ustar00rootroot00000000000000 // sumrfx.cpp // do some simple things with 4D rfx volumes // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "sumrfx.hlp.h" int process_singlemask(vector &rlist,string fname); int process_multimask(vector &rlist,string fname); void do_sumcube(string fname,int index,Cube &mycube,Cube &mask,double thresh,vector &rlist); void do_sumrfx(const string &fname,const string &mname,double thresh,vector &rlist); void sumrfx_help(); int detailflag=0; int compareflag=0; int nozeroflag=0; int main(int argc,char *argv[]) { tokenlist args; double thresh=0.0; string maskfile; string datafile; vector singlemasklist; vector multimasklist; args.Transfer(argc-1,argv+1); if (args.size() == 0) { sumrfx_help(); exit(0); } for (size_t i=0; i rlist; for (size_t i=0; i &rlist,string fname) { Cube mask; if (mask.ReadFile(fname)) { return 101; } VBRegion reg; reg=findregion_mask(mask,vb_gt,0.0); reg.name=xfilename(fname); if (!(reg.voxels.size())) return 102; rlist.push_back(reg); return 0; } int process_multimask(vector &rlist,string fname) { Cube mask; tokenlist args; if (mask.ReadFile(fname)) { return 101; } for (int i=0; i<(int)mask.header.size(); i++) { args.ParseLine(mask.header[i]); if (args[0]!="vb_maskspec:") continue; int value=strtol(args[1]); VBRegion reg; reg=findregion_mask(mask,vb_eq,(double)value); if (reg.voxels.size()) rlist.push_back(reg); } return 0; } void do_sumrfx(const string &fname,const string &mname,double thresh,vector &rlist) { int i,j,k; Tes rfx; Cube mask; rfx.ReadFile(fname); if (!rfx.data_valid) { printf("sumrfx: invalid 4D file %s.\n",fname.c_str()); return; } // specified mask, intersect with tes mask if (mname.size()) { mask.ReadFile(mname); for (i=0; i &rlist) { Cube tmpmask=mask; int i,j,k; printf("%s-%02d\n",fname.c_str(),index); // eliminate from mask any sub-threshold voxels for (i=0; i regionlist; regionlist=findregions(tmpmask,vb_gt,0.0); // now that we have a list of regions we can go through them and produce some stats double grandsum=0.0; double val; int grandcnt=0; for (i=0; i<(int)regionlist.size(); i++) { double sum=0.0,x=0.0,y=0.0,z=0.0; int cnt=0; for (VI myvox=regionlist[i].begin(); myvox!=regionlist[i].end(); myvox++) { if (val==0.0 && nozeroflag) continue; sum+=val; grandsum+=val; x+=myvox->second.x; y+=myvox->second.y; z+=myvox->second.z; cnt++; grandcnt++; } if (detailflag) printf(" region %d: %d voxels, mean %.2f (%d,%d,%d)\n",i,cnt,sum/(double)cnt, (int)x/cnt,(int)y/cnt,(int)z/cnt); } printf(" sum: %.3f count: %d average(sum/cnt): %.6f\n",grandsum,grandcnt,grandsum/(double)grandcnt); // now do the region comparisons if (rlist.size()) { // build a vb_vector for each regionlist vector myvecs; for (i=0; i<(int)rlist.size(); i++) { vector vals; for (VI myvox=rlist[i].begin(); myvox!=rlist[i].end(); myvox++) { val=mycube.GetValue(myvox->second.x,myvox->second.y,myvox->second.z); if (val==0.0 && nozeroflag) continue; if (valReadFile(args[0])) { tmps.str(""); tmps << "tes2cub: couldn't read tes file " << args[0]; printErrorMsg(VB_ERROR,tmps.str()); exit(5); } if (!tes->data_valid) { tmps.str(""); tmps << "tes2cub: tes file " << args[0] << "isn't valid."; printErrorMsg(VB_ERROR,tmps.str()); exit(5); } if (ind > tes->dimt) { tmps.str(""); tmps << "tes2cub: index (" << ind << ") is beyond the last image (" << tes->dimt << ")."; printErrorMsg(VB_ERROR,tmps.str()); exit(5); } cub = new Cube((*tes)[ind]); if (!cub->data_valid) { tmps.str(""); tmps << "tes2cub: error extracting the cube from the 4D file (shouldn't happen!)."; printErrorMsg(VB_ERROR,tmps.str()); exit(5); } if (!cub->WriteFile(args[1])) { tmps.str(""); tmps << "tes2cub: wrote cube " << ind << " to file " << args[1] << "."; printErrorMsg(VB_INFO,tmps.str()); exit(0); } else { tmps.str(""); tmps << "tes2cub: failed to write extracted cube to file " << args[1] << "."; printErrorMsg(VB_INFO,tmps.str()); exit(5); } exit(0); } void tes2cub_help() { cout << boost::format(myhelp) % vbversion; } voxbo-1.8.5~svn1246/munge/tes2cub.hlp000066400000000000000000000001061153177201300173100ustar00rootroot00000000000000 VoxBo tes2cub (v%1%) usage: tes2cub [imagenum] voxbo-1.8.5~svn1246/munge/vb2cub.cpp000066400000000000000000000056441153177201300171370ustar00rootroot00000000000000 // vb2cub.cpp // convert arbitrary 3D data to VoxBo CUB1 // Copyright (c) 1998-2004 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vb2cub.hlp.h" void vb2cub_help(); void vb2cub_version(); int main(int argc,char *argv[]) { if (argc==1) { vb2cub_help(); exit(0); } tokenlist args; string infile,outfile; int floatflag=0,nanflag=1; arghandler ah; string errstr; ah.setArgs("-f","--nofloat",0); ah.setArgs("-n","--nonan",0); ah.setArgs("-h","--help",0); ah.setArgs("-v","--version",0); ah.parseArgs(argc,argv); if ((errstr=ah.badArg()).size()) { printf("[E] vb2cub: %s\n",errstr.c_str()); exit(10); } if (ah.flagPresent("-h")) { vb2cub_help(); exit(0); } if (ah.flagPresent("-v")) { vb2cub_version(); exit(0); } tokenlist filelist=ah.getUnflaggedArgs(); if (filelist.size()!=2) { printf("[E] vb2cub: requires an input and an output file\n"); exit(10); } if (ah.flagPresent("-f")) floatflag=1; if (ah.flagPresent("-n")) nanflag=1; infile = filelist[0]; outfile = filelist[1]; printf("[I] vb2cub: converting %s to %s\n",infile.c_str(),outfile.c_str()); Cube mycube; mycube.ReadFile(infile); if (!(mycube.data_valid)) { printf("[E] vb2cub: couldn't make a valid cube out of %s\n",infile.c_str()); exit(5); } // remove NaNs if requested if (nanflag) mycube.removenans(); // convert to float if requested if (floatflag && mycube.datatype != vb_float) mycube.convert_type(vb_float,VBSETALT|VBNOSCALE); if (mycube.SetFileFormat("cub1")) { printf("[E] vb2cub: file format cub1 not available\n"); exit (106); } mycube.SetFileName(outfile); if (mycube.WriteFile()) { printf("[E] vb2cub: error writing file %s\n",outfile.c_str()); exit(110); } else printf("[I] vb2cub: done.\n"); exit(0); } void vb2cub_help() { cout << boost::format(myhelp) % vbversion; } void vb2cub_version() { printf("VoxBo vb2cub (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vb2cub.hlp000066400000000000000000000003451153177201300171310ustar00rootroot00000000000000 VoxBo vb2cub (v%1%) usage: vb2cub [] <3D file/dir> flags: -f convert to floating point -n replace NaNs and Infs with zeros -h show help -v show version voxbo-1.8.5~svn1246/munge/vb2img.cpp000066400000000000000000000063231153177201300171350ustar00rootroot00000000000000 // vb2img.cpp // convert arbitrary 3D data to ANALYZE(tm) (aka .img) format // Copyright (c) 1998-2004 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vb2img.hlp.h" void vb2img_help(); void vb2img_version(); int main(int argc,char *argv[]) { if (argc==1) { vb2img_help(); exit(0); } string infile,outfile; struct stat st; int floatflag=0,nanflag=1,err; arghandler ah; string errstr; ah.setArgs("-f","--nofloat",0); ah.setArgs("-n","--nonan",0); ah.setArgs("-h","--help",0); ah.setArgs("-v","--version",0); ah.parseArgs(argc,argv); if ((errstr=ah.badArg()).size()) { printf("[E] vb2img: %s\n",errstr.c_str()); exit(10); } if (ah.flagPresent("-h")) { vb2img_help(); exit(0); } if (ah.flagPresent("-v")) { vb2img_version(); exit(0); } tokenlist filelist=ah.getUnflaggedArgs(); if (filelist.size()!=2) { printf("[E] vb2img: requires an input and an output file\n"); exit(10); } if (ah.flagPresent("-f")) floatflag=1; if (ah.flagPresent("-n")) nanflag=1; infile = filelist[0]; outfile = filelist[1]; printf("[I] vb2img: converting file %s to %s\n",infile.c_str(),outfile.c_str()); if (stat(infile.c_str(),&st)) { printf("[E] vb2img: couldn't find input file %s.\n",infile.c_str()); exit(5); } Cube mycube; if ((err=mycube.ReadFile(infile.c_str()))) { printf("[E] vb2img: couldn't read file %s as 3D data (err %d)\n", infile.c_str(),err); exit(5); } if (!mycube.data_valid) { printf("[E] vb2img: couldn't extract valid 3D data from file %s.\n",infile.c_str()); exit(5); } // remove NaNs if requested if (nanflag) mycube.removenans(); // convert to float if requested if (floatflag && mycube.datatype != vb_float) mycube.convert_type(vb_float,VBSETALT|VBNOSCALE); if (mycube.SetFileFormat("img3d")) { printf("[E] vb2img: file format img1 not available\n"); exit (106); } mycube.SetFileName(outfile); if (mycube.WriteFile()) { printf("[E] vb2img: error writing file %s\n",outfile.c_str()); exit(110); } else printf("[I] vb2img: done.\n"); exit(0); } void vb2img_help() { cout << boost::format(myhelp) % vbversion; } void vb2img_version() { printf("VoxBo vb2img (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vb2img.hlp000066400000000000000000000003451153177201300171340ustar00rootroot00000000000000 VoxBo vb2img (v%1%) usage: vb2img [] <3D file/dir> flags: -f convert to floating point -n replace NaNs and Infs with zeros -h show help -v show version voxbo-1.8.5~svn1246/munge/vb2imgs.cpp000066400000000000000000000054701153177201300173220ustar00rootroot00000000000000 // vb2imgs.cpp // convert arbitrary 4D data to a directory of ANALYZE(tm) files // Copyright (c) 1998-2004 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vb2imgs.hlp.h" void vb2imgs_help(); void vb2imgs_version(); int main(int argc,char *argv[]) { if (argc==1) { vb2imgs_help(); exit(0); } string prefix; int err,floatflag=0,nanflag=0; tokenlist args; arghandler ah; string errstr; ah.setArgs("-p","--prefix",1); ah.setArgs("-f","--nofloat",0); ah.setArgs("-n","--nonan",0); ah.setArgs("-h","--help",0); ah.setArgs("-v","--version",0); ah.parseArgs(argc,argv); if ((errstr=ah.badArg()).size()) { cout << "[E] vb2imgs: " << errstr << endl; exit(10); } if (ah.flagPresent("-h")) { vb2imgs_help(); exit(0); } if (ah.flagPresent("-v")) { vb2imgs_version(); exit(0); } if (ah.flagPresent("-f")) floatflag=1; args=ah.getFlaggedArgs("-p"); if (args.size()==1) { prefix=args[0]; exit(0); } args=ah.getUnflaggedArgs(); printf("[I] vb2imgs: converting %s to an img directory\n",args(0)); Tes mytes; mytes.ReadFile(args[0]); if (!mytes.data_valid) { printf("[E] vb2imgs: couldn't read input file %s\n",args(0)); exit(5); } // remove NaNs and Infs if requested if (nanflag) mytes.removenans(); // convert to float if requested if (floatflag && mytes.datatype != vb_float) mytes.convert_type(vb_float,VBSETALT|VBNOSCALE); err=mytes.SetFileFormat("imgdir"); // FIXME should probably check err mytes.SetFileName(args[1]); mytes.ReparseFileName(); err=mytes.WriteFile(); if (err) { printf("[E] vb2imgs: done, but there were errors writing files.\n"); } else { printf("[I] vb2imgs: done.\n"); } } void vb2imgs_help() { cout << boost::format(myhelp) % vbversion; } void vb2imgs_version() { printf("VoxBo vb2imgs (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vb2imgs.hlp000066400000000000000000000004151153177201300173150ustar00rootroot00000000000000 VoxBo vb2imgs (v%1%) usage: vb2imgs <4D file/dir> flags: -p prefix for output files -f convert to floating point -f replace NaNs and Infs with zeros -h show help -v show version voxbo-1.8.5~svn1246/munge/vb2tes.cpp000066400000000000000000000134031153177201300171510ustar00rootroot00000000000000 // vb2tes.cpp // convert 4D data to 4D file in supported formats (not just TES1) // Copyright (c) 1998-2007 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vb2tes.hlp.h" void vb2tes_help(); void vb2tes_version(); void read_multifile_pat(Tes &tes,string infile); void read_multifile_list(Tes &tes,tokenlist &filelist); int main(int argc,char *argv[]) { if (argc==1) { vb2tes_help(); exit(0); } tokenlist args; string infile,outfile; setincludeset,excludeset; int floatflag=0,nanflag=0,multiflag=0; arghandler ah; string errstr; ah.setArgs("-i","--include",1); ah.setArgs("-e","--exclude",1); ah.setArgs("-f","--nofloat",0); ah.setArgs("-m","--multi",1); ah.setArgs("-n","--nonan",0); ah.setArgs("-h","--help",0); ah.setArgs("-v","--version",0); ah.parseArgs(argc,argv); if ((errstr=ah.badArg()).size()) { printf("[E] vb2tes: %s\n",errstr.c_str()); exit(10); } if (ah.flagPresent("-h")) { vb2tes_help(); exit(0); } if (ah.flagPresent("-v")) { vb2tes_version(); exit(0); } tokenlist filelist=ah.getUnflaggedArgs(); if (ah.flagPresent("-f")) floatflag=1; if (ah.flagPresent("-n")) nanflag=1; args=ah.getFlaggedArgs("-i"); if (args.size()) includeset=numberset(args[0]); args=ah.getFlaggedArgs("-e"); if (args.size()) excludeset=numberset(args[0]); args=ah.getFlaggedArgs("-m"); if (args.size()) { multiflag=1; outfile=args[0]; } if (filelist.size()!=2 && !multiflag) { printf("[E] vb2tes: requires an input and an output file\n"); exit(10); } if (multiflag) { printf("[I] vb2tes: converting %s to TES file %s\n",infile.c_str(),outfile.c_str()); } else { infile = filelist[0]; outfile = filelist[1]; printf("[I] vb2tes: converting %s to TES file %s\n",infile.c_str(),outfile.c_str()); } Tes mytes; if (multiflag) { read_multifile_list(mytes,filelist); } else { if (mytes.ReadFile(infile)) { Cube mycube; if (!mycube.ReadFile(infile)) { mytes.SetVolume(mycube.dimx,mycube.dimy,mycube.dimz,1,mycube.datatype); mytes.SetCube(0,mycube); mytes.header=mycube.header; mytes.data_valid=1; } } if (!mytes.data_valid) read_multifile_pat(mytes,infile); } if (!mytes.data_valid) { printf("[E] vb2tes: couldn't read 3D or 4D data from input\n"); exit(5); } // merge include and exclude lists into just an include list if (includeset.size() && excludeset.size()) { for (set::iterator i=excludeset.begin(); i!=excludeset.end(); i++) includeset.erase(*i); excludeset.clear(); } if (includeset.size()) mytes.resizeInclude(includeset); if (excludeset.size()) mytes.resizeExclude(excludeset); // remove NaNs and Infs if requested if (nanflag) mytes.removenans(); // convert to float if requested if (floatflag && mytes.datatype != vb_float) mytes.convert_type(vb_float,VBSETALT|VBNOSCALE); mytes.fileformat=VBFF(); if (mytes.WriteFile(outfile)) { printf("[E] vb2tes: error writing file %s\n",outfile.c_str()); exit(110); } else printf("[I] vb2tes: done.\n"); exit(0); } void read_multifile_pat(Tes &tes,string infile) { struct stat st; string pat; int dims_set=0,ind=0; if (!(stat(infile.c_str(),&st))) { if (S_ISDIR(st.st_mode)) pat=infile+"/*"; } else pat=infile+"*"; vglob vg(pat); if (vg.size()<1) return; tokenlist fnames; for (size_t i=0; i [] flags: -i include only these volumes -e exclude these volumes -m multifile mode, writes to outfile -f convert to floating point -n replace NaNs and Infs with zeros notes: for the -i and -e flags, you can specify a list of numbers as a list range, or combination as follows: 1,3,5,7,9 or 32-45 or 0,1,2,7-10 voxbo-1.8.5~svn1246/munge/vb2vmp.cpp000066400000000000000000000062141153177201300171620ustar00rootroot00000000000000 // vb2vmp.cpp // convert arbitrary 3D data to BrainVoyager(tm) vmp format // Copyright (c) 2005 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vb2vmp.hlp.h" void vb2vmp_help(); void vb2vmp_version(); int main(int argc,char *argv[]) { if (argc==1) { vb2vmp_help(); exit(0); } string infile,outfile; struct stat st; int nanflag=1; arghandler ah; string errstr; ah.setArgs("-n","--nonan",0); ah.setArgs("-h","--help",0); ah.setArgs("-v","--version",0); ah.parseArgs(argc,argv); if ((errstr=ah.badArg()).size()) { printf("[E] vb2vmp: %s\n",errstr.c_str()); exit(10); } if (ah.flagPresent("-h")) { vb2vmp_help(); exit(0); } if (ah.flagPresent("-v")) { vb2vmp_version(); exit(0); } tokenlist filelist=ah.getUnflaggedArgs(); if (filelist.size()!=2) { printf("[E] vb2vmp: requires an input and an output file\n"); exit(10); } if (ah.flagPresent("-n")) nanflag=1; infile = filelist[0]; outfile = filelist[1]; printf("[I] vb2vmp: converting %s to %s\n",infile.c_str(),outfile.c_str()); printf("[I] vb2vmp: converting file %s to %s\n",infile.c_str(),outfile.c_str()); if (stat(infile.c_str(),&st)) { printf("[E] vb2vmp: couldn't find input file %s.\n",infile.c_str()); exit(5); } Cube mycube; if (mycube.ReadFile(infile.c_str())) { printf("[E] vb2vmp: couldn't read file %s as 3D data\n",infile.c_str()); exit(5); } if (!mycube.data_valid) { printf("[E] vb2vmp: couldn't extract valid 3D data from file %s.\n",infile.c_str()); exit(5); } // remove NaNs if requested if (nanflag) mycube.removenans(); // convert to float if requested if (mycube.datatype != vb_float) mycube.convert_type(vb_float,VBSETALT|VBNOSCALE); if (mycube.SetFileFormat("vmp")) { printf("[E] vb2vmp: file format vmp not available\n"); exit (106); } mycube.SetFileName(outfile); if (mycube.WriteFile()) { printf("[E] vb2vmp: error writing file %s\n",outfile.c_str()); exit(110); } else printf("[I] vb2vmp: done.\n"); exit(0); } void vb2vmp_help() { cout << boost::format(myhelp) % vbversion; } void vb2vmp_version() { printf("VoxBo vb2vmp (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vb2vmp.hlp000066400000000000000000000002721153177201300171610ustar00rootroot00000000000000 VoxBo vb2vmp (v%1%) usage: vb2vmp [] <3D file/dir> flags: -n replace NaNs and Infs with zeros -h show help -v show version voxbo-1.8.5~svn1246/munge/vbbatch.cpp000066400000000000000000000241341153177201300173600ustar00rootroot00000000000000 // vbbatch.cpp // queue up jobs that execute a command multiple times with different files or dirs // Copyright (c) 2004-2010 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include #include #include "vbutil.h" #include "vbjobspec.h" #include "vbprefs.h" #include "vbio.h" #include "vbx.h" #include "vbbatch.hlp.h" void vbbatch_help(); void vbbatch_version(); typedef list::iterator LSI; class BatchConfig { public: list filelist; void Run(tokenlist &args); void CreateBatch(); string command; string dirname; // directory (for tmp files, tes and cov) string varstring; // "FILE" by default string basestring; // "BASE" by default string indstring; // "IND" by default string logdir; bool validate; bool interactive; bool usex; bool emailflag; string sname,jname; map reqs; // requirements VBSequence seq; int Ask(string str); void ShowCommandLines(); }; VBPrefs vbp; int main(int argc,char *argv[]) { tokenlist args; vbp.init(); vbp.read_jobtypes(); args.Transfer(argc-1,argv+1); if (args.size() == 0) { vbbatch_help(); exit(0); } BatchConfig bc; bc.seq.source="["+xgetcwd()+"] "+xcmdline(argc,argv); bc.Run(args); exit(0); } void BatchConfig::Run(tokenlist &args) { dirname="/tmp"; emailflag=1; interactive=0; validate=1; usex=0; varstring="FILE"; basestring="BASE"; indstring="IND"; seq.init(); seq.email=vbp.email; seq.priority.maxjobs=10; seq.seqnum=100; int f_run=vbp.cores; int flushflag=0; int appendflag=0; int submitflag=0; usex=0; string seqname,seqdir; sname="vbbatch sequence"; jname="vbbatch job"; struct stat st; for (size_t i=0; ifirst; CreateBatch(); seq.renumber(highest+1); char tmpname[STRINGLEN]; for (SMI jj=seq.specmap.begin(); jj!=seq.specmap.end(); jj++) { sprintf(tmpname,"%s/%05d.job",seqdir.c_str(),jj->first); if (jj->second.Write(tmpname)) { printf("[E] vbbatch: there was an error appending your new jobs\n"); exit(10); } } printf("[I] vbbatch: %d jobs have been appended to sequence %s\n",(int)seq.specmap.size(),seqname.c_str()); exit(0); } else if (submitflag) { VBSequence seq(seqdir); seq.name=seqname; if (seq.specmap.size()==0) { printf("[E] vbbatch: invalid or empty sequence %s\n",seqname.c_str()); exit(11); } // add a notify job if needed if (emailflag && seq.email.size()) { VBJobSpec js; js.init(); js.jobtype="notify"; js.dirname=dirname; js.arguments["email"]=seq.email; js.arguments["msg"]="Your commands have been run."; js.name="Notify"; js.logdir=logdir; js.jnum=0; for (SMI jj=seq.specmap.begin(); jj!=seq.specmap.end(); jj++) { js.waitfor.insert(jj->second.jnum); if (jj->second.jnum>=js.jnum) js.jnum=jj->second.jnum+1; } seq.specmap[js.jnum]=js; } if (f_run) { runseq(vbp,seq,f_run); // QRunSeq qr; // qr.Go(vbp,seq,f_run); // qr.exec(); } else { vbreturn ret(0,""); if ((ret=seq.Submit(vbp))) { printf("[E] vbbatch: %s\n",ret.message().c_str()); exit(11); } printf("[I] vbbatch: %s\n",ret.message().c_str()); } rmdir_force(seqdir); exit(0); } if (validate) ShowCommandLines(); else { CreateBatch(); if (f_run) { runseq(vbp,seq,f_run); // QRunSeq qr; // qr.Go(vbp,seq,f_run); // qr.exec(); } else { vbreturn ret(0,""); if ((ret=seq.Submit(vbp))) { printf("[E] vbbatch: %s\n",ret.message().c_str()); exit(11); } printf("[I] vbbatch: %s\n",ret.message().c_str()); } } } void BatchConfig::ShowCommandLines() { string cline; char tmps[64]; printf("[I] vbbatch: the following command lines were generated:\n"); int i=0; for (LSI ff=filelist.begin(); ff!=filelist.end(); ff++) { cline=command; replace_string(cline,varstring,*ff); replace_string(cline,basestring,xsetextension(*ff,"",1)); sprintf(tmps,"%05d",i++); replace_string(cline,indstring,tmps); printf(" %s\n",cline.c_str()); } } void BatchConfig::CreateBatch() { VBJobSpec js; int jobnum=0; set jlist; string cline; string full_jname; char buf[1024]; int i=-1; for (LSI ff=filelist.begin(); ff!=filelist.end(); ff++) { i++; if (interactive) { if (!Ask(*ff)) continue; } js.init(); js.name="vbbatch cmd"; js.jobtype="shellcommand"; js.dirname=xgetcwd(); js.logdir=logdir; cline=command; full_jname=jname; replace_string(cline,varstring,*ff); replace_string(full_jname,varstring,*ff); replace_string(cline,basestring,xsetextension(*ff,"",1)); replace_string(full_jname,basestring,xsetextension(*ff,"",1)); sprintf(buf,"%05d",i); replace_string(cline,indstring,buf); replace_string(full_jname,indstring,buf); js.arguments["command"]=cline; js.name=full_jname; jlist.insert(jobnum); js.jnum=jobnum; jobnum++; seq.addJob(js); } // notify? if (emailflag && seq.email.size()) { js.init(); js.jobtype="notify"; js.dirname=dirname; js.logdir=logdir; js.arguments["email"]=seq.email; js.arguments["msg"]="Your commands have been run."; js.name="Notify"; js.waitfor=jlist; js.jnum=jobnum++; seq.addJob(js); } } int BatchConfig::Ask(string fname) { termios tsave,tnew; tcgetattr(0,&tsave); tcgetattr(0,&tnew); tnew.c_lflag&=~(ICANON|ECHO); tcsetattr(0,TCSADRAIN,&tnew); string str; cout << "include " << fname << "? " << flush; str=cin.get(); tcsetattr(0,TCSADRAIN,&tsave); if (str[0]=='y' || str[0]=='Y') { cout << "yes" << endl; return 1; } else { cout << "no" << endl; return 0; } } void vbbatch_help() { cout << boost::format(myhelp) % vbversion; } void vbbatch_version() { printf("VoxBo vbbatch (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vbbatch.hlp000066400000000000000000000056071153177201300173650ustar00rootroot00000000000000 VoxBo vbbatch (v%1%) usage: vbbatch -c [ ...] flags: -c "command" command line to execute (should be in quotes) -p set job priority -xfile use str instead of FILE -xind use str instead of IND -xbase use str instead of BASE -m maximum number of concurrent jobs at full priority -r really run it, don't just show the commands -req add a requirement (you'll know if you need it) -i interactive mode (ask for each file) -d add a bunch of dummy files (see below) -sn sequence name visible in queue -jn job names visible in queue (can use FILE, IND) -f flush private sequence -a append to private sequence -s submit private sequence -l directory for storing log files (will be created if necessary) -e address for notification, use -- for no email --run= don't queue, run now on n cores # -g use graphical progress monitor -h show help -v show version notes: In your command, the token FILE will be replaced with each file you specify. The token BASE will be replaced with each filename, but with the extension stripped off. The token IND will be replaced with an index, starting from 000. If you actually need the tokens FILE, IND, or BASE in your command, you can change what vbbatch replaces using the -xfile, -xind, and -xbase flags. maxjobs defaults to 10 The -f, -a, and -s options allow you to build a compound batch job in pieces, and then to submit the whole thing as one sequence. Use -f to first flush it (just in case), then call vbbatch as you normally would, but use -a to append the jobs to your private sequence, and finally use -s to submit the whole thing. The -r flag is there to encourage you to check the generated command lines before you really submit. Run vbbatch without it, and you'll see all the commands that will be run. If you like what you see, run it again with -r. The -p flag can take a numeric priority from 0 to 5 or a scheduling policy (run vbtool pri for more info). If --run is specified without =n, the default is the total number of available cores minus 1 (or 1, if that would be 0). Note that even if you use --run, you still have to include the -r flag to indicate you really want to run the jobs, not just see them. The -d flag lets you create "dummy" files, with the filenames just being the numbers from 0 to n-1. Usually you would use it with IND, not FILE. examples: Run myscript.sh on all your subjects' Anatomy directories: vbbatch -c "myscript.sh FILE" study*/sub*/Anatomy -r Run myperms.sh 1000 times at low priority, with different output files: vbbatch -c "myperms.sh results_IND.nii.gz" -d 1000 -r -p xnice voxbo-1.8.5~svn1246/munge/vbcmp.cpp000066400000000000000000000165341153177201300170630ustar00rootroot00000000000000 // vbcmp.cpp // compare 3d and 4d files, data only // Copyright (c) 1998-2011 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include "vbutil.h" #include "vbio.h" #include "vbcmp.hlp.h" using namespace std; void vbcmp_help(); void vbcmp_version(); void cmp1d(VB_Vector &v1,VB_Vector &v2); void cmp2d(VBMatrix &mat1,VBMatrix &mat2); void cmp3d(Cube &c1,Cube &c2); void cmp4d(Tes &t1,Tes &t2); int main(int argc,char *argv[]) { tokenlist args; string infile,outfile; args.Transfer(argc-1,argv+1); if (args.size() == 0) { vbcmp_help(); exit(0); } if (args.size() != 2) { vbcmp_help(); exit(5); } int err1,err2; Cube cb1,cb2; err1=cb1.ReadFile(args[0]); err2=cb2.ReadFile(args[1]); if (!err1 && !err2) { cmp3d(cb1,cb2); exit(0); } Tes ts1,ts2; err1=ts1.ReadFile(args[0]); err2=ts2.ReadFile(args[1]); if (!err1 && !err2) { cmp4d(ts1,ts2); exit(0); } // try vectors before matrices, because all vectors are matrices VB_Vector v1,v2; err1=v1.ReadFile(args[0]); err2=v2.ReadFile(args[1]); if (!err1 && !err2) { cmp1d(v1,v2); exit(0); } VBMatrix m1,m2; err1=m1.ReadFile(args[0]); err2=m2.ReadFile(args[1]); if (!err1 && !err2) { cmp2d(m1,m2); exit(0); } printf("[E] vbcmp: couldn't read both volumes as same type\n"); exit(100); } void cmp1d(VB_Vector &v1,VB_Vector &v2) { if (v1.size()!=v2.size()) { printf("[E] vbcmp: matrices have different row count\n"); return; } int diffs_all=0; double totals_all=0.0,max_all=0.0; double diff; for (uint32 i=0; imax_all) max_all=diff; } if (diffs_all) totals_all/=(double)diffs_all; if (diffs_all==0) printf("[I] vbcmp: vectors are identical\n"); else { printf("[I] vbcmp: %d total elements\n",(int)v1.size()); printf("[I] vbcmp: total: %d different elements, mean abs diff %g, max diff %g\n",diffs_all,totals_all,max_all); printf("[I] vbcmp: correlation between vectors (Pearson's r) is: %g\n",correlation(v1,v2)); } } // the below should be kept in sync with similar code in vbmm2.cpp void cmp2d(VBMatrix &mat1,VBMatrix &mat2) { if (mat1.m!=mat2.m) { printf("[E] vbcmp: matrices have different row count\n"); return; } if (mat1.n!=mat2.n) { printf("[E] vbcmp: matrices have different column count\n"); return; } int diffs_all=0,diffs_diag=0,diffs_off=0; double totals_all=0.0,totals_diag=0.0,totals_off=0.0; double max_all=0.0,max_diag=0.0,max_off=0.0; double diff; for (uint32 i=0; imax_all) max_all=diff; if (i==j) { diffs_diag++; totals_diag+=diff; if (diff>max_diag) max_diag=diff; } else { diffs_off++; totals_off+=diff; if (diff>max_off) max_off=diff; } } } if (diffs_all) totals_all/=(double)diffs_all; if (diffs_diag) totals_diag/=(double)diffs_diag; if (diffs_off) totals_off/=(double)diffs_off; if (diffs_all==0) printf("[I] vbcmp: matrices are identical\n"); else { printf("[I] vbcmp: out of %d total cells:\n",mat1.m*mat1.n); printf("[I] vbcmp: total: %d different cells, mean abs diff %g, max diff %g\n",diffs_all,totals_all,max_all); if (mat1.m==mat1.n) { printf("[I] vbcmp: diagonal: %d different cells, mean abs diff %g, max diff %g\n",diffs_diag,totals_diag,max_diag); printf("[I] vbcmp: off-diag: %d different cells, mean abs diff %g, max diff %g\n",diffs_off,totals_off,max_off); } } } void cmp3d(Cube &c1,Cube &c2) { if (c1.dimx != c2.dimx || c1.dimy != c2.dimy || c1.dimz != c2.dimz) { printf("[I] vbcmp: dimensions don't match, can't compare.\n"); return; } double totaldiff,maxdiff=0.0,v1,v2,diff; int32 diffcount,voxelcount; int i,j,k; diffcount=0; totaldiff=0.0; int maxx=0,maxy=0,maxz=0; voxelcount=c1.dimx * c1.dimy * c1.dimz; for (i=0; imaxdiff) { maxdiff=diff; maxx=i; maxy=j; maxz=k; } } } } } if (!diffcount) { printf("[I] vbcmp: the data are identical\n"); } else { cout << format("[I] vbcmp: different voxels: %ld of %ld (%.0f%%)\n") % diffcount % voxelcount % ((diffcount*100.0)/voxelcount); cout << format("[I] vbcmp: mean difference: %.8f\n") % (totaldiff/diffcount); cout << format("[I] vbcmp: max difference: %.8f (%d,%d,%d)\n") % maxdiff % maxx % maxy % maxz; } exit(0); } void cmp4d(Tes &t1,Tes &t2) { if (t1.dimx != t2.dimx || t1.dimy != t2.dimy || t1.dimz != t2.dimz || t1.dimt != t2.dimt) { cout << format("[I] vbcmp: dimensions don't match, can't compare.\n"); return; } double totaldiff,maxdiff=0.0,v1,v2,diff; long diffcount,voxelcount; int i,j,k,m,voldiff; int differingvolumes=0; diffcount=0; totaldiff=0.0; voxelcount=t1.dimx * t1.dimy * t1.dimz * t1.dimt; for (m=0; mmaxdiff) maxdiff=diff; } } } } if (voldiff) differingvolumes++; } if (!diffcount) { printf("[I] vbcmp: the data are identical.\n"); } else { printf("[I] vbcmp: different voxels: %ld of %ld (%.0f%%)\n",diffcount,voxelcount, (double)(diffcount*100.0)/voxelcount); printf("[I] vbcmp: mean difference: %.8f\n",totaldiff/diffcount); printf("[I] vbcmp: max difference: %.8f\n",maxdiff); printf("[I] vbcmp: %d of %d volumes differ\n",differingvolumes,t1.dimt); } exit(0); } void vbcmp_help() { cout << boost::format(myhelp) % vbversion; } void vbcmp_version() { printf("\nVoxBo vbcmp (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vbcmp.hlp000066400000000000000000000001731153177201300170540ustar00rootroot00000000000000 VoxBo vbcmp (v%1%) summary: compare two vector, matrix, volume (3D) or volume series(4D) usage: vbcmp voxbo-1.8.5~svn1246/munge/vbconv.cpp000066400000000000000000000175401153177201300172470ustar00rootroot00000000000000 // vbconv.cpp // convert data from one format to another // Copyright (c) 2006-2007 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vbconv.hlp.h" int ConvertMultiple(list &filelist,int nanflag,int floatflag,Tes &newtes); int WriteTes(Tes &newtes,string outfile,int extractflag,int floatflag,int nanflag,set includeset,set excludeset); void vbconv_help(); void vbconv_version(); int main(int argc,char *argv[]) { if (argc==1) { vbconv_help(); exit(0); } tokenlist args; string outfile; int floatflag=0,nanflag=0,extractflag=0; set includeset,excludeset; list filelist; VBFF nullff; args.Transfer(argc-1,argv+1); for (size_t i=0; i1) { Tes newtes; ConvertMultiple(filelist,nanflag,floatflag,newtes); if (WriteTes(newtes,outfile,extractflag,floatflag,nanflag,includeset,excludeset)) exit(223); exit(0); // just in case } int err; // just one file, see what kind Cube cb; if (cb.ReadFile(filelist.front())==0) { cb.fileformat=nullff; if (floatflag && cb.datatype!=vb_float) cb.convert_type(vb_float); if (nanflag) cb.removenans(); if ((err=cb.WriteFile(outfile))) { printf("[E] vbconv: error %d writing %s\n",err,outfile.c_str()); exit(4); } else { printf("[I] vbconv: wrote cube %s\n",outfile.c_str()); exit(0); } } Tes ts; if (ts.ReadFile(filelist.front())==0) { ts.fileformat=nullff; if ((err=WriteTes(ts,outfile,extractflag,floatflag,nanflag,includeset,excludeset))) { printf("[E] vbconv: error %d writing %s\n",err,outfile.c_str()); exit(4); } else { printf("[I] vbconv: wrote 4D volume %s\n",outfile.c_str()); exit(0); } } VB_Vector vv; if (vv.ReadFile(*filelist.begin())==0) { // vv.fileformat=nullff; // FIXME -- can we set 1d fileformat? if (vv.WriteFile(outfile)) { printf("[E] vbconv: error writing %s\n",outfile.c_str()); exit(4); } else { printf("[I] vbconv: wrote vector %s\n",outfile.c_str()); exit(0); } } printf("[E] vbconv: couldn't make sense of file %s\n",filelist.front().c_str()); exit(100); } int ConvertMultiple(list &filelist,int nanflag,int floatflag,Tes &newtes) { // printf("[I] vbconv: converting %d files\n",(int)filelist.size()); // pre-scan for dimensions int dimx=0,dimy=0,dimz=0,dimt=0; VB_datatype dtype=vb_short; for (list::iterator ff=filelist.begin(); ff!=filelist.end(); ff++) { Cube cb; Tes ts; VBImage *im; if (cb.ReadHeader(*ff)==0) { im=&cb; dimt++; } else if (ts.ReadHeader(*ff)==0) { im=&ts; dimt+=ts.dimt; } else { printf("[E] vbconv: couldn't read %s\n",ff->c_str()); exit(51); } if (ff==filelist.begin()) { dimx=im->dimx; dimy=im->dimy; dimz=im->dimz; dimt=1; dtype=im->datatype; } else if (im->dimx!=dimx||im->dimy!=dimy||im->dimz!=dimz) { printf("[E] vbconv: incompatible dimensions in file %s\n",ff->c_str()); exit(51); } } int index=0; if (floatflag) dtype=vb_float; // now grab all the images newtes.SetVolume(dimx,dimy,dimz,dimt,dtype); int findex=1; for (list::iterator ff=filelist.begin(); ff!=filelist.end(); ff++) { printf("[I] vbconv: converting file %d of %d\n",findex++,(int)filelist.size()); newtes.AddHeader("vbconv: included file "+*ff); Cube cb; Tes ts; if (cb.ReadFile(*ff)==0) { newtes.SetCube(index++,cb); } else if (ts.ReadFile(*ff)==0) { for (int i=0; ic_str()); exit(5); } } if (nanflag) newtes.removenans(); return 0; } int WriteTes(Tes &newtes,string outfile,int extractflag,int floatflag,int nanflag,set includeset,set excludeset) { VBFF nullff; // merge include and exclude lists into just an include list if (includeset.size() && excludeset.size()) { for (set::iterator i=excludeset.begin(); i!=excludeset.end(); i++) includeset.erase(*i); excludeset.clear(); } newtes.fileformat=nullff; if (extractflag==0) { if (includeset.size()) newtes.resizeInclude(includeset); if (excludeset.size()) newtes.resizeExclude(excludeset); if (floatflag && newtes.datatype!=vb_float) newtes.convert_type(vb_float); if (nanflag) newtes.removenans(); if (newtes.WriteFile(outfile)) { printf("[E] vbconv: couldn't write output file %s\n",outfile.c_str()); exit(55); } else { printf("[I] vbconv: wrote file %s\n",outfile.c_str()); exit(0); } } printf("[I] vbconv: writing %d volumes: ",newtes.dimt); fflush(stdout); int err; for (int i=0; i [...] [] flags: -f convert to floating point -n replace NaNs and Infs with zeros -x extract 3D volumes, see notes below -i include only the specified volumes -e exclude the specified volumes -o output filename -h show help -v show version notes: If you specify exactly two input files and no -o flag, the first is assumed to be input and the second output. Otherwise, all will be taken as input (any combination of 3D and 4D files) and you must use the -o flag to specify the output 4D filename. If you use the -x flag and the input is a 4D volume, the individual 3D volumes are extracted and written to 3D files. You can also use the -i flag to specify which volumes you want. The output filename may have the string 'XXX' in it, and that string will be replaced with the volume number. the range can be of the form 6,17,22-29,32,38 with no whitespace. (if you only need one volume, you don't need to use XXX.) The range argument to the -i and -e flags can include multiple volumes, or ranges, separated by commas, e.g., 1-5,7-10 note that the first volume is 0. Output filenames specified as "filename[format]" will be written in the specified format. Use ffinfo to get a list of formats. Most formats can be identified by extension, but for example imgdir can be used to force a directory of Analyze img/hdr pairs, regardless of. the directory name. voxbo-1.8.5~svn1246/munge/vbfilter.cpp000066400000000000000000000201511153177201300175570ustar00rootroot00000000000000 // vbfilter.cpp // does some simple frequency filtering of 4D data // Copyright (c) 2008 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #include "vbfilter.hlp.h" class VBFilter { public: enum ftype {hp,lp,bp,bs,rl,rh,rm} type; double f1,f2; int nremove; vector nlist; VBFilter(ftype mytype,double a) {type=mytype;f1=a;} VBFilter(ftype mytype,double a,double b) {type=mytype;f1=a;f2=b;} VBFilter(ftype mytype,uint32 loworhigh) {type=mytype;nremove=loworhigh;} VBFilter(ftype mytype,string mynlist) {type=mytype;nlist=numberlist(mynlist);} }; void vbfilter_help(); void vbfilter_version(); void filter_tes(Tes &tes,vectorfilterlist,double period); VB_Vector make_filter(int len,double period,vectorfilterlist); void filter_signal(VB_Vector &signal,VB_Vector filtermask); void print_filter(VB_Vector &fmask,double period); int main(int argc,char *argv[]) { if (argc==1) { vbfilter_help(); exit(0); } tokenlist args; string outfile,writefile; vector filelist; vector filterlist; double period=0; bool infoflag=0; args.Transfer(argc-1,argv+1); for (size_t i=0; iFLT_MIN) myperiod=mytes.voxsize[3]; if (myperiod==0 && period==0) { printf("[E] vbfilter: no sampling rate information for file %s, skipping\n",filelist[i].c_str()); continue; } if (infoflag) { printf("[I] vbfilter: 4D file %s\n",filelist[i].c_str()); printf("[I] vbfilter: %d observations, sampling period of %f\n", mytes.dimt,myperiod); VB_Vector fmask=make_filter(mytes.dimt,myperiod,filterlist); print_filter(fmask,myperiod); } else { printf("[I] vbfilter: filtering 4D volume %s...",filelist[i].c_str()); fflush(stdout); filter_tes(mytes,filterlist,myperiod); mytes.WriteFile(writefile); printf("done.\n"); } } else if (myvec.ReadFile(filelist[i])==0) { myperiod=period; // for now, always use period from command line if (myperiod==0) { printf("[E] vbfilter: no sampling rate information for file %s, skipping\n",filelist[i].c_str()); continue; } VB_Vector fmask=make_filter(myvec.size(),period,filterlist); if (infoflag) { printf("[I] vbfilter: vector file %s\n",filelist[i].c_str()); printf("[I] vbfilter: %d observations, sampling period of %f\n", (int)(myvec.size()),myperiod); print_filter(fmask,period); } else { printf("[I] vbfilter: filtering vector %s...",filelist[i].c_str()); fflush(stdout); filter_signal(myvec,fmask); myvec.WriteFile(writefile); printf("done.\n"); } } else { printf("[E] vbfilter: couldn't read %s as either a vector or a 4D file\n",filelist[i].c_str()); continue; } } exit(0); } void filter_tes(Tes &tes,vectorfilterlist,double period) { tes.ReadData(tes.GetFileName()); VB_Vector fmask=make_filter(tes.dimt,period,filterlist); for (int i=0; ifilterlist) { int nfreq=len/2; VB_Vector freqmask(len); freqmask*=0.0; freqmask+=1.0; period/=1000.0; // need it in seconds, not ms for (size_t i=0; ifilterlist[i].f1) filterme=1; } else if (filterlist[i].type==VBFilter::bp) { if (thisfreqfilterlist[i].f2) filterme=1; } else if (filterlist[i].type==VBFilter::bs) { if (thisfreq>=filterlist[i].f1 && thisfreq<=filterlist[i].f2) filterme=1; } else if (filterlist[i].type==VBFilter::rl) { if (j<=filterlist[i].nremove) filterme=1; } else if (filterlist[i].type==VBFilter::rh) { if (nfreq-j+1<=filterlist[i].nremove) filterme=1; } else if (filterlist[i].type==VBFilter::rm) { if (find(filterlist[i].nlist.begin(),filterlist[i].nlist.end(),j)!=filterlist[i].nlist.end()) filterme=1; } if (filterme) { freqmask(j)=0; freqmask(len-j)=0; } } } return freqmask; } void print_filter(VB_Vector &fmask,double period) { period/=1000.0; // need it in seconds, not ms for (uint32 i=1; i<(fmask.size()/2)+1; i++) { double thisfreq=(double)i/((double)fmask.size()*period); printf(" frequency %3.d: %f%s\n",i,thisfreq, (fmask[i] ? "" : " to be removed" )); } } void filter_signal(VB_Vector &signal,VB_Vector freqmask) { VB_Vector sig_real(signal.getLength()); VB_Vector sig_imag(signal.getLength()); signal.fft(sig_real,sig_imag); for (size_t i=0; i] <1D or 4D file/dir> ... flags: -lp lowpass: pass frequencies <= freq -hp highpass: pass frequencies >= freq -bp bandpass: pass frequencies f1 <= freq <=f2 -bs bandstop: squash frequencies f1 <= freq <= f2 -rl remove lows: remove the n lowest frequencies -rh remove highs: remove the n highest frequencies -rm remove range: remove ordinal frequencies (e.g., 4-7) -o set output file name -i print info but don't actually do anything -p specify sampling period in ms -h print help -v print version notes: Use the -i option to see the ordinal list of frequencies. All specified filtering options will be applied in sequence, but once an option removes a frequency, subsequent options won't restore it. The rl and rh options take counts, so -rl 1 means to remove the single lowest frequency. The rm option removes ordinal frequencies counting from 1. If no output filename is provided with -o, then the input filename is prepended with f. voxbo-1.8.5~svn1246/munge/vbhdr.cpp000066400000000000000000000156671153177201300170670ustar00rootroot00000000000000 // vbhdr.cpp // set the origin of one image to correspond to that of another // Copyright (c) 1998-2006 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbutil.h" #include "vbio.h" #include "vbjobspec.h" #include "vbprefs.h" #include #include "vbhdr.hlp.h" int vbhdr_copy(vector&hdr,string item,VBImage *im); int vbhdr_set(vector&hdr,string item); int vbhdr_add(vector&hdr,string item); int vbhdr_strip(vector&hdr,string item); void vbhdr_help(); void vbhdr_version(); VBPrefs vbp; int main(int argc,char *argv[]) { vbp.init(); int err = 0; tzset(); // make sure all times are timezone corrected if (argc < 4) { // not enough args, display autodocs vbhdr_help(); exit(106); } tokenlist args; args.Transfer(argc-1,argv+1); string setline,addline,deleteline,neworient,copysrc; int originflag=0,voxsizeflag=0,trflag=0; float voxsizes[3],origin[3],tr=1000; vector filelist; // initialization to make the compiler happy voxsizes[0]=0.0; voxsizes[1]=0.0; voxsizes[2]=0.0; origin[0]=0.0; origin[1]=0.0; origin[2]=0.0; for (size_t i=0; iheader; if ((cb.ReadFile(filelist[i]))==0) { im=&cb; header=cb.header; } else if ((ts.ReadFile(filelist[i]))==0) { im=&ts; header=ts.header; } else { printf("[E] vbhdr: unrecognized file type\n"); exit(104); } if (setline.size()) { err=vbhdr_set(header,setline); printf("[I] vbhdr: setting the following header: %s\n",setline.c_str()); } else if (addline.size()) { err=vbhdr_add(header,addline); printf("[I] vbhdr: adding the following header: %s\n",addline.c_str()); } else if (deleteline.size()) { err=vbhdr_strip(header,deleteline); printf("[I] vbhdr: deleting the following header: %s\n",deleteline.c_str()); } else if (copysrc.size()) { err=vbhdr_copy(header,copysrc,im); printf("[I] vbhdr: copying header from %s\n",copysrc.c_str()); } else if (neworient.size()) { im->orient=neworient; printf("[I] vbhdr: setting orientation to %s\n",neworient.c_str()); } else if (originflag) { im->origin[0]=(int)round(origin[0]); im->origin[1]=(int)round(origin[1]); im->origin[2]=(int)round(origin[2]); im->qoffset[0]=0-origin[0]; im->qoffset[1]=0-origin[1]; im->qoffset[2]=0-origin[2]; printf("[I] vbhdr: setting origin to %.2f %.2f %.2f\n", im->qoffset[0],im->qoffset[1],im->qoffset[2]); printf("[I] vbhdr: note that origins are counting from 0, and that non-integer\n"); printf("[I] vbhdr: origins only work for NIfTI files\n"); } else if (voxsizeflag) { im->voxsize[0]=voxsizes[0]; im->voxsize[1]=voxsizes[1]; im->voxsize[2]=voxsizes[2]; printf("[I] vbhdr: setting voxel sizes to %.4f %.4f %.4f\n", im->voxsize[0],im->voxsize[1],im->voxsize[2]); } else if (trflag) { im->voxsize[3]=tr; printf("[I] vbhdr: TR to %.4fms\n",im->voxsize[3]); } else { printf("[E] vbhdr: nothing to do\n"); return 100; } if (cb.data) { cb.header=header; err = cb.WriteFile(); if (err) { printErrorMsg(VB_ERROR, "vbhdr: Error writing cube to file.\n"); exit(err); } } else { ts.header=header; err = ts.WriteFile(); if (err) { printErrorMsg(VB_ERROR, "vbhdr: Error writing cube to file.\n"); exit(err); } } } exit(0); } int vbhdr_copy(vector&hdr,string item,VBImage *im) { Tes ts; if (ts.ReadHeader(item)==0) { hdr=ts.header; im->CopyHeader(ts); return 0; } Cube cb; if (cb.ReadHeader(item)==0) { hdr=cb.header; im->CopyHeader(cb); return 0; } return 101; } int vbhdr_set(vector&hdr,string item) { vectornewhdr; tokenlist striptags,oldtags; striptags.ParseLine(item); int foundit=0; for (int i=0; i<(int)hdr.size(); i++) { oldtags.ParseLine(hdr[i]); if (oldtags[0]!=striptags[0]) newhdr.push_back(hdr[i]); else { newhdr.push_back(item); foundit=1; } } if (!foundit) newhdr.push_back(item); hdr=newhdr; return (0); } int vbhdr_add(vector&hdr,string item) { string newitem=item; replace_string(newitem,"{DATE}",timedate()); //struct utsname names; //uname(&names); replace_string(newitem,"{HOST}",vbp.thishost.nickname); hdr.push_back(newitem); return (0); } int vbhdr_strip(vector&hdr,string item) { vectornewhdr; tokenlist striptags,oldtags; striptags.ParseLine(item); for (int i=0; i<(int)hdr.size(); i++) { oldtags.ParseLine(hdr[i]); if (oldtags[0]!=striptags[0]) newhdr.push_back(hdr[i]); } hdr=newhdr; return (0); } void vbhdr_help() { cout << boost::format(myhelp) % vbversion; } void vbhdr_version() { printf("VoxBo vbhdr (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vbhdr.hlp000066400000000000000000000007131153177201300170520ustar00rootroot00000000000000 VoxBo vbhdr (v%1%) summary: perform various header-related manipulations usage: vbhdr [ ...] flags: -s set hdr line (replace or add) -a add hdrline -d delete hdr -c copy user headers -o change orientation -x new origin -z new voxel sizes -t new TR (in msec) -h show help -v print version voxbo-1.8.5~svn1246/munge/vbi.cpp000066400000000000000000000075251153177201300165340ustar00rootroot00000000000000 // vbi.cpp // hack to print out information about various file types // Copyright (c) 1998-2009 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbutil.h" #include "vbio.h" #include "vbversion.h" #include #include #include "vbi.hlp.h" extern "C" { #include "analyze.h" #include "nifti.h" #include "dicom.h" } void vbi_help(); void vbi_version(); int main(int argc,char *argv[]) { tokenlist args; args.Transfer(argc-1,argv+1); if (args.size()==0) { vbi_help(); exit(0); } bool f_long=0; bool f_loaddata=0; bool f_fullheader=0; string flagstr; vector filelist; for (size_t i=0; iformats; VBFF fileformat; for (size_t i=0; i [ ...] flags: -d include dimensions -t include data type -z include voxel sizes -o include origin -r include orientation -l produce long format output -a load data before printing info -f show all metadata for analyze, nifti, and dicom files -h help -v version voxbo-1.8.5~svn1246/munge/vbim.cpp000066400000000000000000001532341153177201300167100ustar00rootroot00000000000000 // vbim.cpp // general-purpose munging util for voxbo (used to be vbim) // Copyright (c) 2003-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include "vbutil.h" #include "vbio.h" #include "imageutils.h" #include "vbversion.h" #include "vbim.hlp.h" void vbim_help(string key=""); void vbim_version(); int cube_combine(Cube &cb,tokenlist &args); void selectcubes(list &clist,size_t n); bool comparedims(list cubelist); void cube_random01(Cube &cb); void cube_printregioninfo(Cube &cb,tokenlist &args); void reallyload(Cube &cube); void build_oplist(); // ugly globals -- code needs some reorg Cube mycube; int multi_index; bool f_read4d=0; gsl_rng *rng; class imageop { public: string name; size_t minargs,maxargs; tokenlist args; // generally, an operator is combining if either initfn or finishfn is non-null vbreturn (*initfn)(list &cubelist,tokenlist &args); vbreturn (*procfn)(Cube &cube,tokenlist &args); vbreturn (*finishfn)(list &cubelist,tokenlist &args); bool f_ncwithargs; // if set, this op becomes non-combining when called with arguments // storage for combining operators // sole constructor requires name and min/maxargs imageop(); imageop(string xname,int mina,int maxa,vbreturn (*xprocfn)(Cube &,tokenlist &)); void init(string xname,int mina,int maxa,vbreturn (*xprocfn)(Cube &,tokenlist &)); // random methods bool iscombining() {return (initfn!=NULL || finishfn!=NULL);} }; imageop::imageop() { init("",0,0,NULL); } imageop::imageop(string xname,int mina,int maxa,vbreturn (*xprocfn)(Cube &,tokenlist &)) { init(xname,mina,maxa,xprocfn); } void imageop::init(string xname,int mina,int maxa,vbreturn (*xprocfn)(Cube &,tokenlist &)) { name=xname; minargs=mina; maxargs=maxa; args.clear(); initfn=NULL; procfn=xprocfn; finishfn=NULL; f_ncwithargs=0; } // two operator lists that are handled differently: in phase 1, we do // as many operations as possible for each cube; in phase 2, we do // each operator for each cube before proceeding to the next operator. list phase1; list phase2; typedef list::iterator OPI; typedef list::iterator CUBI; map oplist; int main(int argc,char *argv[]) { if (argc<=1) { vbim_help(); exit(0); } build_oplist(); tokenlist args; list filelist; // string outfile; args.Transfer(argc-1,argv+1); int phase=1; string opname; for (size_t i=0; imyop.maxargs) { cout << format("[E] vbim: operator %s takes from %d to %d arguments\n") %opname%myop.minargs%myop.maxargs; exit(202); } // special case operators that become non-combining with arguments if (myop.f_ncwithargs && myop.args.size()>1) { myop.initfn=NULL; myop.finishfn=NULL; } // now decide which list gets the op if (phase==2) phase2.push_back(myop); // if we're in phase 1 and it's parallel, just put it on else if (!myop.iscombining()) phase1.push_back(myop); // if we're in phase 1 and it's combining, see if we have any parallels first else { if (phase1.size()) phase1.push_back(myop); else phase2.push_back(myop); phase=2; } } list cubelist; Cube master; // pre-load all the files. we should figure out how not to load all // the image data from 4D files, maybe. for (list::iterator ff=filelist.begin(); ff!=filelist.end(); ff++) { printf("[I] vbim: reading file %s\n",ff->c_str()); Cube cb; Tes ts; if (cb.ReadHeader(*ff)==0) { cubelist.push_back(cb); continue; } if (ts.ReadFile(*ff)) { printf("[E] vbim: couldn't read file %s, continuing anyway\n",ff->c_str()); continue; } f_read4d=1; for (int i=0; iid1=index; for (OPI oo=phase1.begin(); oo!=phase1.end(); oo++) { if (oo->initfn && !phase1cflag) { oo->initfn(cubelist,oo->args); phase1cflag=1; } if (oo->procfn) oo->procfn(*cc,oo->args); } index++; // invalidate cube if we have no more use for it if (phase2.empty() && !(phase1.back().finishfn)) cc->invalidate(); } if (phase1.back().iscombining() && phase1.back().finishfn) phase1.back().finishfn(cubelist,phase1.back().args); } // if we have a phase2 block, now do that for (OPI oo=phase2.begin(); oo!=phase2.end(); oo++) { if (oo->initfn) oo->initfn(cubelist,oo->args); index=0; for (CUBI cc=cubelist.begin(); cc!=cubelist.end(); cc++) { cc->id1=index; if (oo->procfn) oo->procfn(*cc,oo->args); index++; } if (oo->finishfn) oo->finishfn(cubelist,oo->args); } exit(0); } // for "combine" the arguments are: // combine fixed/moving x y z op value template int cube_combine_fixed(Cube &cb,tokenlist &args) { int xx=strtol(args[2]); int yy=strtol(args[3]); int zz=strtol(args[4]); string method=args[5]; int f_needval=0; if (method=="sum" || method=="average") f_needval=1; if (xx<1 || yy<1 || zz<1) { printf("[E] vbim: invalid subcube dimensions\n"); return 101; } Cube cb2(cb); // initial subcube range 0:xx-1, etc. int x1=0,y1=0,z1=0; int xn=xx-1,yn=yy-1,zn=zz-1; int i,j,k,count; double total; T val; while(1) { count=0; total=0.0; if (x1>cb.dimx-1 || y1>cb.dimy-1 || z1>cb.dimz-1) break; if (xn>cb.dimx-1) xn=cb.dimx-1; if (yn>cb.dimy-1) yn=cb.dimy-1; if (zn>cb.dimz-1) zn=cb.dimz-1; for (i=x1; i<=xn; i++) { for (j=y1; j<=yn; j++) { for (k=z1; k<=zn; k++) { if (f_needval) { val=cb.getValue(i,j,k); if (val>0.0) count++; total+=val; } else if (cb.testValue(i,j,k)) count++; } } } // calculate the replacement value -- sum, count, average, // pct T newvalue=0; int rsize=(xn-x1+1)*(yn-y1+1)*(zn-z1+1); if (method=="count") newvalue=count; else if (method=="sum") newvalue=total; else if (method=="pct") newvalue=(count*100)/rsize; else if (method=="average") newvalue=total/rsize; else newvalue=0; // all voxels in the subcube get the identical new value for (i=x1; i<=xn; i++) { for (j=y1; j<=yn; j++) { for (k=z1; k<=zn; k++) { cb2.setValue(i,j,k,newvalue); } } } // next subcube if (xn int cube_combine_moving(Cube &cb,tokenlist &args) { int xx=strtol(args[2]); int yy=strtol(args[3]); int zz=strtol(args[4]); string method=args[5]; int f_needval=0; if (method=="sum" || method=="average") f_needval=1; if (xx<1 || yy<1 || zz<1) { printf("[E] vbim: invalid subcube dimensions\n"); return 101; } Cube cb2(cb); // initial subcube range 0:xx-1, etc. int x1=0,y1=0,z1=0; int xn=xx-1,yn=yy-1,zn=zz-1; int i,j,k,count; double total; T val; for (int xxx=0; xxx<=cb.dimx; xxx++) { for (int yyy=0; yyy<=cb.dimy; yyy++) { for (int zzz=0; zzz<=cb.dimz; zzz++) { count=0; total=0.0; // build a neighborhood around the voxel x1=xxx-xx/2; xn=x1+xx-1; y1=yyy-yy/2; yn=y1+yy-1; z1=zzz-zz/2; zn=z1+zz-1; // clip it to cube boundaries if (x1<0) x1=0; if (y1<0) y1=0; if (z1<0) z1=0; if (xn>cb.dimx-1) xn=cb.dimx-1; if (yn>cb.dimy-1) yn=cb.dimy-1; if (zn>cb.dimz-1) zn=cb.dimz-1; for (i=x1; i<=xn; i++) { for (j=y1; j<=yn; j++) { for (k=z1; k<=zn; k++) { if (f_needval) { val=cb.getValue(i,j,k); if (val>0.0) count++; total+=val; } else if (cb.testValue(i,j,k)) count++; } } } // calculate the replacement value -- sum, count, average, // pct T newvalue=0; int rsize=(xn-x1+1)*(yn-y1+1)*(zn-z1+1); if (method=="count") newvalue=count; else if (method=="sum") newvalue=total; else if (method=="pct") newvalue=(count*100)/rsize; else if (method=="average") newvalue=total/rsize; else newvalue=0; // set just the original voxel cb2.setValue(xxx,yyy,zzz,newvalue); } } } cb=cb2; return 0; } int cube_combine(Cube &cb,tokenlist &args) { if (args[1]=="fixed" || args[1]=="f") { switch(cb.datatype) { case vb_byte: return cube_combine_fixed(cb,args); break; case vb_short: return cube_combine_fixed(cb,args); break; case vb_long: return cube_combine_fixed(cb,args); break; case vb_float: return cube_combine_fixed(cb,args); break; case vb_double: return cube_combine_fixed(cb,args); break; } } else if (args[1]=="moving" || args[1]=="m") { switch(cb.datatype) { case vb_byte: return cube_combine_moving(cb,args); break; case vb_short: return cube_combine_moving(cb,args); break; case vb_long: return cube_combine_moving(cb,args); break; case vb_float: return cube_combine_moving(cb,args); break; case vb_double: return cube_combine_moving(cb,args); break; } } return 101; // shouldn't happen } void cube_printregioninfo(Cube &cb,tokenlist &args) { bool f_masked=0; vector rlist; if (args.size()>1) { f_masked=1; Cube mask; if (mask.ReadFile(args[1])) { printf("[E] vbim: couldn't read mask %s\n",args(1)); return; } if (!mask.data || mask.dimx!=cb.dimx||mask.dimy!=cb.dimy||mask.dimz!=cb.dimz) { printf("[E] vbim: non-matching dimensions for mask %s\n",args(1)); return; } VBRegion r; for (int i=0;isecond.val << endl; } else rlist=findregions(cb,vb_ne,0.0); int totalvoxels=0; for (size_t i=0; isecond.x; y1+=myvox->second.y; z1+=myvox->second.z; x2+=myvox->second.x*myvox->second.val; y2+=myvox->second.y*myvox->second.val; z2+=myvox->second.z*myvox->second.val; totalmass+=myvox->second.val; } x1/=rlist[i].size(); y1/=rlist[i].size(); z1/=rlist[i].size(); x2/=totalmass; y2/=totalmass; z2/=totalmass; VBRegion peakrr=rlist[i].maxregion(); VBRegion minrr=rlist[i].minregion(); double pxx,pyy,pzz; peakrr.GeometricCenter(pxx,pyy,pzz); if (i==0) { printf("[I] vbim: all regions combined:\n"); printf("[I] vbim: voxels: %d\n",rlist[i].size()); if (vfactor>FLT_MIN) printf("[I] vbim: mm3: %g\n",vfactor*rlist[i].size()); printf("[I] vbim: sum: %g\n",totalmass); printf("[I] vbim: mean: %g\n",totalmass/(double)rlist[i].size()); printf("[I] vbim: center: %g,%g,%g\n",x1,y1,z1); printf("[I] vbim: weighted ctr: %g,%g,%g\n",x2,y2,z2); printf("[I] vbim: peakval: %g\n",peakrr.begin()->second.val); printf("[I] vbim: peakcnt: %d\n",peakrr.size()); printf("[I] vbim: minval: %g\n",minrr.begin()->second.val); printf("[I] vbim: mincnt: %d\n",minrr.size()); printf("[I] vbim: peak center: %g,%g,%g\n",pxx,pyy,pzz); printf("[I] vbim: note: peakcnt (or lowcnt) is the total number of voxels in\n"); printf("[I] vbim: the region with the same peak (or min) value\n"); continue; } printf("[I] vbim: region %02d: count: %d\n",(int)i,(int)rlist[i].size()); if (vfactor>FLT_MIN) printf("[I] vbim: mm3: %g\n",vfactor*rlist[i].size()); printf("[I] vbim: sum: %g\n",totalmass); printf("[I] vbim: mean: %g\n",totalmass/(double)rlist[i].size()); printf("[I] vbim: center: %g,%g,%g\n",x1,y1,z1); printf("[I] vbim: weighted ctr: %g,%g,%g\n",x2,y2,z2); printf("[I] vbim: peakval: %g\n",peakrr.begin()->second.val); printf("[I] vbim: peakcnt: %d\n",peakrr.size()); printf("[I] vbim: minval: %g\n",minrr.begin()->second.val); printf("[I] vbim: mincnt: %d\n",minrr.size()); printf("[I] vbim: peak center: %g,%g,%g\n",pxx,pyy,pzz); printf("[I] vbim: note: peakcnt (or lowcnt) is the total number of voxels in\n"); printf("[I] vbim: the region with the same peak (or min) value\n"); // totalvoxels+=rlist[i].size(); } // printf("[I] vbim: %d total voxels in volume %s\n",totalvoxels,cb.GetFileName().c_str()); } void cube_random01(Cube &cb) { uint32 rr=0; int pos=32; cb.zero(); for (int i=0; i31) { rr=VBRandom(); pos=0; } if (rr & 1< &clist,size_t n) { if (n>=clist.size() || n<1) return; map randlist; while (randlist.size()::iterator mm=randlist.begin(); list::iterator cc=clist.begin(); int oldn=clist.size(); for (int i=0; isecond) cc++; else cc=clist.erase(cc); mm++; } } bool comparedims(list cubelist) { if (cubelist.size()<2) return 1; list::iterator cc=cubelist.begin(); int dimx=cc->dimx; int dimy=cc->dimy; int dimz=cc->dimz; cc++; while (cc!=cubelist.end()) { if (cc->dimx!=dimx || cc->dimy!=dimy || cc->dimz!=dimz) return 0; cc++; } return 1; } // initfns vbreturn op_shortzeros(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; mycube.SetVolume(cubelist.front().dimx,cubelist.front().dimy, cubelist.front().dimz,vb_short); return 0; } vbreturn op_allones(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; reallyload(cubelist.front()); mycube=cubelist.front(); mycube.quantize(1.0); return 0; } vbreturn op_allzeros(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; reallyload(cubelist.front()); mycube=cubelist.front(); mycube.zero(); mycube.convert_type(vb_double,1); mycube.f_scaled=0; return 0; } vbreturn op_initrng(list &,tokenlist &args) { uint32 rngseed; if (args.size()>3) rngseed=strtol(args[3]); else rngseed=VBRandom(); rng=gsl_rng_alloc(gsl_rng_mt19937); assert(rng); gsl_rng_set(rng,rngseed); return 0; } vbreturn op_freerng(list &,tokenlist &) { gsl_rng_free(rng); rng=NULL; return 0; } vbreturn op_copy(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; reallyload(cubelist.front()); mycube=cubelist.front(); return 0; } // procfn vbreturn op_smoothvox(Cube &cube,tokenlist &args) { reallyload(cube); smoothCube(cube,strtod(args[1]),strtod(args[2]),strtod(args[3])); return 0; } vbreturn op_smoothvox2(Cube &cube,tokenlist &args) { reallyload(cube); smoothCube(cube,strtod(args[1]),strtod(args[2]),strtod(args[3]),1); return 0; } vbreturn op_smoothmm(Cube &cube,tokenlist &args) { reallyload(cube); smoothCube(cube, strtod(args[1])/cube.voxsize[0], strtod(args[2])/cube.voxsize[1], strtod(args[3])/cube.voxsize[2]); return 0; } vbreturn op_smoothmm2(Cube &cube,tokenlist &args) { reallyload(cube); smoothCube(cube, strtod(args[1])/cube.voxsize[0], strtod(args[2])/cube.voxsize[1], strtod(args[3])/cube.voxsize[2], 1); return 0; } vbreturn op_thresh(Cube &cube,tokenlist &args) { reallyload(cube); cube.thresh(strtod(args[1])); return 0; } vbreturn op_rotate(Cube &cube,tokenlist &args) { reallyload(cube); rotatecube(cube,strtod(args[1]),strtod(args[2]),strtod(args[3])); return 0; } vbreturn op_nonans(Cube &cube,tokenlist &) { reallyload(cube); cube.removenans(); return 0; } vbreturn op_regionat(Cube &cube,tokenlist &args) { reallyload(cube); Cube mask; mask.SetVolume(cube.dimx,cube.dimy,cube.dimz,vb_short); mask+=1; VBRegion rr; rr=growregion(strtol(args[1]),strtol(args[2]),strtol(args[3]),cube,mask,vb_agt,FLT_MIN); mask*=0; for (VI myvox=rr.begin(); myvox!=rr.end(); myvox++) { mask.setValue(myvox->second.x,myvox->second.y,myvox->second.z,(int32)1); } cube=mask; return 0; } // FIXME splitregions inexplicably writes output right away. // it shouldn't! vbreturn op_splitregions(Cube &cube,tokenlist &args) { reallyload(cube); vector regions; regions=findregions(cube,vb_gt,0.0); Cube mask; mask.SetVolume(cube.dimx,cube.dimy,cube.dimz,vb_byte); int index=0; string fname; vbforeach(VBRegion &rr,regions) { mask.zero(); for (VI myvox=rr.begin(); myvox!=rr.end(); myvox++) mask.setValue(myvox->second.x,myvox->second.y,myvox->second.z,1); fname=args[1]; string num=(format("%05d")%index).str(); replace_string(fname,"XXX",num); mask.WriteFile(fname); index++; } cube=mask; return 0; } vbreturn op_subdivide(Cube &cube,tokenlist &args) { reallyload(cube); if (args.size()!=4) { cout << "[E] wrong number of arguments for subdivide\n"; return 101; } // FIXME create the subcubes here Cube subcubes(cube.dimx,cube.dimy,cube.dimz,vb_int16); int cx=strtol(args[1]); int cy=strtol(args[2]); int cz=strtol(args[3]); int nx=cube.dimx/cx; if (cube.dimx%cx) nx++; int ny=cube.dimy/cy; if (cube.dimy%cy) ny++; int nz=cube.dimz/cz; if (cube.dimz%cz) nz++; int32 label=1; for (int ii=0; ii=cube.dimx) break; for (int j=jj*cy; j<(jj+1)*cy; j++) { if (j>=cube.dimy) break; for (int k=kk*cz; k<(kk+1)*cz; k++) { if (k>=cube.dimz) break; subcubes.setValue(i,j,k,label); } } } label++; } } } int32 v1,v2; map submaskvals; Cube newcube(cube.dimx,cube.dimy,cube.dimz,vb_int16); label=1; for (int i=0; i(i,j,k); if (!v1) continue; v2=subcubes.getValue(i,j,k); if (!submaskvals.count(twovals(v1,v2))) submaskvals[twovals(v1,v2)]=label++; newcube.setValue(i,j,k,submaskvals[twovals(v1,v2)]); } } } cout << format("[I] vbim: subdivided your volume into %d distinct regions\n")%(label-1); cube=newcube; return 0; } vbreturn op_threshabs(Cube &cube,tokenlist &args) { reallyload(cube); cube.threshabs(strtod(args[1])); return 0; } vbreturn op_cutoff(Cube &cube,tokenlist &args) { reallyload(cube); cube.cutoff(strtod(args[1])); return 0; } vbreturn op_orient(Cube &cube,tokenlist &) { reallyload(cube); printf("orient not implemented\n"); exit(5); return 0; } vbreturn op_setspace(Cube &cube,tokenlist &args) { reallyload(cube); if (args.size()<2) { cube.init_nifti(); return 0; } if (args.size()==2 && vb_tolower(args[1])=="acp") { string acp=cube.GetHeader("AbsoluteCornerPosition:"); tokenlist acpx; acpx.ParseLine(acp); if (acpx.size()!=3) { cout << format("[E] vbim: couldn't get acp from file %s\n")%args[1]; exit(102); } cube.init_nifti(); double xx,yy,zz; xx=strtod(acpx[0]); yy=strtod(acpx[1]); zz=strtod(acpx[2]); cube.qform_code=2; cube.sform_code=2; cube.qoffset[0]=0-xx; cube.qoffset[1]=0-yy; cube.qoffset[2]=0-zz; cube.origin[0]=(int32)(0-xx); cube.origin[1]=(int32)(0-yy); cube.origin[2]=(int32)(0-zz); cube.srow_x[3]=0-xx; cube.srow_y[3]=0-yy; cube.srow_z[3]=0-zz; return 0; } VBImage *im=NULL; Cube cb; Tes ts; if (!cb.ReadFile(args[1])) im=&cb; else if (!ts.ReadFile(args[1])) im=&ts; if (!im) { cout << format("[E] vbim: couldn't read space from file %s\n")%args[1]; exit(101); } cube.voxsize[0]=im->voxsize[0]; cube.voxsize[1]=im->voxsize[1]; cube.voxsize[2]=im->voxsize[2]; cube.voxsize[3]=im->voxsize[3]; cube.origin[0]=im->origin[0]; cube.origin[1]=im->origin[1]; cube.origin[2]=im->origin[2]; cube.qform_code=im->qform_code; cube.sform_code=im->sform_code; cube.qoffset[0]=im->qoffset[0]; cube.qoffset[1]=im->qoffset[1]; cube.qoffset[2]=im->qoffset[2]; cube.quatern_b=im->quatern_b; cube.quatern_c=im->quatern_c; cube.quatern_d=im->quatern_d; cube.srow_x[0]=im->srow_x[0]; cube.srow_x[1]=im->srow_x[1]; cube.srow_x[2]=im->srow_x[2]; cube.srow_x[3]=im->srow_x[3]; cube.srow_y[0]=im->srow_y[0]; cube.srow_y[1]=im->srow_y[1]; cube.srow_y[2]=im->srow_y[2]; cube.srow_y[3]=im->srow_y[3]; cube.srow_z[0]=im->srow_z[0]; cube.srow_z[1]=im->srow_z[1]; cube.srow_z[2]=im->srow_z[2]; cube.srow_z[3]=im->srow_z[3]; cube.orient=im->orient; return 0; } vbreturn op_quantize(Cube &cube,tokenlist &args) { reallyload(cube); cube.quantize(strtod(args[1])); return 0; } vbreturn op_invert(Cube &cube,tokenlist &) { reallyload(cube); cube.invert(); return 0; } vbreturn op_abs(Cube &cube,tokenlist &) { reallyload(cube); cube.abs(); return 0; } vbreturn op_signflip(Cube &cube,tokenlist &) { reallyload(cube); cube*=-1; return 0; } vbreturn op_flipx(Cube &cube,tokenlist &) { reallyload(cube); cube.flipx(); return 0; } vbreturn op_flipy(Cube &cube,tokenlist &) { reallyload(cube); cube.flipy(); return 0; } vbreturn op_flipz(Cube &cube,tokenlist &) { reallyload(cube); cube.flipz(); return 0; } vbreturn op_zeroleft(Cube &cube,tokenlist &) { reallyload(cube); cube.rightify(); return 0; } vbreturn op_zeroright(Cube &cube,tokenlist &) { reallyload(cube); cube.leftify(); return 0; } vbreturn op_bigendian(Cube &cube,tokenlist &) { reallyload(cube); cube.filebyteorder=ENDIAN_BIG; return 0; } vbreturn op_littleendian(Cube &cube,tokenlist &) { reallyload(cube); cube.filebyteorder=ENDIAN_LITTLE; return 0; } vbreturn op_byteswap(Cube &cube,tokenlist &) { reallyload(cube); cube.byteswap(); return 0; } vbreturn op_combine(Cube &cube,tokenlist &args) { reallyload(cube); if (cube_combine(cube,args)) { printf("[E] vbim: error downsampling\n"); exit(212); } return 0; } class sdata { public: int32 count; double sum; int32 nzcount; }; vbreturn op_maskselect(Cube &cube,tokenlist &args) { reallyload(cube); set nums=numberset(args[1]); if (nums.empty()) { cout << format("[E] vbim: bad set of masks to select: %s\n")%args[1]; exit(144); } for (int i=0; i(i); if (!(nums.count(val))) cube.setValue(i,0); } return 0; } vbreturn op_maskcombine(Cube &cube,tokenlist &args) { string mode=vb_tolower(args[2]); reallyload(cube); Cube mask; mask.ReadFile(args[1]); if (!mask) { cout << format("[E] vbim: couldn't read mask file %s\n")%args[1]; exit(212); } if (mask.dimx!=cube.dimx||mask.dimy!=cube.dimy||mask.dimz!=cube.dimz) { cout << format("[E] vbim: incompatible dimensions between mask %s and image data\n")%args[1]; exit(213); } map smap; map::iterator sit; for (int i=0; i(i,j,k); if (!mval) continue; if (!smap.count(mval)) { smap[mval].count=0; smap[mval].sum=0.0; } smap[mval].count++; double val=cube.getValue(i,j,k); smap[mval].sum+=val; if (fabs(val)>=DBL_MIN) smap[mval].nzcount++; } } } if (mode=="count") { for (sit=smap.begin(); sit!=smap.end(); sit++) sit->second.sum=sit->second.nzcount; } else if (mode=="average") { for (sit=smap.begin(); sit!=smap.end(); sit++) sit->second.sum/=sit->second.count; } else if (mode=="pct") { for (sit=smap.begin(); sit!=smap.end(); sit++) sit->second.sum=(double)sit->second.nzcount/sit->second.count; } for (int i=0; i(i,j,k); if (!mval) cube.setValue(i,j,k,0.0); else cube.setValue(i,j,k,smap[mval].sum); } } } return 0; } vbreturn op_convert(Cube &cube,tokenlist &args) { reallyload(cube); string newtype=vb_tolower(args[1]); int err=1; if (newtype=="byte") err=cube.convert_type(vb_byte,VBSETALT); if (newtype=="int16") err=cube.convert_type(vb_short,VBSETALT); if (newtype=="int32") err=cube.convert_type(vb_long,VBSETALT); if (newtype=="float") err=cube.convert_type(vb_float,VBSETALT|VBNOSCALE); if (newtype=="double") err=cube.convert_type(vb_double,VBSETALT|VBNOSCALE); if (err) { printf("[E] vbim: error converting datatype\n"); exit(212); } return 0; } vbreturn op_removesmallregions(Cube &cube,tokenlist &) { reallyload(cube); return 0; } vbreturn op_add(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbim: couldn't read file %s\n",args(1)); exit(202); } cube+=tmp; } else cube+=strtod(args[1]); return 0; } vbreturn op_sub(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbim: couldn't read file %s\n",args(1)); exit(202); } cube-=tmp; } else cube-=strtod(args[1]); return 0; } vbreturn op_mult(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbim: couldn't read file %s\n",args(1)); exit(202); } cube*=tmp; } else cube*=strtod(args[1]); return 0; } vbreturn op_div(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbim: couldn't read file %s\n",args(1)); exit(202); } cube/=tmp; } else cube/=strtod(args[1]); return 0; } vbreturn op_nminus(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbim: couldn't read file %s\n",args(1)); exit(202); } cube=tmp-cube; } else { cube-=strtod(args[1]); cube*=-1.0; } return 0; } vbreturn op_random01(Cube &cube,tokenlist &) { reallyload(cube); cube_random01(cube); return 0; } vbreturn op_writevec(Cube &cube,tokenlist &args) { reallyload(cube); int n=cube.dimx*cube.dimy*cube.dimz; VB_Vector vv(n),somevalues; int index=0; for (int i=0; i(i); if (fabs(val)data,index,sizeof(double),morethan); if (somevalues.WriteFile(args[1])) printf("[E] vbim: error writing file %s\n",args(1)); else printf("[I] vbim: wrote file %s\n",args(1)); return 0; } vbreturn op_writeprefixed(Cube &cube,tokenlist &args) { reallyload(cube); string xd=xdirname(cube.GetFileName()); string xf=xfilename(cube.GetFileName()); string fname=xd+"/"+args[1]+xf; if (xd==".") fname=args[1]+xf; if (cube.WriteFile(fname)) printf("[E] vbim: error writing file %s\n",fname.c_str()); else printf("[I] vbim: wrote file %s\n",fname.c_str()); return 0; } vbreturn op_regioninfo(Cube &cube,tokenlist &args) { reallyload(cube); cube_printregioninfo(cube,args); return 0; } vbreturn op_remap(Cube &cube,tokenlist &args) { reallyload(cube); ifstream fs; fs.open(args(1),ios::in); if (!fs) { printf("[E] vbim: couldn't read map file %s\n",args(1)); return 1; } const short bufsz=1024; char buf[bufsz]; map mymap; int fromval; float toval; tokenlist mapargs; while (fs.good()) { fs.getline(buf,bufsz); if (fs.gcount()==0) break; mapargs.ParseLine(buf); if (mapargs.size()!=2) continue; fromval=strtol(mapargs[0]); toval=strtod(mapargs[1]); if (mymap.count(fromval)) { printf("[E] vbim: duplicate value %d found in map %s\n", fromval,args(1)); fs.close(); return 1; } mymap[fromval]=toval; } fs.close(); // now build the new cube Cube newcube; newcube.SetVolume(cube.dimx,cube.dimy,cube.dimz,vb_float); int mappedcnt=0,unmappedcnt=0; for (int i=0; i(i,j,k); if (mymap.count(key)) { newcube.SetValue(i,j,k,mymap[key]); mappedcnt++; } else { newcube.SetValue(i,j,k,key); unmappedcnt++; } } } } cube=newcube; printf("[I] vbim: applied map file %s (%d voxels mapped, %d unmapped)\n", args(1),mappedcnt,unmappedcnt); return 0; } vbreturn op_info(Cube &cube,tokenlist &) { reallyload(cube); printf("[I] cube %s: min=%f max=%f infs/nans=%d\n", cube.GetFileName().c_str(), cube.get_minimum(),cube.get_maximum(),(int)cube.get_nonfinites()); return 0; } vbreturn op_mask(Cube &cube,tokenlist &args) { bool f_maskout=0; if (args[0]=="maskout") f_maskout=1; Cube mask; if (mask.ReadFile(args[1])) { cout << format("[E] vbim: couldn't open mask file %s\n")%args[1]; exit(101); } reallyload(cube); if (!dimsxyzmatch(cube,mask)) { cout << format("[E] vbim: mask dimensions don't match volume dimensions\n"); exit(102); } for (int i=0; i ret=strtodx(args[1]); if (ret.first) { cout << format("[E] vbim: invalid TR %s\n")%args[1]; exit(111); } cube.voxsize[3]=ret.second; return 0; } vbreturn op_vs(Cube &cube,tokenlist &args) { pair ret1=strtodx(args[1]); pair ret2=strtodx(args[2]); pair ret3=strtodx(args[3]); if (ret1.first) { cout << format("[E] vbim: invalid voxel size %s\n")%args[1]; exit(111); } if (ret2.first) { cout << format("[E] vbim: invalid voxel size %s\n")%args[2]; exit(111); } if (ret3.first) { cout << format("[E] vbim: invalid voxel size %s\n")%args[3]; exit(111); } cube.voxsize[0]=ret1.second; cube.voxsize[1]=ret2.second; cube.voxsize[2]=ret3.second; return 0; } vbreturn op_oo(Cube &cube,tokenlist &args) { pair ret1=strtolx(args[1]); pair ret2=strtolx(args[2]); pair ret3=strtolx(args[3]); if (ret1.first) { cout << format("[E] vbim: invalid origin %s\n")%args[1]; exit(111); } if (ret2.first) { cout << format("[E] vbim: invalid origin %s\n")%args[2]; exit(111); } if (ret3.first) { cout << format("[E] vbim: invalid origin %s\n")%args[3]; exit(111); } cube.origin[0]=ret1.second; cube.origin[1]=ret2.second; cube.origin[2]=ret3.second; return 0; } vbreturn op_addnoise(Cube &cube,tokenlist &args) { double mu=strtod(args[1]); double sigma=strtod(args[2]); double val; reallyload(cube); for (int i=0; i(i,j,k); val+=mu+gsl_ran_gaussian(rng,sigma); cube.SetValue(i,j,k,val); } } } return 0; } // procfns for combining operations vbreturn op_sum(Cube &cube,tokenlist &) { reallyload(cube); mycube+=cube; return 0; } vbreturn op_product(Cube &cube,tokenlist &) { reallyload(cube); mycube*=cube; return 0; } vbreturn op_multi(Cube &cube,tokenlist &) { reallyload(cube); cube.quantize(1.0); cube.invert(); mycube*=cube; cube.invert(); cube*=multi_index; mycube+=cube; multi_index++; return 0; } vbreturn op_union(Cube &cube,tokenlist &args) { // with one argument, we just mask each cube if (args.size()>1) { Cube mask; if (mask.ReadFile(args[1])) { cout << format("[E] vbim: couldn't load union mask %s\n")%args[1] << endl; exit(141); } reallyload(cube); cube.unionmask(mask); return 0; } // with no arguments, we do the combining operation to build mycube reallyload(cube); // cube.quantize(1.0); mycube.unionmask(cube); return 0; } vbreturn op_intersect(Cube &cube,tokenlist &args) { // with one argument, we just intersect each cube if (args.size()>1) { Cube mask; if (mask.ReadFile(args[1])) { cout << format("[E] vbim: couldn't load intersect mask %s\n")%args[1] << endl; exit(141); } reallyload(cube); cube.intersect(mask); return 0; } // with no arguments, we do the combining operation to build mycube reallyload(cube); mycube.intersect(cube); return 0; } vbreturn op_count(Cube &cube,tokenlist &) { reallyload(cube); cube.quantize(1.0); mycube+=cube; return 0; } vbreturn op_write(Cube &cube,tokenlist &args) { reallyload(cube); string fname=cube.filename; if (args.size()>1) fname=args[1]; if (args.size()>2) { replace_string(fname,"IND",(format("%05d")%cube.id1).str()); replace_string(fname,"SUB",(format("%05d")%cube.id2).str()); replace_string(fname,"TAG",(format("%s")%cube.id3).str()); } if (cube.WriteFile(fname)) cout << format("[E] vbim: error writing file %s\n")%fname; else cout << format("[I] vbim: wrote file %s\n")%fname; return 0; } // finishfns for combining operations vbreturn op_separatemasks(list &cubelist,tokenlist &) { if (cubelist.size()!=1) return 101; map rmap; int32 maxval=0; CUBI cc=cubelist.begin(); reallyload(*cc); for (int i=0; idimx; i++) { for (int j=0; jdimy; j++) { for (int k=0; kdimz; k++) { int32 val=cc->getValue(i,j,k); if (!val) continue; VBRegion &rtmp=rmap[val]; rtmp.dimx=cc->dimx; rtmp.dimy=cc->dimy; rtmp.dimz=cc->dimz; rtmp.add(i,j,k,1); if (val>maxval) maxval=val; } } } // now set up the new cubelist list newcubelist; pair r; string fmtstring=(format("%%0%dd")%lround(ceil(log(maxval)/log(10.0)))).str(); vbforeach(r,rmap) { r.second.name=(format(fmtstring)%r.first).str(); if (cc->maskspecs.count(r.first)) r.second.name=cc->maskspecs[r.first].name; Cube cb(r.second); if (r.second.name.size()) { cb.filename=r.second.name+".nii.gz"; cb.id2=r.first; cb.id3=r.second.name; } newcubelist.push_back(cb); } cubelist=newcubelist; return 0; } vbreturn op_oddeven(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; CUBI cceven,ccodd; cceven=cubelist.begin(); ccodd=cceven; ccodd++; list newcubelist; while (cceven!=cubelist.end() && ccodd!=cubelist.end()) { reallyload(*cceven); reallyload(*ccodd); *ccodd-=*cceven; newcubelist.push_back(*ccodd); cceven->invalidate(); ccodd->invalidate(); cceven++; ccodd++; cceven++; ccodd++; } cubelist.clear(); cubelist=newcubelist; return 0; } vbreturn op_uniquemask(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; Tes ts; Cube *cb=&(cubelist.front()); ts.SetVolume(cb->dimx,cb->dimy,cb->dimz,cubelist.size(),cb->datatype); int ind=0; for (CUBI cc=cubelist.begin(); cc!=cubelist.end(); cc++) { reallyload(*cc); ts.SetCube(ind++,*cc); cc->invalidate(); } Cube mask; mask.SetVolume(ts.dimx,ts.dimy,ts.dimz,vb_byte); bitmask bm; bm.resize(ts.dimt); set bset; for (int i=0; i=DBL_MIN) bm.set(m); else bm.unset(m); } if (bset.count(bm)==0) { mask.setValue(i,j,k,1); bset.insert(bm); } } } } ts.invalidate(); cubelist.clear(); cubelist.push_back(mask); return 0; } vbreturn op_overlapmask(list &cubelist,tokenlist &) { if (cubelist.size()!=2 && cubelist.size()!=3) { printf("[E] vbim: overlapmask can only work with 2 or 3 input masks\n"); return 101; } CUBI cc1,cc2,cc3; cc1=cubelist.begin(); cc2=cc1; cc2++; cc3=cc2; cc3++; reallyload(*cc1); reallyload(*cc2); cc1->filename=xsetextension(xfilename(cc1->filename),""); cc2->filename=xsetextension(xfilename(cc2->filename),""); if (cubelist.size()==3) { reallyload(*cc3); cc3->filename=xsetextension(xfilename(cc3->filename),""); } // check dims int dimx=cc1->dimx; int dimy=cc1->dimy; int dimz=cc1->dimz; for (CUBI cc=++(cubelist.begin()); cc!=cubelist.end(); cc++) { // for (size_t j=1; jdimx!=dimx || cc->dimy!=dimy || cc->dimz!=dimz) { printf("[E] vbim: overlapmask requires masks of matching dimensions\n"); return 101; } } Cube outmask; outmask.SetVolume(dimx,dimy,dimz,vb_byte); uint8 val=0; for (int i=0; itestValue(i)) val+=1; if (cc2->testValue(i)) val+=2; if (cubelist.size()==3) if (cc3->testValue(i)) val+=4; outmask.setValue(i,val); } tcolor tc; outmask.maskspecs[1]=VBMaskSpec(cc1->filename,tc.r,tc.g,tc.b); tc.next(); outmask.maskspecs[2]=VBMaskSpec(cc2->filename,tc.r,tc.g,tc.b); tc.next(); outmask.maskspecs[3]=VBMaskSpec(cc1->filename+"/"+cc2->filename,tc.r,tc.g,tc.b); tc.next(); if (cubelist.size()==3) { outmask.maskspecs[4]=VBMaskSpec(cc3->filename,tc.r,tc.g,tc.b); tc.next(); outmask.maskspecs[5]=VBMaskSpec(cc1->filename+"/"+cc3->filename,tc.r,tc.g,tc.b); tc.next(); outmask.maskspecs[6]=VBMaskSpec(cc2->filename+"/"+cc3->filename,tc.r,tc.g,tc.b); tc.next(); outmask.maskspecs[7]=VBMaskSpec(cc1->filename+"/"+cc2->filename+"/"+cc3->filename,tc.r,tc.g,tc.b); } cubelist.clear(); cubelist.push_back(outmask); return 0; } vbreturn op_null(list &cubelist,tokenlist &) { cubelist.clear(); cubelist.push_back(mycube); return 0; } vbreturn op_scale(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; mycube/=cubelist.size(); cubelist.clear(); cubelist.push_back(mycube); return 0; } vbreturn op_select(list &cubelist,tokenlist &args) { selectcubes(cubelist,strtol(args[1])); return 0; } vbreturn op_include(list &cubelist,tokenlist &args) { vector nlist=numberlist(args[1]); if (nlist.empty()) { cout << "[E] vbim: invalid range argument for include operator\n"; exit(111); } bool mymap[cubelist.size()]; memset(mymap,0,cubelist.size()*sizeof(bool)); for (size_t i=0; i=(int)cubelist.size()) { cout << "[E] vbim: invalid range for include operator\n"; exit(111); } mymap[nlist[i]]=1; } list::iterator cc=cubelist.begin(); int osize=cubelist.size(); for (int i=0; i &cubelist,tokenlist &args) { vector nlist=numberlist(args[1]); if (nlist.empty()) { cout << "[E] vbim: invalid range argument for exclude operator\n"; exit(111); } bool mymap[cubelist.size()]; memset(mymap,0,cubelist.size()*sizeof(bool)); for (size_t i=0; i=(int)cubelist.size()) { cout << "[E] vbim: invalid range for include operator\n"; exit(111); } mymap[nlist[i]]=1; } list::iterator cc=cubelist.begin(); int osize=cubelist.size(); for (int i=0; i &cubelist,tokenlist &args) { if (cubelist.size()==0) return 101; Tes ts; Cube *cb=&(cubelist.front()); ts.SetVolume(cb->dimx,cb->dimy,cb->dimz,cubelist.size(),cb->datatype); ts.CopyHeader(cubelist.front()); int ind=0; for (CUBI cc=cubelist.begin(); cc!=cubelist.end(); cc++) { reallyload(*cc); ts.SetCube(ind++,*cc); // cc->invalidate(); } int err; if ((err=ts.WriteFile(args[1]))) printf("[E] vbim: couldn't write file %s (%d)\n",args[1].c_str(),err); else printf("[I] vbim: wrote file %s\n",args[1].c_str()); return 0; } vbreturn op_writecompacted(list &cubelist,tokenlist &args) { if (cubelist.size()==0) return 101; Tes ts; Cube *cb=&(cubelist.front()); ts.SetVolume(cb->dimx,cb->dimy,cb->dimz,cubelist.size(),cb->datatype); ts.CopyHeader(cubelist.front()); int ind=0; for (CUBI cc=cubelist.begin(); cc!=cubelist.end(); cc++) { reallyload(*cc); ts.SetCube(ind++,*cc); // cc->invalidate(); } ts.compact(); int err; if ((err=ts.WriteFile(args[1]))) printf("[E] vbim: couldn't write file %s (%d)\n",args[1].c_str(),err); else printf("[I] vbim: wrote file %s\n",args[1].c_str()); return 0; } vbreturn op_writepca(list &cubelist,tokenlist &args) { if (cubelist.size()==0) return 101; Cube mask; if (mask.ReadFile(args[2])) { cout << format("[E] vbim: couldn't read mask file %s\n")%mask; return 102; } if (mask.dimx != cubelist.front().dimx || mask.dimy != cubelist.front().dimy || mask.dimz != cubelist.front().dimz) { cout << format("[E] vbim: mismatched mask dimensions\n"); return 103; } int n=mask.count(); VBMatrix data(cubelist.size(),n); int ind=0; for (int i=0; igetValue(i)); } // DO THE PCA VB_Vector l(1); VBMatrix comp; VBMatrix e; cout << format("m=%d n=%d\n")%data.m%data.n; if (pca(data,l,comp,e)) { cout << format("[E] vbim: error doing PCA\n"); return 104; } // COPY TO TES int requested=strtol(args[1]); Tes ts(1,1,comp.n,comp.m,vb_float); ts.CopyHeader(cubelist.front()); for (size_t i=0; i &cubelist,tokenlist &args) { if (f_read4d) return op_write4d(cubelist,args); // we only read 3d files, so we should write out each file int ind=0; vbforeach(Cube &c,cubelist) { string fname=c.filename; if (args.size()>1) { fname=args[1]; string num=(format("%05d")%ind).str(); replace_string(fname,"XXX",num); } if (c.WriteFile(fname)) cout << format("[E] vbim: error writing file %s\n")%fname; else cout << format("[I] vbim: wrote file %s\n")%fname; ind++; } return 0; } vbreturn op_newvol(list &cubelist,tokenlist &args) { cubelist.clear(); int32 dimx=strtol(args[1]); int32 dimy=strtol(args[2]); int32 dimz=strtol(args[3]); int32 dimt=strtol(args[4]); VB_datatype dt; int ds; parsedatatype(args[5],dt,ds); if (dimx<0||dimy<0||dimz<0||dimt<0|| dimx>MAX_DIM||dimy>MAX_DIM||dimz>MAX_DIM||dimy>MAX_DIM) { cout << "[E] vbim: invalid dimensions for new volume\n"; exit(199); } if (dimt<1) dimt=1; for (int i=0; i ...] general flags: -i ... specify an arbitrary number of input files -files/-input/-f same as -i, for convenience -o a single output file, will be 3D or 4D -h show help -v show version options for building volumes: -newvol newvol creates new empty volumes -random01 fill entire volume with random 0s and 1s -addnoise add Gaussian noise (an optional third argument is the PRNG seed -- see vbsim for more info) image processing operations: -smoothvox 3D Gaussian smooth -smoothvox2 3D Gaussian smooth with out-of-brain correction -smoothmm 3D Gaussian smooth -smoothmm2 3D Gaussian smooth with out-of-brain correction -thresh zero where <= val -threshabs zero where absolute value <= val -cutoff zero where >= val -quantize set non-zero values to val -convert see below -add add image (if file exists) or scalar -sub subtract image (if file exists) or scalar -mult multiply by image (if file exists) or scalar -div divide by image (if file exists) or scalar -nminus subtract from img (if file exists) or scalar -signflip flip sign -abs absolute value -flipx/flipy/flipz flip x, y, or z axis -bigendian/littleendian change how the data will be written out -nonans replace NaNs and Infs with 0 -byteswap -zeroleft/zeroright -rotate

rotate around origin using pitch/roll/yaw in degrees -regionat create mask of region including voxel at coordinates x,y,z -splitregions output filename (XXX will be replaced by an index) -setspace reset or copy (if file is provided) orientation info -remap file has two values per line: old value and new value -combine ... see below # NOT YET IMPLEMENTED: # orient RPI notation, use -- as from for current orientation # ndividedby # removesmallregions // uses function zerosmallregions(cube,double) mask-related -maskcombine see below -maskselect include only values in supplied list (e.g., 3,24,37-40) -mask mask volume (0's masked out) -maskout mask volume (non-0's masked out) -subdivide subdivide mask using cubes of given dimensions -invert zet non-zeros to zero, zeros to 1 -multi combine input masks into a multi-mask -union [] combine input masks by calculating the union. if mask is provided, apply it separately to each volume. -intersect [] combine input masks by calculating the intersection. if mask is provided, apply it separately to each volume. -count combine input masks by counting non-zero voxels -overlapmask create a color-coded overlap mask of up to 3 masks -uniquemask included voxels will differ in at least one mask -separatemasks separate a 3D multi-ROI volume into separate masks with appropriate filenames already set combining operations: -sum sum all volumes -average average all volumes -product product of all volumes -select randomly select n volumes (discard the rest) -include include volumes in range, e.g., 0-5,7,9-13 (no spaces) -exclude exclude volumes in range, e.g., 0-5,7,9-13 (no spaces) -oddeven replace each pair of images with odd minus even -writecompacted reform 4D data to include only masked-in voxels # -writepca write a 4D file including only the first # n principal components output/summary operations: -write write 3d output, name is optional. if the third argument is supplied, then the string SUB in the filename is replaced with the volume number. -writeprefixed prefix each volume's original name and write -write4d combine the volumes into a 4d file -writeref writes non-zero values, sorted ascending, to a file -info print general info about each 3D volume -regioninfo print region info for all contiguous non-zero regions -regioninfo print region info for region in provided mask examples: Type "vbim -h examples" to see some examples. notes: All arguments that come before the first operation are considered input files. So you can usually omit the -i and do this: vbim *.nii.gz -sum -write sum.nii.gz vbim takes multiple 3D volumes (contained in any combination of 3D and 4D files) and applies the specified image processing operations, in the order specified. vbim replaces all of voxbo's old image/mask mungers. If there's missing functionality you need, please let us know. vbim has three kinds of operations. Image processing operations are applied to each 3D volume independently. Combining operations apply to the whole set of 3D volumes and typically reduce the set to a single volume. Output/summary operations print out information about the volumes as they exist at that point and/or write out files. The operations are applied in the order given, and can be mixed freely (e.g., you can have multiple image processing operations intermixed with the -write operation to save a copy of each step along the way). For the -convert and -newvol operations, valid types are: byte, int16, int32, float, and double. When converting to float or double, images are un-scaled if needed (slope and intercept are factored into the stored values directly). Note that VoxBo historically has used more ambiguous names for int16 and int32. The -combine operation implements several methods for re-calculating each voxel's value as a combination of surrounding voxels. It takes five arguments. The first argment is either "fixed" or "moving" (aka f/m). Fixed means that the brain is divided into fixed subregions, and each voxel in a given subregion gets the same value. Moving means that each voxel gets a value calculated from a region centered at that voxel. The next three arguments are the size of the region in x, y, and z, in voxels. The final argument is the combination method: one of sum count (count nonzero), average, or pct (percent nonzero). Note that the output is stored in the same format as the input, so you may want to convert to a different datatype before performing some operations (e.g., many masks are stored as byte data, which can only represent integers in the 0-255 range). The -maskcombine operator is similar to -combine, using an input mask to define the subregions. The first argument is the name of a mask file, the second is the operator to use. The sum, count, average, and pct operators are supported. -smoothvox2 and -smoothmm2 do Gaussian smoothing without averaging in 0's from outside the volume. voxbo-1.8.5~svn1246/munge/vbim_examples.hlp000066400000000000000000000013741153177201300206040ustar00rootroot00000000000000Here are some examples of using vbim: To get very basic info about a file: vbim foo.nii -info To get more detailed information about the data within a mask: vbim foo.nii -regioninfo mask.nii To apply a mask to a 3D image and write out the result: vbim image.nii -mask mask.nii -write maskedimage.nii To mask a 4D image: vbim image.nii -mask mask.nii -write4D maskedimage.nii To average a bunch of 3D volumes: vbim *.nii.gz -average -write mean.nii.gz To create a lesion count map from a set of lesion masks: vbim *.nii -count -write count.nii.gz To create a 4D volume (20x20x20 voxels, 32-bit int, 10 time points) of random data with a mean of 100 and sd of 10: vbim -newvol 20 20 20 10 int32 -addnoise 100 10 -write3d myvol.nii voxbo-1.8.5~svn1246/munge/vbimagemunge.cpp000066400000000000000000000760331153177201300204220ustar00rootroot00000000000000 // vbimagemunge.cpp // general-purpose munging util for voxbo // Copyright (c) 2003-2009 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include "vbutil.h" #include "vbio.h" #include "imageutils.h" #include "vbversion.h" #include "vbimagemunge.hlp.h" void vbimagemunge_help(); void vbimagemunge_version(); int cube_combine(Cube &cb,tokenlist &args); void selectcubes(list &clist,size_t n); bool comparedims(list cubelist); void cube_random01(Cube &cb); void cube_printregioninfo(Cube &cb); void reallyload(Cube &cube); void build_oplist(); // ugly globals -- code needs some reorg Cube mycube; int multi_index; class imageop { public: string name; int nargs; tokenlist args; // an operator is combining if either initfn or finishfn is non-null vbreturn (*initfn)(list &cubelist,tokenlist &args); vbreturn (*procfn)(Cube &cube,tokenlist &args); vbreturn (*finishfn)(list &cubelist,tokenlist &args); // storage for combining operators // sole constructor requires name and nargs imageop(); imageop(string xname,int xnargs,vbreturn (*xprocfn)(Cube &,tokenlist &)); void init(string xname,int xnargs,vbreturn (*xprocfn)(Cube &,tokenlist &)); // random methods bool iscombining() {return (initfn!=NULL || finishfn!=NULL);} }; imageop::imageop() { init("",0,NULL); } imageop::imageop(string xname,int xnargs,vbreturn (*xprocfn)(Cube &,tokenlist &)) { init(xname,xnargs,xprocfn); } void imageop::init(string xname,int xnargs,vbreturn (*xprocfn)(Cube &,tokenlist &)) { name=xname; nargs=xnargs; args.clear(); initfn=NULL; procfn=xprocfn; finishfn=NULL; } // three operator lists that are handled differently list phase1; // do the cubes one at a time. if last operator is combining, feed. list phase2; // do each operator for all cubes typedef list::iterator OPI; typedef list::iterator CUBI; map oplist; int main(int argc,char *argv[]) { if (argc==1) { vbimagemunge_help(); exit(0); } build_oplist(); tokenlist args; list filelist; // string outfile; args.Transfer(argc-1,argv+1); bool inops=0; int phase=1; for (size_t i=0; i=args.size()) { printf("[E] vbimagemunge: operator %s requires %d arguments\n", myop.name.c_str(),myop.nargs); exit(203); } myop.args.Add(args[i]); // first arg is the operator name for (int j=0; j cubelist; Cube master; // pre-load all the files. we should figure out how not to load all // the image data from 4D files, maybe. for (list::iterator ff=filelist.begin(); ff!=filelist.end(); ff++) { printf("[I] vbimagemunge: reading file %s\n",ff->c_str()); Cube cb; Tes ts; if (cb.ReadHeader(*ff)==0) { cubelist.push_back(cb); continue; } if (ts.ReadFile(*ff)) { printf("[E] vbimagemunge: couldn't read file %s, continuing anyway\n",ff->c_str()); continue; } for (int i=0; iprocfn) oo->procfn(*cc,oo->args); } index++; } if (phase1.back().iscombining() && phase1.back().finishfn) phase1.back().finishfn(cubelist,phase1.back().args); } // if we have a phase2 block, now do that for (OPI oo=phase2.begin(); oo!=phase2.end(); oo++) { if (oo->initfn) oo->initfn(cubelist,oo->args); index=0; for (CUBI cc=cubelist.begin(); cc!=cubelist.end(); cc++) { if (oo->procfn) oo->procfn(*cc,oo->args); index++; } if (oo->finishfn) oo->finishfn(cubelist,oo->args); } exit(0); } // for "combine" the arguments are: // combine fixed/moving x y z op value template int cube_combine_fixed(Cube &cb,tokenlist &args) { int xx=strtol(args[2]); int yy=strtol(args[3]); int zz=strtol(args[4]); string method=args[5]; double value=strtod(args[6]); int f_needval=0; if (method=="sum" || method=="average" || method=="sumthresh" || method=="averagethresh") f_needval=1; if (xx<1 || yy<1 || zz<1) { printf("[E] vbimagemunge: invalid subcube dimensions\n"); return 101; } Cube cb2(cb); // initial subcube range 0:xx-1, etc. int x1=0,y1=0,z1=0; int xn=xx-1,yn=yy-1,zn=zz-1; int i,j,k,count; double total; T val; while(1) { count=0; total=0.0; if (x1>cb.dimx-1 || y1>cb.dimy-1 || z1>cb.dimz-1) break; if (xn>cb.dimx-1) xn=cb.dimx-1; if (yn>cb.dimy-1) yn=cb.dimy-1; if (zn>cb.dimz-1) zn=cb.dimz-1; for (i=x1; i<=xn; i++) { for (j=y1; j<=yn; j++) { for (k=z1; k<=zn; k++) { if (f_needval) { val=cb.getValue(i,j,k); if (val>0.0) count++; total+=val; } else if (cb.testValue(i,j,k)) count++; } } } // calculate the replacement value -- sum, count, average, // pct, any sumthresh, averagethresh T newvalue=0; int rsize=(xn-x1+1)*(yn-y1+1)*(zn-z1+1); if (method=="count") newvalue=count; else if (method=="sum") newvalue=total; else if (method=="pct") newvalue=(count*100)/rsize; else if (method=="average") newvalue=total/rsize; else if (method=="any") { if (count) newvalue=1; } else if (method=="sumthresh") { if (total>value) newvalue=1; } else if (method=="averagethresh") { if ((total/rsize)>value) newvalue=1; } else newvalue=0; // all voxels in the subcube get the identical new value for (i=x1; i<=xn; i++) { for (j=y1; j<=yn; j++) { for (k=z1; k<=zn; k++) { cb2.setValue(i,j,k,newvalue); } } } // next subcube if (xn int cube_combine_moving(Cube &cb,tokenlist &args) { int xx=strtol(args[2]); int yy=strtol(args[3]); int zz=strtol(args[4]); string method=args[5]; double value=strtod(args[6]); int f_needval=0; if (method=="sum" || method=="average" || method=="sumthresh" || method=="averagethresh") f_needval=1; if (xx<1 || yy<1 || zz<1) { printf("[E] vbimagemunge: invalid subcube dimensions\n"); return 101; } Cube cb2(cb); // initial subcube range 0:xx-1, etc. int x1=0,y1=0,z1=0; int xn=xx-1,yn=yy-1,zn=zz-1; int i,j,k,count; double total; T val; for (int xxx=0; xxx<=cb.dimx; xxx++) { for (int yyy=0; yyy<=cb.dimy; yyy++) { for (int zzz=0; zzz<=cb.dimz; zzz++) { count=0; total=0.0; // build a neighborhood around the voxel x1=xxx-xx/2; xn=x1+xx-1; y1=yyy-yy/2; yn=y1+yy-1; z1=zzz-zz/2; zn=z1+zz-1; // clip it to cube boundaries if (x1<0) x1=0; if (y1<0) y1=0; if (z1<0) z1=0; if (xn>cb.dimx-1) xn=cb.dimx-1; if (yn>cb.dimy-1) yn=cb.dimy-1; if (zn>cb.dimz-1) zn=cb.dimz-1; for (i=x1; i<=xn; i++) { for (j=y1; j<=yn; j++) { for (k=z1; k<=zn; k++) { if (f_needval) { val=cb.getValue(i,j,k); if (val>0.0) count++; total+=val; } else if (cb.testValue(i,j,k)) count++; } } } // calculate the replacement value -- sum, count, average, // pct, any sumthresh, averagethresh T newvalue=0; int rsize=(xn-x1+1)*(yn-y1+1)*(zn-z1+1); if (method=="count") newvalue=count; else if (method=="sum") newvalue=total; else if (method=="pct") newvalue=(count*100)/rsize; else if (method=="average") newvalue=total/rsize; else if (method=="any") { if (count) newvalue=1; } else if (method=="sumthresh") { if (total>value) newvalue=1; } else if (method=="averagethresh") { if ((total/rsize)>value) newvalue=1; } else newvalue=0; // set just the original voxel cb2.setValue(xxx,yyy,zzz,newvalue); } } } cb=cb2; return 0; } int cube_combine(Cube &cb,tokenlist &args) { if (args[1]=="fixed" || args[1]=="f") { switch(cb.datatype) { case vb_byte: return cube_combine_fixed(cb,args); break; case vb_short: return cube_combine_fixed(cb,args); break; case vb_long: return cube_combine_fixed(cb,args); break; case vb_float: return cube_combine_fixed(cb,args); break; case vb_double: return cube_combine_fixed(cb,args); break; } } else if (args[1]=="moving" || args[1]=="m") { switch(cb.datatype) { case vb_byte: return cube_combine_moving(cb,args); break; case vb_short: return cube_combine_moving(cb,args); break; case vb_long: return cube_combine_moving(cb,args); break; case vb_float: return cube_combine_moving(cb,args); break; case vb_double: return cube_combine_moving(cb,args); break; } } return 101; // shouldn't happen } void cube_printregioninfo(Cube &cb) { vector rlist=findregions(cb,vb_ne,0.0); int totalvoxels=0; for (size_t i=0; isecond.x; y1+=myvox->second.y; z1+=myvox->second.z; x2+=myvox->second.x*myvox->second.val; y2+=myvox->second.y*myvox->second.val; z2+=myvox->second.z*myvox->second.val; totalmass+=myvox->second.val; } x1/=rlist[i].size(); y1/=rlist[i].size(); z1/=rlist[i].size(); x2/=totalmass; y2/=totalmass; z2/=totalmass; printf("[I] vbimagemunge: region %d, %d voxels,",(int)i,(int)(rlist[i].size())); printf(" center of mass: %g,%g,%g (weighted: %g,%g,%g)\n",x1,y1,z1,x2,y2,z2); // totalvoxels+=rlist[i].size(); } // printf("[I] vbimagemunge: %d total voxels in volume %s\n",totalvoxels,cb.GetFileName().c_str()); } void cube_random01(Cube &cb) { uint32 rr=0; int pos=32; cb.zero(); for (int i=0; i31) { rr=VBRandom(); pos=0; } if (rr & 1< &clist,size_t n) { if (n>=clist.size() || n<1) return; map randlist; while (randlist.size()::iterator mm=randlist.begin(); list::iterator cc=clist.begin(); int oldn=clist.size(); for (int i=0; isecond) cc++; else cc=clist.erase(cc); mm++; } } bool comparedims(list cubelist) { if (cubelist.size()<2) return 1; list::iterator cc=cubelist.begin(); int dimx=cc->dimx; int dimy=cc->dimy; int dimz=cc->dimz; cc++; while (cc!=cubelist.end()) { if (cc->dimx!=dimx || cc->dimy!=dimy || cc->dimz!=dimz) return 0; cc++; } return 1; } // initfns vbreturn op_shortzeros(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; mycube.SetVolume(cubelist.front().dimx,cubelist.front().dimy, cubelist.front().dimz,vb_short); return 0; } vbreturn op_allones(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; reallyload(cubelist.front()); mycube=cubelist.front(); mycube.quantize(1.0); return 0; } vbreturn op_allzeros(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; reallyload(cubelist.front()); mycube=cubelist.front(); mycube.zero(); return 0; } vbreturn op_copy(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; reallyload(cubelist.front()); mycube=cubelist.front(); return 0; } // procfn vbreturn op_smoothvox(Cube &cube,tokenlist &args) { reallyload(cube); smoothCube(cube,strtod(args[1]),strtod(args[2]),strtod(args[3])); return 0; } vbreturn op_smoothmm(Cube &cube,tokenlist &) { reallyload(cube); printf("smoothmm not implemented\n"); exit(5); return 0; } vbreturn op_thresh(Cube &cube,tokenlist &args) { reallyload(cube); cube.thresh(strtod(args[1])); return 0; } vbreturn op_rotate(Cube &cube,tokenlist &args) { reallyload(cube); rotatecube(cube,strtod(args[1]),strtod(args[2]),strtod(args[3])); return 0; } vbreturn op_regionat(Cube &cube,tokenlist &args) { reallyload(cube); Cube mask; mask.SetVolume(cube.dimx,cube.dimy,cube.dimz,vb_short); mask+=1; VBRegion rr; rr=growregion(strtol(args[1]),strtol(args[2]),strtol(args[3]),cube,mask,vb_agt,FLT_MIN); mask*=0; for (VI myvox=rr.begin(); myvox!=rr.end(); myvox++) { mask.setValue(myvox->second.x,myvox->second.y,myvox->second.z,(int32)1); } cube=mask; return 0; } vbreturn op_splitregions(Cube &cube,tokenlist &args) { reallyload(cube); vector regions; regions=findregions(cube,vb_gt,0.0); Cube mask; mask.SetVolume(cube.dimx,cube.dimy,cube.dimz,vb_byte); int index=0; string fname; vbforeach(VBRegion &rr,regions) { mask.zero(); for (VI myvox=rr.begin(); myvox!=rr.end(); myvox++) mask.setValue(myvox->second.x,myvox->second.y,myvox->second.z,1); fname=args[1]; string num=(format("%05d")%index).str(); replace_string(fname,"XXX",num); mask.WriteFile(fname); index++; } cube=mask; return 0; } vbreturn op_threshabs(Cube &cube,tokenlist &args) { reallyload(cube); cube.threshabs(strtod(args[1])); return 0; } vbreturn op_cutoff(Cube &cube,tokenlist &args) { reallyload(cube); cube.cutoff(strtod(args[1])); return 0; } vbreturn op_orient(Cube &cube,tokenlist &) { reallyload(cube); printf("orient not implemented\n"); exit(5); return 0; } vbreturn op_quantize(Cube &cube,tokenlist &args) { reallyload(cube); cube.quantize(strtod(args[1])); return 0; } vbreturn op_invert(Cube &cube,tokenlist &) { reallyload(cube); cube.invert(); return 0; } vbreturn op_flipx(Cube &cube,tokenlist &) { reallyload(cube); cube.flipx(); return 0; } vbreturn op_flipy(Cube &cube,tokenlist &) { reallyload(cube); cube.flipy(); return 0; } vbreturn op_flipz(Cube &cube,tokenlist &) { reallyload(cube); cube.flipz(); return 0; } vbreturn op_zeroleft(Cube &cube,tokenlist &) { reallyload(cube); cube.rightify(); return 0; } vbreturn op_zeroright(Cube &cube,tokenlist &) { reallyload(cube); cube.leftify(); return 0; } vbreturn op_bigendian(Cube &cube,tokenlist &) { reallyload(cube); cube.filebyteorder=ENDIAN_BIG; return 0; } vbreturn op_littleendian(Cube &cube,tokenlist &) { reallyload(cube); cube.filebyteorder=ENDIAN_LITTLE; return 0; } vbreturn op_byteswap(Cube &cube,tokenlist &) { reallyload(cube); cube.byteswap(); return 0; } vbreturn op_combine(Cube &cube,tokenlist &args) { reallyload(cube); if (cube_combine(cube,args)) { printf("[E] vbimagemunge: error downsampling\n"); exit(212); } return 0; } vbreturn op_convert(Cube &cube,tokenlist &args) { reallyload(cube); Cube tmpc; string newtype=vb_tolower(args[1]); int err=1; if (newtype=="byte") err=cube.convert_type(vb_byte,VBSETALT); if (newtype=="int16") err=cube.convert_type(vb_short,VBSETALT); if (newtype=="int32") err=cube.convert_type(vb_long,VBSETALT); if (newtype=="float") err=cube.convert_type(vb_float,VBSETALT|VBNOSCALE); if (newtype=="double") err=cube.convert_type(vb_double,VBSETALT|VBNOSCALE); if (err) { printf("[E] vbimagemunge: error converting datatype\n"); exit(212); } cube=tmpc; return 0; } vbreturn op_removesmallregions(Cube &cube,tokenlist &) { reallyload(cube); return 0; } vbreturn op_add(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbimagemunge: couldn't read file %s\n",args(1)); exit(202); } cube+=tmp; } else cube+=strtod(args[1]); return 0; } vbreturn op_sub(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbimagemunge: couldn't read file %s\n",args(1)); exit(202); } cube-=tmp; } else cube-=strtod(args[1]); return 0; } vbreturn op_mult(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbimagemunge: couldn't read file %s\n",args(1)); exit(202); } cube*=tmp; } else cube*=strtod(args[1]); return 0; } vbreturn op_div(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbimagemunge: couldn't read file %s\n",args(1)); exit(202); } cube/=tmp; } else cube/=strtod(args[1]); return 0; } vbreturn op_nminus(Cube &cube,tokenlist &args) { reallyload(cube); if (vb_fileexists(args[1])) { Cube tmp; if (tmp.ReadFile(args[1])) { printf("[E] vbimagemunge: couldn't read file %s\n",args(1)); exit(202); } cube=tmp-cube; } else { cube-=strtod(args[1]); cube*=-1.0; } return 0; } vbreturn op_random01(Cube &cube,tokenlist &) { reallyload(cube); cube_random01(cube); return 0; } vbreturn op_write(Cube &cube,tokenlist &args) { reallyload(cube); if (cube.WriteFile(args[1])) printf("[E] vbimagemunge: error writing file %s\n",args(1)); else printf("[I] vbimagemunge: wrote file %s\n",args(1)); return 0; } vbreturn op_writeprefixed(Cube &cube,tokenlist &args) { reallyload(cube); string xd=xdirname(cube.GetFileName()); string xf=xfilename(cube.GetFileName()); string fname=xd+"/"+args[1]+xf; if (xd==".") fname=args[1]+xf; if (cube.WriteFile(fname)) printf("[E] vbimagemunge: error writing file %s\n",fname.c_str()); else printf("[I] vbimagemunge: wrote file %s\n",fname.c_str()); return 0; } vbreturn op_regioninfo(Cube &cube,tokenlist &) { reallyload(cube); cube_printregioninfo(cube); return 0; } vbreturn op_remap(Cube &cube,tokenlist &args) { reallyload(cube); ifstream fs; fs.open(args(1),ios::in); if (!fs) { printf("[E] vbimagemunge: couldn't read map file %s\n",args(1)); return 1; } const short bufsz=1024; char buf[bufsz]; map mymap; int fromval; float toval; tokenlist mapargs; while (fs.good()) { fs.getline(buf,bufsz); if (fs.gcount()==0) break; mapargs.ParseLine(buf); if (mapargs.size()!=2) continue; fromval=strtol(mapargs[0]); toval=strtod(mapargs[1]); if (mymap.count(fromval)) { printf("[E] vbimagemunge: duplicate value %d found in map %s\n", fromval,args(1)); fs.close(); return 1; } mymap[fromval]=toval; } fs.close(); // now build the new cube Cube newcube; newcube.SetVolume(cube.dimx,cube.dimy,cube.dimz,vb_float); int mappedcnt=0,unmappedcnt=0; for (int i=0; i(i,j,k); if (mymap.count(key)) { newcube.SetValue(i,j,k,mymap[key]); mappedcnt++; } else { newcube.SetValue(i,j,k,key); unmappedcnt++; } } } } cube=newcube; printf("[I] vbimagemunge: applied map file %s (%d voxels mapped, %d unmapped)\n", args(1),mappedcnt,unmappedcnt); return 0; } vbreturn op_info(Cube &cube,tokenlist &) { reallyload(cube); printf("[I] cube %s: min=%f max=%f infs/nans=%d\n", cube.GetFileName().c_str(), cube.get_minimum(),cube.get_maximum(),(int)cube.get_nonfinites()); return 0; } // procfns for combining operations vbreturn op_sum(Cube &cube,tokenlist &) { reallyload(cube); mycube+=cube; return 0; } vbreturn op_product(Cube &cube,tokenlist &) { reallyload(cube); mycube*=cube; return 0; } vbreturn op_multi(Cube &cube,tokenlist &) { reallyload(cube); cube.quantize(1.0); cube.invert(); mycube*=cube; cube.invert(); cube*=multi_index; mycube+=cube; multi_index++; return 0; } vbreturn op_union(Cube &cube,tokenlist &) { reallyload(cube); cube.quantize(1.0); mycube.unionmask(cube); return 0; } vbreturn op_intersect(Cube &cube,tokenlist &) { reallyload(cube); mycube.intersect(cube); return 0; } vbreturn op_count(Cube &cube,tokenlist &) { reallyload(cube); cube.quantize(1.0); mycube+=cube; return 0; } // finishfns for combining operations vbreturn op_overlapmask(list &cubelist,tokenlist &) { if (cubelist.size()!=2 && cubelist.size()!=3) { printf("[E] vbimagemunge: overlapmask can only work with 2 or 3 input masks\n"); return 101; } CUBI cc1,cc2,cc3; cc1=cubelist.begin(); cc2=cc1; cc2++; cc3=cc2; cc3++; reallyload(*cc1); reallyload(*cc2); cc1->filename=xsetextension(xfilename(cc1->filename),""); cc2->filename=xsetextension(xfilename(cc2->filename),""); if (cubelist.size()==3) { reallyload(*cc3); cc3->filename=xsetextension(xfilename(cc3->filename),""); } // check dims int dimx=cc1->dimx; int dimy=cc1->dimy; int dimz=cc1->dimz; for (CUBI cc=++(cubelist.begin()); cc!=cubelist.end(); cc++) { // for (size_t j=1; jdimx!=dimx || cc->dimy!=dimy || cc->dimz!=dimz) { printf("[E] vbimagemunge: overlapmask requires masks of matching dimensions\n"); return 101; } } Cube outmask; outmask.SetVolume(dimx,dimy,dimz,vb_byte); uint8 val=0; for (int i=0; itestValue(i)) val+=1; if (cc2->testValue(i)) val+=2; if (cubelist.size()==3) if (cc3->testValue(i)) val+=4; outmask.setValue(i,val); } outmask.AddHeader((string)"vb_maskspec: 1 255 0 0 "+cc1->filename); outmask.AddHeader((string)"vb_maskspec: 2 0 0 255 "+cc2->filename); outmask.AddHeader((string)"vb_maskspec: 3 170 0 170 \""+cc1->filename+"/"+cc2->filename+"\""); if (cubelist.size()==3) { outmask.AddHeader((string)"vb_maskspec: 4 220 220 0 "+cc3->filename); outmask.AddHeader((string)"vb_maskspec: 5 255 140 0 \""+cc1->filename+"/"+cc3->filename+"\""); outmask.AddHeader((string)"vb_maskspec: 6 0 255 0 \""+cc2->filename+"/"+cc3->filename+"\""); outmask.AddHeader((string)"vb_maskspec: 7 140 140 80\""+cc1->filename+"/"+cc2->filename+"/"+cc3->filename+"\""); } cubelist.clear(); cubelist.push_back(outmask); return 0; } vbreturn op_null(list &cubelist,tokenlist &) { cubelist.clear(); cubelist.push_back(mycube); return 0; } vbreturn op_scale(list &cubelist,tokenlist &) { if (cubelist.size()==0) return 101; mycube/=cubelist.size(); cubelist.clear(); cubelist.push_back(mycube); return 0; } vbreturn op_select(list &cubelist,tokenlist &args) { selectcubes(cubelist,strtol(args[1])); return 0; } vbreturn op_include(list &cubelist,tokenlist &args) { vector nlist=numberlist(args[1]); bool mymap[cubelist.size()]; memset(mymap,0,cubelist.size()*sizeof(bool)); for (size_t i=0; i::iterator cc=cubelist.begin(); int osize=cubelist.size(); for (int i=0; i &cubelist,tokenlist &args) { vector nlist=numberlist(args[1]); bool mymap[cubelist.size()]; memset(mymap,0,cubelist.size()*sizeof(bool)); for (size_t i=0; i::iterator cc=cubelist.begin(); int osize=cubelist.size(); for (int i=0; i &cubelist,tokenlist &args) { if (cubelist.size()==0) return 101; Tes ts; Cube *cb=&(cubelist.front()); ts.SetVolume(cb->dimx,cb->dimy,cb->dimz,cubelist.size(),cb->datatype); int ind=0; for (CUBI cc=cubelist.begin(); cc!=cubelist.end(); cc++) { reallyload(*cc); ts.SetCube(ind++,*cc); cc->invalidate(); } if (ts.WriteFile(args[1])) printf("[E] vbimagemunge: couldn't write file %s\n",args[1].c_str()); else printf("[I] vbimagemunge: wrote file %s\n",args[1].c_str()); return 0; } void build_oplist() { // non-combining ones are easy oplist["smoothvox"]=imageop("smoothvox",3,op_smoothvox); oplist["smoothmm"]=imageop("smoothmm",3,op_smoothmm); oplist["thresh"]=imageop("thresh",1,op_thresh); oplist["rotate"]=imageop("rotate",3,op_rotate); oplist["regionat"]=imageop("regionat",3,op_regionat); oplist["threshabs"]=imageop("threshabs",1,op_threshabs); oplist["cutoff"]=imageop("cutoff",1,op_cutoff); oplist["invert"]=imageop("invert",0,op_invert); oplist["splitregions"]=imageop("splitregions",1,op_splitregions); oplist["flipx"]=imageop("flipx",0,op_flipx); oplist["flipy"]=imageop("flipy",0,op_flipy); oplist["flipz"]=imageop("flipz",0,op_flipz); oplist["zeroleft"]=imageop("zeroleft",0,op_zeroleft); oplist["zeroright"]=imageop("zeroright",0,op_zeroright); oplist["bigendian"]=imageop("bigendian",0,op_bigendian); oplist["littleendian"]=imageop("zeroright",0,op_littleendian); oplist["byteswap"]=imageop("zeroright",0,op_byteswap); oplist["orient"]=imageop("",99,op_orient); oplist["quantize"]=imageop("quantize",1,op_quantize); oplist["remap"]=imageop("remap",1,op_remap); oplist["combine"]=imageop("combine",6,op_combine); oplist["convert"]=imageop("convert",1,op_convert); oplist["removesmallregions"]=imageop("removesmallregions",1,op_removesmallregions); oplist["add"]=imageop("add",1,op_add); oplist["sub"]=imageop("sub",1,op_sub); oplist["mult"]=imageop("mult",1,op_mult); oplist["div"]=imageop("div",1,op_div); oplist["nminus"]=imageop("nminus",1,op_nminus); oplist["random01"]=imageop("random01",0,op_random01); oplist["write"]=imageop("write",1,op_write); oplist["writeprefixed"]=imageop("writeprefixed",1,op_writeprefixed); oplist["regioninfo"]=imageop("regioninfo",0,op_regioninfo); oplist["info"]=imageop("info",0,op_info); // combining operators take a little more work imageop tmp; // by doing it this way, all the cubes are in core before we select. // if we create an initfn that stores the inclusion map and a procfn // that invalidates the data for the ones we don't want, we can be // tighter about memory tmp=imageop("overlapmask",0,NULL); tmp.finishfn=op_overlapmask; oplist[tmp.name]=tmp; tmp=imageop("select",1,NULL); tmp.finishfn=op_select; oplist[tmp.name]=tmp; tmp=imageop("include",1,NULL); tmp.finishfn=op_include; oplist[tmp.name]=tmp; tmp=imageop("exclude",1,NULL); tmp.finishfn=op_exclude; oplist[tmp.name]=tmp; tmp=imageop("sum",0,NULL); tmp.initfn=op_allzeros; tmp.procfn=op_sum; tmp.finishfn=op_null; oplist[tmp.name]=tmp; tmp=imageop("average",0,NULL); tmp.initfn=op_allzeros; tmp.procfn=op_sum; tmp.finishfn=op_scale; oplist[tmp.name]=tmp; tmp=imageop("multi",0,NULL); tmp.initfn=op_shortzeros; tmp.procfn=op_multi; tmp.finishfn=op_null; oplist[tmp.name]=tmp; tmp=imageop("union",0,NULL); tmp.initfn=op_shortzeros; tmp.procfn=op_union; tmp.finishfn=op_null; oplist[tmp.name]=tmp; tmp=imageop("intersect",0,NULL); tmp.initfn=op_allones; tmp.procfn=op_intersect; tmp.finishfn=op_null; oplist[tmp.name]=tmp; tmp=imageop("count",0,NULL); tmp.initfn=op_shortzeros; tmp.procfn=op_count; tmp.finishfn=op_null; oplist[tmp.name]=tmp; tmp=imageop("product",0,NULL); tmp.initfn=op_allones; tmp.procfn=op_product; tmp.finishfn=op_null; oplist[tmp.name]=tmp; tmp=imageop("write4d",1,NULL); tmp.finishfn=op_write4d; oplist[tmp.name]=tmp; } void reallyload(Cube &cube) { if (cube.data) return; if (cube.ReadData(cube.GetFileName())) printf("[E] vbimagemunge: error reading file %s\n",cube.GetFileName().c_str()); } void vbimagemunge_help() { cout << boost::format(myhelp) % vbversion; } void vbimagemunge_version() { printf("VoxBo vbimagemunge (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vbimagemunge.hlp000066400000000000000000000111201153177201300204050ustar00rootroot00000000000000VoxBo vbimagemunge (v%1%) summary: image munging for VoxBo usage: vbimagemunge [ ...] -- [ ...] flags: -h show help -v show version image processing operations: smoothvox 3D Gaussian smooth smoothmm 3D Gaussian smooth thresh zero where <= val threshabs zero where absolute value <= val cutoff zero where >= val quantize set non-zero values to val invert zet non-zeros to zero, zeros to 1 combine ... see below convert see below add add image (if file exists) or scalar sub subtract image (if file exists) or scalar mult multiply by image (if file exists) or scalar div divide by image (if file exists) or scalar nminus subtract from img (if file exists) or scalar random01 fill entire volume with random 0s and 1s remap file has two values per line: old value and new value flipx/flipy/flipz bigendian/littleendian change how the data will be written out byteswap zeroleft/zeroright rotate regionat find region including voxel at coordinates x,y,z splitregions output filename (XXX will be replaced by an index) # NOT YET IMPLEMENTED: # orient RPI notation, use -- as from for current orientation # ndividedby # removesmallregions // uses function zerosmallregions(cube,double) combining operations: sum sum all volumes average average all volumes product product of all volumes multi combine input masks into a multi-mask union combine input masks by calculating the union intersect combine input masks by calculating the intersection count combine input masks by counting non-zero voxels overlapmask create a color-coded overlap mask of up to 3 masks select randomly select n volumes include include volumes in range, e.g., 0-5,7,9-13 (no spaces) exclude exclude volumes in range, e.g., 0-5,7,9-13 (no spaces) output/summary operations: write write to single output filename writeprefixed prefix each volume's original name and write write4d combine the volumes into a 4d file info print general info about each 3D volume regioninfo print region info // vbregion has great methods notes: vbimagemunge replaces vbmaskmunge, for the most part. vbimagemunge takes multiple 3D volumes as input, and applies the specified image processing operations, in the order specified. If a 4D input volume is specified, it is broken down into 3D volumes. vbimagemunge has three kinds of operations. Image processing operations are applied to each 3D volume independently. Combining operations apply to the whole set of 3D volumes and typically reduce the set to a single volume. Output/summary operations print out information about the volumes as they exist at that point and/or write out files. The operations are applied in the order given. For convert, valid new types are: byte, int16, int32, float, and double. Note that VoxBo historically has used more ambiguous names for int16 and int32. The combine operation implements several methods for re-calculating each voxel's value as a combination of surrounding voxels. It takes six arguments. The first argment is either "fixed" or "moving" (can be abbreviated with f/m). Fixed means that the brain is divided into fixed subregions, and each voxel in a given subregion gets the same value. Moving means that each voxel gets a value calculated from a region centered at that voxel. The next three arguments are the size of the region in x, y, and z. The following argument is the combination method. The following methods are supported: sum, count (count nonzero), average, pct (percent nonzero), any (1 if any voxel in the region is nonzero), sumthresh (1 if the sum exceeds a threshold), and averagethresh. The final argument is the threshold for sumthresh and averagethresh (ignored for the other methods, but you must still supply a value. Note that the output is stored in the same format as the input, so you may want to convert to a different datatype before performing some operations (e.g., many masks are stored as byte data, which can only represent integers in the 0-255 range). voxbo-1.8.5~svn1246/munge/vbinterpolate.cpp000066400000000000000000000104341153177201300206230ustar00rootroot00000000000000 // vbinterpolate.cpp // interpolate volumes in a 4D file // Copyright (c) 2006 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbio.h" #include "vbinterpolate.hlp.h" void interpolate(Tes &im,vector missings,int linearflag); void vbinterpolate_help(); void vbinterpolate_version(); int main(int argc,char *argv[]) { if (argc==1) { vbinterpolate_help(); exit(0); } tokenlist args; string infile,outfile; int floatflag=0,nanflag=1,linearflag=0; arghandler ah; string errstr; ah.setArgs("-f","--nofloat",0); ah.setArgs("-n","--nonan",0); ah.setArgs("-l","--linear",0); ah.setArgs("-h","--help",0); ah.setArgs("-v","--version",0); ah.parseArgs(argc,argv); if ((errstr=ah.badArg()).size()) { printf("[E] vbinterpolate: %s\n",errstr.c_str()); exit(10); } if (ah.flagPresent("-h")) { vbinterpolate_help(); exit(0); } if (ah.flagPresent("-v")) { vbinterpolate_version(); exit(0); } tokenlist filelist=ah.getUnflaggedArgs(); if (filelist.size()!=3) { printf("[E] vbinterpolate: requires an input and an output file, plus indices\n"); exit(10); } if (ah.flagPresent("-f")) floatflag=1; if (ah.flagPresent("-n")) nanflag=1; if (ah.flagPresent("-l")) linearflag=1; infile = filelist[0]; outfile = filelist[1]; vector targets=numberlist(filelist[2]); printf("[I] vbinterpolate: interpolating\n"); Tes im; im.ReadFile(infile); if (!(im.data_valid)) { printf("[E] vbinterpolate: couldn't make a valid 4D volume out of %s\n",infile.c_str()); exit(5); } // remove NaNs and Infs if requested if (nanflag) im.removenans(); // convert to float if requested if (floatflag && im.datatype != vb_float) im.convert_type(vb_float,VBSETALT|VBNOSCALE); interpolate(im,targets,linearflag); im.SetFileName(outfile); if (im.WriteFile()) { printf("[E] vbinterpolate: error writing file %s\n",outfile.c_str()); exit(110); } else printf("[I] vbinterpolate: done.\n"); exit(0); } void interpolate(Tes &im,vector missings,int linearflag) { int points=im.dimt-missings.size(); VB_Vector tesmask(im.dimt); tesmask*=0.0; tesmask+=1.0; for(int i=0; i<(int)missings.size(); i++) tesmask[missings[i]]=0.0; VB_Vector xa(points); VB_Vector ya(points); gsl_interp *myinterp; if (linearflag) myinterp=gsl_interp_alloc(gsl_interp_linear,points); else myinterp=gsl_interp_alloc(gsl_interp_cspline,points); double *xptr=xa.getTheVector()->data; double *yptr=ya.getTheVector()->data; double val; for (int i=0; i] <4D infile> <4D outfile> flags: -f convert to floating point -n replace NaNs and Infs with zeros -l use linear interpolation (default is cubic spline) -h show help -v show version notes: vols to remove is a comma-separated list of volume indices (you can also use a dash for ranges), with the first volume being 0. e.g., 44,45,51,51 interpolates 4 volumes, as does 24-27 voxbo-1.8.5~svn1246/munge/vbmakerfx.cpp000066400000000000000000000336261153177201300177420ustar00rootroot00000000000000 // vbmakerfx.cpp // creates a random effects TES from a description file // Copyright (c) 1998-2002 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include #include "vbutil.h" #include "vbjobspec.h" #include "vbprefs.h" #include "vbio.h" #include "vbmakerfx.hlp.h" void vbmakerfx_help(); void vbmakerfx_sample(FILE *); void vbmakerfx_make_sample(const string &fname); void vbmakerfx_show_sample(); void buildcontrastvector(char *tmp,vector cv); const int BUFLEN=1024; bool ignorewarnings,validateonly; class RFXSubject { public: string glmpath; string glmstem; vector contrastvector; int scale; int affineonlyflag; double voxelsize[3]; string normparams; string originfile; string outfile; RFXSubject(); void init(); }; class RFXConfig { public: RFXConfig(string fname); int ParseFile(string filename); string seqname; // name of the sequence string dirname; // directory (for tmp files, tes and cov) string tesfile; // full path of tes file to produce string coveragefile; // full path of coverage map to produce double skernel[3]; vector glmlist; // list of all GLM dirs RFXSubject rfxg; RFXSubject rfxs; string email; // email address int pri; bool auditflag,emailflag; VBSequence seq; void init(); int RunCheck(); int WriteJobs(); void Validate(); void CreateRFXJobs(int chk); }; VBPrefs vbp; int main(int argc,char *argv[]) { tokenlist args; vbp.init(); args.Transfer(argc-1,argv+1); if (args.size() == 0) { vbmakerfx_help(); exit(0); } if (args[0]=="-h") { vbmakerfx_show_sample(); exit(0); } if (args[0]=="-x") { if (args.size() > 1) vbmakerfx_make_sample(args[1]); else printf("vbmakerfx -x needs a filename to store the sample rfx file\n"); exit(0); } // okay, let's fly tokenlist files; ignorewarnings=FALSE; validateonly=FALSE; for (int i=0; iCreateRFXJobs(i); rfxc->WriteJobs(); delete rfxc; } exit(0); } void RFXConfig::init() { seqname=""; dirname=""; glmlist.clear(); email=vbp.email; pri=2; auditflag=1; emailflag=1; skernel[0]=skernel[1]=skernel[2]=0.0; seq.init(); } RFXSubject::RFXSubject() { init(); } void RFXSubject::init() { glmpath=""; glmstem=""; contrastvector.clear(); scale=2; affineonlyflag=0; voxelsize[0]=3.75; voxelsize[1]=3.75; voxelsize[2]=5.0; normparams=""; originfile=""; outfile=""; } RFXConfig::RFXConfig(string fname) { init(); ParseFile(fname); } int RFXConfig::ParseFile(string filename) { ifstream infile; char buf[BUFLEN]; tokenlist args; RFXSubject *rfxptr=&rfxg; infile.open(filename.c_str()); if (!infile) { cout << "*** vbmakerfx: couldn't open " << filename << "." << endl; return 1; // error! } while (infile.getline(buf,BUFLEN,'\n')) { args.ParseLine(buf); if (args.size()) { if (args[0][0]=='#' || args[0][0] == ';') continue; if (args[0]=="name" || args[0]=="seqname") { seqname=args.Tail(); } else if (args[0]=="dirname") { if (args.size() == 2) dirname=args[1]; else cout << "*** vbmakerfx: dirname takes exactly one argument" << endl; } else if (args[0]=="glmdir") { if (args.size() != 2) { cout << "*** vbmakerfx: glmdir takes exactly one argument" << endl; continue; } rfxs=rfxg; rfxptr=&rfxs; rfxptr->glmpath=args[1]; rfxptr->glmstem=args[1]+(string)"/"+xfilename(args[1]); } else if (args[0]=="add") { glmlist.push_back(*rfxptr); rfxptr=&rfxg; } else if (args[0]=="tesfile") { if (args.size() == 2) tesfile=args[1]; else cout << "*** vbmakerfx: tesfile takes exactly one argument" << endl; } else if (args[0]=="originfile") { if (args.size() == 2) rfxptr->originfile=args[1]; else cout << "*** vbmakerfx: originfile takes exactly one argument" << endl; } else if (args[0]=="normparams") { if (args.size() == 2) rfxptr->normparams=args[1]; else cout << "*** vbmakerfx: normparams takes exactly one argument" << endl; } else if (args[0]=="coveragemap") { if (args.size() == 2) coveragefile=args[1]; else cout << "*** vbmakerfx: coveragemap takes exactly one argument" << endl; } else if (args[0]=="skernel") { if (args.size() !=2 && args.size() != 4) cout << "*** vbmakerfx: skernel takes 1 or 3 arguments" << endl; else { skernel[0]=skernel[1]=skernel[2]=strtod(args[1]); if (args.size()==4) { skernel[1]=strtod(args[2]); skernel[2]=strtod(args[3]); } } } else if (args[0]=="contrastvector") { if (args.size() < 2) cout << "*** vbmakerfx: contrastvector needs at least one value" << endl; else { rfxptr->contrastvector.clear(); for (int i=1; icontrastvector.push_back(strtol(args[i])); } } else if (args[0]=="affineonly") { if (args.size() == 2) { if (args[1]=="yes" || args[1]=="true" || args[1]=="1") rfxptr->affineonlyflag=1; } else cout << "*** vbmakerfx: kernel takes exactly one argument" << endl; } else if (args[0]=="scale") { if (args.size() == 2) { args[1]=vb_tolower(args[1]); if (args[1]=="t") rfxptr->scale=0; else if (args[1]=="percent") rfxptr->scale=1; else if (args[1]=="beta") rfxptr->scale=2; else if (args[1]=="f") rfxptr->scale=3; else if (args[1]=="snr") rfxptr->scale=5; } else cout << "*** vbmakerfx: scale takes exactly one argument" << endl; } else if (args[0]=="voxelsize") { if (args.size() == 4) { rfxptr->voxelsize[0]=strtod(args[1]); rfxptr->voxelsize[1]=strtod(args[2]); rfxptr->voxelsize[2]=strtod(args[3]); } else cout << "*** vbmakerfx: voxelsize takes three arguments" << endl; } else if (args[0]=="pri") { if (args.size() == 2) pri=strtol(args[1]); else cout << "*** vbmakerfx: pri takes exactly one argument" << endl; } else if (args[0]=="audit") { if (args.size() != 2) cout << "*** vbmakerfx: audit takes exactly one argument" << endl; if (args[1]=="yes" || args[1]=="1") auditflag=TRUE; else if (args[1]=="no" || args[1]=="0") auditflag=FALSE; else cout << "*** vbmakerfx: unrecognized value for audit flag (should be yes/no)" << endl; } else if (args[0]=="email") { emailflag=TRUE; if (args.size() == 2) email=args[1]; } else { cout << "*** vbmakerfx: unrecognized keyword " << args[0] << endl; } } } infile.close(); return 0; // no error! } void RFXConfig::CreateRFXJobs(int chk) { VBJobSpec js; char tmp[10240]; int jobnum=0,onum; int qtime=time(NULL) % 1000; vector jlist; seq.name=seqname; // set filenames for each single subject for (int i=0; i<(int)glmlist.size(); i++) { sprintf(tmp,"%ld-%d-%d-%d.cub",(long)getpid(),chk,qtime,i); glmlist[i].outfile=tmp; } // create copyorigin and single cub job for each subject for (int i=0; i<(int)glmlist.size(); i++) { if (glmlist[i].originfile.size()) { js.init(); js.jobtype="rfxcopy"; js.dirname=dirname; js.arguments.Add(glmlist[i].originfile); // originfile js.arguments.Add(glmlist[i].glmstem+".prm"); // glmstem js.name="rfxcopy"; js.jnum=jobnum++; onum=js.jnum; seq.speclist.push_back(js); } // build single rfx volume in native space, generate mask js.init(); js.jobtype="rfxsingle"; js.dirname=dirname; js.arguments.Add("glmdir "+glmlist[i].glmstem); // glmstem js.arguments.Add("params "+glmlist[i].normparams); // normparams js.arguments.Add("outfile "+glmlist[i].outfile); // path to cube file buildcontrastvector(tmp,glmlist[i].contrastvector); js.arguments.Add((string)"contrast "+tmp); // contrast vector e.g., [0,0,0] sprintf(tmp,"scale %d",glmlist[i].scale); js.arguments.Add(tmp); // scale js.magnitude=0; // set it to something! js.name="rfxsingle"; if (glmlist[i].originfile.size()) js.waitfor.push_back(onum); // wait for origin job js.jnum=jobnum++; jlist.push_back(js.jnum); seq.speclist.push_back(js); // normalize map and mask if needed if (glmlist[i].normparams.size()) { // FIXME sprintf(tmp,"%.4f",glmlist[i].voxelsize[0]); js.arguments.Add(tmp); // vox1 sprintf(tmp,"%.4f",glmlist[i].voxelsize[1]); js.arguments.Add(tmp); // vox2 sprintf(tmp,"%.4f",glmlist[i].voxelsize[2]); js.arguments.Add(tmp); // vox3 sprintf(tmp,"%d",glmlist[i].affineonlyflag); js.arguments.Add(tmp); // affineonly } } // rfxmerge // first build subject list for IDL string sublist="["; for (int i=0; i<(int)glmlist.size(); i++) { sublist+=(string)"'"+glmlist[i].outfile+(string)"'"; if (i<(int)glmlist.size()-1) sublist+=","; } sublist+="]"; // now build the actual merge job js.init(); js.jobtype="rfxmerge"; js.dirname=dirname; js.name="RFX Merge"; js.arguments.Add(sublist); js.arguments.Add(tesfile); js.arguments.Add(coveragefile); if ((skernel[0]+skernel[1]+skernel[2])>0.0001) sprintf(tmp,"[%.4f,%.4f,%.4f]",skernel[0],skernel[1],skernel[2]); else sprintf(tmp,"0"); js.arguments.Add(tmp); js.waitfor=jlist; js.jnum=jobnum++; seq.speclist.push_back(js); // notify? if (emailflag && email.size()) { js.init(); js.jobtype="notify"; js.dirname=dirname; js.arguments.Add(email); js.arguments.Add("Your RFX volume has been built."); js.magnitude=0; // set it to something! js.name="Notify"; js.waitfor.push_back(jobnum-1); js.jnum=jobnum; seq.speclist.push_back(js); } } int RFXConfig::WriteJobs() { // copy a few things to the sequence seq.priority=pri; seq.email=email; return seq.Submit(); } void buildcontrastvector(char *tmp,vector cv) { char tmp2[64]; sprintf(tmp,"["); for (int i=0; i<(int)cv.size()-1; i++) { sprintf(tmp2,"%d,",cv[i]); strcat(tmp,tmp2); } sprintf(tmp2,"%d]",cv[cv.size()-1]); strcat(tmp,tmp2); } void vbmakerfx_make_sample(const string &fname) { printf("Creating sample glm file in %s...",fname.c_str()); fflush(stdout); FILE *fp=fopen(fname.c_str(),"w"); if (fp) { vbmakerfx_sample(fp); fclose(fp); printf("done.\n"); } else { printf("failed.\n"); } } void vbmakerfx_show_sample() { printf("\nHere's what a valid .rfx file looks like, more or less:\n\n"); vbmakerfx_sample(stdout); } void vbmakerfx_sample(FILE *fp) { fprintf(fp,"\n"); fprintf(fp,"###############################################################\n"); fprintf(fp,"# Sample .rfx file for VoxBo vbmakerfx.\n"); fprintf(fp,"###############################################################\n"); fprintf(fp,"\n"); fprintf(fp,"# name for your sequence (so you can spot it in the queue)\n"); fprintf(fp,"seqname my rfx sequence\n"); fprintf(fp,"# where do you want to put your output files?\n"); fprintf(fp,"dirname /data/myanalysis/GROUP\n"); fprintf(fp,"# what's name would you like for your group TES file?\n"); fprintf(fp,"tesfile group.tes\n"); fprintf(fp,"# what name would you like for your coverage map?\n"); fprintf(fp,"coveragemap coverage.cub\n"); fprintf(fp,"# what priority (1 is low, 4 is high)\n"); fprintf(fp,"pri 2\n"); fprintf(fp,"# what smoothing kernel for your group TES file (comment out for no smoothing)\n"); fprintf(fp,"skernel 2 2 1.5\n"); fprintf(fp,"# what kind of statistic? (t/f/percent/beta/snr)?\n"); fprintf(fp,"scale beta\n"); fprintf(fp,"# what is your contrast vector?\n"); fprintf(fp,"contrastvector 1 -1 1 -1\n"); fprintf(fp,"# affine only normalization?\n"); fprintf(fp,"affineonly 0\n"); fprintf(fp,"# voxel size in mm for output TES\n"); fprintf(fp,"voxelsize 3.75 3.75 5.0\n"); fprintf(fp,"# email address for notification, defaults to your voxbo email\n"); fprintf(fp,"# email nobody@nowhere.com\n"); fprintf(fp,"\n"); fprintf(fp,"##################################################################\n"); fprintf(fp,"# Now create paragraphs of specific stuff for each individual GLM.\n"); fprintf(fp,"# (you can also override scale and contrastvector here)\n"); fprintf(fp,"##################################################################\n"); fprintf(fp,"\n"); fprintf(fp,"# For each glmdir section below:\n"); fprintf(fp,"# comment out originfile to leave origin unchanged\n"); fprintf(fp,"# comment out normparams to skip normalization\n"); fprintf(fp,"# comment out add line to omit this subject temporarily\n"); fprintf(fp,"\n"); fprintf(fp,"glmdir /data/study/Models/myglm\n"); fprintf(fp,"originfile /data/study/data/sub1/Anatomy/EPI.cub\n"); fprintf(fp,"normparams /data/study/data/sub1/Anatomy/NormParams.ref\n"); fprintf(fp,"add\n"); fprintf(fp,"\n"); } void vbmakerfx_help() { cout << boost::format(myhelp) % vbversion; } voxbo-1.8.5~svn1246/munge/vbmakerfx.hlp000066400000000000000000000003061153177201300177300ustar00rootroot00000000000000 VoxBo vbmakerfx (v%1%) usage: vbmakerfx submit rfx job defined in file vbmakerfx -x create sample config in file vbmakerfx -h show help (sample config) voxbo-1.8.5~svn1246/munge/vbmaskcompare.cpp000066400000000000000000000304021153177201300205740ustar00rootroot00000000000000 // questions re: fiez et al. // fig 3a shows sizes of 16 and 19 and calculates the percent // difference as 16%. the calculation given in the article (diff // divided by mean size) gives 17%. which is right? // fig 3b shows surface distances. the algorithm isn't clear, and not // spelled out in the refs, so here's my guess. accumulate all the // surface voxels for each volume. surface-surface matches are 0's. // other surface voxels that don't overlap with non-surface voxels are // given the distance to the nearest surface voxel (positive for A-B, // negative for B-A). calculate euclidean distances, but round. // vbmaskcompare.cpp // mask comparison utility for doing inter-rater reliability // Copyright (c) 2005-2009 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // based on Fiez et al. #include #include "vbutil.h" #include "vbio.h" #include "vbversion.h" #include "vbmaskcompare.hlp.h" class subrect { public: subrect() {xmin=-1;} int32 xmin,xmax,ymin,ymax,zmin,zmax; void include(int x,int y,int z); }; void subrect::include(int x,int y,int z) { if (xmin==-1) { xmin=xmax=x; ymin=ymax=y; zmin=zmax=z; return; } if (xxmax) xmax=x; if (yymax) ymax=y; if (zzmax) zmax=z; } class VBComp { private: Cube mask1,mask2; int m_union,m_intersection,m_just1,m_just2,m_neither; int m_discrepant1,m_discrepant2; VBRegion surface1,surface2; // surfaces for the two volumes VBRegion unique1,unique2; // unique voxels for the two volumes VBRegion discrepants1,discrepants2,nondiscrepants; VBRegion allvoxels1,allvoxels2; vector distances; public: VBComp(); int surfaceflag; // double and integer versions of the maximum allowable non-discrepant distance double f_ddist; int32 f_idist; string stem; int load_masks(string m1,string m2); void check_volumes(); void check_volumes2(); void check_surfaces(); void check_discrepants(); void write_discrepants(); void summarize(); }; void vbmaskcompare_help(); void vbmaskcompare_version(); int main(int argc,char *argv[]) { if (argc==1) { vbmaskcompare_help(); exit(0); } VBComp cmp; cmp.surfaceflag=0; tokenlist args; vector filelist; args.Transfer(argc-1,argv+1); for (size_t i=0; isecond,vox2->second)); if (dist0 && !(allvoxels2.contains(vox1->second.x,vox1->second.y,vox1->second.z))) distances.push_back(mindist); } // distances for second surface (excluding matching surface voxels) // for (int i=0; i<(int)surface2.size(); i++) { for (VI vox2=surface2.begin(); vox2!=surface2.end(); vox2++) { mindist=mask1.dimx+mask1.dimy+mask1.dimz; // suitably large value for (VI vox1=surface1.begin(); vox1!=surface1.end(); vox1++) { int dist=(int)round(voxeldistance(vox1->second,vox2->second)); if (dist < mindist) mindist=dist; } if (mindist!=0 && !(allvoxels1.contains(vox2->second.x,vox2->second.y,vox2->second.z))) distances.push_back(0-mindist); } double meandist=0; for (size_t i=0; isecond.x-f_idist; int x2=vox1->second.x+f_idist; int y1=vox1->second.y-f_idist; int y2=vox1->second.y+f_idist; int z1=vox1->second.z-f_idist; int z2=vox1->second.z+f_idist; for (int i=x1; i<=x2; i++) { for (int j=y1; j<=y2; j++) { for (int k=z1; k<=z2; k++) { if (!(mask2.testValue(i,j,k))) continue; dist=voxeldistance(i,j,k,vox1->second.x,vox1->second.y,vox1->second.z); if (distDBL_MIN) { m_discrepant1++; discrepants1.add(vox1->second); } else nondiscrepants.add(vox1->second); } for (VI vox2=unique2.begin(); vox2!=unique2.end(); vox2++) { mindist=999999999; int x1=vox2->second.x-f_idist; int x2=vox2->second.x+f_idist; int y1=vox2->second.y-f_idist; int y2=vox2->second.y+f_idist; int z1=vox2->second.z-f_idist; int z2=vox2->second.z+f_idist; for (int i=x1; i<=x2; i++) { for (int j=y1; j<=y2; j++) { for (int k=z1; k<=z2; k++) { if (!(mask1.testValue(i,j,k))) continue; dist=voxeldistance(i,j,k,vox2->second.x,vox2->second.y,vox2->second.z); if (distDBL_MIN) { m_discrepant2++; discrepants2.add(vox2->second); } else nondiscrepants.add(vox2->second); } } void VBComp::write_discrepants() { Cube cb; string fname; cb.SetVolume(mask1.dimx,mask1.dimy,mask1.dimz,vb_byte); cb.zero(); for (VI vox=discrepants1.begin(); vox!=discrepants1.end(); vox++) cb.setValue(vox->second.x,vox->second.y,vox->second.z,1); if (discrepants1.size()==0) cout << format("[W] vbmaskcompare: no discrepant voxels in first mask\n"); fname=stem; replace_string(fname,"XXX","d1"); if (cb.WriteFile(fname)) cout << format("[E] vbmaskcompare: couldn't write output file %s\n") % fname; else cout << format("[I] vbmaskcompare: wrote output file %s\n") % fname; cb.zero(); for (VI vox=discrepants2.begin(); vox!=discrepants2.end(); vox++) cb.setValue(vox->second.x,vox->second.y,vox->second.z,1); if (discrepants2.size()==0) cout << format("[W] vbmaskcompare: no discrepant voxels in second mask\n"); fname=stem; replace_string(fname,"XXX","d2"); if (cb.WriteFile(fname)) cout << format("[E] vbmaskcompare: couldn't write output file %s\n") % fname; else cout << format("[I] vbmaskcompare: wrote output file %s\n") % fname; cb.zero(); for (VI vox=nondiscrepants.begin(); vox!=nondiscrepants.end(); vox++) cb.setValue(vox->second.x,vox->second.y,vox->second.z,1); if (nondiscrepants.size()==0) cout << format("[W] vbmaskcompare: no nondiscrepant voxels anywhere\n"); fname=stem; replace_string(fname,"XXX","nond"); if (cb.WriteFile(fname)) cout << format("[E] vbmaskcompare: couldn't write output file %s\n") % fname; else cout << format("[I] vbmaskcompare: wrote output file %s\n") % fname; } void VBComp::summarize() { if (m_union==0) { printf("[E] vbmaskcompare: no voxels found in either mask\n"); return; } printf("[I] vbmaskcompare: total voxels: %d\n",m_union+m_neither); printf("[I] vbmaskcompare: %s: %d total, %d unique\n", mask1.GetFileName().c_str(),m_intersection+m_just1,m_just1); printf("[I] vbmaskcompare: %s: %d total, %d unique\n", mask2.GetFileName().c_str(),m_intersection+m_just2,m_just2); printf("[I] vbmaskcompare: total mask voxels (mask union): %d\n",m_union); printf("[I] vbmaskcompare: common (mask intersection): %d\n",m_intersection); float dice=(2.0*m_intersection)/(m_union+m_intersection); printf("[I] vbmaskcompare: dice overlap: %.4f\n",dice); float disc=(float)fabs(m_union-m_intersection)/(float)m_union; printf("[I] vbmaskcompare: percent non-overlapping: %.2f%%\n",100.0*disc); printf("[I] vbmaskcompare: discrepant voxels in %s: %d\n", mask1.GetFileName().c_str(),m_discrepant1); printf("[I] vbmaskcompare: discrepant voxels in %s: %d\n", mask2.GetFileName().c_str(),m_discrepant2); printf("[I] vbmaskcompare: total discrepant voxels: %d (%.2f%%)\n",m_discrepant1+m_discrepant2, (float)(m_discrepant1+m_discrepant2)/(float)m_union); } void vbmaskcompare_help() { cout << boost::format(myhelp) % vbversion; } void vbmaskcompare_version() { printf("VoxBo vbmaskcompare (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vbmaskcompare.hlp000066400000000000000000000010451153177201300205760ustar00rootroot00000000000000 VoxBo vbmaskcompare (v%1%) summary: mask comparison for VoxBo usage: vbmaskcompare flags: -h show help -v show version -s include surface comparison -dd maximum allowable distance for non-discrepant voxels -o base output filename for discrepant voxel masks notes: Your output stem should include the substring XXX. That part will be replaced in the actual output, so if you specify foo_XXX.cub, you will get filenames like: foo_d1.cub, foo_d2.cub, etc. voxbo-1.8.5~svn1246/munge/vbmaskinfo.cpp000066400000000000000000000342721153177201300201120ustar00rootroot00000000000000 // vbmaskinfo.cpp // mask/lesion summary utility, mostly for counting unique voxels // Copyright (c) 2005-2011 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #include "glmutil.h" #include "vbversion.h" #include "vbmaskinfo.hlp.h" class pdata { public: pdata() {voxels=0;} int voxels; VBVoxel firstvox; }; int reduce(Tes &ts,Cube mymask,size_t npats,int minpatients,string matfile, double maxrmul,double countweight,string mapfile); void vbmaskinfo_help(); void vbmaskinfo_version(); class img { public: Tes ts; Cube cb; int pos; }; int main(int argc,char *argv[]) { if (argc==1) { vbmaskinfo_help(); exit(0); } int minpatients=1; size_t npats=0; // number of vectors to keep string matfile,maskfile,mapfile; double maxrmul=1.0-FLT_MIN; double countweight=1.0; size_t nrandom=0; string coordfile; tokenlist args,filelist; args.Transfer(argc-1,argv+1); for (size_t i=0; i=1, set it to special >1 value if (maxrmul>=1.0) maxrmul=3.0; // otherwise, cap it at just under 1 else if (1.0-maxrmul mm=strtolx(args[++i]); if (mm.first) { cout << format("[E] vbmaskinfo: non-numeric argument to -n: %s\n")%args[i]; exit(98); } minpatients=mm.second; } else if (args[i]=="-m" && i0 && filelist.size()==1) { if (tes.ReadFile(filelist[0])) { exit(999); } reduce(tes,mask,npats,minpatients,matfile,maxrmul,countweight,mapfile); exit(0); } printf("[I] vbmaskinfo: counting patterns (min patients %d)\n",minpatients); map patterns; vector allbitmasks; int includedvoxels=0; VB_Vector myvec(dimt); int i,j,k,t; bitmask bm; bm.resize(dimt); int16 val; bool f_non1=0; for (i=0; i(i,j,k,t); if (val) { bm.set(myimages[v].pos+t); if (val!=1) f_non1=1; } } } else { val=myimages[v].cb.getValue(i,j,k); if (val) { bm.set(myimages[v].pos); if (val!=1) f_non1=1; } } } if (bm.count()voxels==0) { pv->firstvox.init(i,j,k); allbitmasks.push_back(bm); } pv->voxels++; includedvoxels++; } } } int voxeltotal[dimt+1]; // number of voxels with n lesions int uniquetotal[dimt+1]; // number of unique voxels with n lesions for (int i=0; i::iterator pp=patterns.begin(); pp!=patterns.end(); pp++) { int cnt=pp->first.count(); voxeltotal[cnt]+=pp->second.voxels; uniquetotal[cnt]++; } if (f_non1) printf("[W] non-0/1 values found in masks\n"); printf("[I] total patients: %d\n",dimt); printf("[I] total voxels in volume: %d\n",dimx*dimy*dimz); printf("[I] voxels with included data: %d\n",includedvoxels); printf("[I] uncounted voxels: %d\n",(dimx*dimy*dimz)-includedvoxels); printf("[I] total distinct voxels: %d\n",(int)patterns.size()); for (int i=minpatients; i0) printf("[I] voxels with %d lesions: %d voxels, %d distinct voxels\n", i,voxeltotal[i],uniquetotal[i]); } printf("[I] Distinct voxels are voxels with different patterns of lesioned\n"); printf("[I] patients. Sets of voxels in which exactly the same patients are\n"); printf("[I] lesioned are counted as a single distinct voxel.\n"); // select n random voxels if that's what we're doing set indices; if (nrandom>0) { VBMatrix coords(nrandom,3); gsl_rng *rng; rng=gsl_rng_alloc(gsl_rng_mt19937); assert(rng); gsl_rng_set(rng,VBRandom()); for (uint32 i=0; i patterns; map keptpatterns; pair pat; int dimt; VBMatrix kpmat; int mincount,maxcount; double minvar,maxvar; bool f_scale=0; double varweight; if (countweight<0.0 || countweight>100.0) { cout << format("[E] vbmaskinfo: invalid count weight %g\n")%countweight; exit(4); } if (countweight>1.0) countweight/=100.0; varweight=1.0-countweight; if (abs(countweight)>FLT_MIN && abs(varweight)>FLT_MIN) f_scale=1; cout << format("[I] vbmaskinfo: countweight=%g varianceweight=%g\n")%countweight%varweight; // the color map will eventually have a map of the voxels included // in the patterns, with a different color (int) for each pattern colormap.SetVolume(ts.dimx,ts.dimy,ts.dimz,vb_int32); set keptcolors; map colorkey; dimt=ts.dimt; bm.resize(dimt); ts.ExtractMask(mask); if (mymask) mask.intersect(mymask); // collect all the patterns, with counts int32 nextcolor=1; for (int i=0; iFLT_MIN) bm.set(t); } if (bm.count()first).getVariance(); mincount=maxcount=patterns.begin()->second; double var; vbforeach(pat,patterns) { var=VB_Vector(pat.first).getVariance(); if (varmaxvar) maxvar=var; if (pat.secondmaxcount) maxcount=pat.second; } vbforeach(pat,patterns) { double wvar=VB_Vector(pat.first).getVariance(); double wcount=pat.second; if (f_scale) { wvar-=minvar; wvar/=maxvar-minvar; wcount-=mincount; wcount/=maxcount-mincount; } patterns[pat.first]=(varweight*wvar)+(countweight*wcount); } cout << format("%d total patterns\n")%patterns.size(); // now do our stuff int removed=0; double removedtotal=0,kepttotal=0; VB_Vector v1(dimt); // icol is created so that we can add an intercept easily VB_Vector icol(dimt); icol+=1; v1+=1; while(1) { if (patterns.size()==0) break; // find the largest score double maxcnt=0; bitmask maxpat; vbforeach(pat,patterns) { if (pat.second>maxcnt || maxpat.size()==0) { maxpat=pat.first; maxcnt=pat.second; } } // now we have the largest score, we either add or remove it (we // always keep the single largest) if (keptpatterns.size()==0) { keptpatterns[maxpat]=maxcnt; kepttotal+=maxcnt; patterns.erase(maxpat); kpmat.resize(dimt,2); kpmat.SetColumn(0,icol); kpmat.SetColumn(1,VB_Vector(maxpat)); cout << format("pattern added: %d kept, %d left")%keptpatterns.size()%patterns.size() << endl; continue; } // otherwise see if it's linearly dependent on previously kept pats // FIRST, convert our set into a matrix VB_Vector checkvec(maxpat); double rmul; if (maxrmul<1.9) rmul=calcColinear(kpmat,checkvec); else rmul=0.000001; // should always be kept if (rmul>maxrmul || rmul<0 || abs(rmul-1.0)=npats) break; } cout << format("final pattern count: %d (%g total score)\n")%keptpatterns.size()%kepttotal; cout << format("final patterns removed: %d (%g total score)\n")%removed%removedtotal; if (keptpatterns.size()) { VBMatrix m(keptpatterns.begin()->first.size(),keptpatterns.size()); int col=0; pair bb; vbforeach(bb,keptpatterns) { m.SetColumn(col++,VB_Vector(bb.first)); } if (m.WriteFile(matfile)) { cout << format("[E] vbmaskinfo: error writing feature file %s\n")%matfile; exit(201); } else { cout << format("[I] vbmaskinfo: wrote feature file %s\n")%matfile; } if (mapfile!="none") { // build set of colorkeys associated with kept patterns vbforeach(pat,keptpatterns) { cout << "keeping " << colorkey[pat.first] << endl; keptcolors.insert(colorkey[pat.first]); } for (int i=0; i(i); if (!(keptcolors.count(val))) colormap.setValue(i,0); } if (colormap.WriteFile(mapfile)) { cout << format("[E] vbmaskinfo: error writing colormap %s\n")%matfile; exit(201); } else { cout << format("[I] vbmaskinfo: wrote colormap %s\n")%matfile; } } } exit(0); } void vbmaskinfo_help() { cout << boost::format(myhelp) % vbversion; } void vbmaskinfo_version() { printf("VoxBo vbmaskinfo (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/munge/vbmaskinfo.hlp000066400000000000000000000047311153177201300201100ustar00rootroot00000000000000 VoxBo vbmaskinfo (v%1%) summary: mask/lesion summary utility for VoxBo usage: vbmaskinfo [ ...] flags: -m inclusion mask (include voxels with non-zero values) -n minimum lesions for a voxel to be included (default 1) -u write unique-voxel volume -s select n random distinct in-mask voxels, write as matrix -r see below -h show help -v show version notes: vbmaskinfo treats all the passed 3D and 4D volumes as one large series of masks, typically lesion masks, and produces a summary of the number of total and distinct voxels in the combined volume. The -u option creates a volume with only unique voxels. For every set of n identical voxels (voxels that have the same value at every point in the series), only one will be included. The -r flag is used to extract matrices of feature vectors heuristically from a 4D mask set. Each feature vector contains the data from a single voxel, as a column in the matrix. E.g., if you have 20 masks and you extract 50 features, your feature matrix will be 20x50. The -r flag must be followed by five arguments, as follows: -r mfile is the name of the matrix output file (something.mtx for a text matrix). map is the name of the 3D file to be used as output (use "none" to suppress). nvoxels is the maximum number of features you'd like to extract. maxrmul is the maximum R value for a model of the candidate vector, with the already-included vectors as the IVs (the higher the maxrmul, the less the multicollinearity among the features). if maxrmul is 1.0 or greater, then all voxels will be included (this is useful if you want to create a "district" map of identical voxels). countweight is the amount of weight given to the number of voxels containing the pattern to be considered. countweight can be given either in the 0-1 range or in the 0-100 range. the remaining weight is given to the feature's variance. if both weighting parameters are non-zero, then the numbers used are scaled to the 0-1 range, so that they're at least roughly comparable. Note that when writing matrix files using -s or -r, the .mat extension will get you a VoxBo matrix (MAT1) file, while the .mtx extension will get you a text format matrix file with features in columns and subjects (volumes) in rows. Lines beginning with # are comments. voxbo-1.8.5~svn1246/munge/vbmaskmunge.cpp000066400000000000000000000167121153177201300202710ustar00rootroot00000000000000 // vbmaskmunge.cpp // mask munging util for voxbo // Copyright (c) 2003-2007 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #include "imageutils.h" #include "vbversion.h" #include "vbmaskmunge.hlp.h" void vbmaskmunge_help(); void vbmaskmunge_version(); int main(int argc,char *argv[]) { if (argc==1) { vbmaskmunge_help(); exit(0); } arghandler ah; string errstr; ah.setArgs("-s","--smooth",3); ah.setArgs("-t","--thresh",1); ah.setArgs("-x","--cutoff",1); ah.setArgs("-c","--combine",0); ah.setArgs("-u","--union",0); ah.setArgs("-n","--count",0); ah.setArgs("-i","--intersect",0); ah.setArgs("-q","--quantize",0); ah.setArgs("-z","--zzinvert",0); ah.setArgs("-d","--diff",0); ah.setArgs("-r","--ratio",0); ah.setArgs("-m","--multiply",0); ah.setArgs("-p","--prepend",1); ah.setArgs("-a","--apply",1); ah.setArgs("-o","--output",1); ah.setArgs("-h","--help",0); ah.setArgs("-v","--version",0); ah.parseArgs(argc,argv); if ((errstr=ah.badArg()).size()) { cout << "[E] vbmaskmunge: " << errstr << endl; exit(10); } if (ah.flagPresent("-h")) { vbmaskmunge_help(); exit(0); } if (ah.flagPresent("-v")) { vbmaskmunge_version(); exit(0); } tokenlist filelist=ah.getUnflaggedArgs(); enum {mm_none,mm_combine,mm_union,mm_intersect,mm_sum,mm_diff,mm_ratio,mm_product}; tokenlist args; string outx,prepend="m",target; int smoothflag=0,threshflag=0,outfileflag=0,quantizeflag=0,applyflag=0,invertflag=0; int cutoffflag=0; int combinemode=mm_none; int quantizeval=1; double sx=0,sy=0,sz=0,thresh=0.0,cutoff=0.0; args=ah.getFlaggedArgs("-o"); if (args.size()) { outfileflag=1; outx=args[0]; } args=ah.getFlaggedArgs("-s"); if (args.size()) { smoothflag=1; sx=strtod(args[0]); sy=strtod(args[1]); sz=strtod(args[2]); } args=ah.getFlaggedArgs("-t"); if (args.size()) { threshflag=1; thresh=strtod(args[0]); } args=ah.getFlaggedArgs("-x"); if (args.size()) { cutoffflag=1; cutoff=strtod(args[0]); } args=ah.getFlaggedArgs("-p"); if (args.size()) { prepend=args[0]; } if (ah.flagPresent("-c")) { quantizeflag=1; combinemode=mm_combine; } if (ah.flagPresent("-u")) { combinemode=mm_union; } if (ah.flagPresent("-n")) { quantizeflag=1; combinemode=mm_sum; } if (ah.flagPresent("-d")) { quantizeflag=0; combinemode=mm_diff; } if (ah.flagPresent("-r")) { quantizeflag=0; combinemode=mm_ratio; } if (ah.flagPresent("-m")) { quantizeflag=0; combinemode=mm_product; } if (ah.flagPresent("-i")) { combinemode=mm_intersect; } if (ah.flagPresent("-q")) quantizeflag=1; if (ah.flagPresent("-z")) invertflag=1; args=ah.getFlaggedArgs("-a"); if (args.size()) { applyflag=1; combinemode=mm_intersect; target=args[0]; } Cube master; for (size_t i=0; i [ ...] flags: -s smooth with FWHM of x/y/z voxels -t threshold at t (zero values <= t) -x cutoff at t (zero values >= t) -q set non-zero values to 1 -z set zero values to 1, others to zero -c combine input masks into a multi-mask -u combine input masks by calculating the union -i combine input masks by calculating the intersection -n combine input masks by counting -d calculate the difference between first two input cubes -r calculate the ratio of the first two input cubes -m calculate the product of the first two input cubes -a apply result mask to file instead of saving -p

       prepend 'pre' to output (default 'm')
  -o       output filename (for single files only)
  -h             show help
  -v             show version
notes:
  The -c option proceeds with the input masks in the order given.  The
  first mask is given code 1, the second 2, etc.  If there's overlap,
  later masks override earlier ones.
voxbo-1.8.5~svn1246/munge/vbmerge4d.cpp000066400000000000000000000057731153177201300176360ustar00rootroot00000000000000
// vbmerge4d.cpp
// convert arbitrary 4D data to VoxBo TES1
// Copyright (c) 2005 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include 
#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vbmerge4d.hlp.h"

void vbmerge4d_help();
void vbmerge4d_version();

int
main(int argc,char *argv[])
{
  if (argc==1) {
    vbmerge4d_help();
    exit(0);
  }
  arghandler ah;
  string errstr;
  ah.setArgs("-o","--outfile",1);
  ah.setArgs("-h","--help",0);
  ah.setArgs("-v","--version",0);
  ah.parseArgs(argc,argv);

  if ((errstr=ah.badArg()).size()) {
    printf("[E] vbmerge4d: %s\n",errstr.c_str());
    exit(10);
  }
  if (ah.flagPresent("-h")) {
    vbmerge4d_help();
    exit(0);
  }
  if (ah.flagPresent("-v")) {
    vbmerge4d_version();
    exit(0);
  }

  tokenlist patlist=ah.getUnflaggedArgs();
  tokenlist infilelist;
  // build infilelist
  for (size_t i=0; i ...] -o 
flags:
  -h       show help
  -v       show version
voxbo-1.8.5~svn1246/munge/vbmunge.cpp000066400000000000000000000122671153177201300174160ustar00rootroot00000000000000
// vbmunge.cpp
// generalized munging
// Copyright (c) 1998-2002 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vbmunge.hlp.h"

class VBMunge {
private:
  enum modetype {m_flipx,m_flipy,m_flipz,m_leftify,m_rightify,m_addcube,
		 m_striporigin};
  vector modes;
  tokenlist args;
  string extrafile;
  vector filelist;
  int munge3d(const string &fname);
  int munge4d(const string &fname);
  int munge(Cube *cub,modetype mode);
  void help();
public:
  int Go(int argc,char **argv);
};

void leftify(Cube &cub);
void rightify(Cube &cub);
void addcube(Cube &cub,string infile);

int
main(int argc,char *argv[])
{
  VBMunge *vbm=new VBMunge();
  int err=vbm->Go(argc-1,argv+1);
  exit(err);
}

int
VBMunge::Go(int argc,char **argv)
{
  args.Transfer(argc,argv);
  if (args.size() == 0) {
    help();
    return (0);
  }
  if (args.size() < 2) {
    help();
    return (100);
  }
  args.Transfer(argc,argv);
  for (size_t i=0; itypelist=EligibleFileTypes(filelist[i]);
    switch (typelist[0].getDimensions()) {
    case 3:
      munge3d(filelist[i]);
      break;
    case 4:
      munge4d(filelist[i]);
      break;
    default:
      cout << "bad filetype..." << endl;
      break;
    }
    cout << "done." << endl;
  }
  return 0;
}

int
VBMunge::munge4d(const string &fname)
{
  Cube *cube;
  Tes *tes=new Tes();
  if (tes->ReadFile(fname)) {
    printf("error: couldn't read 4D file\n");
    return 1;
  }
  if (!tes->data_valid) {
    printf("error: invalid 4D file\n");
    return 1;
  }
  for (int i=0; i<(int)modes.size(); i++) {
    if (modes[i] == m_striporigin)
      tes->SetOrigin(0,0,0);
    else {
      for (int j=0; jdimt; j++) {
	cube=new Cube((*tes)[j]);
	munge(cube,modes[i]);
	tes->SetCube(j,*cube);
	delete cube;
      }
    }
  }
  int err=tes->WriteFile();
  delete tes;
  return (err);
}

int
VBMunge::munge3d(const string &fname)
{
  Cube *cube=new Cube;
  if (cube->ReadFile(fname)) {
    printf("error: couldn't read 3D file\n");
    return 2;
  }
  if (!cube->data_valid) {
    printf("error: invalid 3D file\n");
    return 2;
  }
  for (int i=0; i<(int)modes.size(); i++) {
    if (modes[i]==m_striporigin)
      cube->SetOrigin(0,0,0);
    else
      munge(cube,modes[i]);
  }
  return (cube->WriteFile());
}

int
VBMunge::munge(Cube *cub,VBMunge::modetype mode)
{
  if (mode == m_flipx)
    cub->flipx();
  else if (mode == m_flipy)
    cub->flipy();
  else if (mode == m_flipz)
    cub->flipz();
  else if (mode == m_leftify)
    leftify(*cub);
  else if (mode == m_rightify)
    rightify(*cub);
  else if (mode == m_addcube)
    addcube(*cub,extrafile);
  return 0;
}

void
leftify(Cube &cub)
{
  for (int i=(cub.dimx+1)/2; i<=cub.dimx; i++) {
    for (int j=0; jReadFile(infile.c_str())) {
    printf("couldn't read add image\n");
    return;
  }
  if (!cb->data_valid) {
    printf("couldn't open add image\n");
    return;
  }
  if (cub.dimx != cb->dimx || cub.dimy != cb->dimy ||
      cub.dimz != cb->dimz) {
    printf("dimension mismatch\n");
    return;
  }
  for (int i=0; i<=cub.dimx; i++) {
    for (int j=0; jGetValue(i,j,k));
      }
    }
  }
}

void
VBMunge::help()
{
  cout << boost::format(myhelp) % vbversion;
}
voxbo-1.8.5~svn1246/munge/vbmunge.hlp000066400000000000000000000006751153177201300174170ustar00rootroot00000000000000
VoxBo vbmunge (v%1%)
usage:
   vbmunge [flags]  [ ...]
flags:      -x           flip x
            -y           flip y
            -z           flip z
            -s           strip origin (set to 0,0,0)
            -l           extract the left (zero the right)
            -r           extract the right (zero the left)
            -a      add img to infile image
notes:
  that's left and right of the image, not hemispheres
voxbo-1.8.5~svn1246/munge/vborient.cpp000066400000000000000000000122701153177201300175750ustar00rootroot00000000000000
// vborient.cpp
// client code for re-orienting a cub or tes file
// Copyright (c) 1998-2008 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Tom King based on code by Daniel Y. Kimberg
// later changes by Dan Kimberg

using namespace std;

#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vborient.hlp.h"

void vborient_help();

int
main(int argc,char *argv[])
{
  int err = 0;
  int interleaved = 0;
  string in, out;
  string inFile, outFile;
  tokenlist args;
  args.Transfer(argc-1,argv+1);
  string oldorient,neworient;
  vector filelist;

  for (size_t i=0; i   [flag]
flags:
  -from    specify orientation of input volume
  -i               data should be interleaved
notes:
  Orientation codes are three-letter codes, with the letters
  specifying orientation of the x, y, and z axes, respectively.  The
  letter codes are: (R)ight, (L)eft, (I)nferior, (S)uperior,
  (A)nterior, and (P)osterior.  So an axial image in radiological
  orientation is RPI.

  If the -from flag is not present, the orientation must be indicated
    in the file.

  If the -i flag is specified, the volume will be de-interleaved.
voxbo-1.8.5~svn1246/munge/vboverlap.cpp000066400000000000000000000107061153177201300177470ustar00rootroot00000000000000
// vboverlap.cpp
// mask/lesion summary utility, mostly for counting unique voxels
// Copyright (c) 2008-2010 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vbversion.h"
#include "vboverlap.hlp.h"

void vboverlap_help();
void vboverlap_version();

void calc_overlap(Cube &atlas,Cube &mask,int maskval,int atlasval);

int
main(int argc,char *argv[])
{
  if (argc==1) {
    vboverlap_help();
    exit(0);
  }

  tokenlist args,filelist;
  args.Transfer(argc-1,argv+1);
  string atlasname;
  int maskval=-1;
  int atlasval=-1;
  for (size_t i=0; i breakdown;
  typedef map::iterator MI;
  int masktotal=0,inmask,aval,mval;
  for (int i=0; i-1 && atlasval!=aval) continue;
        mval=(int)mask.GetValue(i,j,k);
        if ((mval>0 && maskval<0) || (mval==maskval))
          inmask=1;
        else
          inmask=0;
        if (inmask) masktotal++;
        breakdown[aval].total++;
        if (inmask) breakdown[aval].overlap++;
      }
    }
  }
  printf("[I] vboverlap: atlas %s, mask %s:\n",atlas.GetFileName().c_str(),mask.GetFileName().c_str());
  printf("[I]   mask includes %d ",masktotal);
  if (maskval<0)
    printf("nonzero voxels\n");
  else
    printf("voxels with value %d\n",maskval);
  for (MI mm=breakdown.begin(); mm!=breakdown.end(); mm++) {
    //if (mm->second.overlap==0) continue;
    string rname;
    if (atlas.maskspecs.count(mm->first))
      rname=atlas.maskspecs[mm->first].name;
    else
      rname="anon";
    printf("[I]   region %d (%s): mask includes %d of %d voxels (%.4f)\n",
           mm->first,rname.c_str(),mm->second.overlap,mm->second.total,
           (float)mm->second.overlap/(float)mm->second.total);
  }
}

void
vboverlap_help()
{
  cout << boost::format(myhelp) % vbversion;
}

void
vboverlap_version()
{
  printf("VoxBo vboverlap (v%s)\n",vbversion.c_str());
}
voxbo-1.8.5~svn1246/munge/vboverlap.hlp000066400000000000000000000007501153177201300177460ustar00rootroot00000000000000
VoxBo vboverlap (v%1%)
summary: mask/lesion summary utility for VoxBo
usage:
  vboverlap  [...]
flags:
  -a         atlas file
  -m           value of interest in mask(s)
  -r           value of interest in atlas
  -h        show help
  -v        show version
notes:

  If -m is not specified, all non-zero values in the mask are
  included.  If -r is not specified, each distinct value in the atlas
  is considered separately.

  The -a flag is mandatory.
voxbo-1.8.5~svn1246/munge/vbprep.cpp000066400000000000000000000165171153177201300172530ustar00rootroot00000000000000
// vbprep.cpp
// executable that reads script files and creates jobs  
// Copyright (c) 1998-2010 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Tom King based on code by Daniel Y. Kimberg

#include 
#include 
#include 
#include 
#include "vbpreplib.h"
#include "vbprefs.h"
#include "vbutil.h"
#include "vbio.h"
#include "vbx.h"
#include "vbjobspec.h"
#include "vbprep.hlp.h"

void vbprep_help();
void vbprep_version();
void vbprep_sample(FILE *);
void vbprep_make_sample(const string &fname);
void vbprep_show_sample();

using namespace std;

VBPrefs vbp;

int main(int argc, char **argv)
{
  vbp.init();
  vbp.read_jobtypes();
  int err = 0;
  VBpri mypri;
  bool separateflag=0;
  VBSequence bigseq;
  string selectedSequence;
  tokenlist fileName;
  string cmdline=xcmdline(argc,argv);
  tokenlist args;
  int f_run=vbp.cores;

  args.Transfer(argc-1,argv+1);
  if (args.size() == 0) {
    vbprep_help();
    exit(0);
  }

  for (size_t i=0; isecond.shortname)) {
              found = 1;
              break;
            }
          } 
          //invalid job type
          if ((found == 0) && (myjobtype != "waitprev")) {
            printf("[E] vbprep: jobtype %s not found\n",myjobtype.c_str());
            exit(107);
          }
          found = 0;
        }
        //must use only commands of last joblist
        prep.data[dataSetNum].joblist = prep.study.joblist;
        //build job sequence
        err = prep.data[dataSetNum].BuildJobs(vbp);
        switch (err) {
        case 100:
          printErrorMsg(VB_ERROR, "vbprep: There were no jobs in the script file.");
          return 100;
        case 101:
          printErrorMsg(VB_ERROR, "vbprep: waitprev cannot be the first command in script.");
          return 101;
        case 102:
          printErrorMsg(VB_ERROR, "vbprep: waitprev cannot be the last command in script.");
          return 102;
        case 103:
          printErrorMsg(VB_ERROR, "vbprep: A waitprev cannot follow another waitprev in script.");
          return 103;
        case 104:
          printErrorMsg(VB_ERROR, "vbprep: There were no files specified in the script.");
          return 104;
        case 105:
          printErrorMsg(VB_ERROR, "vbprep: A directory was not specified in the script.");
          return 105;
        case 106:
          printErrorMsg(VB_ERROR, "vbprep: One or more script files could not be opened.");
          return 106;
        }
      }
      //submit job sequence
      if (prep.data[dataSetNum].joblist.size()<1)
        return -1;
      // run each unit separately?
      if (separateflag) {
        prep.data[dataSetNum].seq.priority=mypri;
        prep.data[dataSetNum].seq.source="["+xgetcwd()+"] "+cmdline;
        if (prep.data[dataSetNum].seq.specmap.size())
          createfullpath(prep.data[dataSetNum].seq.specmap.begin()->second.logdir);
        if (f_run) {
          runseq(vbp,prep.data[dataSetNum].seq,f_run);
        }
        else {
          ret=prep.data[dataSetNum].seq.Submit(vbp);
          if (ret) {
            printf("[E] vbprep: %s\n",ret.message().c_str());
            exit(111);
          }
          else
            printf("[I] vbprep: %s\n",ret.message().c_str());
        }
      }
      else {
        // copy sequence for first job
        if (bigseq.specmap.size()<1)
          bigseq=prep.data[dataSetNum].seq;
        else {
          int highest=bigseq.specmap.rbegin()->second.jnum;
          prep.data[dataSetNum].seq.renumber(highest+1);
          for (SMI jj=prep.data[dataSetNum].seq.specmap.begin(); jj!=prep.data[dataSetNum].seq.specmap.end(); jj++) {
            bigseq.specmap[jj->second.jnum]=jj->second;
          }
        }
      }
    }
  }
  if (!separateflag) {
    bigseq.priority=mypri;
    bigseq.source="["+xgetcwd()+"] "+cmdline;
    if (bigseq.specmap.size())
      createfullpath(bigseq.specmap.begin()->second.logdir);
    if (f_run) {
      runseq(vbp,bigseq,f_run);
    }
    else {
      ret=bigseq.Submit(vbp);
    }
    if (ret) {
      printf("[E] vbprep: %s\n",ret.message().c_str());
      exit(111);
    }
    else
      printf("[I] vbprep: %s\n",ret.message().c_str());
  }
}

void
vbprep_help()
{
  cout << boost::format(myhelp) % vbversion;
}

void
vbprep_version()
{
  cout << format("VoxBo vbprep (v%s)\n")%vbversion;
}

void
vbprep_make_sample(const string &fname)
{
  printf("Creating sample script file in %s...",fname.c_str());  fflush(stdout);
  FILE *fp=fopen(fname.c_str(),"w");
  if (fp) {
    vbprep_sample(fp);
    fclose(fp);
    printf("done.\n");
  }
  else {
    printf("failed.\n");
  }
}

void
vbprep_show_sample()
{
  cout << vbpsample;
}

void
vbprep_sample(FILE *fp)
{
  fprintf(fp,vbpsample);
}
voxbo-1.8.5~svn1246/munge/vbprep.hlp000066400000000000000000000014001153177201300172350ustar00rootroot00000000000000
VoxBo vbprep (v%1%)
usage: vbprep [flags] file [file ...]
flags:
  -h              i'm lazy, show me a sample script file
  -x    i'm really lazy, make me a sample script file
  -n  processes only study name data set
  -p        set priority options, see below
  -s              keep sequences separate
  --run=       don't queue, run now on n cores
notes:
  -p can take priority 0-5, or various presets.  See voxq help for
   more info.

  If --run is specified without =n, the default is the total number of
  available cores minus 1 (or 1, if that would be 0).

  log files for vbprep jobs are created in a subdirectory of the
  working directory called logs, which is created if needed.  log
  files are generally not overwritten.

voxbo-1.8.5~svn1246/munge/vbpsample.hlp000066400000000000000000000015421153177201300177370ustar00rootroot00000000000000
###############################################################
# sample script file for VoxBo vbprep
###############################################################

# at the top, set the working directory, priority, sequence name, and
# your email address
DIR /home/username
PRIORITY 3
SEQUENCENAME mySequenceName
EMAIL yourusername@yourdomain.edu

# set global variable
GLOBALS myValue=LAS

# establish the separate bits of data to which the script will be applied
FILE myInFile=/home/myName/file1.cub myOutFile=/home/myName/file2.cub
FILE myInFile=/home/myName/file3.cub myOutFile=/home/myName/file4.cub

# now the actual script

# the next line runs twice, once for each FILE line above
vborient $myInFile $myOutFile $myValue

# "runonce" makes the next line run once, FILE variables aren't used
runonce vborient /home/myName/file1 /home/myName/file2 $myValue
voxbo-1.8.5~svn1246/munge/vbregion.cpp000066400000000000000000000125621153177201300175640ustar00rootroot00000000000000
// vbregion.cpp
// region of interest info for voxbo stat cubes
// Copyright (c) 2003-2008 by The VoxBo Development Team

// This file is part of VoxBo
// 
// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include 
#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vbregion.hlp.h"

void vbregion_help();

int
main(int argc,char *argv[])
{
  tokenlist args;
  args.Transfer(argc-1,argv+1);
  if (args.size() < 1) {
    vbregion_help();
    exit(100);
  }

  string maskfile="";
  double threshold=0.0;
  listcubelist;
  int f_thresh=0,f_absthresh=0,f_mask=0;
  stringstream tmps;
  
  for (size_t i=0; i::iterator mm=cubelist.begin(); mm!=cubelist.end(); mm++) {
    if (mycub.ReadFile(*mm)) {
      printf("[E] vbregion: couldn't read cube %s\n",mm->c_str());
      continue;
    }
    if (f_mask)
      mycub.intersect(mask);
    vector rlist;
    if (f_thresh)
      rlist=findregions(mycub,vb_gt,threshold);
    else if (f_absthresh)
      rlist=findregions(mycub,vb_agt,threshold);
    else
      rlist=findregions(mycub,vb_gt,0.0);
    uint64 xx,yy,zz;
    double xxx,yyy,zzz,val;
    int index=1;
    // make sure origin is sane for origin-corrected coordinates
    if (mycub.origin[0]==0 && mycub.origin[1]==0 && mycub.origin[2]==0) {
      mycub.guessorigin();
      if (mycub.origin[0] || mycub.origin[1] || mycub.origin[2])
        printf("[I] vbregion: guessing origin %d,%d,%d based on image dimensions\n",
               mycub.origin[0],mycub.origin[1],mycub.origin[2]);
    }
    printf("[I] vbregion: cube %s has %d regions\n",mm->c_str(),(int)(rlist.size()));
    if (!(mycub.voxsize[0]>0.0 && mycub.voxsize[1]>0.0 && mycub.voxsize[2]>0.0)) {
      printf("[W] vbregion: no voxel sizes found, all origin-relative coordinates\n");
      printf("[W] vbregion: are in voxels, not mm.\n");
    }
    for (vector::iterator rr=rlist.begin(); rr!=rlist.end(); rr++) {
      printf("region %d info:\n",index++);
      printf("  %d voxels\n",rr->size());
      rr->max(xx,yy,zz,val);

      printf("  max voxel at %d,%d,%d ",(int)xx,(int)yy,(int)zz);
      if (mycub.voxsize[0]>0.0 && mycub.voxsize[1]>0.0 && mycub.voxsize[2]>0.0)
        printf("(%.2f,%.2f,%.2f mm relative to origin), ",
               mycub.voxsize[0]*(xx-mycub.origin[0]),
               mycub.voxsize[1]*(yy-mycub.origin[1]),
               mycub.voxsize[2]*(zz-mycub.origin[2]));
      else
        printf("(%d,%d,%d voxels relative to origin), ",
               (int)(xx-mycub.origin[0]),
               (int)(yy-mycub.origin[1]),
               (int)(zz-mycub.origin[2]));
      printf("value is %g\n",val);

      rr->min(xx,yy,zz,val);
      printf("  min voxel at %d,%d,%d ",(int)xx,(int)yy,(int)zz);
      if (mycub.voxsize[0]>0.0 && mycub.voxsize[1]>0.0 && mycub.voxsize[2]>0.0)
        printf("(%.2f,%.2f,%.2f mm relative to origin), ",
               mycub.voxsize[0]*(xx-mycub.origin[0]),
               mycub.voxsize[1]*(yy-mycub.origin[1]),
               mycub.voxsize[2]*(zz-mycub.origin[2]));
      else
        printf("(%d,%d,%d voxels relative to origin), ",
               (int)(xx-mycub.origin[0]),
               (int)(yy-mycub.origin[1]),
               (int)(zz-mycub.origin[2]));
      printf("value is %g\n",val);

      rr->GeometricCenter(xxx,yyy,zzz);
      printf("  geometric center is at %.2f,%.2f,%.2f ",xxx,yyy,zzz);
      if (mycub.voxsize[0]>0.0 && mycub.voxsize[1]>0.0 && mycub.voxsize[2]>0.0)
        printf("(%.2f,%.2f,%.2f mm relative to origin), ",
               mycub.voxsize[0]*(xxx-mycub.origin[0]),
               mycub.voxsize[1]*(yyy-mycub.origin[1]),
               mycub.voxsize[2]*(zzz-mycub.origin[2]));
      else
        printf("(%.2f,%.2f,%.2f voxels relative to origin), ",
               (xxx-mycub.origin[0]),
               (yyy-mycub.origin[1]),
               (zzz-mycub.origin[2]));
      printf("value is %g\n",val);
    }
  }
  exit(0);
}

void
vbregion_help()
{
  cout << boost::format(myhelp) % vbversion;
}
voxbo-1.8.5~svn1246/munge/vbregion.hlp000066400000000000000000000004321153177201300175560ustar00rootroot00000000000000
VoxBo vbregion (v%1%)
summary: region info
usage:
  vbregion []  ...
flags:
  -t   include voxels where value > threshold
  -a   include voxels where abs(value) > thresh
  -m 
notes:
  The default threshold is -t 0 (include all positive voxels).
voxbo-1.8.5~svn1246/munge/vbse.cpp000066400000000000000000000137471153177201300167160ustar00rootroot00000000000000
// vbse.cpp
// estimate smoothness from residual map
// Copyright (c) 1998-2005 by Team VoxBo

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// some code written by Kosh Banerjee, based on code by Geoff Aguirre,
// based on methods by Kiebel et al.

using namespace std;

#include 
#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vbse.hlp.h"

void vbse_help();
void vbse_version();
int residualSmoothness(Tes &resTes,VB_Vector &mapSmoothness);
unsigned short shiftLeft(const unsigned short index,
                         const unsigned short dimIndex);

int
main(int argc,char *argv[])
{
  if (argc==1) {
    vbse_help();
    exit(0);
  }
  else if (argc!=3) {
    vbse_help();
    exit(100);
  }
  string infile=argv[1];
  string outfile=argv[2];

  Tes mytes;
  if (mytes.ReadFile(infile)) { 
    printf("[E] vbse: couldn't read file %s\n",infile.c_str());
    exit (200);
  }
  
  printf("[I] vbse: estimating smoothness from %s\n",infile.c_str());
  VB_Vector smoothness(3);
  residualSmoothness(mytes,smoothness);
  smoothness.setFileName(outfile);
  if (smoothness.WriteFile()) {
    printf("[E] vbse: error writing file %s\n",outfile.c_str());
    exit(110);
  }
  else
    printf("[I] vbse: done.\n");
  exit(0);
}

int
residualSmoothness(Tes &resTes,VB_Vector &mapSmoothness)
{
  uint32 volume = resTes.dimx * resTes.dimy * resTes.dimz;
  vector maskPoints;
  vector xNonZeros;
  vector yNonZeros;
  vector zNonZeros;
  
  double *rssq=new double[volume];
  memset(rssq, 0, sizeof(double) * volume);
  vector noBrain;

  for (int i=0; i 
voxbo-1.8.5~svn1246/munge/vbshift.cpp000066400000000000000000000214451153177201300174160ustar00rootroot00000000000000
// vbshift.cpp
// VoxBo shift correction module (corrects local shifts of whole voxels, with wrap)
// Copyright (c) 2003 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

// #include 
#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vbshift.hlp.h"

class shiftspec {
public:
  int x,y,z;
  double score;
};

class VBShifter {
private:
  Cube refcube,mycube;
  string refname,imagename,outname;
  string paramfile;
  tokenlist args;
  vector speclist;
  void Compare(int xoff,int yoff,int zoff,Cube &mycube);
  int x1,x2,y1,y2,z1,z2,ssx,ssy,ssz;
  void ShiftImage(Cube &mycube);
  void ShiftImage(Tes &mytes);
  int LoadRefCube();
  int ShiftFile();
public:
  int Go(tokenlist &args);
};

void vbshift_help();

int
main(int argc,char *argv[])
{
  stringstream tmps;
  tokenlist args;
  tzset();                     // make sure all times are timezone corrected
  if (argc < 2) {              // not enough args, display autodocs
    vbshift_help();
    exit(0);
  }

  args.Transfer(argc-1,argv+1);
  VBShifter r;
  int err=r.Go(args);
  exit(err);
}

int
VBShifter::Go(tokenlist &args)
{
  int err=0;

  if (args.size()<3) {
    vbshift_help();
    return 200;
  }
  imagename=args[0];
  outname=args[1];

  x1=-4;
  x2=4;
  y1=-4;
  y2=4;
  z1=-4;
  z2=4;
  ssx=ssy=ssz=0;

  for (size_t i=2; i refcube.dimx-1) xx-=refcube.dimx;
        while (zz > refcube.dimz-1) zz-=refcube.dimy;
        while (yy > refcube.dimy-1) yy-=refcube.dimz;
        ss.score+=fabs(refcube.GetValue(i,j,k)-mycube.GetValue(xx,yy,zz));
      }
    }
  }
  speclist.push_back(ss);
}

int
VBShifter::LoadRefCube()
{
  stringstream tmps;
  if (!(refcube.ReadFile(refname))) {
    tmps.str("");
    tmps << "vbshift: read reference volume from " << refname;
    printErrorMsg(VB_INFO,tmps.str());
    return 0;
  }
  Tes tmptes;
  if (!(tmptes.ReadFile(refname))) {
    refcube=tmptes[0];
    tmps.str("");
    tmps << "vbshift: read reference from the first volume of " << refname;
    printErrorMsg(VB_INFO,tmps.str());
    return 0;
  }
  tmps.str("");
  tmps << "vbshift: couldn't read reference from " << refname;
  printErrorMsg(VB_INFO,tmps.str());
  return 100;  
}

void
VBShifter::ShiftImage(Cube &mycube)
{
  int i,j,k,tmpx,tmpy,tmpz;
  struct tm *mytm;
  time_t mytime;
  stringstream tmps;

  mytime = time(NULL);
  mytm = localtime(&mytime);
  char timestring[STRINGLEN];
  strftime(timestring,STRINGLEN,"%d%b%Y_%T",mytm);
  mycube.AddHeader((string)"vbshift_date: "+timestring);

  if (refcube.data_valid) {
    tmps.str("");
    tmps << "vbshift: comparing " << imagename << " to reference volume " << refname;
    printErrorMsg(VB_INFO,tmps.str());
    // first build a list of comparisons at various offsets
    for (i=x1; i<=x2; i++) {
      for (j=y1; j<=y2; j++) {
	for (k=z1; k<=z2; k++) {
	  Compare(i,j,k,mycube);
	}
      }
    }
    
    int good=0;
    for (i=1; i<(int)speclist.size(); i++) {
      if (speclist[i].score < speclist[good].score)
	good=i;
    }
    ssx=speclist[good].x;
    ssy=speclist[good].y;
    ssz=speclist[good].z;
    mycube.AddHeader((string)"vbshift_ref: "+refname);
  }
  if (ssx==0 && ssy==0 && ssz==0)
    mycube.AddHeader("vbshift: no adjustment necessary");
  else {
    Cube newcube=mycube;
    for (int i=0; i mycube.dimx-1) tmpx-=mycube.dimx;
	  while (tmpy > mycube.dimy-1) tmpy-=mycube.dimy;
	  while (tmpz > mycube.dimz-1) tmpz-=mycube.dimz;
	  newcube.SetValue(i,j,k,mycube.GetValue(tmpx,tmpy,tmpz));
	}
      }
    }
    mycube=newcube;
  }
  tmps.str("");
  tmps << "vbshift_offset: " << ssx << " " << ssy << " " << ssz;
  mycube.AddHeader(tmps.str());
  printErrorMsg(VB_INFO,tmps.str());
}

void
VBShifter::ShiftImage(Tes &mytes)
{
  int i,j,k;
  struct tm *mytm;
  time_t mytime;
  stringstream tmps;

  mytime = time(NULL);
  mytm = localtime(&mytime);
  char timestring[STRINGLEN];
  strftime(timestring,STRINGLEN,"%d%b%Y_%T",mytm);
  mytes.AddHeader((string)"vbshift_date: "+timestring);

  if (refcube.data_valid) {
    tmps.str("");
    tmps << "vbshift: comparing " << imagename << " to reference volume " << refname;
    printErrorMsg(VB_INFO,tmps.str());
    Cube mycube=mytes[0];
    // first build a list of comparisons at various offsets
    for (i=x1; i<=x2; i++) {
      for (j=y1; j<=y2; j++) {
	for (k=z1; k<=z2; k++) {
	  Compare(i,j,k,mycube);
	}
      }
    }
    
    int good=0;
    for (i=1; i<(int)speclist.size(); i++) {
      if (speclist[i].score < speclist[good].score)
	good=i;
    }
    ssx=speclist[good].x;
    ssy=speclist[good].y;
    ssz=speclist[good].z;
    mytes.AddHeader((string)"vbshift_ref: "+refname);
  }
  if (ssx==0 && ssy==0 && ssz==0)
    mytes.AddHeader("vbshift: no adjustment necessary");
  else {
    // make a copy of the data pointer array and copy the new pointer
    // array from the old one
    unsigned char **tmpdata=new unsigned char *[mytes.dimx*mytes.dimy*mytes.dimz];
    memcpy(tmpdata,mytes.data,sizeof(unsigned char *)*mytes.dimx*mytes.dimy*mytes.dimz);
    int oldpos,newpos,tmpx,tmpy,tmpz;
    for (i=0; i mytes.dimx-1) tmpx-=mytes.dimx;
	  while (tmpy > mytes.dimy-1) tmpy-=mytes.dimy;
	  while (tmpz > mytes.dimz-1) tmpz-=mytes.dimz;
	  oldpos=mytes.voxelposition(tmpx,tmpy,tmpz);
	  newpos=mytes.voxelposition(i,j,k);
	  mytes.data[newpos]=tmpdata[oldpos];
	}
      }
    }
    delete tmpdata;
    mytes.Remask();
  }

  tmps.str("");
  tmps << "vbshift_offset: " << ssx << " " << ssy << " " << ssz;
  mytes.AddHeader(tmps.str());
  printErrorMsg(VB_INFO,tmps.str());
}

int
VBShifter::ShiftFile()
{
  stringstream tmps;
  Tes mytes;
  Cube mycube;
  int dims=0;

  if (!(mytes.ReadFile(imagename)))
    dims=4;
  else if (!(mycube.ReadFile(imagename)))
    dims=3;
  if (dims==0) {
    tmps.str("");
    tmps << "vbshift: couldn't read file " << imagename;
    printErrorMsg(VB_ERROR,tmps.str());
    return 140;
  }

  int err;
  if (dims==4) {
    ShiftImage(mytes);
    mytes.SetFileName(outname);
    err=mytes.WriteFile();
  }
  else { 
    ShiftImage(mycube); 
    mycube.SetFileName(outname);
    err=mycube.WriteFile();
  }
  if (!err) {
    tmps.str("");
    tmps << "vbshift: wrote " << outname;
    printErrorMsg(VB_INFO,tmps.str());
    return 0;
  }
  else {
    tmps.str("");
    tmps << "vbshift: error writing " << outname;
    printErrorMsg(VB_ERROR,tmps.str());
    return 110;
  }
}

void
vbshift_help()
{
  cout << boost::format(myhelp) % vbversion;
}
voxbo-1.8.5~svn1246/munge/vbshift.hlp000066400000000000000000000003601153177201300174100ustar00rootroot00000000000000
VoxBo vbshift (v%1%)
usage:
  vbshift in out [flags]
flags:
  -r   guess offset by comparison with file 
  -x        force shift of num in x 
  -y        force shift of num in y
  -z        force shift of num in z
voxbo-1.8.5~svn1246/munge/vbsim.cpp000066400000000000000000000160571153177201300170740ustar00rootroot00000000000000
// vbsim.cpp
// VoxBo simulated data generator
// Copyright (c) 2003-2010 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include "vbio.h"
#include "vbutil.h"
#include "imageutils.h"
#include 
#ifdef CYGWIN
#include "ieeefp.h"
#endif
#include "vbsim.hlp.h"

int get_datasize(VB_datatype type);

class VBSim {
private:
  int dimx,dimy,dimz,dimt;

  Cube anat;                        // anatomy
  string anatname;
  double n_mean,n_variance,n_fwhm;  // noise
  VB_Vector signal;
  string outfile;
  VB_datatype datatype;
  Tes mytes;
  Cube mycube;
  int AddUniform(Cube &cb,double low,double range,double sx,double sy,double sz);
  double gaussian_random(double sigma);
  gsl_rng *rng;
  int AddGaussian(Cube &cb,double mu,double variance,double sx=0.0,double sy=0.0,double sz=0.0);
public:
  int Go(int argc,char **argv);
};

void vbsim_help();

int
main(int argc,char *argv[])
{
  stringstream tmps;
  tzset();                     // make sure all times are timezone corrected
  VBSim sim;
  int err=sim.Go(argc-1,argv+1);
  exit(err);
}

int
VBSim::Go(int argc,char *argv[])
{
  tokenlist args;
  rng=NULL;
  dimx=0;
  dimy=0;
  dimz=0;
  dimt=0;
  n_mean=10.0;
  n_variance=5.0;
  n_fwhm=1.0;
  float vx=1.0;
  float vy=1.0;
  float vz=1.0;
  float vt=2000;
  uint32 rngseed=VBRandom();

  args.Transfer(argc,argv);

  if (args.size() == 0) {
    vbsim_help();
    exit(0);
  }

  for (size_t i=0; i       set dimensions
  -c               "anatomy" file (added to image)
  -s              seed for random number generator
  -n        noise mean,variance,and smoothness
  -z        set voxel sizes (t is usually TR in ms)
  -o          output filename (default \"data.tes\"
  -h                    help
  -v                    version
notes:
  FWHM is in voxels (data don't even have voxel sizes)

  using -c and -a is additive

  noise defaults to 10,5,1 if -n isn't specified

  If y, z, and t dimensions are 0, a 1D vector file is created.  If
  just t is 0, a 3D volume is created.  In the former case, the fwhm
  is ignored, but you still have to provide it.

  vbsim uses GSL's pseudo random number generator, specifically
  gsl_rng_mt19927, and uses gsl_ran_gaussian() to generate random
  variates with a Gaussian distribution.  If you use the -s flag to
  set the seed, you can get the program to produce predictable output
  (perhaps useful for testing purposes and for repeatable resampling
  tests).  Any integer in the 0-2^32 range is fine.  If -s isn't
  provided, the value is taken from /dev/urandom (system permitting).

voxbo-1.8.5~svn1246/munge/vbsmooth.cpp000066400000000000000000000166221153177201300176130ustar00rootroot00000000000000
// vbsmooth.cpp
// smoothing utility for voxbo
// Copyright (c) 2003-2004 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include "vbutil.h"
#include "vbio.h"
#include "imageutils.h"
#include "vbversion.h"
#include 
#include 
#include "vbsmooth.hlp.h"

int vbsmooth_smooth(tokenlist &args);
int smooth_file(string infile,string ofile);
int vbsmooth_estimate(tokenlist &args);
void vbsmooth_help();
void vbsmooth_version();

int
main(int argc,char *argv[])
{
  tzset();                     // make sure all times are timezone corrected
  if (argc < 2) {              // not enough args, display autodocs
    vbsmooth_help();
    exit(0);
  }

  tokenlist args;
  args.Transfer(argc-1,argv+1);
  if (args[0]=="-v") {
    vbsmooth_version();
    exit(0);
  }
  if (args[0]=="-h") {
    vbsmooth_help();
    exit(0);
  }


  int err;
  if (args[0]=="-e")
    err=vbsmooth_estimate(args);
  else
    err=vbsmooth_smooth(args);

  exit(err);
}

// FIXME should class-ify this

Cube mask,remask;
double sx,sy,sz;
enum smode {vb_mm,vb_vox} mode;
string maskfile,remaskfile;
string prepend="s";
int sflag=0;

int
vbsmooth_smooth(tokenlist &args)
{
  vector filelist;
  string outfile;

  // default smoothing kernel in vox
  mode=vb_vox;
  sx=sy=sz=3.0;

  for (size_t i=0; ifiletypes;
  Tes tes;

  if (sx<0 || sy<0 || sz<0) {
    tmps.str("");
    tmps << "vbsmooth: invalid smoothing kernel ";
    printErrorMsg(VB_ERROR,tmps.str());
    return 100;
  }

  if (maskfile.size()) {
    filetypes=EligibleFileTypes(maskfile);
    if (filetypes.size()<1) {
      printf("[E] vbsmooth: can't understand file %s",maskfile.c_str());
      return 100;
    }
    if (filetypes[0].getDimensions()==3)
      mask.ReadFile(maskfile);
    else {
      tes.ReadHeader(maskfile);
      if (tes.ExtractMask(mask)) {
        printf("[E] vbsmooth: can't extract mask from 4d file %s",maskfile.c_str());
        return 100;
      }
    }
  }
  if (remaskfile.size()) {
    filetypes=EligibleFileTypes(remaskfile);
    if (filetypes.size()<1) {
      printf("[E] vbsmooth: couldn't open (re)mask file %s\n",remaskfile.c_str());
      return 100;
    }
    if (filetypes[0].getDimensions()==3)
      remask.ReadFile(remaskfile);
    else {
      tes.ReadHeader(remaskfile);
      if (tes.ExtractMask(remask)) {
        printf("[E] vbsmooth: can't extract mask from 4d file %s\n",remaskfile.c_str());
        return 100;
      }
      remask.convert_type(vb_float,VBSETALT|VBNOSCALE);
    }
  }
  int err=0;
  for (int i=0; i<(int)filelist.size(); i++) {
    if (smooth_file(filelist[i],outfile))
      err++;
  }
  return err;
}

int
smooth_file(string infile,string ofile)
{
  stringstream tmps;
  vectorfiletypes;
  Cube cube;
  Tes tes;
  string outfile;

  if (ofile.size())
    outfile=ofile;
  else
    outfile=xdirname(infile)+(string)"/"+prepend+xfilename(infile);
  filetypes=EligibleFileTypes(infile);
  if (filetypes[0].getDimensions()==3) {
    if (cube.ReadFile(infile)) {
      tmps.str("");
      tmps << "vbsmooth: error reading " << infile;
      printErrorMsg(VB_ERROR,tmps.str());
      return 100;
    }
    if (mode==vb_mm) {
      sx/=cube.voxsize[0];
      sy/=cube.voxsize[1];
      sz/=cube.voxsize[2];
    }
    // if it's "fancy" remask, quantize to 1.0, smooth, thresh at 0.5, and quantize again
    if (sflag) {
      remask.quantize(1.0);
      smoothCube(remask,sx,sy,sz);
      remask.thresh(0.5);
      remask.quantize(1.0);
    } 
    printf("[I] vbsmooth: smoothing %s with a kernel (voxels) of %f,%f,%f\n",infile.c_str(),sx,sy,sz);

    if (mask.data)
      smoothCube_m(cube,mask,sx,sy,sz);
    else
      smoothCube(cube,sx,sy,sz);
    tmps.str("");
    tmps << "SpatialSmooth: " << timedate() << " " << sx << " " << sy << " " << sz;
    cube.AddHeader(tmps.str());
    cube.SetFileName(outfile);
    if (remask.data)
      cube.intersect(remask);
    if (cube.WriteFile()) {
      printf("[E] vbsmooth: error writing %s\n",infile.c_str());
      return 101;
    }
    else {
      printf("[I] vbsmooth: smoothed 4D data written to %s\n",outfile.c_str());
      return 0;
    }
  }
  else if (filetypes[0].getDimensions()==4) {
    if (tes.ReadFile(infile)) {
      printf("[E] vbsmooth: couldn't open file %s\n",infile.c_str());
      return 102;
    }
    if (mode==vb_mm) {
      sx/=tes.voxsize[0];
      sy/=tes.voxsize[1];
      sz/=tes.voxsize[2];
    }
    // if it's "fancy" remask, quantize to 1.0, smooth, thresh at 0.5, and quantize again
    if (sflag) {
      remask.quantize(1.0);
      smoothCube(remask,sx,sy,sz);
      remask.thresh(0.5);
      remask.quantize(1.0);
    }
    printf("[I] vbsmooth: smoothing %s with a kernel (voxels) of %f,%f,%f\n",infile.c_str(),sx,sy,sz);

    for (int i=0; i ...]    smooth all passed files
  vbsmooth -e               estimate smoothness of image
flags:
  -vox       specify fwhm in voxels
  -mm        specify fwhm in mm
  -m            mask file, use only for variance maps
  -r            remask using mask cube or tes mask
  -s            special remask (see below)
  -p             tag to prepend to outfile if not using -o
  -o        set output filename
  -h                  help
  -v                  version
notes:
  default smoothing kernel is 3x3x3 voxels

  default output filename is input filename prepended with an s

  you can override the prepend with -p

  Note that there are three remasking options.  -m divides by the mask
  (should be used for variance maps).  -r remasks using the mask
  specified.  -s remasks by smoothing the mask passed, and including
  any voxel that is more than 50 percent from within the original
  mask.
voxbo-1.8.5~svn1246/munge/vbthresh.cpp000066400000000000000000000374511153177201300176020ustar00rootroot00000000000000
// vbthresh.cpp
// Copyright (c) 1998-2010 by The VoxBo Development Team

// This file is part of VoxBo
// 
// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
// 
// original version written by Kosh Banerjee, modified by Dan Kimberg

using namespace std;

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "vbprefs.h"
#include "vbutil.h"
#include "vbio.h"
//#include "utils.h"
//#include "koshutil.h"
#include "vbthresh.hlp.h"

unsigned int determineCutOff(const int binSize, Tes& tesFile);
void processData(Tes& theTes, const int cutOff);
void vbthresh_help();
void vbthresh_version();

int
main(int argc, char *argv[])
{
  /*********************************************************************
  * VARIABLES:   TYPE:           DESCRIPTION:                          *
  * ----------   -----           ------------                          *
  * cutOff       int             Holds the threshold cut off value.    *
  * tesFile      string          Holds the input 4D data file name.    *
  * outFile      string          Holds the output file name.           *
  * binSize      int             Holds the bin size (if the histogram  *
  *                              thresh holding is used).              *
  *********************************************************************/
  int cutOff = 0;
  int binSize = 0;
  string tesFile;
  string outFile;
  if (argc == 1) {
    vbthresh_help();
    exit(0);
  }

  /*********************************************************************
  * Now processing the command line options.                           *
  * -h ==> Display usage information.                                  *
  * -i ==> Specifies the input 4D data file.                           *
  * -o ==> Specifies the output file name.                             *
  * -c ==> Specifies the threshold cut off value.                      *
  * -b ==> Specifies the bin size for histogram thresh holding.        *
  * -v ==> Print global VoxBo version.                                 *
  *                                                                    *
  * Now processing the command line options. printHelp is a flag       *
  * variable, used to determine if the "-h" command line option was    *
  * used or not. printVersion is a flag variable, used to determine if *
  * the user wants the global VoxBo version printed or not.            *
  *********************************************************************/
  arghandler a;
  a.setArgs("-h", "--help", 0);
  a.setArgs("-i", "--inputfile", 1);
  a.setArgs("-o", "--outfile", 1);
  a.setArgs("-c", "--threshold", 1);
  a.setArgs("-b", "--binsize", 1);
  a.setArgs("-v", "--version", 0);
  a.parseArgs(argc, argv);
  string errstring = a.badArg();
  if (errstring.size()) {
     errstring = "[E] unknown flag: " + errstring;
     printErrorMsg(VB_ERROR, errstring.c_str());
     exit(-1);
  }
  if (a.flagPresent("-h")) {
    vbthresh_help();
    exit(0);
  }
  tesFile = a.getFlaggedArgs("-i")[0];
  outFile = a.getFlaggedArgs("-o")[0];
  cutOff = atoi(a.getFlaggedArgs("-c")[0].c_str());
  binSize = atoi(a.getFlaggedArgs("-b")[0].c_str());
  if (a.flagPresent("-v")) {
    vbthresh_version();
    exit(0);
  }
  if (binSize < 0) {
    ostringstream errorMsg;
    errorMsg << "Line Number [" << __LINE__ << "] binSize: [" << binSize << "] must be > 0.";
    printErrorMsg(VB_ERROR, errorMsg.str());
  } 
  if (tesFile.size() == 0) {
    ostringstream errorMsg;
    errorMsg << "Line Number [" << __LINE__ << "] Must specify the input 4D data file name.";
    printErrorMsg(VB_ERROR, errorMsg.str());
  } 
  if (outFile.size() == 0)
    outFile = tesFile;
  /*********************************************************************
  * If the threshold cut off value was not specified at the command    *
  * line and binSize == 0, then cutOff is assigned the default value   *
  * of 600. NOTE: If binSize is 0, then it is assumed that "-b" was    *
  * not used as a command line option for this program.                *
  *********************************************************************/
  if ( (cutOff == 0) && (binSize == 0) )
    cutOff = 600;
  Tes theTes(tesFile);
  if (!theTes.data_valid) {
    ostringstream errorMsg;
    errorMsg << "Line Number [" << __LINE__ << "] Unable to read VoxBo 4D file [" << tesFile << "].";
    printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1);
  } 
  if (binSize > 0)
    cutOff = determineCutOff(binSize, theTes);
  processData(theTes, cutOff);
  string timeStr=timedate();
  ostringstream headerLine;
  headerLine << "Thresh_Abs:" << "\t" << timeStr << "\t" << cutOff;
  theTes.AddHeader(headerLine.str());
  theTes.SetFileName(outFile);
  if (theTes.WriteFile(outFile)) {
    ostringstream errorMsg;
    errorMsg << "Line Number [" << __LINE__ << "] Could not write to output file [" << theTes.filename << "].";
    printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 6);
  } 
  return 0;
} 

// if the minimum signal value is less than the threshold value for a
// particular voxel, that voxel is zeroed out for the whole time
// series

void
processData(Tes& theTes, const int cutOff)
{
  for (int i=0; i histogram[localMin], then histogram[i] has just  *
    * started to increase. This means that the current value of localMin *
    * is an index of a local minimum in histogram[]. We must also check  *
    * to see if this local minimum is greater than zero.                 *
    *********************************************************************/
    if ( (histogram[i] > histogram[localMin]) && ((signalMin + (localMin * binSize)) > 0) )
      break;
    /*********************************************************************
    * If program flow ends up here, then histogram[i] is still decreasing*
    * and so we have not yet found the index of the first local minimum. *
    * Therefore, localMin is set to i.                                   *
    *********************************************************************/
    else
      localMin = i;
  } 

  /*********************************************************************
  * Now returning the lower boundary value of the "bin" in histogram[] *
  * corresponding to localMin.                                         *
  *********************************************************************/
  return (signalMin + (localMin * binSize));
} 


void
vbthresh_help()
{
  cout << boost::format(myhelp) % vbversion;
}

void
vbthresh_version()
{
  printf("VoxBo vbthresh (v%s)\n",vbversion.c_str());
}

voxbo-1.8.5~svn1246/munge/vbthresh.hlp000066400000000000000000000010151153177201300175660ustar00rootroot00000000000000
VoxBo vbthresh (v%1%)
summary: threshold 4D files
usage:
  vbthresh [...]
flags:
  -i           input 4D filename
  -o           set output filename (default: input filename)
  -c            absolute threshold value
  -b           bin size for histogram thresholding method
  -h                 show help
  -v                 show version
notes:
  The -i argument must be provided.

  Note that if vbthresh finds a value below threshold, it zeroes out
  the entire time series for that voxel.

voxbo-1.8.5~svn1246/munge/vbtool.cpp000066400000000000000000000107041153177201300172520ustar00rootroot00000000000000
// vbtool.cpp
// general-purpose voxbo tool
// Copyright (c) 2010 by The VoxBo Development Team

// This file is part of VoxBo
// 
// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include 
#include 
#include 
#include "vbutil.h"
#include "vbjobspec.h"
#include "vbio.h"
#include "vbprefs.h"
#include "vbtool.hlp.h"

VBPrefs vbp;

void vbtool_help();
void vbtool_version();
void vbtool_tip();
void vbtool_dumpconfig();

int
main(int argc,char *argv[])
{
  vbp.init();
  vbp.read_jobtypes();
  if (argc<2) {
    vbtool_help();
    exit(0);
  }
  tokenlist args;
  string mode=argv[1];
  bool f_endl=0;    // newlines around tips
  int f_ntips=1;   // number of tips
  args.Transfer(argc-2,argv+2);
  for (size_t i=0; i50) f_ntips=50;
      if (f_ntips<1) f_ntips=1;
    }
    else if (args[i]=="-w") {
      f_endl=1;
    }
  }


  if (mode=="dirname") {
  }
  else if (mode=="conf") {
    vbtool_dumpconfig();
  }
  else if (mode=="contrast") {
    cout << contrasthelp;
  }
  else if (mode=="tip") {
    if (f_endl) cout << endl;
    for (int i=0; i0) cout << endl;
      vbtool_tip();
    }
    if (f_endl) cout << endl;
  }
  else if (mode=="pri") {
    cout << priorityhelp;
  }
  else {
    cout << "[E] vbtool: unrecognized function" << endl;
    vbtool_help();
  }
  exit(0);
}

void
vbtool_tip()
{
  tokenlist lines;
  vglob vg;
  vg.append(vbp.rootdir+"/etc/tips.txt",vglob::f_filesonly);
  vg.append(vbp.rootdir+"/etc/localtips.txt",vglob::f_filesonly);
  vg.append(vbp.userdir+"/etc/tips.txt",vglob::f_filesonly);
  vg.append(vbp.homedir+"/.voxbo/tips.txt",vglob::f_filesonly);
  vg.append(vbp.homedir+"/voxbotips.txt",vglob::f_filesonly);
  for (size_t i=0; i tips;
  vbforeach(string line,lines) {
    if (line.substr(0,3)=="---") {
      if (tip.size())
        tips[VBRandom()]=tip;
      tip="";
      continue;
    }
    // first line can't begin with a # or it's considered a comment
    if (tip.empty() && line[0]=='#') continue;
    // first line must also have some non-whitespace
    if (tip.empty() && xstripwhitespace(line).empty()) continue;
    if (tip.empty()) tip=line;
    else tip+="\n"+line;
  }
  if (tip.size())
    tips[VBRandom()]=tip;
  string mytip=tips.begin()->second;
  mytip=xstripwhitespace(mytip,"\n");
  cout << mytip << endl;
}

void
vbtool_dumpconfig()
{
  printf("\nVoxBo configuration info:\n\n");

  if (vbp.su) printf("You are a VoxBo super-user.\n");
  else printf("You are a regular VoxBo user.\n");

  // user stuff
  printf("User Config:\n");
  printf("  username: %s\n",vbp.username.c_str());
  printf("  email address: %s\n",vbp.email.c_str());
  printf("  home directory: %s\n",vbp.homedir.c_str());
  printf("  user directory: %s\n",vbp.userdir.c_str());

  // system stuff
  printf("System Config:\n");
  printf("  root directory %s\n",vbp.rootdir.c_str());
  printf("  queuedir: %s\n",vbp.queuedir.c_str());
  printf("  host name: %s\n",vbp.thishost.hostname.c_str());
  printf("  host nickname: %s\n",vbp.thishost.nickname.c_str());
  printf("  ncores: %d (%s mode)\n",vbp.cores,(vbp.cores?"desktop":"cluster"));
  printf("\n");
}

void
vbtool_help()
{
  cout << boost::format(myhelp) % vbversion;
}

void
vbtool_version()
{
  printf("VoxBo vbtool (v%s)\n",vbversion.c_str());
}
voxbo-1.8.5~svn1246/munge/vbtool.hlp000066400000000000000000000007721153177201300172570ustar00rootroot00000000000000
VoxBo vbtool (v%1%)
summary:
  vbtool is an all-purpose tool for getting information about VoxBo
usage:
  vbtool tip -n  -w  show n randomly selected VoxBo tips (default:1)
                        -w adds a blank line before and after
  vbtool conf           show various config settings
  vbtool contrast       show help on specifying a statistical contrast
  vbtool pri            show help on specifying job priorities
  vbtool -h             see this help
  vbtool -v             just get version

voxbo-1.8.5~svn1246/munge/vbvec2hdr.cpp000066400000000000000000000064041153177201300176340ustar00rootroot00000000000000
// vbvec2hdr.cpp
// copy information from a vec to an image header
// Copyright (c) 2010 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include "vbutil.h"
#include "vbio.h"
//#include "vbprefs.h"
#include "vbvec2hdr.hlp.h"

int newheader(string tag,string file,string &result);
void vbvec2hdr_help();
void vbvec2hdr_version();

int
main(int argc,char *argv[])
{
  if (argc==1) {
    vbvec2hdr_help();
    exit(106);
  }
  tokenlist args;
  vector newheaders;
  string outfile;
  args.Transfer(argc-1,argv+1);
  
  for (size_t i=0; i
flags:
  -o     set hdr line (replace or add)
  -t    vector file and text tag (in quotes)
  -h              show help
  -v              print version
voxbo-1.8.5~svn1246/munge/vecsplit.cpp000066400000000000000000000045501153177201300176000ustar00rootroot00000000000000
// vecsplit.cpp
// little hack to bust up movement param files
// Copyright (c) 2004 by The VoxBo Development Team

// VoxBo 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.
// 
// VoxBo 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 VoxBo.  If not, see .
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include 
#include 
#include 
#include "vbutil.h"
#include "vbio.h"
#include "vecsplit.hlp.h"

void vecsplit_help();

int
main(int argc,char *argv[])
{
  tokenlist args;
  int ind;
  string filename;

  args.Transfer(argc-1,argv+1);

  if (args.size() == 0) {
    vecsplit_help();
    exit(0);
  }

  VB_Vector x,y,z,pitch,roll,yaw;
  for (size_t i=0; i ...]
notes:
  for every movement parameter file you specify, vecsplit will split
  it into six separate vectors, for the six paramters.
voxbo-1.8.5~svn1246/qa/000077500000000000000000000000001153177201300145255ustar00rootroot00000000000000voxbo-1.8.5~svn1246/qa/Makefile000066400000000000000000000001321153177201300161610ustar00rootroot00000000000000ifeq ($(shell uname -s), Darwin)
	include Makefile.mac
else
	include Makefile.linux
endif
voxbo-1.8.5~svn1246/qa/Makefile.linux000066400000000000000000000024651153177201300173320ustar00rootroot00000000000000
# Makfile for qa

include ../make_stuff.txt

# place to search for includes and targets
VPATH = ../lib:../vbwidgets
# voxbo libs that might be important here
VBLIBS=libvbutil.a libvbio.a libvbprefs.a

CPLUS_INCLUDE_PATH=../lib:$(QTINCDIR):../vbwidgets:/sw/include
LIBRARY_PATH=:../lib:$(QTLIBDIR):/usr/X11R6/lib:/sw/lib
export CPLUS_INCLUDE_PATH LIBRARY_PATH
OBJECTS=vbqa.o ../vbwidgets/display.o ../vbwidgets/moc_display.o
XLIBS=-lX11 -lXext -lpthread 
LIBS=-lvbio -lvbprefs -lvbutil -lz $(QTLIBNAME) $(GSL_LIBS) $(XLIBS) $(DLLIB)
CFLAGS=-O3 -Wall

# qtsurf itself

all: vbqa

install:
	cp vbqa $(BINDIR)

vbqa: $(OBJECTS) $(VBLIBS)
	$(CXX) -o vbqa $(OBJECTS) $(LIBS) $(RPATHS)

# the objects

vbqa.o: ../vbwidgets/display.h vbqa.cpp
	$(CXX) -c vbqa.cpp -Wall $(CFLAGS)

testx.o: testx.cpp
	$(CXX) -c testx.cpp -Wall $(CFLAGS)

# display code

../vbwidgets/display.o: ../vbwidgets/display.cpp ../vbwidgets/display.h
	make -C ../vbwidgets display.o

../vbwidgets/moc_display.o: ../vbwidgets/moc_display.cpp ../vbwidgets/display.h 
	make -C ../vbwidgets moc_display.o

../vbwidgets/moc_display.cpp: $(MOC) ../vbwidgets/display.h ../vbwidgets/display.cpp 
	$(MOC) ../vbwidgets/display.h -o moc_display.cpp

# clean!

clean:
	rm -f *.o *~ *.moc.h vbqa qatest *.exe

# rule to build the libvoxbo libraries
$(VBLIBS):
	make -C ../lib $@
voxbo-1.8.5~svn1246/qa/Makefile.mac000066400000000000000000000037231153177201300167310ustar00rootroot00000000000000
# Makfile for qa, mac version

include ../make_stuff.txt

# place to search for includes and targets
VPATH = ../lib:../vbwidgets
# voxbo libs that might be important here
VBLIBS=libvbutil.a libvbio.a libvbprefs.a
DEL_FILE = rm -f  
CPLUS_INCLUDE_PATH=../lib:$(QTINCDIR):../vbwidgets:/sw/include
LIBRARY_PATH=:../lib:$(QTLIBDIR):/usr/X11R6/lib:/sw/lib
export CPLUS_INCLUDE_PATH LIBRARY_PATH
OBJECTS=vbqa.o ../vbwidgets/display.o ../vbwidgets/moc_display.o
XLIBS=-lX11 -lXext -lXrender -lpthread -lSM -lGL
LIBS=-lvbio -lvbprefs -lvbutil $(QTLIBNAME) -lgsl -lgslcblas -lz $(XLIBS) -framework Carbon

all: vbqa.app/Contents/MacOS/../PkgInfo vbqa.app/Contents/MacOS/../Info.plist vbqa

install:
	cp vbqa $(BINDIR)

vbqa: $(OBJECTS) $(VBLIBS)
	$(CXX) -o vbqa.app/Contents/MacOS/vbqa $(OBJECTS) $(LIBS) $(RPATHS)

vbqa.app/Contents/MacOS/../PkgInfo:
	@test -d vbqa.app/Contents/MacOS/ || mkdir -p vbqa.app/Contents/MacOS/
	@$(DEL_FILE) vbqa.app/Contents/MacOS/../PkgInfo
	@echo "APPL????" >vbqa.app/Contents/MacOS/../PkgInfo
vbqa.app/Contents/MacOS/../Info.plist:
	@test -d vbqa.app/Contents/MacOS/ || mkdir -p vbqa.app/Contents/MacOS/
	@$(DEL_FILE) vbqa.app/Contents/MacOS/../Info.plist
	@sed -e "s,@ICON@,application.icns,g" -e "s,@EXECUTABLE@,vbqa,g" "/usr/local/qt/mkspecs/macx-g++/Info.plist.app" >"vbqa.app/Contents/MacOS/../Info.plist"

# the objects

vbqa.o: ../vbwidgets/display.h vbqa.cpp
	$(CXX) -c vbqa.cpp -Wall $(CFLAGS)

testx.o: testx.cpp
	$(CXX) -c testx.cpp -Wall $(CFLAGS)

# display code

../vbwidgets/display.o: ../vbwidgets/display.cpp ../vbwidgets/display.h
	make -C ../vbwidgets display.o

../vbwidgets/moc_display.o: ../vbwidgets/moc_display.cpp ../vbwidgets/display.h 
	make -C ../vbwidgets moc_display.o

../vbwidgets/moc_display.cpp: $(MOC) ../vbwidgets/display.h ../vbwidgets/display.cpp 
	$(MOC) ../vbwidgets/display.h -o moc_display.cpp

# clean!

clean:
	rm -f *.o *~ *.moc.h vbqa qatest
	rm -r -f vbqa.app

# rule to build the libvoxbo libraries
$(VBLIBS):
	make -C ../lib $@
voxbo-1.8.5~svn1246/qa/qatest.cpp000066400000000000000000000106651153177201300165420ustar00rootroot00000000000000
using namespace std;

#include "display.moc.h"
#include "vb_vector.h"
#include 
#include 
#include 
#include 
#include 

class VBQA {
public:
  string datadir;        // where to look for data
  string outputdir;      // where to put the reports
  ofstream outfile;      // the output file, open during execution
  int Go(string,string);
  void ShowNormSlices();
  void PlotMoveParams();
  void GenerateMovementWarnings();
  void PlotGlobalSignal();
  void CopyGLMInfo();
};

// EXAMPLE OF HOW TO CAPTURE A PLOT
//   QFrame me;
//   PlotScreen ps(&me);
//   ps.setInputFile("test.ref");
//   //ps.setPlotMode(1);
//   ps.setUpdatesEnabled(TRUE);
//   ps.setYCaption("Hi There");
//   ps.setOrgXLength(250);
//   ps.setXCaption("Yo yo yo");
//   me.show();
//   QPixmap::grabWidget(&ps).save("test.png","PNG");

int
main(int argc,char **argv)
{
  QApplication a(argc,argv); // qt init
  QFont f("Helvetica",10,0);
  a.setFont(f);
  if (argc<3)
    exit(100);
  VBQA qa;
  qa.Go(argv[1],argv[2]);
  exit(0);
}


int
VBQA::Go(string data_dir,string output_dir)
{
  datadir=data_dir;
  outputdir=output_dir;
  // FIXME should really get the dirs graphically
  mkdir(outputdir.c_str(),0777);
  outfile.open((outputdir+(string)"/"+"index.html").c_str(),ios::out);
  if (!outfile)
    return (100);
  ShowNormSlices();
  PlotMoveParams();
  GenerateMovementWarnings();
  PlotGlobalSignal();
  CopyGLMInfo();
  outfile.close();
}

void
VBQA::ShowNormSlices()
{
  QWidget w;
  int i,interval;
  glob_t gb;

  glob("*/nNorm.cub",0,NULL,&gb);
  for (i=0; i.
// 
// For general information on VoxBo, including the latest complete
// source code and binary distributions, manual, and associated files,
// see the VoxBo home page at: http://www.voxbo.org/
//
// original version written by Dan Kimberg

using namespace std;

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "plotscreen.h"
#include "vbutil.h"
#include "vbio.h"
#include "vbprefs.h"

void boxit(ofstream &os,string text,string subtext);
void vbqa_help();

class ProcPattern {
public:
  vector  steps;
  vector  filelist;
};

class VBQA {
private:
//   vector normpat;
//   vector showallpat;
//   vector filepat;
public:
  vectordirlist;
  string outputdir;      // where to put the reports
  ofstream outfile;      // the output file, open during execution
  int levels;
  int Go(tokenlist &args);
  // the actual tests
  void ShowNormSlices(vector dirlist);
  void PlotMoveParams(vector dirlist);
  void GenerateMovementWarnings(vector dirlist);
  void PlotGlobalSignal(vector dirlist);
  void CheckGLMInfo(vector dirlist);
  void ExamineTesFiles(vector dirlist);
  // build this build that
  void BuildIndex();
  void BuildDirList(string dir,int level);
  // void LoadQAConf();
};

VBPrefs vbp;

int
main(int argc,char **argv)
{
  tokenlist args;
  args.Transfer(argc-1,argv+1);
  if (args.size()==0) {
    vbqa_help();
    exit(0);
  }

  QApplication a(argc,argv); // qt init
  QWidget w(NULL,NULL);
  a.setMainWidget(&w);
  QFont f("Helvetica",10,0);
  a.setFont(f);
  VBQA qa;

  vbp.init();
  qa.Go(args); 
  exit(0);
}

int
VBQA::Go(tokenlist &args)
{
  string outputname;
  string rootdir;
  vector deletelist;
  int i,deleteflag=0;
  char tmp[STRINGLEN];

  // default: no levels deep, use current dir, use dirname as name
  levels=100;
  char buf[STRINGLEN];
  getcwd(buf,STRINGLEN);
  outputname=buf;
  rootdir=buf;
  if (outputname=="") outputname="foo";

  for (i=0; i\n\nYour VoxBo Quality Assurance Page\n" << endl;
  indstream << "\n\n";
  indstream << "

Your VoxBo Quality Assurance Page

\n\n"; indstream << "

" << endl; indstream << "The table below shows your collection of VoxBo quality assurance reports," << endl; indstream << "generated by vbqa. To delete one of these reports, type" << endl; indstream << "vbqa -d , where is the name of the report you want to" << endl; indstream << "delete (if it has spaces, enclose the name in double quotes.)" << endl; indstream << "For more information, type vbqa (with no arguments) at the" << endl; indstream << "command line." << endl; indstream << "

" << endl; indstream << "" << endl; indstream << "" << endl; vglob vg(vbp.homedir+"/.voxbo/reports/*"); for (size_t i=0; i
Try one of these links:
" << endl; sprintf(tmp,"%s", vbp.homedir.c_str(),fname.c_str(),fname.c_str()); indstream << tmp << endl; } indstream << "
\n\n\n" << endl; indstream.close(); return; } void VBQA::ShowNormSlices(vector dirlist) { QWidget w; int j,interval; glob_t gb; char fname[512]; Cube cube; if (dirlist.size()==0) return; for (size_t i=0; i"+vg[i]+(string)""; boxit(outfile,"Normalization Results",subtitle); // outfile << "

Normalization Results

" << endl; outfile << "

" << endl; outfile << "Here are some normalized slices from " << vg[i] << ":" << endl; outfile << "

" << endl; outfile << "

" << endl; outfile << "" << endl; outfile << "" << endl; outfile << "" << endl; outfile << "" << endl; outfile << "
" << endl; outfile << "

" << endl; } // FIXME should also show some slices from the template, to see how things went } void VBQA::PlotMoveParams(vector dirlist) { VB_Vector allmoveparams,x,y,z,pitch,roll,yaw,iterations; size_t i,j,multiples; char fname[STRINGLEN]; for (i=0; i1) multiples++; } char tmpf[STRINGLEN]; PlotScreen ps(NULL); ps.setPlotMode(1); ps.setUpdatesEnabled(TRUE); // FIXME ps.setOrgXLength(points); ps.setXCaption("Image Number (starting with 0)"); ps.addVector(&x,"red"); ps.addVector(&y,"green"); ps.addVector(&z,"blue"); ps.setYCaption("Motion in xyz (mm, red/green/blue)"); sprintf(tmpf,"%s/move_%d_xyz.png",outputdir.c_str(),i); QPixmap::grabWidget(&ps).save(tmpf,"PNG"); ps.clear(); ps.addVector(&pitch,"red"); ps.addVector(&roll,"green"); ps.addVector(&yaw,"blue"); ps.setYCaption("Pitch, roll, and yaw (degrees, red/green/blue)"); sprintf(tmpf,"%s/move_%d_pry.png",outputdir.c_str(),i); QPixmap::grabWidget(&ps).save(tmpf,"PNG"); ps.clear(); ps.addVector(&iterations); ps.setYCaption("Iterations applied to correct movement"); sprintf(tmpf,"%s/move_%d_iter.png",outputdir.c_str(),i); QPixmap::grabWidget(&ps).save(tmpf,"PNG"); string subtitle=(string)"movement parameters from directories below "+(string)dirlist[i]+(string)""; boxit(outfile,"Movement Parameter Graphs",subtitle); // outfile << "

Movement Parameters

" << endl; outfile << "

" << endl; outfile << "Here are graphs of your movement parameters." << endl; outfile << "

" << endl; if (multiples) { outfile << "

" << endl; outfile << "Warning" << endl; outfile << "Note that " << multiples << " of your images " << (multiples==1 ? "was" : "were") << " corrected more than once." << endl; outfile << "

" << endl; } outfile << "

" << endl; outfile << "
" << endl; outfile << "
" << endl; outfile << "
" << endl; outfile << "

" << endl; } } void VBQA::GenerateMovementWarnings(vector dirlist) { } void VBQA::PlotGlobalSignal(vector dirlist) { VB_Vector allgs; size_t i,j; char fname[STRINGLEN]; for (i=0; i"+(string)dirlist[i]+(string)""; boxit(outfile,"Global Signal",subtitle); outfile << "
from below directory: " << dirlist[i] << "

" << endl; outfile << "

" << endl; outfile << "Here is the global signal from all your processed 4D files, concatenated" << endl; outfile << "into one big graph." << endl; outfile << "

" << endl; // hardcoded criterion for spikes: mean +/- 4sd double sd=sqrt(allgs.getVariance()); double mean=allgs.getVectorMean(); double low=mean-(3.5*sd); double high=mean+(3.5*sd); vector spikes,lowvals; for (j=0; j<(int)allgs.getLength(); j++) { if (allgs[j]>high || allgs[j]" << endl; outfile << "Warning" << endl; outfile << "We found " << spikes.size() << " spikes in your data, using a criterion of 3.5sd," << endl; outfile << "at the following time points (counting from 0): " << endl; outfile << spikes[0]; for (j=1; j<(int)spikes.size(); j++) outfile << ", " << spikes[j]; outfile << "\n

" << endl; } if (lowvals.size()) { outfile << "

" << endl; outfile << "Warning" << endl; outfile << "We found " << lowvals.size() << " values in your data below an absolute value of .001," << endl; outfile << "at the following time points (counting from 0): " << endl; for (j=0; j<(int)lowvals.size(); j++) outfile << lowvals[j] << " "; outfile << "It might not be an issue, but you might want to make sure data didn't get zeroed out somehow." << endl; outfile << "

" << endl; } outfile << "

" << endl; outfile << "
" << endl; outfile << "

" << endl; } } void VBQA::CheckGLMInfo(vector dirlist) { size_t i,j; ifstream infofile; struct stat st; string prmname,subtitle; char buf[STRINGLEN]; int goflag; int aftercollflag=0,collinearitywarnings=0; tokenlist toks; toks.SetSeparator("\t\n"); for(i=0; i<(int)dirlist.size(); i++) { vglob vg("*.info"); vg.append("*/*.info"); for (j=0; j"+(string)gb.gl_pathv[j]+(string)""; boxit(outfile,"GLM Audit Results",subtitle); outfile << "
" << endl;
        goflag=0;
        while (!infofile.eof()) {
          infofile.getline(buf,STRINGLEN);
          toks.ParseLine(buf);
          // lines to ignore
          if (toks[0]==";VB98") continue;
          if (toks[0]==";TXT1") continue;
          if (toks[0]==";" && toks.size()==1) continue;
          // get rid of leading blank lines
          if (buf[0]=='\0' && !goflag) continue;
          // lines to correct
          if (toks[0]=="(null)")
            buf[0]='\0';
          if (toks[0]=="Colinearity" || toks[0]=="Collinearity")
            aftercollflag=1;
          if (toks.size()==3) {
            double rmul=strtod(toks[2]);
            if (isdigit(toks[0][0]) && rmul < 1.01 && rmul < 0.5)
              collinearitywarnings++;
          }
          outfile << buf << endl;
          goflag=1;
        }
        outfile << "
" << endl; infofile.close(); if (collinearitywarnings) outfile << "Warning: " << collinearitywarnings << " of your variables had Rmul values above 0.5" << endl; } } } } void boxit(ofstream &os,string text,string subtext) { os << "" << endl; os << "" << endl; os << "" << endl; os << "
" << endl; os << text << endl; os << "
" << endl; os << subtext << endl; os << "
" << endl; } void VBQA::BuildDirList(string dir,int level) { // first add it dirlist.push_back(dir); // if level>0, scan for children struct stat st; string entries=dir+"/*"; if (level > 0) { vglob vg(entries); for (size_t i=0; i dirlist) { vector pplist; size_t i,j,foundit; char tmp[STRINGLEN],fname[STRINGLEN]; tokenlist args; vglob vg; for (i=0; i mysteps; mytes.ReadFile(vg[i]); // FIXME should be readheader probably // make a list of all the characteristics of mytes, start with // some basic header info sprintf(tmp,"dim(%d,%d,%d)",mytes.dimx,mytes.dimy,mytes.dimz); mysteps.push_back(tmp); sprintf(tmp,"voxsize(%.4f,%.4f,%.4f)",mytes.voxsize[0],mytes.voxsize[1],mytes.voxsize[2]); mysteps.push_back(tmp); // FIXME this loop detects common header tags that we should // match. we can probably do a little better than hardcoding, if // we want. for (j=0; j<(int)mytes.header.size(); j++) { args.ParseLine(mytes.header[j]); if (!args.size()) continue; if (args[0]=="AcqCorrect:") { sprintf(tmp,"acqcorrect(%s,%s)",args[2].c_str(),args[3].c_str()); mysteps.push_back(tmp); } if (args[0]=="TR(msecs):") { sprintf(tmp,"tr(%s)",args[1].c_str()); mysteps.push_back(tmp); } if (args[0]=="PulseSeq:") { sprintf(tmp,"pulseseq(%s)",args[1].c_str()); mysteps.push_back(tmp); } else if (args[0]=="ChangeOrient:") { sprintf(tmp,"orient(%s)",args[2].c_str()); mysteps.push_back(tmp); } else if (args[0]=="Realigned" && args[1]=="by" && args[2]=="realign:") mysteps.push_back("realign"); else if (args[0]=="realign_date") mysteps.push_back("realign"); else if (args[0]=="Thresh_Abs:") { sprintf(tmp,"thresh(%s)",args[2].c_str()); mysteps.push_back(tmp); } else if (args[0]=="Normalized" && args[1]=="by" && args[2]=="norm:") mysteps.push_back("norm"); else if (args[0]=="SpatialSmooth:") { sprintf(tmp,"smooth(%s,%s,%s)",args[2].c_str(),args[3].c_str(),args[4].c_str()); mysteps.push_back(tmp); } } foundit=0; for (j=0; j<(int)pplist.size(); j++) { if (pplist[j].steps==mysteps) { pplist[j].filelist.push_back(vg[i]); foundit=1; break; } } if (!foundit) { ProcPattern newpp; newpp.steps=mysteps; newpp.filelist.push_back(vg[i]); pplist.push_back(newpp); } } string subtitle="includes TES files from all directories specified"; boxit(outfile,"TES File Consistency Check",subtitle); outfile << "

" << endl; outfile << "The TES files listed below have been grouped according to various" << endl; outfile << "characteristics, including their dimensions and some of the processing steps" << endl; outfile << "applied to them. Files that have been grouped together" << endl; outfile << "are not guaranteed to have been processed identically, but files grouped separately" << endl; outfile << "almost certainly differ in some way." << endl; outfile << "So you might be concerned if you see any oddballs, files that should" << endl; outfile << "have been processed just like the rest but for some reason weren't." << endl; outfile << "Or if you half your subjects were processed one way, half another." << endl; outfile << "Note that this program only knows about certain things, mostly the standard" << endl; outfile << "set of VoxBo preprocessing steps. So you still need to be careful, even." << endl; outfile << "if all your TES files end up in the expected number of groups." << endl; outfile << "

" << endl; // now print out the groups for (i=0; i" << endl; outfile << "" << endl; outfile << "" << endl; outfile << "" << endl; outfile << "
Group " << i+1 << "
Characteristics
Files
" << endl; for (j=0; j<(int)pplist[i].steps.size(); j++) { outfile << pplist[i].steps[j] << "
" << endl; } outfile << "
" << endl; for (j=0; j<(int)pplist[i].filelist.size(); j++) { outfile << pplist[i].filelist[j] << "
" << endl; } outfile << "

" << endl; } return; } // void // LoadQAConf() // { // // normpat.push_back( // // if no normpats, set nNorm.cub and nAnatomical.cub // } void vbqa_help() { printf("\nVoxBo vbqa (v%s)\n",vbversion.c_str()); printf("summary:\n"); printf(" vbqa produces voxbo quality assurance reports in html format. Point\n"); printf(" your web browser at HOME/.voxbo/reports/index.html to review your reports.\n"); printf("usage:\n"); printf(" vbqa [flags]
...\n"); printf("flags:\n"); printf(" -l go so many levels deep (default 100)\n"); printf(" -n use for the report generated\n"); printf(" -d [...] delete one or more reports\n"); printf("\n"); } voxbo-1.8.5~svn1246/qtglm/000077500000000000000000000000001153177201300152505ustar00rootroot00000000000000voxbo-1.8.5~svn1246/qtglm/Makefile000066400000000000000000000122301153177201300167060ustar00rootroot00000000000000 # Makefile for building: glm, gdw, vecview include ../make_stuff.txt -include ../make_vars.txt CXXFLAGS += -DQT3_SUPPORT $(QTINCDIRS) -I../utils PERM_EX=../stand_alone/perm.o ../stand_alone/utils.o ../stand_alone/time_series_avg.o GDW_EX=../utils/fitOneOverF.o # define object variables GLM_OBJECTS=glm_main.o glm.o gdw.o gheaderinfo.o block.o paired.o glm_tab3.o GLM_OBJMOC = moc_glm.o moc_gdw.o moc_block.o moc_paired.o moc_glm_tab3.o GDW_OBJECTS=gdw_main.o gdw.o gheaderinfo.o block.o paired.o GDW_OBJMOC = moc_gdw.o moc_block.o moc_paired.o VECVIEW_OBJECTS = vecview.o VECVIEW_OBJMOC = moc_vecview.o TCALC_OBJECTS= vbtcalc.o PERMGEN_OBJECTS= vbpermgen.o # miscellaneous flags and such LIBS=$(LDFLAGS) $(LIBDIRS) $(QTLIBDIRS) $(QTLIBS) -lz -lvbglm -lvbprefs -lvbio -lvbutil -lz $(GSL_LIBS) $(DLLIB) ALLBINS= glm gdw vecview vbpermgen vbtcalc OSXTRA=glm.app glm.dmg gdw.app gdw.dmg vecview.app vecview.dmg vbpermgen.app vbpermgen.dmg vbtcalc.app vbtcalc.dmg ifeq ($(ARCH),DARWIN) ALLBINS+=$(OSXTRA) endif ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else ifeq ($(VB_TARGET),spm) BINS=$(ALLBINS) else BINS= endif ifdef VB_NOX BINS= endif # the main targets all: $(BINS) install: $(BINS) ifdef BINS cp -rf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -rf $(CLEANME) $(ALLBINS) $(VBLIBS): +make -C ../lib $@ %.hlp.h : %.hlp $(VBRC) $@ -myhelp $< %.moc.h : %.h $(MOC) $< -o $@ glm: $(GLM_OBJECTS) $(GLM_OBJMOC) $(VBLIBS) $(GDW_EX) $(CXX) -o glm $(GLM_OBJECTS) $(GLM_OBJMOC) $(GDW_EX) $(LIBS) glm.app: glm mkdir -p glm.app/Contents/MacOS echo "APPL????" > glm.app/Contents/PkgInfo cp glm glm.app/Contents/MacOS glm.dmg: glm glm.app/Contents/PkgInfo @rm -f glm.dmg hdiutil create -fs HFS+ -volname glm -srcfolder glm.app glm.dmg gdw: $(GDW_OBJECTS) $(GDW_OBJMOC) $(VBLIBS) $(GDW_EX) $(CXX) -o gdw $(GDW_OBJECTS) $(GDW_OBJMOC) $(GDW_EX) $(LIBS) gdw.app: gdw mkdir -p gdw.app/Contents/MacOS echo "APPL????" > gdw.app/Contents/PkgInfo cp gdw gdw.app/Contents/MacOS gdw.dmg: gdw gdw.app/Contents/PkgInfo @rm -f gdw.dmg hdiutil create -fs HFS+ -volname gdw -srcfolder gdw.app gdw.dmg vecview: $(VECVIEW_OBJECTS) $(VECVIEW_OBJMOC) $(VBLIBS) $(GDW_EX) $(CXX) -o vecview $(VECVIEW_OBJECTS) $(VECVIEW_OBJMOC) $(GDW_EX) $(LIBS) vecview.app: vecview mkdir -p vecview.app/Contents/MacOS echo "APPL????" > vecview.app/Contents/PkgInfo cp vecview vecview.app/Contents/MacOS vecview.dmg: vecview vecview.app/Contents/PkgInfo @rm -f vecview.dmg hdiutil create -fs HFS+ -volname vecview -srcfolder vecview.app vecview.dmg # thresholdcalculator executable vbtcalc: $(TCALC_OBJECTS) $(VBLIBS) $(CXX) -o vbtcalc $(TCALC_OBJECTS) $(LIBS) vbtcalc.app: vbtcalc mkdir -p vbtcalc.app/Contents/MacOS echo "APPL????" > vbtcalc.app/Contents/PkgInfo cp vbtcalc vbtcalc.app/Contents/MacOS vbtcalc.dmg: vbtcalc vbtcalc.app/Contents/PkgInfo @rm -f vbtcalc.dmg hdiutil create -fs HFS+ -volname vbtcalc -srcfolder vbtcalc.app vbtcalc.dmg # vbpermgen executable vbpermgen: $(PERMGEN_OBJECTS) $(PERM_EX) $(VBLIBS) $(CXX) -o vbpermgen $(PERMGEN_OBJECTS) $(PERM_EX) $(LIBS) vbpermgen.app: vbpermgen mkdir -p vbpermgen.app/Contents/MacOS echo "APPL????" > vbpermgen.app/Contents/PkgInfo cp vbpermgen vbpermgen.app/Contents/MacOS vbpermgen.dmg: vbpermgen vbpermgen.app/Contents/PkgInfo @rm -f vbpermgen.dmg hdiutil create -fs HFS+ -volname vbpermgen -srcfolder vbpermgen.app vbpermgen.dmg # DEPENDENCIES ELSEWHERE $(GDW_EX) $(PERM_EX): +make -C $(@D) $(@F) # the local objects glm_main.o: glm_main.cpp glm.h glm.hlp.h $(CXX) -c $(CXXFLAGS) glm_main.cpp gdw_main.o: gdw_main.cpp gdw.h gdw.hlp.h $(CXX) -c $(CXXFLAGS) gdw_main.cpp glm.o: glm.cpp glm.h gdw.h $(CXX) -c $(CXXFLAGS) glm.cpp moc_glm.o: moc_glm.cpp glm.h $(CXX) -c $(CXXFLAGS) moc_glm.cpp moc_glm.cpp: $(MOC) glm.h $(MOC) glm.h -o moc_glm.cpp gdw.o: gdw.cpp gdw.h ../vbwidgets/plotscreen.h gheaderinfo.h block.h paired.h $(CXX) -c $(CXXFLAGS) gdw.cpp moc_gdw.o: moc_gdw.cpp gdw.h $(CXX) -c $(CXXFLAGS) moc_gdw.cpp moc_gdw.cpp: $(MOC) gdw.h $(MOC) gdw.h -o moc_gdw.cpp block.o: block.cpp block.h $(CXX) -c $(CXXFLAGS) block.cpp moc_block.o: moc_block.cpp block.h $(CXX) -c $(CXXFLAGS) moc_block.cpp moc_block.cpp: $(MOC) block.h $(MOC) block.h -o moc_block.cpp paired.o: paired.cpp paired.h $(CXX) -c $(CXXFLAGS) paired.cpp moc_paired.o: moc_paired.cpp paired.h $(CXX) -c $(CXXFLAGS) moc_paired.cpp moc_paired.cpp: $(MOC) paired.h $(MOC) paired.h -o moc_paired.cpp glm_tab3.o: glm_tab3.cpp glm_tab3.h $(CXX) -c $(CXXFLAGS) glm_tab3.cpp moc_glm_tab3.o: moc_glm_tab3.cpp glm_tab3.h $(CXX) -c $(CXXFLAGS) moc_glm_tab3.cpp moc_glm_tab3.cpp: $(MOC) glm_tab3.h $(MOC) glm_tab3.h -o moc_glm_tab3.cpp gheaderinfo.o: gheaderinfo.cpp gheaderinfo.h $(CXX) -c $(CXXFLAGS) gheaderinfo.cpp vecview.o: vecview.cpp vecview.h vecview.hlp.h ../vbwidgets/plotscreen.h $(CXX) -c $(CXXFLAGS) vecview.cpp moc_vecview.o: moc_vecview.cpp vecview.h $(CXX) -c $(CXXFLAGS) moc_vecview.cpp moc_vecview.cpp: $(MOC) vecview.h vecview.cpp $(MOC) vecview.h -o moc_vecview.cpp vbtcalc.o: vbtcalc.cpp vbtcalc.hlp.h $(CXX) -c $(CXXFLAGS) vbtcalc.cpp vbpermgen.o: vbpermgen.cpp vbpermgen.moc.h vbpermgen.hlp.h $(CXX) -c $(CXXFLAGS) vbpermgen.cpp voxbo-1.8.5~svn1246/qtglm/block.cpp000066400000000000000000000155471153177201300170620ustar00rootroot00000000000000/**************************************************************************** ** Form implementation generated from reading ui file 'block.ui' ** ** Created: Tue Jan 23 11:56:53 2007 ** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.4 edited Nov 24 2003 $) ** ** WARNING! All changes made in this file will be lost! ****************************************************************************/ #include "block.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Constructs a BlockDesign as a child of 'parent', with the * name 'name' and widget flags set to 'f'. * */ BlockDesign::BlockDesign( QWidget* parent, const char* name, Qt::WFlags fl ) : Q3MainWindow( parent, name, fl ) { (void)statusBar(); if ( !name ) setName( "BlockDesign" ); setCentralWidget( new QWidget( this, "qt_central_widget" ) ); cancelButton = new QPushButton( centralWidget(), "cancelButton" ); cancelButton->setGeometry( QRect( 180, 300, 70, 31 ) ); textLabel5 = new QLabel( centralWidget(), "textLabel5" ); textLabel5->setGeometry( QRect( 10, 260, 140, 20 ) ); QFont textLabel5_font( textLabel5->font() ); textLabel5_font.setPointSize( 11 ); textLabel5->setFont( textLabel5_font ); textLabel5->setAlignment( int( Qt::AlignCenter ) ); offEditor = new QLineEdit( centralWidget(), "offEditor" ); offEditor->setGeometry( QRect( 150, 220, 170, 25 ) ); QFont offEditor_font( offEditor->font() ); offEditor_font.setPointSize( 12 ); offEditor->setFont( offEditor_font ); orderGroup = new Q3ButtonGroup( centralWidget(), "orderGroup" ); orderGroup->setGeometry( QRect( 20, 90, 130, 80 ) ); QFont orderGroup_font( orderGroup->font() ); orderGroup_font.setPointSize( 9 ); orderGroup->setFont( orderGroup_font ); orderGroup->setLineWidth( 1 ); orderGroup->setAlignment( int( Qt::AlignHCenter ) ); onFirst = new QRadioButton( orderGroup, "onFirst" ); onFirst->setGeometry( QRect( 10, 20, 80, 20 ) ); QFont onFirst_font( onFirst->font() ); onFirst_font.setPointSize( 11 ); onFirst->setFont( onFirst_font ); onFirst->setChecked( TRUE ); offFirst = new QRadioButton( orderGroup, "offFirst" ); offFirst->setGeometry( QRect( 10, 50, 70, 20 ) ); QFont offFirst_font( offFirst->font() ); offFirst_font.setPointSize( 11 ); offFirst->setFont( offFirst_font ); textLabel1 = new QLabel( centralWidget(), "textLabel1" ); textLabel1->setGeometry( QRect( 110, 10, 130, 30 ) ); QFont textLabel1_font( textLabel1->font() ); textLabel1_font.setPointSize( 12 ); textLabel1_font.setBold( TRUE ); textLabel1_font.setUnderline( TRUE ); textLabel1->setFont( textLabel1_font ); unitGroup = new Q3ButtonGroup( centralWidget(), "unitGroup" ); unitGroup->setGeometry( QRect( 160, 90, 160, 80 ) ); unitGroup->setLineWidth( 1 ); unitGroup->setAlignment( int( Qt::AlignHCenter ) ); ms = new QRadioButton( unitGroup, "ms" ); ms->setGeometry( QRect( 10, 50, 40, 20 ) ); QFont ms_font( ms->font() ); ms_font.setPointSize( 11 ); ms->setFont( ms_font ); TR = new QRadioButton( unitGroup, "TR" ); TR->setGeometry( QRect( 10, 20, 50, 20 ) ); QFont TR_font( TR->font() ); TR_font.setPointSize( 11 ); TR->setFont( TR_font ); TR->setChecked( TRUE ); numberEditor = new QLineEdit( centralWidget(), "numberEditor" ); numberEditor->setGeometry( QRect( 150, 260, 170, 25 ) ); QFont numberEditor_font( numberEditor->font() ); numberEditor_font.setPointSize( 12 ); numberEditor->setFont( numberEditor_font ); okButton = new QPushButton( centralWidget(), "okButton" ); okButton->setGeometry( QRect( 70, 300, 80, 30 ) ); textLabel3 = new QLabel( centralWidget(), "textLabel3" ); textLabel3->setGeometry( QRect( 20, 180, 120, 20 ) ); QFont textLabel3_font( textLabel3->font() ); textLabel3_font.setPointSize( 11 ); textLabel3->setFont( textLabel3_font ); textLabel3->setAlignment( int( Qt::AlignVCenter | Qt::AlignRight ) ); textLabel4 = new QLabel( centralWidget(), "textLabel4" ); textLabel4->setGeometry( QRect( 20, 220, 120, 20 ) ); QFont textLabel4_font( textLabel4->font() ); textLabel4_font.setPointSize( 11 ); textLabel4->setFont( textLabel4_font ); textLabel4->setAlignment( int( Qt::AlignVCenter | Qt::AlignLeft ) ); textLabel2 = new QLabel( centralWidget(), "textLabel2" ); textLabel2->setGeometry( QRect( 20, 50, 90, 20 ) ); QFont textLabel2_font( textLabel2->font() ); textLabel2_font.setPointSize( 11 ); textLabel2->setFont( textLabel2_font ); textLabel2->setAlignment( int( Qt::AlignVCenter | Qt::AlignLeft ) ); nameEditor = new QLineEdit( centralWidget(), "nameEditor" ); nameEditor->setGeometry( QRect( 105, 50, 210, 25 ) ); QFont nameEditor_font( nameEditor->font() ); nameEditor_font.setPointSize( 12 ); nameEditor->setFont( nameEditor_font ); onEditor = new QLineEdit( centralWidget(), "onEditor" ); onEditor->setGeometry( QRect( 150, 180, 170, 25 ) ); QFont onEditor_font( onEditor->font() ); onEditor_font.setPointSize( 12 ); onEditor->setFont( onEditor_font ); onEditor->setCursorPosition( 0 ); // toolbars languageChange(); resize( QSize(341, 359).expandedTo(minimumSizeHint()) ); // setAttribute(Qt::WState_Polished,0); // tab order setTabOrder( nameEditor, onFirst ); setTabOrder( onFirst, offFirst ); setTabOrder( offFirst, TR ); setTabOrder( TR, ms ); setTabOrder( ms, onEditor ); setTabOrder( onEditor, offEditor ); setTabOrder( offEditor, numberEditor ); setTabOrder( numberEditor, okButton ); setTabOrder( okButton, cancelButton ); } /* * Destroys the object and frees any allocated resources */ BlockDesign::~BlockDesign() { // no need to delete child widgets, Qt does it all for us } /* * Sets the strings of the subwidgets using the current * language. */ void BlockDesign::languageChange() { setCaption( tr( "Block Design" ) ); cancelButton->setText( tr( "Cancel" ) ); textLabel5->setText( tr( "Number of Blocks:" ) ); orderGroup->setTitle( tr( "Set Order of Blocks" ) ); onFirst->setText( tr( "On First" ) ); offFirst->setText( tr( "Off First" ) ); textLabel1->setText( tr( "Block Design" ) ); unitGroup->setTitle( tr( "Set Unit of Block Length" ) ); ms->setText( tr( "ms" ) ); TR->setText( tr( "TR" ) ); okButton->setText( tr( "OK" ) ); textLabel3->setText( tr( "Block Length (On):" ) ); textLabel4->setText( tr( "Block Length (Off):" ) ); textLabel2->setText( tr( "Effect Name:" ) ); onEditor->setInputMask( QString::null ); } voxbo-1.8.5~svn1246/qtglm/block.h000066400000000000000000000031261153177201300165150ustar00rootroot00000000000000/**************************************************************************** ** Form interface generated from reading ui file 'block.ui' ** ** Created: Tue Jan 23 11:56:53 2007 ** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.4 edited Nov 24 2003 $) ** ** WARNING! All changes made in this file will be lost! ****************************************************************************/ #ifndef BLOCKDESIGN_H #define BLOCKDESIGN_H #include #include //Added by qt3to4: #include #include #include #include #include #include class Q3VBoxLayout; class Q3HBoxLayout; class Q3GridLayout; class QSpacerItem; class QAction; class Q3ActionGroup; class Q3ToolBar; class Q3PopupMenu; class QPushButton; class QLabel; class QLineEdit; class Q3ButtonGroup; class QRadioButton; class BlockDesign : public Q3MainWindow { Q_OBJECT public: BlockDesign( QWidget* parent = 0, const char* name = 0, Qt::WFlags fl = Qt::WType_TopLevel ); ~BlockDesign(); QPushButton* cancelButton; QLabel* textLabel5; QLineEdit* offEditor; Q3ButtonGroup* orderGroup; QRadioButton* onFirst; QRadioButton* offFirst; QLabel* textLabel1; Q3ButtonGroup* unitGroup; QRadioButton* ms; QRadioButton* TR; QLineEdit* numberEditor; QPushButton* okButton; QLabel* textLabel3; QLabel* textLabel4; QLabel* textLabel2; QLineEdit* nameEditor; QLineEdit* onEditor; protected: protected slots: virtual void languageChange(); }; #endif // BLOCKDESIGN_H voxbo-1.8.5~svn1246/qtglm/block.ui000066400000000000000000000263371153177201300167140ustar00rootroot00000000000000 BlockDesign BlockDesign 0 0 341 359 Block Design cancelButton 180 300 70 31 Cancel textLabel5 10 260 140 20 11 Number of Blocks: AlignCenter offEditor 150 220 170 25 12 orderGroup 20 90 130 80 9 1 Set Order of Blocks AlignHCenter onFirst 10 20 80 20 11 On First true offFirst 10 50 70 20 11 Off First textLabel1 110 10 130 30 12 1 1 Block Design unitGroup 160 90 160 80 1 Set Unit of Block Length AlignHCenter ms 10 50 40 20 11 ms TR 10 20 50 20 11 TR true numberEditor 150 260 170 25 12 okButton 70 300 80 30 OK textLabel3 20 180 120 20 11 Block Length (On): AlignVCenter|AlignRight textLabel4 20 220 120 20 11 Block Length (Off): AlignVCenter|AlignLeft textLabel2 20 50 90 20 11 Effect Name: AlignVCenter|AlignLeft nameEditor 105 50 210 25 12 onEditor 150 180 170 25 12 0 nameEditor onFirst offFirst TR ms onEditor offEditor numberEditor okButton cancelButton voxbo-1.8.5~svn1246/qtglm/gdw.cpp000066400000000000000000007050321153177201300165440ustar00rootroot00000000000000 // gdw.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu #include #include #include #include #include using namespace std; #include "gdw.h" #include "fileopen.xpm" #include "filesave.xpm" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern VBPrefs vbp; /* Gdw constructor */ Gdw::Gdw(int inputNumberOfPoints, int inputTR, int inputMode, QString inputFileName) : Q3MainWindow(0, "G Design Workshop", Qt::WDestructiveClose) { filterPath = getFilterPath(); init(inputNumberOfPoints, inputTR); initGrpCount(); setMode(inputMode); setupMenu(); setupWidgets(); setCaption("G Design Workshop: New Design"); // In combo mode, G matrix filename is passed from glm interface if (mode == COMBO) { gFileName = inputFileName; setCaption("G Design Workshop: " + gFileName + ".G"); setStatusText(); return; } // if the input filename is null if (inputFileName.isEmpty()) { gFileName = QString::null; setStatusText(); return; } // If it is SINGLE mode and input filename is not null, read it string tmpString((const char *)inputFileName); if (!chkFileStat(tmpString.c_str(), true)) { setStatusText(); return; } VB_Vector testVec; // If it's a valid ref file, load it as condition function if (testVec.ReadFile(tmpString) == 0) { loadCondFunct(inputFileName); gFileName = QString::null; } // If it not ref file, assume it is G matrix file else readG(tmpString); setStatusText(); } /* Initialize global variables */ void Gdw::init(int inputNumberOfPoints, int inputTR) { tesNum = 0; xMagnification = 1; totalReps = inputNumberOfPoints; TR = inputTR; tmpResolve = 100; psFlag = fitFlag = false; gUpdateFlag = false; condRef = QString::null; /* Make sure vb_vector pointers are initialized to be zero. * If not, destructor will generate segv */ timeVector = 0; fftVector = 0; noiseVec = 0; condVector = 0; itemCounter = 0; d_index = -1; interceptID.clear(); } /* Deconstructor: delete some vb_vector pointers */ Gdw::~Gdw() { if (timeVector) delete timeVector; if (fftVector) delete fftVector; if (noiseVec) delete noiseVec; if (condVector) delete condVector; if (covList.size()) covList.clear(); } /* This function will copy an input covariate list to covList. * It is called when "edit" button is clicked on glm tab3 interface */ void Gdw::cpGlmList(vector inputList) { if (covList.size()) covList.clear(); int covNum = inputList.size(); for (int i = 0; i < covNum; i++) { VB_Vector *tmpVec = new VB_Vector(inputList[i]); covList.push_back(tmpVec); } } /* This function sounds like it is doing the same thing as the previous one, * but it is written to transfer tmpResolve from glm to gdw. */ void Gdw::cpTmpResolve(int inputVal) { tmpResolve = inputVal; } /* This function sets a certain condition function in gdw and sets the key list view */ void Gdw::cpGlmCondFxn(QString inputFile, tokenlist inputKeys) { condRef = inputFile; condVector = new VB_Vector(inputFile.ascii()); condKey = tokenlist(inputKeys); if (keyList->count()) keyList->clear(); for (size_t m = 0; m < condKey.size(); m++) { QString keyString = QString(condKey(m)); keyList->insertItem(keyString); } keyList->setCurrentItem(0); } /* Set up the menu */ void Gdw::setupMenu() { /* A toolbar which has three buttons so far: fileOpen, fileSave, editUndo */ Q3Action *fileOpenAction; fileOpenAction = new Q3Action("Open File", QPixmap(fileopen), "&Open", Qt::CTRL+Qt::Key_O, this, "open"); connect(fileOpenAction, SIGNAL(activated()) , this, SLOT(fileOpen())); fileSaveAction = new Q3Action("Save File", QPixmap(filesave), "&Save", Qt::CTRL+Qt::Key_S, this, "save"); fileSaveAction->setEnabled(false); connect(fileSaveAction, SIGNAL(activated()) , this, SLOT(fileSave())); Q3ToolBar *fileTools = new Q3ToolBar(this, "file operations"); fileTools->setLabel("File Operations"); fileOpenAction->addTo(fileTools); fileSaveAction->addTo(fileTools); Q3ToolBar * editTools = new Q3ToolBar(this, "edit operations"); editTools->setLabel("Edit Operations"); /* Create the menu of "File", $QTDIR/lib/doc/examples/textedit/ is a good example on * using QAction to generate menubar, here we use a compact form instead */ fileMenu = new Q3PopupMenu(this); menuBar()->insertItem(tr("&File"), fileMenu); /* "File" includes the following functionalities */ fileOpenAction->addTo(fileMenu); fileSaveAction->addTo(fileMenu); fileMenu->insertItem("Save &As", this, SLOT(fileSaveAs())); fileMenu->insertSeparator(); fileMenu->insertItem("&Done", this, SLOT(close()), Qt::CTRL + Qt::Key_Q); /* Create the menu of "Edit" */ Q3PopupMenu *edit = new Q3PopupMenu(this); menuBar()->insertItem("&Edit", edit); /* The submenu of "Add Interest" includes 7 functionalities */ Q3PopupMenu *iMenu = new Q3PopupMenu(this); edit->insertItem("Add Interest", iMenu); iMenu->insertItem("Contrasts", this, SLOT(add_I_Contrasts())); iMenu->insertItem("Diagonal set", this, SLOT(add_I_DS())); iMenu->insertItem("Covariate(s) from file", this, SLOT(add_I_Single())); iMenu->insertItem("Trial effects", this, SLOT(add_I_Trial())); iMenu->insertItem("Var length trial effects", this, SLOT(add_I_varTrial())); /* The submenu of "Add No interest" includes 11 functionalities */ Q3PopupMenu *nMenu = new Q3PopupMenu(this); edit->insertItem("Add No interest", nMenu); nMenu->insertItem("Contrasts", this, SLOT(add_N_Contrasts())); nMenu->insertItem("Diagonal set", this, SLOT(add_N_DS())); nMenu->insertItem("Covariate(s) from file", this, SLOT(add_N_Single())); nMenu->insertItem("Trial effects", this, SLOT(add_N_Trial())); nMenu->insertItem("Var length trial effects", this, SLOT(add_N_varTrial())); nMenu->insertSeparator(); nMenu->insertItem("Global signals", this, SLOT(addGlobal())); nMenu->insertItem("Intercept", this, SLOT(slot_addIntercept())); nMenu->insertItem("Movement parameters", this, SLOT(addMovement())); nMenu->insertItem("Scan effects", this, SLOT(addScanfx())); nMenu->insertItem("Spike", this, SLOT(addSpike())); nMenu->insertItem("Txt file as multi-covariates", this, SLOT(addTxt())); /* "Modify Selection(s)" includes 16 functionalities */ Q3PopupMenu *modMenu = new Q3PopupMenu(this); edit->insertItem("Modify Selection(s)", modMenu); modMenu->insertItem("Duplicate", this, SLOT(duplicate())); modMenu->insertItem("Delete", this, SLOT(delCov()), Qt::CTRL + Qt::Key_D); modMenu->insertSeparator(); modMenu->insertItem("Convert to delta", this, SLOT(modC2D())); modMenu->insertItem("Convolve", this, SLOT(modConv())); modMenu->insertItem("Mean center", this, SLOT(modMean())); modMenu->insertItem("Mean center non-zero", this, SLOT(meanNonZero())); modMenu->insertItem("Multiply by covar", this, SLOT(modMult())); modMenu->insertItem("Orthogonalize", this, SLOT(modOrth())); modMenu->insertItem("Time shift", this, SLOT(modTS())); modMenu->insertItem("Unit excursion", this, SLOT(UnitExcurs())); modMenu->insertItem("Unit variance", this, SLOT(unitVar())); modMenu->insertSeparator(); modMenu->insertItem("Derivative(s)", this, SLOT(modDeriv())); modMenu->insertItem("Eigenvector set", this, SLOT(modES())); modMenu->insertItem("Exponential", this, SLOT(modExpn())); modMenu->insertItem("Finite impulse response", this, SLOT(modFIR())); modMenu->insertItem("Fourier set", this, SLOT(modFS())); // add canned models Q3PopupMenu *modelMenu = new Q3PopupMenu(this); edit->insertItem("Add Canned Models", modelMenu); modelMenu->insertItem("Block Design", this, SLOT(showBlockUI())); modelMenu->insertItem("Paired Design", this, SLOT(showPairUI())); // "Select All" edit->insertItem("Select All", this, SLOT(selectAll())); /* Create the menu of "Evaluate" */ Q3PopupMenu *evaluate = new Q3PopupMenu(this); menuBar()->insertItem("E&valuate", evaluate); /* "Evaluate" includes 6 functionalities */ evaluate->insertItem("Efficiency", this, SLOT(efficiency())); evaluate->insertItem("Mean and SD", this, SLOT(meanSD())); evaluate->insertItem("Noise spectra", this, SLOT(evalNoise())); evaluate->insertSeparator(); evaluate->insertItem("Colinearity with all [ I/N/K ]", this, SLOT(colAll())); evaluate->insertItem("Colinearity with interest [ I ]", this, SLOT(col_I())); evaluate->insertItem("Colinearity with non-interest [ N/K ]", this, SLOT(col_N())); evaluate->insertSeparator(); evaluate->insertItem("Linear dependence of all [ I/N/K ]", this, SLOT(a_LD())); evaluate->insertItem("Linear dependence of all interest [ I ]", this, SLOT(i_LD())); evaluate->insertItem("Linear dependence of all non-interest [ N/K ]", this, SLOT(nk_LD())); evaluate->insertItem("Linear dependence of selected covariates", this, SLOT(sel_LD())); /* Create the menu of "Tools" */ Q3PopupMenu *tools = new Q3PopupMenu(this); menuBar()->insertItem("&Tools", tools); /* "Tools" includes four functionalities */ tools->insertItem("Load condition function", this, SLOT(loadCondFunct())); tools->insertItem("Load condition labels", this, SLOT(loadCondLabel())); tools->insertItem("Save condition labels", this, SLOT(saveCondLabel())); tools->insertSeparator(); tools->insertItem("Reset upsampling rate", this, SLOT(setUpsampling())); tools->insertItem("Save covariate as ref", this, SLOT(saveCov2Ref())); } /* Set up the widgets on the interface */ void Gdw::setupWidgets() { /********************************************************************************* * The menu bar setup is done. The next step is to set up the graphical display, * the condition key editor, dependent variables editor and another graphical * display at the bottom *********************************************************************************/ /* tab3_main is a QVBox which includes all three parts */ Q3VBox *tab3_main = new Q3VBox(this); tab3_main->setMargin(10); tab3_main->setSpacing(2); /* Display a blank screen when first launched */ upperWindow = new PlotScreen(tab3_main); upperWindow->setUpdatesEnabled(true); if (TR && tmpResolve) upperWindow->setRatio(TR / tmpResolve); QObject::connect(this, SIGNAL(newCovLoaded(VB_Vector *)), this, SLOT(upperWindowUpdate(VB_Vector *))); upperWindow->setFocus(); /* Add "magnification" and "position" slide bars with captions and a "center" button in the middle */ Q3HBox *widgetBox = new Q3HBox(tab3_main); widgetBox->setSpacing(20); QLabel *magLab = new QLabel("Magnification", widgetBox); magLab->setAlignment(Qt::AlignHCenter); /*********************************************************************** * Horizontal magnification slider bar, with the tickmarks on the above * Maximum: 10, Minimum: 1, step: 1, default position: 1 * May need to change later **********************************************************************/ magSlider = new QSlider(1, 10, 1, 1, Qt::Horizontal, widgetBox); magSlider->setTickmarks( QSlider::Below ); QObject::connect(magSlider, SIGNAL(valueChanged(int)), upperWindow, SLOT(setXMag(int))); QObject::connect(upperWindow, SIGNAL(xMagChanged(int)), magSlider, SLOT(setValue(int))); QPushButton *graphCenter = new QPushButton("Center", widgetBox); // "center" pushbutton QObject::connect(graphCenter, SIGNAL(clicked()), upperWindow, SLOT(centerX())); /* In the middle is a QHBox: two lineEdit box on the left side, two radio button groups on the right */ Q3HBox *middle = new Q3HBox(tab3_main); Q3VBox *paraSetBox = new Q3VBox(middle); /* The HBOx on top includes label and a line editor for TR input */ Q3HBox *TREditBox = new Q3HBox(paraSetBox); (void) new QLabel("Time of Repetition: ", TREditBox); if (TR > 0) trString = new QLabel(QString::number(TR), TREditBox); else trString = new QLabel("Not set", TREditBox); QPushButton *trButton = new QPushButton("Edit", TREditBox); if (mode == COMBO) trButton->setDisabled(true); QObject::connect(trButton, SIGNAL(clicked()), this, SLOT(changeTR())); (void) new QLabel("", TREditBox); // For alignment purpose /* Show upsampling rate value */ Q3HBox *samplingBox = new Q3HBox(paraSetBox); (void) new QLabel("Upsampling Rate: ", samplingBox); if (tmpResolve > 0) samplingStr = new QLabel(QString::number(tmpResolve), samplingBox); else samplingStr = new QLabel("Not set", samplingBox); QPushButton *upsButton = new QPushButton("Edit", samplingBox); QObject::connect(upsButton, SIGNAL(clicked()), this, SLOT(setUpsampling())); (void) new QLabel("", samplingBox); // For alignment purpose /* The next HBox includes label and a line editor for number of time points */ Q3HBox *numberEditBox = new Q3HBox(paraSetBox); (void) new QLabel("Number of Points: ", numberEditBox); if (totalReps > 0) numberString = new QLabel(QString::number(totalReps), numberEditBox); else numberString = new QLabel("Not set", numberEditBox); QPushButton *numberButton = new QPushButton("Edit", numberEditBox); if (mode == COMBO) numberButton->setDisabled(true); QObject::connect(numberButton, SIGNAL(clicked()), this, SLOT(changeNumberPoints())); (void) new QLabel("", numberEditBox); // For alignment purpose /* Two groups of radio buttons: Time plot vs. Freq plot and Secs(Hz) vs. TRs(Freq) */ Q3VBox *radioButtons = new Q3VBox(middle); Q3HButtonGroup *radioButton1 = new Q3HButtonGroup(radioButtons); radioButton1->setLineWidth(1); // hide this button group's border timePlotButt = new QRadioButton("Time Plot", radioButton1); // Time Plot timePlotButt->setChecked(true); // Default is "Time Plot" QRadioButton *freqPlotButt = new QRadioButton("Freq Plot", radioButton1); // Freq Plot fftFlag = 0; // default plot is in time domain secFlag = 1; // default X axis unit is second/Hz QObject::connect(timePlotButt, SIGNAL(clicked()), this, SLOT(timePlotClicked())); QObject::connect(freqPlotButt, SIGNAL(clicked()), this, SLOT(freqPlotClicked())); (void) new QLabel("", radioButtons); // for alignment purpose only Q3HButtonGroup *radioButton2 = new Q3HButtonGroup(radioButtons); radioButton2->setLineWidth(1); // hide this button group's border secButt = new QRadioButton("Secs", radioButton2); // "Secs" radio button secButt->setChecked(true); // Default is "Secs" QRadioButton *TRButt = new QRadioButton("TRs (Freq)", radioButton2); // "TRs" radio button QObject::connect(secButt, SIGNAL(clicked()), this, SLOT(secClicked())); QObject::connect(TRButt, SIGNAL(clicked()), this, SLOT(TRClicked())); /* Condition keys and variables editor */ Q3HBox *middleBox = new Q3HBox(tab3_main); middleBox->setSpacing(20); /* A QVGroupBox called "keyGroup", which includes a listbox, a label and a line editor */ Q3VGroupBox *keyGroup = new Q3VGroupBox("Condition Keys", middleBox); keyGroup->setAlignment(Qt::AlignHCenter); // caption in the middle keyList = new Q3ListBox(keyGroup); // key listbox /* Another HBox which includes label and a line editor */ Q3HBox *keyEditorBox = new Q3HBox(keyGroup); (void) new QLabel("Label: ", keyEditorBox); keyEditor = new QLineEdit(keyEditorBox); QObject::connect(keyList, SIGNAL(highlighted(int)), this, SLOT(setKeyEditor(int))); QObject::connect(keyEditor, SIGNAL(textChanged(const QString &)), this, SLOT(setKeyText())); QObject::connect(keyEditor, SIGNAL(returnPressed()), this, SLOT(nextKey())); // Optional /* "Variables" is similar to condition keys, with three radio buttons at the bottom */ Q3VGroupBox *varGroup = new Q3VGroupBox("Variables", middleBox); varGroup->setAlignment(Qt::AlignHCenter); // Caption in the middle /* varListView replaces varList boxes */ varListView = new Q3ListView(varGroup); varListView->setSelectionMode(Q3ListView::Extended); varListView->addColumn("Name"); varListView->addColumn("Type"); varListView->setColumnAlignment(1, Qt::AlignHCenter); varListView->addColumn("ID"); varListView->setColumnAlignment(2, Qt::AlignHCenter); varListView->addColumn("hidden", 0); varListView->setRootIsDecorated(true); // Disable automatic column sorting permanently varListView->setSortColumn(-1); QObject::connect(varListView, SIGNAL(itemRenamed(Q3ListViewItem *, int)), this, SLOT(renameUpdate())); QObject::connect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); QObject::connect(varListView, SIGNAL(doubleClicked(Q3ListViewItem *, const QPoint &, int)), this, SLOT(dbClick(Q3ListViewItem *))); // right click signal/slot pair in varListView QObject::connect(varListView, SIGNAL(rightButtonPressed(Q3ListViewItem *, const QPoint &, int)), this, SLOT(rightClick())); Q3HBox *typeBox = new Q3HBox(varGroup); (void) new QLabel("Change Variable Type: ", typeBox); typeCombo = new QComboBox(typeBox); typeCombo->insertItem("I: Interest"); typeCombo->insertItem("N: No Interest"); typeCombo->insertItem("K: Keep No Interest"); typeCombo->insertItem("D: Dependent"); // When covariates selected have different types, a blank item will be shown typeCombo->insertItem("Reserved"); QObject::connect(typeCombo, SIGNAL(activated(int)), this, SLOT(setVarType(int))); meanAll = new QCheckBox("Mean center all but intercept before saving", varGroup); meanAll->setChecked(true); setCentralWidget(tab3_main); } /* Right click on list view box */ void Gdw::rightClick() { Q3PopupMenu *rightMenu = new Q3PopupMenu(this); Q_CHECK_PTR(rightMenu); rightMenu->insertItem("Select all", this, SLOT(selectAll())); rightMenu->insertItem("Duplicate", this, SLOT(duplicate())); rightMenu->insertItem("Delete", this, SLOT(delCov())); rightMenu->insertSeparator(); rightMenu->insertItem("Convert to delta", this, SLOT(modC2D())); rightMenu->insertItem("Convolve", this, SLOT(modConv())); rightMenu->insertItem("Mean center", this, SLOT(modMean())); rightMenu->insertItem("Mean center non-zero", this, SLOT(meanNonZero())); rightMenu->insertItem("Multiply by covar", this, SLOT(modMult())); rightMenu->insertItem("Orthogonalize", this, SLOT(modOrth())); rightMenu->insertItem("Time shift", this, SLOT(modTS())); rightMenu->insertItem("Unit excursion", this, SLOT(UnitExcurs())); rightMenu->insertItem("Unit variance", this, SLOT(unitVar())); rightMenu->insertSeparator(); rightMenu->insertItem("Derivative(s)", this, SLOT(modDeriv())); rightMenu->insertItem("Eigenvector set", this, SLOT(modES())); rightMenu->insertItem("Exponential", this, SLOT(modExpn())); rightMenu->insertItem("Finite impulse response", this, SLOT(modFIR())); rightMenu->insertItem("Fourier set", this, SLOT(modFS())); rightMenu->insertSeparator(); Q3PopupMenu *evalMenu = new Q3PopupMenu(this); rightMenu->insertItem("Evaluate", evalMenu); evalMenu->insertItem("Efficiency", this, SLOT(efficiency())); evalMenu->insertItem("Mean and SD", this, SLOT(meanSD())); evalMenu->insertItem("Noise spectra", this, SLOT(evalNoise())); evalMenu->insertSeparator(); evalMenu->insertItem("Colinearity with all [ I/N/K ]", this, SLOT(colAll())); evalMenu->insertItem("Colinearity with interest [ I ]", this, SLOT(col_I())); evalMenu->insertItem("Colinearity with non-interest [ N/K ]", this, SLOT(col_N())); evalMenu->insertSeparator(); evalMenu->insertItem("Linear dependence of all [ I/N/K ]", this, SLOT(a_LD())); evalMenu->insertItem("Linear dependence of all interest [ I ]", this, SLOT(i_LD())); evalMenu->insertItem("Linear dependence of all non-interest [ N/K ]", this, SLOT(nk_LD())); evalMenu->insertItem("Linear dependence of selected covariates", this, SLOT(sel_LD())); rightMenu->exec(QCursor::pos()); delete rightMenu; } /* This function is to to set up the status bar at the bottom */ void Gdw::setStatusText() { if (covList.size()) statusBar()->message(QString("Number of covariate defined: %1").arg(covList.size())); else statusBar()->message(QString("Status: no covariates defined")); } /* reInit() will delete all previous setup and reset the whole interface. * It accepts an input condition function flag. * When this flag is true, condition function and keyList will also be reset. * When it's false, don't reset the condition function. * Note that TR isn't reset to be zero here.*/ void Gdw::reInit(bool condFlag) { covList.clear(); // reset the caption for SINGLE mode if (mode == SINGLE) { gFileName = QString::null; this->setCaption("G Design Workshop: New Design"); } tmpResolve = 100; timeVector = fftVector = 0; magSlider->setValue(1); // Magnification slider goes back to 1 timePlotButt->setChecked(true); // Check "time" radiobutton secButt->setChecked(true); // Check "Second" radiobutton psFlag = fitFlag = false; fftFlag = 0; // Default plot is in time domain secFlag = 1; // Default X axis unit is second/Hz d_index = -1; interceptID.clear(); initGrpCount(); varListView->clear(); statusBar()->message(QString("Status: no covariates defined")); typeCombo->setCurrentItem(4); // condFlag determines whether condition functions should be reset or not if (condFlag) { condRef = QString::null; condKey.clear(); condVector = 0; keyEditor->clear(); // Clear the condition key line editor keyList->clear(); } upperWindow->clear(); /* Because any text changed in keyEditor and varEditor boxes could set gUpdateFlag to 1, * the reinitialization of gUpdateFlag has to be put at the end. Otherwise gUpdateFlag * will be always 1 after calling reInit(). */ gUpdateFlag = false; } /* initGrpCount() resets all possible group counters to be 0 */ void Gdw::initGrpCount() { contrast_count = 0, diagonal_count = 0; trialfx_count = 0, var_len_count = 0; scanfx_count = 0, global_count = 0; mvpr_count = 0, spike_count = 0, txt_var_count = 0; } /* Set up the G Matrix update flag */ void Gdw::setGUpdateFlag(bool inputFlag) { gUpdateFlag = inputFlag; if (mode == SINGLE) fileSaveAction->setEnabled(inputFlag); } /* Set up the mode, 0 is single mode, 1 is COMBO mode with GLM interface */ void Gdw::setMode(int inputMode) { if (inputMode == 0) mode = SINGLE; else mode = COMBO; } /* Set up TES file list, simply passes the right side listbox in tab2 as an argument */ void Gdw::setTesList(Q3ListBox * inputList) { tesList = inputList; tesNum = tesList->count(); } /* Function to calculate the noise model using calcPS() and fitOneOverF functions */ void Gdw::calcNoiseModel() { VB_Vector *psVector = calcPS(); if (psFlag) { double var3min = (-1.0) / (totalReps * TR / 1000.0); VB_Vector *fitParams = new VB_Vector(8); fitParams = fitOneOverF(psVector, var3min, (double)TR); if (fitParams->getElement(0) == 1.0) { VB_Vector *noiseModel = new VB_Vector(totalReps); double var1 = fitParams->getElement(2); double var2 = fitParams->getElement(3); double var3 = fitParams->getElement(4); noiseModel = makeOneOverF(totalReps, var1, var2, var3, (double)TR); noiseVec = new VB_Vector(totalReps / 2 + 1); for (int i = 0; i < totalReps / 2 + 1; i++) noiseVec->setElement(i, noiseModel->getElement(i)); delete noiseModel; double minElement = noiseVec->getMinElement(); (*noiseVec)+=(minElement * (-2)); double maxElement = noiseVec->getMaxElement(); noiseVec->scaleInPlace(1.0 / maxElement); fitFlag = true; } else printf("Fitting not successful. No noise model defined.\n"); delete fitParams; } delete psVector; } /* calcPS() is a function written specially for COMBO mode. It will calculate the power * spectrum based on the tes files selected in step 2. * * First, this function will search *_PS.ref files in the same directory where tes files * are located. If any of the corresponding *_PS.ref files isn't found, psFlag will be set * false. No noise model will be drawn in freqency mode; * If PS files are available for each tes file and they have same number of elements, then * these PS vectors will be combined together and an average is calculated as the return value; * If all PS files are available but the number of elements is different, then the first PS * file will be returned. * * This implementation is copied from Geoff's IDL code (VoxBo_MatrixDesign.pro, lines 971-1010). */ VB_Vector * Gdw::calcPS() { if (TR <= 0 || totalReps <= 0 || tesList->count() <= 0) { QMessageBox::warning(0, "Warning!", "Please make sure TR, number of images and tes file(s)\ are set.

No noise model will be built."); return 0; } if (!chkPSstat()) { psFlag = false; return 0; } QString tesFileName = tesList->item(0)->text(); const char *psFileName; psFileName = tesFileName.replace(tesFileName.length() - 4, 4, "_PS.ref"); VB_Vector *initVector = new VB_Vector(psFileName); VB_Vector *psVector = new VB_Vector(psFileName); unsigned psLength = psVector->getLength(); int psNum = 1; for (int i = 1; i < tesNum; i++) { tesFileName = tesList->item(i)->text(); const char *psFileName; psFileName = tesFileName.replace(tesFileName.length() - 4, 4, "_PS.ref"); VB_Vector tmpVector(psFileName); if (psLength != tmpVector.getLength()) { psFlag = true; return initVector; } (*psVector)+=tmpVector; psNum++; } psFlag = true; psVector->scaleInPlace(1.0 / (double) psNum); return psVector; } /* Read tes file list and check if the corresponding power spectrum file exists or not. * Returns true if each tes file has its own ps file, returns false otherwise */ bool Gdw::chkPSstat() { QString tesFileName, psFile; for (int i = 0; i < tesNum; i++) { tesFileName = tesList->item(i)->text(); // If the TES file name is "my_tes_file.tes", the corresponding PS file should be: "my_tes_file_PS.ref" psFile = tesFileName.replace(tesFileName.length() - 4, 4, "_PS.ref"); if (!chkFileStat(psFile.ascii(), false)) return false; } return true; } /* chkGSstat() is copied from the one above. * It reads tes file list and check if the corresponding global signal file exists * or not. Returns true if each tes file has its own gs file. Otherwise return false. */ bool Gdw::chkGSstat() { QString tesFileName, gsFile; for (int i = 0; i < tesNum; i++) { tesFileName = tesList->item(i)->text(); // my_tes_file.tes -> my_tes_file_GS.ref gsFile = tesFileName.replace(tesFileName.length() - 4, 4, "_GS.ref"); if (!chkFileStat(gsFile.ascii(), true)) return false; } return true; } /* This function will return the upsampling rate */ int Gdw::getUpsampling() { return tmpResolve; } /* Set up TR value (in unit of millisecond) */ void Gdw::setTR(int inputTR) { TR = inputTR; } /* Set up total number of time points */ void Gdw::setTimePoints(int inputTimePoints) { totalReps = inputTimePoints; } /* changeTR() is slot to take care of new TR input. * reInit(false) is called here, which means TR is completely * independent with condition function information. */ void Gdw::changeTR() { bool ok; int newTR = QInputDialog::getInteger("Enter New TR", "Please enter the new TR", TR, 0, 2147483647, 1, &ok); if (ok && (newTR != TR) && (newTR % tmpResolve == 0)) { // "OK" clicked, and it's a different value if (covList.size() > 0 && gUpdateFlag == true) { switch(QMessageBox::warning(0, "Warning!", "You have typed in a new TR.\

Your previous GLM design will be aborted. Do you want to save it now?", \ "Yes", "No", "Cancel", 0, 2)) { case 0: fileSave(); reInit(false); TR = newTR; upperWindow->setRatio(TR / tmpResolve); trString->setText(QString::number(TR)); upperWindow->update(); break; case 1: reInit(false); TR = newTR; upperWindow->setRatio(TR / tmpResolve); trString->setText(QString::number(TR)); upperWindow->update(); break; case 2: break; // Nothing happens if "cancel" is clicked. } } else { reInit(false); TR = newTR; upperWindow->setRatio(TR / tmpResolve); trString->setText(QString::number(TR)); upperWindow->update(); } } else if (ok && TR == newTR) // "OK" clicked, but the TR isn't really changed QMessageBox::warning(0, "Warning", "Same TR, nothing changed."); else if (ok && newTR % tmpResolve != 0) // "OK" clicked, but input number isn't a multiple of 100ms QMessageBox::critical(0, "Error", "The new TR must be multiple of " + QString::number(tmpResolve) + " ms."); } /* changeNumberPoints() is slot to take care of new number of points input. * Note that reInit(true) is called here, which means condition function * information is always deleted when new number of points is loaded. */ void Gdw::changeNumberPoints() { bool ok; int newNumber = QInputDialog::getInteger("Enter New number of time points", "Please enter the new number of points", totalReps, 0, 2147483647, 1, &ok); if (ok && newNumber != totalReps) { if (covList.size() > 0 && gUpdateFlag == true) switch(QMessageBox::warning(0, "Warning!", "You have typed in a new number of time points.\

Your previous GLM design will be aborted. Do you want to save it now?", \ "Yes", "No", "Cancel", 0, 2)) { case 0: fileSave(); reInit(true); totalReps = newNumber; numberString->setText(QString::number(totalReps)); upperWindow->update(); break; case 1: reInit(true); totalReps = newNumber; numberString->setText(QString::number(totalReps)); upperWindow->update(); break; case 2: break; } else { reInit(true); totalReps = newNumber; numberString->setText(QString::number(totalReps)); upperWindow->update(); } } else if (ok && newNumber == totalReps) QMessageBox::warning(0, "Warning", "Same number, nothing changed."); } /* This slot is listening to the signal of newCovLoaded and show the new covariate on the upperWindow display */ void Gdw::upperWindowUpdate(VB_Vector *newVector) { timeVector = newVector; // Downsample the time vector before fft (because Goeff did it too) VB_Vector *timeVector_down = downSampling(timeVector, TR / tmpResolve); fftVector = fftNyquist(timeVector_down); // If "Freq Plot" radio button is selected if (fftFlag) { upperWindow->setFirstVector(fftVector); if (mode == COMBO && fitFlag) { QColor noiseColor = Qt::red; VB_Vector *newNoiseVec = new VB_Vector(noiseVec); newNoiseVec->scaleInPlace(fftVector->getMaxElement()); upperWindow->addVector(newNoiseVec, noiseColor); } int lowFreqIndex = getLowFreq(fftVector) - 1; if (lowFreqIndex > 1) statusBar()->message(QString("Covariate info: frequency 0-%1 < 1% power. You can remove %2 \ frequencies safely.").arg(lowFreqIndex).arg(lowFreqIndex)); else if (lowFreqIndex == 1) statusBar()->message(QString("Covariate info: frequency 0-1 < 1% power. You can remove 1 \ frequency safely.")); else if (lowFreqIndex == 0) statusBar()->message(QString("Covariate info: frequency 0 < 1% power")); else statusBar()->message(QString("Covariate info: no low frequency cutoff found.")); // "Freq Plot" + "Secs/Hz" combination if (secFlag) { upperWindow->setAllNewX(0, 1.0 / (2.0 * TR / 1000.0)); // Set unit of x axis to Hz upperWindow->setXCaption("Freq (Hz)"); } // "Freq Plot" + "TRs (Freq)" combination else { upperWindow->setAllNewX(0, (double) totalReps / 2.0); // Set unit of x axis to number of images upperWindow->setXCaption("Freq (Number)"); } } // If "Time Plot" radio button is selected else { upperWindow->setFirstVector(timeVector); // "Time Plot" + "Secs/Hz" combination if (secFlag) { if (upperWindow->getFirstPlotMode() % 2 == 1) upperWindow->setFirstXLength((totalReps - 1) * TR / 1000.0); else upperWindow->setFirstXLength(totalReps * TR / 1000.0); upperWindow->setXCaption("Time (Sec)"); } // "Time Plot" + "TRs (Freq)" combination else { if (upperWindow->getFirstPlotMode() % 2 == 1) upperWindow->setFirstXLength(totalReps - 1); else upperWindow->setFirstXLength(totalReps); upperWindow->setXCaption("Time (Images)"); } // Print out the highlighted covariate's mean and std values double vecMean = timeVector_down->getVectorMean(); double vecSD = sqrt(timeVector_down->getVariance()); statusBar()->message(QString("Covariate info: mean=%1, SD=%2").arg(vecMean).arg(vecSD)); } upperWindow->setYCaption("Magnitude"); upperWindow->update(); } /* Slot for "File -> Open" */ void Gdw::fileOpen() { if (gUpdateFlag) switch(QMessageBox::warning(0, "Warning!", "Do you want to save your previous GLM design?", \ "Yes", "No", "Cancel", 0, 2)) { case 0: fileSave(); break; case 1: break; case 2: // Nothing happens if "cancel" is clicked. return; } QString loadedFilename = Q3FileDialog::getOpenFileName(QString::null, "G matrix files (*.G)", this, \ "Open a G matrix file", "Choose a G Matrix file to open"); if (loadedFilename.isEmpty()) return; const string s1(loadedFilename.ascii()); if (chkFileStat(loadedFilename.ascii(), true)) readG(s1); } /* readG() reads a certain G file into the upper window and set up other * parameters based on the input G matrix file */ void Gdw::readG(const string inputName) { pregStat = true; if (!chkG(inputName)) return; gMatrix = myGInfo.gMatrix; // Do NOT overwrite G matrix filename in COMBO mode if (mode == SINGLE) gFileName = QString(inputName.c_str()); reInit(true); upperWindow->setRatio(TR / tmpResolve); if (myGInfo.condStat) cpCondInfo(); setGname(inputName); if (pregStat) pregStat = chkPreG(inputName); buildCovList(pregStat); buildTree(); } /* Set gFilename and interface caption */ void Gdw::setGname(string inputName) { if (mode == SINGLE) { gFileName = (QString)(inputName.c_str()); this->setCaption("G Design Workshop: " + gFileName); } else this->setCaption("G Design Workshop: " + gFileName + ".G"); // If the filename ends with ".G", truncate ".G" for .preG save purpose if (gFileName.right(2) == ".G") gFileName.truncate(gFileName.length() - 2); // Because setVarEditor() always sets gUpdateFlag to be true, reset it to be false here. if (mode == SINGLE) setGUpdateFlag(false); // In COMBO mode, loading a new G matrix file means it is already updated else setGUpdateFlag(true); } /* buildCovList() reads each column of gMatrix or pregMatrix (if available) into covList */ void Gdw::buildCovList(bool pregStat) { if (interceptID.size()) interceptID.clear(); VB_Vector tmpVec; int upRatio = TR / tmpResolve; for (uint32 i = 0; i < gMatrix.n; i++) { // If preG is valid, use it instead if (pregStat) { tmpVec = pregMatrix.GetColumn(i); VB_Vector *newVector = new VB_Vector(tmpVec); // record intercept index if (newVector->getVariance() <= 1e-15) interceptID.push_back(i); covList.push_back(newVector); } // Otherwise use G file else { tmpVec = gMatrix.GetColumn(i); VB_Vector *downVector = new VB_Vector(tmpVec); VB_Vector *newVector = upSampling(downVector, upRatio); if (newVector->getVariance() <= 1e-15) interceptID.push_back(i); covList.push_back(newVector); delete downVector; } } } /* buildTree() builds the varListView tree based on the parameter lines in G matrix file */ void Gdw::buildTree() { QString nameStr, sectionStr, typeStr; QStringList qList; for (int i = 0; i < (int) myGInfo.nameList.size(); i++) { nameStr = QString(myGInfo.nameList[i].c_str()); typeStr = QString(myGInfo.typeList[i].c_str()); QStringList qList = QStringList::split("->", nameStr); Q3ListViewItem *parent = varListView->firstChild(); for (int j = 0; j < qList.size(); j++) { sectionStr = *qList.at(j); // Covariate is a direct child of varListView if (qList.size() == 1) { (void) new Q3ListViewItem(varListView, getLastChild(varListView), sectionStr, typeStr, QString::number(i)); break; } // Covariate belongs to a certain group if (j == qList.size() - 1) { (void) new Q3ListViewItem(parent, getLastChild(parent), sectionStr, typeStr, QString::number(i)); break; } // Create the covariate's first layer group item (if not available) if (j == 0) { if (!searchDepth0(sectionStr)) { parent = new Q3ListViewItem(varListView, getLastChild(varListView), sectionStr); parent->setOpen(true); } else parent = searchDepth0(sectionStr); } // Create group items after the first layer else if (!findGrp(parent, sectionStr)) { parent = new Q3ListViewItem(parent, getLastChild(parent), sectionStr); parent->setOpen(true); } else parent = findGrp(parent, sectionStr); } } plotCov(0); // label intercept covariate(s) in hidden column for (unsigned k = 0; k < interceptID.size(); k++) { QString tmpStr = QString::number(interceptID[k]); varListView->findItem(tmpStr, 2)->setText(3, "intercept"); } } /* searchDepth0() searches the direct child(ren) of varListView and returns the QListViewtem * that is a group item and name matches the input QString. Returns 0 if name not found */ Q3ListViewItem *Gdw::searchDepth0(QString grpName) { Q3ListViewItem *child = varListView->firstChild(); while (child) { if (child->text(2).isEmpty() && child->text(0) == grpName) return child; child = child->nextSibling(); } return 0; } /* plotCov() draws a covariate in upperWindow based on the input * covariate index and set up related parameters correctly. */ void Gdw::plotCov(unsigned inputIndex) { if (!covList.size()) return; if (inputIndex >= covList.size()) return; Q3ListViewItem *myItem = varListView->findItem(QString::number(inputIndex), 2); if (!myItem) return; QObject::disconnect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); selID.clear(); selID.push_back(inputIndex); itemCounter = 1; varListView->setSelected(myItem, true); varListView->setCurrentItem(myItem); int covType = convtType(myItem->text(1)); typeCombo->setCurrentItem(covType); emit(newCovLoaded(covList[inputIndex])); QObject::connect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); } /* chkG() makes sure the input G file is valid */ bool Gdw::chkG(string inputName) { // Only accept *.G file int strLen = inputName.length(); if (inputName.substr(strLen - 2, 2) != ".G") { printf("[Error] Input filename not in *.G format: %s\n", inputName.c_str()); return false; } myGInfo = gHeaderInfo(); if (!myGInfo.read(inputName, false)) return false; if (!cmpTR(myGInfo.TR)) return false; if (!cmpTotalReps(myGInfo.rowNum)) return false; if (!cmpSampling(myGInfo.sampling)) return false; return true; } /* Compare TR in G amtrix with TR defined on the interface */ bool Gdw::cmpTR(int headerTR) { // When no TR in G matrix header if (headerTR == -1) { if (TR) QMessageBox::warning(0, "Warning", "No TR information available in G matrix file. \
The original value will be used."); else { QMessageBox::warning(0, "Warning", "No TR information available. \
The default value of 2000ms is used."); TR = 2000; trString->setText("2000"); } return true; } else if (mode == COMBO && TR != headerTR) { switch(QMessageBox::warning(0, "Warning!", QString("TR in G matrix file header (%1) is different \ from the original value (%2). The original value will be used.
Do you want to continue?") .arg(headerTR).arg(TR), "Yes", "No", 0)) { case 0: pregStat = false; return true; case 1: // Terminate this function for "No" return false; } } else if (mode == SINGLE && TR != headerTR) { TR = headerTR; trString->setText(QString::number(TR)); } return true; } /* Compare totalReps on the interface with totalReps in G matrix header */ bool Gdw::cmpTotalReps(int rowNum) { // If number of time points not set yet, set it to be the number of rows in matrix if (totalReps == 0) { totalReps = rowNum; numberString->setText(QString::number(totalReps)); return true; } // Inconsistency in combo mode: error message if (totalReps != rowNum && mode == COMBO) { QMessageBox::critical(0, "Error!", QString("The number of rows (%1) in G matrix not match \ the original number of time points (%2)").arg(rowNum).arg(totalReps)); return false; } // In SINGLE mode, if number of time points doesn't match, give a warning message if (totalReps != rowNum && mode == SINGLE) { totalReps = rowNum; numberString->setText(QString::number(totalReps)); } return true; } /* Compare sampling rate in the header with the one defined on the interface */ bool Gdw::cmpSampling(int headerSampling) { if (headerSampling == 0) { printf("G matrix warning: No upsampling rate information in the matrix file's header.\n"); printf("Default value of 100ms is used.\n"); tmpResolve = 100; } else if (tmpResolve != headerSampling) tmpResolve = headerSampling; if (TR % tmpResolve != 0) { QMessageBox::critical(0, "Error!", QString("TR (%1) is not multiple of sampling rate(%2)") .arg(TR).arg(tmpResolve)); return false; } // Check condition function length again, because TR or sampling or totalReps might have been changed if (myGInfo.condStat) { int condLen = myGInfo.condVector->getLength(); if ((TR / tmpResolve) % (condLen / totalReps) != 0) { QString helpStr = "G matrix error: Condition function can not be upsampled with current sampling rate."; QMessageBox::critical(0, "Error!", helpStr); return false; } } // Pass! samplingStr->setText(QString::number(tmpResolve)); upperWindow->setRatio(TR / tmpResolve); return true; } /* chkPreG() makes sure the preG file exists and in valid format */ bool Gdw::chkPreG(string inputName) { string pregName = inputName; int dotPost = pregName.rfind("."); pregName.erase(dotPost); pregName.append(".preG"); // Start to read preG file if (pregMatrix.ReadHeader(pregName) || pregMatrix.ReadFile(pregName) || !pregMatrix.m || !pregMatrix.n) { printf("[E] couldn't read %s as a valid G matrix file\n", pregName.c_str()); return false; } gHeaderInfo myPreGInfo = gHeaderInfo(pregMatrix); if ( !myPreGInfo.chkInfo(true) ) return false; return cmpG2preG(myGInfo, myPreGInfo); } /* Copy condition function name, condition keys and condition function vector from G matrix header */ void Gdw::cpCondInfo() { int condLen = myGInfo.condVector->getLength(); condVector = new VB_Vector(condLen); for (int i = 0; i < condLen; i++) (*condVector)[i] = (myGInfo.condVector)->getElement(i); condKey = tokenlist(myGInfo.condKey); condRef = QString(myGInfo.condfxn.c_str()); for (size_t m = 0; m < condKey.size(); m++) { QString keyString = QString(condKey(m)); keyList->insertItem(keyString); } keyList->setCurrentItem(0); } /* Slot for "File -> Save" */ void Gdw::fileSave() { if (!covList.size()) { QMessageBox::information(0, "Info", "No covariates defined yet."); return; } if (!chkItemName()) return; if (gFileName.isEmpty()) { fileSaveAs(); return; } if (!gUpdateFlag) { QMessageBox::information(0, "Info", "No changes to be saved."); return; } writeG(gFileName.toStdString(), TR, totalReps, tmpResolve, covList, varListView, condRef, condKey, meanAll->isChecked()); setGUpdateFlag(false); } /* Slot for "File -> Save As" */ void Gdw::fileSaveAs() { if (!covList.size()) { QMessageBox::information(0, "Info", "No covariates defined yet."); return; } if (!chkItemName()) return; // If input filename is foo, new files generated will be: foo.G and foo.preG QString newName = Q3FileDialog::getSaveFileName(QString::null, tr("G Matrix Files (*.G);;All Files (*)"), this, "Save G Matrix File", "Choose a filename to save the G matrix under: "); if (newName.isEmpty()) return; if (!newName.endsWith(".G")) newName = newName + ".G"; QFileInfo *newFileInfo = new QFileInfo(newName); QString pathString = newFileInfo->dirPath(true); // Absolute path of the G matrix file QFileInfo *newFilePath = new QFileInfo(pathString); if (newFileInfo->exists()) { switch(QMessageBox::warning(0, "Warning!", newName + " already exists. Are you sure you want to overwrite this file now?", "Yes", "No", "Cancel", 0, 2)) { // "Yes" overwrites the file case 0: // Remove ".G" at the tail newName.remove(newName.length() - 2, 2); // exit if the directory is not writable if (!newFilePath->isWritable()) { QMessageBox::critical(0, "Error!", "Not permitted to write file in this directory: " + pathString); return; } writeG(newName.toStdString(), TR, totalReps, tmpResolve, covList, varListView, condRef, condKey, meanAll->isChecked()); if (mode == SINGLE) singleSaveAs(newName); break; default: // Do nothing for "No" and "Cancel" break; } } else { newName.remove(newName.length() - 2, 2); // Is this directory writable? if (!newFilePath->isWritable()) { QMessageBox::critical(0, "Error!", "Not permitted to write file in this directory: " + pathString); return; } writeG(newName.toStdString(), TR, totalReps, tmpResolve, covList, varListView, condRef, condKey, meanAll->isChecked()); if (mode == SINGLE) singleSaveAs(newName); } } /* Function specially written for "File -> Save As" in SINGLE mode */ void Gdw::singleSaveAs(QString &inputName) { gFileName = inputName; setGUpdateFlag(false); this->setCaption("G Design Workshop: " + inputName + ".G"); } /* chkViewItem() checks the item in varListView to make sure their names do not * include "->" and no blank names available. * returns true if the names are good, otherwise false */ bool Gdw::chkItemName() { QString nameStr; bool status = true; Q3ListViewItemIterator it(varListView); while (it.current()) { nameStr = it.current()->text(0); if (!nameStr.length()) { QMessageBox::critical(0, "Error", "Blank group/covariate name not allowed in covariate tree"); status = false; } else if (nameStr.contains("->")) { QMessageBox::critical(0, "Error", "-> not allowed in group/covariate name:

" + nameStr); status = false; } else if (!it.current()->text(2).length() && !chkGrpName(it.current())) { QMessageBox::critical(0, "Error", "Duplicate group names not allowed at same tree level:

" + nameStr); status = false; } ++it; } return status; } /* chkGrpName() checkes the input item's name and make sure there are is no duplicate group names * at same tree level. Returns true if the input item is not a group or no same group name found. */ bool Gdw::chkGrpName(Q3ListViewItem *inputItem) { QString inputName = inputItem->text(0); Q3ListViewItem *next = inputItem->nextSibling(); while (next) { if (inputName == next->text(0)) return false; next = next->nextSibling(); } return true; } /* closeEvent() is an overloaded function called when user clicks "quit" or the "x" button on * the upperleft corner. Note that the response will be different for combo and single mode: * In SINGLE mode, it will check whether the latest G matrix has already saved on the disk. * If yes, close the window; if no, ask the user whether he wants to save it or not. * In COMBO mode, since we have already determined the analysis folder's name, simply * write the file and emit the signal. */ void Gdw::closeEvent(QCloseEvent *ce) { if (!covList.size()) { // If there is no any covariates defined yet switch(QMessageBox::information(0, "Info", "You haven't created any covariates yet. \

Are you sure you want to quit?", "Quit", "Don't Quit", QString::null, 0, 1)) { case 0: ce->accept(); if (mode == COMBO) emit(cancelSignal(true)); break; case 1: ce->ignore(); break; } } /* If covariate(s) do(es) exist, then in COMBO mode, if the G matrix has been changed, * simply save it with the filename determined in tab1. */ else if (mode == COMBO) { emit(doneSignal(covList, varListView, tmpResolve, condRef, condKey, meanAll->isChecked())); ce->accept(); } // In SINGLE mode, if the G matrix has been changed, ask the user whether it should be saved else if (gUpdateFlag) { switch(QMessageBox::information(0, "Info", "G matrix has been changed since the last time you saved it.

\ Do you want to save it first?", "Yes", "No", "Cancel", 0, 2)) { case 0: // If yes, save it and close the window fileSave(); ce->accept(); break; case 1: // If no, simply close the window ce->accept(); break; case 2: // If cancel, do nothing ce->ignore(); break; } } else // If in sigle mode and G matrix isn't changed, close the window ce->accept(); } /* This function checks whether both TR and totalReps have been set. * Returns true if both are set, otherwise false. */ bool Gdw::chkTR_imgNum() { if (TR <= 0) { QMessageBox::critical(0, "Error!", "Invalid TR value"); return false; } if (totalReps <= 0) { QMessageBox::critical(0, "Error!", "Invalid number of time points"); return false; } return true; } /* This function checks these three parameters: TR, totalReps and condVector. * Returns true if all of three are set, otherwise false. */ bool Gdw::chkTR_imgNum_condfx() { if (TR <= 0) { QMessageBox::critical(0, "Error!", "Invalid TR value"); return false; } if (totalReps <= 0) { QMessageBox::critical(0, "Error!", "Invalid number of time points"); return false; } if (!condVector) { QMessageBox::critical(0, "Error!", "Condition function not found"); return false; } return true; } /* This is a generic function to add contrast(s), the input string is covariate type ("I" or "N") * The other two add-contrasts slots for "I" and "N" are wrappers based on this function */ void Gdw::addContrasts(QString inputType) { if (!chkTR_imgNum_condfx()) return; varType = inputType; G_Contrast *myContrast = new G_Contrast(keyList->count(), tmpResolve); myContrast->setCaption("Set up Contrasts Options"); myContrast->setFixedWidth(400); myContrast->show(); this->setDisabled(true); QObject::connect(myContrast, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myContrast, SIGNAL(doneSignal(Q3TextEdit *, int, int, bool, VB_Vector*, double, QString&)), this, SLOT(showContrasts(Q3TextEdit *, int, int, bool, VB_Vector*, double, QString&))); } /* Slot for "Edit -> Add Interest -> Contrast(s)", a wrapper based on the generic one. */ void Gdw::add_I_Contrasts() { addContrasts("I"); } /* Slot to work with contrast parameters collected from contrast matrix */ void Gdw::showContrasts(Q3TextEdit *matrixText, int scaleFlag, int centerFlag, bool convStat, VB_Vector *convVector, double sampling, QString &tag) { QString lineString; int lineNum = matrixText->paragraphs(); double contrastMatrix[keyList->count()]; QString tmpVarTxt; /* Upsample the original condition function */ int upRatio = (TR / tmpResolve) / (condVector->getLength() / totalReps); VB_Vector *condVector_up = upSampling(condVector, upRatio); contrast_count++; QString groupStr = "contrasts_g" + QString::number(contrast_count); Q3ListViewItem *contrastGrp = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); contrastGrp->setOpen(true); for (int i = 0; i < lineNum; i++) { tmpVarTxt =""; lineString = (matrixText->text(i)).simplifyWhiteSpace(); // Skip blank row in contrast matrix if (!lineString.length()) continue; // Make new covariate name based on contrast matrix elements for (unsigned j = 0; j < keyList->count(); j++) { QString element = lineString.section(' ', j, j); contrastMatrix[j] = element.toDouble(); // Exclude the element which is zero if (!contrastMatrix[j]) continue; tmpVarTxt = tmpVarTxt + element + "*" + keyList->text(j); if (j < keyList->count() - 1) tmpVarTxt = tmpVarTxt + " + "; } // Make sure there is no "+" at the end of the covariate name if (tmpVarTxt.endsWith(" + ")) tmpVarTxt.truncate(tmpVarTxt.length() - 3); // Build new VB_Vector to represent new contrast covariate VB_Vector *contrastVec = new VB_Vector(condVector_up->getLength()); for (unsigned j = 0; j < condVector_up->getLength(); j++) { int n = (int) condVector_up->getElement(j); // scale or not? if (scaleFlag) contrastVec->setElement(j, contrastMatrix[n] / countNum(condVector_up, n)); else contrastVec->setElement(j, contrastMatrix[n]); } // mean-center or not? if (centerFlag) contrastVec->meanCenter(); // convolution or not? if (convStat) { contrastVec = new VB_Vector(getConv(contrastVec, convVector, (int) sampling, tmpResolve)); tmpVarTxt = tmpVarTxt + " (" + tag + ")"; } covList.push_back(contrastVec); QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(contrastGrp, getLastChild(contrastGrp), tmpVarTxt, varType, idStr); } loadSingleCov(getLastChild(contrastGrp), convtType(varType)); delete condVector_up; } /* Slot for ""Edit -> Add Interest -> Diagonal set" */ void Gdw::add_I_DS() { addDS("I"); } /* Slot for ""Edit -> Add NoInterest -> Diagonal set" */ void Gdw::add_N_DS() { addDS("N"); } /* addDS() is a generation function to add diagonal set covariate(s) */ void Gdw::addDS(QString inputType) { if (!chkTR_imgNum_condfx()) return; varType = inputType; G_DS *myDS = new G_DS(tmpResolve); myDS->setFixedWidth(350); myDS->setCaption("Set up Diagonal Set Options"); myDS->show(); this->setDisabled(true); QObject::connect(myDS, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myDS, SIGNAL(doneSignal(int, int, bool, VB_Vector*, double, QString&)), this, SLOT(showDS(int, int, bool, VB_Vector*, double, QString&))); } /* showDS() adds new covariate(s) into covList and show them on the interface */ void Gdw::showDS(int scaleFlag, int centerFlag, bool convStat, VB_Vector *convVector, double sampling, QString &tag) { int upRatio = (TR / tmpResolve) / (condVector->getLength() / totalReps); VB_Vector *condVector_up = upSampling(condVector, upRatio); diagonal_count++; QString groupStr = "diagonal_g" + QString::number(diagonal_count); Q3ListViewItem *diagonalGrp = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); diagonalGrp->setOpen(true); int upLength = condVector_up->getLength(); int rowNum = keyList->count() - 1; double diagMatrix[keyList->count()]; QString tmpVarTxt; for (int i = 0; i < rowNum; i++) { tmpVarTxt=""; for (unsigned j = 0; j < keyList->count(); j++) { if (j - i == 1) diagMatrix[j] = 1.0; else diagMatrix[j] = 0; } VB_Vector *diagVec = new VB_Vector(upLength); tmpVarTxt = keyList->text(i+1); for (unsigned j = 0; j < condVector_up->getLength(); j++) { double m = condVector_up->getElement(j); int n = (int) m; // scale or not? if (scaleFlag) diagVec->setElement(j, diagMatrix[n] / countNum(condVector_up, n)); else diagVec->setElement(j, diagMatrix[n]); } // mean-center or not? if (centerFlag) diagVec->meanCenter(); // convolution or not? if (convStat) { diagVec = new VB_Vector(getConv(diagVec, convVector, (int) sampling, tmpResolve)); tmpVarTxt = tmpVarTxt + " (" + tag + ")"; } covList.push_back(diagVec); QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(diagonalGrp, getLastChild(diagonalGrp), tmpVarTxt, varType, idStr); } loadSingleCov(getLastChild(diagonalGrp), convtType(varType)); delete condVector_up; } /* This is a generic function to add single covariate, * the input string is covariate type ("I" or "N"); * The other two add-single-covariate slots for interest and * no interest are simply wrappers based on this function. */ void Gdw::addSingle(QString inputType) { if (!chkTR_imgNum()) return; // Open a FileDialog window to select ref file QString tmpString=QFileDialog::getOpenFileName(this,"Add Covariate","","Vector and Matrix files (*.ref *.mtx *.mat);;All files (*)"); if (!tmpString.length()) return; VB_Vector tmpVector; VBMatrix mymat; string cname; string infile=tmpString.toStdString(); if (!tmpVector.ReadFile(infile)) { int refLength = tmpVector.getLength(); // Get the number of points in REF file /* If the number of points in REF file isn't a multiple of the concatenated total number of TES files, * pop out an error message and ask the user to try again. */ if (refLength % totalReps != 0) { QMessageBox::critical(0, "Error!", "Number of elements in REF function must be a multiple of total number of time points."); return; } else if ((TR / tmpResolve) % (refLength / totalReps) != 0) { QString helpStr; if (TR % (refLength / totalReps) == 0) { int maxSamp = TR / (refLength / totalReps); helpStr = "Reference function can NOT be upsampled with the current sampling rate.\

Click Tools to reset the upsampling rate. \

Recommended value: " + QString::number(maxSamp) + "/N (N is positive integer)"; } else helpStr = "Invalid reference function: can not be upsampled with the current sampling rate."; QMessageBox::critical(0, "Error!", helpStr); return; } int upRatio = (TR / tmpResolve) / (refLength / totalReps); VB_Vector *newVector = upSampling(&tmpVector, upRatio); covList.push_back(newVector); QString covID = QString::number(covList.size() - 1); cname=xfilename(infile); Q3ListViewItem *newItem = new Q3ListViewItem(varListView, getLastChild(varListView),cname.c_str(), inputType, covID); loadSingleCov(newItem, convtType(inputType)); } else if (!mymat.ReadFile(infile)) { int refLength = mymat.rows; if (refLength % totalReps != 0) { QMessageBox::critical(0, "Error!", "Number of elements in your covariate file must be a multiple of total number of time points."); return; } else if ((TR / tmpResolve) % (refLength / totalReps) != 0) { QString helpStr; if (TR % (refLength / totalReps) == 0) { int maxSamp = TR / (refLength / totalReps); helpStr = "Reference function can NOT be upsampled with the current sampling rate.\

Click Tools to reset the upsampling rate. \

Recommended value: " + QString::number(maxSamp) + "/N (N is positive integer)"; } else helpStr = "Invalid reference function: can not be upsampled with the current sampling rate."; QMessageBox::critical(0, "Error!", helpStr); return; } int upRatio = (TR / tmpResolve) / (refLength / totalReps); for (uint32 i=0; i Add Interest -> Single covariate", a wrapper based on the generic one. */ void Gdw::add_I_Single() { addSingle("I"); } /* addTrialFx() is a generic function which adds trial effects of fixed value * * It accepts an argument which is the variable type * ("I" for interest, "N" for no interest or "K" for keep no interest) */ void Gdw::addTrialFx(QString inputType) { if (!chkTR_imgNum()) return; bool ok; int trialLength = QInputDialog::getInteger("Trial Effects Options", "Trial length (secs): ", 1, 1, TR * totalReps, 1, &ok, this); if (!ok) return; int numTrials = TR * totalReps / (trialLength * 1000) - 1; // Make sure trialfx group will have at least 1 child covaraite if (!numTrials) { QMessageBox::critical(0, "Error", "No trial effect covariates can be defined with a trial length of ." + QString::number(trialLength)); return; } int unitLength = trialLength * 1000 / tmpResolve; trialfx_count++; QString groupStr = "trialfx_g" + QString::number(trialfx_count); Q3ListViewItem *trialfx = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); trialfx->setOpen(true); for (int i = 0; i < numTrials; i++) { VB_Vector * newCov = new VB_Vector(TR * totalReps / tmpResolve); newCov->setAll(0); for (int j = i * unitLength; j < (i + 1) * unitLength; j++) { newCov->setElement(j, 1.0); } newCov->meanCenter(); covList.push_back(newCov); QString idStr = QString::number(covList.size() - 1); QString tmpVarTxt = "Trial effect " + QString::number(i + 1); (void) new Q3ListViewItem(trialfx, getLastChild(trialfx), tmpVarTxt, inputType, idStr); } loadSingleCov(getLastChild(trialfx), convtType(inputType)); } /* Slot for "Edit -> Add Interest -> Trial Effects" */ void Gdw::add_I_Trial() { addTrialFx("I"); } /* addVarTrial() is a generic function to add trial effects from a certain ref file. * It will pop out a window to ask the user to pick up the ref file which includes the trial length. * As usual, this function accepts an argument to lable the covariate's type [ I/N/K ]. */ void Gdw::addVarTrial(QString inputType) { if (!chkTR_imgNum()) return; QString trialFile = Q3FileDialog::getOpenFileName(QString::null, "Ref files (*.ref)", this, "Add Single Covariate", "Please choose the ref function"); if (!trialFile.length()) return; VB_Vector trialVec; if (trialVec.ReadFile(trialFile.ascii())) { QMessageBox::critical(0, "Error", "Invalid ref file format: " + trialFile); return; } int trialSum = (int) trialVec.getVectorSum(); if (trialSum != totalReps * TR / 1000) { QMessageBox::critical(0, "Error", "The sum of elements in " + trialFile + " isn't equal to the actual length.

Please try another file."); return; } if (trialVec.getLength() == 1) { QMessageBox::critical(0, "Error", trialFile + " has only line.

Trial effect covaraite can NOT be defined. \

Please try another file."); return; } int trialOffset = 0; var_len_count++; QString groupStr = "var_trialfx_g" + QString::number(var_len_count); Q3ListViewItem *trialfx = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); trialfx->setOpen(true); for (unsigned i = 0; i < trialVec.getLength() - 1; i++) { VB_Vector *newCov = new VB_Vector(TR * totalReps / tmpResolve); newCov->setAll(0); int nonZeroUnit = (int) trialVec.getElement(i) * 1000 / tmpResolve; for (int j = trialOffset; j < trialOffset + nonZeroUnit; j++) { newCov->setElement(j, 1.0); } newCov->meanCenter(); covList.push_back(newCov); QString idStr = QString::number(covList.size() - 1); QString tmpVarTxt = "Trial effect " + QString::number(i + 1); (void) new Q3ListViewItem(trialfx, getLastChild(trialfx), tmpVarTxt, inputType, idStr); trialOffset += nonZeroUnit; } loadSingleCov(getLastChild(trialfx), convtType(inputType)); // Highlight the last new item } /* Slot for "Add -> Interest -> Var Length Trial fx" */ void Gdw::add_I_varTrial() { addVarTrial("I"); } /* Slot for "Add -> No interest -> Intercept" */ void Gdw::slot_addIntercept() { // Make sure TR and totalReps are valid if (!chkTR_imgNum()) return; // Only one intercept covariate is allowed if (interceptID.size()) { QMessageBox::critical(0, "Error!", "Intercept covariate already defined"); return; } addIntercept(); QString idStr = QString::number(covList.size() - 1); loadSingleCov(varListView->findItem(idStr, 2), 2); } /* This is a generic function to add intercept. * It is also called by block and paired t-test models. */ void Gdw::addIntercept() { VB_Vector *newVector = new VB_Vector(totalReps * TR / tmpResolve); newVector->setAll(1.0); covList.push_back(newVector); QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(varListView, getLastChild(varListView), "Intercept", "K", idStr, "intercept"); varListView->hideColumn(3); interceptID.push_back(covList.size() - 1); } /* Slot for "Edit -> Add No interest -> Trial Effects" */ void Gdw::add_N_Trial() { addTrialFx("N"); } /* Slot for "Edit -> Add No interest -> Var Length Trial fx" */ void Gdw::add_N_varTrial() { addVarTrial("N"); } /* Slot for "Edit -> Add No interest -> Scan effects" */ /* Question: In SINGLE mode, when the user clicked "OK" but the input is invalid, * how can I keep the dialog box? * A possible solution is to write a new widget instead of using QT's QInputDialog class. */ void Gdw::addScanfx() { if (mode == SINGLE) singleScanfx(); else comboScanfx(); } /* singleScanfx() adds scan effect cavariate in single mode */ void Gdw::singleScanfx() { if (!chkTR_imgNum()) return; bool ok = false; QString text = QInputDialog::getText("Set up scan effects parameters", "Please type in the number of scans and number of TRs \ in each scan separated by a \",\".

For example: \"2: 100, 200\" means there are two scans. \ The first scan includes 100 TRs and the second 200 TRs.", QLineEdit::Normal, QString::null, &ok, this); if (!ok) return; if (text.isEmpty()) { QMessageBox::critical(0, "Error!", "No input found."); return; } text = text.simplifyWhiteSpace(); int colonPos = text.find(":", 0); if (colonPos == -1) { QMessageBox::critical(0, "Error!", "Number of scans not found. Please type in the numbers again."); return; } bool scanNumConvert = false; int scanNum = (text.section(":", 0, 0)).toInt(&scanNumConvert, 10); if (!scanNumConvert) { QMessageBox::critical(0, "Error!", "Invalid input for number of scans. Please type in the number again."); return; } int trArray[scanNum]; int totalTR = 0; text.remove(0, colonPos + 1); // Removes the number of scan section (includes ":") bool trNumConvert = false; for (int i = 0; i < scanNum; i++) { trArray[i] = (text.section(",", i, i)).toInt(&trNumConvert, 10); if (!trNumConvert) { QMessageBox::critical(0, "Error!", "The input number's format is incorrect. Please type it again."); return; } totalTR += trArray[i]; } if (totalTR != totalReps) { QMessageBox::critical(0, "Error", "The total number of TRs you typed in is unequal to \ the original number of time points. Please type in your number again."); return; } int offset = 0; scanfx_count++; QString groupStr = "scanfx_g" + QString::number(scanfx_count); Q3ListViewItem *scanfx = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); scanfx->setOpen(true); for (int i = 0; i < scanNum - 1; i++) { VB_Vector *newVector = new VB_Vector(totalReps * TR / tmpResolve); int singleLength = trArray[i] * TR / tmpResolve; for (int j = 0; j < totalReps * TR / tmpResolve; j++) { if (j < offset) newVector->setElement(j, 0); else if (j < singleLength + offset) newVector->setElement(j, 1.0); else newVector->setElement(j, 0); } offset += singleLength; newVector->meanCenter(); covList.push_back(newVector); QString idStr = QString::number(covList.size() - 1); QString tmpVarTxt = "Scan Effect " + QString::number(i + 1); (void) new Q3ListViewItem(scanfx, getLastChild(scanfx), tmpVarTxt, "N", idStr); } loadSingleCov(getLastChild(scanfx), 1); } /* comboScanfx() adds scan effect covariates in combo mode */ void Gdw::comboScanfx() { if (tesNum == 0) { QMessageBox::critical(0, "Error", "No TES files defined yet."); return; } if (tesNum == 1) { QMessageBox::critical(0, "Error", "Only one TES file found. No scan effects defined."); return; } Tes tmpTes; int offset = 0; scanfx_count++; QString groupStr = "scanfx_g" + QString::number(scanfx_count); Q3ListViewItem *scanfx = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); scanfx->setOpen(true); for (int i = 0; i < tesNum - 1; i++) { const char *tmpFileName = tesList->item(i)->text(); string selectedFiles (tmpFileName); tmpTes.ReadFile(selectedFiles); int singleLength = tmpTes.dimt * TR / tmpResolve; VB_Vector *newVector = new VB_Vector(totalReps * TR / tmpResolve); for (int j = 0; j < totalReps * TR / tmpResolve; j++) { if (j < offset) newVector->setElement(j, 0); else if (j < singleLength + offset) newVector->setElement(j, 1.0); else newVector->setElement(j, 0); } newVector->meanCenter(); covList.push_back(newVector); QString tmpVarTxt = "Scan Effect " + QString::number(i + 1); QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(scanfx, getLastChild(scanfx), tmpVarTxt, "N", idStr); offset += singleLength; } loadSingleCov(getLastChild(scanfx), 1); } /* Slot for "Edit -> Add No interest -> Global signals" */ void Gdw::addGlobal() { if (mode == SINGLE) { QMessageBox::information(0, "Information", "Please use GLM interface to define TES files first."); return; } // First make sure each tes file has its own gloabl signal file, if not, close the function if (!chkGSstat()) return; // Assume that the global signal files are in the same directory as the TES files QString tesFileName; VB_Vector *tmpVector = new VB_Vector(); // This vector will hold data read from a certain GS file int tmpLength; int startPos = 0; global_count++; QString groupStr = "global_signal_g" + QString::number(global_count); Q3ListViewItem *gSignal = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); gSignal->setOpen(true); for (int i = 0; i < tesNum; i++) { VB_Vector *newVector = new VB_Vector(totalReps); newVector->setAll(0); tesFileName = tesList->item(i)->text(); // If the TES file name is "my_tes_file.tes", the corresponding GS file should be: "my_tes_file_GS.ref" const char *gsFileName; gsFileName = tesFileName.replace(tesFileName.length() - 4, 4, "_GS.ref"); if (tmpVector->ReadFile(gsFileName)) { QMessageBox::critical(0, "Error", "Invalid ref file format: " + QString(gsFileName)); delete tmpVector; return; } tmpVector->meanCenter(); // Geoff did it, so do I tmpLength = tmpVector->getLength(); for (int j = startPos; j < tmpLength + startPos; j++) // Then assign some elements to be the value in GS file newVector->setElement(j, tmpVector->getElement(j - startPos)); VB_Vector *newVector_up = upSampling(newVector, TR / tmpResolve); covList.push_back(newVector_up); QString idStr = QString::number(covList.size() - 1); QString tmpVarTxt = "Global Signal " + QString::number(i + 1); (void) new Q3ListViewItem(gSignal, getLastChild(gSignal), tmpVarTxt, "N", idStr); startPos += tmpLength; delete newVector; } loadSingleCov(getLastChild(gSignal), 1); delete tmpVector; } /* This is a function to collect movement parameter files * for each tes file before adding covariates */ tokenlist Gdw::getMPFiles() { tokenlist mpFiles = tokenlist(); QString tesFileName, mpFileName; for (int i = 0; i < tesNum; i++) { tesFileName = tesList->item(i)->text(); mpFileName = tesFileName.left(tesFileName.length() - 4) + "_MoveParams.ref"; QFileInfo newFileInfo = QFileInfo(mpFileName); // If the default movement parameter filename not found, ask user to choose one if (!newFileInfo.exists()) { mpFileName = Q3FileDialog::getOpenFileName(QString::null, "Movement parameter files (*.ref)", this, "Open a movement parameter file", "Choose a movement parameter file for " + tesFileName); if (mpFileName.isEmpty()) { QMessageBox::information(0, "Info", "Movement parameter file for " + tesFileName + " not available. No covariates added."); mpFiles.clear(); return mpFiles; } } mpFiles.Add(mpFileName.ascii()); } return mpFiles; } /* Slot for "Edit -> Add No interest -> Movement params" */ void Gdw::addMovement() { if (mode == SINGLE) { QMessageBox::information(0, "Information", "Please use GLM interface to define TES files first."); return; } tokenlist mpFiles = getMPFiles(); if (!mpFiles.size()) return; int mpLength, unitLength; int startPost = 0; mvpr_count++; for (int i = 0; i < tesNum; i++) { const char * mpFileName = mpFiles(i); VB_Vector *mpTotal = new VB_Vector(mpFileName); mpLength = mpTotal->getLength(); unitLength = mpLength / 7; QString groupStr = "move_param_g" + QString::number(mvpr_count) + " set #" + QString::number(i+1); Q3ListViewItem *mpGrp = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); mpGrp->setOpen(true); for (int j = 0; j < 6; j++) { VB_Vector *newVector = new VB_Vector(totalReps); newVector->setAll(0); // Read 1/7 of the total movement parameter vector into moveinfo and mean center it VB_Vector *moveInfo = new VB_Vector(unitLength); double moveVal; for (int k = 0; k < unitLength; k++) { moveVal = mpTotal->getElement(k * 7 + j); moveInfo->setElement(k, moveVal); } moveInfo->meanCenter(); for (int k = 0; k < unitLength; k++) newVector->setElement(k + startPost, moveInfo->getElement(k)); delete moveInfo; VB_Vector *newVector_up = upSampling(newVector, TR / tmpResolve); covList.push_back(newVector_up); QString idStr = QString::number(covList.size() - 1); QString tmpVarTxt; switch(j) { case 0: tmpVarTxt = "X"; break; case 1: tmpVarTxt = "Y"; break; case 2: tmpVarTxt = "Z"; break; case 3: tmpVarTxt = "Pitch"; break; case 4: tmpVarTxt = "Roll"; break; case 5: tmpVarTxt = "Yaw"; break; } (void) new Q3ListViewItem(mpGrp, getLastChild(mpGrp), tmpVarTxt, "N", idStr); delete newVector; } startPost += unitLength; delete mpTotal; } loadSingleCov(varListView->lastItem(), 1); } /* Slot for "Edit -> Add No interest -> Single covariate", a wrapper based on the generic one */ void Gdw::add_N_Single() { addSingle("N"); } /* Slot for "Edit -> Add No interest -> Contrast(s)", a wrapper based on the generic one */ void Gdw::add_N_Contrasts() { addContrasts("N"); } /* Slot for "Add No interest -> Spike" */ void Gdw::addSpike() { if (!chkTR_imgNum()) return; bool ok = false; QString text = QInputDialog::getText("Define spike position", "Please type in spike covariate's position in unit of TR. \
It should be a series of integers separated by , or :. \

A good example will be: \"20, 30, 98-100\". \
Here \"98-100\" is equivalent to \"98, 99, 100\".\

Note that spike's position starts from 0 instead of 1.", QLineEdit::Normal, QString::null, &ok, this); if (!ok) return; if (text.isEmpty()) { QMessageBox::critical(0, "Error!", "No input found."); return; } vector spike = numberlist((const string)text.ascii()); if (!chkSpike(spike)) return; VB_Vector tmpVec(totalReps); int spikeIndex; spike_count++; QString groupStr = "spike_g" + QString::number(spike_count); Q3ListViewItem *spikeGrp = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); spikeGrp->setOpen(true); for (int i = 0; i < (int) spike.size(); i++) { tmpVec.setAll(0); spikeIndex = spike[i]; tmpVec[spikeIndex] = 1.0; tmpVec.meanCenter(); // mean center by default covList.push_back(upSampling(&tmpVec, TR / tmpResolve)); QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(spikeGrp, getLastChild(spikeGrp), QString::number(spikeIndex), "N", idStr); } loadSingleCov(getLastChild(spikeGrp), 1); // Highlight the new item } /* chkSpike() is a function to check the spike string to make sure it is valid */ bool Gdw::chkSpike(vector inputSpike) { if (!inputSpike.size()) { QMessageBox::critical(0, "Error", "Invalid spike position"); return false; } for (int i = 0; i < (int) inputSpike.size(); i++) { if (inputSpike[i] < 0 || inputSpike[i] >= totalReps) { QMessageBox::critical(0, "Error", "Spike position out of range:" + QString::number(inputSpike[i])); return false; } } return true; } /* "Add No interest -> Txt file as multi-covariate" */ void Gdw::addTxt() { if (!chkTR_imgNum()) return; // Open a FileDialog window to select txt file QString tmpString = Q3FileDialog::getOpenFileName (QString::null, "Txt files (*.txt)", this, "Add Multiple Covariates from Txt File", "Please choose the txt file."); if (!tmpString.length()) return; const char *txtFile = tmpString; // Convert the input filename from QString to const char * int txtColNum = getTxtColNum(txtFile); int txtRowNum = getTxtRowNum(txtFile); if (txtColNum < 0) { QMessageBox::critical(0,"Error", "File NOT readable: " + tmpString); return; } if (txtRowNum == 0) { QMessageBox::critical(0,"Error", "No uncommented lines in: " + tmpString); return; } if (txtRowNum != totalReps) { QMessageBox::critical(0,"Error", "Number of elements in txt file doesn't match the total number of time points"); return; } std::vector< VB_Vector *> txtCov; for (int i = 0; i < txtColNum; i++) { VB_Vector *txtVec = new VB_Vector(txtRowNum); txtVec->setAll(0); txtCov.push_back(txtVec); } int readStat = readTxt(txtFile, txtCov); if (readStat == 1) { QMessageBox::critical(0,"Error", "input file doesn't have exactly the same number of elements in all rows"); return; } int upRatio = (TR / tmpResolve) / (txtRowNum / totalReps); txt_var_count++; QString groupStr = "txt_var_g" + QString::number(txt_var_count); Q3ListViewItem *txtVarGrp = new Q3ListViewItem(varListView, getLastChild(varListView), groupStr); txtVarGrp->setOpen(true); for (int k = 0; k < txtColNum; k++) { VB_Vector *newVector = upSampling(txtCov[k], upRatio); covList.push_back(newVector); QString idStr = QString::number(covList.size() -1); QString tmpVarTxt = "col #" + QString::number(k + 1); (void) new Q3ListViewItem(txtVarGrp, getLastChild(txtVarGrp), tmpVarTxt, "N", idStr); } txtCov.clear(); loadSingleCov(getLastChild(txtVarGrp), 1); // Highlight the new item } /* Slot for "Edit -> Select All" */ void Gdw::selectAll() { varListView->selectAll(true); } /* Slot for "Modify Selection(s) -> Duplicate" * Note that because covList is a vector of VB_Vector pointers, we cannot simply push_back() * the currently highlighted element in the vector to duplicate it. This way the new element * will always be equal to the original element, even after the user has manipulated the * original or new covariate (eg. convolve, mean center, etc.) So another brandnew VB_Vector * object is declared and put at the end of covariateList. */ void Gdw::duplicate() { if (!chkSel()) return; if (chkD()) { QMessageBox::critical(0,"Error", "Operation not allowed:\

More than one dependent covariate would exist after it"); return; } if (chkIntercept()) { QMessageBox::critical(0,"Error", "Operation not permitted on intercept covariate"); return; } Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { cpItem(it.current()); ++it; } setGUpdateFlag(true); } /* cpItem() will recursively copy the input listViewItem, written for covariate duplication * orgDepth is input item's original depth */ void Gdw::cpItem(Q3ListViewItem *inputItem) { if (inputItem->text(2).isEmpty()) cpGrp(inputItem); else cpCov(inputItem); } /* cpGrp() only add the new group item as the last child of parentItem. * None of its child will be copied */ void Gdw::cpGrp(Q3ListViewItem *inputItem) { // If the group item is a direct child of varListView, the new group name will be: _cp if (inputItem->depth() == 0) { QString tmpStr = inputItem->text(0) + "_cp"; (void) new Q3ListViewItem(varListView, getLastChild(varListView), tmpStr); return; } // If inputItem's parent is not selected, insert inputItem as a direct child of varListView if (!inputItem->parent()->isSelected()) { (void) new Q3ListViewItem(varListView, getLastChild(varListView), inputItem->text(0)); return; } (void) new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0)); } /* cpCov() will insert newItem as the last child of parentItem * and push back the corresponding vb_vector into covList */ void Gdw::cpCov(Q3ListViewItem *inputItem) { int covID = inputItem->text(2).toInt(); VB_Vector *newVec = new VB_Vector(covList[covID]); covList.push_back(newVec); QString idStr = QString::number(covList.size() - 1); if (inputItem->depth() == 0 || !inputItem->parent()->isSelected()) { (void) new Q3ListViewItem(varListView, getLastChild(varListView), inputItem->text(0), inputItem->text(1), idStr); return; } (void) new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0), inputItem->text(1), idStr); } /* findParent() returns inputItem's parent item when it is * inserted into the tree as a new item */ Q3ListViewItem *Gdw::findParent(Q3ListViewItem *inputItem) { int lastDepth = varListView->lastItem()->depth(); int inputDepth = getNewDepth(inputItem); if (lastDepth < inputDepth) return varListView->lastItem(); Q3ListViewItem *newParent = varListView->lastItem()->parent(); while (newParent->depth() > inputDepth - 1) newParent = newParent->parent(); return newParent; } /* getNewDepth() returns the input item's new depth in the tree after it is copied. * It checks if its direct parent is selected or not. If yes, check its parent's parent, * until it reached the point that one of its grandparent is not selected. * The new depth is equal to the number of checks */ int Gdw::getNewDepth(Q3ListViewItem *inputItem) { int newDepth = 0; Q3ListViewItem *itemParent = inputItem->parent(); while (itemParent) { if (itemParent->isSelected()) newDepth++; itemParent = itemParent->parent(); } return newDepth; } /* Slot for "Edit -> Modify Selection(s) -> Delete" */ void Gdw::delCov() { if (!varListView->childCount()) { QMessageBox::critical(0, "Error", "No covariate defined yet."); return; } // Make sure there is at least one selected item if (!itemCounter) { QMessageBox::critical(0, "Error", "No covariate selected yet."); return; } if (selID.size() == covList.size()) delAll(); else delPart(); } /* delAll will first ask user's confirmation to delete all covariates */ void Gdw::delAll() { switch(QMessageBox::warning(0, "Warning!", "Are you sure you want to delete all covariates?", "Yes", "Cancel", 0, 0, 1)) { case 0: covList.clear(); timeVector = fftVector= 0; d_index = -1; interceptID.clear(); varListView->clearSelection(); varListView->clear(); typeCombo->setCurrentItem(4); upperWindow->clear(); upperWindow->update(); initGrpCount(); setGUpdateFlag(false); statusBar()->message(QString("Status: no covariates defined")); break; case 1: break; } } /* delPart() will delete selected covariates/groups and update the index. * Note that a group item is deleted only when all of its direct/indirect children * are selected. If not the group item will be kept with its other survived child(ren). */ void Gdw::delPart() { // If D type is involved, reset d_index if (chkD()) d_index = -1; QObject::disconnect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); Q3PtrList lst; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { lst.append(it.current()); ++it; } varListView->clearSelection(); int selSize = lst.count(); for (int i = 0; i < selSize; i++) { Q3ListViewItem *last = lst.last(); lst.remove(lst.last()); if (!last->text(2).isEmpty()) delete last; else if (chkGrpSel(last)) delete last; } QObject::connect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); updateID(); updateInterceptID(); setGUpdateFlag(true); } /* chkGrpSel() checks whether the input group item's direct/indirect children * are all selected or not. * Returns true if all selected, false otherwise */ bool Gdw::chkGrpSel(Q3ListViewItem *inputGrp) { Q3ListViewItem * myChild = inputGrp->firstChild(); while (myChild) { if (!myChild->isSelected()) return false; if (myChild->childCount() && !chkGrpSel(myChild)) return false; myChild = myChild->nextSibling(); } return true; } /* updateID() is another function written for deleting covariates. * It updates covList array and the survived covariates' indices to * make sure they match each other */ void Gdw::updateID() { // If there is no any real covariate in the selected item, skip the removal if (!selID.size()) return; // sorting selID is required to calculate the index offset sort(selID.begin(), selID.end()); unsigned orgSize = covList.size(); // First delete selected covariates from covList array for (unsigned i = 0; i < selID.size(); i++) covList.erase(covList.begin() + selID[i] - i); // Now change the index in varListView to match covList for (unsigned i = 0; i < orgSize; i++) { unsigned offset = chkID(i); if (offset) (varListView->findItem(QString::number(i), 2))->setText(2, QString::number(i - offset)); } if (!varListView->childCount()) initGrpCount(); // Show a blank plot window now timeVector = fftVector= 0; typeCombo->setCurrentItem(4); upperWindow->clear(); upperWindow->update(); selID.clear(); itemCounter = 0; } /* This function returns intercept covariate's ID. Return -1 if no intercept is defined */ void Gdw::updateInterceptID() { interceptID.clear(); QString col2, col3; Q3ListViewItemIterator it(varListView); while (it.current()) { col2 = it.current()->text(2); col3 = it.current()->text(3); if (col2.length() && col3 == "intercept") interceptID.push_back(col2.toUInt()); it++; } } /* chkID() is written specially for "delete" functionality. * It checks whether an input integer equals any of the elements * in selID array. If yes, return 0, otherwise returns the number * of elements in selID that are less than the inputID. */ unsigned Gdw::chkID(int inputID) { for (unsigned i = 0; i < selID.size(); i++) { if (inputID == selID[i]) return 0; else if (inputID < selID[i]) return i; } return selID.size(); } /* chkSel() makes sure that at least one covariate is selected * before modifying, returns true if positive, otherwise false. */ bool Gdw::chkSel() { if (!covList.size()) { QMessageBox::critical(0, "Error", "No covariate defined yet!"); return false; } if (!selID.size()) { QMessageBox::critical(0, "Error", "No covariate selected yet!"); return false; } return true; } /* chkD() checks the status of D type covariate. * returns true if D type exists and is one of the selected covariates, otherwise false * This function is mainly used for duplicate/delete operation; or when the "modify" * operation not only modifies selected covariate, but also generates new covariate(s) * of the same type based on the selection */ bool Gdw::chkD() { if (d_index == -1) return false; for (int i = 0; i < (int) selID.size(); i++) { if (d_index == selID[i]) return true; } return false; } /* This function checks whether intercept covariate is selected or not */ bool Gdw::chkIntercept() { if (!interceptID.size()) return false; QString col3; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { col3 = it.current()->text(3); if (col3 == "intercept") return true; it++; } return false; } /* updateMod() shows the single modified covariate in upper plot window * and set gUpdateFlag to be true, since G matrix has been changed */ void Gdw::updateMod() { if (selID.size() == 1) emit(newCovLoaded( covList[selID[0]])); setGUpdateFlag(true); } /* Slot for "Edit -> Modify Selection(s) -> Mean center" */ void Gdw::modMean() { if (!chkSel()) return; for (int i = 0; i < (int) selID.size(); i++) covList[selID[i]]->meanCenter(); updateMod(); } /* Slot for "Edit -> Modify Selection(s) -> Mean center non-zero" */ void Gdw::meanNonZero() { if (!chkSel()) return; int varIndex = 0, numNonZero = 0; int length = totalReps * TR / tmpResolve; double nonZeroMean = 0, element = 0; for (int j = 0; j < (int) selID.size(); j++) { varIndex = selID[j]; numNonZero = countNonZero(covList[varIndex]); nonZeroMean = (covList[varIndex])->getVectorSum() / (double) numNonZero; for (int i = 0; i < length; i++) { element = (covList[varIndex])->getElement(i); if (element) (covList[varIndex])->setElement(i, element - nonZeroMean); } } updateMod(); } /* Slot for "Edit -> Modify Selection(s) -> Unit variance" */ void Gdw::unitVar() { if (!chkSel()) return; for (int i = 0; i < (int) selID.size(); i++) covList[selID[i]]->unitVariance(); updateMod(); } /* Slot for "Edit -> Modify Selection(s) -> Unit excursion" */ void Gdw::UnitExcurs() { if (!chkSel()) return; int varIndex; double vecMax = 0, vecMin = 0; for (int i = 0; i < (int) selID.size(); i++) { varIndex = selID[i]; vecMin = (covList[varIndex])->getMinElement(); (*(covList[varIndex]))+=(0 - vecMin); vecMax = (covList[varIndex])->getMaxElement(); (covList[varIndex])->scaleInPlace(1.0 / vecMax); } updateMod(); } /* Slot for "Edit -> Modify Selection(s) -> Convolve" */ void Gdw::modConv() { if (!chkSel()) return; G_Convolve *myConv = new G_Convolve(tmpResolve); myConv->setCaption("Convolve options"); myConv->show(); this->setDisabled(true); QObject::connect(myConv, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myConv, SIGNAL(doneSignal(VB_Vector *, double, QString&)), this, SLOT(showConv(VB_Vector*, double, QString&))); } /* This slot is to show the covariate after convolution */ void Gdw::showConv(VB_Vector *convVector, double sampling, QString &tag) { // update covList array int varIndex; for (int i = 0; i < (int) selID.size(); i++) { varIndex = selID[i]; VB_Vector *tmpVec = covList[varIndex]; covList[varIndex] = new VB_Vector(getConv(tmpVec, convVector, (int) sampling, tmpResolve)); } // update covariate name based on the tag string from convolve interface QString newStr, idStr; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { idStr = it.current()->text(2); if (!idStr.isEmpty() && tag.length() > 0) { newStr = it.current()->text(0) + " (" + tag + ")"; it.current()->setText(0, newStr); } it++; } updateMod(); } /* Slot for "Edit -> Modify Selection(s) -> Exponential" */ void Gdw::modExpn() { if (!chkSel()) return; if (chkD()) { QMessageBox::critical(0,"Error", "Operation not allowed: \

more than one dependent covariate would exist in G matrix after it"); return; } if (chkIntercept()) { QMessageBox::critical(0,"Error", "Operation not permitted on intercept covariate"); return; } G_Expn *myExpn = new G_Expn(); myExpn->setCaption("Exponential Options"); myExpn->show(); this->setDisabled(true); QObject::connect(myExpn, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myExpn, SIGNAL(doneSignal(double, int)), this, SLOT(showExpn(double, int))); } /* showExpn() shows the new exponential covariate */ void Gdw::showExpn(double power, int centerFlag) { int varIndex; double tmpVal, expVal; int vecLength = totalReps * TR / tmpResolve; // Sort selID to make the new index ranking easier sort(selID.begin(), selID.end()); for (int j = 0; j < (int) selID.size(); j++) { varIndex = selID[j]; VB_Vector *newVec = new VB_Vector(vecLength); for (int i = 0; i < vecLength; i++) { tmpVal = (covList[varIndex + j])->getElement(i); expVal = pow(tmpVal, power); newVec->setElement(i, expVal); } if (centerFlag) { newVec->meanCenter(); newVec->unitVariance(); } covList.insert(covList.begin() + varIndex + j + 1, newVec); } // Insert the new covariate right after original one with a modified name QString newStr, idStr; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { idStr = it.current()->text(2); if (!idStr.isEmpty()) { newStr = it.current()->text(0) + " [^" + QString::number(power) + "]"; if (it.current()->parent()) (void) new Q3ListViewItem(it.current()->parent(), it.current(), newStr, it.current()->text(1), "-1"); else (void) new Q3ListViewItem(varListView, it.current(), newStr, it.current()->text(1), "-1"); } it++; } rankID(); updateMod(); } /* rankID() ranks the covariates from the top of the tree to the bottom serially. * Assumption: the covariates are always ranked from small to big in up->down tree view */ void Gdw::rankID() { QString idStr; int counter = 0; Q3ListViewItemIterator it(varListView); while (it.current()) { idStr = it.current()->text(2); if (!idStr.isEmpty()) { it.current()->setText(2, QString::number(counter)); counter++; } it++; } // selID and d_index must be updated now updateSelID(); update_d_index(); } /* updateSelID() keeps selID array updated. This function should be * called after rankID(), when new covariates have been added. */ void Gdw::updateSelID() { selID.clear(); Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); QString idStr; while (it.current()) { idStr = it.current()->text(2); if (idStr.size()) selID.push_back(idStr.toInt()); it++; } } /* update_d_index() keeps d_index updated. This function should be * called after rankID(), when new covariates have been added. */ void Gdw::update_d_index() { if (d_index == -1) return; if (varListView->findItem("D", 1)) d_index = varListView->findItem("D", 1)->text(2).toInt(); } /* Slot for "Edit -> Modify Selection(s) -> Multiply by covar" */ void Gdw::modMult() { if (!chkSel()) return; G_Multiply *myMult = new G_Multiply(varListView); myMult->setCaption("Multiply Options"); myMult->show(); this->setDisabled(true); QObject::connect(myMult, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myMult, SIGNAL(doneSignal(int)), this, SLOT(showMult(int))); } /* Function to show multiplied covariate */ void Gdw::showMult(int selection) { int varIndex; for (int j = 0; j < (int) selID.size(); j++) { varIndex = selID[j]; (covList[varIndex])->elementByElementMult(covList[selection]); } updateMod(); } /* Slot for "Modify Selection(s) -> Derivative(s)" */ void Gdw::modDeriv() { if (!chkSel()) return; if (chkD()) { QMessageBox::critical(0,"Error", "Operation not allowed: \

more than one dependent covariate would exist in G matrix after it"); return; } if (chkIntercept()) { QMessageBox::critical(0,"Error", "Operation not permitted on intercept covariate"); return; } if (totalReps * TR / tmpResolve % 2 != 0) { QMessageBox::critical(0, "Error", "The number of observations must be an even number."); return; } G_Deriv *myDeriv = new G_Deriv(); myDeriv->setCaption("Derivative Options"); myDeriv->show(); this->setDisabled(true); QObject::connect(myDeriv, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myDeriv, SIGNAL(doneSignal(unsigned, int)), this, SLOT(showDeriv(unsigned, int))); } /* This slot will show the derivative covariates for a selected covariate */ void Gdw::showDeriv(unsigned numDeriv, int inputType) { // Sort selID to make the new index ranking easier sort(selID.begin(), selID.end()); int varIndex; for (int j = 0; j < (int) selID.size(); j++) { varIndex = selID[j] + j * numDeriv; for (unsigned i = 0; i < numDeriv; i++) { VB_Vector *currentVec = covList[varIndex]; VB_Vector *newVec = derivative(currentVec); covList.insert(covList.begin() + varIndex + 1, newVec); varIndex++; } } insertDerivGrp(numDeriv, inputType); rankID(); updateMod(); } /* insertDerivGrp() builds a new subgroup based on selected covariate(s) to include * both original and new derivative covariate(s) */ void Gdw::insertDerivGrp(unsigned numDeriv, int inputType) { QString typeStr; if (inputType == 0) typeStr = "I"; else typeStr = "N"; QString newStr, idStr; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { QString orgName = it.current()->text(0); idStr = it.current()->text(2); if (!idStr.isEmpty()) { (void) new Q3ListViewItem(it.current(), it.current()->text(0), it.current()->text(1), it.current()->text(2)); it.current()->setText(0, it.current()->text(0) + " (deriv group)"); it.current()->setText(1, QString::null); it.current()->setText(2, QString::null); for (unsigned i = 0; i < numDeriv; i++) { newStr = orgName + " [ deriv #" + QString::number(i + 1) + " ]"; (void) new Q3ListViewItem(it.current(), getLastChild(it.current()), newStr, typeStr, "-1"); } it.current()->setOpen(true); } it++; } } /* Slot for "Modify Selection(s) -> Fourier set" */ void Gdw::modFS() { if (!chkSel()) return; if (chkD()) { QMessageBox::critical(0,"Error", "Operation not allowed: \

more than one dependent covariate would exist in G matrix after it"); return; } if (chkIntercept()) { QMessageBox::critical(0,"Error", "Operation not permitted on intercept covariate"); return; } double totalTime = (double)(totalReps * TR) / 1000.0; G_Fourier *myFS = new G_Fourier(totalTime); myFS->setCaption("Fourier basis set options"); myFS->show(); this->setDisabled(true); QObject::connect(myFS, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myFS, SIGNAL(doneSignal(int, int, int, int)), this, SLOT(showFS(int, int, int, int))); } /* This function will show the new Fourier set covariate on the display window. */ void Gdw::showFS(int period, int number, int addFlag, int deltaFlag) { fs_set_covList(period, number, addFlag, deltaFlag); fs_set_view(number, addFlag); /* clearSelection() here not only clears current highlighted items, but also emits selectionChanged() * signal, which calls selectionUpdate() to re-select the item and its child(ren). */ varListView->clearSelection(); rankID(); setGUpdateFlag(true); } /* update covList array after new Fourier Set covariates are added */ void Gdw::fs_set_covList(int period, int number, int addFlag, int deltaFlag) { //QObject::disconnect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); // Sort selID to make the new index ranking easier sort(selID.begin(), selID.end()); int windowWidth = period * 1000 / tmpResolve; int numComp = 2 * number + addFlag; int orderG = totalReps * TR / tmpResolve; double pix2 = 2.0 * 3.14159; int varIndex; for (int j = 0; j < (int) selID.size(); j++) { varIndex = selID[j] + j * (numComp - 1); VB_Vector *currentVec = new VB_Vector(covList[varIndex]); if (addFlag) { insertCovDC(windowWidth, varIndex, deltaFlag); varIndex++; } else covList.erase(covList.begin() + varIndex); VB_Vector *fourierVec = new VB_Vector(orderG); for (int i = 1; i <= number; i++) { fourierVec->setAll(0); for (int k = 0; k < windowWidth; k++) (*fourierVec)[k] = sin(pix2 * k / windowWidth * i); VB_Vector *newVec = fs_getFFT(currentVec, fourierVec, deltaFlag); covList.insert(covList.begin() + varIndex, newVec); for (int k = 0; k < windowWidth; k++) (*fourierVec)[k] = cos(pix2 * k / windowWidth * i); VB_Vector *newVec2 = fs_getFFT(currentVec, fourierVec, deltaFlag); covList.insert(covList.begin() + varIndex + 1, newVec2); varIndex += 2; } delete currentVec; delete fourierVec; } //QObject::connect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); } /* insertCovDC() inserts the DC covariate in covList array */ void Gdw::insertCovDC(int windowWidth, int varIndex, int deltaFlag) { int orderG = totalReps * TR / tmpResolve; VB_Vector *fourierVec = new VB_Vector(orderG); fourierVec->setAll(0); for (int j = 0; j < windowWidth; j++) fourierVec->setElement(j, 1.0); VB_Vector *currentVec = new VB_Vector(covList[varIndex]); VB_Vector *newVec = fs_getFFT(currentVec, fourierVec, deltaFlag); delete currentVec; delete fourierVec; covList.at(varIndex) = newVec; } /* fs_getFFT() returns the new sin/cos vb_vector */ VB_Vector * Gdw::fs_getFFT(VB_Vector *currentVec, VB_Vector *fourierVec, int deltaFlag) { if (deltaFlag) calcDelta(currentVec); VB_Vector *newVec = new VB_Vector(fftConv(currentVec, fourierVec, false)); newVec->meanCenter(); newVec->unitVariance(); return newVec; } /* Update varListView for new Fourier Set covariates * This step could be done at the same time when covList is updated, * but that makes debugging more difficult */ void Gdw::fs_set_view(int number, int addFlag) { Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); QString orgName, orgType, orgID; while (it.current()) { orgID = it.current()->text(2); if (!orgID.isEmpty()) { orgName = it.current()->text(0); orgType = it.current()->text(1); it.current()->setText(0, orgName + " (FS group)"); it.current()->setText(1, QString::null); it.current()->setText(2, QString::null); if (addFlag) (void) new Q3ListViewItem(it.current(), orgName + " [DC]", orgType, orgID); QString nameStr; for (int i = 1; i <= number; i++) { nameStr = orgName + " [sin #" + QString::number(i) + "]"; (void) new Q3ListViewItem(it.current(), getLastChild(it.current()), nameStr, orgType, orgID); nameStr = orgName + " [cos #" + QString::number(i) + "]"; (void) new Q3ListViewItem(it.current(), getLastChild(it.current()), nameStr, orgType, orgID); } it.current()->setOpen(true); } ++it; } } /* Slot for "Modify Selection(s) -> Eigenvector set" */ void Gdw::modES() { if (!chkSel()) return; if (chkD()) { QMessageBox::critical(0,"Error", "Operation not allowed: \

more than one dependent covariate would exist in G matrix after it"); return; } if (chkIntercept()) { QMessageBox::critical(0,"Error", "Operation not permitted on intercept covariate"); return; } es_set_covList(); es_set_view(); /* clearSelection() here not only clears current highlighted items, but also emits selectionChanged() * signal, which calls selectionUpdate() to re-select the item and its child(ren). */ varListView->clearSelection(); rankID(); setGUpdateFlag(true); } /* update covList for new eigenvector set covariates */ void Gdw::es_set_covList() { int orderG = totalReps * TR / tmpResolve; double magFactor = 2000.0 / (double) tmpResolve; if (magFactor != floor(magFactor)) { QMessageBox::critical(0, "Error", "Invalid upsampling rate!"); return; } VB_Vector *eigenVec1 = new VB_Vector(orderG); eigenVec1->setAll(0); VB_Vector *eigenVec2 = new VB_Vector(orderG); eigenVec2->setAll(0); VB_Vector *eigenVec3 = new VB_Vector(orderG); eigenVec3->setAll(0); VB_Vector *tmpVec1 = new VB_Vector((string)filterPath.latin1() + "Eigen1.ref"); tmpVec1->sincInterpolation((unsigned)magFactor); VB_Vector *tmpVec2 = new VB_Vector((string)filterPath.latin1() + "Eigen2.ref"); tmpVec2->sincInterpolation((unsigned)magFactor); VB_Vector *tmpVec3 = new VB_Vector((string)filterPath.latin1() + "Eigen3.ref"); tmpVec3->sincInterpolation((unsigned)magFactor); int vecLength = tmpVec1->getLength(); for (int i = 0; i < vecLength; i++) { (*eigenVec1)[i] = (*tmpVec1)[i]; (*eigenVec2)[i] = (*tmpVec2)[i]; (*eigenVec3)[i] = (*tmpVec3)[i]; } // Sort selID to make the new index ranking easier sort(selID.begin(), selID.end()); // Modify selected covariates one by one int varIndex; for (int j = 0; j < (int)selID.size(); j++) { varIndex = selID[j] + 2 * j; VB_Vector *myVec = covList[varIndex]; calcDelta(myVec); VB_Vector *newVec1 = new VB_Vector(fftConv(myVec, eigenVec1, false)); VB_Vector *newVec2 = new VB_Vector(fftConv(myVec, eigenVec2, false)); VB_Vector *newVec3 = new VB_Vector(fftConv(myVec, eigenVec3, false)); covList.at(varIndex) = newVec1; covList.insert(covList.begin() + varIndex + 1, newVec2); covList.insert(covList.begin() + varIndex + 2, newVec3); delete myVec; } delete tmpVec1; delete tmpVec2; delete tmpVec3; delete eigenVec1; delete eigenVec2; delete eigenVec3; } /* update varListView after adding eigenvector set covariates */ void Gdw::es_set_view() { QString orgName, orgType, orgID; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { orgID = it.current()->text(2); if (!orgID.isEmpty()) { orgName = it.current()->text(0); orgType = it.current()->text(1); it.current()->setText(0, orgName + " (eigen group)"); it.current()->setText(1, QString::null); it.current()->setText(2, QString::null); (void) new Q3ListViewItem(it.current(), orgName + " [Eigen1]", orgType, orgID); (void) new Q3ListViewItem(it.current(), getLastChild(it.current()), orgName + " [Eigen2]", orgType, orgID); (void) new Q3ListViewItem(it.current(), getLastChild(it.current()), orgName + " [Eigen3]", orgType, orgID); it.current()->setOpen(true); } it++; } } /* Slot for "Modify Selection(s) -> Time shift" */ void Gdw::modTS() { // Make sure selection exists if (!chkSel()) return; // Make sure input value is valid bool ok; int msecShift = QInputDialog::getInteger("Time Shift Option", "Please type in time shift value in unit of ms.
\ Positive values lag right.", 0, -2147483647, 2147483647, 1, &ok); if (!ok || !msecShift) return; // Update covList int varIndex; double imageShift; for (int i = 0; i < (int) selID.size(); i++) { varIndex = selID[i]; imageShift = (double) msecShift / (double) tmpResolve; (covList[varIndex])->phaseShift(imageShift); } // Update treeview Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); QString orgName, orgID, newLabel; while (it.current()) { orgID = it.current()->text(2); if (!orgID.isEmpty()) { newLabel = it.current()->text(0) + " [shift " + QString::number(msecShift) + "]"; it.current()->setText(0, newLabel); } it++; } updateMod(); } /* Slot for "Modify Selection(s) -> Orthogonalize" */ void Gdw::modOrth() { if (!chkOrth()) return; G_Orth *myOrth = new G_Orth(varListView); myOrth->setCaption("Orthogonalize Options"); myOrth->show(); this->setDisabled(true); QObject::connect(myOrth, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myOrth, SIGNAL(doneSignal(std::vector)), this, SLOT(showOrth(std::vector))); } /* chkOrth() makes sure there are at least one covariate which is not selected */ bool Gdw::chkOrth() { if (!chkSel()) return false; if (covList.size() == 1) { QMessageBox::critical(0, "Error", "Orthogonalization not allowed with only one covariate!"); return false; } if (covList.size() == selID.size()) { QMessageBox::critical(0, "Error", "At least one independent covariate should be unselected for \ orthogonalization!"); return false; } if (chkD()) { QMessageBox::critical(0,"Error", "Orthogonalization operation not allowed on dependent covariate"); return false; } if (chkIntercept()) { QMessageBox::critical(0,"Error", "Operation not permitted on intercept covariate"); return false; } if (d_index != -1 && covList.size() - selID.size() == 1) { QMessageBox::critical(0, "Error", "At least one independent covariate should be unselected for \ orthogonalization operation!"); return false; } return true; } /* Show orthogonalized covariate */ void Gdw::showOrth(std::vector orthID) { // Build subG that consists of covariates defined by orthID int rowNum = totalReps * TR / tmpResolve; int colNum = orthID.size(); VBMatrix subG(rowNum, colNum); VB_Vector tmpVec; for (int i = 0; i < colNum; i++) { tmpVec = *covList[orthID[i]]; subG.SetColumn(i, tmpVec); } // Modify selected covariates one by one by subtracting fits int varIndex; for (int i = 0; i < (int) selID.size(); i++) { varIndex = selID[i]; VB_Vector orthVec=calcfits(subG,*covList[varIndex]); if (orthVec.size()<1) { QMessageBox::critical(0, "Error", "Non-dependent covariates are linearly dependent, invalid Orthogonalization!"); return; } (*(covList[varIndex]))-=orthVec; } updateMod(); } /* Slot for "Modify Selection(s) -> Convert to delta" */ void Gdw::modC2D() { if (!chkSel()) return; int varIndex; for (int i = 0; i < (int) selID.size(); i++) { varIndex = selID[i]; calcDelta(covList[varIndex]); } updateMod(); } /* Modify Selection(s) -> Finite Impulse Response */ void Gdw::modFIR() { if (!chkSel()) return; if (chkD()) { QMessageBox::critical(0,"Error", "Operation not allowed: \

more than one dependent covariate would exist in G matrix after it"); return; } if (chkIntercept()) { QMessageBox::critical(0,"Error", "Operation not permitted on intercept covariate"); return; } // Ask user to type in a input value as number of TRs bool ok; int numTR = QInputDialog::getInteger("Set Finite Impulse Response", "Please type in the number of TRs used in finite inpulse response", 0, 0, totalReps, 1, &ok); // Make sure the input value is valid if (!ok || !numTR) return; fir_set_covList(numTR); fir_set_view(numTR); /* clearSelection() here not only clears current highlighted items, but also emits selectionChanged() * signal, which calls selectionUpdate() to re-select the item and its child(ren). */ varListView->clearSelection(); rankID(); setGUpdateFlag(true); } /* Put new FIR covariate(s) into covList */ void Gdw::fir_set_covList(int numTR) { int varIndex; double timeShift; // Sort selID to make the new index ranking easier sort(selID.begin(), selID.end()); for (int i = 0; i < (int) selID.size(); i++) { varIndex = selID[i] + i * numTR; // First convert the highlighted covariates to delta calcDelta(covList[varIndex]); // Generate equal number of time-shifted covariates based on the selected one for (int j = 1; j <= numTR; j++) { VB_Vector *newVec = new VB_Vector(); timeShift = (double) j * TR / tmpResolve; covList[varIndex]->phaseShift(timeShift, *newVec); covList.insert(covList.begin() + varIndex + j, newVec); } } } /* Update varListView after FIR covariates are added */ void Gdw::fir_set_view(int numTR) { QString orgName, orgType, orgID, newLabel; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); while (it.current()) { orgID = it.current()->text(2); if (!orgID.isEmpty()) { orgName = it.current()->text(0); orgType = it.current()->text(1); it.current()->setText(0, orgName + " (FIR group)"); it.current()->setText(1, QString::null); it.current()->setText(2, QString::null); (void) new Q3ListViewItem(it.current(), orgName + " [FIR0]", orgType, orgID); for (int i = 1; i <= numTR; i++) { newLabel = orgName + " [FIR" + QString::number(i) + "]"; (void) new Q3ListViewItem(it.current(), getLastChild(it.current()), newLabel, orgType, orgID); } it.current()->setOpen(true); } it++; } } /* Slot for "Evaluate -> Colinearity with all" */ void Gdw::colAll() { if (!chkColinear()) return; getColinear(0); } /* Slot for "Evaluate -> Colinearity with interest" */ void Gdw::col_I() { if (!chkColinear()) return; getColinear(1); } /* Slot for "Evaluate -> Colinearity with no interest" */ void Gdw::col_N() { if (!chkColinear()) return; getColinear(2); } /* chkColinear() makes sure there are at least two covariates defined and only one is selected */ bool Gdw::chkColinear() { if (d_index == -1 && covList.size() < 2) { QMessageBox::critical(0, "Error", "At least two independent covariates are required for colinearity evaluation!"); return false; } if (d_index != -1 && covList.size() < 3) { QMessageBox::critical(0, "Error", "At least two independent covariates are required for colinearity evaluation!"); return false; } if (selID.size() != 1) { QMessageBox::critical(0, "Error", "Please select one and only one covariate for colinearity evaluation!"); return false; } if (selID[0] == d_index) { QMessageBox::critical(0, "Error", "Type D covariate can not be selected to evaluate colinearity!"); return false; } return true; } /* getColinear() is a generic functions to show colinear values. * It accepts an integer value as the covariate category: * 0: all covariates * 1: all of intrerest ("I") * 2: all of no interest (includes both "N" and "K") */ void Gdw::getColinear(unsigned colType) { if (colType > 2) { QMessageBox::critical(0, "Error", "getColinear(): Invalid covariate type"); return; } int selIndex = selID[0]; if (!(covList[selIndex])->getVariance()) { QMessageBox::critical(0, "Error", "Selected covariate is a constant. Can not evaluate colinearity."); return; } std::vector colList = findColID(colType); QString helpStr; if (colType == 0) helpStr = "[ I/N/K ]"; else if (colType == 1) helpStr = "of interest type [ I ]"; else helpStr = "of no interest type [ N/K ]"; if (!colList.size()) { QMessageBox::critical(0, "Error", "Other independent covariates " + helpStr + " not found."); return; } int rowNum = totalReps, colNum = colList.size(); int ratio = TR / tmpResolve; VB_Vector currentVec = *downSampling(covList[selIndex], ratio); VBMatrix subA(rowNum, colNum); VB_Vector tmpVec; int j = 0; for (int i = 0; i < (int) colList.size(); i++) { j = colList[i]; tmpVec = *downSampling(covList[j], ratio); subA.SetColumn(i, tmpVec); } double colVal = calcColinear(subA, currentVec); if (colVal < 0) { QMessageBox::information(0, "Colinearity Info", "Invalid colinearity value"); return; } QMessageBox::information(0, "Colinearity Info", "The colinearity between the selected \ covariate and all the other independent covariates " + helpStr + " is " + QString::number(colVal) + ".

This value is the correlation between the covariate and the best linear \ combination of the other independent variables. \

Note that this is calculated prior to any exogenous smoothing that might be applied."); } /* findColID() returns an array of integers that is the index of colinearity covariate(s). * It accepts two arguments: the first is the index of the currently selected covariate. * This index will be skipped. The second is type of colinearity covariate. */ std::vector Gdw::findColID(int colType) { std::vector colList; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Unselected); QString idStr, typeStr; while (it.current()) { typeStr = it.current()->text(1); idStr = it.current()->text(2); if (colType == 0 && idStr.length() && typeStr != "D") colList.push_back(idStr.toInt()); else if (colType == 1 && idStr.length() && typeStr == "I") colList.push_back(idStr.toInt()); else if (colType == 2 && idStr.length() && (typeStr == "N" || typeStr == "K")) colList.push_back(idStr.toInt()); ++it; } return colList; } /* Slot for "Evaluate -> Linear dependence of all" */ void Gdw::a_LD() { if (!chkLD()) return; showLD(0); } /* Slot for "Evaluate -> Linear dependence of interest" */ void Gdw::i_LD() { if (!chkLD()) return; showLD(1); } /* Slot for "Evaluate -> Linear dependence of non-interest" */ void Gdw::nk_LD() { if (!chkLD()) return; showLD(2); } /* Slot for "Evaluate -> Linear dependence of selected" */ void Gdw::sel_LD() { if (!chkLD()) return; if (!selID.size()) { QMessageBox::critical(0, "Error", "No covariate selected yet."); return; } if (chkD()) { QMessageBox::critical(0, "Error", "Please deselect type D cocariate before checking linear dependence."); return; } if (selID.size() == 1) { QMessageBox::critical(0, "Error", "Invalid operation:
\ only one independent covariate available for linear dependence check"); return; } showLD(3); } /* showLD() calculates determinant of the matrix based on the input covariate type */ void Gdw::showLD(int ldType) { std::vector ldList = find_LD_ID(ldType); QString helpStr; if (ldType == 0) helpStr = "[ I/N/K ]"; else if (ldType == 1) helpStr = "of interest [ I ]"; else if (ldType == 2) helpStr = "of no interest [ N/K ]"; else helpStr = "that are selected"; if (!ldList.size()) { QMessageBox::critical(0, "Error", "No independent covariate " + helpStr + " found."); return; } if (ldList.size() == 1) { QMessageBox::critical(0, "Error", "Invalid operation:
only one independent covariate " + helpStr + " available for linear dependence check"); return; } double gDeterm = ldDeterm(ldList); QString tmpStr = "determinant = " + QString::number(gDeterm); if (gDeterm == 0) QMessageBox::information(0, "Info", tmpStr + "

The covariates " + helpStr + " ARE linearly dependent!"); else if (gDeterm < 0.000001) QMessageBox::information(0, "Info", tmpStr + "

The covariates " + helpStr + " are CLOSE to linear dependence."); else QMessageBox::information(0, "Info", tmpStr + "

The covariates " + helpStr + " are NOT linearly dependent."); } /* chkLD() checks the G matrix status before calculating determinant. * Returns true if it passws, false otherwise */ bool Gdw::chkLD() { // No covariates defined at all if (!covList.size()) { QMessageBox::critical(0, "Error", "No independent covariates found."); return false; } // Only one covariate is defined and it is type D if (d_index != -1 && covList.size() == 1) { QMessageBox::critical(0, "Error", "No independent covariates found."); return false; } // Only one independent covariate if (d_index == -1 && covList.size() == 1) { QMessageBox::critical(0, "Error", "Invalid operation:
\ only one independent covariate available for linear dependence check"); return false; } // Only one independent covariate if (d_index != -1 && covList.size() == 2) { QMessageBox::critical(0, "Error", "Invalid operation:
\ only one independent covariate available for linear dependence check"); return false; } // Pass! return true; } /* find_LD_ID() accepts an integer to label the covariate type and * returns the covariate index that matches the type. * 0: I/N/K 1: I 2: N/K 3: selected covariates */ std::vector Gdw::find_LD_ID(int ldType) { std::vector ldList; if (ldType == 0) { for (int i = 0; i < (int)covList.size(); i++) { if (i != d_index) ldList.push_back(i); } return ldList; } if (ldType == 3) return selID; Q3ListViewItemIterator it(varListView); QString idStr, typeStr; while (it.current()) { typeStr = it.current()->text(1); idStr = it.current()->text(2); if (ldType == 1 && idStr.length() && typeStr == "I") ldList.push_back(idStr.toInt()); else if (ldType == 2 && idStr.length() && (typeStr == "N" || typeStr == "K")) ldList.push_back(idStr.toInt()); ++it; } return ldList; } /* This function calculates the determinant of the downsampled G matrix */ double Gdw::ldDeterm(std::vector ldList) { int downRatio = TR / tmpResolve; int colNum = ldList.size(); VBMatrix downG(totalReps, colNum); VB_Vector tmpVec; int j = 0; for (int i = 0; i < colNum; i++) { j = ldList[i]; tmpVec = *downSampling(covList[j], downRatio); downG.SetColumn(i, tmpVec); } return getDeterm(downG); } /* Slot for "Evaluate -> Mean and SD" */ void Gdw::meanSD() { if (!covList.size()) { QMessageBox::critical(0, "Error", "No covariate defined yet!"); return; } if (!selID.size()) { QMessageBox::critical(0, "Error", "No covariate selected yet!"); return; } int myIndex; VB_Vector myVec; double vecMean = 0, vecSD = 0; QString helpStr = ""; for (int i = 0 ; i < (int) selID.size(); i++) { myIndex = selID[i]; myVec =*downSampling(covList[myIndex], TR / tmpResolve); vecMean = myVec.getVectorMean(); vecSD = sqrt(myVec.getVariance()); helpStr += QString("Covariate #%1:
Mean = %2, SD = %3

").arg(i).arg(vecMean).arg(vecSD); } QMessageBox::information(0, "Information", helpStr); } /* Slot for "Evaluate -> Efficiency" */ void Gdw::efficiency() { if (covList.size() < 2) { QMessageBox::critical(0, "Error", "At least two covariates are required to evaluate efficiency!"); return; } G_Eff *myEff = new G_Eff(varListView, covList, TR, totalReps, tmpResolve); myEff->setCaption("Check Efficiency"); myEff->show(); this->setDisabled(true); myEff->setFocus(); QObject::connect(myEff, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); QObject::connect(myEff, SIGNAL(delSignal(std::vector)), this, SLOT(showEff(std::vector))); } /* Function to show the new G matrix after efficiency evaluation */ void Gdw::showEff(std::vector delList) { // If all covariates will be deleted, call delAll() if (delList.size() == covList.size()) { delAll(); return; } // Ignore selection change signal first QObject::disconnect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); // If only some of the covaraites will be deleted, remove them from covList first for (int i = 0; i < (int) delList.size(); i++) covList.erase(covList.begin() + delList[i] - i); // Sort selection ID sort(selID.begin(), selID.end()); std::vector surviver = findDiff(delList); // If some (not all) of the selected covariates will be kept, clear all selection now if (surviver.size() < selID.size()) varListView->clearSelection(); // Delete items in delList for (int i = 0; i < (int) delList.size(); i++) delete varListView->findItem(QString::number(delList[i]), 2); // Reselect survived items if (surviver.size() && surviver.size() < selID.size()) for (int i = 0; i < (int) surviver.size(); i++) (varListView->findItem(QString::number(delList[i]), 2))->setSelected(true); // All selected items are deleted, update upperWindow else if (!surviver.size()) { timeVector = fftVector= 0; typeCombo->setCurrentItem(4); upperWindow->clear(); upperWindow->update(); } // Update ID field rankID(); QObject::connect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); setGUpdateFlag(true); // update intercept status updateInterceptID(); } /* chkElement() checks if the index of D type covariate is one of the members in delList array. * returns true if element exists and is one of the selected covariates, otherwise false. * THis function is written specially for efficiency evaluation */ bool Gdw::chkElement(int inElement, std::vector inList) { int inSize = inList.size(); if (inElement < inList[0] || inElement > inList[inSize - 1]) return false; for (int i = 0; i < inSize; i++) { if (inElement == inList[i]) return true; } return false; } /* findDiff() compares selID and delList and put the elements which are in selID but not in * inList into diffList. diffList is returned. */ std::vector Gdw::findDiff(std::vector inList) { int j; std::vector diffList; for (int i = 0; i < (int) selID.size(); i++) { j = selID[i]; if (!chkElement(j, inList)) diffList.push_back(j); } return diffList; } /* Slot for "Evaluate -> Noise spectra" */ void Gdw::evalNoise() { if (!chkNoise()) return; VB_Vector *psVec = getPSVec(); if (!psVec) { QMessageBox::warning(0, "Error!", "No power spectrum vector found."); return; } double var3min = (-1.0) / (totalReps * TR / 1000.0); VB_Vector *fitParams = new VB_Vector(8); fitParams = fitOneOverF(psVec, var3min, (double)TR); if (fitParams->getElement(0) != 1.0) { QMessageBox::critical(0, "Error", "Fitting not successful. No noise model defined."); return; } double var1 = fitParams->getElement(2); double var2 = fitParams->getElement(3); double var3 = fitParams->getElement(4); VB_Vector *noiseVec1= makeOneOverF(totalReps, var1, var2, var3, (double)TR); VB_Vector *noiseVec2 = new VB_Vector(totalReps / 2 + 1); for (int i = 0; i < totalReps / 2 + 1; i++) noiseVec2->setElement(i, noiseVec1->getElement(i)); delete noiseVec1; double minElement = noiseVec2->getMinElement(); (*noiseVec2)+=(minElement * (-2)); double maxElement = noiseVec2->getMaxElement(); noiseVec2->scaleInPlace(1.0 / maxElement); int varIndex = selID[0]; VB_Vector *currentVec = downSampling(covList[varIndex], TR / tmpResolve); currentVec->getPS(); VB_Vector *halfVec = new VB_Vector(currentVec->getLength() / 2); for (int i = 0; i < (int) currentVec->getLength() / 2; i++) (*halfVec)[i] = (*currentVec)[i]; delete currentVec; double vecMax = halfVec->getMaxElement(); halfVec->scaleInPlace(1.0 / vecMax); PlotScreen *noiseWindow = new PlotScreen(); noiseWindow->setCaption("Noise Spectra Evaluation"); noiseWindow->setPlotMode(1); noiseWindow->setFirstVector(halfVec); QColor noiseColor = Qt::red; noiseWindow->addVector(noiseVec2, noiseColor); noiseWindow->setXCaption("Freq (Number)"); noiseWindow->setYCaption("Magnitude"); noiseWindow->update(); noiseWindow->show(); } /* chkNoise() makes sure there is only one covariate selected now */ bool Gdw::chkNoise() { if (!covList.size()) { QMessageBox::critical(0, "Error", "No covariates defined yet."); return false; } if (!selID.size()) { QMessageBox::critical(0, "Error", "No covariates selected yet."); return false; } if (selID.size() > 1) { QMessageBox::critical(0, "Error", "Please select one and only one covariate."); return false; } return true; } /* getPSVec() is a function written specially for noise evaluation. * It calculates the power spectrum based on either the tes files * selected in previous step or user's input file. * If it is combo mode and _PS.ref files are all available and have same length, * average them and return the final result. Otherwise ask user to choose one file */ VB_Vector * Gdw::getPSVec() { if (mode == COMBO && chkPSstat()) { QString tesFileName = tesList->item(0)->text(); const char *psFileName; psFileName = tesFileName.replace(tesFileName.length() - 4, 4, "_PS.ref"); VB_Vector *psVector = new VB_Vector(psFileName); unsigned psLength = psVector->getLength(); int psNum = 1; for (int i = 1; i < tesNum; i++) { tesFileName = tesList->item(i)->text(); const char *psFileName = tesFileName.replace(tesFileName.length() - 4, 4, "_PS.ref").ascii(); VB_Vector *tmpVector = new VB_Vector(psFileName); if (psLength != tmpVector->getLength()) break; (*psVector)+=tmpVector; psNum++; } if (psNum == tesNum) { psVector->scaleInPlace(1.0 / (double)psNum); return psVector; } delete psVector; } // If it is SINGLE mode, or _PS.ref files not found in combo mode, or found but not same length QString psFilename = Q3FileDialog::getOpenFileName(QString::null, "G matrix files (*_PS.ref)", this, "Open a power spectrum file", "Choose a *_PS.ref file"); if (psFilename.isEmpty()) return 0; VB_Vector *tmpVector = new VB_Vector(); if (tmpVector->ReadFile(psFilename.ascii()) == 0) return tmpVector; return 0; } /* Slot for "Tools -> Load condition function", wrapper of loadCondFunct(string) */ void Gdw::loadCondFunct() { // Open a FileDialog window to select ref file QString inputString = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load condition function", "Please choose the condition function."); if (inputString.isEmpty()) return; loadCondFunct(inputString); } /* A generic function which reads the input filename as condition function name */ void Gdw::loadCondFunct(QString &tmpString) { if (!chkCondition(tmpString.ascii())) return; condRef = tmpString; // Now delete the original conditional keys in the listbox keyList->clear(); // Add keys into the condition key listbox for (size_t m = 0; m < condKey.size(); m++) { QString keyString = QString(condKey(m)); keyList->insertItem(keyString); } keyList->setCurrentItem(0); setGUpdateFlag(true); } /* chkCondition() checks the condition function file. * Returns true if all parameters are good, otherwise false. */ bool Gdw::chkCondition(const char *condFile) { condKey.clear(); condVector = new VB_Vector(); int refStat = getCondVec(condFile, condKey, condVector); if (refStat == -1) { // Quit if the file isn't readable QMessageBox::critical(0, "Condition Function Error!", "File not readable: " + QString(condFile)); return false; } else if (refStat == -2) { QMessageBox::critical(0, "Condition Function Error!", "Different number of keys in header and content: " \ + QString(condFile)); return false; } else if (refStat == 1) { QMessageBox::critical(0, "Condition Function Error!", "Different keys in header and content: " + QString(condFile)); return false; } int condLength = condVector->getLength(); if (!totalReps) { totalReps = condLength; numberString->setText(QString::number(totalReps)); } // Make sure the number of elements in condition function is a multiple of total time points else if (condLength % totalReps != 0) { QMessageBox::critical(0, "Error!", "Number of elements in condition function must be a multiple of \ total number of time points."); condKey.clear(); condVector = 0; return false; } // Make sure condition function can be upsampled if ((TR / tmpResolve) % (condLength / totalReps) != 0) { QString helpStr; if (TR % (condLength / totalReps) == 0) { int maxSamp = TR / (condLength / totalReps); helpStr = "Condition function can not be upsampled with the current sampling rate.\

Click Tools to reset the upsampling rate. \

Recommended value: " + QString::number(maxSamp) + "/N (N is positive integer)"; } else helpStr = "Invalid condition function: can not be upsampled with the current sampling rate."; QMessageBox::critical(0, "Error!", helpStr); condKey.clear(); condVector = 0; return false; } return true; } /* Slot for "Tools -> Load condition labels" * If the number of lines in condition label file is more than that of the keys in original * condition function, warn the user of possible error and let him/her decide whether to continue; * If the first number is less than the second, report an error and quit; otherwise preceed without * any complaints. */ void Gdw::loadCondLabel() { if (!condVector) { QMessageBox::critical(0, "Error!", "Condition function not defined yet."); return; } tokenlist newCondKey; QString tmpString = Q3FileDialog::getOpenFileName (QString::null, "Condition label files (*.txt)", this, "Load condition function", "Please choose the new condition label file."); if (tmpString.isEmpty()) return; const char *tmpStr2 = tmpString; int readFlag = getCondLabel(newCondKey, tmpStr2); // Quit if the file chosen isn't readable if (readFlag == -1) { QMessageBox::critical(0, "Error!", "The file you choose isn't readable, \ please change its permission or try another file."); return; } unsigned int keyNum = newCondKey.size(); if (keyNum > keyList->count()) { switch(QMessageBox::warning(0, "Warning!", "The file you choose contains more condition \ keys than you need for the current condition function.

Click continue to use the first " + QString::number(keyList->count()) + " keys in this file.

Click Cancel to go back \ and load another condition label file.", "Continue", "Cancel", 0, 0, 1)) { case 0: for (unsigned int i = 0; i < keyList->count(); i++) { QString newKey = QString(newCondKey(i)); keyList->changeItem(newKey, i); condKey[i] = newCondKey[i]; } setGUpdateFlag(true); break; case 1: break; } } else if (keyNum == keyList->count()) { for (unsigned int i = 0; i < keyList->count(); i++) { QString newKey = QString(newCondKey(i)); keyList->changeItem(newKey, i); condKey[i] = newCondKey[i]; } setGUpdateFlag(true); } else QMessageBox::critical(0, "Error!", "The number of condition keys in this file \ is less than that required by the condition function.

Please choose another condition label file."); } /* Slot for "Tools -> Save condition labels" */ void Gdw::saveCondLabel() { if (keyList->count() == 0) { QMessageBox::information(0, "Error", "No condition keys found."); return; } QString labelFile = Q3FileDialog::getSaveFileName(QString::null, tr("TXT files (*.txt);;All files (*)"), this, "Save Condition Labels", "Choose a filename to save condition labels under: "); if (labelFile.isEmpty()) return; QFileInfo *labFileInfo = new QFileInfo(labelFile); QString pathString = labFileInfo->dirPath(true); QFileInfo *labFilePath = new QFileInfo(pathString); if (labFileInfo->exists()) { switch(QMessageBox::warning(0, "Warning!", labelFile + " already exists. Are you sure you want to overwrite \ this file now?", "Yes", "No", "Cancel", 0, 2)) { case 0: // "Yes" overwrites the file if (labFilePath->isWritable()) { writeLabFile(labelFile); } else QMessageBox::critical(0, "Error!", "Not permitted to write file in this directory: " + pathString); break; case 1: // "No" does nothing break; case 2: // "Cancel" closes the function break; return; } } else if (labFilePath->isWritable()) writeLabFile(labelFile); else QMessageBox::critical(0, "Error!", "Not permitted to write file in this directory: " + pathString); } /* setUpsampling() will reset the upsampling rate (tmpResolve) */ void Gdw::setUpsampling() { bool ok; int newSampling = QInputDialog::getInteger("Enter New upsampling rate", "Please enter the new upsampling rate (ms)", tmpResolve, 0, 2147483647, 1, &ok); if (!ok) return; if (newSampling != tmpResolve && TR % newSampling == 0) { reInit(true); tmpResolve = newSampling; if (TR) upperWindow->setRatio(TR / tmpResolve); upperWindow->update(); samplingStr->setText(QString::number(tmpResolve)); } else if (TR % newSampling != 0) { QMessageBox::critical(0, "Error!", "Invalid value. TR must be multiple of the new sampling rate."); return; } } /* writeLabFile() will generate a condition label file with the name of input QString */ void Gdw::writeLabFile(QString &inputFile) { const char *filename = inputFile.ascii(); FILE *condLabFile; condLabFile = fopen(filename, "w"); fprintf(condLabFile, ";VB98\n"); fprintf(condLabFile, ";TXT1\n\n"); const char *tmpString; for (unsigned i = 0; i < keyList->count(); i++) { tmpString = keyList->text(i); fprintf(condLabFile, tmpString); fprintf(condLabFile, "\n"); } fclose(condLabFile); } /* Slot for "Tools -> Save covariate as ref" */ void Gdw::saveCov2Ref() { if (!covList.size()) { QMessageBox::critical(0, "Error", "No covariate defined yet"); return; } if (selID.size() != 1) { QMessageBox::critical(0, "Error", "Please select one and only one covariate"); return; } QString covFile = Q3FileDialog::getSaveFileName(QString::null, tr("REF files (*.ref);;All files (*)"), this, "Save Single Covariate", \ "Choose a filename to save selecteded covariate under: "); if (covFile.isEmpty()) return; QFileInfo *covFileInfo = new QFileInfo(covFile); QString pathString = covFileInfo->dirPath(true); QFileInfo *covFilePath = new QFileInfo(pathString); if (covFileInfo->exists()) { switch(QMessageBox::warning(0, "Warning!", covFile + " already exists. Are you sure you want to overwrite \ this file now?", "Yes", "No", "Cancel", 0, 2)) { case 0: // "Yes" overwrites the file if (covFilePath->isWritable()) { writeCovFile(covFile); } else QMessageBox::critical(0, "Error!", "Not permitted to write file in this directory: " + pathString); break; case 1: // "No" does nothing break; case 2: // "Cancel" closes the function break; return; } } else if (covFilePath->isWritable()) writeCovFile(covFile); else QMessageBox::critical(0, "Error!", "Not permitted to write file in this directory: " + pathString); } /* This function generates a REF file based on currently highlighted covariate. * The new file's name is the input string. */ void Gdw::writeCovFile(QString &inputName) { const char *filename = inputName; int selIndex = selID[0]; QString selName = getCovName(varListView->findItem(QString::number(selIndex), 2)); QString selLine = ";; Name: " + selName + "\n"; FILE *covFile; covFile = fopen(filename, "w"); fprintf(covFile, ";VB98\n"); fprintf(covFile, ";REF1\n"); fprintf(covFile, ";\n"); fprintf(covFile, ";; Single covariate from G matrix\n"); fprintf(covFile, selLine.ascii()); fprintf(covFile, ";\n"); char numLine[100]; VB_Vector *downVec = downSampling(covList[selIndex], TR / tmpResolve); for (unsigned i = 0; i < downVec->getLength(); i++) { sprintf(numLine, "%f\n", downVec->getElement(i)); fprintf(covFile, numLine); } fclose(covFile); delete downVec; } /* Slot when "Secs" is chosen */ void Gdw::secClicked() { if (secFlag) return; if (selID.size() != 1) { secFlag = 1; return; } if (fftFlag) { upperWindow->setAllNewX(0, 1000.0 / (2.0 * TR)); upperWindow->setXCaption("Freq (Hz)"); } else { if (upperWindow->getFirstPlotMode() % 2 == 1) upperWindow->setFirstXLength((totalReps - 1) * TR / 1000.0); else upperWindow->setFirstXLength(totalReps * TR / 1000.0); upperWindow->setXCaption("Time (Sec)"); } upperWindow->update(); secFlag = 1; } /* Slot when "TRs" is chosen */ void Gdw::TRClicked() { if (!secFlag) return; if (selID.size() != 1) { secFlag = 0; return; } if (fftFlag) { upperWindow->setAllNewX(0, (double) totalReps / 2.0); upperWindow->setXCaption("Freq (Number)"); } else { if (upperWindow->getFirstPlotMode() % 2 == 1) upperWindow->setAllNewX(0, totalReps - 1.0); else upperWindow->setAllNewX(0, totalReps); upperWindow->setXCaption("Time (Images)"); } upperWindow->update(); secFlag = 0; } /* Slot when "Time Plot" is chosen */ void Gdw::timePlotClicked() { // Do nothing if it is already in time plot mode if (!fftFlag) return; // Do nothing if no vector stored in upperWindow if (!upperWindow->getVecNum()) { fftFlag = 0; return; } upperWindow->setFirstVector(timeVector); QString xCaption; if (secFlag) { xCaption = "Time (Sec)"; if (upperWindow->getFirstPlotMode() % 2 == 1) upperWindow->setFirstXLength((totalReps - 1) * TR / 1000.0); else upperWindow->setFirstXLength(totalReps * TR / 1000.0); } else { xCaption = "Time (Images)"; if (upperWindow->getFirstPlotMode() % 2 == 1) upperWindow->setFirstXLength(totalReps - 1); else upperWindow->setFirstXLength(totalReps); } secButt->setText("Secs"); // Label the button "Secs" upperWindow->setXCaption(xCaption); upperWindow->update(); fftFlag = 0; // Print out the highlighted covariate's mean and std values VB_Vector *timeVector_down = downSampling(timeVector, TR / tmpResolve); double vecMean = timeVector_down->getVectorMean(); double vecSD = sqrt(timeVector_down->getVariance()); statusBar()->message(QString("Covariate info: mean=%1, SD=%2").arg(vecMean).arg(vecSD)); } /* Slot when "Freq Plot" is chosen */ void Gdw::freqPlotClicked() { // Do nothing if it is already in time plot mode if (fftFlag) return; // Do nothing if no vector stored in upperWindow if (!upperWindow->getVecNum()) { fftFlag = 1; return; } upperWindow->setFirstVector(fftVector); if (mode == COMBO && fitFlag) { QColor noiseColor = Qt::red; VB_Vector *newNoiseVec = new VB_Vector(noiseVec); newNoiseVec->scaleInPlace(fftVector->getMaxElement()); upperWindow->addVector(newNoiseVec, noiseColor); } upperWindow->setPlotMode(1); int lowFreqIndex = getLowFreq(fftVector) - 1; if (lowFreqIndex > 1) statusBar()->message(QString("Covariate info: frequency 0-%1 < 1% power. You can remove %2 \ frequencies safely.").arg(lowFreqIndex).arg(lowFreqIndex)); else if (lowFreqIndex == 1) statusBar()->message(QString("Covariate info: frequency 0-1 < 1% power. You can remove 1 \ frequency safely.")); else if (lowFreqIndex == 0) statusBar()->message(QString("Covariate info: frequency 0 < 1% power")); else statusBar()->message(QString("Covariate info: no low frequency cutoff found.")); QString xCaption; if (secFlag) { xCaption = "Freq (Hz)"; upperWindow->setAllNewX(0, 1000.0 / (2.0 * TR)); // Set unit of x axis to Hz } else { xCaption = "Freq (Number)"; upperWindow->setAllNewX(0, (double) totalReps / 2.0); // Set unit of x axis to number of images } secButt->setText("Hz"); // Label the button "Hz" upperWindow->setXCaption(xCaption); upperWindow->update(); fftFlag = 1; } /* Slot to set the text in left key line editor */ void Gdw::setKeyEditor(int i) { QString txtInBox = keyList->text(i); // Disconnect the following signal/slot pair temporarily to avoid infinite loops QObject::disconnect(keyEditor, SIGNAL(textChanged(const QString &)), this, SLOT(setKeyText())); keyEditor->setText(txtInBox); keyEditor->setFocus(); // Reconnect it now QObject::connect(keyEditor, SIGNAL(textChanged(const QString &)), this, SLOT(setKeyText())); } /* Slot to set the text in left key list box */ void Gdw::setKeyText() { int currentIndex = keyList->currentItem(); QString newKey = keyEditor->text(); // Disconnect the following signal/slot pair temporarily to avoid infinite loops QObject::disconnect(keyList, SIGNAL(highlighted(int)), this, SLOT(setKeyEditor(int))); keyList->changeItem(newKey, currentIndex); condKey[currentIndex] = newKey.ascii(); // Reconnect it now QObject::connect(keyList, SIGNAL(highlighted(int)), this, SLOT(setKeyEditor(int))); setGUpdateFlag(true); } /* nextKey() is a slot which replies keyList->returnPressed() signal. * It will highlight the next condition key in the key listbox. */ void Gdw::nextKey() { int keyIndex = keyList->currentItem(); if (keyIndex < (int)keyList->count() - 1) keyList->setCurrentItem(keyIndex + 1); else keyList->setCurrentItem(0); } /* renameUpdate() takes care of itemRenamed() signal from varListView. * For now it simply sets gUpdateFlag to be true. */ void Gdw::renameUpdate() { setGUpdateFlag(true); } /* selectGroup() selects all real covariates in a certain group */ void Gdw::selectGrp(Q3ListViewItem *inputItem) { // If the input item hasn't been selected, have it selected if (!varListView->isSelected(inputItem)) varListView->setSelected(inputItem, true); // Do nothing if it doesn't have child if (!inputItem->childCount()) return; Q3ListViewItem * myChild = inputItem->firstChild(); while(myChild) { selectGrp(myChild); myChild = myChild->nextSibling(); } } /* selectionUpdate() takes care of the selection change signal from varListView * If the new item has child, highlighted is a group, do nothing; * if the new item doesn't have child, it must be a real covariate, * emit newCovLoaded() signal and change the typeComBo value. * Note: itemCounter is different from covList.size(). * It is possible (although not very likely) that user creates a group with a few covariates, * then he/she deletes the real covariates, but the empty group item is still there. * itemCounter is defined to give user ability to remove empty group. */ void Gdw::selectionUpdate() { selID.clear(); itemCounter = 0; QObject::disconnect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); selectGrp(varListView->currentItem()); QObject::connect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); int typeStat = -1; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); QString typeStr, idStr; while (it.current()) { idStr = it.current()->text(2); if (!idStr.isEmpty()) { selID.push_back(idStr.toLong()); if (typeStat == -1) { typeStr = it.current()->text(1); typeStat = 0; } else if (typeStat == 0 && typeStr != it.current()->text(1)) typeStat = 1; } itemCounter++; ++it; } if (typeStat == -1 || typeStat == 1) typeStat = 4; else typeStat = convtType(typeStr); if (selID.size() == 1) singleCovUpdate(typeStat); else multiCovUpdate(typeStat); } /* convtType() translates input covariate's type into an integer. * returns 0 for "I", 1 for "N", 2 for "K", 3 for "D", 4 otherwise */ int Gdw::convtType(QString inputType) { if (inputType == "I") return 0; else if (inputType == "N") return 1; else if (inputType == "K") return 2; else if (inputType == "D") return 3; else return 4; } /* varListView selection update: when there is exactly one covariate highlighted */ void Gdw::singleCovUpdate(int covType) { typeCombo->setCurrentItem(covType); QString idStr = varListView->currentItem()->text(2); int covID = idStr.toInt(); emit(newCovLoaded(covList[covID])); } /* multi-selection (includes both multi and extended) update in varListView */ void Gdw::multiCovUpdate(int covType) { typeCombo->setCurrentItem(covType); timeVector = fftVector= 0; statusBar()->clear(); upperWindow->clear(); upperWindow->update(); } /* loadSingleCov() highlights a new item and shows it in upper plot window * Selection change signal/slot pair is disbaled, upper plot window is updated manually. * Hopefully it will make the update faster. */ void Gdw::loadSingleCov(Q3ListViewItem *newItem, int covType) { QObject::disconnect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); selID.clear(); selID.push_back(covList.size() - 1); itemCounter = 1; varListView->clearSelection(); varListView->setSelected(newItem, true); varListView->setCurrentItem(newItem); singleCovUpdate(covType); setGUpdateFlag(true); QObject::connect(varListView, SIGNAL(selectionChanged()), this, SLOT(selectionUpdate())); } /* dbClick() takes care of the double click signal from varListView */ void Gdw::dbClick(Q3ListViewItem *newItem) { // Don't do anything if no item is selected if (!newItem) return; // If clicked item isn't "All", enable renaming option newItem->setRenameEnabled(0, true); newItem->startRename(0); } /* setVarType() is a slot that takes care of typeCombo's activated() signal. * It will change selected covariates(s)' type according to typeCombo's new * hightlighted item index. */ void Gdw::setVarType(int typeIndex) { if (!selID.size()) return; // The last item in typeCombo is reserved if (typeIndex == 4) { QMessageBox::critical(0, "Error", "Blank covariate type is reserved for display purpose!"); return; } // Type D is available for only one covariate if (typeIndex == 3) { // Error message if D already exists if (d_index != -1) { QMessageBox::critical(0, "Error", "D type covariate already exists.
\ Only one covariate could be set to type D!"); return; } // Error message if more than one covariate is selected to set to type D if (selID.size() > 1) { QMessageBox::critical(0, "Error", "Only one covariate could be set to type D!"); return; } varListView->findItem(QString::number(selID[0]), 2)->setText(1, "D"); d_index = selID[0]; return; } // Time to deal with I/N/K types QString newType; if (typeIndex == 0) newType = "I"; else if (typeIndex == 1) newType = "N"; else newType = "K"; Q3ListViewItemIterator it(varListView, Q3ListViewItemIterator::Selected); QString typeStr; while (it.current()) { typeStr = it.current()->text(1); if (!typeStr.isEmpty() && typeStr != newType) it.current()->setText(1, newType); ++it; } // If type D is one of the selected for I/N/K, reset d_index to -1 if (chkD()) d_index = -1; } /* This function launches block design interface &*/ void Gdw::showBlockUI() { // check TR if (!TR) { QMessageBox::critical(0, "Error!", "TR is required for model design"); return; } // check totalReps if (!totalReps) { QMessageBox::critical(0, "Error!", "Number of time points is required for model design"); return; } // make sure TR is good if (TR % tmpResolve) { QMessageBox::critical(0, "Error", "TR is not a multiple of upsampling rate."); return; } this->setDisabled(true); myBlock = new BlockDesign(); myBlock->show(); myBlock->setFixedSize(myBlock->width(), myBlock->height()); myBlock->nameEditor->setText("block"); myBlock->nameEditor->setFocus(); myBlock->nameEditor->selectAll(); QIntValidator *onVal = new QIntValidator(myBlock->onEditor); onVal->setBottom(1); myBlock->onEditor->setValidator(onVal); QIntValidator *offVal = new QIntValidator(myBlock->offEditor); offVal->setBottom(1); myBlock->offEditor->setValidator(offVal); QIntValidator *numberVal = new QIntValidator(myBlock->numberEditor); numberVal->setBottom(2); myBlock->numberEditor->setValidator(numberVal); QObject::connect(myBlock->okButton, SIGNAL(clicked()), this, SLOT(okBlock())); QObject::connect(myBlock->cancelButton, SIGNAL(clicked()), this, SLOT(cancelBlock())); } /* This function deals with the signal emitted from "ok" button on block design */ void Gdw::okBlock() { if (!chkBlockUI()) return; myBlock->close(); this->setEnabled(true); if (!totalReps) { totalReps = totalReps_block; numberString->setText(QString::number(totalReps)); } VB_Vector *blockVec = new VB_Vector(totalReps); int i = 0; while (i < totalReps) { for (int j = 0; j < firstLen; j++) blockVec->setElement(i + j, first); if ((i + firstLen) < totalReps - 1) { for (int k = 0; k < secondLen; k++) blockVec->setElement(i + firstLen + k, second); } i += firstLen + secondLen; } int upRatio = TR / tmpResolve; VB_Vector *newVector = upSampling(blockVec, upRatio); covList.push_back(newVector); QString covID = QString::number(covList.size() - 1); delete blockVec; Q3ListViewItem *newItem = new Q3ListViewItem(varListView, getLastChild(varListView), myBlock->nameEditor->text(), "I", covID); // Add intercept if (!interceptID.size()) addIntercept(); // Highlights the block design covariate loadSingleCov(newItem, convtType("I")); } /* This function deals with the signal emitted from "cancel" button on block design */ void Gdw::cancelBlock() { myBlock->close(); this->setEnabled(true); } /* This function checks the input on block design interface to make sure: * (1) Effect name field is not blank; * (2) Block on/off length is positive integer; * (3) Number of blocks is an integer larger than 1. */ bool Gdw::chkBlockUI() { QString blockStr = myBlock->nameEditor->text(); if (blockStr.isEmpty()) { QMessageBox::critical(myBlock, "Error", "Effect name not found."); return false; } int onLength = myBlock->onEditor->text().toInt(); if (onLength < 1) { QMessageBox::critical(myBlock, "Error", "Minimum block length of on is 1."); return false; } int offLength = myBlock->offEditor->text().toInt(); if (offLength < 1) { QMessageBox::critical(myBlock, "Error", "Minimum block length of off is 1."); return false; } if (myBlock->ms->isChecked()) { if (onLength % TR != 0) { QMessageBox::critical(myBlock, "Error", "Length of on block must be a multiple of TR."); return false; } if (offLength % TR != 0) { QMessageBox::critical(myBlock, "Error", "Length of off block must be a multiple of TR."); return false; } onLength = onLength / TR; offLength = offLength / TR; } int blockNum = myBlock->numberEditor->text().toInt(); if (blockNum < 2) { QMessageBox::critical(myBlock, "Error", "Minimum value of number of blocks is 2."); return false; } first = 1, second = 0; firstLen = onLength, secondLen = offLength; int pairNum = blockNum / 2; int endLen = 0; if (myBlock->offFirst->isChecked()) { firstLen = offLength, secondLen = onLength; first = 0, second = 1; } if (blockNum % 2) endLen = firstLen; totalReps_block = (firstLen + secondLen) * pairNum + endLen; if (totalReps && totalReps != totalReps_block) { QMessageBox::critical(myBlock, "Error", "Number of points on this interface doesn't match the value on main interface."); return false; } return true; } /* This function launches paired design interface */ void Gdw::showPairUI() { // check TR if (!TR) { QMessageBox::critical(0, "Error!", "TR is required for model design"); return; } // check totalReps if (!totalReps) { QMessageBox::critical(0, "Error!", "Number of time points is required for model design"); return; } // make sure TR is good if (TR % tmpResolve) { QMessageBox::critical(0, "Error", "TR is not a multiple of upsampling rate."); return; } this->setDisabled(true); myPair = new PairDesign(); myPair->show(); myPair->setFixedSize(myPair->width(), myPair->height()); myPair->nameEditor->setFocus(); myPair->nameEditor->selectAll(); QIntValidator *numberVal = new QIntValidator(myPair->numberEditor); numberVal->setBottom(2); myPair->numberEditor->setValidator(numberVal); QObject::connect(myPair->okButton, SIGNAL(clicked()), this, SLOT(okPair())); QObject::connect(myPair->cancelButton, SIGNAL(clicked()), this, SLOT(cancelPair())); } /* This slot takes care of "ok" button click from paired design interface */ void Gdw::okPair() { if (!chkPairUI()) return; myPair->close(); this->setEnabled(true); if (!totalReps) { totalReps = totalReps_pair; numberString->setText(QString::number(totalReps)); } VB_Vector *mainVec = new VB_Vector(totalReps); mainVec->setAll(0); if (myPair->group->isChecked()) { for (int i = totalReps / 2; i < totalReps; i++) mainVec->setElement(i, 1); } else { for (int i = 1; i < totalReps; i+=2) mainVec->setElement(i, 1); } VB_Vector *mainVec_up = upSampling(mainVec, TR / tmpResolve); covList.push_back(mainVec_up); delete mainVec; // add the first group covariate, whose name is the input effect name string QString idStr = QString::number(covList.size() - 1); Q3ListViewItem *effect_item = new Q3ListViewItem(varListView, getLastChild(varListView), myPair->nameEditor->text(), "I", idStr); // add a new group to include subject covariates Q3ListViewItem *pairGrp = new Q3ListViewItem(varListView, getLastChild(varListView), "subjects"); pairGrp->setOpen(true); // add the other n-1 covariates into the tree view for (int i = 0; i < totalReps / 2 - 1; i++) { VB_Vector *subVec = new VB_Vector(totalReps); subVec->setAll(0); if (myPair->group->isChecked()) { subVec->setElement(i, 1); subVec->setElement(i + totalReps / 2, 1); } else { subVec->setElement(2 * i, 1); subVec->setElement(2 * i + 1, 1); } VB_Vector *subVec_up = upSampling(subVec, TR / tmpResolve); covList.push_back(subVec_up); idStr = QString::number(covList.size() - 1); QString subName = "subject " + QString::number(i + 1); (void) new Q3ListViewItem(pairGrp, getLastChild(pairGrp), subName, "I", idStr); delete subVec; } // Add intercept if (!interceptID.size()) addIntercept(); // Highlights the block design covariate loadSingleCov(effect_item, convtType("I")); } /* This slot takes care of "cancel" button click from paired design interface */ void Gdw::cancelPair() { myPair->close(); this->setEnabled(true); } /* This function checks the input on paired design interface */ bool Gdw::chkPairUI() { QString nameStr = myPair->nameEditor->text(); if (nameStr.isEmpty()) { QMessageBox::critical(myPair, "Error", "Effect name not found."); return false; } int subNum = myPair->numberEditor->text().toInt(); if (subNum < 2) { QMessageBox::critical(myPair, "Error", "Minimum value of number of subjects is 2."); return false; } totalReps_pair = 2 * subNum; if (totalReps && totalReps != totalReps_pair) { QMessageBox::critical(myPair, "Error", "Number of points on this interface doesn't match the value on main interface."); return false; } return true; } /********************************************************************** * G_Contrast class definition **********************************************************************/ G_Contrast::G_Contrast(int keyNum, int inputResolve, QWidget *parent, const char *name) : QWidget(parent, name) { // Set basic parameters condKeyNum = keyNum; tmpResolve = inputResolve; // QT interface design Q3BoxLayout *contrast_main = new Q3VBoxLayout(this, 10); // First is explanation text QLabel *text = new QLabel("Enter a contrast matrix below to define your covariates.

You need to enter " + QString::number(keyNum) + " values each separated by a space on each row.\

Leave a column of zeroes for the baseline condition. \

Each row defines a separate covariate.", this); contrast_main->addWidget(text); // matrix line input box matrixText = new Q3TextEdit(this); contrast_main->addWidget(matrixText); // Two push buttons after matrix input box: "Diagonal matrix" and "Show example line" Q3HBoxLayout *pushButtons = new Q3HBoxLayout(contrast_main, 30); QPushButton *diagonalMat = new QPushButton("Diagonal matrix", this); pushButtons->addWidget(diagonalMat); QObject::connect(diagonalMat, SIGNAL(clicked()), this, SLOT(makeDiagMat())); QPushButton *addZeroLn = new QPushButton("Show example line", this); pushButtons->addWidget(addZeroLn); QObject::connect(addZeroLn, SIGNAL(clicked()), this, SLOT(addZeroLine())); // Two radio buttons for contrast options: scale, center and normalize Q3HButtonGroup *scaleButtons = new Q3HButtonGroup(this); scaleButtons->setLineWidth(0); // hide this button group's border QRadioButton *noScale = new QRadioButton("Do not scale", scaleButtons); noScale->setFixedWidth(100); QRadioButton *scale = new QRadioButton("Scale by trial count", scaleButtons); scale->setFixedWidth(150); scale->setChecked(true); scaleFlag = 1; contrast_main->addWidget(scaleButtons); QObject::connect(noScale, SIGNAL(clicked()), this, SLOT(noScaleClicked())); QObject::connect(scale, SIGNAL(clicked()), this, SLOT(scaleClicked())); Q3HButtonGroup *offsetButtons = new Q3HButtonGroup(this); offsetButtons->setLineWidth(0); // hide this button group's border QRadioButton *leaveOffset = new QRadioButton("Leave offset", offsetButtons); leaveOffset->setFixedWidth(100); QRadioButton *centerNorm = new QRadioButton("Center and normalize", offsetButtons); centerNorm->setFixedWidth(150); centerNorm->setChecked(true); centerFlag = 1; contrast_main->addWidget(offsetButtons); QObject::connect(leaveOffset, SIGNAL(clicked()), this, SLOT(offsetClicked())); QObject::connect(centerNorm, SIGNAL(clicked()), this, SLOT(centerClicked())); // Convolution or not? (By default it is disabled) Q3BoxLayout *convolution = new Q3VBoxLayout(contrast_main, 10); convolution->setMargin(10); convButt = new QRadioButton("Convolve Contrast Covariate(s)", this); convolution->addWidget(convButt); QObject::connect(convButt, SIGNAL(clicked()), this, SLOT(convClicked())); // Set convolution kernel (filter) Q3BoxLayout *filterBox = new Q3HBoxLayout(convolution); filter = new QLabel("Filter: ", this); combo = new QComboBox(this); combo->insertItem("Load"); combo->insertItem("First eigenvector"); combo->insertItem("Blocked IRF"); combo->insertItem("Poisson"); filterBox->addWidget(filter); filterBox->addWidget(combo); filterBox->addStretch(5); // Force the widgets to shrink to minimum size filterName = new QLabel(" ", this); convolution->addWidget(filterName); QObject::connect(combo, SIGNAL(activated(int)), this, SLOT(filterSelected(int))); // Set convolution kernel sampling rate Q3BoxLayout *sampleBox = new Q3HBoxLayout(convolution); samplingLab = new QLabel("Filter sampling (msecs): ", this); QString tmpString("2000"); samplingEditor = new QLineEdit(tmpString, this); sampleBox->addWidget(samplingLab); sampleBox->addWidget(samplingEditor); sampleBox->addStretch(5); // Set convolution tag (for labelling purpose only) Q3BoxLayout *tagBox = new Q3HBoxLayout(convolution); tag = new QLabel("Label tag: ", this); tagEditor = new QLineEdit(this); tagBox->addWidget(tag); tagBox->addWidget(tagEditor); tagBox->addStretch(5); // By default, disable convolution part convStat = false; filter->setEnabled(false); combo->setEnabled(false); filterName->setEnabled(false); samplingLab->setEnabled(false); samplingEditor->setEnabled(false); tag->setEnabled(false); tagEditor->setEnabled(false); // "Cancel" and "Done" buttons at the bottom Q3HBoxLayout *finalFunct = new Q3HBoxLayout(contrast_main, 30); QPushButton *cancel = new QPushButton("Cancel", this); QPushButton *done = new QPushButton("Done", this); cancel->setMaximumWidth(80); done->setMaximumWidth(80); finalFunct->addWidget(cancel, 4); finalFunct->addWidget(done, 4); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); } /* Deconstructor does nothing so far */ G_Contrast::~G_Contrast() { } /* makeDiagMat() clears matrix text editor box and * add diagnal matrix elements in that area. */ void G_Contrast::makeDiagMat() { matrixText->blockSignals(true); // Disable signals from matrixText temporariliy matrixText->clear(); QString tmp; for (int i = 1; i < condKeyNum; i++) { tmp = ""; for (int j = 0; j < condKeyNum; j++) { if (i == j) tmp = tmp + "1 "; else tmp = tmp + "0 "; } matrixText->insertParagraph(tmp, -1); } matrixText->blockSignals(false); // Now enable signals from matrixText } /* loadMatrix() is supposed to be working when "Load matrix" button is clicked. * Since the button isn't that helpful and Geoff's IDL code doesn't make sense * to me either, this functionality isn't available now. */ void G_Contrast::loadMatrix() { } /* addZeroLine() appends a line with all elements set to be zero. * It basically add one line as an example. Not that helpful. * To make it worse, this kind of format is actually invalid. */ void G_Contrast::addZeroLine() { matrixText->blockSignals(true); // Disable signals from matrixText temporariliy QString tmp =""; for (int j = 0; j < condKeyNum; j++) tmp = tmp + "0 "; matrixText->insertParagraph(tmp, -1); matrixText->blockSignals(false); // Now enable signals from matrixText } /* set scale flag to be false */ void G_Contrast::noScaleClicked() { scaleFlag = 0; } /* set scale flag to be true */ void G_Contrast::scaleClicked() { scaleFlag = 1; } /* set center flag to be false */ void G_Contrast::offsetClicked() { centerFlag = 0; } /* set center flag to be true */ void G_Contrast::centerClicked() { centerFlag = 1; } /* This slot enables convolution part when convolution setup radio button is clicked */ void G_Contrast::convClicked() { if (convButt->isChecked()) convStat = true; else convStat = false; filter->setEnabled(convStat); combo->setEnabled(convStat); filterName->setEnabled(convStat); samplingLab->setEnabled(convStat); samplingEditor->setEnabled(convStat); tag->setEnabled(convStat); tagEditor->setEnabled(convStat); } /* Slot to take care of the filter selection from combo box */ void G_Contrast::filterSelected(int selection) { QString filterPath = getFilterPath(); switch (selection) { case 0: filterFile = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load a filter file", "Please choose your filter."); if (filterFile.length() != 0) { filterName->setText("" + filterFile + ""); } break; case 1: filterFile = filterPath + "Eigen1.ref"; filterName->setText("" + filterFile + ""); break; case 2: filterFile = filterPath + "EmpiricalBlocked_IRF.ref"; filterName->setText("" + filterFile + ""); break; case 3: filterFile = filterPath + "Poisson_IRF.ref" ; filterName->setText("" + filterFile + ""); break; } } /* Overloaded closeEvent() function */ void G_Contrast::closeEvent(QCloseEvent *ce) { ce->accept(); emit cancelSignal(true); } /* slot to take care of "cancel" button */ void G_Contrast::cancelClicked() { this->close(); } /* Slot for "Done" button. When this button is clicked, all rows are checked. * If ok the window is closed and a signal is emited for contrast matrix building */ void G_Contrast::doneClicked() { // Make sure the text edit area isn't blank if (matrixText->text().isEmpty()) { QMessageBox::critical(this, "Error", "No matrix defined yet."); return; } int lineNum = matrixText->paragraphs(); QString lineString; for (int i = 0; i < lineNum; i++) { lineString = (matrixText->text(i)).simplifyWhiteSpace(); // error generated if the blank line isn't the last if (lineString.isEmpty() && i != lineNum - 1) { QMessageBox::critical(this, "Error", "Row " + QString::number(i + 1) + " invalid: blank line"); return; } // ignore the last blank line else if (lineString.isEmpty() && i == lineNum - 1) continue; int spaceCount = 0; for (int j = 0; j < lineString.length(); j++) { if (lineString.at(j) == ' ') spaceCount++; } // Make sure elements on each line match condition keys if (spaceCount != condKeyNum - 1) { QMessageBox::critical(this, "Error", "The number of elements on row " + QString::number(i) + " not equal to that of condition keys."); return; } QString numString; bool ok; double line[condKeyNum]; for (int j = 0; j < condKeyNum; j++) { numString = lineString.section(" ", j, j); line[j] = numString.toDouble(&ok); // Make sure input elements are valid if (!ok) { QMessageBox::critical(this, "Error", "Invalid value on row " + QString::number(i) + ": " + numString); return; } } int k; for (k = 0; k < condKeyNum; k++) { if (line[k]) break; else continue; } // Make sure each line has at least one non-zero element if (k == condKeyNum) { QMessageBox::critical(this, "Error", "Row " + QString::number(i) + " invalid: all elements are zero!"); return; } } // Check convolution parameters if (!chkConvolve()) return; // Everything is fine now QString tagStr = tagEditor->text(); this->close(); emit doneSignal(matrixText, scaleFlag, centerFlag, convStat, convVector, samplingVal, tagStr); } /* This function checks whether convolution parameters are set up * correctly or not;. Returns true if yes, returns false if not. */ bool G_Contrast::chkConvolve() { // Always pass if convolution is not enabled if (!convStat) return true; // Is the filter file already set up? if (filterFile.isEmpty()) { QMessageBox::critical(this, "Error", "No filter file loaded yet!"); return false; } // Is the filter a valid ref format file? convVector = new VB_Vector(); int readStat = convVector->ReadFile((const char *) filterFile); if (readStat) { QMessageBox::critical(this, "Error", "Invalid filter file: " + filterFile); return false;; } samplingVal = samplingEditor->text().toDouble(); // Is sampling value valid? if (samplingVal < (double)tmpResolve) { QMessageBox::critical(this, "Error", "Convolution sampling rate must be equal to or larger than G design sampling rate!"); return false; } return true; } /********************************************************************** * G_DS class definition: for diagonal set covariates generation **********************************************************************/ G_DS::G_DS(int inputResolve, QWidget *parent, const char *name) : QWidget(parent, name) { // Set basic parameters tmpResolve = inputResolve; // QT interface design Q3BoxLayout *ds_main = new Q3VBoxLayout(this, 10); // Two radio buttons for contrast options: scale, center and normalize Q3HButtonGroup *scaleButtons = new Q3HButtonGroup(this); scaleButtons->setLineWidth(0); // hide this button group's border QRadioButton *noScale = new QRadioButton("Do not scale", scaleButtons); noScale->setFixedWidth(100); QRadioButton *scale = new QRadioButton("Scale by trial count", scaleButtons); scale->setFixedWidth(150); noScale->setChecked(true); scaleFlag = 0; ds_main->addWidget(scaleButtons); QObject::connect(noScale, SIGNAL(clicked()), this, SLOT(noScaleClicked())); QObject::connect(scale, SIGNAL(clicked()), this, SLOT(scaleClicked())); Q3HButtonGroup *offsetButtons = new Q3HButtonGroup(this); offsetButtons->setLineWidth(0); // hide this button group's border QRadioButton *leaveOffset = new QRadioButton("Leave offset", offsetButtons); leaveOffset->setFixedWidth(100); QRadioButton *centerNorm = new QRadioButton("Center and normalize", offsetButtons); centerNorm->setFixedWidth(150); centerNorm->setChecked(true); centerFlag = 1; ds_main->addWidget(offsetButtons); QObject::connect(leaveOffset, SIGNAL(clicked()), this, SLOT(offsetClicked())); QObject::connect(centerNorm, SIGNAL(clicked()), this, SLOT(centerClicked())); // Convolution or not? (By default it is disabled.) Mainly copied from G_Convolve widget Q3BoxLayout *convolution = new Q3VBoxLayout(ds_main, 10); convolution->setMargin(10); convButt = new QRadioButton("Convolve Diagonal Set Covariate(s)", this); convolution->addWidget(convButt); QObject::connect(convButt, SIGNAL(clicked()), this, SLOT(convClicked())); // Set convolution kernel (filter) Q3BoxLayout *filterBox = new Q3HBoxLayout(convolution); filter = new QLabel("Filter: ", this); combo = new QComboBox(this); combo->insertItem("Load"); combo->insertItem("First eigenvector"); combo->insertItem("Blocked IRF"); combo->insertItem("Poisson"); filterBox->addWidget(filter); filterBox->addWidget(combo); filterBox->addStretch(5); // Force the widgets to shrink to minimum size filterName = new QLabel(" ", this); convolution->addWidget(filterName); QObject::connect(combo, SIGNAL(activated(int)), this, SLOT(filterSelected(int))); // Set convolution kernel sampling rate Q3BoxLayout *sampleBox = new Q3HBoxLayout(convolution); samplingLab = new QLabel("Filter sampling (msecs): ", this); QString tmpString("2000"); samplingEditor = new QLineEdit(tmpString, this); sampleBox->addWidget(samplingLab); sampleBox->addWidget(samplingEditor); sampleBox->addStretch(5); // Set convolution tag (for labelling purpose only) Q3BoxLayout *tagBox = new Q3HBoxLayout(convolution); tag = new QLabel("Label tag: ", this); tagEditor = new QLineEdit(this); tagBox->addWidget(tag); tagBox->addWidget(tagEditor); tagBox->addStretch(5); // By default, disable convolution part convStat = false; filter->setEnabled(false); combo->setEnabled(false); filterName->setEnabled(false); samplingLab->setEnabled(false); samplingEditor->setEnabled(false); tag->setEnabled(false); tagEditor->setEnabled(false); // "Cancel" and "Done" buttons at the bottom Q3HBoxLayout *finalFunct = new Q3HBoxLayout(ds_main, 30); QPushButton *cancel = new QPushButton("Cancel", this); QPushButton *done = new QPushButton("Done", this); cancel->setMaximumWidth(80); done->setMaximumWidth(80); finalFunct->addWidget(cancel, 4); finalFunct->addWidget(done, 4); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); } /* Deconstructor does nothing so far */ G_DS::~G_DS() { } /* set scale flag to be false */ void G_DS::noScaleClicked() { scaleFlag = 0; } /* set scale flag to be true */ void G_DS::scaleClicked() { scaleFlag = 1; } /* set center flag to be false */ void G_DS::offsetClicked() { centerFlag = 0; } /* set center flag to be true */ void G_DS::centerClicked() { centerFlag = 1; } /* This slot enables convolution part when convolution setup radio button is clicked */ void G_DS::convClicked() { if (convButt->isChecked()) convStat = true; else convStat = false; filter->setEnabled(convStat); combo->setEnabled(convStat); filterName->setEnabled(convStat); samplingLab->setEnabled(convStat); samplingEditor->setEnabled(convStat); tag->setEnabled(convStat); tagEditor->setEnabled(convStat); } /* Slot to take care of the filter selection from combo box */ void G_DS::filterSelected(int selection) { QString filterPath = getFilterPath(); switch (selection) { case 0: filterFile = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load a filter file", "Please choose your filter."); if (filterFile.length() != 0) { filterName->setText("" + filterFile + ""); } break; case 1: filterFile = filterPath + "Eigen1.ref"; filterName->setText("" + filterFile + ""); break; case 2: filterFile = filterPath + "EmpiricalBlocked_IRF.ref"; filterName->setText("" + filterFile + ""); break; case 3: filterFile = filterPath + "Poisson_IRF.ref" ; filterName->setText("" + filterFile + ""); break; } } /* Overloaded closeEvent() function */ void G_DS::closeEvent(QCloseEvent *ce) { ce->accept(); emit cancelSignal(true); } /* slot to take care of "cancel" button */ void G_DS::cancelClicked() { this->close(); } /* Slot for "Done" button. When this button is clicked, all rows are checked. * If ok the window is closed and a signal is emited for contrast matrix building */ void G_DS::doneClicked() { // Check convolution parameters if (!chkConvolve()) return; // Everything is fine now QString tagStr = tagEditor->text(); this->close(); emit doneSignal(scaleFlag, centerFlag, convStat, convVector, samplingVal, tagStr); } /* This function checks whether convolution parameters are set up * correctly or not;. Returns true if yes, returns false if not. */ bool G_DS::chkConvolve() { // Always pass if convolution is not enabled if (!convStat) return true; // Is the filter file already set up? if (filterFile.isEmpty()) { QMessageBox::critical(this, "Error", "No filter file loaded yet!"); return false; } // Is the filter a valid ref format file? convVector = new VB_Vector(); int readStat = convVector->ReadFile((const char *) filterFile); if (readStat) { QMessageBox::critical(this, "Error", "Invalid filter file: " + filterFile); return false;; } samplingVal = samplingEditor->text().toDouble(); // Is sampling value valid? if (samplingVal < (double)tmpResolve) { QMessageBox::critical(this, "Error", "Convolution sampling rate must be equal to or larger than G design sampling rate!"); return false; } return true; } /********************************************************** * This is the class which defines the convolve interface * **********************************************************/ /* First comes the constructor */ G_Convolve::G_Convolve(int inputResolve, QWidget *parent, const char *name) : QWidget(parent, name) { tmpResolve = inputResolve; Q3BoxLayout *convolve_main = new Q3VBoxLayout(this, 10); Q3BoxLayout *filterBox = new Q3HBoxLayout(convolve_main); QLabel *filter = new QLabel("Filter: ", this); combo = new QComboBox(this); combo->insertItem("Load"); combo->insertItem("First eigenvector"); combo->insertItem("Blocked IRF"); combo->insertItem("Poisson"); filterBox->addWidget(filter); filterBox->addWidget(combo); filterBox->addStretch(5); // Force the widgets to shrink to minimum size filterName = new QLabel(" ", this); convolve_main->addWidget(filterName); QObject::connect(combo, SIGNAL(activated(int)), this, SLOT(filterSelected(int))); Q3BoxLayout *sampleBox = new Q3HBoxLayout(convolve_main); QLabel *sampling = new QLabel("Filter sampling (msecs): ", this); QString tmpString("2000"); samplingEditor = new QLineEdit(tmpString, this); sampleBox->addWidget(sampling); sampleBox->addWidget(samplingEditor); sampleBox->addStretch(5); Q3BoxLayout *tagBox = new Q3HBoxLayout(convolve_main); QLabel *tag = new QLabel("Label tag: ", this); tagEditor = new QLineEdit(this); tagBox->addWidget(tag); tagBox->addWidget(tagEditor); tagBox->addStretch(5); Q3HBoxLayout *finalFunct = new Q3HBoxLayout(convolve_main, 30); QPushButton *cancel = new QPushButton("Cancel", this); QPushButton *done = new QPushButton("Done", this); finalFunct->addWidget(cancel); finalFunct->addWidget(done); finalFunct->addStretch(5); convolve_main->addSpacing(20); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); } /* Deconstructor does nothing so far */ G_Convolve::~G_Convolve() { } /* Slot to take care of the filter selection from combo box */ void G_Convolve::filterSelected(int selection) { QString filterPath = getFilterPath(); switch (selection) { case 0: filterFile = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load a filter file", "Please choose your filter."); if (filterFile.length() != 0) { filterName->setText("" + filterFile + ""); } break; case 1: filterFile = filterPath + "Eigen1.ref"; filterName->setText("" + filterFile + ""); break; case 2: filterFile = filterPath + "EmpiricalBlocked_IRF.ref"; filterName->setText("" + filterFile + ""); break; case 3: filterFile = filterPath + "Poisson_IRF.ref" ; filterName->setText("" + filterFile + ""); break; } } /* closeEvent() is overloaded so that when user clicks "File->close" or "x" on the corner, * he/she won't get a disbaled gdw interface */ void G_Convolve::closeEvent(QCloseEvent *ce) { ce->accept(); emit(cancelSignal(true)); } /* Slot to take care of the click of "cancel" button */ void G_Convolve::cancelClicked() { this->close(); } /* Slot to take care of the click of "Done" button */ void G_Convolve::doneClicked() { // Is the filter file already set up? if (filterFile.isEmpty()) { QMessageBox::critical(this, "Error", "No filter file loaded yet!"); return; } // Is the filter a valid ref format file? convVector = new VB_Vector(); int readStat = convVector->ReadFile((const char *) filterFile); if (readStat) { QMessageBox::critical(this, "Error", "Invalid filter file: " + filterFile); return; } double sampling = samplingEditor->text().toDouble(); // Is sampling value valid? if (sampling < (double)tmpResolve) { QMessageBox::critical(this, "Error", "Convolution sampling rate must be equal to or larger than G design sampling rate!"); return; } // Everything is ready, let's go this->setEnabled(false); QString tag = tagEditor->text(); emit doneSignal(convVector, sampling, tag); // This signal doesn't include deltaFlag this->close(); this->setEnabled(true); } /* This is the class which defines the derivative interface */ /* First comes the constructor */ G_Deriv::G_Deriv(QWidget *parent, const char *name) : QWidget(parent, name) { Q3BoxLayout *deriv_main = new Q3VBoxLayout(this, 10); Q3BoxLayout *numDeriv = new Q3HBoxLayout(deriv_main); QLabel *text = new QLabel("Number of derivatives: ", this); derivEdit = new QLineEdit("1", this); numDeriv->addWidget(text); numDeriv->addWidget(derivEdit); numDeriv->addStretch(5); Q3HButtonGroup *radioButtons = new Q3HButtonGroup(this); radioButtons->setLineWidth(0); (void) new QRadioButton("Interest", radioButtons); QRadioButton *noInterButt = new QRadioButton("No interest", radioButtons); noInterButt->setChecked(true); varType = 1; QObject::connect(radioButtons, SIGNAL(clicked(int)), this, SLOT(setVarType(int))); deriv_main->addWidget(radioButtons); Q3HBoxLayout *finalFunct = new Q3HBoxLayout(deriv_main, 30); QPushButton *done = new QPushButton("Done", this); QPushButton *cancel = new QPushButton("Cancel", this); finalFunct->addWidget(done); finalFunct->addWidget(cancel); finalFunct->addStretch(5); deriv_main->addSpacing(20); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); } /* Deconstructor does nothing so far */ G_Deriv::~G_Deriv() { } /* Slot to take care of the two radio buttons */ void G_Deriv::setVarType(int flag) { varType = flag; } /* closeEvent() is overloaded so that when user clicks "File->close" or "x" on the corner, * he/she won't get a disbaled gdw interface */ void G_Deriv::closeEvent(QCloseEvent *ce) { ce->accept(); emit(cancelSignal(true)); } /* Slot to take care of the click of "cancel" button */ void G_Deriv::cancelClicked() { this->close(); } /* Slot to take care of the click of "Done" button */ void G_Deriv::doneClicked() { bool ok; unsigned numDeriv = derivEdit->text().toUInt(&ok); if (!ok || numDeriv == 0) { QMessageBox::critical(this, "Error", "Invalid number of derivatives. Please try again."); return; } if (numDeriv > 18) { QMessageBox::information(this, "Info", "The maximum of number of derivatives is 18. \

Larger value will be reset to 18."); numDeriv = 18; } emit doneSignal(numDeriv, varType); this->close(); } /* G_Orth defines the orthogonalize interface */ /* First comes the constructor */ G_Orth::G_Orth(Q3ListView *inputView, QWidget *parent, const char *name) : QWidget(parent, name) { Q3BoxLayout *orth_main = new Q3VBoxLayout(this, 10); QLabel *textLine1 = new QLabel("Orthogonalize covariate with respect to:", this); orth_main->addWidget(textLine1); Q3BoxLayout *covLayout = new Q3HBoxLayout(orth_main); Q3VButtonGroup *radioButtons = new Q3VButtonGroup(this); radioButtons->setLineWidth(0); (void) new QRadioButton("all unselected", radioButtons); QRadioButton *interestButt = new QRadioButton("all unselected interest", radioButtons); (void) new QRadioButton("all unselected no interest", radioButtons); (void)new QRadioButton("specific unselected", radioButtons); QObject::connect(radioButtons, SIGNAL(clicked(int)), this, SLOT(selectCov(int))); // Default is "all unselected interest" interestButt->setChecked(true); covGroup = 1; covLayout->addWidget(radioButtons); Q3BoxLayout *covBox = new Q3VBoxLayout(covLayout); QLabel *textLine2 = new QLabel("Pick Covariate:", this); covBox->addWidget(textLine2); // Build covView covView = new Q3ListView(this); covView->setSelectionMode(Q3ListView::Extended); covView->addColumn("Name"); covView->addColumn("Type"); covView->setColumnAlignment(1, Qt::AlignHCenter); covView->addColumn("ID"); covView->setColumnAlignment(2, Qt::AlignHCenter); covView->setRootIsDecorated(true); covView->setSortColumn(-1); covBox->addWidget(covView); // Copy items from inputView Q3ListViewItemIterator it(inputView); while (it.current()) { cpItem(it.current()); ++it; } // Don't allow the user to play with it, unless "specific unselected" radiobutton is selected covView->setEnabled(false); Q3BoxLayout *botButt = new Q3HBoxLayout(orth_main); QPushButton *done = new QPushButton("Done", this); QPushButton *cancel = new QPushButton("Cancel", this); botButt->addWidget(done); botButt->addWidget(cancel); botButt->addStretch(5); orth_main->addSpacing(20); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); } /* Deconstructor does nothing so far */ G_Orth::~G_Orth() { } /* cpItem() will recursively copy the input listViewItem, written for covariate duplication * orgDepth is input item's original depth */ void G_Orth::cpItem(Q3ListViewItem *inputItem) { Q3ListViewItem *newItem; // Copy a group item and disable it if (inputItem->text(2).isEmpty()) { // Ignore the empty group if (!inputItem->childCount()) return; if (inputItem->depth() == 0) newItem = new Q3ListViewItem(covView, getLastChild(covView), inputItem->text(0)); else newItem = new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0)); newItem->setOpen(true); newItem->setEnabled(false); return; } // Copy a real covariate if (inputItem->depth() == 0) newItem = new Q3ListViewItem(covView, getLastChild(covView), inputItem->text(0), inputItem->text(1), inputItem->text(2)); else newItem = new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0), inputItem->text(1), inputItem->text(2)); // If input item is selected in original tree view, disable it if (inputItem->isSelected()) newItem->setEnabled(false); // Disable type D covariate too else if (inputItem->text(1) == "D") newItem->setEnabled(false); // By default, select covariates of type "I" else if (inputItem->text(1) == "I") newItem->setSelected(true); } /* Modified based on gdw's same function */ Q3ListViewItem * G_Orth::findParent(Q3ListViewItem *inputItem) { int lastDepth = covView->lastItem()->depth(); int inputDepth = inputItem->depth(); if (lastDepth < inputDepth) return covView->lastItem(); Q3ListViewItem *newParent = covView->lastItem()->parent(); while (newParent->depth() > inputDepth - 1) newParent = newParent->parent(); return newParent; } /* Slot to highlight selected covariates in listbox on right side */ void G_Orth::selectCov(int selection) { // Don't do anything if the same radiobutton is clicked if (covGroup == selection) return; // Activate the tree view before change selection covView->setEnabled(true); // If "specific unselected" is clicked, keep the original selection and exit if (selection == 3) { covGroup = selection; return; } // typeStr is null, "I" or "N" QString typeStr; if (selection == 1) typeStr = "I"; else if (selection == 2) typeStr = "N"; // Clear the selection for the first 3 radiobuttons, generate selection automatically covView->clearSelection(); Q3ListViewItemIterator it(covView, Q3ListViewItemIterator::Selectable); while (it.current()) { if (!typeStr.length()) it.current()->setSelected(true); else if (it.current()->text(1) == typeStr) it.current()->setSelected(true); ++it; } covView->setEnabled(false); covGroup = selection; } /* closeEvent() is overloaded so that when user clicks "File->close" or "x" on the corner, * he/she won't get a disbaled gdw interface */ void G_Orth::closeEvent(QCloseEvent *ce) { ce->accept(); emit(cancelSignal(true)); } /* Slot to take care of the click of "cancel" button */ void G_Orth::cancelClicked() { this->close(); } /* Slot to take care of the click of "done" button. * This function emits a signal which includes an array of integers that * lables the index/ID of selected covariates on orthogonalization interface. */ void G_Orth::doneClicked() { Q3ListViewItemIterator it(covView, Q3ListViewItemIterator::Selected); int j; while (it.current()) { // This condition is actually redundant, but it makes me feel safer if (!it.current()->text(2).isEmpty()) { j = it.current()->text(2).toInt(); orthID.push_back(j); } ++it; } // Make sure at least one covariate is selected if (!orthID.size()) { QMessageBox::critical(0, "Error", "No covariate selected in orhtogonalization option"); return; } this->close(); emit doneSignal(orthID); } /* Here comes a class for exponential interface */ G_Expn::G_Expn(QWidget *parent, const char *name) : QWidget(parent, name) { Q3BoxLayout *exp_main = new Q3VBoxLayout(this, 10); QLabel *text1 = new QLabel("Replace param with param^x", this); exp_main->addWidget(text1); Q3HBoxLayout *inputLine = new Q3HBoxLayout(exp_main); QLabel *text2 = new QLabel("Exponential (x): ", this); inputBox = new QLineEdit("2", this); inputLine->addWidget(text2); inputLine->addWidget(inputBox); Q3HButtonGroup *offsetButtons = new Q3HButtonGroup(this); offsetButtons->setLineWidth(0); // hide this button group's border (void) new QRadioButton("Leave offset", offsetButtons); QRadioButton *centerNorm = new QRadioButton("Center and normalize", offsetButtons); centerNorm->setChecked(true); centerFlag = 1; exp_main->addWidget(offsetButtons); QObject::connect(offsetButtons, SIGNAL(clicked(int)), this, SLOT(setFlag(int))); Q3HBoxLayout *finalFunct = new Q3HBoxLayout(exp_main, 30); QPushButton *done = new QPushButton("Done", this); QPushButton *cancel = new QPushButton("Cancel", this); cancel->setMaximumWidth(80); done->setMaximumWidth(80); finalFunct->addWidget(done); finalFunct->addWidget(cancel); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); } /* Deconstructor does nothing so far */ G_Expn::~G_Expn() { } /* Slot to take care of the radio buttons to set whether center and normalization is needed */ void G_Expn::setFlag(int flag) { centerFlag = flag; } /* Slot to take care of the click of "Done" button */ void G_Expn::doneClicked() { QString expText = inputBox->text(); bool ok; double expVal = expText.toDouble(&ok); if (!ok) { QMessageBox::critical(this, "Error", "Invalid exponenetial value!"); return; } emit doneSignal(expVal, centerFlag); this->close(); } /* closeEvent() is overloaded so that when user clicks "File->close" or "x" on the corner, * he/she won't get a disbaled gdw interface */ void G_Expn::closeEvent(QCloseEvent *ce) { ce->accept(); emit(cancelSignal(true)); } /* Slot to take care of the click of "cancel" button */ void G_Expn::cancelClicked() { this->close(); } /* Class for multiply interface */ G_Multiply::G_Multiply(Q3ListView *inputView, QWidget *parent, const char *name) : QWidget(parent, name) { Q3BoxLayout *multpl_main = new Q3VBoxLayout(this, 10); QLabel *text1 = new QLabel("Pick covariate by which to multiply", this); multpl_main->addWidget(text1); covView = new Q3ListView(this); covView->addColumn("Name"); covView->addColumn("Type"); covView->setColumnAlignment(1, Qt::AlignHCenter); covView->addColumn("ID"); covView->setColumnAlignment(2, Qt::AlignHCenter); covView->setRootIsDecorated(true); covView->setSortColumn(-1); multpl_main->addWidget(covView); Q3ListViewItemIterator it(inputView); while (it.current()) { cpItem(it.current()); ++it; } Q3BoxLayout *botButt = new Q3HBoxLayout(multpl_main); QPushButton *done = new QPushButton("Done", this); QPushButton *cancel = new QPushButton("Cancel", this); botButt->addWidget(done); botButt->addWidget(cancel); botButt->addStretch(5); multpl_main->addSpacing(20); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); } /* Deconstructor does nothing so far */ G_Multiply::~G_Multiply() { } /* cpItem() will recursively copy the input listViewItem, written for covariate duplication * orgDepth is input item's original depth */ void G_Multiply::cpItem(Q3ListViewItem *inputItem) { if (inputItem->text(2).isEmpty()) { if (!inputItem->childCount()) return; Q3ListViewItem *newItem; if (inputItem->depth() == 0) newItem = new Q3ListViewItem(covView, getLastChild(covView), inputItem->text(0)); else newItem = new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0)); newItem->setOpen(true); newItem->setEnabled(false); return; } if (inputItem->depth() == 0) (void) new Q3ListViewItem(covView, getLastChild(covView), inputItem->text(0), inputItem->text(1), inputItem->text(2)); else (void) new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0), inputItem->text(1), inputItem->text(2)); } /* Modified based on gdw's same function */ Q3ListViewItem * G_Multiply::findParent(Q3ListViewItem *inputItem) { int lastDepth = covView->lastItem()->depth(); int inputDepth = inputItem->depth(); if (lastDepth < inputDepth) return covView->lastItem(); Q3ListViewItem *newParent = covView->lastItem()->parent(); while (newParent->depth() > inputDepth - 1) newParent = newParent->parent(); return newParent; } /* closeEvent() is overloaded so that when user clicks "File->close" or "x" on the corner, * he/she won't get a disbaled gdw interface */ void G_Multiply::closeEvent(QCloseEvent *ce) { ce->accept(); emit(cancelSignal(true)); } /* Slot to take care of the click of "Cancel" button */ void G_Multiply::cancelClicked() { this->close(); } /* Slot to take care of the click of "Done" button * When "Done" is clicked, it simply emit a signal * which includes the index number of the selected covariate. */ void G_Multiply::doneClicked() { if (!covView->currentItem()) { QMessageBox::critical(0, "Error", "No covariate selected"); return; } int selection = covView->currentItem()->text(2).toInt(); this->close(); emit(doneSignal(selection)); } /* Class for Fourier set interface */ G_Fourier::G_Fourier(double timeLength, QWidget *parent, const char *name) : QWidget(parent, name) { totalTime = timeLength; Q3BoxLayout *fourier_main = new Q3VBoxLayout(this, 10); QLabel *finalText = new QLabel("This tool will convolve your selected parameters with \ a set of sines and cosines that are harmonics of the period to be modeled, starting \ with the first harmonic. \
The zeroeth frequency (DC component) of the period can also be included if desired. \
The \"Delta covariate\" option will convert your input parameters to simple delta \ functions (recommended).

", this); fourier_main->addWidget(finalText); Q3BoxLayout *line1 = new Q3HBoxLayout(fourier_main); QLabel *label1 = new QLabel("Period to model (seconds): ", this); periodEditor = new QLineEdit("0", this); QLabel *label2 = new QLabel("Number of harmonics: ", this); numberEditor = new QLineEdit("0", this); line1->addWidget(label1); line1->addWidget(periodEditor); line1->addWidget(label2); line1->addWidget(numberEditor); Q3HButtonGroup *group1 = new Q3HButtonGroup(this); group1->setLineWidth(0); // hide this button group's border QRadioButton *button1 = new QRadioButton("DO NOT add freq zero", group1); (void) new QRadioButton("DO add freq zero", group1); button1->setChecked(true); addFlag = 0; fourier_main->addWidget(group1); QObject::connect(group1, SIGNAL(clicked(int)), this, SLOT(setAddZero(int))); Q3HButtonGroup *group2 = new Q3HButtonGroup(this); group2->setLineWidth(0); // hide this button group's border (void) new QRadioButton("DO NOT alter covariates", group2); QRadioButton *button2 = new QRadioButton("Delta covariates", group2); button2->setChecked(true); deltaFlag = 1; fourier_main->addWidget(group2); QObject::connect(group2, SIGNAL(clicked(int)), this, SLOT(setDelta(int))); Q3HBoxLayout *finalFunct = new Q3HBoxLayout(fourier_main, 30); QPushButton *done = new QPushButton("Done", this); QPushButton *cancel = new QPushButton("Cancel", this); cancel->setMaximumWidth(80); done->setMaximumWidth(80); finalFunct->addWidget(done); finalFunct->addWidget(cancel); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); QObject::connect(done, SIGNAL(clicked()), this, SLOT(doneClicked())); } /* Destructor doesn't do anything now */ G_Fourier::~G_Fourier() { } /* Set "add zero frequency" flag, 0 is no, 1 is yes */ void G_Fourier::setAddZero(int input) { addFlag = input; } /* Set "delta covariate" flag, 0 is no, 1 is yes */ void G_Fourier::setDelta(int input) { deltaFlag = input; } /* Slot to take care of the click of "Done" button */ void G_Fourier::doneClicked() { bool ok; // Convert period value QString periodTxt = periodEditor->text(); int period = periodTxt.toInt(&ok); if (!ok || period <= 0) { QMessageBox::critical(this, "Error", "Invalid period value!"); return; } if ((double) period > totalTime) { QMessageBox::critical(this, "Error", "Period must be less than or equal to " + QString::number(totalTime) + " seconds!"); return; } // Convert number of harmonics QString numberTxt = numberEditor->text(); int number = numberTxt.toInt(&ok); if (!ok || number <= 0) { QMessageBox::critical(this, "Error", "Invalid number of harmonics!"); return; } emit doneSignal(period, number, addFlag, deltaFlag); this->close(); } /* closeEvent() is overloaded so that when user clicks "File->close" or "x" on the corner, * he/she won't get a disbaled gdw interface */ void G_Fourier::closeEvent(QCloseEvent *ce) { ce->accept(); emit(cancelSignal(true)); } /* Slot to take care of the click of "cancel" button */ void G_Fourier::cancelClicked() { this->close(); } /************************************************************************ * Class for efficiency evaluation Interface ************************************************************************/ G_Eff::G_Eff(Q3ListView *inputView, std::vector< VB_Vector *> inputCovList, int inTR, int inTotalReps, int inTmpResolve, QWidget *parent, const char *name) : QWidget(parent, name) { int covNum = inputCovList.size(); init(inTR, inTotalReps, inTmpResolve, covNum); for (int i = 0; i < covNum; i++) covList.push_back(inputCovList[i]); Q3BoxLayout *eff_main = new Q3VBoxLayout(this, 10); QLabel *text1 = new QLabel("Select a filter to evaluate: ", this); eff_main->addWidget(text1); Q3VButtonGroup *radioButtons1 = new Q3VButtonGroup(this); radioButtons1->setLineWidth(0); QRadioButton *butt1 = new QRadioButton("Do not downsample", radioButtons1); (void) new QRadioButton("Downsample before convolution", radioButtons1); (void) new QRadioButton("Downsample after convolution", radioButtons1); butt1->setChecked(true); downFlag = 0; QObject::connect(radioButtons1, SIGNAL(clicked(int)), this, SLOT(setDownFlag(int))); eff_main->addWidget(radioButtons1); QLabel *filter = new QLabel("Filter: ", this); combo = new QComboBox(this); combo->insertItem("None"); combo->insertItem("Load"); combo->insertItem("First eigenvector"); combo->insertItem("Blocked IRF"); combo->insertItem("Poisson"); eff_main->addWidget(filter); eff_main->addWidget(combo); filterLabel = new QLabel("", this); eff_main->addWidget(filterLabel); QObject::connect(combo, SIGNAL(activated(int)), this, SLOT(filterSelected(int))); Q3BoxLayout *displayBox = new Q3HBoxLayout(eff_main); Q3BoxLayout *leftDisplay = new Q3VBoxLayout(displayBox); QLabel *text2 = new QLabel("Display:", this); leftDisplay->addWidget(text2, 1, Qt::AlignCenter); Q3VButtonGroup *radioButtons2 = new Q3VButtonGroup(this); radioButtons2->setLineWidth(0); (void) new QRadioButton("All covariates", radioButtons2); QRadioButton *interestButt = new QRadioButton("All of interest", radioButtons2); (void) new QRadioButton("All of no interest", radioButtons2); interestButt->setChecked(true); typeFlag = 1; QObject::connect(radioButtons2, SIGNAL(clicked(int)), this, SLOT(selectCovType(int))); leftDisplay->addWidget(radioButtons2, 8, Qt::AlignTop); Q3BoxLayout *rightDisplay = new Q3VBoxLayout(displayBox); QLabel *text3 = new QLabel("Covariates and their relative efficiencies: ", this); rightDisplay->addWidget(text3); // Copy the input tree, select 1st selectable covariate and set baseIndex cpView(inputView); Q3ListViewItemIterator all(covView, Q3ListViewItemIterator::Selectable); if (all.current()) { covView->setSelected(all.current(), true); baseIndex = all.current()->text(2).toInt(); } QObject::connect(covView, SIGNAL(selectionChanged(Q3ListViewItem *)), this, SLOT(modEffBase(Q3ListViewItem *))); rightDisplay->addWidget(covView); Q3BoxLayout *cutoffBox = new Q3HBoxLayout(eff_main); QLabel *text4 = new QLabel("Efficiency cut-off: ", this); cutoffBox->addWidget(text4); cutoffEdit = new QLineEdit("0.02", this); cutoffBox->addWidget(cutoffEdit); Q3BoxLayout *botButt = new Q3HBoxLayout(eff_main); QPushButton *delButt = new QPushButton("Delete", this); QPushButton *cancel = new QPushButton("Cancel", this); botButt->addWidget(delButt); botButt->addWidget(cancel); botButt->addStretch(5); QObject::connect(delButt, SIGNAL(clicked()), this, SLOT(delClicked())); QObject::connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked())); modFilterVec(); modRawEff(); } /* Deconstructor does nothing so far */ G_Eff::~G_Eff() { if (filterVec) delete filterVec; } /* init() initialize some simple parameters */ void G_Eff::init(int inTR, int inTotalReps, int inTmpResolve, int covNum) { TR = inTR; totalReps = inTotalReps; tmpResolve = inTmpResolve; baseIndex = -1; for (int i = 0; i < covNum; i++) rawEff.push_back(-1.0); filterVec = new VB_Vector(); } /* This slot will set the downsampling flag in radiobutton1 */ void G_Eff::setDownFlag(int selection) { downFlag = selection; modFilterVec(); modRawEff(); } /* Slot to take care of the filter selection from combo box */ void G_Eff::filterSelected(int selection) { QString filterPath = getFilterPath(); switch (selection) { case 0: filterFile = QString::null; filterLabel->clear(); break; case 1: filterFile = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load a filter file", "Please choose your filter."); if (filterFile.length()) { filterLabel->setText("Filter filename: " + filterFile); } break; case 2: filterFile = filterPath + "Eigen1.ref"; filterLabel->setText("Filter filename: " + filterFile); break; case 3: filterFile = filterPath + "EmpiricalBlocked_IRF.ref"; filterLabel->setText("Filter filename: " + filterFile); break; case 4: filterFile = filterPath + "Poisson_IRF.ref" ; filterLabel->setText("Filter filename: " + filterFile); break; } modFilterVec(); modRawEff(); } /* Select proper covaraites when radio button is clicked */ void G_Eff::selectCovType(int selection) { typeFlag = selection; modView(); modRawEff(); } /* modEffBase() is the slot which replies the highlighted(int) signal * from newCovBox listbox. It will use the new highlighted covariate as * the base to update other covariates' efficiency. So the highlighted * covariate's efficiency will be always 1.0 */ void G_Eff::modEffBase(Q3ListViewItem *newItem) { baseIndex = newItem->text(2).toInt(); int tmpIndex; double baseEff = getRawEff(baseIndex); if (baseEff == -1.0 || baseEff == 0) { QMessageBox::critical(this, "Error!", QString("Covariate #%1 has an invalid efficiency value! Evaluation aborted") .arg(baseIndex)); Q3ListViewItemIterator all(covView, Q3ListViewItemIterator::Selectable); while (all.current()) { all.current()->setText(3, QString::null); ++all; } return; } double tmpEff; Q3ListViewItemIterator all(covView, Q3ListViewItemIterator::Selectable); while (all.current()) { tmpIndex = all.current()->text(2).toInt(); tmpEff = rawEff[tmpIndex]; all.current()->setText(3, getEffStr(tmpEff/baseEff)); ++all; } } /* cpView() copies input QListView and add it on the main interface */ void G_Eff::cpView(Q3ListView *inputView) { covView = new Q3ListView(this); covView->addColumn("Name"); covView->addColumn("Type"); covView->setColumnAlignment(1, Qt::AlignHCenter); covView->addColumn("ID"); covView->setColumnAlignment(2, Qt::AlignHCenter); covView->addColumn("Efficiency"); covView->setColumnAlignment(3, Qt::AlignHCenter); covView->setRootIsDecorated(true); covView->setSortColumn(-1); Q3ListViewItemIterator it(inputView); while (it.current()) { cpItem(it.current()); ++it; } } /* modViewEff() only modifies efficiency value, not enable/disable items in covView */ void G_Eff::modRawEff() { // Don't do anything if no valid base covariate if (baseIndex == -1) return; double baseEff = getRawEff(baseIndex); if (baseEff == -1 || baseEff == 0) { QMessageBox::critical(this, "Error!", QString("Covariate #%1 has an invalid efficiency value! Evaluation aborted") .arg(baseIndex)); Q3ListViewItemIterator all(covView, Q3ListViewItemIterator::Selectable); while (all.current()) { all.current()->setText(3, QString::null); ++all; } return; } double tmpEff; int tmpIndex; Q3ListViewItemIterator all(covView, Q3ListViewItemIterator::Selectable); while (all.current()) { tmpIndex = all.current()->text(2).toInt(); tmpEff = getRawEff(tmpIndex); if (tmpEff == -1) { QMessageBox::critical(this, "Error!", QString("Covariate #%1 has an invalid efficiency value! Evaluation aborted") .arg(tmpIndex)); all.current()->setText(3, QString::null); return; } rawEff[tmpIndex] = tmpEff; all.current()->setText(3, getEffStr(tmpEff / baseEff)); ++all; } } /* getEffStr() converts the input efficiency of double type to a QString */ QString G_Eff::getEffStr(double inputEff) { double foo = inputEff; // Reset the efficiency to be zero if it is less than or equal to 0.01 if (foo <= 0.01) foo = 0; QString effStr = QString::number(foo).left(4); // 1.00 or 0.00 makes the interface look nicer if (effStr == "1") effStr = "1.00"; else if (effStr == "0") effStr = "0.00"; return effStr; } /* modView() will enable/disable covariates in covView and set the first selectable * item as the efficiency base */ void G_Eff::modView() { baseIndex = -1; for (int i = 0; i < (int) rawEff.size(); i++) rawEff[i] = -1.0; QObject::disconnect(covView, SIGNAL(selectionChanged(Q3ListViewItem *)), this, SLOT(modEffBase(Q3ListViewItem *))); if (covView->selectedItem()) covView->setSelected(covView->selectedItem(), false); Q3ListViewItemIterator all(covView); QString typeStr; while (all.current()) { typeStr = all.current()->text(1); all.current()->setText(3, QString::null); if (typeFlag == 0 && typeStr.length()) all.current()->setEnabled(true); else if (typeFlag == 1 && typeStr == "I") all.current()->setEnabled(true); else if (typeFlag == 2 && (typeStr == "N" || typeStr == "K")) all.current()->setEnabled(true); else all.current()->setEnabled(false); ++all; } Q3ListViewItemIterator all2(covView, Q3ListViewItemIterator::Selectable); if (all2.current()) { baseIndex = all2.current()->text(2).toInt(); covView->setSelected(all2.current(), true); modRawEff(); } QObject::connect(covView, SIGNAL(selectionChanged(Q3ListViewItem *)), this, SLOT(modEffBase(Q3ListViewItem *))); } /* getRawEff() returns a certain covariate's raw efficiency value */ double G_Eff::getRawEff(int inputIndex) { double neuralPower, boldPower; VB_Vector *tmpVar = covList[inputIndex]; neuralPower = getSquareSum(*tmpVar); if (!neuralPower) { return -1.0; } boldPower = getBold(tmpVar); return boldPower / neuralPower; } /* modFilterVec() will modify filterVec based on the selected filter file. */ void G_Eff::modFilterVec() { int orderG = totalReps * TR / tmpResolve; int ratio = orderG / totalReps; // (Do not downsample | Downsample after convolution) & filter file available if (downFlag != 1 && !filterFile.isNull()) { filterVec = new VB_Vector((const char *) filterFile); /* dhu bug: need to make sure 2000 % tmpResolve == 0 here if not, pop out an error message */ filterVec->sincInterpolation(2000 / tmpResolve); /* dhu bug: need to make sure orderG - filterVec->getLength() > 0, if orderG - filterVec->getLength() == 0, tmpVec is not needed if orderG - filterVec->getLength() < 0, pop out an error message */ VB_Vector tmpVec(orderG - filterVec->getLength()); tmpVec.setAll(0); filterVec->concatenate(tmpVec); } // (Do not downsample | Downsample after convolution) & filter file not available else if (downFlag != 1 && filterFile.isNull()) { filterVec = new VB_Vector(orderG); filterVec->setAll(0); (*filterVec)[0] = 1.0; } // Downsample before convolution & filter file available else if (downFlag == 1 && !filterFile.isNull()) { filterVec = new VB_Vector((const char *) filterFile); filterVec->sincInterpolation((2000 / tmpResolve) / ratio); VB_Vector tmpVec(totalReps - filterVec->getLength()); tmpVec.setAll(0); filterVec->concatenate(tmpVec); } // Downsample before convolution & filter file not available else if (downFlag == 1 && filterFile.isNull()) { filterVec = new VB_Vector(totalReps); filterVec->setAll(0); (*filterVec)[0] = 1.0; } filterVec->meanCenter(); filterVec->normMag(); } /* getBold() reads an input VB_Vector and calculates the efficiency of * this covariate. A double value of the efficiency is returned. */ double G_Eff::getBold(VB_Vector *inputCov) { int orderG = totalReps * TR / tmpResolve; int ratio = orderG / totalReps; double boldPower = 0; VB_Vector *vec2, *vec3, filteredParam; switch(downFlag) { case 0: // Do not downsample filteredParam = fftConv(inputCov, filterVec, true); boldPower = getSquareSum(filteredParam); break; case 1: // Downsample before convolution vec2 = downSampling(inputCov, ratio); filteredParam = fftConv(vec2, filterVec, true); boldPower = getSquareSum(filteredParam) * (double)ratio; delete vec2; break; case 2: // Downsample after convolution filteredParam = fftConv(inputCov, filterVec, true); vec3 = downSampling(&filteredParam, ratio); boldPower = getSquareSum(*vec3) * (double)ratio; delete vec3; break; } return boldPower; } /* Function that returns the input vector's sum of squares of each element. */ double G_Eff::getSquareSum(VB_Vector& inputVec) { double sum = 0; for (int i = 0; i < (int)inputVec.getLength(); i++) sum += inputVec[i] * inputVec[i]; return sum; } /* cpItem() will recursively copy the input listViewItem, written for covariate duplication * orgDepth is input item's original depth */ void G_Eff::cpItem(Q3ListViewItem *inputItem) { Q3ListViewItem *newItem; if (inputItem->text(2).isEmpty()) { if (!inputItem->childCount()) return; if (inputItem->depth() == 0) newItem = new Q3ListViewItem(covView, getLastChild(covView), inputItem->text(0)); else newItem = new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0)); newItem->setOpen(true); newItem->setEnabled(false); return; } if (inputItem->depth() == 0) newItem = new Q3ListViewItem(covView, getLastChild(covView), inputItem->text(0), inputItem->text(1), inputItem->text(2)); else newItem = new Q3ListViewItem(findParent(inputItem), getLastChild(findParent(inputItem)), inputItem->text(0), inputItem->text(1), inputItem->text(2)); // By default, only enable type I covariates if (newItem->text(1) != "I") newItem->setEnabled(false); } /* Modified based on gdw's same function */ Q3ListViewItem * G_Eff::findParent(Q3ListViewItem *inputItem) { int lastDepth = covView->lastItem()->depth(); int inputDepth = inputItem->depth(); if (lastDepth < inputDepth) return covView->lastItem(); Q3ListViewItem *newParent = covView->lastItem()->parent(); while (newParent->depth() > inputDepth - 1) newParent = newParent->parent(); return newParent; } /* Slot for "Delete" */ void G_Eff::delClicked() { bool ok; double cutoffVal = cutoffEdit->text().toDouble(&ok); if (!ok) { QMessageBox::critical(this, "Error", "Invalid cutoff value!"); return; } QString delStr = "
"; std::vector< int > delList; double tmpEff; Q3ListViewItemIterator all(covView, Q3ListViewItemIterator::Selectable); while (all.current()) { if (all.current()->text(3).length()) { tmpEff = all.current()->text(3).toDouble(); if (tmpEff >= 0 && tmpEff < cutoffVal) { delList.push_back(all.current()->text(2).toInt()); delStr += QString("-- Covariate #%1
").arg(all.current()->text(2)); } } ++all; } // Sort delList to make life easier when it is passed back to gdw interface sort(delList.begin(), delList.end()); if (!delList.size()) { QMessageBox::information(this, "Info", "No covariates will be deleted."); this->close(); emit(cancelSignal(true)); return; } switch(QMessageBox::warning(this, "Warning!", "Are you sure you want to delete the following covariate(s)?" + delStr, "Yes", "No", 0, 0, 1)) { case 0: emit delSignal(delList); this->close(); break; case 1: break; } } /* closeEvent() is overloaded so that when user clicks "File->close" or "x" on the corner, * he/she won't get a disbaled gdw interface */ void G_Eff::closeEvent(QCloseEvent *ce) { ce->accept(); emit(cancelSignal(true)); } /* Slot for "Cancel" */ void G_Eff::cancelClicked() { this->close(); } /* Compare two VBMatrix headers to determine whether they match each other. * This function is called by both glm and gdw. */ bool cmpG2preG(gHeaderInfo myGInfo, gHeaderInfo pregInfo) { if (myGInfo.TR != pregInfo.TR) { printf("Different TR in G and preG file. preG file is ignored.\n"); return false; } if (myGInfo.colNum != pregInfo.colNum) { printf("Different number of columns in G and preG file. preG file is ignored.\n"); return false; } if (myGInfo.sampling != pregInfo.sampling) { printf("Different sampling rate in G and preG file. preG file is ignored.\n"); return false; } if (myGInfo.TR && myGInfo.sampling && myGInfo.rowNum * myGInfo.TR / myGInfo.sampling != pregInfo.rowNum) { printf("The number of rows in preG file is NOT the upsampled number based on G file.\n"); printf("preG file is ignored.\n"); return false; } if (myGInfo.condfxn != pregInfo.condfxn) { printf("Different condition function filenames in G and preG file. preG file is ignored.\n"); return false; } if (myGInfo.condfxn.length() && !cmpArray(myGInfo.condKey, pregInfo.condKey)) { printf("Different Condition lines in G and preG file. preG file is ignored.\n"); return false; } if (!cmpArray(myGInfo.nameList, pregInfo.nameList)) { printf("Different covariate names in G and preG file. preG file is ignored.\n"); return false; } if (!cmpArray(myGInfo.typeList, pregInfo.typeList)) { printf("Different covariate types in G and preG file. preG file is ignored.\n"); return false; } return true; } /* This function compares two tokenlist objects. * Returns true their elements are same, otherwise false */ bool cmpArray(tokenlist listA, tokenlist listB) { if (!listA.size() || !listB.size() || listA.size() != listB.size()) return false; for (size_t i = 0; i < listA.size(); i++) { if (listA[i] != listB[i]) return false; } return true; } /* This function compares two tokenlist objects. * Returns true their elements are same, otherwise false */ bool cmpArray(deque listA, deque listB) { if (!listA.size() || !listB.size() || listA.size() != listB.size()) return false; for (unsigned i = 0; i < listA.size(); i++) { if (listA[i] != listB[i]) { return false; } } return true; } /* This function returns the filters directory's absolute path by calling vbp.rootdir */ QString getFilterPath() { QString vbStr(vbp.rootdir.c_str()); if (!vbStr.endsWith("/")) vbStr += "/"; QString bar(vbStr + "elements/filters/"); return bar; } /* This function will copy an input covatiate tree view to varListView on gdw interface. * It is called when "edit" button is clicked on glm tab3 interface */ void cpView(Q3ListView *inputView, Q3ListView *outputView) { if (outputView->childCount()) outputView->clear(); if (!inputView->childCount()) return; Q3ListViewItemIterator it(inputView); while (it.current()) { cpItem(it.current(), outputView); ++it; } } /* This function will recursively copy the input listViewItem, written for covariate duplication * orgDepth is input item's original depth */ void cpItem(Q3ListViewItem *inputItem, Q3ListView *outputView) { Q3ListViewItem *newItem; if (inputItem->text(2).isEmpty()) { if (inputItem->depth() == 0) newItem = new Q3ListViewItem(outputView, getLastChild(outputView), inputItem->text(0)); else newItem = new Q3ListViewItem(findOrgParent(inputItem, outputView), getLastChild(findOrgParent(inputItem, outputView)), inputItem->text(0)); newItem->setOpen(true); return; } if (inputItem->depth() == 0) newItem = new Q3ListViewItem(outputView, getLastChild(outputView), inputItem->text(0), inputItem->text(1), inputItem->text(2), inputItem->text(3)); else newItem = new Q3ListViewItem(findOrgParent(inputItem, outputView), getLastChild(findOrgParent(inputItem, outputView)), inputItem->text(0), inputItem->text(1), inputItem->text(2), inputItem->text(3)); } /* Modified based on gdw's same function */ Q3ListViewItem * findOrgParent(Q3ListViewItem *inputItem, Q3ListView *outputView) { int lastDepth = outputView->lastItem()->depth(); int inputDepth = inputItem->depth(); if (lastDepth < inputDepth) return outputView->lastItem(); Q3ListViewItem *newParent = outputView->lastItem()->parent(); while (newParent->depth() > inputDepth - 1) newParent = newParent->parent(); return newParent; } /* findGrp() searches the input parent's direct child and returns the QListViewItem group * whose name is the input QString. Returns 0 if not found. */ Q3ListViewItem * findGrp(Q3ListViewItem *parent, QString grpName) { Q3ListViewItem *child = parent->firstChild(); while (child) { if (child->text(2).isEmpty() && child->text(0) == grpName) return child; child = child->nextSibling(); } return 0; } /* This getLastChild() will return a QListView's last direct child QListViewItem. * Return 0 if the input QListViewItem does not have any child. */ Q3ListViewItem * getLastChild(Q3ListView *parentView) { if (!parentView->childCount()) return 0; Q3ListViewItem * myChild = parentView->firstChild(); for (int i = 0; i < parentView->childCount() - 1; i++) myChild = myChild->nextSibling(); return myChild; } /* This getLastChild() will return a QListViewItem's last direct child QListViewItem. * Return 0 if the input QListViewItem does not have any child. */ Q3ListViewItem * getLastChild(Q3ListViewItem *parentItem) { if (!parentItem->childCount()) return 0; Q3ListViewItem * myChild = parentItem->firstChild(); for (int i = 0; i < parentItem->childCount() - 1; i++) myChild = myChild->nextSibling(); return myChild; } /* This function will write .G and .preG file */ void writeG(string stemname,int TR,int totalReps,int tmpResolve, vector covList,Q3ListView *covView, QString &condRef, tokenlist condKey,bool meanAll) { int colNum = covList.size(); int pregRowNum = totalReps * TR / tmpResolve; int gRowNum = totalReps; // Convert the QString to const string for VBMatrix() const string fn2=stemname+".G"; const string fn3=stemname+".preG"; VBMatrix *myPreG = new VBMatrix(pregRowNum, colNum); VBMatrix *myG = new VBMatrix(gRowNum, colNum); // Add date when this file is created string myTime, myDate, timeHeader; // maketimedate() is defined in libvoxbo/vbutil.cpp, recommended by Dan maketimedate(myTime, myDate); timeHeader = (string)"DateCreated:\t" + myTime + (string)"_" + myDate + (string)"\n"; myPreG->AddHeader(timeHeader); myG->AddHeader(timeHeader); QString tmpQString = "TR(ms):\t\t" + QString::number(TR); const string tmpString1((const char *)tmpQString); myPreG->AddHeader(tmpString1); myG->AddHeader(tmpString1); tmpQString = "Sampling(ms):\t" + QString::number(tmpResolve); const string tmpString2((const char *) tmpQString); myPreG->AddHeader(tmpString2); myG->AddHeader(tmpString2); if (condRef.length()) { QString tmpQStr = "ConditionFile:\t" + condRef; const string tmpStr(tmpQStr.ascii()); myPreG->AddHeader(tmpStr); myG->AddHeader(tmpStr); } // Convert "keyText" into "Condition:indexkeyText" in the condition key list box for (size_t i = 0; i < condKey.size(); i++) { //QString keyString = keyList->text(i); QString keyString = "Condition:\t" + QString::number(i) + "\t" + condKey(i); //const string keyString2((const char *)keyString); myPreG->AddHeader(keyString.ascii()); myG->AddHeader(keyString.ascii()); } // Add a blank line here myPreG->AddHeader((string)"\n"); myG->AddHeader((string)"\n"); // Convert "I: varText" into "Parameter:indextypevarText" QStringList nameList, typeList; getCovInfo(nameList, typeList, covView); QString myName, myType, varHeader; for (unsigned i = 0; i < covList.size(); i++) { myName = nameList[i]; myType = typeList[i]; // Create header line for each covariate if (myType == "I") varHeader = "Parameter:\t" + QString::number(i) + "\tInterest\t" + myName; else if (myType == "N") varHeader = "Parameter:\t" + QString::number(i) + "\tNoInterest\t" + myName; else if (myType == "K") varHeader = "Parameter:\t" + QString::number(i) + "\tKeepNoInterest\t" + myName; else if (myType == "D") varHeader = "Parameter:\t" + QString::number(i) + "\tDependent\t" + myName; else varHeader = "Parameter:\t" + QString::number(i) + "\tUndefined\t" + myName; const string headerString(varHeader.ascii()); myPreG->AddHeader(headerString); myG->AddHeader(headerString); } // Write *.preG file now for (int i = 0; i < colNum; i++) { // If the covariate's variance is less than or equal to 1e-15, // assume it is intercept and don't mean center it. if (meanAll && covList[i]->getVariance() > 1e-15) covList[i]->meanCenter(); myPreG->SetColumn((const int)i, *covList[i]); } myPreG->WriteFile(fn3); myPreG->clear(); delete myPreG; // Write *.G file now int downRatio = TR / tmpResolve; VB_Vector tmpVec; for (int i = 0; i < colNum; i++) { tmpVec = *downSampling(covList[i], downRatio); if (meanAll && tmpVec.getVariance() > 1e-15) tmpVec.meanCenter(); myG->SetColumn((const int)i, tmpVec); } myG->WriteFile(fn2); myG->clear(); delete myG; } /* getCovInfo() collects each real covariate's name and type, put them into * two QStringList arguments respectively: nameList and typeList */ void getCovInfo(QStringList &nameList, QStringList &typeList, Q3ListView *covView) { Q3ListViewItemIterator it(covView); QString nameStr; while (it.current()) { if (it.current()->text(2).length()) { nameStr = getCovName(it.current()); nameList.push_back(nameStr); typeList.push_back(it.current()->text(1)); } it++; } } /* getCovName() returns the input covariate's full name, starting from depth 1 */ QString getCovName(Q3ListViewItem *inputItem) { int depth = inputItem->depth(); QString fullName = inputItem->text(0); Q3ListViewItem *parent = inputItem->parent(); for (int i = 0; i < depth; i++) { fullName = parent->text(0) + "->" + fullName; parent = parent->parent(); } return fullName; } /* getLowFreq() will evaluate the input VB_Vector instance and return the * number of frequencies which are lower than 1% of the total power spectrum. * Note that the returned number isn't the largest index of the cutoff frequency. * * In Geoff's IDL code, ps2percent = (inputVector->getVectorSum()) * 0.01 / 2; * which is one half of my calculation. After talking with Geoff, do not divide by 2. */ int getLowFreq(VB_Vector *inputVector) { double ps1percent = (inputVector->getVectorSum()) * 0.01; double subPower = inputVector->getElement(0); int i = 0; while (subPower < ps1percent) { i++; subPower += inputVector->getElement(i); } return i; } /* This method is to calculate a VB_Vector's fft and return another vector up to Nyquist frequency */ VB_Vector * fftNyquist(VB_Vector *inputVector) { int totalLength = inputVector->getLength(); VB_Vector *fullFFT = new VB_Vector(totalLength); inputVector->getPS(fullFFT); int newLength = totalLength / 2 + 1; VB_Vector *halfFFT = new VB_Vector(newLength); for (int i = 0; i < newLength; i++) { halfFFT->setElement(i, fullFFT->getElement(i)); } delete fullFFT; return halfFFT; } voxbo-1.8.5~svn1246/qtglm/gdw.h000066400000000000000000000417141153177201300162110ustar00rootroot00000000000000 // gdw.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu #ifndef GDW_H #define GDW_H #include "plotscreen.h" #include "glmutil.h" #include "fitOneOverF.h" #include "gheaderinfo.h" #include "vbprefs.h" #include "block.h" #include "paired.h" #include #include #include #include //Added by qt3to4: #include #include #include class QAction; class QComboBox; class QLabel; class QLineEdit; class Q3ListBox; class Q3ListView; class Q3ListViewItem; class Q3PopupMenu; class QRadioButton; class QSlider; class QStringList; class Q3TextEdit; class Q3VBox; class tokenlist; /*************************************************************************** * Gdw class: G Design Workshop ***************************************************************************/ class Gdw: public Q3MainWindow { Q_OBJECT public: Gdw(int inputNumerOfPoints = 0, int inputTR = 2000, int inputMode = 0, QString analDir = QString::null); ~Gdw(); void cpGlmView(Q3ListView *); void cpCovList(vector); void readG(const string ); void calcNoiseModel(); void setTesList(Q3ListBox *); void setGUpdateFlag(bool); void cpGlmList(vector); void cpTmpResolve(int); void cpGlmCondFxn(QString, tokenlist); void updateInterceptID(); Q3ListView *varListView; private slots: /* "File" slots */ void fileOpen(); void fileSave(); void fileSaveAs(); void rightClick(); /* Edit: Add Interest */ void add_I_Contrasts(); void showContrasts(Q3TextEdit *, int, int, bool, VB_Vector *, double, QString &); void add_I_DS(); void showDS(int, int, bool, VB_Vector*, double, QString&); void add_I_Single(); void add_I_Trial(); void add_I_varTrial(); /* Edit: Add No interest */ void add_N_Contrasts(); void add_N_DS(); void addGlobal(); void slot_addIntercept(); void addMovement(); void addScanfx(); void singleScanfx(); void comboScanfx(); void add_N_Single(); void add_N_Trial(); void add_N_varTrial(); void addSpike(); void addTxt(); void selectAll(); /* "Edit: Modify" slots */ void duplicate(); void delCov(); void modC2D(); void modConv(); void showConv(VB_Vector *, double, QString&); void modMean(); void meanNonZero(); void modMult(); void showMult(int); void modOrth(); void showOrth(std::vector); void modTS(); void UnitExcurs(); void unitVar(); void modDeriv(); void showDeriv(unsigned numDeriv, int varType); void modES(); void modExpn(); void showExpn(double, int); void modFIR(); void modFS(); void showFS(int, int, int, int); /* "Edit: load pre-defined models" slots */ void showBlockUI(); void okBlock(); void cancelBlock(); void showPairUI(); void okPair(); void cancelPair(); /* "Evaluate" slots*/ void colAll(); void col_I(); void col_N(); void a_LD(); void i_LD(); void nk_LD(); void sel_LD(); void showLD(int); void meanSD(); void efficiency(); void showEff(std::vector); void evalNoise(); /* "Tools" slots */ void loadCondFunct(); void loadCondLabel(); void saveCondLabel(); void setUpsampling(); void saveCov2Ref(); /* Slots on main interface */ void selectionUpdate(); void upperWindowUpdate(VB_Vector *); void changeTR(); void changeNumberPoints(); void secClicked(); void TRClicked(); void timePlotClicked(); void freqPlotClicked(); void setKeyEditor(int); void setKeyText(); void nextKey(); void dbClick(Q3ListViewItem *); void renameUpdate(); void setVarType(int ); signals: void newCovLoaded(VB_Vector *); void cancelSignal(bool); void doneSignal(vector , Q3ListView *, int, QString, tokenlist, bool); private: // private functions void init(int, int); void setMode(int ); void setupMenu(); void setStatusText(); void setupWidgets(); void setTR(int ); void setTimePoints(int ); void reInit(bool condFlag); void initGrpCount(); VB_Vector * calcPS(); bool chkPSstat(); bool chkGSstat(); tokenlist getMPFiles(); int getUpsampling(); void cpGlmItem(Q3ListViewItem *); Q3ListViewItem * findOrgParent(Q3ListViewItem *); void cpCondInfo(); void setGname(string); void buildCovList(bool); void buildTree(); bool cmpSampling(int); bool chkG(string); bool chkPreG(string); bool cmpTR(int); bool cmpTotalReps(int); Q3ListViewItem *searchDepth0(QString); void plotCov(unsigned ); bool chkItemName(); bool chkGrpName(Q3ListViewItem *); void singleSaveAs(QString &); // Generic functions for both "interest" and "no interest" void addContrasts(QString varType); void addDS(QString, bool, bool); void addDS(QString); void addSingle(QString varType); void addTrialFx(QString varType); void addVarTrial(QString varType); void addIntercept(); bool chkTR_imgNum(); bool chkTR_imgNum_condfx(); bool chkSpike(vector ); void cpItem(Q3ListViewItem *); void cpGrp(Q3ListViewItem *); void cpCov(Q3ListViewItem *); Q3ListViewItem *findParent(Q3ListViewItem *); int getNewDepth(Q3ListViewItem *); void delAll(); void delPart(); bool chkGrpSel(Q3ListViewItem *); void updateID(); unsigned chkID(int); bool chkSel(); bool chkD(); void rankID(); void updateSelID(); void update_d_index(); void updateMod(); void insertDerivGrp(unsigned, int); void fs_set_covList(int, int, int, int); void fs_set_view(int, int); void insertCovDC(int , int, int); VB_Vector *fs_getFFT(VB_Vector *, VB_Vector *, int); void es_set_covList(); void es_set_view(); bool chkOrth(); void fir_set_covList(int); void fir_set_view(int); bool chkColinear(); void getColinear(unsigned colType); std::vector findColID(int colType); bool chkLD(); double ldDeterm(std::vector ldList); std::vector find_LD_ID(int ldType); bool chkElement(int, std::vector); std::vector findDiff(std::vector); bool chkNoise(); VB_Vector *getPSVec(); void loadCondFunct(QString &); bool chkCondition(const char *); void writeLabFile(QString &); void writeCovFile(QString &); void selectGrp(Q3ListViewItem *); void singleCovUpdate(int); void loadSingleCov(Q3ListViewItem *, int); void multiCovUpdate(int); int convtType(QString); void closeEvent(QCloseEvent *); bool chkIntercept(); bool chkBlockUI(); bool chkPairUI(); // private variables vector < VB_Vector *> covList; bool psFlag, fitFlag; Q3PopupMenu *fileMenu; enum gdw_mode {SINGLE, COMBO} mode; Q3Action *fileSaveAction; bool gUpdateFlag; int tesNum; Q3ListBox *tesList; Q3VBox *tab3_main; PlotScreen *upperWindow; const string selectedFiles; bool pregStat; VBMatrix gMatrix, pregMatrix; gHeaderInfo myGInfo; int totalReps, TR, tmpResolve; int contrast_count, diagonal_count; int trialfx_count, var_len_count; int scanfx_count, global_count; int mvpr_count, spike_count, txt_var_count; QLabel *trString, *samplingStr, *numberString; VB_Vector *timeVector, *fftVector; VB_Vector *noiseVec; VB_Vector *condVector; QSlider *magSlider; int xMagnification; QRadioButton *timePlotButt, *secButt; int fftFlag; int secFlag; Q3ListBox *keyList; QLineEdit *keyEditor; QString varType; int itemCounter, d_index; vector< int > interceptID; vector< int > selID; QComboBox *typeCombo; QString condRef; tokenlist condKey; QString gFileName; QString filterPath; QCheckBox *meanAll; BlockDesign *myBlock; int firstLen, secondLen, totalReps_block; int first, second; PairDesign *myPair; int totalReps_pair; }; /***************************************************************************** * Contrast Interface *****************************************************************************/ class G_Contrast: public QWidget { Q_OBJECT public: G_Contrast(int keyNum, int inputResolve, QWidget *parent = 0, const char *name = 0); ~G_Contrast(); private: void loadMatrix(); void closeEvent(QCloseEvent *); bool chkConvolve(); int condKeyNum, tmpResolve; Q3TextEdit *matrixText; int scaleFlag, centerFlag; QRadioButton *convButt; bool convStat; QComboBox *combo; QLabel *filter; QString filterFile; QLabel *filterName; QLabel *samplingLab; QLineEdit *samplingEditor; QLabel *tag; QLineEdit *tagEditor; VB_Vector *convVector; double samplingVal; private slots: void makeDiagMat(); void addZeroLine(); void noScaleClicked(); void scaleClicked(); void offsetClicked(); void centerClicked(); void convClicked(); void filterSelected(int ); void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(Q3TextEdit *, int, int, bool, VB_Vector *, double, QString&); }; /***************************************************************************** * Diagonal Set Interface *****************************************************************************/ class G_DS: public QWidget { Q_OBJECT public: G_DS(int, QWidget *parent = 0, const char *name = 0); ~G_DS(); private: void closeEvent(QCloseEvent *); bool chkConvolve(); int tmpResolve; int scaleFlag, centerFlag; QRadioButton *convButt; bool convStat; QComboBox *combo; QLabel *filter; QString filterFile; QLabel *filterName; QLabel *samplingLab; QLineEdit *samplingEditor; QLabel *tag; QLineEdit *tagEditor; VB_Vector *convVector; double samplingVal; private slots: void noScaleClicked(); void scaleClicked(); void offsetClicked(); void centerClicked(); void convClicked(); void filterSelected(int ); void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(int, int, bool, VB_Vector *, double, QString&); }; /***************************************************************************** * Convolution Interface *****************************************************************************/ class G_Convolve: public QWidget { Q_OBJECT public: G_Convolve(int tmpResolve, QWidget *parent = 0, const char *name = 0); ~G_Convolve(); private: void closeEvent(QCloseEvent *); VB_Vector *convVector; QComboBox *combo; int tmpResolve; QString filterFile; QLabel *filterName; QLineEdit *samplingEditor; QLineEdit *tagEditor; private slots: void filterSelected(int ); void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(VB_Vector *, double, QString&); // This signal doesn't include deltaFlag! }; /***************************************************************************** * Derivative Interface *****************************************************************************/ class G_Deriv: public QWidget { Q_OBJECT public: G_Deriv(QWidget *parent = 0, const char *name = 0); ~G_Deriv(); private: void closeEvent(QCloseEvent *); QLineEdit *derivEdit; int varType; private slots: void setVarType(int ); void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(unsigned, int); }; /***************************************************************************** * Orthogonalize Interface *****************************************************************************/ class G_Orth: public QWidget { Q_OBJECT public: G_Orth(Q3ListView *inputView, QWidget *parent = 0, const char *name = 0); ~G_Orth(); private: void cpItem(Q3ListViewItem *); Q3ListViewItem * findParent(Q3ListViewItem *); void closeEvent(QCloseEvent *); Q3ListView *covView; std::vector orthID; int covGroup; private slots: void selectCov(int ); void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(std::vector ); }; /***************************************************************************** * Exponential Interface *****************************************************************************/ class G_Expn: public QWidget { Q_OBJECT public: G_Expn(QWidget *parent = 0, const char *name = 0); ~G_Expn(); private: void closeEvent(QCloseEvent *); QLineEdit *inputBox; int centerFlag; private slots: void setFlag(int ); void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(double, int); }; /***************************************************************************** * Multiply Interface *****************************************************************************/ class G_Multiply: public QWidget { Q_OBJECT public: G_Multiply(Q3ListView *inputView, QWidget *parent = 0, const char *name = 0); ~G_Multiply(); private: void cpItem(Q3ListViewItem *); Q3ListViewItem *findParent(Q3ListViewItem *); void closeEvent(QCloseEvent *); Q3ListView *covView; private slots: void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(int); }; /***************************************************************************** * Fourier Set Interface *****************************************************************************/ class G_Fourier: public QWidget { Q_OBJECT public: G_Fourier(double timeLength, QWidget *parent = 0, const char *name = 0); ~G_Fourier(); private: void closeEvent(QCloseEvent *); QLineEdit *periodEditor; QLineEdit *numberEditor; double totalTime; int addFlag; int deltaFlag; private slots: void setAddZero(int); void setDelta(int); void cancelClicked(); void doneClicked(); signals: void cancelSignal(bool); void doneSignal(int, int, int, int); }; /***************************************************************************** * Efficiency Evaluation Interface *****************************************************************************/ class G_Eff: public QWidget { Q_OBJECT public: G_Eff(Q3ListView *inputView, std::vector covList, int TR, int totalReps, int tmpResolve, QWidget *parent = 0, const char *name = 0); ~G_Eff(); private: void init(int, int, int, int); void cpView(Q3ListView *); void cpItem(Q3ListViewItem *); Q3ListViewItem *findParent(Q3ListViewItem *); void modRawEff(); void modView(); void modFilterVec(); double getRawEff(int); double getBold(VB_Vector *inputCov); double getEffBase(); double getSquareSum(VB_Vector &); QString getEffStr(double); void closeEvent(QCloseEvent *); int TR, totalReps, tmpResolve; QComboBox *combo; int downFlag, typeFlag, baseIndex; QString filterFile; VB_Vector *filterVec; QLabel *filterLabel; Q3ListView *covView; QLineEdit *cutoffEdit; std::vector< VB_Vector *> covList; std::vector< double > rawEff; private slots: void setDownFlag(int); void filterSelected(int); void selectCovType(int); void modEffBase(Q3ListViewItem *); void delClicked(); void cancelClicked(); signals: void cancelSignal(bool); void delSignal(std::vector delList); }; /***************************************************************************** * Some functions called by both glm and gdw (originally written in gdw) *****************************************************************************/ bool cmpG2preG(gHeaderInfo gInfo, gHeaderInfo pregInfo); bool cmpArray(tokenlist, tokenlist); bool cmpArray(deque, deque); QString getFilterPath(); void cpView(Q3ListView *source, Q3ListView *target); void cpItem(Q3ListViewItem *source, Q3ListView *target); Q3ListViewItem * findOrgParent(Q3ListViewItem *source, Q3ListView *target); Q3ListViewItem * findGrp(Q3ListViewItem *, QString); Q3ListViewItem * getLastChild(Q3ListView *parentView); Q3ListViewItem * getLastChild(Q3ListViewItem *parent); void getInterceptID(Q3ListView *, vector); VB_Vector * fftNyquist(VB_Vector *); int getLowFreq(VB_Vector *); void writeG(string stemname, int, int, int, vector, Q3ListView *, QString &, tokenlist, bool); void getCovInfo(QStringList &nameList, QStringList &typeList, Q3ListView *); QString getCovName(Q3ListViewItem *); #endif voxbo-1.8.5~svn1246/qtglm/gdw.hlp000066400000000000000000000002371153177201300165400ustar00rootroot00000000000000 VoxBo gdw (v%1%) summary: graphcal design matrix editor usage: gdw flags: -h show help -v show version voxbo-1.8.5~svn1246/qtglm/gdw_main.cpp000066400000000000000000000054161153177201300175470ustar00rootroot00000000000000 // gdw_main.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu using namespace std; #include #include #include #include "gdw.h" #include "gdw.hlp.h" void gdw_help(); void gdw_version(); VBPrefs vbp; /* The main function accepts up to two arguments: * If there is no argument, simply launch the interface; * If there is only one argument, then set it to be a filename. * If there are two or more arguments, set the first is number of time points, * the second is TR value (msec) */ int main( int argc, char **argv ) { QApplication a(argc, argv); // By default, set number of time points and TR to be 0 int inputNumberOfPoints = 0, inputTR = 0, inputMode = 0; QString fileName = QString::null; tokenlist args; vector nonflags; args.Transfer(argc-1,argv+1); for (size_t i=0; ishow(); int result = a.exec(); return result; } void gdw_help() { cout << format(myhelp) % vbversion; } void gdw_version() { cout << format("VoxBo gdw (v%s)\n")%vbversion; } voxbo-1.8.5~svn1246/qtglm/gheaderinfo.cpp000066400000000000000000000163501153177201300202340ustar00rootroot00000000000000 // gheaderinfo.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu #include "gheaderinfo.h" #include #include /* Basic constructor */ gHeaderInfo::gHeaderInfo() { init(); } /* This constructor takes VBMatrix as an argument */ gHeaderInfo::gHeaderInfo(VBMatrix inputG) { init(); getInfo(inputG); } /* Destructor */ gHeaderInfo::~gHeaderInfo() { } /* Initialize parameters */ void gHeaderInfo::init() { TR = -1; rowNum = colNum = 0; sampling = 0; condfxn=""; condStat = false; condKey.clear(); typeList.clear(); nameList.clear(); } /* Collect TR, sampling, totalReps, condition function information * because the .G and .preG files generated by Geoff's code doesn't include TR and sampling * rate information, we cannot simply assume that the third line will hold TR and the 4th * line will hold sampling rate value. It is only available in my header files. * The header is checked line by line for TR and sampling rate value. * This is for compatibility of different header format between mine and Geoff's. * When the header is eventually fixed, we can check a certain line instead of each line. */ void gHeaderInfo::getInfo(VBMatrix inputG) { vectortmpHeader = inputG.header; QString qLine, key, name, type; const char * charLine = 0; for (unsigned i = 0; i < tmpHeader.size(); i++) { if ((tmpHeader[i]).substr(0, 7) == "TR(ms):") { charLine = (tmpHeader[i]).data(); qLine = charLine; TR = (qLine.right(qLine.length() - 9)).toInt(); } else if ((tmpHeader[i]).substr(0, 13) == "Sampling(ms):") { charLine = (tmpHeader[i]).data(); qLine = charLine; sampling = (qLine.right(qLine.length() - 14)).toInt(); } else if ((tmpHeader[i]).substr(0, 14) == "ConditionFile:") { charLine = (tmpHeader[i]).data(); qLine = charLine; condfxn = (string) (qLine.right(qLine.length() - 15)).ascii(); } else if ((tmpHeader[i]).substr(0, 13) == "ConditionKey:") { charLine = (tmpHeader[i]).data(); qLine = charLine; key = qLine.section('\t', 2, 2); condKey.Add(key.ascii()); } else if ((tmpHeader[i]).substr(0, 10) == "Condition:") { charLine = (tmpHeader[i]).data(); qLine = charLine; key = qLine.section('\t', 2, 2); condKey.Add(key.ascii()); } else if ((tmpHeader[i]).substr(0, 10) == "Parameter:") { charLine = (tmpHeader[i]).data(); qLine = charLine; type = qLine.section('\t', 2, 2).left(1); name = qLine.section('\t', 3, 3); typeList.push_back(type.ascii()); nameList.push_back(name.ascii()); } } tmpHeader.clear(); rowNum = inputG.m, colNum = inputG.n; } /* Check if the information in header is consistent or not */ bool gHeaderInfo::chkInfo(bool preG) { if (typeList.size() != colNum || nameList.size() != colNum) { QMessageBox::critical(0, "G matrix Error", QString("The number of covariates in the header (%1) does \ not match the actual number of columns (%2)").arg(typeList.size()).arg(colNum)); return false; } if (TR && sampling && TR % sampling != 0) { QMessageBox::critical(0, "G matrix Error", QString("TR in the header (%1) is not a multiple of \ sampling rate (%2)").arg(TR).arg(sampling)); return false; } return chkCondfxn(preG); } /* Make sure condition function is in good shape */ bool gHeaderInfo::chkCondfxn(bool preG) { if (!condfxn.length()) return true; tokenlist condKeyInFile; condVector = new VB_Vector(); int refStat = getCondVec(condfxn.c_str(), condKeyInFile, condVector); QString tmpString(condfxn.c_str()); if (refStat == -1) { // Quit if the file isn't readable QMessageBox::warning(0, "Warning!", "Condition function in G matrix header not readable: " + tmpString); return true; } if (refStat == -2) { QMessageBox::critical(0, "Error!", "Condition function has different number \ of keys in header and content: " + tmpString); return false; } if (refStat == 1) { QMessageBox::critical(0, "Error!", "Condition function defined in the header has different \ keys in header and content: " + tmpString); return false; } if (condKey.size() != condKeyInFile.size()) { QMessageBox::critical(0, "Error!", QString("Condition function (%1) defined in the header has %2 condition \ keys, but there are %3 Condition lines").arg(condfxn.c_str()).arg(condKeyInFile.size()).arg(condKey.size())); return false; } // stop checking condition function if it is a preG file if (preG) { condStat = true; return true; } int condLen = condVector->getLength(); // Make sure the number of elements in condition function is a multiple of total time points if (condLen % rowNum != 0) { QMessageBox::critical(0, "Error!", "Number of elements in condition function must be a multiple of \ total number of time points."); return false; } // Make sure condition function can be upsampled if (sampling && (TR / sampling) % (condLen / rowNum) != 0) { QString helpStr = "G matrix header error: Condition function can not be upsampled with the sampling rate."; QMessageBox::critical(0, "Error!", helpStr); return false; } condStat = true; return true; } /* Check G matrix file validity */ bool gHeaderInfo::read(const string& inputName, bool preG) { if (!chkFileStat(inputName.c_str(), true)) return false; string gName = inputName; // previously converted to absolute path, but why??? if (gMatrix.ReadHeader(gName) || gMatrix.ReadFile(gName)) { QMessageBox::critical(0, "Error", "Invalid G matrix file format:" + QString(gName.c_str())); return false; } if (!gMatrix.m) { QMessageBox::critical(0, "Error", "G matrix file does not have any rows:" + QString(gName.c_str())); return false; } if (!gMatrix.n) { QMessageBox::critical(0, "Error", "G matrix file does not have any columns:" + QString(gName.c_str())); return false; } getInfo(gMatrix); if (!chkInfo(preG)) return false; return true; } /* chkFileStat() makes sure a certain file exists and is regular file and readable. * If qtFlag is true, it also pops up a QT message box to tell the user check status */ bool chkFileStat(const char * inputName, bool qtFlag) { if (access(inputName,R_OK)) { if (qtFlag) QMessageBox::critical(0, "Error", "File not exist: " + QString(inputName)); return false; } return true; } voxbo-1.8.5~svn1246/qtglm/gheaderinfo.h000066400000000000000000000030531153177201300176750ustar00rootroot00000000000000 // gheaderinfo.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu using namespace std; #include "glmutil.h" #include #include #include class gHeaderInfo { public: gHeaderInfo(); gHeaderInfo(VBMatrix ); ~gHeaderInfo(); bool chkInfo(bool); private: void init(); void getInfo(VBMatrix); bool chkCondfxn(bool); public: bool read(const std::string& inputName, bool); unsigned rowNum, colNum; int TR, sampling; bool condStat; std::string condfxn; std::deque nameList, typeList; tokenlist condKey; VB_Vector *condVector; VBMatrix gMatrix; }; bool chkFileStat(const char * inputName, bool qtFlag); voxbo-1.8.5~svn1246/qtglm/glm.cpp000066400000000000000000001717111153177201300165430ustar00rootroot00000000000000 // glm.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu #include #include #include using namespace std; #include "glm.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "runseq.h" extern VBPrefs vbp; /* glm constructor */ glm::glm(QWidget *parent, const char *name) : QWidget(parent, name) { TR = 0, totalReps = 0; endFlag = false; Q3GridLayout *mainGrid = new Q3GridLayout(this, 2, 1, 5, 5); tabSection = new QTabWidget(this); setElementPath(); setupTab1(); setupTab2(); setupTab3(); setupTab4(); mainGrid->addWidget(tabSection, 0, 0); buttons = new Q3HBoxLayout(mainGrid); setupButtons(); } /************************************************************************************* * Tab1 setup * *************************************************************************************/ void glm::setupTab1() { tab1 = new Q3VBox(tabSection); tab1->setMargin(20); tab1->setSpacing(10); QFileInfo fileinfo; Q3VGroupBox *tab1Box = new Q3VGroupBox("Please set up your analysis folder:", tab1); tab1Box->setLineWidth(0); Q3HBox *pathRow = new Q3HBox(tab1Box); pathRow->setSpacing(10); pathEditor = new QLineEdit(fileinfo.absFilePath(), pathRow); QObject::connect(pathEditor, SIGNAL(textChanged(const QString &)), this, SLOT(tab1_pathChanged())); QObject::connect(pathEditor, SIGNAL(returnPressed()), this, SLOT(enableTab2())); pathText = pathEditor->text(); folderInfo = QFileInfo(pathText); QPushButton *browseButt = new QPushButton("&Browse...", pathRow); QObject::connect(browseButt, SIGNAL(clicked()), this, SLOT(tab1_browse())); tab1Box->addSpace(5); finalName = new QLabel ("Analysis folder already exists: " + pathEditor->text() + "", tab1Box); tab1Box->addSpace(20); Q3HBox *seqBox = new Q3HBox(tab1Box); (void) new QLabel("Sequence Name: ", seqBox); seqEditor = new QLineEdit("Make GLM matrices", seqBox); tab1Box->addSpace(20); Q3HBox *priorityBox = new Q3HBox(tab1Box); QLabel *priLab = new QLabel("Priority: ", priorityBox); priLab->setFixedWidth(50); priCombo = new QComboBox(priorityBox); QLabel *blankLab = new QLabel("", priorityBox); priorityBox->setStretchFactor(priCombo, 1); priorityBox->setStretchFactor(blankLab, 5); // Totally there are four priority levels priCombo->insertItem("1 (overnight)"); priCombo->insertItem("2 (low priority)"); priCombo->insertItem("3 (normal)"); priCombo->insertItem("4 (high)"); priCombo->insertItem("5 (emergency)"); priCombo->setCurrentItem(1); // Default is "Standard" tab1Box->addSpace(10); auditCheck = new QCheckBox("Audit GLM", tab1Box); auditCheck->setChecked(true); Q3HBox *emailBox = new Q3HBox(tab1Box); emailCheck = new QCheckBox("Email me when done: ", emailBox); emailCheck->setChecked(true); emailEditor = new QLineEdit(QString(vbp.email.c_str()), emailBox); connect(emailCheck, SIGNAL(toggled(bool)), emailEditor, SLOT(setEnabled(bool))); // Manually set number of pieces for matrix operations Q3HBox *pieceBox = new Q3HBox(tab1Box); pieceCheck = new QCheckBox("Manually set number of pieces for matrix operations: ", pieceBox); pieceCheck->setChecked(false); pieceEditor = new QLineEdit(pieceBox); pieceEditor->setEnabled(false); // pieceEditor will only accept integers between 1 and 1000 QValidator* validator = new QIntValidator(1, 1000, this); pieceEditor->setValidator(validator); connect(pieceCheck, SIGNAL(toggled(bool)), pieceEditor, SLOT(setEnabled(bool))); tabSection->addTab(tab1, "General Options"); } /* Slot for "Browse" button */ void glm::tab1_browse() { Q3FileDialog *fileOpen = new Q3FileDialog(this); QString fn = fileOpen->getExistingDirectory(QString::null, this, ""); if (!fn.isEmpty()) pathEditor->setText(fn); } /* Slot to take care of text change in pathText line editor */ void glm::tab1_pathChanged() { pathText = pathEditor->text(); if (pathText.isEmpty()) { finalName->setText("No analysis folder defined yet!"); return; } // Remove "/" at the end if (pathText.right(1) == "/" && pathText.length() > 1) pathText = pathText.left(pathText.length() - 1); folderInfo = QFileInfo(pathText); if (folderInfo.exists() && folderInfo.isDir()) finalName->setText("Analysis folder already exists: " + pathText + ""); else if (folderInfo.exists()) finalName->setText("" + pathText + " exists, but is NOT a directory!"); else finalName->setText("New analysis folder: " + pathText + ""); } /* This function checks the whole glm interface to make sure all parameters * are available before glm submission. */ bool glm::chkSubmit() { // Check parameters in tab1 if (!chkTab1()) return false; // Check the availability of tes file(s) if (!tab2_lb2->count()) { QMessageBox::critical(0, "Error!", "No tes files selected."); return false; } // Is G matrix available? if (!covList.size() || !tab3->covView->childCount()) { QMessageBox::critical(0, "Error!", "No covariates defined."); return false; } // If condition function is defined, are condition keys available? if (condRef.length() && !condKey.size()) { QMessageBox::critical(0, "Error!", "Condition keys not found."); return false; } // If filter file is defined, is kernel TR valid? if (filterFile.size()) { bool ok; kTR = kernelTR->text().toUInt(&ok); if (!ok || kTR == 0) { QMessageBox::critical(0, "Error", "Invalid Kernel TR"); return false; } } // Does TR match that in G matrix? // This check may seem to be redundant. But it is needed when // user changes tes file selection AFTER G matrix has been designed. if (TR && TR != g_TR) { QMessageBox::critical(0, "Error", "TR in tes files doesn't match TR in G matrix"); return false; } // Does number of points in tes file match that in G matrix? // This check may seem to be redundant. But it is needed when // user changes tes file selection AFTER G matrix has been designed. if (totalReps != g_totalReps) { QMessageBox::critical(0, "Error", "Number of images in tes files doesn't match the number of imagess in G matrix"); return false; } // If "set number of pieces for matrix operations" is checked in "General options" interface, // is the input value valid? if (pieceCheck->isChecked()) { if (pieceEditor->text().isEmpty()) { QMessageBox::critical(0, "Error", "Number of pieces in \"General Options\" is blank"); return false; } uint value = pieceEditor->text().toUInt(); if (value == 0 || value > 1000) { QMessageBox::critical(0, "Error", "Number of pieces in \"General Options\" must be an integer between 1 and 1000"); return false; } } return true; } /* This function checks analysis folder's validity */ bool glm::chkAnalysisDIR() { // Never ever use "/" as the analysis folder, even if the user is root! if (pathText == "/") { QMessageBox::critical(0, "Error", "Please don't use / as your analysis folder."); return false; } // If analysis folder exists and is a directory, make sure it is writable and executble if (folderInfo.exists() && folderInfo.isDir()) { if (!folderInfo.isWritable()) { QMessageBox::critical(0, "Error", "Analysis folder exists but not writable: " + pathText); return false; } if (!folderInfo.isExecutable()) { QMessageBox::critical(0, "Error", "Analysis folder exists but not executable: " + pathText); return false; } return true; } // If analysis folder exists but is not a directory, give error message if (folderInfo.exists()) { QMessageBox::critical(0, "Error", "" + pathText + " exists, but is NOT a directory!"); return false; } // If analysis folder is new, make sure its parent directory is valid QString dirText = folderInfo.dirPath(true); QFileInfo pathInfo = QFileInfo(dirText); // Parent directory not exists if (!pathInfo.exists()) { QMessageBox::critical(0, "Error", "Parent directory not exists: " + dirText); return false; } // Parient directory is not really a directory if (!pathInfo.isDir()) { QMessageBox::critical(0, "Error", "File exists but not a directory: " + dirText); return false; } // Parient directory not writable if (!pathInfo.isWritable()) { QMessageBox::critical(0, "Error", "Parent directory not writable: " + dirText); return false; } // Parient directory not executable if (!pathInfo.isExecutable()) { QMessageBox::critical(0, "Error", "Parent directory not executable: " + dirText); return false; } return true; } /* This function checks the parameters in tab1: * (1) Is analysis folder valid? * (2) Is sequence name valid? * (3) If email check is selected, is email address valid? */ bool glm::chkTab1() { if (!chkAnalysisDIR()) return false; if (seqEditor->text().isEmpty()) { QMessageBox::critical(0, "Error", "Sequence name is blank."); return false; } if (emailCheck->isChecked()) { if (emailEditor->text().isEmpty()) { QMessageBox::critical(0, "Error", "Email address is blank."); return false; } QString email = emailEditor->text(); if (email.contains('@') != 1 || email.contains(32) || email.right(1) == "@") { QMessageBox::critical(0, "Error", "Invalid email address: " + email); return false; } } return true; } /* This function will check whether the analysis folder typed in is valid * or not. If yes, enable tab2. If not, pop out some error messages. */ void glm::enableTab2() { if (!chkTab1()) return; fileName = folderInfo.fileName(); //tabSection->setTabEnabled(tab2, true); tabSection->setCurrentPage(1); } /************************************************************************************* * Tab2 Setup * *************************************************************************************/ void glm::setupTab2() { tab2 = new Q3VBox(tabSection); tab2->setMargin(20); Q3ButtonGroup *part21 = new Q3ButtonGroup(1, Qt::Horizontal, "Please select scans:", tab2); Q3HBox *cwd = new Q3HBox(part21); cwd->setMargin(5); QFileInfo fileinfo; tab2_dirName = fileinfo.absFilePath(); /* Change this section from a simple label into label + line editor */ (void) new QLabel("Your current working directory is: ", cwd); dirEditor = new QLineEdit(tab2_dirName, cwd); QObject::connect(dirEditor, SIGNAL(textChanged(const QString &)), this, SLOT(tab2_listChanged())); QPushButton *browse_tab2 = new QPushButton ("Browse...", cwd); cwd->setStretchFactor(dirEditor, 2); connect(browse_tab2, SIGNAL(clicked()), this, SLOT(tab2Browse())); /* Main layout of tab2, which includes three vboxes. * The left box lists the files, the middle box includes the buttons. * The right side listbox shows the file(s) selected. */ Q3HBox *tab2_main = new Q3HBox(part21); tab2_main->setMargin(5); tab2_main->setSpacing(5); Q3VBox *tab2_vbox1 = new Q3VBox(tab2_main); tab2_main->setStretchFactor(tab2_vbox1, 3); Q3VBox *tab2_vbox2 = new Q3VBox(tab2_main); tab2_main->setStretchFactor(tab2_vbox2, 1); Q3VBox *tab2_vbox3 = new Q3VBox(tab2_main); tab2_main->setStretchFactor(tab2_vbox3, 3); // Set up the filter Q3HBox *hbox_filter = new Q3HBox (tab2_vbox1); (void) new QLabel("Filter: ", hbox_filter); tab2Filter = new QLineEdit("*.tes", hbox_filter); tab2_filterText = tab2Filter->text(); hbox_filter->setSpacing(2); // Create the listbox on the left side tab2_lb1 = new Q3ListBox(tab2_vbox1); tab2_lb1->setSelectionMode(Q3ListBox::Multi); connect(tab2_lb1, SIGNAL(selected(int)), this, SLOT(lb1_select(int))); tab2_vbox1->setSpacing(5); // List *.tes files in current directory tab2_listChanged(); // Change the filter whose text change will list new files connect(tab2Filter, SIGNAL(textChanged(const QString &)), this, SLOT(tab2_listChanged())); // In the middle, create some pushbuttons for left <-> right file transfer tab2_vbox2->setSpacing(5); (void) new QLabel("", tab2_vbox2); // A fake label for alignment purpose // Buttons and the related actions if you dare to press them QPushButton *left2right = new QPushButton(" -> ", tab2_vbox2); connect(left2right, SIGNAL(clicked()), this, SLOT(tab2_slotLeft2Right())); QPushButton *left2right_all = new QPushButton("ALL->", tab2_vbox2); connect(left2right_all, SIGNAL(clicked()), this, SLOT(tab2_slotLeft2Right_all())); // Should it be called "Remove" or "<-"? QPushButton *right2left = new QPushButton("<-", tab2_vbox2); connect(right2left, SIGNAL(clicked()), this, SLOT(tab2_slotRight2Left())); QPushButton *right2left_all = new QPushButton("<-ALL", tab2_vbox2); connect(right2left_all, SIGNAL(clicked()), this, SLOT(tab2_slotRight2Left_all())); QPushButton *button_done = new QPushButton("DONE", tab2_vbox2); connect(button_done, SIGNAL(clicked()), this, SLOT(enableTab3())); (void) new QLabel("", tab2_vbox2); // Another fake label for alignment purpose // Right Side of the layout QLabel *fileSelected = new QLabel("File Selected:", tab2_vbox3); fileSelected->setAlignment(Qt::AlignCenter); // create another multi-selection ListBox on the right side tab2_lb2 = new Q3ListBox(tab2_vbox3); tab2_lb2->setSelectionMode(Q3ListBox::Multi); connect(tab2_lb2, SIGNAL(selected(int)), this, SLOT(lb2_select(int))); tab2_vbox3->setSpacing(15); tabSection->addTab(tab2, "Data Selection"); //tabSection->setTabEnabled(tab2, false); // Disable tab2 if tab1 isn't done } /* Slot for "browse" button in tab2 */ void glm::tab2Browse() { Q3FileDialog *dirOpen = new Q3FileDialog(this); tab2_dirName = dirOpen->getExistingDirectory(QString::null, this, ""); if (tab2_dirName.isEmpty()) return; dirEditor->setText(tab2_dirName); tab2_listChanged(); } /* tab2_listChanged() is copied from Tom's fileView.cpp. * With glob_t it the filter supports multi-layer text format. * This slot will update the file list in left side list box. * It listens to the signals from path line editor change, * filter line editor change and the browse push button */ void glm::tab2_listChanged() { tab2_dirName = dirEditor->text(); tab2_filterText = tab2Filter->text(); tab2_lb1->clear(); struct stat st; vglob vg((string)tab2_dirName.ascii()+"/"+tab2_filterText.ascii()); for (size_t i=0; iinsertItem(vg[i].c_str()); } } /* This is the slot that responds to the mouse double click action in the left listbox. * It will move the selected item from left to right */ void glm::lb1_select(int selection) { Q3ListBoxItem *item = tab2_lb1->item(selection); if (!chkTesFile(item->text())) return; int answer = tesChanged(); if (answer < 2) { tab2_lb2->insertItem(item->text()); totalReps += getTesImgNo(item->text()); tab2_lb1->removeItem(selection); } if (answer == 1) clearG(); } /************************************************************************ * tab2_slotLeft2Right copies all selected items in the first ListBox * into the second ListBox. ************************************************************************/ void glm::tab2_slotLeft2Right() { for (unsigned int i = 0; i < tab2_lb1->count(); i++) { Q3ListBoxItem *item = tab2_lb1->item(i); if (item->isSelected() && !chkTesFile(item->text())) return; } int answer = tesChanged(); if (answer < 2) { // Go through each element in the listbox, if selected, insert it in the right listbox for (unsigned int i = 0; i < tab2_lb1->count(); i++) { Q3ListBoxItem *item = tab2_lb1->item(i); if (item->isSelected()) { tab2_lb2->insertItem(item->text()); totalReps += getTesImgNo(item->text()); tab2_lb1->removeItem(i); i--; // Important!! Without which multiple selection removal won't work! } } } if (answer == 1) clearG(); } // This slot will transfer all the items in the left to right side void glm::tab2_slotLeft2Right_all() { for (unsigned int i = 0; i < tab2_lb1->count(); i++) { Q3ListBoxItem *item = tab2_lb1->item(i); if (!chkTesFile(item->text())) return; } int answer = tesChanged(); if (answer < 2) { // Go through all items of the first ListBox for (unsigned int i = 0; i < tab2_lb1->count(); i++) { Q3ListBoxItem *item = tab2_lb1->item(i); tab2_lb2->insertItem(item->text()); totalReps += getTesImgNo(item->text()); tab2_lb1->removeItem(i); i--; // Important!! Without which multiple selection removal won't work! } } if (answer == 1) clearG(); } /* This is the slot that responds to the mouse double click action in the right listbox. * It will move the selected item from right to left */ void glm::lb2_select(int selection) { int answer = tesChanged(); if (answer < 2) { Q3ListBoxItem *item = tab2_lb2->item(selection); tab2_lb1->insertItem(item->text()); totalReps -= getTesImgNo(item->text()); tab2_lb2->removeItem(selection); updateTR(); } if (answer == 1) clearG(); } // Transfer the selected item(s) from right to left side void glm::tab2_slotRight2Left() { int answer = tesChanged(); if (answer < 2) { // This loop merges the insert and remove process together, better than tab2_slotLeft2Right() for (unsigned int i = 0; i < tab2_lb2->count(); i++) { Q3ListBoxItem *item = tab2_lb2->item(i); if (item->isSelected()) { tab2_lb1->insertItem(item->text()); totalReps -= getTesImgNo(item->text()); tab2_lb2->removeItem(i); i--; // Important!!! Without which multiple selection removal won't work! } } updateTR(); } if (answer == 1) clearG(); } /* Transfer all the items in the right side to left side */ void glm::tab2_slotRight2Left_all() { int answer = tesChanged(); if (answer < 2) { // This slot uses one loop to insert the item in the left side and remove it from the right side for (unsigned int i = 0; i < tab2_lb2->count(); i++) { Q3ListBoxItem *item = tab2_lb2->item(i); tab2_lb1->insertItem(item->text()); tab2_lb2->removeItem(i); i--; } TR = 0, totalReps = 0; } if (answer == 1) clearG(); } /* This function is called when tes file list is changed. It checks whether G matrix has * already been designed. If yes, it will ask user if he/she wants to keep the original * covariates or clear them and start G design from scratch. */ int glm::tesChanged() { if (!covList.size()) return 0; int answer = QMessageBox::warning(0, "Warning!", "It seems that you have already designed G matrix. \

Changeing your selected data may make your G matrix inconsistent with the tes files. \

Do you want to keep your original G matrix or clear it up ?", "Keep it and continue", "Clear it up and continue", "Cancel this operation", 0, 2); return answer; } /* This function checks the input tes file to make sure its TR matches the TR of selected * tes files. If no tes file selected in right side list box, set TR to the input file's TR */ bool glm::chkTesFile(QString tesName) { // Is it a valid file? if (!chkFileStat(tesName.ascii(), true)) return false; int inputTR = getTesTR(tesName); // Is the header readable? if (inputTR == -1) { QMessageBox::critical(0, "Tes file Reading Error", "Invalid header in tes file: " + tesName); return false; } // Does its header include TR? // if (!inputTR) { // QMessageBox::critical(0, "Tes file Reading Error", "Invalid TR in tes file: " + tesName); // return false; // } // If tes file doesn't have a valid TR, still accept it if (!inputTR) return true; // Is this the first tes file selected? if (!TR) { TR = inputTR; return true; } // TR in this file is different if (inputTR != TR) { QMessageBox::critical(0, "Different TR Found", tesName + "has different TR: " + QString::number(inputTR)); return false; } // Silently accept good TR return true; } /* This function returns a certain tes file's TR from header */ int glm::getTesTR(QString tesName) { string tmpName(tesName.ascii()); Tes myTes; int tesStat = myTes.ReadHeader(tmpName); if (tesStat) return -1; int tesTR = myTes.voxsize[3]; return tesTR; } /* This function goes through each tes file in right listbox and update TR */ void glm::updateTR() { TR = 0; for (unsigned i = 0; i < tab2_lb2->count(); i++) { string tmpName(tab2_lb2->item(i)->text().ascii()); Tes myTes; myTes.ReadHeader(tmpName); int tesTR = myTes.voxsize[3]; if (tesTR>FLT_MIN) TR = tesTR; } } /* This function returns a certain tes file's TR from header */ int glm::getTesImgNo(QString tesName) { string tmpName(tesName.ascii()); Tes myTes; myTes.ReadHeader(tmpName); return myTes.dimt; } /* Slot for "DONE" button: When files are selected, click the button will enable tab3 * But if no file selected, an error message will pop out. */ void glm::enableTab3() { if (!tab2_lb2->count()) { QMessageBox::information(0, "Error!", "No TES files selected yet."); return; } //tabSection->setTabEnabled(tab3, true); tabSection->setCurrentPage(2); } /************************************************************************** * Tab 3 setup **************************************************************************/ void glm::setupTab3() { gUpdate = false; meanAll = false; pregStat = true; tab3 = new glm_tab3(); tab3_TR = 0, tmpResolve = 100; g_TR = 0, g_totalReps = 0; setupTab3_view(); tabSection->addTab(tab3, "Design Matrix"); //tabSection->setTabEnabled(tab3, false); } /* This function initializes the list view in tab3 */ void glm::setupTab3_view() { tab3->covView->clear(); tab3->covView->setColumnText(0, "Name"); tab3->covView->addColumn("Type"); tab3->covView->setColumnAlignment(1, Qt::AlignHCenter); tab3->covView->addColumn("ID"); tab3->covView->setColumnAlignment(2, Qt::AlignHCenter); tab3->covView->addColumn("hidden", 0); tab3->covView->setRootIsDecorated(true); tab3->covView->setSortColumn(-1); connect(tab3->editButt, SIGNAL(clicked()), this, SLOT(tab3_edit())); connect(tab3->loadButt, SIGNAL(clicked()), this, SLOT(tab3_load())); connect(tab3->clearButt, SIGNAL(clicked()), this, SLOT(tab3_clear())); connect(tab3->blockButt, SIGNAL(clicked()), this, SLOT(tab3_blockUI())); connect(tab3->pairButt, SIGNAL(clicked()), this, SLOT(tab3_pairUI())); connect(tab3->interButt, SIGNAL(clicked()), this, SLOT(tab3_inter())); } /* Slot for "edit" button on tab3, it launches Gdw fro G matrix editing */ void glm::tab3_edit() { // check TR if (!tab3_TR) { QMessageBox::critical(0, "Error!", "TR not found"); return; } // check totalReps if (!totalReps) { QMessageBox::critical(0, "Error!", "Number of time points not found"); return; } /* Since G file is not saved by gdw now, it is not that important to pass * gFileName to gdw now. The only use is to make gdw's caption look nice. */ if (pathText.right(1) == "/") gFileName = pathText + fileName; else gFileName = pathText + "/" + fileName; Gdw *gdi = new Gdw(totalReps, tab3_TR, 1, gFileName); gdi->setTesList(tab2_lb2); gdi->calcNoiseModel(); gdi->show(); // Copy glm's treeview into gdw's tree view cpView(tab3->covView, gdi->varListView); // Copy glm's covariate list into gdw's covList gdi->cpGlmList(covList); // Copy tmpResolve too, because it might be copied from a G matrix file, // instead of default value of 100ms gdi->cpTmpResolve(tmpResolve); // Copy condition function information if (condKey.size()) gdi->cpGlmCondFxn(condRef, condKey); // update interceptID in gdw gdi->updateInterceptID(); // If some covariates are copied from glm, gdw's status should be "update" if (covList.size()) gdi->setGUpdateFlag(true); this->setDisabled(true); connect(gdi, SIGNAL(cancelSignal(bool)), this, SLOT(setEnabled(bool))); connect(gdi, SIGNAL(doneSignal(vector , Q3ListView *, int, QString, tokenlist, bool)), this, SLOT(gdwDone(vector , Q3ListView *, int, QString, tokenlist, bool))); } /* Slot for "load" button on tab3, it loads an existing G matrix * and show the covariates in the list view */ void glm::tab3_load() { // check TR if (!tab3_TR) { QMessageBox::critical(0, "Error!", "TR not found"); return; } // check totalReps if (!totalReps) { QMessageBox::critical(0, "Error!", "Number of time points not found"); return; } clearG(); QString loadedFilename = Q3FileDialog::getOpenFileName(QString::null, "G matrix files (*.G)", this, "Load a G matrix file", "Choose a G Matrix file to load"); if (!loadedFilename.isEmpty()) { const string s1(loadedFilename.ascii()); tab3_readG(s1); } } /* Read an input G matrix file, add covariate information to the tree view in tab3 */ void glm::tab3_readG(const string inputName) { if (!chkG(inputName)) return; gMat = myGInfo.gMatrix; if (myGInfo.sampling) tmpResolve = myGInfo.sampling; if (myGInfo.condStat) { condRef = QString(myGInfo.condfxn.c_str()); condKey = tokenlist(myGInfo.condKey); } if (pregStat) pregStat = chkPreG(inputName); buildCovList(pregStat); buildTree(); mainNextButton->setEnabled(true); } /* buildCovList() reads each column of gMat or pregMat (if available) into covList */ void glm::buildCovList(bool pregStat) { VB_Vector tmpVec; int upRatio = tab3_TR / tmpResolve; int vecSize; for (uint32 i=0; igetVariance() <= 1e-15) interceptID.push_back(i); covList.push_back(newVector); } // Otherwise use G file else { tmpVec = gMat.GetColumn(i); VB_Vector *downVector = new VB_Vector(tmpVec); VB_Vector *newVector = upSampling(downVector, upRatio); if (newVector->getVariance() <= 1e-15) interceptID.push_back(i); covList.push_back(newVector); delete downVector; } } g_TR = tab3_TR, g_totalReps = totalReps; gUpdate = true; } /* buildTree() builds the covView tree based on the parameter lines in G matrix file */ void glm::buildTree() { QString nameStr, sectionStr, typeStr; QStringList qList; for (int i = 0; i < (int) myGInfo.nameList.size(); i++) { nameStr = QString(myGInfo.nameList[i].c_str()); typeStr = QString(myGInfo.typeList[i].c_str()); QStringList qList = QStringList::split("->", nameStr); Q3ListViewItem *parent = tab3->covView->firstChild(); for (int j = 0; j < qList.size(); j++) { sectionStr = *qList.at(j); // Covariate is a direct child of covView if (qList.size() == 1) { (void) new Q3ListViewItem(tab3->covView, getLastChild(tab3->covView), sectionStr, typeStr, QString::number(i)); break; } // Covariate belongs to a certain group if (j == qList.size() - 1) { (void) new Q3ListViewItem(parent, getLastChild(parent), sectionStr, typeStr, QString::number(i)); break; } // Create the covariate's first layer group item (if not available) if (j == 0) { if (!searchDepth0(sectionStr)) { parent = new Q3ListViewItem(tab3->covView, getLastChild(tab3->covView), sectionStr); parent->setOpen(true); } else parent = searchDepth0(sectionStr); } // Create group items after the first layer else if (!findGrp(parent, sectionStr)) { parent = new Q3ListViewItem(parent, getLastChild(parent), sectionStr); parent->setOpen(true); } else parent = findGrp(parent, sectionStr); } } // label intercept covariate(s) in hidden column for (unsigned k = 0; k < interceptID.size(); k++) { QString tmpStr = QString::number(interceptID[k]); tab3->covView->findItem(tmpStr, 2)->setText(3, "intercept"); } } /* searchDepth0() searches the direct child(ren) of covView and returns the QListViewtem * that is a group item and name matches the input QString. Returns 0 if name not found */ Q3ListViewItem * glm::searchDepth0(QString grpName) { Q3ListViewItem *child = tab3->covView->firstChild(); while (child) { if (child->text(2).isEmpty() && child->text(0) == grpName) return child; child = child->nextSibling(); } return 0; } /* chkG() makes sure the input G file is valid */ bool glm::chkG(string inputName) { // Only accept *.G file int strLen = inputName.length(); if (inputName.substr(strLen - 2, 2) != ".G") { printf("[Error] Input filename not in *.G format: %s\n", inputName.c_str()); return false; } myGInfo = gHeaderInfo(); if (!myGInfo.read(inputName, false)) return false; if (!cmpTR(myGInfo.TR)) return false; if (!cmpTotalReps(myGInfo.rowNum)) return false; return true; } /* Compare TR in G amtrix with TR defined on the interface */ bool glm::cmpTR(int headerTR) { // When no TR in G matrix header if (headerTR == -1) { QMessageBox::warning(0, "Warning", "No TR information available in G matrix file. \
The original value will be used."); } // If there is no TR in tes files, use the TR in header else if (!TR) { tab3_TR = headerTR; // tab3->TR->setText("TR: " + QString::number(tab3_TR) + "ms, "); } else if (TR != headerTR) { switch(QMessageBox::warning(0, "Warning!", QString("TR in G matrix file header (%1) is different \ from the original value (%2). The original value will be used.
Do you want to continue?") .arg(headerTR).arg(TR), "Yes", "No", 0)) { case 0: pregStat = false; return true; case 1: // Terminate this function for "No" return false; } } return true; } /* Compare totalReps on the interface with totalReps in G matrix header */ bool glm::cmpTotalReps(int rowNum) { // Inconsistency in combo mode: error message if (totalReps != rowNum) { QMessageBox::critical(0, "Error!", QString("The number of rows (%1) in G matrix not match \ the original number of time points (%2)").arg(rowNum).arg(totalReps)); return false; } return true; } /* chkPreG() makes sure the preG file exists and in valid format */ bool glm::chkPreG(string inputName) { string pregName = inputName; int dotPost = pregName.rfind("."); pregName.erase(dotPost); pregName.append(".preG"); if (!vb_fileexists(pregName)) { printf("[E] couldn't read preG file %s\n", pregName.c_str()); return false; } if (pregMat.ReadHeader(pregName) || pregMat.ReadFile(pregName) || !pregMat.m || !pregMat.n) { printf("preG file is ignored because it is not valid G matrix file: %s\n", pregName.c_str()); return false; } gHeaderInfo myPreGInfo = gHeaderInfo(pregMat); if ( !myPreGInfo.chkInfo(true) ) return false; return cmpG2preG(myGInfo, myPreGInfo); } /* This slot clears up the tree view in tab3 */ void glm::tab3_clear() { clearG(); mainSubmitButton->setDisabled(true); mainNextButton->setDisabled(true); } /* This function is written to initialize G matrix parameters that are specific in tab3 */ void glm::clearG() { tab3->covView->clear(); covList.clear(); tmpResolve = 100; meanAll = false; g_TR = 0, g_totalReps = 0; gUpdate = true; interceptID.clear(); condKey.clear(); condRef = QString::null; pregStat = true; } /* This slot takes care of radiobutton clicks for each canned model */ void glm::tab3_model(int modelID) { if (modelID == 0) tab3_blockUI(); else if (modelID == 1) tab3_pairUI(); } void glm::tab3_inter() { clearG(); VB_Vector *newVector = new VB_Vector(totalReps * tab3_TR / tmpResolve); newVector->setAll(1.0); covList.push_back(newVector); QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(tab3->covView, getLastChild(tab3->covView), "Intercept", "I", idStr, "intercept"); tab3->covView->hideColumn(3); interceptID.push_back(covList.size() - 1); g_TR = tab3_TR, g_totalReps = totalReps; //cout << TR << " " << g_TR << " " << tab3_TR << endl; gUpdate = true; mainNextButton->setEnabled(true); } /* This slot is called when "block design" radio button is toggled. */ void glm::tab3_blockUI() { // check TR if (!tab3_TR) { QMessageBox::critical(0, "Error!", "TR is required for model design"); return; } // Current TR is different from the one in G matrix (if it exists) if (g_TR && tab3_TR != g_TR) { QMessageBox::critical(0, "Error!", "TR is different from the value in current G matrix"); return; } // Current number of points is different from the one in G matrix (if it exists) if (g_totalReps && totalReps != g_totalReps) { QMessageBox::critical(0, "Error!", "Number of points is different from the value in current G matrix"); return; } // check totalReps if (!totalReps) { QMessageBox::critical(0, "Error!", "Number of time points is required for model design"); return; } // make sure TR is good if (tab3_TR % tmpResolve) { QMessageBox::critical(0, "Error", "TR is not a multiple of upsampling rate. Please click edit button to launch main G design interface and reset upsampling rate"); return; } this->setDisabled(true); tab3_block = new BlockDesign(); tab3_block->show(); tab3_block->setFixedSize(tab3_block->width(), tab3_block->height()); tab3_block->nameEditor->setText("block"); tab3_block->nameEditor->setFocus(); tab3_block->nameEditor->selectAll(); QIntValidator *onVal = new QIntValidator(tab3_block->onEditor); onVal->setBottom(1); tab3_block->onEditor->setValidator(onVal); QIntValidator *offVal = new QIntValidator(tab3_block->offEditor); offVal->setBottom(1); tab3_block->offEditor->setValidator(offVal); QIntValidator *numberVal = new QIntValidator(tab3_block->numberEditor); numberVal->setBottom(2); tab3_block->numberEditor->setValidator(numberVal); QObject::connect(tab3_block->okButton, SIGNAL(clicked()), this, SLOT(okBlock())); QObject::connect(tab3_block->cancelButton, SIGNAL(clicked()), this, SLOT(cancelBlock())); } /* This function deals with the signal emitted from "ok" button on block design */ void glm::okBlock() { if (!chkBlockUI()) return; tab3_block->close(); this->setEnabled(true); VB_Vector *blockVec = new VB_Vector(totalReps); int i = 0; while (i < totalReps) { for (int j = 0; j < firstLen; j++) blockVec->setElement(i + j, first); if ((i + firstLen) < totalReps - 1) { for (int k = 0; k < secondLen; k++) blockVec->setElement(i + firstLen + k, second); } i += firstLen + secondLen; } int upRatio = tab3_TR / tmpResolve; VB_Vector *newVector = upSampling(blockVec, upRatio); covList.push_back(newVector); QString covID = QString::number(covList.size() - 1); delete blockVec; (void) new Q3ListViewItem(tab3->covView, getLastChild(tab3->covView), tab3_block->nameEditor->text(), "I", covID); // Add intercept if (!interceptID.size()) addIntercept(); g_TR = tab3_TR, g_totalReps = totalReps; gUpdate = true; mainNextButton->setEnabled(true); } /* This is a generic function to add intercept. * It is also called by block and paired t-test models. */ void glm::addIntercept() { VB_Vector *newVector = new VB_Vector(totalReps * tab3_TR / tmpResolve); newVector->setAll(1.0); covList.push_back(newVector); QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(tab3->covView, getLastChild(tab3->covView), "Intercept", "K", idStr, "intercept"); tab3->covView->hideColumn(3); interceptID.push_back(covList.size() - 1); } /* This function deals with the signal emitted from "cancel" button on block design */ void glm::cancelBlock() { tab3_block->close(); this->setEnabled(true); } /* This function checks the input on block design interface to make sure: * (1) Effect name field is not blank; * (2) Block on/off length is positive integer; * (3) Number of blocks is an integer larger than 1. */ bool glm::chkBlockUI() { QString blockStr = tab3_block->nameEditor->text(); if (blockStr.isEmpty()) { QMessageBox::critical(tab3_block, "Error", "Effect name not found."); return false; } int onLength = tab3_block->onEditor->text().toInt(); if (onLength < 1) { QMessageBox::critical(tab3_block, "Error", "Minimum block length of on is 1."); return false; } int offLength = tab3_block->offEditor->text().toInt(); if (offLength < 1) { QMessageBox::critical(tab3_block, "Error", "Minimum block length of off is 1."); return false; } if (tab3_block->ms->isChecked()) { if (onLength % tab3_TR != 0) { QMessageBox::critical(tab3_block, "Error", "Length of on block must be a multiple of TR."); return false; } if (offLength % tab3_TR != 0) { QMessageBox::critical(tab3_block, "Error", "Length of off block must be a multiple of TR."); return false; } onLength = onLength / tab3_TR; offLength = offLength / tab3_TR; } int blockNum = tab3_block->numberEditor->text().toInt(); if (blockNum < 2) { QMessageBox::critical(tab3_block, "Error", "Minimum value of number of blocks is 2."); return false; } first = 1, second = 0; firstLen = onLength, secondLen = offLength; int pairNum = blockNum / 2; int endLen = 0; if (tab3_block->offFirst->isChecked()) { firstLen = offLength, secondLen = onLength; first = 0, second = 1; } if (blockNum % 2) endLen = firstLen; int totalReps_block = (firstLen + secondLen) * pairNum + endLen; if (totalReps != totalReps_block) { QMessageBox::critical(tab3_block, "Error", "Number of points on this interface doesn't match the value on main interface."); return false; } return true; } /* This slot is called when "block design" radio button is toggled. */ void glm::tab3_pairUI() { // check TR if (!tab3_TR) { QMessageBox::critical(0, "Error!", "TR is required for model design"); return; } // Current TR is different from the one in G matrix (if it exists) if (g_TR && tab3_TR != g_TR) { QMessageBox::critical(0, "Error!", "TR is different from the value in current G matrix"); return; } // Current number of points is different from the one in G matrix (if it exists) if (g_totalReps && totalReps != g_totalReps) { QMessageBox::critical(0, "Error!", "Number of points is different from the value in current G matrix"); return; } // check totalReps if (!totalReps) { QMessageBox::critical(0, "Error!", "Number of time points is required for model design"); return; } // make sure TR is good if (tab3_TR % tmpResolve) { QMessageBox::critical(0, "Error", "TR is not a multiple of upsampling rate. Please click edit button to launch main G design interface and reset upsampling rate"); return; } this->setDisabled(true); tab3_pair = new PairDesign(); tab3_pair->show(); tab3_pair->setFixedSize(tab3_pair->width(), tab3_pair->height()); tab3_pair->nameEditor->setFocus(); tab3_pair->nameEditor->selectAll(); QIntValidator *numberVal = new QIntValidator(tab3_pair->numberEditor); numberVal->setBottom(2); tab3_pair->numberEditor->setValidator(numberVal); connect(tab3_pair->okButton, SIGNAL(clicked()), this, SLOT(okPair())); connect(tab3_pair->cancelButton, SIGNAL(clicked()), this, SLOT(cancelPair())); } /* This slot takes care of "ok" button click from paired design interface */ void glm::okPair() { if (!chkPairUI()) return; tab3_pair->close(); this->setEnabled(true); VB_Vector *mainVec = new VB_Vector(totalReps); mainVec->setAll(0); if (tab3_pair->group->isChecked()) { for (int i = totalReps / 2; i < totalReps; i++) mainVec->setElement(i, 1); } else { for (int i = 1; i < totalReps; i+=2) mainVec->setElement(i, 1); } VB_Vector *mainVec_up = upSampling(mainVec, tab3_TR / tmpResolve); covList.push_back(mainVec_up); delete mainVec; // add the first group covariate, whose name is the input effect name string QString idStr = QString::number(covList.size() - 1); (void) new Q3ListViewItem(tab3->covView, getLastChild(tab3->covView), tab3_pair->nameEditor->text(), "I", idStr); // add a new group to include subject covariates Q3ListViewItem *pairGrp = new Q3ListViewItem(tab3->covView, getLastChild(tab3->covView), "subjects"); pairGrp->setOpen(true); // add the other n-1 covariates into the tree view for (int i = 0; i < totalReps / 2 - 1; i++) { VB_Vector *subVec = new VB_Vector(totalReps); subVec->setAll(0); if (tab3_pair->group->isChecked()) { subVec->setElement(i, 1); subVec->setElement(i + totalReps / 2, 1); } else { subVec->setElement(2 * i, 1); subVec->setElement(2 * i + 1, 1); } VB_Vector *subVec_up = upSampling(subVec, tab3_TR / tmpResolve); covList.push_back(subVec_up); idStr = QString::number(covList.size() - 1); QString subName = "subject " + QString::number(i + 1); (void) new Q3ListViewItem(pairGrp, getLastChild(pairGrp), subName, "I", idStr); delete subVec; } // Add intercept if (!interceptID.size()) addIntercept(); g_TR = tab3_TR, g_totalReps = totalReps; gUpdate = true; mainNextButton->setEnabled(true); } /* This slot takes care of "cancel" button click from paired design interface */ void glm::cancelPair() { tab3_pair->close(); this->setEnabled(true); } /* This function checks the input on paired design interface */ bool glm::chkPairUI() { QString nameStr = tab3_pair->nameEditor->text(); if (nameStr.isEmpty()) { QMessageBox::critical(tab3_pair, "Error", "Effect name not found."); return false; } int subNum = tab3_pair->numberEditor->text().toInt(); if (subNum < 2) { QMessageBox::critical(tab3_pair, "Error", "Minimum value of number of subjects is 2."); return false; } if (totalReps != 2 * subNum) { QMessageBox::critical(tab3_pair, "Error", "Number of points on this interface doesn't match the value on main interface."); return false; } return true; } /* This slot takes care of "done" signal" from gdw interface */ void glm::gdwDone(vector gdwList, Q3ListView *gdwView, int gdwSampling, QString gdwString, tokenlist gdwKeys, bool gdw_meanAll) { this->setEnabled(true); // Sync tree view and covList with gdw interface cpGdwList(gdwList); cpView(gdwView, tab3->covView); updateInterceptID(); tmpResolve = gdwSampling; condRef = gdwString; meanAll = gdw_meanAll; if (condKey.size()) condKey.clear(); condKey = tokenlist(gdwKeys); if (covList.size()) mainNextButton->setEnabled(true); else mainNextButton->setEnabled(false); } /* Copy gdw's covList back to glm */ void glm::cpGdwList(vector inputList) { if (covList.size()) covList.clear(); int covNum = inputList.size(); for (int i = 0; i < covNum; i++) { VB_Vector *tmpVec = new VB_Vector(inputList[i]); covList.push_back(tmpVec); } g_TR = tab3_TR, g_totalReps = totalReps; gUpdate = true; } /* This function returns intercept covariate's ID. Return -1 if no intercept is defined */ void glm::updateInterceptID() { interceptID.clear(); QString col2, col3; Q3ListViewItemIterator it(tab3->covView); while (it.current()) { col2 = it.current()->text(2); col3 = it.current()->text(3); if (col2.length() && col3 == "intercept") interceptID.push_back(col2.toUInt()); it++; } } /******************************************************************************* * Tab 4 setup *******************************************************************************/ void glm::setupTab4() { tab4 = new Q3VBox(tabSection); tab4->setMargin(20); tab4->setSpacing(20); Q3VGroupBox *smooth = new Q3VGroupBox("Define Exogenous Smoothing", tab4); smooth->setInsideSpacing(20); filter_hint = new QLabel("No covariates defined yet.", smooth); Q3HBox *filterRow = new Q3HBox(smooth); QLabel *notchLabel = new QLabel("Notch Filter: ", filterRow); notchLabel->setFixedWidth(80); Q3VBox *box1 = new Q3VBox(filterRow); (void) new QLabel("", filterRow); Q3HBox *row1 = new Q3HBox(box1); Q3HBox *row2 = new Q3HBox(box1); row1->setSpacing(10); row2->setSpacing(10); QLabel *belowTxt = new QLabel("at and below: ", row1); belowTxt->setFixedWidth(80); belowEdit = new QLineEdit("0", row1); belowEdit->setFixedWidth(80); belowLab = new QLabel("------ Hz", row1); belowLab->setFixedWidth(100); QObject::connect(belowEdit, SIGNAL(lostFocus()), this, SLOT(convertBelow())); QObject::connect(belowEdit, SIGNAL(returnPressed()), this, SLOT(convertBelow())); QLabel *aboveTxt = new QLabel("at and above: ", row2); aboveTxt->setFixedWidth(80); aboveEdit = new QLineEdit("0", row2); aboveEdit->setFixedWidth(80); aboveLab = new QLabel("------ Hz", row2); aboveLab->setFixedWidth(100); QObject::connect(aboveEdit, SIGNAL(lostFocus()), this, SLOT(convertAbove())); QObject::connect(aboveEdit, SIGNAL(returnPressed()), this, SLOT(convertAbove())); // Create a special line to hold the combo box 1 and textedit box for user-defined TR Q3HBox *kerBox = new Q3HBox(smooth); (void) new QLabel("Convolution Kernel: ", kerBox); combo1 = new QComboBox(kerBox); combo1->insertItem("No Kernel"); combo1->insertItem("Load"); // Search voxbo fiters dir for smoothing kernel files QDir vbfilter(elementPath + "filters"); QString tmpFilter; for (uint i = 0; i < vbfilter.count(); i++) { tmpFilter = vbfilter[i]; if (tmpFilter == "Eigen1.ref") combo1->insertItem("First eigenvector"); else if (tmpFilter == "EmpiricalBlocked_IRF.ref") combo1->insertItem("Blocked IRF"); else if (tmpFilter == "Poisson_IRF.ref") combo1->insertItem("Poisson"); else if (tmpFilter.endsWith(".ref")) { tmpFilter.remove(tmpFilter.length() - 4, 4); combo1->insertItem(tmpFilter); } } QObject::connect(combo1, SIGNAL(activated(int)), this, SLOT(smoothKernSelected(int))); QLabel *space1 = new QLabel("", kerBox); (void) new QLabel("Kernel TR: ", kerBox); kernelTR = new QLineEdit("2000", kerBox); QLabel *space2 = new QLabel("", kerBox); kerBox->setStretchFactor(space1, 1); kerBox->setStretchFactor(kernelTR, 2); kerBox->setStretchFactor(space2, 3); smoothKernel = new QLabel("", smooth); Q3VGroupBox *timeSeries = new Q3VGroupBox("Time Series Correction Options", tab4); meanCheck = new QCheckBox("Mean norm data", timeSeries); meanCheck->setChecked(true); driftCheck = new QCheckBox("Drift correction", timeSeries); driftCheck->setChecked(true); Q3VGroupBox *noise = new Q3VGroupBox("Define Intrinsic Noise Model", tab4); noise->setInsideSpacing(10); // "Create empirical 1/f fit" button QPushButton * oneOverFButt = new QPushButton("Create empirical 1/f fit", noise); oneOverFButt->setFixedWidth(200); QObject::connect(oneOverFButt, SIGNAL(clicked()), this, SLOT(oneOverFClicked())); combo2 = new QComboBox(noise); combo2->setFixedWidth(200); combo2->insertItem("None"); combo2->insertItem("Load"); // Search voxbo noise model dir for noise model files QDir vbnoise(elementPath + "noisemodels"); QString tmpNoise; for (uint i = 0; i < vbnoise.count(); i++) { tmpNoise = vbnoise[i]; if (tmpNoise == "unsmooth_params.ref") combo2->insertItem("Unsmooth, No GSCV"); else if (tmpNoise == "smooth_params.ref") combo2->insertItem("Smooth, No GSCV"); else if (tmpNoise == "unsmooth__GCV_params.ref") combo2->insertItem("Unsmooth, with GSCV"); else if (tmpNoise == "smooth__GCV_params.ref") combo2->insertItem("Smooth, with GSCV"); else if (tmpNoise.endsWith(".ref")) { tmpNoise.remove(tmpNoise.length() - 4, 4); combo2->insertItem(tmpNoise); } } noiseModel = new QLabel("", noise); noiseModel->setFixedWidth(500); QObject::connect(combo2, SIGNAL(activated(int)), this, SLOT(noiseModSelected(int))); tabSection->addTab(tab4, "Filter and Noise Model"); //tabSection->setTabEnabled(tab4, false); } /* This function checks each covariate and gives the minimum frequency to which * the power spectrum is less than 1%. */ void glm::setFilterHint() { if (!covList.size()) { filter_hint->setText("(No covariates defined yet.)"); return; } if (!gUpdate) return; int lowFreqIndex = -10; for (unsigned i = 0; i < covList.size(); i++) { if (covList[i]->getVariance() <= 1e-15) continue; VB_Vector *downVec = downSampling(covList[i], g_TR / tmpResolve); VB_Vector *fftVec = fftNyquist(downVec); int newVal = getLowFreq(fftVec) - 1; if (lowFreqIndex == -10 || lowFreqIndex > newVal) lowFreqIndex = newVal; delete downVec; delete fftVec; } if (lowFreqIndex == -10) filter_hint->setText("(No non-intercept covariates defined yet.)"); else if (lowFreqIndex == -1) filter_hint->setText("(Cut-off frequency not found.)"); else if (lowFreqIndex == 0) filter_hint->setText("(Frequency 0 < 1% power for all covariates.)"); else filter_hint->setText("(Frequencies 0-" + QString::number(lowFreqIndex) + " < 1% power for all covariates.)" ); } /* This slot will convert the "at and below" value to a value in unit of Hz */ void glm::convertBelow() { bool convertStat; double tmpVal = belowEdit->text().toDouble(&convertStat); if (!convertStat) { QMessageBox::information(0, "Error", "Invalid input value"); return; } if (tmpVal != 0) { tmpVal = tmpVal / (totalReps * g_TR / 1000.0); belowLab->setText(QString::number(tmpVal).left(6) + " Hz"); } else belowLab->setText("------ Hz"); } /* This slot will convert the "at and above" value to a value in unit of Hz */ void glm::convertAbove() { bool convertStat; double tmpVal = aboveEdit->text().toDouble(&convertStat); if (!convertStat) { QMessageBox::information(0, "Error", "Invalid input value"); return; } if (tmpVal != 0) { tmpVal = (totalReps / 2.0 - (tmpVal - 1.0)) / (totalReps * g_TR / 1000.0); aboveLab->setText(QString::number(tmpVal).left(6) + " Hz"); } else aboveLab->setText("------ Hz"); } // This slot will take care of the combo box 1 options when selecting exogenous smoothing models void glm::smoothKernSelected(int selection) { if (selection == 0) { filterFile = QString::null; smoothKernel->clear(); } else if (selection == 1) { filterFile = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load a filter file", "Please choose your filter."); if (filterFile.length() != 0) { smoothKernel->setText("File loaded is: " + filterFile + ""); } } else { filterFile = getFilterFile(selection); smoothKernel->setText("File loaded is: " + filterFile + ""); } } /* This function uses vbp.rootdir to get elements directory's absolute path */ void glm::setElementPath() { QString vbStr(vbp.rootdir.c_str()); if (!vbStr.endsWith("/")) vbStr += "/"; elementPath = vbStr + "elements/"; } /* getFilterFile(int) returns the smoothing kernel's real file name */ QString glm::getFilterFile(int comboIndex) { if (comboIndex < 2) return QString::null; QString tmpTxt = combo1->text(comboIndex); QString realName; if (tmpTxt == "First eigenvector") realName = elementPath + "filters/Eigen1.ref"; else if (tmpTxt == "Blocked IRF") realName = elementPath + "filters/EmpiricalBlocked_IRF.ref"; else if (tmpTxt == "Poisson") realName = elementPath + "filters/Poisson_IRF.ref"; else realName = elementPath + "filters/" + tmpTxt + ".ref"; return realName; } /*This is the slot to take care of combo box 2 when selecting noise models, * very similar to the slot above */ void glm::noiseModSelected(int selection) { if (selection == 0) { noiseFile = QString::null; noiseModel->clear(); } else if (selection == 1) { noiseFile = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load a filter file", "Please choose your filter."); if (noiseFile.length() != 0) { noiseModel->setText("File loaded is: " + noiseFile + ""); } } else { noiseFile = getNoiseFile(selection); noiseModel->setText("File loaded is: " + noiseFile + ""); } } /* getNoiseFile(int) returns the noise model's real file name */ QString glm::getNoiseFile(int comboIndex) { if (comboIndex < 2) return QString::null; QString tmpTxt = combo2->text(comboIndex); QString realName; if (tmpTxt == "Unsmooth, No GSCV") realName = elementPath + "noisemodels/unsmooth_params.ref"; else if (tmpTxt == "Smooth, No GSCV") realName = elementPath + "noisemodels/smooth_params.ref"; else if (tmpTxt == "Unsmooth, with GSCV") realName = elementPath + "noisemodels/unsmooth__GCV_params.ref"; else if (tmpTxt == "Smooth, with GSCV") realName = elementPath + "noisemodels/smooth__GCV_params.ref"; else realName = elementPath + "noisemodels/"+ tmpTxt + ".ref"; return realName; } // Slot when "Create empirical 1/f" button is clicked void glm::oneOverFClicked() { QString psFile = Q3FileDialog::getOpenFileName (QString::null, "PS files (*_PS.ref)", this, "Load a power spectrum file", "Please choose the PS file"); if (!psFile.length()) return; QString condFile = Q3FileDialog::getOpenFileName (QString::null, "Ref files (*.ref)", this, "Load a condition function mask (cancel for none)", "Please choose condition function mask"); QString defaultName = pathText + "/OneOverFParams.ref"; QString paramFileName = Q3FileDialog::getSaveFileName(defaultName, tr("Ref Files (*.ref);;All Files (*)"), this, "Save Fitting Parameter File", "Choose a filename to save the fitting parameters under: "); QFileInfo *paramFileInfo = new QFileInfo(paramFileName); // What will happen if the file already exists? if (paramFileInfo->exists()) { // pathString is the absolute path of the G matrix file QString pathString = paramFileInfo->dirPath(true); QFileInfo *paramFilePath = new QFileInfo(pathString); switch(QMessageBox::warning(0, "Warning!", paramFileName + " already exists. Are you sure you want to overwrite this file now?", "Yes", "No", "Cancel", 0, 2)) { // "Yes", simply overwrite the file case 0: if (!paramFilePath->isWritable()) // Check if this directory is writable or not QMessageBox::critical(0, "Error!", "You are not permitted to write file in this directory: " + pathString); break; // If "No", nothing happens so far. How can I make it to start from the beginning? case 1: break; return; case 2: // If "cancel" is clicked, close the function break; return; } } else { // pathString is the absolute path of the G matrix file QString pathString = paramFileInfo->dirPath(true); QFileInfo *paramFilePath = new QFileInfo(pathString); // Check if this directory is writable or not if (!paramFilePath->isWritable()) QMessageBox::critical(0, "Error!", "You are not permitted to write file in this directory: " + pathString); } double var3min = -1.0 / (totalReps * g_TR / 1000.0); if (!condFile.length()) fitOneOverF((const char *)psFile, var3min, (double)g_TR, 0.1, 20.0, 2.0, -0.0001, (const char *)paramFileName); else fitOneOverF((const char *)psFile, (const char *)condFile, var3min, (double)g_TR, 0.1, 20.0, 2.0, -0.0001, (const char *)paramFileName); } /* Set up "Submit" and "Cancel" buttons at the bottom */ void glm::setupButtons() { mainSubmitButton = new QPushButton("&Submit", this); QPushButton *mainCancelButton = new QPushButton("&Quit", this); mainNextButton = new QPushButton("&Next", this); buttons->addStretch(2); buttons->addWidget(mainSubmitButton, 1, Qt::AlignRight); buttons->addStretch(1); buttons->addWidget(mainCancelButton, 1, Qt::AlignLeft); buttons->addStretch(1); buttons->addWidget(mainNextButton, 1, Qt::AlignLeft); buttons->addStretch(2); mainSubmitButton->setDisabled(true); connect(tabSection, SIGNAL(currentChanged(QWidget *)), this, SLOT(tabChange())); connect(mainSubmitButton, SIGNAL(clicked()), this, SLOT(submitAll())); connect(mainCancelButton, SIGNAL(clicked()), this, SLOT(close())); connect(mainNextButton, SIGNAL(clicked()), this, SLOT(clickNext())); } /* Slot to enable the main "submit" button when user is on the last step interface. */ void glm::tabChange() { int tabIdx = tabSection->currentPageIndex(); if (tabIdx == 3) { if (covList.size() && tab2_lb2->count()) mainSubmitButton->setEnabled(true); mainNextButton->hide(); setFilterHint(); return; } mainNextButton->show(); string status; if (tabIdx == 2) { if (TR) { tab3_TR = TR; status+="TR: "+strnum(tab3_TR) + "ms, "; } else if (tab2_lb2->count()) { tab3_TR = 1000; status+="TR: 1000ms, "; } else status+="TR: not set, "; if (totalReps) status+="; Number of Points: " + strnum(totalReps); else status+="; Number of Points: not set"; tab3->status->setText(status.c_str()); if (!tab3->covView->childCount()) mainNextButton->setDisabled(true); } } /* clickNext() will guide user glm's next step interface */ void glm::clickNext() { int glmIndex = tabSection->currentPageIndex(); if (glmIndex == 0) enableTab2(); else if (glmIndex == 1) enableTab3(); else if (glmIndex == 2) { //tabSection->setTabEnabled(tab4, true); tabSection->setCurrentPage(3); } } // submitAll() populates a GLMParams structure, writes out the G // matrix, and then uses GLMParams to create the GLM dir and job // sequence void glm::submitAll() { if (!chkSubmit()) return; GLMParams gp; gp.TR=TR; gp.dirname=pathText.toStdString(); string stemname=gp.dirname+"/"+xfilename(gp.dirname); gp.gmatrix=stemname+".G"; mkdir(gp.dirname.c_str(),0777); writeG(stemname,g_TR,totalReps,tmpResolve, covList,tab3->covView,condRef,condKey,meanAll); gp.name=seqEditor->text().toStdString(); gp.dirname=pathText.toStdString(); for (uint32 i=0; icount(); i++) gp.scanlist.push_back(tab2_lb2->text(i).toStdString()); gp.lows=strtol(belowEdit->text().toStdString()); gp.highs=strtol(aboveEdit->text().toStdString()); gp.orderg=totalReps; if (pieceCheck->isChecked()) gp.pieces=strtol(pieceEditor->text().toStdString()); else gp.pieces=0; if (filterFile.size()) { gp.kernelname=filterFile.toStdString(); gp.kerneltr=kTR; } if (noiseFile.size()) gp.noisemodel=noiseFile.toStdString(); if (condRef.length()>0) gp.refname=condRef.toStdString(); gp.pri=priCombo->currentItem()+1; if (auditCheck->isChecked()) gp.auditflag=1; else gp.auditflag=0; if (meanCheck->isChecked()) gp.meannorm=1; else gp.meannorm=0; if (driftCheck->isChecked()) gp.driftcorrect=1; else gp.driftcorrect=0; if (emailCheck->isChecked()) gp.email=emailEditor->text().toStdString(); gp.FixRelativePaths(); gp.CreateGLMDir(); gp.CreateGLMJobs2(); if (vbp.cores) { QRunSeq qr; qr.Go(vbp,gp.seq,vbp.cores); qr.exec(); } else { if (gp.seq.Submit(vbp)) QMessageBox::critical(0, "Error", "Error submitting your GLM to the queue."); else QMessageBox::information(0, "Submitted", "Your GLM has been submitted to the queue"); } // this->close(); return; } /* closeEvent is an overloaded function called when user clicks "quit" or the "x" button * on the upperleft corner. If yes, close the window; if no, nothing happens. */ void glm::closeEvent(QCloseEvent *ce) { if (endFlag) { ce->accept(); return; } switch(QMessageBox::warning(0, "Warning!", "Are you sure you want to quit GLM program? \

Your previous setup will be aborted without a backup!","Quit", "Don't Quit", QString::null, 0, 1)) { case 0: ce->accept(); break; case 1: ce->ignore(); break; } } voxbo-1.8.5~svn1246/qtglm/glm.h000066400000000000000000000104621153177201300162030ustar00rootroot00000000000000 // glm.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu #ifndef GLM_H #define GLM_H #include "glm_tab3.h" #include "gdw.h" #include #include #include #include #include #include //Added by qt3to4: #include #include #include class QCheckBox; class Q3FileDialog; class Q3HBox; class Q3HBoxLayout; class QPushButton; class glm : public QWidget { Q_OBJECT public: glm( QWidget *parent, const char *name ); private slots: void tab1_browse(); void tab1_pathChanged(); void enableTab2(); void tab2Browse(); void tab2_listChanged(); void lb1_select(int ); void lb2_select(int ); void tab2_slotLeft2Right(); void tab2_slotLeft2Right_all(); void tab2_slotRight2Left(); void tab2_slotRight2Left_all(); void enableTab3(); void tab3_edit(); void tab3_load(); void tab3_clear(); void tab3_model(int); void tab3_blockUI(); void tab3_pairUI(); void tab3_inter(); void okBlock(); void cancelBlock(); void okPair(); void cancelPair(); void gdwDone(vector , Q3ListView *, int, QString, tokenlist, bool); void cpGdwList(vector ); void convertBelow(); void convertAbove(); void smoothKernSelected(int); void noiseModSelected(int); void oneOverFClicked(); void tabChange(); void submitAll(); void clickNext(); private: void setupTab1(); void setupTab2(); void setupTab3(); void setupTab4(); void setFilterHint(); void setupButtons(); void closeEvent(QCloseEvent *); void setElementPath(); QString getFilterFile(int ); QString getNoiseFile(int ); bool chkTab1(); bool chkAnalysisDIR(); bool chkTesFile(QString); int getTesTR(QString); void updateTR(); int getTesImgNo(QString); int tesChanged(); void setupTab3_view(); void tab3_readG(string); void buildCovList(bool); void buildTree(); Q3ListViewItem * searchDepth0(QString grpName); bool chkG(string inputName); bool cmpTR(int headerTR); bool cmpTotalReps(int rowNum); bool chkPreG(string inputName); void clearG(); bool chkBlockUI(); bool chkPairUI(); void addIntercept(); void updateInterceptID(); bool chkSubmit(); QTabWidget *tabSection; Q3HBoxLayout *buttons; Q3VBox *tab1; QString pathText, fileName, gFileName; QLineEdit *pathEditor; QFileInfo folderInfo; QLabel *finalName; QLineEdit *seqEditor; QComboBox *priCombo; QCheckBox *auditCheck, *emailCheck, *pieceCheck; QLineEdit *emailEditor, *pieceEditor; Q3VBox *tab2; QString tab2_dirName; QLineEdit *dirEditor, *tab2Filter; QString tab2_filterText; Q3ListBox *tab2_lb1; Q3ListBox *tab2_lb2; int totalReps, TR; bool endFlag; glm_tab3 *tab3; vector< int > interceptID; gHeaderInfo myGInfo; bool meanAll, pregStat; VBMatrix gMat, pregMat; vector< VB_Vector *> covList; QString condRef; tokenlist condKey; int tab3_TR, tmpResolve; int g_TR, g_totalReps; bool gUpdate; BlockDesign *tab3_block; int firstLen, secondLen; int first, second; PairDesign *tab3_pair; Q3VBox *tab4; QLabel *filter_hint; QLineEdit *belowEdit, *aboveEdit; QLabel *belowLab, *aboveLab; QLabel *smoothKernel; QLineEdit *kernelTR; QComboBox *combo1, *combo2; QString elementPath, filterFile; unsigned kTR; QCheckBox *meanCheck, *driftCheck; QLabel *noiseModel; QString noiseFile; QPushButton *mainSubmitButton, *mainNextButton; }; #endif voxbo-1.8.5~svn1246/qtglm/glm.hlp000066400000000000000000000002461153177201300165360ustar00rootroot00000000000000 VoxBo glm (v%1%) summary: glm construction graphical interface usage: glm flags: -h show help -v show version voxbo-1.8.5~svn1246/qtglm/glm_main.cpp000066400000000000000000000036501153177201300175430ustar00rootroot00000000000000 // glm_main.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu using namespace std; #include "vbprefs.h" #include "glm.h" #include #include #include #include "glm.hlp.h" void glm_help(); void glm_version(); VBPrefs vbp; int main( int argc, char **argv ) { tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; iresize( 630, 490 ); glm_main->setCaption( "GLM Main Interface" ); a.setMainWidget( glm_main ); glm_main->show(); a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); int result = a.exec(); delete glm_main; return result; } void glm_help() { cout << format(myhelp) % vbversion; } void glm_version() { cout << format("VoxBo glm (v%s)\n")%vbversion; } voxbo-1.8.5~svn1246/qtglm/glm_tab3.cpp000066400000000000000000000040521153177201300174450ustar00rootroot00000000000000 #include "glm_tab3.h" #include #include #include #include #include #include #include #include "myboxes.h" glm_tab3::glm_tab3(QWidget* parent, const char* name) : QWidget(parent,name) { // (void)statusBar(); if ( !name ) setName( "glm_tab3" ); QHBoxLayout *hb=new QHBoxLayout(); setLayout(hb); QVBoxLayout *vb=new QVBoxLayout(); hb->addLayout(vb); label1 = new QLabel; vb->addWidget(label1); covView = new Q3ListView(this, "covView" ); vb->addWidget(covView); covView->addColumn( tr( "Column 1" ) ); // covView->setGeometry( QRect( 10, 70, 330, 310 ) ); status=new QLabel; vb->addWidget(status); QHBox *tmph=new QHBox; vb->addWidget(tmph); editButt = new QPushButton(this,"editButt" ); tmph->addWidget(editButt); loadButt = new QPushButton(this,"loadButt" ); tmph->addWidget(loadButt); clearButt = new QPushButton(this, "clearButt" ); tmph->addWidget(clearButt); QGroupBox *gb=new QGroupBox("Quick Models"); hb->addWidget(gb); QVBoxLayout *vv=new QVBoxLayout(); vv->setAlignment(Qt::AlignTop); gb->setLayout(vv); blockButt = new QPushButton(this, "blockButt" ); vv->addWidget(blockButt); pairButt = new QPushButton(this, "pairButt" ); vv->addWidget(pairButt); interButt = new QPushButton(this, "interButt" ); vv->addWidget(interButt); languageChange(); // resize( QSize(518, 442).expandedTo(minimumSizeHint()) ); // clearWState( WState_Polished ); } void glm_tab3::languageChange() { clearButt->setText( tr( "Clear" ) ); editButt->setText( tr( "Edit G" ) ); loadButt->setText( tr( "Load G" ) ); covView->header()->setLabel( 0, tr( "Column 1" ) ); covView->clear(); Q3ListViewItem * item = new Q3ListViewItem( covView, 0 ); item->setText( 0, tr( "New Item" ) ); label1->setText( tr( "Current G Matrix" ) ); status->setText(""); blockButt->setText( tr( "Block Design" ) ); pairButt->setText( tr( "Paired t-Test" ) ); interButt->setText( tr( "Intercept-Only" ) ); } voxbo-1.8.5~svn1246/qtglm/glm_tab3.h000066400000000000000000000020241153177201300171070ustar00rootroot00000000000000/**************************************************************************** ** Form interface generated from reading ui file 'glm_tab3.ui' ** ** Created: Thu Feb 8 15:58:07 2007 ** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.4 edited Nov 24 2003 $) ** ** WARNING! All changes made in this file will be lost! ****************************************************************************/ #ifndef GLM_TAB3_H #define GLM_TAB3_H #include #include #include class QSpacerItem; class Q3ToolBar; class QPushButton; class Q3ListView; class Q3ListViewItem; class QLabel; class Q3ButtonGroup; class glm_tab3 : public QWidget { Q_OBJECT public: glm_tab3(QWidget* parent=0,const char* name=0); QPushButton* clearButt; QPushButton* editButt; QPushButton* loadButt; Q3ListView* covView; QLabel* label1; QLabel* status; QPushButton* blockButt; QPushButton* pairButt; QPushButton* interButt; protected: protected slots: virtual void languageChange(); }; #endif // GLM_TAB3_H voxbo-1.8.5~svn1246/qtglm/glm_tab3.ui000066400000000000000000000162011153177201300172770ustar00rootroot00000000000000 glm_tab3 glm_tab3 0 0 518 442 Form4 clearButt 230 390 70 31 11 Clear editButt 30 390 70 31 11 Edit G loadButt 130 390 70 31 11 Load G Column 1 true true New Item covView 10 70 330 310 label1 100 20 150 20 14 1 Current G Matrix TR 10 50 130 20 11 TR: AlignVCenter|AlignRight totalReps 140 50 200 20 11 Number of Points: modelGrp 350 20 170 400 14 1 0 Canned Models AlignHCenter blockButt 10 30 151 31 0 Block Design pairButt 10 70 151 31 0 Paired t-Test covView editButt loadButt clearButt blockButt pairButt voxbo-1.8.5~svn1246/qtglm/paired.cpp000066400000000000000000000116371153177201300172300ustar00rootroot00000000000000/**************************************************************************** ** Form implementation generated from reading ui file 'paired.ui' ** ** Created: Tue Jan 23 10:57:45 2007 ** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.4 edited Nov 24 2003 $) ** ** WARNING! All changes made in this file will be lost! ****************************************************************************/ #include "paired.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Constructs a PairDesign as a child of 'parent', with the * name 'name' and widget flags set to 'f'. * */ PairDesign::PairDesign( QWidget* parent, const char* name, Qt::WFlags fl ) : Q3MainWindow( parent, name, fl ) { (void)statusBar(); if ( !name ) setName( "PairDesign" ); setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 0, 0, sizePolicy().hasHeightForWidth() ) ); setCentralWidget( new QWidget( this, "qt_central_widget" ) ); textLabel2 = new QLabel( centralWidget(), "textLabel2" ); textLabel2->setGeometry( QRect( 20, 50, 90, 20 ) ); QFont textLabel2_font( textLabel2->font() ); textLabel2_font.setPointSize( 11 ); textLabel2->setFont( textLabel2_font ); textLabel2->setAlignment( int( Qt::AlignCenter ) ); numberEditor = new QLineEdit( centralWidget(), "numberEditor" ); numberEditor->setGeometry( QRect( 160, 150, 100, 25 ) ); QFont numberEditor_font( numberEditor->font() ); numberEditor_font.setPointSize( 12 ); numberEditor->setFont( numberEditor_font ); numberEditor->setCursorPosition( 0 ); orderGroup = new Q3ButtonGroup( centralWidget(), "orderGroup" ); orderGroup->setGeometry( QRect( 20, 90, 240, 50 ) ); QFont orderGroup_font( orderGroup->font() ); orderGroup_font.setPointSize( 9 ); orderGroup->setFont( orderGroup_font ); orderGroup->setLineWidth( 0 ); orderGroup->setAlignment( int( Qt::AlignHCenter ) ); subject = new QRadioButton( orderGroup, "subject" ); subject->setGeometry( QRect( 10, 0, 230, 20 ) ); QFont subject_font( subject->font() ); subject_font.setPointSize( 11 ); subject->setFont( subject_font ); subject->setChecked( TRUE ); group = new QRadioButton( orderGroup, "group" ); group->setGeometry( QRect( 10, 30, 230, 20 ) ); QFont group_font( group->font() ); group_font.setPointSize( 11 ); group->setFont( group_font ); textLabel1 = new QLabel( centralWidget(), "textLabel1" ); textLabel1->setGeometry( QRect( 90, 10, 110, 30 ) ); QFont textLabel1_font( textLabel1->font() ); textLabel1_font.setPointSize( 12 ); textLabel1_font.setBold( TRUE ); textLabel1_font.setUnderline( TRUE ); textLabel1->setFont( textLabel1_font ); textLabel5 = new QLabel( centralWidget(), "textLabel5" ); textLabel5->setGeometry( QRect( 20, 150, 140, 20 ) ); QFont textLabel5_font( textLabel5->font() ); textLabel5_font.setPointSize( 11 ); textLabel5->setFont( textLabel5_font ); textLabel5->setAlignment( int( Qt::AlignCenter ) ); nameEditor = new QLineEdit( centralWidget(), "nameEditor" ); nameEditor->setGeometry( QRect( 110, 50, 150, 25 ) ); QFont nameEditor_font( nameEditor->font() ); nameEditor_font.setPointSize( 12 ); nameEditor->setFont( nameEditor_font ); cancelButton = new QPushButton( centralWidget(), "cancelButton" ); cancelButton->setGeometry( QRect( 160, 190, 70, 30 ) ); okButton = new QPushButton( centralWidget(), "okButton" ); okButton->setGeometry( QRect( 60, 190, 70, 30 ) ); // toolbars languageChange(); resize( QSize(278, 242).expandedTo(minimumSizeHint()) ); // clearWState( WState_Polished ); // tab order setTabOrder( nameEditor, subject ); setTabOrder( subject, numberEditor ); setTabOrder( numberEditor, okButton ); setTabOrder( okButton, cancelButton ); setTabOrder( cancelButton, group ); } /* * Destroys the object and frees any allocated resources */ PairDesign::~PairDesign() { // no need to delete child widgets, Qt does it all for us } /* * Sets the strings of the subwidgets using the current * language. */ void PairDesign::languageChange() { setCaption( tr( "Paired Design" ) ); textLabel2->setText( tr( "Effect Name:" ) ); numberEditor->setInputMask( QString::null ); orderGroup->setTitle( QString::null ); subject->setText( tr( "Subjects together (AABBCC...)" ) ); group->setText( tr( "Groups together (ABCABC...)" ) ); textLabel1->setText( tr( "Paired t-Test" ) ); textLabel5->setText( tr( "Number of Subjects:" ) ); nameEditor->setText( tr( "group" ) ); cancelButton->setText( tr( "Cancel" ) ); okButton->setText( tr( "OK" ) ); } voxbo-1.8.5~svn1246/qtglm/paired.h000066400000000000000000000026411153177201300166700ustar00rootroot00000000000000/**************************************************************************** ** Form interface generated from reading ui file 'paired.ui' ** ** Created: Tue Jan 23 10:57:45 2007 ** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.4 edited Nov 24 2003 $) ** ** WARNING! All changes made in this file will be lost! ****************************************************************************/ #ifndef PAIRDESIGN_H #define PAIRDESIGN_H #include #include //Added by qt3to4: #include #include #include #include #include #include class Q3VBoxLayout; class Q3HBoxLayout; class Q3GridLayout; class QSpacerItem; class QAction; class Q3ActionGroup; class Q3ToolBar; class Q3PopupMenu; class QLabel; class QLineEdit; class Q3ButtonGroup; class QRadioButton; class QPushButton; class PairDesign : public Q3MainWindow { Q_OBJECT public: PairDesign( QWidget* parent = 0, const char* name = 0, Qt::WFlags fl = Qt::WType_TopLevel ); ~PairDesign(); QLabel* textLabel2; QLineEdit* numberEditor; Q3ButtonGroup* orderGroup; QRadioButton* subject; QRadioButton* group; QLabel* textLabel1; QLabel* textLabel5; QLineEdit* nameEditor; QPushButton* cancelButton; QPushButton* okButton; protected: protected slots: virtual void languageChange(); }; #endif // PAIRDESIGN_H voxbo-1.8.5~svn1246/qtglm/paired.ui000066400000000000000000000162311153177201300170560ustar00rootroot00000000000000 PairDesign PairDesign 0 0 278 242 5 5 0 0 Paired Design textLabel2 20 50 90 20 11 Effect Name: AlignCenter numberEditor 160 150 100 25 12 0 orderGroup 20 90 240 50 9 0 AlignHCenter subject 10 0 230 20 11 Subjects together (AABBCC...) true group 10 30 230 20 11 Groups together (ABCABC...) textLabel1 90 10 110 30 12 1 1 Paired t-Test textLabel5 20 150 140 20 11 Number of Subjects: AlignCenter nameEditor 110 50 150 25 12 group cancelButton 160 190 70 30 Cancel okButton 60 190 70 30 OK nameEditor subject numberEditor okButton cancelButton group voxbo-1.8.5~svn1246/qtglm/vbpermgen.cpp000066400000000000000000000545101153177201300177460ustar00rootroot00000000000000 // vbpermgen.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Tom King and Dan Kimberg #include "vbpermgen.moc.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vbprefs.h" #include "vbx.h" #include #include #include "vbcontrast.h" #include "runseq.h" #include "vbpermgen.hlp.h" using namespace std; void vbpermgen_help(); void vbpermgen_version(); int commandlineExecute(int argc, char **argv); VBPrefs vbp; VBSequence seq; VBJobSpec js; string tempPRM; int msgboxsetpermnumber; gsl_rng *theRNG; int main( int argc, char ** argv ) { vbp.init(); vbp.read_jobtypes(); if (argc > 2) { int err = 0; err = commandlineExecute(argc, argv); if (err) switch (err) { case 1: printErrorMsg(VB_ERROR, "vbpermgen: bad argument structure.\n"); return -1; case 2: printErrorMsg(VB_ERROR, "vbpermgen: no matrix stem name indicated.\n"); return -1; case 3: printErrorMsg(VB_ERROR, "vbpermgen: no permutation directory indicated.\n"); return -1; case 4: printErrorMsg(VB_ERROR, "vbpermgen: no method indicated.\n"); return -1; case 5: printErrorMsg(VB_ERROR, "vbpermgen: number of permutations not indicated.\n"); return -1; case 6: printErrorMsg(VB_ERROR, "vbpermgen: scale not indicated.\n"); return -1; case 7: printErrorMsg(VB_ERROR, "vbpermgen: no contrasts inciated.\n"); return -1; case 8: printErrorMsg(VB_ERROR, "vbpermgen: number of permuations desired exceeds number possible.\n"); return -1; } return 0; } QApplication a(argc,argv); permGenerator pg; if (argc > 0) { if (strcmp(argv[argc-1], "-h")==0) { vbpermgen_help(); exit(0); } } QFont font( "SansSerif", 10, 0 ); font.setStyleHint( QFont::SansSerif ); a.setFont( font ); pg.setFont( font ); a.setMainWidget(&pg); pg.show(); a.connect( &a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()) ); return a.exec(); } permGenerator::permGenerator( QWidget* parent, const char* name, bool modal, Qt::WFlags fl ) : QDialog( parent, name, modal, fl ) { if ( !name ) setName( "permGenerator" ); Q3BoxLayout *x = new Q3VBoxLayout(this); txtPRM = new QLineEdit( this, "txtPRM" ); txtPRM->setGeometry( QRect( 250, 10, 170, 24 ) ); connect(txtPRM, SIGNAL(textChanged(const QString &)), this, SLOT(CalculateNumPerms())); pbDir = new QPushButton( this, "pbDir" ); pbDir->setGeometry( QRect( 50, 10, 180, 20 ) ); connect(pbDir, SIGNAL(clicked()), this, SLOT(getPRMFile())); Q3BoxLayout *y = new Q3HBoxLayout(x); y->insertWidget(0, pbDir, 10, Qt::AlignRight); y->addSpacing(30); y->insertWidget(2, txtPRM, 10, Qt::AlignTop); y->addStretch(1); y->setMargin(5); txtPermDir = new QLineEdit( this, "txtPermDir" ); txtPermDir->setGeometry( QRect( 250, 40, 170, 24 ) ); lblPermDir = new QLabel( this, "lblPermNumber" ); lblPermDir->setGeometry( QRect( 90, 130, 140, 20 ) ); Q3BoxLayout *y1 = new Q3HBoxLayout(x); y1->insertWidget(0, lblPermDir, 10, Qt::AlignRight); y1->addSpacing(30); y1->insertWidget(2, txtPermDir, 10, Qt::AlignTop); y1->addStretch(1); y1->setMargin(5); txtContrasts = new QLineEdit( this, "txtContrasts" ); txtContrasts->setGeometry( QRect( 250, 70, 100, 24 ) ); btnContrasts = new QPushButton(this,"btnContrasts"); btnContrasts->setGeometry(QRect(395,70,100,24)); btnContrasts->setText("Edit"); QObject::connect(btnContrasts,SIGNAL(clicked()),this,SLOT(getContrast())); lblContrasts = new QLabel( this, "lblContrasts" ); lblContrasts->setGeometry( QRect( 130, 70, 100, 20 ) ); Q3BoxLayout *y2 = new Q3HBoxLayout(x); y2->insertWidget(0, lblContrasts, 10, Qt::AlignRight); y2->addSpacing(30); y2->insertWidget(2, txtContrasts, 10, Qt::AlignTop); y2->addSpacing(5); y2->insertWidget(4,btnContrasts,5,Qt::AlignTop); y2->addStretch(1); y2->setMargin(5); // cbScale = new QComboBox( this, "txtScale" ); // cbScale->setGeometry( QRect( 250, 100, 170, 24 ) ); // lblScale = new QLabel( this, "lblScale" ); // lblScale->setGeometry( QRect( 130, 100, 100, 20 ) ); // Q3BoxLayout *y5 = new Q3HBoxLayout(x); // y5->insertWidget(0, lblScale, 10, Qt::AlignRight); // y5->addSpacing(30); // y5->insertWidget(2, cbScale, 10, Qt::AlignTop); // y5->addStretch(1); // y5->setMargin(5); txtPermNumber = new QLineEdit( this, "txtPermNumber" ); txtPermNumber->setGeometry( QRect( 250, 130, 170, 24 ) ); connect(txtPermNumber, SIGNAL(textChanged(const QString &)), this, SLOT(warnCalculateNumPerms())); lblPermNumber = new QLabel( this, "lblPermNumber" ); lblPermNumber->setGeometry( QRect( 90, 130, 140, 20 ) ); Q3BoxLayout *y3 = new Q3HBoxLayout(x); y3->insertWidget(0, lblPermNumber, 10, Qt::AlignRight); y3->addSpacing(30); y3->insertWidget(2, txtPermNumber, 10, Qt::AlignTop); y3->addStretch(1); y3->setMargin(5); lblPseudoT = new QLabel( this, "lblPseudoT" ); lblPseudoT->setGeometry( QRect(10, 150, 143, 40) ); QCheckBox *on=new QCheckBox("on/off",this); on->setChecked(0); on->setGeometry( QRect( 160, 160, 60, 21 ) ); QObject::connect(on,SIGNAL(toggled(bool)),this,SLOT(mod(bool))); txtZ = new QLineEdit( this, "txtZ" ); txtZ->setGeometry( QRect( 390, 160, 30, 24 ) ); txtZ->setDisabled(true); lblZ = new QLabel( this, "lblZ" ); lblZ->setGeometry( QRect( 370, 160, 16, 21 ) ); txtX = new QLineEdit( this, "txtX" ); txtX->setGeometry( QRect( 270, 160, 30, 24 ) ); txtX->setDisabled(true); txtY = new QLineEdit( this, "txtY" ); txtY->setGeometry( QRect( 330, 160, 30, 24 ) ); txtY->setDisabled(true); lblX = new QLabel( this, "lblX" ); lblX->setGeometry( QRect( 250, 160, 16, 20 ) ); lblY = new QLabel( this, "lblY" ); lblY->setGeometry( QRect( 310, 160, 16, 20 ) ); Q3BoxLayout *y4 = new Q3HBoxLayout(x); y4->addSpacing(10); y4->insertWidget(1, lblPseudoT, 10, Qt::AlignRight); y4->addSpacing(10); y4->insertWidget(3, on, 10, Qt::AlignRight); y4->addSpacing(10); y4->insertWidget(5, lblX, 10, Qt::AlignRight); y4->addSpacing(5); y4->insertWidget(7, txtX, 10, Qt::AlignTop); y4->addSpacing(10); y4->insertWidget(9, lblY, 10, Qt::AlignRight); y4->addSpacing(5); y4->insertWidget(11, txtY, 10, Qt::AlignTop); y4->addSpacing(10); y4->insertWidget(13, lblZ, 10, Qt::AlignRight); y4->addSpacing(5); y4->insertWidget(15, txtZ, 10, Qt::AlignTop); y4->addStretch(1); y4->setMargin(5); lblPermType = new QLabel( this, "lblPermType" ); lblPermType->setGeometry( QRect( 0, 190, 230, 20 ) ); cbPermType = new QComboBox( this, "cbPermType" ); cbPermType->setGeometry( QRect( 250, 190, 170, 24 ) ); Q3BoxLayout *y6 = new Q3HBoxLayout(x); y6->insertWidget(0, lblPermType, 10, Qt::AlignRight); y6->addSpacing(30); y6->insertWidget(2, cbPermType, 10, Qt::AlignTop); y6->addStretch(1); y6->setMargin(5); line2 = new Q3Frame( this, "line2" ); line2->setGeometry( QRect( 21, 220, 400, 20 ) ); line2->setFrameShape( Q3Frame::HLine ); line2->setFrameShadow( Q3Frame::Sunken ); line2->setFrameShape( Q3Frame::HLine ); Q3BoxLayout *y7 = new Q3HBoxLayout(x); y7->addSpacing(10); y7->addWidget(line2, 10, Qt::AlignTop); y7->addSpacing(10); y7->setMargin(5); sbPriority = new QSpinBox( this, "sbPriority" ); sbPriority->setGeometry( QRect( 360, 240, 41, 20 ) ); sbPriority->setMaxValue( 5 ); sbPriority->setMinValue( 0 ); sbPriority->setValue( 3 ); txtSN = new QLineEdit( this, "txtSN" ); txtSN->setGeometry( QRect( 140, 240, 130, 23 ) ); lblPriority = new QLabel( this, "lblPriority" ); lblPriority->setGeometry( QRect( 300, 240, 50, 21 ) ); lblSN = new QLabel( this, "lblSequenceName" ); lblSN->setGeometry( QRect( 30, 240, 111, 21 ) ); Q3BoxLayout *y8 = new Q3HBoxLayout(x); y8->addSpacing(30); y8->insertWidget(1, lblSN, 10, Qt::AlignRight); y8->addSpacing(30); y8->insertWidget(3, txtSN, 10, Qt::AlignTop); y8->addSpacing(10); y8->insertWidget(5, lblPriority, 10, Qt::AlignRight); y8->addSpacing(30); y8->insertWidget(7, sbPriority, 10, Qt::AlignLeft); y8->addStretch(1); y8->setMargin(5); pbCancel = new QPushButton( this, "pbCancel" ); pbCancel->setGeometry( QRect( 310, 280, 110, 30 ) ); connect(pbCancel, SIGNAL(clicked()), this, SLOT(exitProgram())); pbGO = new QPushButton( this, "pbGO" ); pbGO->setGeometry( QRect( 30, 280, 120, 30 ) ); connect(pbGO, SIGNAL(clicked()), this, SLOT(pressed())); Q3BoxLayout *y10 = new Q3HBoxLayout(x); y10->addSpacing(30); y10->insertWidget(1, pbGO, 10, Qt::AlignTop); y10->addSpacing(100); y10->insertWidget(3, pbCancel, 10, Qt::AlignTop); y10->addSpacing(30); y10->addStretch(1); y10->setMargin(5); languageChange(); resize( QSize(436, 318).expandedTo(minimumSizeHint()) ); } void permGenerator::languageChange() { setCaption( tr( "Permutation Generator" ) ); lblZ->setText( tr( "z:" ) ); lblX->setText( tr( "x:" ) ); lblY->setText( tr( "y:" ) ); txtX->insert("0"); txtY->insert("0"); txtZ->insert("0"); pbGO->setText( tr( "Submit Jobs" ) ); lblContrasts->setText( tr( "Contrast:" ) ); // lblScale->setText( tr( "Scale:" ) ); txtPermNumber->insert("0"); lblPermNumber->setText( tr( "Number of Permutations:" ) ); lblPseudoT->setText( tr( "Smoothing for Pseudo-t \n" "map (FWHM in Voxels):" ) ); lblPermType->setText( tr( " Perm Type:" ) ); pbDir->setText( tr( "Select PRM File" ) ); lblPriority->setText( tr( "Priority:" ) ); lblSN->setText( tr( "Sequence Name:" ) ); lblPermDir->setText( tr( "Perm Directory (to be created):" ) ); txtPermDir->setText("perm"); cbPermType->addItem("sign flipping"); cbPermType->addItem("order permutation"); pbCancel->setText( tr( "Cancel" ) ); msgboxsetpermnumber = 0; } void permGenerator::mod(bool x) { txtX->setEnabled(x); txtY->setEnabled(x); txtZ->setEnabled(x); if (x == FALSE) { txtX->clear(); txtX->insert("0"); txtY->clear(); txtY->insert("0"); txtZ->clear(); txtZ->insert("0"); } return; } QString permGenerator::getPRMFile() { QString s=Q3FileDialog::getOpenFileName(".","All (*.prm)",this,"open .prm file","Choose a .prm file to load"); if (s==QString::null) return QString(""); tempPRM = s.ascii(); txtPRM->clear(); createfullpath(s.ascii()); txtPRM->insert(s.ascii()); if (s==QString::null) return QString(""); else return s; } void permGenerator::getContrast() { VB::VBContrastParamScalingWidget vv; vv.showBrowseButton(1); // vv.writeFilesOnExit(1); string stem=xsetextension(txtPRM->text().toStdString(),""); vv.LoadContrastInfo(stem); if (vv.exec()) { string cstring="anon "; cstring+=vv.selectedContrast()->scale+" vec "; GLMInfo glmi; glmi.setup(stem); for (size_t i=0; icontrast[glmi.interestlist[i]]).str(); } txtContrasts->setText(cstring.c_str()); } } int commandlineExecute(int argc, char **argv) { GLMInfo glmi; string matrixStemName,permdir,seqname,clist,plist; VB_permtype method=vb_noperm; tokenlist args; int nperms=1; uint32 rngseed=0; args.Transfer(argc-1,argv+1); for (size_t i=0; i maxPerms) return 8; string presentDir=xgetcwd()+"/"; struct stat my_stat; if (glmi.parsecontrast(clist) != 0) { cout << "[E] vbpermgen: failed to derive a valid contrast from " << clist << endl; return -1; } permclass pc; pc.rngseed=rngseed; pc.stemname=glmi.stemname; pc.permdir=permdir; pc.method=method; pc.contrast=clist; pc.pseudotlist=plist; pc.SetFileName("perminfo.txt"); pc.AddPrmTimeStamp(glmi.stemname); string pfile=xdirname(glmi.stemname)+"/"+permdir+"/permutations.mat"; permStart(pc); pc.SavePermClass(); memset((void*)&my_stat, 0, sizeof(my_stat)); seq.init(); QString name; int count = 0; if (nperms > 0) { for (int permIndex = 0; permIndex < nperms; permIndex++) { js.init(); js.arguments.clear(); js.jobtype="shellcommand"; string cmd=(format("permstep -m %s -d %s -t %s -c '%s' %s -n %d") %glmi.stemname%permdir%permclass::methodstring(method) %clist%(plist.size()?(string)"-p "+plist:"") %permIndex).str(); if (method==vb_signperm) cmd+=" -e"; js.arguments["command"]=cmd; js.magnitude=0; js.name=permdir; js.dirname = presentDir; js.logdir=xdirname(glmi.stemname)+"/"+permdir+"/logs"; js.jnum = permIndex; count = permIndex; seq.addJob(js); } } js.init(); js.arguments.clear(); js.jobtype="shellcommand"; string cmd=(format("vbperminfo -p %s %s 0.05") %(xdirname(glmi.stemname)+"/"+permdir+"/iterations/permcube") %(xdirname(glmi.stemname)+"/"+permdir+"/results.ref")).str(); js.arguments["command"]=cmd; js.magnitude=0; js.name="finish"; js.dirname = presentDir; js.logdir=xdirname(glmi.stemname)+"/"+permdir+"/logs"; js.jnum = count + 1; for (int i=0; i<=count; i++) js.waitfor.insert(i); seq.addJob(js); seq.name=seqname; if (seq.name.size() == 0) seq.name="perm"+matrixStemName; seq.seqnum = (int)getpid(); if (vbp.cores==0) { if (seq.Submit(vbp) == 0) { cout << "[I] vbpermgen: successfully submitted the sequence.\n"; } else { cout << "[E] vbpermgen: failed to submit the sequence.\n"; return -1; } } else { runseq(vbp,seq,vbp.cores); } return 0; } void permGenerator::pressed() { GLMInfo glmi; string presentDir=xgetcwd()+"/"; string matrixStemName=txtPRM->text().toStdString(); string permDir = txtPermDir->text().toStdString(); // string scale = cbScale->currentText().toStdString(); VB_permtype method; if (cbPermType->currentItem()==0) method=vb_signperm; else method=vb_orderperm; int numPerms=strtol(txtPermNumber->text().toStdString()); string contrast=txtContrasts->text().toStdString(); string plist=(string)txtX->text().toStdString() + " " + txtY->text().toStdString() + " " + txtZ->text().toStdString(); if (!txtX->isEnabled()) plist="0 0 0"; permclass pc; glmi.setup(matrixStemName); pc.stemname=glmi.stemname; pc.permdir=permDir; pc.method=method; pc.contrast=contrast; pc.pseudotlist=plist; pc.AddPrmTimeStamp(glmi.stemname); pc.SetFileName("perminfo.txt"); if (matrixStemName.size() == 0) { QMessageBox::warning( this, "Warning!", "Must specify the matrix stem name (glm directory).\n"); return; } if (permDir.size() == 0) { QMessageBox::warning( this, "Warning!", "Must specify the permutation directory name.\n"); return; } // FIXME test validity of contrast? struct stat my_stat; //check permutation directory if mat file already exists string pfile = xdirname(glmi.stemname)+"/"+permDir+"permutations.mat"; // FIXME if permstart returns an error, we're in trouble. but most // of permstart shouold really be a job instead permStart(pc); pc.SavePermClass(); memset((void*)&my_stat, 0, sizeof(my_stat)); seq.init(); QString name; int count = 0; if (numPerms > 0) { for (int permIndex = 0; permIndex < numPerms; permIndex++) { js.init(); js.arguments.clear(); js.jobtype="shellcommand"; string cmd=(format("permstep -m %s -d %s -t %s -c '%s' %s -n %d") %glmi.stemname%permDir%permclass::methodstring(method) %contrast%(plist.size()?(string)"-p "+plist:"") %permIndex).str(); if (method==vb_signperm) cmd+=" -e"; js.arguments["command"]=cmd; js.magnitude=0; js.name=permDir; js.dirname = presentDir; js.logdir=xdirname(glmi.stemname)+"/"+permDir+"/logs"; js.jnum = permIndex; count = permIndex; seq.addJob(js); } } js.init(); js.arguments.clear(); js.jobtype="shellcommand"; string cmd=(format("vbperminfo -p %s %s 0.05") %(xdirname(glmi.stemname)+"/"+permDir+"/iterations/permcube") %(xdirname(glmi.stemname)+"/"+permDir+"/results.ref")).str(); js.arguments["command"]=cmd; js.magnitude=0; js.name="finish"; js.dirname = presentDir; js.logdir=xdirname(glmi.stemname)+"/"+permDir+"/logs"; js.jnum = count + 1; for (int i=0; i<=count; i++) js.waitfor.insert(i); seq.addJob(js); seq.name=txtSN->text().ascii(); if (seq.name.size() == 0) seq.name="perm"+matrixStemName; seq.priority = sbPriority->value(); seq.seqnum = (int)getpid(); if (vbp.cores==0) { if (seq.Submit(vbp) == 0) { QMessageBox::warning( this, "Information", "The requested sequence was submitted.\n"); return; } else { QMessageBox::warning( this, "Information", "The requested sequence failed to submit.\n"); return; } } else { //runseq(vbp,seq,vbp.cores); QRunSeq qr; qr.Go(vbp,seq,vbp.cores); qr.exec(); } msgboxsetpermnumber = 0; return; } int permGenerator::warnCalculateNumPerms() { if (msgboxsetpermnumber) return 1; VBMatrix headerMatrix; GLMInfo glmi; struct stat my_stat; int numPerms = 0; string matrixStemName; if (txtPRM->text().length()) matrixStemName = txtPRM->text().ascii(); else matrixStemName = tempPRM; string headerName = xrootname(matrixStemName) + ".G"; if (stat(headerName.c_str(),&my_stat)) { return 1; } headerMatrix.ReadHeader(headerName); double orderG = (double)headerMatrix.m; if (pow(2.0, (orderG-1)) < 1000) numPerms = (int)pow(2.0, (orderG-1)); else numPerms = 1000; char num[STRINGLEN]; char obs[STRINGLEN]; char old[STRINGLEN]; sprintf(num, "%d", numPerms); sprintf(obs, "%d", (int)orderG); sprintf(old, "%d", atoi(txtPermNumber->text().ascii())); string snum = num; string og = obs; string sold = old; string msg = "Maximum permutations is " + snum + " based on your data.\n Do you want to generate the " + snum + " possible?"; if (atoi(txtPermNumber->text().ascii()) > numPerms) { QMessageBox mb( "vbpermgen", msg.c_str(), QMessageBox::Information, QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape ); mb.setButtonText( QMessageBox::Yes, "Replace" ); mb.setButtonText( QMessageBox::No, "Abort" ); switch( mb.exec() ) { case QMessageBox::Yes: msgboxsetpermnumber = 1; txtPermNumber->clear(); txtPermNumber->insert(num); msgboxsetpermnumber = 0; return 0; break; case QMessageBox::No: msgboxsetpermnumber = 1; txtPermNumber->clear(); txtPermNumber->insert("0"); msgboxsetpermnumber = 0; return 1; break; case QMessageBox::Cancel: msgboxsetpermnumber = 1; txtPermNumber->clear(); txtPermNumber->insert("0"); msgboxsetpermnumber = 0; return 1; break; } } return numPerms; } void permGenerator::CalculateNumPerms() { if (msgboxsetpermnumber) return; VBMatrix headerMatrix; GLMInfo glmi; struct stat my_stat; int numPerms = 0; string matrixStemName; if (txtPRM->text().length()) matrixStemName = txtPRM->text().ascii(); else matrixStemName = tempPRM; string headerName = xrootname(matrixStemName) + ".G"; if (stat(headerName.c_str(),&my_stat)) { return; } headerMatrix.ReadHeader(headerName); double orderG = (double)headerMatrix.m; if (pow(2.0, (orderG-1)) < 1000) numPerms = (int)pow(2.0, (orderG-1)); else numPerms = 1000; char num[STRINGLEN]; sprintf(num, "%d", numPerms); txtPermNumber->clear(); txtPermNumber->insert(num); return; } void permGenerator::closeEvent( QCloseEvent *ce ){ ce->accept(); return; } void permGenerator::exitProgram() { exit(0); return; } void vbpermgen_help() { cout << boost::format(myhelp) % vbversion; } void vbpermgen_version() { printf("VoxBo vbpermgen (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/qtglm/vbpermgen.h000066400000000000000000000051341153177201300174110ustar00rootroot00000000000000 // permgen.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Tom King #ifndef PERMGENERATOR_H #define PERMGENERATOR_H #include #include #include //Added by qt3to4: #include #include #include #include #include #include #include "../stand_alone/perm.h" #include "glmutil.h" #include "vbprefs.h" #include "vbutil.h" #include "vbio.h" #include "vbjobspec.h" class QCheckBox; class Q3VBoxLayout; class Q3HBoxLayout; class Q3GridLayout; class QLabel; class QPushButton; class Q3TextEdit; class QComboBox; class QLineEdit; class QSpinBox; class Q3Frame; class permGenerator : public QDialog { Q_OBJECT public: permGenerator( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, Qt::WFlags fl = 0 ); QLabel* lblY; QLabel* lblX; QLineEdit* txtPRM; QLabel* lblPermDir; QLineEdit* txtPermDir; QLabel* lblContrasts; QPushButton *btnContrasts; QLineEdit* txtContrasts; // QLabel* lblScale; QLabel* lblPermNumber; QLineEdit* txtPermNumber; QLabel* lblPseudoT; QLineEdit* txtX; QLineEdit* txtY; QLineEdit* txtZ; QLabel* lblZ; QLabel* lblPermType; QComboBox* cbPermType; QPushButton* pbGO; // QComboBox* cbScale; QPushButton* pbDir; QComboBox* c; QPushButton* pbCancel; QSpinBox* sbPriority; QLabel* lblPriority; QLabel *lblSN; QLineEdit *txtSN; Q3Frame *line2; protected: protected slots: virtual void languageChange(); void pressed(); QString getPRMFile(); void getContrast(); void exitProgram(); void mod(bool x); void CalculateNumPerms(); int warnCalculateNumPerms(); private: void closeEvent( QCloseEvent *ce ); }; #endif // PERMGENERATOR_H voxbo-1.8.5~svn1246/qtglm/vbpermgen.hlp000066400000000000000000000022041153177201300177400ustar00rootroot00000000000000 VoxBo vbpermgen (v%1%) summary: creates permutations on data from a specified glm directory. usage: vbpermgen [flags] example (GUI): vbpermgen example (command line): vbpermgen -m glm -d perm -t 1 -c "mycontrast" -n 10 -b 2 flags: -h help -m the matrix stem name (required) -d permutation directory name (required) -t permutation type (required) 0 means no permutation 1 means order permutation. 2 means sign permutation -c contrast specification (required) -p pseudo-t smoothing kernel, in quotes -n number of permutations -s set seed for random number generator -a sequence name for the scheduler -b priority -v print version -h print help notes: If you use the -s flag to set the RNG seed, you can get the program to produce predictable output (perhaps useful for testing purposes and for repeatable resampling tests). Any integer in the 0-2^32 range is fine. If -s isn't provided, the value is taken from /dev/urandom (system permitting). voxbo-1.8.5~svn1246/qtglm/vbtcalc.cpp000066400000000000000000000107321153177201300173750ustar00rootroot00000000000000 // tcalc.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Tom King, modified severely by Dan // Kimberg #include #include "threshcalc.h" #include "statthreshold.h" #include "vbtcalc.hlp.h" int flag; // FIXME sloppy way to not update when populating dialog void vbtcalc_help(); void vbtcalc_version(); void tcalc_cmd(threshold &v); int main( int argc, char ** argv ) { // set defaults threshold v; v.searchVolume=50000*3*3*3; v.numVoxels=50000; v.fwhm=2.0; v.effdf=15; v.denomdf=0; v.pValPeak=0.05; v.vsize[0]=3.0; v.vsize[1]=3.0; v.vsize[2]=3.0; v.pValExtent=0.05; v.clusterThreshold=0.001; // jic v.peakthreshold = 0; v.pvalpeak = 0; v.bonpeakthreshold = 0; v.bonpvalpeak = 0; v.clusterthreshold = 0; v.peakthreshold1 = 0; v.pvalpeak1 = 0; v.extentthreshold = 0; v.extentthreshold1 = 0; v.pvalextent = 0; v.pvalextent1 = 0; bool f_cmd=0; tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; iFLT_MIN) { cout << format("Critical value for F(%g,%g): %g\n")% v.effdf%v.denomdf%bestt; } else { cout << format("Critical value for t(%g): %g\n")% v.effdf%bestt; } if (finite(v.peakthreshold)) cout << format(" RFT threshold: %g\n")%v.peakthreshold; else cout << format(" RFT threshold: none\n"); if (finite(v.bonpeakthreshold)) cout << format(" Bonferroni threshold: %g\n")%v.bonpeakthreshold; else cout << format(" Bonferroni threshold: none\n"); cout << format(" search volume: %d mm^3\n")%v.searchVolume; cout << format(" total voxels: %d\n")%v.numVoxels; cout << format("FWHM smoothness in mm: %g\n")%v.fwhm; cout << format(" alpha: %g\n")%v.pValPeak; cout << format(" voxel sizes: %g %g %g\n")%v.vsize[0]%v.vsize[1]%v.vsize[2]; } void vbtcalc_help() { cout << boost::format(myhelp) % vbversion; } void vbtcalc_version() { printf("VoxBo vbtcalc (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/qtglm/vbtcalc.hlp000066400000000000000000000010131153177201300173660ustar00rootroot00000000000000 VoxBo vbtcalc (v%1%) summary: calculates Bonferroni and Gaussian t or F threshold values usage for gui: vbtcalc usage for command line: vbtcalc [flags] flags: -n total voxels -s fwhm smoothness in mm (average xyz) -z voxel sizes -tdf df for t test -fdf df for f test -a alpha criterion -h show help -v show version notes: If you specify -fdf with a d2 of 0, you'll just get a t threshold. voxbo-1.8.5~svn1246/qtglm/vecview.cpp000066400000000000000000000434051153177201300174320ustar00rootroot00000000000000 // vecview.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu using namespace std; #include #include #include #include #include #include #include #include #include #include #include #include #include "vecview.h" #include "vecview.hlp.h" // FIXME arg handling below is messy /* Here comes the main function for vecview binary file * If there is only one argument, check the argument to * see if it is a valid ref or VBMatrix file. If it is ref, * show it in mode 1; if it's VBMatrix, show it in mode 2; * otherwise report an error message. * * If there are two argument, make sure the first is "-m", * then check the 2nd argument to make sure it's a valid * movement parameter ref file. If yes, show it in mode 3. * If not, report an error message. * For any other auguments, print out a usage line. */ int main( int argc, char **argv ) { QApplication a( argc, argv ); VecView *w; char *fileName; int fileMode; if (argc == 2) { if ((string)argv[1] == "-h") { vecview_help(); exit(0); } else if ((string)argv[1]=="-v") { vecview_version(); exit(0); } } if (argc == 2) { fileName = argv[1]; fileMode = checkInFile(fileName, false); if (fileMode < 0) { printf("%s: not a valid ref or VBMatrix file.\n", fileName); return 0; } w = new VecView(fileName, fileMode); w->setCaption("vecview: " + QString(fileName)); } // Is it movement parameter files? else if (argc >= 3 && dancmp(argv[1], "-m")) { VB_Vector *totalVec = new VB_Vector(); QString nameCombo = ""; for (int i = 2; i < argc; i++) { fileName = argv[i]; fileMode = checkInFile(fileName, true); if (fileMode == -2) { printf("%s: invalid movement parameter file.\n", fileName); return 0; } else if (fileMode == -3) { printf("%s: invalid ref file.\n", fileName); return 0; } // Combine name together to show on title bar if (i != argc - 1) nameCombo += QString(fileName) + " + "; else nameCombo += QString(fileName); VB_Vector tmpVec(fileName); totalVec->concatenate(tmpVec); } w = new VecView(totalVec, true); w->setCaption("vecview: " + nameCombo); } // "-s" accepts multiple ref files and draw them seperately else if (argc >= 3 && dancmp(argv[1], "-a")) { VB_Vector *totalVec = new VB_Vector(); QString nameCombo = ""; for (int i = 2; i < argc; i++) { fileName = argv[i]; fileMode = checkInFile(fileName, false); if (fileMode != 1) { printf("%s: invalid ref file.\n", fileName); return 0; } // Combine name together to show on title bar if (i != argc - 1) nameCombo += QString(fileName) + " + "; else nameCombo += QString(fileName); VB_Vector tmpVec(fileName); totalVec->concatenate(tmpVec); } w = new VecView(totalVec, false); w->setCaption("vecview: " + nameCombo); } // Otherwise concatenate all arguments as one big ref file else if (argc >= 3) { tokenlist refList; for (int i = 1; i < argc; i++) { fileName = argv[i]; fileMode = checkInFile(fileName, false); if (fileMode != 1) { printf("%s: invalid ref file.\n", fileName); return 0; } refList.Add(fileName); } w = new VecView(refList); } // Print help message else { vecview_help(); return 0; } a.setMainWidget(w); w->show(); return a.exec(); } /* Constructor which accepts a single filename and inputMode */ VecView::VecView( const char * inputFile, int inputMode, QWidget *parent, const char *name ) : Q3MainWindow( parent, name ) { init(); string fileString = inputFile; if (inputMode == 1) { VB_Vector *myVec = new VB_Vector(fileString); vecShow(myVec); } else { initColor(); setVecList(fileString); matShow(); } setCentralWidget(mainBox); } /* Another constructor which accepts vb_vector and movement parameter flag */ VecView::VecView( VB_Vector *inputVec, bool mvpmFlag, QWidget *parent, const char *name ) : Q3MainWindow( parent, name ) { init(); if (mvpmFlag) mvpmShow(inputVec); else vecShow(inputVec); setCentralWidget(mainBox); } /* This constructor shows multiple ref files */ VecView::VecView( tokenlist refList, QWidget *parent, const char *name ) : Q3MainWindow( parent, name ) { refFiles = refList; init(); initColor(); plotStat = 1; for (size_t i = 0; i < refList.size(); i++) { VB_Vector myVec(refList[i]); vecList.push_back(myVec); psList.push_back(fftnyquist(myVec)); } mainScreen->addVector(vecList[0]); setCommon(); setVecBox(); setCentralWidget(mainBox); int vecLen = vecList[0].getLength(); statusBar()->message(QString("%1 length: %2").arg(refFiles(0)).arg(vecLen)); } /* Simple destructor */ VecView::~VecView() { mainScreen->clear(); if (colorList.size()) colorList.clear(); } /* Initialize the interface */ void VecView::init() { plotStat = 0; psChecked = false; mainBox = new Q3VBox(this); mainScreen = new PlotScreen(mainBox); mainScreen->setMinimumSize(600, 300); mainScreen->setUpdatesEnabled(true); mainBox->setStretchFactor(mainScreen, 20); ctrlPressed = false; } /* Set predetermined 9 colors */ void VecView::initColor() { if (colorList.size()) colorList.clear(); colorList.Add("green"); colorList.Add("red"); colorList.Add("blue"); colorList.Add("cyan"); colorList.Add("magenta"); colorList.Add("yellow"); colorList.Add("gray"); colorList.Add("lightGray"); colorList.Add("white"); } /* vecShow() shows a simple ref file (mode 1) */ void VecView::vecShow(VB_Vector *inputVec) { plotStat = 0; vecList.push_back(inputVec); VB_Vector psVec = fftnyquist(*inputVec); psList.push_back(psVec); mainScreen->addVector(inputVec); setCommon(); statusBar()->message(QString("Ref file length: %1").arg(inputVec->getLength())); } /* matShow() shows a VBMatrix file (mode 2). * It adds a slider bar at the bottom so that user can show different columns. */ void VecView::matShow() { plotStat = 2; mainScreen->addVector(vecList[0]); setCommon(); setVecBox(); int vecLen = vecList[0].getLength(); int vecNum = vecList.size(); if (vecNum > 1) statusBar()->message(QString("Column #1 (G matrix dimension: %1 rows, %2 columns)").arg(vecLen).arg(vecNum)); else statusBar()->message(QString("Column #1 (G matrix dimension: %1 rows, 1 column)").arg(vecLen)); } /* This function adds the vector selection box on the interface */ void VecView::setVecBox() { Q3HBox *vecBox = new Q3HBox(mainBox); vecBox->setMargin(10); vecBox->setSpacing(20); QLabel *vecTxt = new QLabel(vecBox); if (plotStat == 2) vecTxt->setText("Browse Columns"); else vecTxt->setText("Browse Ref Files"); int vecNum = vecList.size(); vecSlider = new QSlider(0, vecNum - 1, 1, 0, Qt::Horizontal, vecBox); vecSlider->setTickmarks( QSlider::Below ); QObject::connect(vecSlider, SIGNAL(valueChanged(int)), this, SLOT(changeVec(int))); showAll = new QCheckBox("Show All", vecBox); QObject::connect(showAll, SIGNAL(toggled(bool)), this, SLOT(toggleShow(bool))); autoScale = new QCheckBox("Y Auto Scale", vecBox); autoScale->setChecked(true); QObject::connect(autoScale, SIGNAL(toggled(bool)), this, SLOT(toggleScale(bool))); } /* This function replies "Show All" checkbox toggle action. */ void VecView::toggleShow(bool showStat) { mainScreen->clear(); if (showStat) { QString statusTxt = ""; for (int i = 0; i < (int) vecList.size(); i++) { int j = i % colorList.size(); if (!psChecked) mainScreen->addVector(vecList[i], QColor(colorList(j))); else mainScreen->addVector(psList[i], QColor(colorList(j))); if (plotStat == 2 && i != (int) vecList.size() - 1) statusTxt += "Column #" + QString::number(i + 1) + ": " + QString(colorList(j)) + "; "; else if (plotStat == 2) statusTxt += "Column #" + QString::number(i + 1) + ": " + QString(colorList(j)); else if (i != (int) vecList.size() - 1) statusTxt += QString(refFiles(i)) + ": " + QString(colorList(j)) + "; "; else statusTxt += QString(refFiles(i)) + ": " + QString(colorList(j)); } statusBar()->message(statusTxt); vecSlider->setDisabled(true); } else { vecSlider->setEnabled(true); int vecIndex = vecSlider->value(); int vecLen = vecList[vecIndex].getLength(); int vecNum = vecList.size(); if (plotStat == 2 && vecNum > 1) statusBar()->message(QString("Column #%1 (G matrix dimension: %2 rows, %3 columns)"). arg(vecIndex + 1).arg(vecLen).arg(vecNum)); else if (plotStat == 2) statusBar()->message(QString("Column #%1 (G matrix dimension: %2 rows, 1 column)"). arg(vecIndex + 1).arg(vecLen)); else statusBar()->message(QString("%1 length: %2").arg(refFiles(vecIndex)).arg(vecLen)); if (!psChecked) mainScreen->addVector(vecList[vecIndex]); else mainScreen->addVector(psList[vecIndex]); } mainScreen->update(); } /* This function replies "Y Auto Scale" checkbox toggle action. */ void VecView::toggleScale(bool scaleStat) { if (scaleStat) mainScreen->enableFixedY(false); else mainScreen->enableFixedY(true); mainScreen->update(); } /* mvpmShow() shows a movement parameter ref file (mode 3). * Three radiobuttons at the bottom are available for user to * choose different groups: X/Y/Z, Pitch/Roll/Yaw, Iteration. */ void VecView::mvpmShow(VB_Vector *inputVec) { plotStat = 3; int unitLength = inputVec->getLength() / 7; for (int mpIndex = 0; mpIndex < 7; mpIndex++) { VB_Vector tmpVec(unitLength); for (int i = 0; i < unitLength; i++) tmpVec.setElement(i, inputVec->getElement(i * 7 + mpIndex)); vecList.push_back(tmpVec); psList.push_back(fftnyquist(tmpVec)); } mainScreen->addVector(vecList[0], "green"); mainScreen->addVector(vecList[1], "red"); mainScreen->addVector(vecList[2], "yellow"); setCommon(); Q3HButtonGroup *mpGroup = new Q3HButtonGroup(mainBox); mpGroup->setLineWidth(0); QRadioButton *XYZ = new QRadioButton("X (green), Y (red), Z (yellow)", mpGroup); (void) new QRadioButton("Pitch (green), Roll (red), Yaw (yellow)", mpGroup); (void) new QRadioButton("Iterations", mpGroup); XYZ->setChecked(true); QObject::connect(mpGroup, SIGNAL(clicked(int)), this, SLOT(changeMP(int))); statusBar()->message(QString("Movement parameter component length: %1").arg(unitLength)); } /* setCommon() sets the common widgets in three mode: * magnification slider bar with text, position slider bar * with text and a center pushbutton. */ void VecView::setCommon() { mainScreen->setXCaption("X Axis"); mainScreen->setYCaption("Y Axis"); mainScreen->update(); /* Add "magnification" and "position" slide bars and a "center" button in the middle */ Q3VBox *mag_pos = new Q3VBox(mainBox); mag_pos->setSpacing(1); Q3HBox *widgetBox = new Q3HBox(mag_pos); widgetBox->setSpacing(20); widgetBox->setMargin(2); QLabel *magLab = new QLabel("Magnification", widgetBox); magLab->setAlignment(Qt::AlignHCenter); /*********************************************************************** * Horizontal magnification slider bar, with the tickmarks on the above * Maximum: 10, Minimum: 1, step: 1, default position: 1 **********************************************************************/ magSlider = new QSlider(1, 10, 1, 1, Qt::Horizontal, widgetBox); magSlider->setTickmarks( QSlider::Below ); QObject::connect(magSlider, SIGNAL(valueChanged(int)), mainScreen, SLOT(setXMag(int))); QObject::connect(mainScreen, SIGNAL(xMagChanged(int)), magSlider, SLOT(setValue(int))); QPushButton *graphCenter = new QPushButton("Center", widgetBox); // "center" pushbutton QObject::connect(graphCenter, SIGNAL(clicked()), mainScreen, SLOT(centerX())); QCheckBox *psOption = new QCheckBox("Show Power Spectrum", widgetBox); QObject::connect(psOption, SIGNAL(toggled(bool)), this, SLOT(togglePS(bool))); mainScreen->setFocus(); } /* This function reads the input matrix file and puts each column into vecList array */ void VecView::setVecList(string filename) { VBMatrix *myMat = new VBMatrix(filename); for (size_t i = 0; i < myMat->n; i++) { VB_Vector tmpVec = myMat->GetColumn(i); vecList.push_back(tmpVec); psList.push_back(fftnyquist(tmpVec)); } } /* togglePS() determines whether vector is plotted in time or frequency domain */ void VecView::togglePS(bool psStat) { psChecked = psStat; mainScreen->clear(); // Plot single vector's power spectrum if (psChecked && plotStat == 0) mainScreen->addVector(psList[0]); // Plot single vector in regular domain else if (plotStat == 0) mainScreen->addVector(vecList[0]); // Plot multiple vectors (input is either G matrix or more than one ref files) else if (plotStat == 1 || plotStat == 2) { /* Automatically set auto scale, because very likely the * scale in time and frequency domain will be very different */ autoScale->setChecked(true); mainScreen->enableFixedY(false); if (showAll->isChecked()) { for (unsigned i = 0; i < psList.size(); i++) { int j = i % colorList.size(); if (psChecked) mainScreen->addVector(psList[i], QColor(colorList(j))); else mainScreen->addVector(vecList[i], QColor(colorList(j))); } } else { int vecIndex = vecSlider->value(); if (psChecked) mainScreen->addVector(psList[vecIndex]); else mainScreen->addVector(vecList[vecIndex]); } } // plot movement parameter file else plotMP(); mainScreen->update(); } /* changeVec() takes care of the signal from vector browser slider bar. */ void VecView::changeVec(int i) { int vecLen = vecList[i].getLength(); int vecNum = vecList.size(); if (plotStat == 2 && vecNum > 1) statusBar()->message(QString("Column #%1 (G matrix dimension: %2 rows, %3 columns)"). arg(i + 1).arg(vecLen).arg(vecNum)); else if (plotStat == 2) statusBar()->message(QString("Column #%1 (G matrix dimension: %2 rows, 1 column)"). arg(i + 1).arg(vecLen)); else statusBar()->message(QString("%1 length: %2").arg(refFiles(i)).arg(vecLen)); mainScreen->clear(); if (!psChecked) mainScreen->addVector(vecList[i]); else mainScreen->addVector(psList[i]); mainScreen->update(); } /* changeMP() takes care of the signal from the movement parameter * radiobutton group. */ void VecView::changeMP(int mpGroup) { mainScreen->clear(); plotStat = 3 + mpGroup; plotMP(); mainScreen->update(); } /* Plot movement parameter vectors */ void VecView::plotMP() { if (plotStat == 3 && psChecked) { mainScreen->addVector(psList[0], "green"); mainScreen->addVector(psList[1], "red"); mainScreen->addVector(psList[2], "yellow"); } else if (plotStat == 3) { mainScreen->addVector(vecList[0], "green"); mainScreen->addVector(vecList[1], "red"); mainScreen->addVector(vecList[2], "yellow"); } else if (plotStat == 4 && psChecked) { mainScreen->addVector(psList[3], "green"); mainScreen->addVector(psList[4], "red"); mainScreen->addVector(psList[5], "yellow"); } else if (plotStat == 4) { mainScreen->addVector(vecList[3], "green"); mainScreen->addVector(vecList[4], "red"); mainScreen->addVector(vecList[5], "yellow"); } else if (psChecked) mainScreen->addVector(psList[6]); else mainScreen->addVector(vecList[6]); } /* Overwrited function for ctrl+s implementation */ void VecView::keyPressEvent( QKeyEvent *e ) { if (e->key() == Qt::Key_Control) ctrlPressed = true; else if (ctrlPressed && e->key() == Qt::Key_S) { QString s = Q3FileDialog::getSaveFileName(".", "All (*.*)", this, "save image file", "Choose a filename for your snapshot"); if (s == QString::null) return; QPixmap::grabWidget(mainScreen).save(s.latin1(),"PNG"); } } /* Overwrited function for ctrl+s implementation */ void VecView::keyReleaseEvent ( QKeyEvent * e ) { if (e->key() == Qt::Key_Control) ctrlPressed = false; } /* checkInFile() checks the input file to make sure it is a valid * ref, VBMatrix or movement parameter type. * Note the various return values for different check result. */ int checkInFile(char * fileName, bool mvpmFlag) { VB_Vector testVec; VBMatrix testMat; if (!mvpmFlag) { if (testVec.ReadFile((string)fileName) == 0) return 1; else if (testMat.ReadHeader((string)fileName) == 0 && testMat.m && testMat.n) return 2; else return -1; } if (testVec.ReadFile((string)fileName) == 0) { int vecSize = testVec.getLength(); if (vecSize % 7 == 0) return 3; else return -2; } return -3; } /* Print out help message */ void vecview_help() { cout << boost::format(myhelp) % vbversion; } void vecview_version() { printf("VoxBo vecview (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/qtglm/vecview.h000066400000000000000000000045121153177201300170730ustar00rootroot00000000000000 // vecview.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dongbo Hu #ifndef VECVIEW_H #define VECVIEW_H #include "plotscreen.h" #include #include #include #include #include #include //Added by qt3to4: #include class VecView : public Q3MainWindow { Q_OBJECT public: VecView( const char * inputFile, int mode, QWidget *parent = 0, const char *name = 0 ); VecView( VB_Vector * inputVec, bool mvpmFlag, QWidget *parent = 0, const char *name = 0 ); VecView( tokenlist refList, QWidget *parent = 0, const char *name = 0 ); ~VecView(); void keyPressEvent( QKeyEvent * ); void keyReleaseEvent( QKeyEvent * ); private slots: void changeVec(int ); void changeMP(int ); void toggleShow(bool ); void toggleScale(bool ); void togglePS(bool ); private: void init(); void initColor(); void vecShow(VB_Vector *); void mvpmShow(VB_Vector *); void matShow(); void setCommon(); void setVecList(string); void setVecBox(); void plotMP(); Q3VBox *mainBox; PlotScreen *mainScreen; QSlider *magSlider; QSlider *vecSlider; QCheckBox *showAll; QCheckBox *autoScale; int plotStat; bool psChecked; tokenlist refFiles; tokenlist colorList; std::vector< VB_Vector > vecList; std::vector< VB_Vector > psList; bool ctrlPressed; }; int checkInFile(char * fileName, bool mvpmFlag); void vecview_help(); void vecview_version(); #endif voxbo-1.8.5~svn1246/qtglm/vecview.hlp000066400000000000000000000014731153177201300174320ustar00rootroot00000000000000 VoxBo vecview (v%1%) usage: vecview ... view vector file(s) vecview -a ... view vector files concatenated vecview view columns of matrix file vecview -m view movement parameter file vecview -h show help vecview -v show version notes: Movement parameter files are assumed to be sets of six parameters for each volume, stored as a 1-dimensional vector, in this order: x,y,z,pitch,roll,yaw. The following keys are recognized by the grapher. The up and down arrows let you zoom in or out. The tab key lets you switch between vectors when more than one is displayed. The shift key lets you see interpolated values (otherwise, clicking on the graph snaps to the nearest point). F1 through F4 select view modes. voxbo-1.8.5~svn1246/qtvlsm/000077500000000000000000000000001153177201300154525ustar00rootroot00000000000000voxbo-1.8.5~svn1246/qtvlsm/Makefile000066400000000000000000000022621153177201300171140ustar00rootroot00000000000000 # Makefile for vbvlsm(?) -include ../make_vars.txt include ../make_stuff.txt CXXFLAGS += -DQT3_SUPPORT $(QTINCDIRS) PERMUTATION_OBJECTS=../stand_alone/perm.o ../stand_alone/utils.o ../stand_alone/time_series_avg.o ../stand_alone/koshutil.o OBJECTS=vbvlsm.o rsrc.o $(PERMUTATION_OBJECTS) LIBS = $(LDFLAGS) $(LIBDIRS) $(QTLIBDIRS) $(QTLIBS) -Xlinker -lvbglm -lvbprefs -lvbio -lvbutil -lz $(DLLIB) -lgsl -lgslcblas ALLBINS=vbvlsm ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else BINS= endif ifdef VB_NOX BINS= endif all: $(BINS) install: ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) $(VBLIBS): +make -C ../lib $@ # executables test: test.o $(CXX) -o test test.o $(LIBS) vbvlsm: $(OBJECTS) $(CXX) $(CXXFLAGS) -o vbvlsm $(OBJECTS) $(LIBS) # the objects rsrc.o : rsrc.qrc $(RCC) rsrc.qrc -o rsrc.cpp $(CXX) -c rsrc.cpp $(CXXFLAGS) vbvlsm.o: vbvlsm.cpp $(MOC) vbvlsm.cpp -o vbvlsm.moc.h $(CXX) -c vbvlsm.cpp $(CXXFLAGS) # custom qt widgets vbqt_canvas.o: vbqt_canvas.moc.h vbqt_canvas.cpp $(CXX) -c vbqt_canvas.cpp $(CXXFLAGS) # mocs vbqt_canvas.moc.h: vbqt_canvas.h $(MOC) vbqt_canvas.h -o vbqt_canvas.moc.h voxbo-1.8.5~svn1246/qtvlsm/icons/000077500000000000000000000000001153177201300165655ustar00rootroot00000000000000voxbo-1.8.5~svn1246/qtvlsm/icons/icon_check.png000066400000000000000000000003631153177201300213620ustar00rootroot00000000000000‰PNG  IHDR‰ sRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ*$¼?"sIDAT8Ë­”Á!MÆþ[æ¾êÀIÿ,+Daf6_  }À\zfm†ç ØiW6ôÂN»’a_vÚmÀ(¨ŠkèA³Â+ÿnOŸ·™)vÐë|Â2Õy†4ÛŒ•bi)+Ti0_Ý.)ºŠŠ_IEND®B`‚voxbo-1.8.5~svn1246/qtvlsm/rsrc.qrc000066400000000000000000000001551153177201300171330ustar00rootroot00000000000000 icons/icon_check.png voxbo-1.8.5~svn1246/qtvlsm/vbvlsm.cpp000066400000000000000000000572111153177201300174750ustar00rootroot00000000000000 // vbvlsm.cpp // VoxBo analysis tool // Copyright (c) 2009 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // FIXME set up a set() of time points to omit // FIXME do it now or queue jobs, if doing it now, display the results #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vbio.h" #include "vbutil.h" #include "stats.h" #include "tokenlist.h" #include "glmutil.h" #include "myboxes.h" #include "../stand_alone/perm.h" using namespace std; using boost::format; // FIXME global required for old perm mat code gsl_rng *theRNG = NULL; const string p_dim1d="%d elements"; const string p_dim2d="%d variables of length %d"; const string p_dim3d="%dx%dx%d"; const string p_dim4d="%d volumes of %dx%dx%d"; enum t_stat {id_ttest,id_welchs,id_regression,id_resid,id_noperm,id_dvperm,id_ivperm}; enum t_loglevel {t_status,t_log,t_error}; class ModelItem { public: string fullname; string filename; vector dims; string dimstring; int criticaldim; int nvars; QTreeWidgetItem *item; bool f_iv,f_dv,f_pv; Tes tdata; VB_Vector vdata; VBMatrix mdata; }; // collection of model items types typedef vector MIList; typedef vector::iterator MII; typedef pair MP; class VSetup : public QObject { Q_OBJECT public: QApplication *app; QMainWindow *mainwindow; QFrame *mainframe; QVBoxLayout *mainlayout; QPalette bgpal,pal2; QLineEdit *w_dirname; QLineEdit *w_nperms; QLineEdit *w_stem; QHBox *w_permbox; QCheckBox *w_permcb; QTreeWidget *tree; QGroupBox *statbox; MIList itemlist; // interface void init(int argc,char **argv); void build_mainwindow(); void build_filelist(string dir); // stat functions void run_ttest(); void run_regression(); int do_regression_volume(int permindex); int do_ttest_volume(int permindex); int do_regression_single(int permindex); int do_ttest_single(int permindex); // stat config and data t_stat mystat; int dimx,dimy,dimz; map ivmap; map dvmap; VBMatrix permmat; int permcount; Cube tmap,pmap,zmap; Cube mask; VB_Vector permdist; int ivcount,dvcount,critsize; bool f_volume; VBMatrix pmat; int ivperm; int dvperm; public slots: void dchandler(QTreeWidgetItem *,int); void handle_treecontext(const QPoint &pos); void handle_selectionchanged(); void handle_statbutton(int val); void handle_permcheckbox(bool state); void handle_dependent(MII mi); void handle_independent(MII mi); void handle_permute(MII mi); void handle_remove(); void handle_clear(); void handle_newdir(); void setstatus(const string &str,t_loglevel level=t_error); void go(); void runstats(); }; #include "vbvlsm.moc.h" enum {col_name=0,col_dims,col_len,col_dv,col_iv,col_pv}; void VSetup::dchandler(QTreeWidgetItem *item,int col) { MII it; for (it=itemlist.begin(); it!=itemlist.end(); it++) if (it->item==item) break; if (it==itemlist.end()) return; if (col==col_dv) { handle_dependent(it); } if (col==col_iv) { handle_independent(it); } if (col==col_pv) { handle_permute(it); } } void VSetup::handle_selectionchanged() { // FIXME no actual reason to handle this } int main(int argc,char **argv) { VSetup vv; vv.init(argc,argv); vv.build_mainwindow(); vv.go(); } void VSetup::init(int argc,char **argv) { app=new QApplication(argc,argv); // build_filelist("/junk/vtest"); permcount=1; ivperm=0; dvperm=0; } void VSetup::go() { app->exec(); } void VSetup::build_filelist(string dir) { tokenlist files; vglob vg(dir+"/*"); for(size_t i=0; iclear(); ivmap.clear(); dvmap.clear(); // tree header stuff QStringList *strings=new QStringList(); strings->clear(); *strings << "filename" << "dims" << "len" << "DV" << "IV" << "PV"; tree->setHeaderLabels(*strings); // go through the files and add to three QTreeWidgetItem *it; for (size_t i=0; iclear(); *strings << itemlist[i].filename.c_str() << itemlist[i].dimstring.c_str() << strnum(itemlist[i].criticaldim).c_str() << "" << ""; it=new QTreeWidgetItem(*strings); tree->addTopLevelItem(it); // it->setFlags(it->flags() | Qt::ItemIsEditable); itemlist[i].item=it; // connect it all up } tree->resizeColumnToContents(0); tree->resizeColumnToContents(1); tree->resizeColumnToContents(2); tree->resizeColumnToContents(3); tree->resizeColumnToContents(4); w_dirname->setText(dir.c_str()); } void VSetup::handle_treecontext(const QPoint &pt) { QTreeWidgetItem *it=tree->itemAt(pt); cout << (long)it << endl; // QMenu popup; // popup.addAction("foo"); // popup.addAction("bar"); // popup.addAction("baz!!!"); // QAction *act=popup.exec(tree->mapToGlobal(pt)); } void VSetup::handle_statbutton(int val) { if (val==id_ttest) mystat=id_ttest; else if (val==id_welchs) mystat=id_welchs; else if (val==id_regression) mystat=id_regression; else if (val==id_resid) mystat=id_resid; else cout << "FIXME shouldn't happen (statbutton)" << endl; } void VSetup::handle_permcheckbox(bool state) { w_permbox->setVisible(state); return; } void VSetup::handle_dependent(MII mi) { // if it's already a DV, unset it if (mi->f_dv) { mi->item->setIcon(col_dv,QIcon()); mi->f_dv=0; dvmap.clear(); return; } // it's a DV mi->item->setDisabled(0); mi->item->setIcon(col_dv,QIcon(QPixmap(":/icons/icon_check.png"))); dvmap[mi->filename]=*mi; mi->f_dv=1; int critlen=mi->criticaldim; if (mi->f_iv) { ivmap.erase(mi->filename); mi->item->setIcon(col_iv,QIcon()); mi->f_iv=0; } // go through remaining items, gray out ones with bad length, cancel out ones with dv selected for (MII mix=itemlist.begin(); mix!=itemlist.end(); mix++) { if (mix==mi) continue; if (mix->criticaldim!=critlen) { mix->item->setIcon(col_iv,QIcon()); mix->item->setIcon(col_dv,QIcon()); mix->item->setIcon(col_pv,QIcon()); mix->f_iv=0; mix->f_dv=0; mix->f_pv=0; mix->item->setDisabled(1); continue; } else if (mix->f_dv) { mix->f_dv=0; mix->item->setIcon(col_dv,QIcon()); } else mix->item->setDisabled(0); } } void VSetup::handle_independent(MII mi) { // if it's already an IV, unset it if (mi->f_iv) { mi->item->setIcon(col_iv,QIcon()); mi->f_iv=0; ivmap.erase(mi->filename); return; } // it's an IV mi->item->setDisabled(0); mi->item->setIcon(col_iv,QIcon(QPixmap(":/icons/icon_check.png"))); ivmap[mi->filename]=*mi; mi->f_iv=1; int critlen=mi->criticaldim; // it's not a DV if (mi->f_dv) { dvmap.clear(); mi->item->setIcon(col_dv,QIcon()); mi->f_dv=0; } // go through remaining items, gray out ones with bad length for (MII mix=itemlist.begin(); mix!=itemlist.end(); mix++) { if (mix==mi) continue; if (mix->criticaldim!=critlen) { mix->item->setIcon(col_iv,QIcon()); mix->item->setIcon(col_dv,QIcon()); mix->item->setIcon(col_pv,QIcon()); mix->f_iv=0; mix->f_dv=0; mix->f_pv=0; mix->item->setDisabled(1); } else mix->item->setDisabled(0); } } void VSetup::handle_permute(MII mi) { if (mi->f_iv) { // just de-iv it mi->item->setIcon(col_iv,QIcon()); mi->f_iv=0; return; } } void VSetup::handle_remove() { } void VSetup::handle_clear() { for (MII mi=itemlist.begin(); mi!=itemlist.end(); mi++) { mi->item->setDisabled(0); mi->item->setText(3,""); // mi->type=t_none; } tree->clearSelection(); } void VSetup::handle_newdir() { QString newdir=QFileDialog::getExistingDirectory(NULL,QString("Which folder/directory contains the files for your analysis?")); if (newdir.size()) { // chdir(newdir.toStdString().c_str()); chdir(newdir.toAscii()); build_filelist(newdir.toStdString()); } } void VSetup::build_mainwindow() { QFrame *myframe; // string sectionstyle="QLabel {background:#ffffee;border:2px solid red;}"; string sectionstyle="QLabel {border:1px solid black;}"; // string framestyle="QFrame {padding-left:40px;border:1px solid black;}"; mainwindow=new QMainWindow(); mainwindow->resize(660,600); mainframe=new QFrame(); mainwindow->setCentralWidget(mainframe); mainlayout=new QVBoxLayout(); mainlayout->setSpacing(8); mainlayout->setMargin(4); mainlayout->setAlignment(Qt::AlignTop); mainframe->setLayout(mainlayout); QLabel *label; QHBoxLayout *hbox; QVBoxLayout *vbox,*fbox; QPushButton *button; // SELECT VARIABLES myframe=new QFrame(); // myframe->setStyleSheet(framestyle.c_str()); mainlayout->addWidget(myframe); fbox=new QVBoxLayout(); myframe->setLayout(fbox); label=new QLabel("Select your variables/files"); label->setStyleSheet(sectionstyle.c_str()); fbox->addWidget(label); // mainwindow->show(); // return; hbox=new QHBoxLayout(); fbox->addLayout(hbox); hbox->setSpacing(2); hbox->setMargin(0); hbox->addSpacing(40); button=new QPushButton("Directory"); hbox->addWidget(button); QObject::connect(button,SIGNAL(clicked()), this,SLOT(handle_newdir())); w_dirname=new QLineEdit(); hbox->addWidget(w_dirname); w_dirname->setText(""); tree=new QTreeWidget(); tree->setRootIsDecorated(0); fbox->addWidget(tree); tree->setSelectionMode(QAbstractItemView::ExtendedSelection); // tree->setFocusPolicy(Qt::NoFocus); tree->setStyleSheet("selection-background-color:#d0b0b0;alternate-background-color:yellow;"); tree->setContextMenuPolicy(Qt::CustomContextMenu); tree->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QStringList *strings=new QStringList(); strings->clear(); *strings << "filename" << "dims" << "len" << "DV" << "IV" << "PV"; tree->setHeaderLabels(*strings); QObject::connect(tree,SIGNAL(itemDoubleClicked(QTreeWidgetItem *,int)), this,SLOT(dchandler(QTreeWidgetItem *,int))); QObject::connect(tree,SIGNAL(customContextMenuRequested(const QPoint &)), this,SLOT(handle_treecontext(const QPoint &))); QObject::connect(tree,SIGNAL(itemSelectionChanged()), this,SLOT(handle_selectionchanged())); label=new QLabel("DV: dependent variable; IV: independent variable; PV: variable to permute"); fbox->addWidget(label); hbox=new QHBoxLayout(); hbox->setAlignment(Qt::AlignLeft); fbox->addLayout(hbox); button=new QPushButton("remove"); hbox->addWidget(button); QObject::connect(button,SIGNAL(clicked()), this,SLOT(handle_remove())); button=new QPushButton("clear all"); hbox->addWidget(button); QObject::connect(button,SIGNAL(clicked()), this,SLOT(handle_clear())); // SELECT TEST STATISTIC myframe=new QFrame(); // myframe->setStyleSheet(framestyle.c_str()); mainlayout->addWidget(myframe); vbox=new QVBoxLayout(); myframe->setLayout(fbox); label=new QLabel("Select your test statistic"); label->setStyleSheet(sectionstyle.c_str()); mainlayout->addWidget(label); // statbox=new QGroupBox(); // ("Select your test statistic"); hbox=new QHBoxLayout(); mainlayout->addLayout(hbox); hbox->setSpacing(2); hbox->setMargin(0); hbox->addSpacing(40); vbox=new QVBoxLayout(); hbox->addLayout(vbox); QButtonGroup *bg=new QButtonGroup(); vbox->setSpacing(0); QRadioButton *rb; rb=new QRadioButton("ttest (w/df, p, and z maps)"); rb->setChecked(1); mystat=id_ttest; bg->addButton(rb); bg->setId(rb,id_ttest); vbox->addWidget(rb); rb=new QRadioButton("welch's (w/df, p, and z maps)"); bg->addButton(rb); bg->setId(rb,id_welchs); vbox->addWidget(rb); rb=new QRadioButton("regression t (w/df, p, and z maps)"); bg->addButton(rb); bg->setId(rb,id_regression); vbox->addWidget(rb); rb=new QRadioButton("residual map"); bg->addButton(rb); bg->setId(rb,id_resid); vbox->addWidget(rb); vbox->addStretch(1); // statbox->setLayout(vbox); // mainlayout->addWidget(statbox); QObject::connect(bg,SIGNAL(buttonClicked(int)),this, SLOT(handle_statbutton(int))); label=new QLabel("Permutation testing"); label->setStyleSheet(sectionstyle.c_str()); mainlayout->addWidget(label); hbox=new QHBoxLayout(); hbox->setSizeConstraint(QLayout::SetFixedSize); mainlayout->addLayout(hbox); hbox->setAlignment(Qt::AlignLeft); hbox->addSpacing(40); w_permcb=new QCheckBox("Permutation test"); hbox->addWidget(w_permcb); QObject::connect(w_permcb,SIGNAL(toggled(bool)),this, SLOT(handle_permcheckbox(bool))); w_permbox=new QHBox; hbox->addWidget(w_permbox); w_nperms=new QLineEdit(); // w_nperms->setValidator(new QIntValidator(0,10000,w_stem)); w_permbox->addWidget(w_nperms); w_nperms->setText(QString("1000")); label=new QLabel("permutations (order of DV)"); w_permbox->addWidget(label); w_permbox->setVisible(0); label=new QLabel("Output"); label->setStyleSheet(sectionstyle.c_str()); mainlayout->addWidget(label); hbox=new QHBoxLayout(); mainlayout->addLayout(hbox); hbox->setSpacing(2); hbox->setMargin(0); hbox->addSpacing(40); hbox->setAlignment(Qt::AlignLeft); label=new QLabel("Stem for output files:"); hbox->addWidget(label); w_stem=new QLineEdit(); hbox->addWidget(w_stem); w_stem->setText(QString("myvlsm")); mainlayout->addStretch(100); hbox=new QHBoxLayout(); // hbox->setAlignment(Qt::AlignLeft); hbox->setSpacing(2); hbox->setMargin(0); // hbox->addSpacing(40); mainlayout->addLayout(hbox); button=new QPushButton("GO!"); hbox->addWidget(button); QObject::connect(button,SIGNAL(clicked()), this,SLOT(runstats())); hbox->addStretch(1); mainwindow->show(); } // type is MSG_STATUS or MSG_LOG void VSetup::setstatus(const string &str,t_loglevel level) { if (level==t_error) cout << "ERR: "; // put message in status line, log window, error popup, and possibly log file cout << "STATUS: " << str << endl; } void VSetup::runstats() { critsize=0; f_volume=0; dimx=dimy=dimz=0; ivcount=dvcount=0; mask.invalidate(); Tes ts; if (w_permcb->isChecked()) permcount=strtol(w_nperms->text().toStdString()); else permcount=1; if (permcount<1) permcount=1; if (permcount>1) permdist.resize(permcount); // set up QProgressDialog with either the number of iterations or // the number of in-mask voxels // first pass over variables to count variables, set crit size, // build mask, etc. vbforeach (MP mi,ivmap) { // vbforeach (ModelItem &mi,ivmap) { ivcount+=mi.second.nvars; if (critsize==0) critsize=mi.second.criticaldim; if (mi.second.criticaldim!=critsize) { setstatus("bogus variable size, shouldn't happen",t_error); return; } if (mi.second.dims.size()==4) { f_volume=1; if (dimx==0) {dimx=mi.second.dims[0];dimy=mi.second.dims[1];dimz=mi.second.dims[2];} if (mi.second.dims[0]!=dimx || mi.second.dims[1]!=dimy || mi.second.dims[2]!=dimz) { setstatus("bad 4D volume size",t_error); return; } if (ts.ReadHeader(mi.second.filename)) { setstatus("couldn't read 4D file header",t_error); return; } Cube tmpmask; if (ts.ExtractMask(tmpmask)==0) { if (mask.data) mask.intersect(tmpmask); else mask=tmpmask; } } } vbforeach (MP mi,dvmap) { dvcount+=mi.second.nvars; if (critsize==0) critsize=mi.second.criticaldim; if (mi.second.criticaldim!=critsize) { setstatus("bogus variable size, shouldn't happen",t_error); return; } } // run the right test if (mystat==id_ttest || mystat==id_welchs) run_ttest(); else if (mystat==id_regression || mystat==id_resid) run_regression(); else setstatus("shouldn't happen (runstats)",t_error); } void VSetup::run_ttest() { if (ivcount!=1) { setstatus("For a t test, you must select a grouping variable as your independent variable.",t_error); return; } if (dvcount!=1) { setstatus("For a t test, you must select a single dependent variable or volume."); return; } int err; int permindex=-1; // -1 means don't permute if (permcount>1) pmat=createPermMatrix(permcount,critsize,vb_orderperm,0); format progformat("Calculating statmaps (%d of %d completed) ..."); QProgressDialog prog((progformat%0%permcount).str().c_str(),"Abort",0,permcount); prog.setWindowModality(Qt::WindowModal); prog.show(); for (int i=0; i1) permindex=i; if (f_volume) err=do_ttest_volume(permindex); else err=do_ttest_single(permindex); if (err) break; // FIXME } prog.setValue(permcount); // permutation test cleanup if (permcount>1) { permdist.WriteFile("permdist.ref"); // FIXME and more? } else if (mystat==id_welchs) { tmap.WriteFile("tmap.cub.gz"); pmap.WriteFile("pmap.cub.gz"); zmap.WriteFile("zmap.cub.gz"); } else if (mystat==id_ttest) { tmap.WriteFile("tmap.cub.gz"); pmap.WriteFile("pmap.cub.gz"); zmap.WriteFile("zmap.cub.gz"); } } void VSetup::run_regression() { if (permcount>1) { // FIXME make a permutation matrix here } for (int i=0; isecond; ModelItem dvitem=dvmap.begin()->second; int order=ivitem.criticaldim; bitmask bm; bm.resize(order); // read any 4d data, otherwise copy to iv/dv if (ivitem.dims.size()==4) { // FIXME test error ivitem.tdata.ReadFile(ivitem.filename); } else { for (int t=0; tFLT_MIN) bm.set(t); else bm.unset(t); } } if (dvitem.dims.size()==4) dvitem.tdata.ReadFile(dvitem.filename); else dv=dvitem.vdata; // FIXME right now we only offer the option of order-permuting the // dv. if it's a vector we do it once, here. if (permcount>1) pvec=pmat.GetColumn(permindex); if (permcount>1 && dvitem.dims.size()==1) { for (uint32 i=0; i(i,j,k,t)) bm.set(t); else bm.unset(t); } } // if it's 4d data, grab the right time series if (dvitem.dims.size()==4) { dvitem.tdata.GetTimeSeries(i,j,k); // FIXME right now we only offer the option of order // permuting the dv. if it's image data, we do it for each // position, here if (permcount>1) { for (uint32 i=0; i1) { double max; if (mystat==id_welchs) max=zmap.get_maximum(); else max=tmap.get_maximum(); permdist[permindex]=max; } else { // FIXME do FDR // calc bonferroni for unique voxels } // FIXME obey mask // if we're not doing a permutation test: // do z conversion, saving both p and z // flip if requested // calc fdr thresh // calc bonferroni for unique voxels thresh // if we are doing a perm test, just stash the stat value // (same for regular ttest, but call calc_ttest() instead) return 0; } int VSetup::do_regression_volume(int permindex) { cout << permindex << endl; bool f_resid=(mystat==id_resid); cout << f_resid << endl; GLMInfo glmi; vector ivnames; string dvname,resname; vector ivmats; // not used // FIXME build ivnames and dvnames -- volumeregress() will load them for us glmi.rescount=0; int err=glmi.VolumeRegress(mask,1,1,ivnames,dvname,ivmats); // FIXME check error if (err) return err; glmi.residtes.WriteFile(resname); return 0; } int VSetup::do_regression_single(int permindex) { cout << permindex << endl; return 0; } int VSetup::do_ttest_single(int permindex) { cout << permindex << endl; return 0; } voxbo-1.8.5~svn1246/resample/000077500000000000000000000000001153177201300157345ustar00rootroot00000000000000voxbo-1.8.5~svn1246/resample/Makefile000066400000000000000000000017051153177201300173770ustar00rootroot00000000000000 # Makefile for resample -include ../make_vars.txt include ../make_stuff.txt # object files for the executables RESAMPLEOBJECTS = resample.o VBTRANSFORMOBJECTS = vbtransform.o # miscellaneous flags and such LIBS = $(LDFLAGS) $(LIBDIRS) -lm -lvbprefs -lvbio -lvbutil -lz -lpng $(DLLIB) $(GSL_LIBS) # resample is in all packages BINS=resample OUT=vbtransform # the main targets all: $(BINS) install: $(BINS) ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(BINS) $(VBLIBS): +make -C ../lib $@ # THE EXECUTABLES resample: $(RESAMPLEOBJECTS) $(VBLIBS) $(CXX) -o resample $(RESAMPLEOBJECTS) $(LIBS) vbtransform: $(VBTRANSFORMOBJECTS) $(VBLIBS) $(CXX) -o vbtransform $(VBTRANSFORMOBJECTS) $(LIBS) # THE OBJECTS resample.o: resample.cpp $(VBLIBS) $(CXX) $(CXXFLAGS) -c -o resample.o resample.cpp vbtransform.o: vbtransform.cpp $(VBLIBS) $(CXX) $(CXXFLAGS) -c -o vbtransform.o vbtransform.cpp voxbo-1.8.5~svn1246/resample/resample.cpp000066400000000000000000000164071153177201300202600ustar00rootroot00000000000000 // resample.cpp // sinc resampling of volumes, adapted from spm // Copyright (c) 1998-2008 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // note that the guts of the underlying sinc resample code were ported // from SPM96b source code written by John Ashburner using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #include "imageutils.h" void resample_help(); int main(int argc,char *argv[]) { tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs resample_help(); exit(0); } Resample rr; enum {mode_rr,mode_rc,mode_rz,mode_rd,mode_ra,mode_d,mode_rw,mode_none} mode=mode_none; tokenlist args; tokenlist files; string reffile; int err; int zsize=1,dimx=1,dimy=1,dimz=1; double x1=0,y1=0,z1=0; // start voxel (0 indexed) in x,y,z int nx=1,ny=1,nz=1; // number of voxels in resampled image double xstep=1,ystep=1,zstep=1; // resample interval in voxels bool q_nnflag=0,q_xxflag=0,q_yyflag=0,q_zzflag=0; args.Transfer(argc-1,argv+1); for(size_t i=0; i hh=rr.headerstrings(); newtes.header.insert(newtes.header.end(),hh.begin(),hh.end()); for (size_t i=0; i hh=rr.headerstrings(); newcube.header.insert(newcube.header.end(),hh.begin(),hh.end()); for (size_t i=0; i [flags]\n"); printf("flags:\n"); printf(" -rr ref=image in desired space\n"); printf(" -rc ref=image with desired field of view\n"); printf(" -rz [z] same but specify size in z\n"); printf(" -rd ref=image of desired dimensions\n"); printf(" -ra aligns to ref on all dims, using corner position\n"); printf(" -rw aligns to ref on all dims, using corner position, same voxel sizes\n"); printf(" -d desired dimensions\n"); printf(" -nn use nearest neighbor interpolation (default is sinc)\n"); printf(" -xx a=start voxel (from 0); b=interval in voxels; c=# of voxels\n"); printf(" -yy same for y dimension\n"); printf(" -zz same for z dimension\n"); printf("\n"); printf(" -r generic ref cube\n"); printf(" -aa, -ax, -ay, -az [origin/corner]\n"); printf(" -sa, -sx, -sy, -sz [n]\n"); printf("\n"); printf("Some examples for an axial image of dimensions 64x64x21:\n"); printf(" invert the order of the slices: resample in.cub out.cub -zz 20 -1 21\n"); printf(" swap left-right: resample in.cub out.cub -xx 63 -1 64\n"); printf(" interpolate in-plane: resample in.cub out.cub -xx 0 .25 256 -yy 0 .25 256\n"); printf(" crop to 40x64x21: resample in.cub out.cub -xx 12 1 40\n"); printf("\n"); } voxbo-1.8.5~svn1246/resample/vbtransform.cpp000066400000000000000000000301671153177201300210120ustar00rootroot00000000000000 // vbtransform.cpp // apply an affine transform, resample // Copyright (c) 2007 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // note that the guts of the underlying sinc resample code were ported // from SPM96b source code written by John Ashburner using namespace std; #include #include #include "vbutil.h" #include "vbio.h" #define PI 3.14159265358979 #define TINY 0.05 void make_lookup(double coord,int nn,int dim,int *d1,double *table, double **ptpend); template void resample_sinc(int m,T *vol,VB_Vector &out,const VB_Vector &x, const VB_Vector &y,const VB_Vector &z, int dimx,int dimy,int dimz,int nn,double background, double scale); class VBTransform { private: string imagename; // name of the image to be normalized string refname; // name of the reference image string outname; // name of the output image vector newheaders; // headers to be added to output file enum {vb_3d,vb_4d} mode; enum {vb_nn,vb_sinc} method; tokenlist args; // structure to be used for argument parsing Cube *mycube,*newcube; Tes *mytes,*newtes; double zsize; // size of slices in mm double x1,y1,z1; // start voxel (0 indexed) in x,y,z int nx,ny,nz; // number of voxels in resampled image int dimx,dimy,dimz; // original dimensions double voxsize[3]; // original voxsize double xstep,ystep,zstep; // resample interval in voxels public: VBTransform(int argc,char **argv); ~VBTransform(); void init(); int Setup(); // set up parameters int VBTransformFile(); // detect filetype int VBTransform3D(); // set up for 3d int VBTransform4D(); // set up for 4d int VBTransformCube(); // dispatch to sinc or nn resample int SincVBTransformCube(); // do it for each cube int NNVBTransformCube(); // do it for each cube void AdjustCornerAndOrigin(VBImage &im); // methods for working out the resample parameters int UseZ(const string &refname,double zsize); int UseDims(const string &refname); int UseTLHC(const string &refname); int UseCorner(const string &refname); int SetAlign(const string mode,const string ref); }; void resample_help(); int main(int argc,char *argv[]) { tzset(); // make sure all times are timezone corrected if (argc < 2) { // not enough args, display autodocs resample_help(); exit(0); } VBTransform *r=new VBTransform(argc,argv); // init resample object, parse args if (!r) { printf("*** resample: couldn't allocate a tiny structure\n"); exit(5); } int err; err=r->Setup(); // set the start, stop, nslices, etc. if (!err) err = r->VBTransformFile(); // do it delete r; // clean up if (err) printf("*** resample: error resampling (%d).\n",err); else printf("resample: done.\n"); exit(err); } void VBTransform::init() { imagename=refname=""; zsize=0.0; x1=y1=z1=0; xstep=ystep=zstep=1.0; nx=41; ny=51; nz=27; method=vb_sinc; } VBTransform::VBTransform(int argc,char *argv[]) { init(); args.Transfer(argc-1,argv+1); } int VBTransform::TransformFile() { printf("resample: resampling %s\n",args[0].c_str()); if (mode == vb_3d) return VBTransform3D(); else if (mode == vb_4d) return VBTransform4D(); else { printf("*** resample: error\n"); return 200; } } int VBTransform::Transform3D() { stringstream tmps; if (VBTransformCube()) return 101; newcube->SetFileName(args[1]); newcube->SetFileFormat(mycube->GetFileFormat()); newcube->header=mycube->header; if (mycube->origin[0]) { newcube->origin[0]=lround((mycube->origin[0]-x1)/xstep); newcube->origin[1]=lround((mycube->origin[1]-y1)/ystep); newcube->origin[2]=lround((mycube->origin[2]-z1)/zstep); } // add new headers for (int i=0; i<(int)newheaders.size(); i++) newcube->AddHeader(newheaders[i]); newcube->AddHeader((string)"resample_date: "+timedate()); AdjustCornerAndOrigin(*newcube); if (newcube->WriteFile()) printf("*** resample: error writing %s\n",args[1].c_str()); else printf("resample: wrote %s.\n",args[1].c_str()); delete newcube; return 0; } int VBTransform::Transform4D() { newtes=new Tes(); newtes->SetVolume(nx,ny,nz,mytes->dimt,mytes->datatype); newtes->voxsize[0]=fabs(xstep*mytes->voxsize[0]); newtes->voxsize[1]=fabs(ystep*mytes->voxsize[1]); newtes->voxsize[2]=fabs(zstep*mytes->voxsize[2]); if (mytes->origin[0]) { newtes->origin[0]=lround((mytes->origin[0]-x1)/xstep); newtes->origin[1]=lround((mytes->origin[1]-y1)/ystep); newtes->origin[2]=lround((mytes->origin[2]-z1)/zstep); } for (int i=0; idimt; i++) { mycube=new Cube((*mytes)[i]); if (VBTransformCube()) return 102; newtes->SetCube(i,newcube); delete newcube; delete mycube; } // add new headers for (int i=0; i<(int)newheaders.size(); i++) newtes->AddHeader(newheaders[i]); newtes->AddHeader((string)"resample_date: "+timedate()); newtes->SetFileName(args[1]); newtes->SetFileFormat(mytes->GetFileFormat()); newtes->header=mytes->header; AdjustCornerAndOrigin(*newtes); if (int err=newtes->WriteFile()) printf("*** resample: error %d writing %s\n",err,args[1].c_str()); else printf("resample: wrote %s.\n",args[1].c_str()); return 0; } int VBTransform::ResampleCube() { if (method==vb_nn) return NNVBTransformCube(); else return SincVBTransformCube(); } int VBTransform::NNResampleCube() { int i,j,k; if (!mycube) return 5; newcube=new Cube(); newcube->SetVolume(nx,ny,nz,mycube->datatype); VBMatrix coord(4,1); for (i=0; iSetValue(i,j,k,mycube->GetValue(c1,c2,c3)); } } } return 0; // no error } int VBTransform::SincVBTransformCube() { int i,j,k; if (!mycube) return 5; newcube=new Cube(); newcube->SetVolume(nx,ny,nz,mycube->datatype); newcube->voxsize[0]=fabs(xstep*mycube->voxsize[0]); newcube->voxsize[1]=fabs(ystep*mycube->voxsize[1]); newcube->voxsize[2]=fabs(zstep*mycube->voxsize[2]); VB_Vector c1(1),c2(1),c3(1),out(1); for (k=0; kdatatype) { case vb_byte: resample_sinc(1,(unsigned char *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_short: resample_sinc(1,(int16 *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_long: resample_sinc(1,(int32 *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_float: resample_sinc(1,(float *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; case vb_double: resample_sinc(1,(double *)mycube->data,out,c1,c2,c3, mycube->dimx,mycube->dimy,mycube->dimz,5, 0.0,1.0); break; } newcube->SetValue(i,j,k,out(0)); } } } return 0; // no error } void resample_help() { printf("\nVoxBo resample (v%s)\n",vbversion.c_str()); printf("usage: resample [flags]\n"); printf("flags:\n"); printf(" -rr ref=image in desired space\n"); printf(" -rc ref=image with desired field of view\n"); printf(" -rz [z] same but specify size in z\n"); printf(" -rd ref=image of desired dimensions\n"); printf(" -ra aligns to ref on all dims, using corner position\n"); printf(" -d desired dimensions\n"); printf(" -nn use nearest neighbor interpolation (default is sinc)\n"); printf(" -xx a=start voxel (from 0); b=interval in voxels; c=# of voxels\n"); printf(" -yy same for y dimension\n"); printf(" -zz same for z dimension\n"); printf("\n"); printf(" -r generic ref cube\n"); printf(" -aa, -ax, -ay, -az [origin/corner]\n"); printf(" -sa, -sx, -sy, -sz [n]\n"); printf("\n"); printf("Some examples for an axial image of dimensions 64x64x21:\n"); printf(" invert the order of the slices: resample in.cub out.cub -zz 20 -1 21\n"); printf(" swap left-right: resample in.cub out.cub -xx 63 -1 64\n"); printf(" interpolate in-plane: resample in.cub out.cub -xx 0 .25 256 -yy 0 .25 256\n"); printf(" crop to 40x64x21: resample in.cub out.cub -xx 12 1 40\n"); printf("\n"); } template void resample_sinc(int m,T *vol,VB_Vector &out,const VB_Vector &x, const VB_Vector &y,const VB_Vector &z, int dimx,int dimy,int dimz,int nn,double background, double scale) { int i, dim1xdim2 = dimx*dimy; int dx1, dy1, dz1; static double tablex[255],tabley[255],tablez[255]; vol -= (1 + dimx*(1 + dimy)); for (i=0; i=1-TINY && z(i)<=dimz+TINY && y(i)>=1-TINY && y(i)<=dimy+TINY && x(i)>=1-TINY && x(i)<=dimx+TINY) { T *dp1; double dat=0.0, *tp1, *tp1end, *tp2end, *tp3end; make_lookup(x(i), nn, dimx, &dx1, tablex, &tp3end); make_lookup(y(i), nn, dimy, &dy1, tabley, &tp2end); make_lookup(z(i), nn, dimz, &dz1, tablez, &tp1end); tp1 = tablez; dy1 *= dimx; dp1 = vol + dim1xdim2*dz1; while(tp1 <= tp1end) { T *dp2 = dp1 + dy1; double dat2 = 0.0, *tp2 = tabley; while (tp2 <= tp2end) { register double dat3 = 0.0, *tp3 = tablex; register T *dp3 = dp2 + dx1; while(tp3 <= tp3end) dat3 += *(dp3++) * *(tp3++); dat2 += dat3 * *(tp2++); dp2 += dimx; } dat += dat2 * *(tp1++); dp1 += dim1xdim2; } out(i) = scale*dat; } else out(i) = background; } } // Generate a sinc lookup table with a Hanning filter envelope void make_lookup(double coord,int nn,int dim,int *d1,double *table,double **ptpend) { register int d2, d, fcoord; register double *tp, *tpend, dtmp; if (fabs(coord-rint(coord))<0.00001) { /* Close enough to use nearest neighbour */ *d1=(int)rint(coord); if (*d1<1 || *d1>dim) /* Pixel location outside image */ *ptpend = table-1; else { table[0]=1.0; *ptpend = table; } } else { fcoord = (int)floor(coord); *d1 = fcoord-nn; if (*d1<1) *d1=1; d2 = fcoord+nn; if (d2>dim) d2 = dim; *ptpend = tpend = table+(d2 - *d1); d = *d1, tp = table; while (tp <= tpend) { dtmp = PI*(coord-(double)(d++)); *(tp++) = sin(dtmp)/dtmp* 0.5*(1.0 + cos(dtmp/nn)) ; } } } voxbo-1.8.5~svn1246/scheduler/000077500000000000000000000000001153177201300161025ustar00rootroot00000000000000voxbo-1.8.5~svn1246/scheduler/Makefile000066400000000000000000000021341153177201300175420ustar00rootroot00000000000000 # Makefile for voxbo scheduler and related executables -include ../make_vars.txt include ../make_stuff.txt LIBS=$(LDFLAGS) $(LIBDIRS) -lvbprefs -lvbutil -lz ALLBINS=voxbo vbsrvd voxq vbq vq ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else BINS= endif all: $(BINS) install: $(BINS) ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) $(VBLIBS): +make -C ../lib $@ # here are all the executables voxbo: voxbo.o schedlib.o $(VBLIBS) $(CXX) $(CXXFLAGS) -o voxbo voxbo.o schedlib.o $(LIBS) vbsrvd: vbsrvd.o $(VBLIBS) $(CXX) $(CXXFLAGS) -o vbsrvd vbsrvd.o $(LIBS) voxq: voxq.o $(VBLIBS) $(CXX) $(CXXFLAGS) -o voxq voxq.o $(LIBS) vbq: voxq ln -sf ./voxq vbq vq: voxq ln -sf ./voxq vq # and now for the building blocks vbsrvd.o: vbsrvd.cpp $(CXX) $(CXXFLAGS) -c -o vbsrvd.o vbsrvd.cpp voxq.o: voxq.cpp $(VBRC) voxq.hlp.h -help1 voxq1.hlp -help2 voxq2.hlp $(CXX) $(CXXFLAGS) -c -o voxq.o voxq.cpp voxbo.o: voxbo.cpp $(CXX) $(CXXFLAGS) -c -o voxbo.o voxbo.cpp schedlib.o: schedlib.cpp $(CXX) $(CXXFLAGS) -c -o schedlib.o schedlib.cpp voxbo-1.8.5~svn1246/scheduler/pixmaps.cpp000066400000000000000000000744321153177201300203010ustar00rootroot00000000000000 /* XPM */ char * voxprep_xpm[] = { "160 53 810 2", " c None", ". c #FFFFFF", "+ c #FDFDFD", "@ c #FEFEFE", "# c #FCFCFC", "$ c #FBFBFB", "% c #FAFAFA", "& c #9E9E9E", "* c #737373", "= c #848484", "- c #818181", "; c #EDEDED", "> c #D2D2D2", ", c #B7B7B7", "' c #ADADAD", ") c #ABABAB", "! c #A1A1A1", "~ c #9F9F9F", "{ c #A0A0A0", "] c #A8A8A8", "^ c #B8B8B8", "/ c #D1D1D1", "( c #ECECEC", "_ c #F5F5F5", ": c #3C3C3C", "< c #000000", "[ c #CCCCCC", "} c #E2E2E2", "| c #0D0D0D", "1 c #292929", "2 c #949494", "3 c #EBEBEB", "4 c #5D5D5D", "5 c #010101", "6 c #030303", "7 c #111111", "8 c #272727", "9 c #424242", "0 c #828282", "a c #C9C9C9", "b c #F9F9F9", "c c #767676", "d c #6D6D6D", "e c #020202", "f c #A3A3A3", "g c #5A5A5A", "h c #474747", "i c #AFAFAF", "j c #999999", "k c #191919", "l c #F6F6F6", "m c #1B1B1B", "n c #696969", "o c #040404", "p c #727272", "q c #F8F8F8", "r c #F4F4F4", "s c #222222", "t c #989898", "u c #787878", "v c #6E6E6E", "w c #0B0B0B", "x c #7F7F7F", "y c #7D7D7D", "z c #808080", "A c #797979", "B c #626262", "C c #606060", "D c #868686", "E c #373737", "F c #434343", "G c #0E0E0E", "H c #DDDDDD", "I c #6C6C6C", "J c #151515", "K c #E4E4E4", "L c #F3F3F3", "M c #B2B2B2", "N c #5B5B5B", "O c #959595", "P c #E0E0E0", "Q c #B9B9B9", "R c #CBCBCB", "S c #070707", "T c #6F6F6F", "U c #141414", "V c #DFDFDF", "W c #131313", "X c #242424", "Y c #676767", "Z c #565656", "` c #6A6A6A", " . c #CACACA", ".. c #161616", "+. c #D9D9D9", "@. c #AAAAAA", "#. c #B0B0B0", "$. c #CDCDCD", "%. c #060606", "&. c #0F0F0F", "*. c #E8E8E8", "=. c #454545", "-. c #717171", ";. c #E1E1E1", ">. c #898989", ",. c #525252", "'. c #838383", "). c #E5E5E5", "!. c #C8C8C8", "~. c #E3E3E3", "{. c #D6D6D6", "]. c #7E7E7E", "^. c #212121", "/. c #E7E7E7", "(. c #747474", "_. c #F9FFFF", ":. c #FFFCFB", "<. c #FCFFFF", "[. c #FAFEFD", "}. c #FFFFFB", "|. c #FFFEFF", "1. c #E8EBE4", "2. c #CDCAD1", "3. c #AAADA2", "4. c #9AA39E", "5. c #A09FA5", "6. c #AAA5A9", "7. c #C0C4C3", "8. c #E0E2DD", "9. c #F9FFFB", "0. c #FCFDFF", "a. c #FCFFFB", "b. c #FFFEFA", "c. c #FFFDFF", "d. c #FEFFFF", "e. c #FFFDFA", "f. c #232323", "g. c #F1F1F1", "h. c #2C2C2C", "i. c #323232", "j. c #5C5C5C", "k. c #202020", "l. c #535353", "m. c #9B9B9B", "n. c #919191", "o. c #1C1C1C", "p. c #B5B5B5", "q. c #757575", "r. c #FFFDFE", "s. c #FFFEF9", "t. c #FEFFFD", "u. c #FFFBFF", "v. c #C4C4C6", "w. c #6B6B69", "x. c #2A292F", "y. c #000207", "z. c #030002", "A. c #030004", "B. c #040001", "C. c #030000", "D. c #1C171D", "E. c #4F4E4C", "F. c #A79CA2", "G. c #FDFDFB", "H. c #FBFFFF", "I. c #FDFEFF", "J. c #FEFFFB", "K. c #343434", "L. c #A9A9A9", "M. c #929292", "N. c #505050", "O. c #484848", "P. c #D3D3D3", "Q. c #F2F2F2", "R. c #AEAEAE", "S. c #8E8E8E", "T. c #FEFBFF", "U. c #5F5D5E", "V. c #0B090A", "W. c #010000", "X. c #000200", "Y. c #060300", "Z. c #000500", "`. c #010100", " + c #000106", ".+ c #000204", "++ c #3F3F3D", "@+ c #BFBABE", "#+ c #9C9C9C", "$+ c #444444", "%+ c #494949", "&+ c #1E1E1E", "*+ c #EFEFEF", "=+ c #121212", "-+ c #3A3A3A", ";+ c #F7F7F7", ">+ c #C6C6C6", ",+ c #FFFCFD", "'+ c #B0B3AA", ")+ c #191A1C", "!+ c #020204", "~+ c #000600", "{+ c #060004", "]+ c #020003", "^+ c #040005", "/+ c #000102", "(+ c #000004", "_+ c #060000", ":+ c #000201", "<+ c #010005", "[+ c #090000", "}+ c #070E07", "|+ c #8B8C86", "1+ c #FFFDFC", "2+ c #F0F0F0", "3+ c #969696", "4+ c #0C0C0C", "5+ c #404040", "6+ c #050505", "7+ c #9D9D9D", "8+ c #EEEEEE", "9+ c #B1B1B1", "0+ c #595959", "a+ c #252525", "b+ c #FDFFFC", "c+ c #B4A5AA", "d+ c #090A0E", "e+ c #020200", "f+ c #000100", "g+ c #020100", "h+ c #0B0109", "i+ c #490900", "j+ c #590902", "k+ c #841200", "l+ c #981300", "m+ c #6C0F07", "n+ c #282129", "o+ c #0D0804", "p+ c #000300", "q+ c #000205", "r+ c #050000", "s+ c #898B86", "t+ c #FFFEFD", "u+ c #7B7B7B", "v+ c #636363", "w+ c #101010", "x+ c #A7A7A7", "y+ c #DCDCDC", "z+ c #E6E6E6", "A+ c #3D3D3D", "B+ c #C2C2C2", "C+ c #DEDEDE", "D+ c #353535", "E+ c #EAEAEA", "F+ c #B4B4B4", "G+ c #BFC1BC", "H+ c #0E0C0D", "I+ c #05000A", "J+ c #010009", "K+ c #030005", "L+ c #230402", "M+ c #971600", "N+ c #B41A02", "O+ c #E21A01", "P+ c #FF2002", "Q+ c #FD2500", "R+ c #FF2402", "S+ c #D12000", "T+ c #5C1B00", "U+ c #622300", "V+ c #050006", "W+ c #040007", "X+ c #A6A8A5", "Y+ c #656565", "Z+ c #D5D5D5", "`+ c #858585", " @ c #888888", ".@ c #CFCFCF", "+@ c #E9E9E9", "@@ c #BCBCBC", "#@ c #1D1D1D", "$@ c #181818", "%@ c #8D8D8D", "&@ c #262429", "*@ c #000700", "=@ c #6B1403", "-@ c #DB2100", ";@ c #3A0800", ">@ c #A71D00", ",@ c #FF2E00", "'@ c #FF2A00", ")@ c #FF2C04", "!@ c #F72B00", "~@ c #FF3200", "{@ c #C02103", "]@ c #B84904", "^@ c #7E2807", "/@ c #000005", "(@ c #060100", "_@ c #000501", ":@ c #140F15", "<@ c #D5D6DA", "[@ c #5E5E5E", "}@ c #8B8B8B", "|@ c #C7C7C7", "1@ c #4D4D4D", "2@ c #D4D4D4", "3@ c #8F8F8F", "4@ c #414141", "5@ c #040000", "6@ c #000002", "7@ c #5D1000", "8@ c #E22505", "9@ c #B01C00", "0@ c #DE2506", "a@ c #811604", "b@ c #C32300", "c@ c #FF3206", "d@ c #FD2C03", "e@ c #FF3605", "f@ c #C52900", "g@ c #B92D00", "h@ c #D33103", "i@ c #893F00", "j@ c #542803", "k@ c #554E55", "l@ c #FDFDFF", "m@ c #2F2F2F", "n@ c #333333", "o@ c #A4A4A4", "p@ c #8A8A8A", "q@ c #C0C0C0", "r@ c #464646", "s@ c #000104", "t@ c #200400", "u@ c #D92701", "v@ c #A12201", "w@ c #E42F00", "x@ c #F73100", "y@ c #791903", "z@ c #BE3000", "A@ c #FB4000", "B@ c #C42C00", "C@ c #B72C03", "D@ c #F53D00", "E@ c #FF4103", "F@ c #D93900", "G@ c #BB5500", "H@ c #3A383B", "I@ c #000007", "J@ c #000400", "K@ c #C7C5C8", "L@ c #282828", "M@ c #5F5F5F", "N@ c #A2A2A2", "O@ c #7A7A7A", "P@ c #5C1501", "Q@ c #B42400", "R@ c #E73109", "S@ c #FD3706", "T@ c #FE3D02", "U@ c #F73D00", "V@ c #7B1E00", "W@ c #992800", "X@ c #CA3308", "Y@ c #FA4100", "Z@ c #FE4800", "`@ c #FF4400", " # c #FE4B08", ".# c #DE4400", "+# c #6D2F00", "@# c #000302", "## c #5E5C5D", "$# c #2D2D2D", "%# c #BBBBBB", "&# c #C4C4C4", "*# c #BFBFBF", "=# c #313131", "-# c #545454", ";# c #040002", "># c #1A0800", ",# c #6A1C00", "'# c #7F2000", ")# c #FF4300", "!# c #FF4102", "~# c #FF3E07", "{# c #FA4500", "]# c #FF4804", "^# c #C23700", "/# c #631900", "(# c #BF3705", "_# c #FF4F00", ":# c #FC4C00", "<# c #FD4D02", "[# c #FF5000", "}# c #FE4E02", "|# c #9E3400", "1# c #171614", "2# c #1C1817", "3# c #080808", "4# c #878787", "5# c #CECECE", "6# c #646464", "7# c #030200", "8# c #451201", "9# c #F24004", "0# c #B32E05", "a# c #932600", "b# c #FE4600", "c# c #FF4B00", "d# c #FF4E00", "e# c #C83A00", "f# c #B83906", "g# c #F14F04", "h# c #7C2900", "i# c #C04000", "j# c #FA5B00", "k# c #FF5500", "l# c #ED5603", "m# c #AD3C04", "n# c #DB5202", "o# c #733006", "p# c #04010C", "q# c #000202", "r# c #020300", "s# c #BABABA", "t# c #909090", "u# c #8C8C8C", "v# c #585858", "w# c #979797", "x# c #939393", "y# c #4C4C4C", "z# c #040006", "A# c #992A00", "B# c #FC4A04", "C# c #B33401", "D# c #8E2E06", "E# c #F85800", "F# c #CA3E01", "G# c #B03D00", "H# c #FA5601", "I# c #FF5A00", "J# c #F55902", "K# c #7C2B00", "L# c #B54400", "M# c #F85F02", "N# c #A94000", "O# c #DB5400", "P# c #FF5F00", "Q# c #C34F02", "R# c #010004", "S# c #555555", "T# c #C1C1C1", "U# c #2A2A2A", "V# c #DB4900", "W# c #FF5004", "X# c #FD5100", "Y# c #FF5900", "Z# c #BC400A", "`# c #5D2400", " $ c #BC4503", ".$ c #FB610B", "+$ c #FC5E00", "@$ c #FF5B02", "#$ c #FC6104", "$$ c #F86404", "%$ c #8A3300", "&$ c #813400", "*$ c #E95E00", "=$ c #FC6701", "-$ c #FE6C00", ";$ c #E15700", ">$ c #160903", ",$ c #080000", "'$ c #040301", ")$ c #DBDBDB", "!$ c #B3B3B3", "~$ c #A5A5A5", "{$ c #D7D7D7", "]$ c #1F1F1F", "^$ c #0F170A", "/$ c #F45504", "($ c #FD5800", "_$ c #FF5907", ":$ c #FC5F02", "<$ c #CA4B00", "[$ c #842F06", "}$ c #933800", "|$ c #FE6200", "1$ c #FF6602", "2$ c #FD6300", "3$ c #FF6900", "4$ c #EB6601", "5$ c #BD4D01", "6$ c #672D00", "7$ c #B55000", "8$ c #FF7606", "9$ c #FC6F03", "0$ c #F76A00", "a$ c #311406", "b$ c #616161", "c$ c #C5C5C5", "d$ c #BDBDBD", "e$ c #262024", "f$ c #CA5100", "g$ c #FE6505", "h$ c #FF6201", "i$ c #BB4D00", "j$ c #B74E00", "k$ c #FF6A00", "l$ c #B84D00", "m$ c #893700", "n$ c #FB6C04", "o$ c #FF7000", "p$ c #EF6800", "q$ c #A54A04", "r$ c #D66500", "s$ c #FF7702", "t$ c #823E01", "u$ c #AD5209", "v$ c #FB7F00", "w$ c #FF7B00", "x$ c #291800", "y$ c #010204", "z$ c #030007", "A$ c #575757", "B$ c #D8D8D8", "C$ c #393939", "D$ c #666666", "E$ c #222220", "F$ c #6E3102", "G$ c #DC5C01", "H$ c #C95405", "I$ c #B84D07", "J$ c #FD6F00", "K$ c #FC7600", "L$ c #B25601", "M$ c #8E3E03", "N$ c #EF6C04", "O$ c #AA4E01", "P$ c #E16B01", "Q$ c #FE7A00", "R$ c #F77D02", "S$ c #864300", "T$ c #B25F00", "U$ c #E66A06", "V$ c #271700", "W$ c #BEBEBE", "X$ c #9A9A9A", "Y$ c #171717", "Z$ c #D0D0D0", "`$ c #191718", " % c #D86107", ".% c #622700", "+% c #9E4800", "@% c #FF7D00", "#% c #FF7100", "$% c #FF7200", "%% c #FF7400", "&% c #FF8400", "*% c #AF5000", "=% c #532605", "-% c #E47300", ";% c #FB7F01", ">% c #FF7F02", ",% c #FF8105", "'% c #FB8A00", ")% c #683901", "!% c #703900", "~% c #332000", "{% c #DADADA", "]% c #090909", "^% c #7C7C7C", "/% c #010705", "(% c #AE4F00", "_% c #BA5A06", ":% c #743D00", "<% c #DC6801", "[% c #F87E00", "}% c #FC7D08", "|% c #FF7E02", "1% c #EC7500", "2% c #B45F05", "3% c #AD5800", "4% c #8C4800", "5% c #FB8602", "6% c #FC8900", "7% c #FF8102", "8% c #FB8D00", "9% c #CA7300", "0% c #B96400", "a% c #834A07", "b% c #170D01", "c% c #00000B", "d% c #686868", "e% c #2E2E2E", "f% c #ACACAC", "g% c #C3C3C3", "h% c #3E3E3E", "i% c #924205", "j% c #FD8200", "k% c #E67A00", "l% c #6C3F00", "m% c #DF6D00", "n% c #FF8702", "o% c #EC7D09", "p% c #A95500", "q% c #DD7600", "r% c #FF9300", "s% c #C46900", "t% c #804500", "u% c #FC8B09", "v% c #FC9300", "w% c #CB6F02", "x% c #AF6705", "y% c #F69604", "z% c #CD7700", "A% c #060200", "B% c #050004", "C% c #020001", "D% c #2B2B2B", "E% c #020106", "F% c #834300", "G% c #FF8700", "H% c #FF8500", "I% c #EA8006", "J% c #764600", "K% c #C86D04", "L% c #B16200", "M% c #DC8001", "N% c #FF9200", "O% c #FD8B04", "P% c #FB9800", "Q% c #C57000", "R% c #8A5200", "S% c #D57D01", "T% c #BB6A00", "U% c #F79800", "V% c #FF9705", "W% c #9E6300", "X% c #060201", "Y% c #4A4A4A", "Z% c #000306", "`% c #3A2400", " & c #FB8507", ".& c #FF8A00", "+& c #FF9104", "@& c #D68200", "#& c #3D2000", "$& c #BD6B05", "%& c #FFA000", "&& c #FE9700", "*& c #FF9202", "=& c #FF9504", "-& c #FEA500", ";& c #A36403", ">& c #513102", ",& c #EC9E06", "'& c #FFA300", ")& c #FD9F02", "!& c #453100", "~& c #010103", "{& c #1B1A18", "]& c #0A0A0A", "^& c #777777", "/& c #070000", "(& c #040605", "_& c #C16D00", ":& c #FF9600", "<& c #E08D03", "[& c #A86703", "}& c #DF8900", "|& c #7C5200", "1& c #CC7D04", "2& c #FFA400", "3& c #FB9C02", "4& c #FFA208", "5& c #C97B00", "6& c #C07B02", "7& c #C98000", "8& c #835400", "9& c #F69F00", "0& c #D48D00", "a& c #0E0700", "b& c #5B605C", "c& c #B6B6B6", "d& c #4B2F00", "e& c #E98D06", "f& c #A46700", "g& c #EB9001", "h& c #FEA700", "i& c #EC9F01", "j& c #7A4E03", "k& c #CB8500", "l& c #FBB500", "m& c #C18100", "n& c #B47A00", "o& c #FDA800", "p& c #FCB700", "q& c #CC8904", "r& c #7B5703", "s& c #533908", "t& c #BEBDC2", "u& c #383838", "v& c #6B6B6B", "w& c #363636", "x& c #020107", "y& c #6D4300", "z& c #E39A00", "A& c #FEA800", "B& c #FFA401", "C& c #FFA506", "D& c #E7AE00", "E& c #795602", "F& c #A06D02", "G& c #C98300", "H& c #FFAE00", "I& c #FBB404", "J& c #FFAF00", "K& c #FFB802", "L& c #7A5E00", "M& c #484846", "N& c #FCFCFA", "O& c #1A1A1A", "P& c #0F1217", "Q& c #010400", "R& c #000403", "S& c #020400", "T& c #9C6D01", "U& c #FFAA00", "V& c #FFAA08", "W& c #FFB700", "X& c #C38C00", "Y& c #574200", "Z& c #CE9506", "`& c #F9C402", " * c #FFB500", ".* c #A88900", "+* c #150601", "@* c #080904", "#* c #CCCDC8", "$* c #FEFDFF", "%* c #303030", "&* c #949790", "** c #010006", "=* c #010002", "-* c #030305", ";* c #735E01", ">* c #EAA700", ",* c #FEBD01", "'* c #C88F00", ")* c #BB8A01", "!* c #F0C000", "~* c #7B6200", "{* c #C89506", "]* c #EEBD00", "^* c #8D6601", "/* c #11080B", "(* c #FDFBFC", "_* c #262626", ":* c #FDFCFF", "<* c #797A75", "[* c #221C00", "}* c #584000", "|* c #796000", "1* c #C39406", "2* c #C79405", "3* c #A98D00", "4* c #3B2F00", "5* c #20180B", "6* c #6C6D71", "7* c #FEFDFB", "8* c #FDFEF9", "9* c #818179", "0* c #000103", "a* c #020308", "b* c #777781", "c* c #FAFAF8", "d* c #FEFFFA", "e* c #FDFCFA", "f* c #F9FEFF", "g* c #A7B0AF", "h* c #2B2A28", "i* c #010200", "j* c #060002", "k* c #27252A", "l* c #A2A3A5", "m* c #FFFEFB", "n* c #FAFFFB", "o* c #4F4F4F", "p* c #FEFCFF", "q* c #8F968F", "r* c #353B31", "s* c #110C12", "t* c #060910", "u* c #2D2E33", "v* c #7E8480", "w* c #FEFEFC", "x* c #FFFFFA", "y* c #CBCAC6", "z* c #A1A69F", "A* c #8A8589", "B* c #7B7577", "C* c #7A7C7B", "D* c #7F7E7A", "E* c #A09E9F", "F* c #C4C2C7", "G* c #F8F9F1", "H* c #FFFCFF", "I* c #FEFFF9", ". . . . . . . . . + . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . @ . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . + . . # @ . . . . . . . . . . . . . . . . . . . @ @ @ . @ . . . @ . @ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @ . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . @ . # . . @ . . . . . . . . . . . . . . . . . @ @ . @ + . @ @ . . + . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . @ . . + . . . . . . . . . . . . . . . . . . . . . @ . $ . . . @ . + . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ + . . @ . . @ . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . @ . . # . . . . . . . . . . . . . . . . . . . @ @ . . @ @ . @ . @ . . @ . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @ . . . @ . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . + . . @ . @ . . . . . . . . . . . . . . . . . . . + . @ . @ . . @ . . @ . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . @ . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . + . @ . . @ . . . . . . . . . . . . . . . . . @ . . @ @ . . . . @ . # . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . @ . . . @ . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . % & * + . . @ . . . . . . . . . . . . . . . . . . . @ . . . . = - ; . @ . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > , ' ) ! & ~ & { ~ { ] ^ / ( @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . @ _ ' : < < [ . @ . . . . . . . . . . . . . . . . . . . @ . + . . } | < 1 2 3 . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 < 5 < < < < < < < < < 6 7 8 9 0 a b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". @ . @ . . c < < < < d . . . @ . . . . . . . . . . . . . . . . . . @ . @ @ 0 < 5 < e f . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . g < < 5 < e < < < < 5 5 < 5 < 5 < < h i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . @ j 5 < < < k 3 . @ . . . . . . . . . . . . . . . . . @ . + . # l 8 e < < m ( + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . n < 5 < e < 5 < e < < e < 5 5 < < 5 < o p q # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . @ . r s < 5 < < t # . . . . . . . . . . . . . . . . . . . . . . . i < < < e u . . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v 5 < < w d - x y z A B 9 m e e < < e < < C . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . @ + . # . D < 6 < < E $ . @ . . . . . . . . . . . . . . . . . . . . @ F e < 5 G H @ . # . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I < < 6 J K @ . . @ . + + L M N e < < e < 5 O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". # . . + @ . P J < o < 5 Q . . . . . . . . . . . . . . . . . . . @ @ . R S 5 < < B . @ + . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . T < 5 < U V . . . . . . . + @ . ] W 5 < 5 < X _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", "@ . . @ . . . . Y < 5 5 < Z @ . . . . . . . . . . . . . . . . . . @ . # ` 6 < < S .@ . . # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . d 5 < < ..+.. . . @ . . . . . @ . @.6 < 5 < 6 #.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . @ . + . $.%.< < 5 &.H . . . . . . . . . . . . . . . . . . . . *.W < < 5 =.@ . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.< 5 < k ;.. . . @ . @ . @ . @ . . 9 < < 5 < >.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . @ ,.< < < < '.. . @ @ . + . @ . . . . . . . . . . . . >.< 5 5 < #.. . . @ . . @ ).a @.~ ~ ] !.~.. @ . + . . @ . . . @ . . {.# + . @ . . + . . . . @ . . @ . + ~.. @ . @ . . . . ].< < < ^./.. . . . . @ . . @ . . . O < < 5 < (.. @ . . . . @ . _.:.<.[.}.|.<.1.2.3.4.5.6.7.8.<.9.0.a.b.c.<.d.e.. . . . . . . . ", ". . . . . . . . . ^ 5 < 5 < f.g.+ . . @ . + . + . . . . . . . . @ . r h.< < < i.b . + . . # Q j.X < < 5 < 6 < k.l.#.+ . @ . . . @ . . . m.J n.. @ . . + . . @ . @ . . . . . [ o.>.@ . . @ + . . ].< < < ^./.. . . # @ . . @ . . + . p.5 6 < < q.@ . # . . @ + . d.r.s.t.u.v.w.x.< y.z.A.B.C.D.E.F.G.u.d.H.I.J.. . . . . . . . . ", ". . . . . . . . . % K.< < < < L.. # . . . . @ . . . . . . . . . . . #.< < 5 e M.@ . . . > N.%.< < e < < e < < 5 5 o O.P.. @ . @ . @ 3 (.< 5 W P.. . @ @ . # . . . . . . @ Q.E 5 < j.;.@ @ . + . ].< < < ^./.. . @ . . . @ @ . . . . R.5 < e 5 S.. @ . . # . . @ T.<.H.V U.V.W.X.z.X.W.Y.Z.`. +W..+++@+c.. b.c.d.. . . . . . . . ", ". . . . . . . . @ . #+< < e < $+$ . . @ . . . . . . . . . . . . . + %+5 < < &+*+. # . #+=+< < < < 5 < < < < e < < e < =+! . . . @ . f < 5 < e -+;+. @ . + . . + . @ . + . d e < < < j . . @ . . ].< < < ^./.. . . . @ @ . . @ @ . . c < 5 < 6 >+@ @ . @ . @ @ . d.,+'+)+!+~+{+]+^+/+(+_+X.:+C.<+[+y.}+|+. 1+. H.. . . . . . . . ", ". . . . . . . . . + 2+s e < e e !.@ . . . @ . @ . . . . . . . . . $.S < < < '.. + . 3+< < 5 < < 4+l.].D D y 5+6+6 < < < %.7+. . @ . 8+=.5 5 < 5 A . . @ . . @ . . @ @ . 9+o < 5 < 0+;+. + . . . ].< < < ^./.. . . @ . . + . . @ . g.a+6 < e E + . . @ @ . @ . + b+c+d+e+Z.f+g+h+i+j+k+l+m+n+o+p+q+r+f+< s+H.t+d.. . . . . . . . ", ". . . . . . . . + . . u+< < 6 < v+. . . . + . . . . . . . . . . . v 5 < < w+H @ @ x+5 < e < 5 N.x y+z+H *+;+L ^ A+< < < 5 | B++ @ . . C+&+< < < 6+p.+ . @ . . + . . . ).k.< o 5 D+E+@ . + + . . ].< < < ^./.. . . @ . . . @ + . @ ].e < 5 < F+. @ @ . . + @ @ . G+H+I+J+B.K+L+M+N+O+P+Q+R+S+T+U+C.C.V+W+X.X+c.@ . . . . . . . . ", ". . . . . . . . . + . P 7 < < 5 w+~.. # . . @ @ . . . . . . . . *.=+< 6 < Y+# . Z+G 5 < < e `+V @P.g..@P.).E+% $ N < < < 5 X +@. . @ . @@S 5 < < #@P @ . + @ . @ . + O.< e < $@Z+. @ . . . . @ ].< < < ^./.. . . . @ . . . . # %@e 5 < e y . @ . . @ @ . @ . /.&@*@(+Z._+=@-@;@>@,@'@)@!@~@{@]@^@X./@(@_@:@<@a.. . . . . . . . ", ". . . . . . . . @ . + . [@e 5 < < >.. . + . . . . . . . . . . . }@6 < < %.|@. . 1@< < 5 < -.;+/ S.2@l g.3@3+P q . L.4@< < < 5 T . . . . . }@< 5 5 < l.+ @ . @ . . + @< < < %.) . @ . @ . . . . ].< < < ^./.. . . . . . @ . a 0+< 5 < e T + . . . . . @ . . @ -.5@6@5@/@7@8@9@0@a@b@c@d@e@f@g@h@i@j@< +`.p+k@l@. . . . . . . . ", ". . . . . . . . @ . + . >+%.5 < 5 h.;++ . + . . . @ + . . @ . l m@< 5 < %++ @ @@< 5 < 5 n@K r x+7+C+E+b o@p@P b . ' x+o.< < 5 w+V . @ . $ . l.< < < < 3@. . @ @ . q@%.e < < `+. . . . . . . . . ].< < < ^./.. . . } B+p.`+r@4+< 5 < 8 #+. @ . . . @ @ . . . +.&.W.s@g+t@u@v@w@~@x@y@z@A@B@C@D@E@F@G@H@5 < I@J@K@. . . @ . @ . . ", ". . . . . . . . . + . . . h < e < 5 R.. + . . . . . . . . . . ' < 5 < 5 9+. . 0+< < e < ~ r K 0 F+).z+;+#.R.~.$ $ 9+, u 5 5 < 5 - . @ # . + ( L@< < < w >+. @ . +@a+o < < M@# . . . . . . . . . ].< < < ^./.. . @ 2 < < < < 5 < < s N@L . . + . @ . . @ . @ O@5 I@5 6@P@Q@R@S@A@T@U@V@W@X@Y@Z@`@ #.#+#@#W.e+s@##. @ . . . . . . ", ". . . . . . . . . . @ @ . M e < < e h @ . . + . . @ . . @ . @ h 5 < < m@b @ z+U < < < $#V $ p.S./ +@2+Q.N@%#P r l @.^ &#..< < 5 i.q . . . . . *#w < < < =#( . + M@e < 6 =#; . . . . . . . . . . ].< < < ^./.. . . 9+< < 5 < < 5 < 6 &...-#) @ @ . # . . . % h.< ;#J@>#,#'#)#!#~#{#]#^#/#(#_#:#<#[#}#|#1#5@X.`.2#3 . . . @ . . . ", ". . . . . . . . @ . . . . q $#< < 5 3#$.@ . . . . @ . @ @ @ .@6+< < 5 O @ . R.< < 5 < O@8+K 4##.} 3 % P 7+Q +.3 ; N@) 5#Z e < < G P.. @ . . . @ n.e < < < 6#+ j < < 5 U $.@ . . . . . . . . . . ].< < < ^./.. . . $.e < < < 5 < 5 < < < < 5 =.5#. . . . . P.5 5 7#f+8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#C.p#q#r#s#@ . @ . . . . ", ". . . . . . . . . + . @ . . t#e 6 < < I . @ . @ @ . @ . . . v < 5 < &+Q.@ . u+< 5 < < { _ #.%@5#Q.q *+u#x ^ 2@V z+N@L.B+}@< < < < L.. . . . $ . . v#o 5 < < -.W 5 < 5 ) . @ . . . . . . . . . . ].< < < ^./.. . @ ;+w#x#O O x#y y#W < < < < < k s#. @ . @ N@< < A.z#A#B#[#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#:+X.R#<+}@. . @ . @ @ @ ", ". . . . . . . . . . . . + . z+$@< 5 < ..).@ . . . . @ . @ K J 5 < < x % . . S#5 < < G T#P p@9+*.l b *+p.y 2 B+;.Q.f R. .f 6 < e 5 p@. # . @ . @ . E+U#< e < < < < < x @ . . . @ . . . . . . . . ].< < < ^./.. . . @ . . . . @ . + K `+w+e < 6 < U > . @ @ y < e `.Z.V#W#X#Y#Z#`# $.$+$@$#$$$%$&$*$=$-$;$>$,$'$f+` . @ . . . . . ", ". . . . . . . . . . + + . . @ p 5 < e < >.. @ . . + . . + 3@< 5 < =+;.. . # =.< < 5 X )$!$u#{.g.P K E+. } S.~${$q R. @ .!.k < < < p @ . @ . . . @ . &#w < < 5 < 5 S#% . + . . . . . . . . . . . ].< < < ^./.. . @ . # . # . + . . + . |@]$< < < e A+b . . M@6 < < ^$/$($_$:$<$[$}$|$1$2$3$4$5$6$7$8$9$0$a$6@6@f+-#. @ . @ @ . @ ", ". . . . . . . . . @ . . . + . Z+3#5 < < h.r . @ . . . + b L@5 < < b$@ . @ . -+< < 5 =#{$j t /.P.c$P.)$C+L P d$)$;+$.,.i ).^.5 < 5 Y . @ . . . . . . @ w#< < < < 6 P.. . . + . . . . . . . . . . ].< < < ^./.. . . @ . + . # . . @ . @ . %#w < 5 < < i . @ g < < z.e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$u$v$w$x$y$z$f+F @ . . @ . @ . ", ". . . . . . . . . . . . . . . . A$< < 5 < p.@ . . . . @ ' < < 5 6 >+@ . + . -+< < 5 D+B$3+~$*.Q F++.{.P C+).L /.q +.C$q.T#^.< 5 5 Y . . . @ . + . . . i 5 < < 5 5 [@+ . . @ . . . . . . . . . . ].< < 5 ^./.. + . . . . . . . . . . @ @ . D$< < < < Y+. @ N < < W.E$F$G$H$I$o$J$K$L$M$N$O$P$Q$w$R$S$T$U$V$s@e W.9 @ . @ @ . . . ", ". . . . . . . . . . . . . . . . *#e < < 5 =.@ . . . + @ $+< e < h . @ @ . @ F < 5 < L@+.m.{ ;.C+p.c$~.K W$y+z+; V X$}@x+! Y$e < < p . @ . . + . . . Z$U < < 5 < < 5 D . + . . @ . . . . . . . . ].< < < k.z+. . . . . . . . . . @ . + . . !.o < 5 < K.b . v+5 < K+`$ %.%+%@%#%$%%%&%*%=%-%;%>%>%,%'%)%!%~%C.C.6@,.. . . @ . . @ ", ". . . . . . . . . . . . . . . . + E 5 < < 3# .@ + . @ $.6+e < e R.. @ . . . S#< < < ..2@@.2 &#{%y+ .K /.m.c$!.!${ R $ q &#G < < < %@$ . + . . @ . *+E < e < G < < < ]%Q . . + . . . . . . . . . ].< 5 < s /.@ . . . . . . . . . . @ . @ @ 3 ]$< < e #@l @ ^%< < f+/%(%_%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%/+c%W.d%. @ . . @ . . ", ". . . . . . . . . . . . . . . . . N@< < < < n . . . @ v+e < < e%b + . + @ . u+5 < e e c$Q n.f%Q {$( ;+g%[@ @) &#z+. > c$@.< < e 5 x+. . . . @ . . Y+e < < h%B+..< 5 5 f.} . + . . . . . . . . . ].< < 5 s *.. . . . . . . . . . . # . . . g.U#5 < < Y$;+. { < < X.5@i%j%k%l%m%n%o%p%q%r%s%t%u%v%w%x%y%z%A%B%q+C%u#. . @ . @ @ @ ", ". . . . . . . . . . . . . . . . @ *+a+< 5 5 ]%P . # } =+< < 5 X$. . . . . . 9+< 5 < e D R }@#.Q !.+.f%3@, V z+( *+2+y+X$b$5 e < G 2@. # . . . . 3@e < e k B$. ) o 5 < < =.$ . . . . . . . . . . x < < < m ~.. @ . . . . . . . . . . @ @ . z+f.< e < D%;+@ Z+5 < E%(+F%G%H%I%J%K%L%M%N%O%P%Q%R%S%T%U%V%W%q#C.X%r+@@. . @ . . @ . ", ". . . . . . . . . . . . . . . . . @ z < < < e ^%+ . '.< < 6 $@3 . + . . + . z+7 < 5 e 4@>+j @.^ F+S.~$)$} z+V V +@q b ] ..5 < 5 i.% . . . @ . s#]%< 5 < ' . + . -.< < < e O@. . . . . . . . . . A < 5 < ..C+. @ . . . . . . . . @ @ . . . !.6 < < 6 Y%@ . ;+$#5 f+Z%`% &.&+&@&#&$&%&&&*&=&-&;&>&,&'&)&!&{+~&f+{&3 . . . @ . @ . ", ". . . . . . . . . . . . . . . . . . C+4+< < < ^.r ;+]$< 5 < (.@ + . . @ . @ . Z 5 < < ]&3@x+9+~$c i B$!.|@B$*+Z+&#Q._ @.5 < < < 0 . + . @ . C+s < e < (.. . @ . % E 5 < < 6+f%@ . . . . . . . . T < < < J y+. . . . . . . . . . @ . . . . T < 5 5 < p@@ . @ ^&< /&<+(&_&:&<&[&}&|&1&2&3&4&5&6&7&8&9&0&a&s@< f+b&. . . . . . . . ", ". . . . . . . . . . . . . . . . . . . B < 5 < 5 ' L.5 < < 4+{%@ . . . . @ . @ p.< < < < =#2 & T o@C+2@*#c&c$V K B$E+{.h.e < e | {%. . + . _ F < 5 < 4@;+. # . . + 2@=+< 5 < J Z+. . . . . . . . I 5 5 < ..y+. . . . . . . . . . . + @ . F+S 5 < 5 G +.. + . Z$]%X.X.C.d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&f+f+6@o t&. . . + . . . . ", ". . . . . . . . . . . . . . . . . . . &#o < < 5 n@h%< < < N . . . . . . . . @ # u&< 5 < e 5+N.^%P.Z$B${%F+' &#V *.y+d < 5 < < D$. . . @ . v&< 5 < &.B$+ . . . @ . . #+< < < 5 w&r @ . . + . . . v < < < U y+. . . @ . . . + . . @ . . M W < e < < q.. @ . . @ 4 (+C.x&{+y&z&A&B&C&D&E&F&G&H&I&J&K&L&W.6@:+I@M&N&. . . . . . . . ", ". . . . . . . . . . . . . . . . . . @ . F < 6 < < < 5 e e g%$ . . . . . . . . @ W$< e < < ]&w&) $.a R B${.X$~$R ~.z 6+5 < e O&} . @ @ . x#e < < 5 & . . # @ . . @ . . j.< 5 < < ` . + @ . @ . . v&6 < 5 ..).+ . @ . . + . . . . L !.M@%.5 5 < < w&L + . . @ . {.P&Q&W.R&S&T&U&V&J&W&X&Y&Z&`&p& *.*+*/@< ]+@*#*$*. . . . . . . . ", ". . . . . . . . . . . . . . . . @ . . + @.e < e < < < < 5+@ . . . . . . . . . . . A < 5 5 < 3#Y &#|@|@c$)${.w#x#4 6 < e < e f%. @ . . Q | < 5 5 b$. @ @ . . . @ . # . +@a+5 < 5 < 7+. @ @ . . . v < < < W F+C+V V H C+Z+T#R.2 -.: 5 5 5 < < e %*V + . @ . @ . . &*f+X.**=*-*;*>*,*'*)*!*~*{*]*^*/*J@p+g+R#x#(*|.. . . . . . . . ", ". . . . . . . . . . . . . . . . . . . . 2+_*< < < < < 5 o@. @ @ . . . . . . . . . ;+j.< < < 6 < s 0+`+O 3+& g W < 5 5 < < %@. . @ . {.f.< 5 < U#3 . @ . # . @ . # . + . c&%.< 5 5 | &#@ . . + @ v < 5 < < 4+W ..U J J w+3#e 5 < < < 5 < < 5 N 3 . . . + . . . @ :*<*< C.z$~&=*[*}*|*1*2*3*4*5*W.c%< I@< 6*. }.7*. . . . . . . . ", ". . . . . . . . . . . . . . . . . + . @ . '.6 < < < < 8 q # . @ . . . . . . . . . . l d%5 < < 5 < 5 < < < 6 < < < < e 6+M.. . . . 8+m@< < 6 6 *#. + @ + . + . . . @ . + . (.< < < < i.L @ @ . . v+5 < < e < o < 5 e < < < < < 5 < < < S 5+i @ @ + . . + . @ @ . 8*H.9*5@p+X.g+X.0*J@f+<+g+a*f+X.C.5@7#b*c*|.@ d*. . . . . . . . ", ". . . . . . . . . . . . . . . . . . . . @ P w+5 < e e D @ . @ . . . . . . . . . . . . + t #@5 < < < < 6 < < 5 5 5 < =#s#. + . @ @ ;+T < < < A @ . + . . # . . + @ . . . . *+E < < $@~$# . . . @ Z < 5 < 5 < < 5 < < < 5 < 5 < < < _*Y+M # @ . . . @ @ . @ . . @ t+e*f*g*h*;#< I@< 5@r+< i*/+X.j*p+k*l*b+m*t+n*H.. . . . . . . . ", ". . . . . . . . . . . . . . . . . + . + . . Y+< e < w ).+ . @ . . . . . . . . . . + @ . . ).= e%S < 5 < e < < 4+K.j *+. + . . . . . . X$4+-+r . @ . # . . . . . . . . . . . a 3#%*[ . . + . @ . S.=.5+: D+n@D+%*=#n@=#D+h%o*-.#+[ *.+ . @ . . @ @ . . + . + . . p*. c.m*E+q*r*s*R#f+Z%(+p+R#t*u*v*( 0.t.u.}.<.w*. . . . . . . . ", ". . . . . . . . . . . . . . . . @ . + . + . V ~ ~ ~ d$. . . . . . . . . . . . . . . . . + . . ;+g%7+0 A A = { R # @ . . . . @ . . . @ . d$> . @ . @ . @ + . . @ + . . @ . . @ !$K . . @ . @ @ . @ . + . + $ + + + + # @ @ . . . . @ . @ . + . . . @ . . @ . . . x*H.d.|.}.d.:*y*z*A*B*C*D*E*F*G*. H*. I*x*I.<.u.. . . . . . . . ", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . @ @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . @ . . . . . . . . . . . . . . . . ", ". . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", ". . . . . . . . . . . . . . . . + # % b q ;+l _ l l l l ;+;+l l l ;+q q q % $ % % % % % % $ # # # # + + # $ q ;+% $ $ $ % % % % # % b q q $ @ . . . . . . . . . . . . . . . . . . . . . . . @ + $ $ $ $ $ % b b # # $ $ $ $ # # + + # + + + + + @ @ @ @ . . . . . . . . . . . . @ . . . . + $ b . . . . . . . . . . . . . . . . "}; /* XPM */ char * x_xpm[] = { "16 16 3 1", " c None", ". c #FF0000", "+ c #FFFFFF", "..++++++++++++..", "...++++++++++...", "+...++++++++...+", "++...++++++...++", "+++...++++...+++", "++++...++...++++", "+++++......+++++", "++++++....++++++", "++++++....++++++", "+++++......+++++", "++++...++...++++", "+++...++++...+++", "++...++++++...++", "+...++++++++...+", "...++++++++++...", "..++++++++++++.."}; /* XPM */ char * check_xpm[] = { "16 16 3 1", " c #000000", ". c #FFFFFF", "+ c #007F00", "..............++", ".............+++", "............++++", "...........+++++", "..........++++..", "++.......++++...", "++.......+++....", "+++.....+++.....", ".+++....+++.....", ".++++..+++......", "..+++.++++......", "...++++++.......", "...++++++.......", "....++++........", ".....++.........", ".....++........."}; voxbo-1.8.5~svn1246/scheduler/schedlib.cpp000066400000000000000000000062511153177201300203670ustar00rootroot00000000000000 // schedlib.cpp // VoxBo job scheduling util functions // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include #include #include #include "vbutil.h" #include "vbprefs.h" #include "vbjobspec.h" #include "voxbo.h" #include "schedlib.h" void read_queue(string queuedir,map &seqlist) { seqlist.clear(); int err; struct stat st; string seqpat=queuedir+"/[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"; vglob vg(seqpat); for(size_t i=0; i= js.startedtime) return 0; // if it's been more than RESEND_WAIT secs, don't refract if ((time(NULL) - js.startedtime) > RESEND_WAIT) return 0; // run out of reasons to let it go, better hold it up return 1; } // int // has_unsatisfied_dependencies(SI seq,JI js) // { // int jn,satisfied; // for (int i=0; i<(int)js->waitfor.size(); i++) { // jn=js->waitfor[i]; // // seq=js.sequence; // satisfied=0; // for (JI j=seq->speclist.begin(); jspeclist.end(); j++) { // // if it's satisfied, break and move on to the next one. if // // it's not, we can pass on this job immediately // if (j->jnum==jn) { // if (j->status=='D') {satisfied =1; break; } // else return 1; // } // } // if (!satisfied) // return 1; // } // return 0; // } int has_unsatisfied_dependencies(JI js,char donetable[],int maxjnum) { vbforeach(int32 jn,js->waitfor) { if (jn>maxjnum) continue; // bound checking, ignore on failure if (!(donetable[jn])) return 1; } return 0; } void remove_seqwait(string queuedir,int snum) { vglob vg((format("%s/waitfor.%d")%queuedir%snum).str()); for (size_t i=0; i &seqlist); int should_refract(VBJobSpec &js); void remove_seqwait(string queuedir,int snum); void cleanupqueue(map &seqlist,string qdir); int has_unsatisfied_dependencies(JI js,char donetable[],int maxjnum); voxbo-1.8.5~svn1246/scheduler/vbsrvd.cpp000066400000000000000000000352641153177201300201260ustar00rootroot00000000000000 // vbsrvd.cpp // The VoxBo server // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg using namespace std; #include "vbx.h" #include #include #include void vbsrvd_phone_home(); void vbsrvd_phone_home(tokenlist &args); float server_check_load(); int server_check_running(int snum,int jnum,pid_t pid); int server_check_resource(const string &command); void do_errornotify(VBJobSpec &js); int load_job_spec(VBJobSpec &js); void job_cleanup(VBJobSpec &js); void cleanup_update(VBJobSpec &js); void vbsrvd_help(); void vbsrvd_version(); void server_run_benchmark(string name,string cmd); void server_kill_job(tokenlist &args); VBPrefs vbp; int main(int argc,char *argv[]) { string fname; const int BUFSIZE=128; char buf[BUFSIZE]; tokenlist args; int cnt; // kill buffers so that we can reassign stdio below // setbuf(stdout,(char *)NULL); setbuf(stderr,(char *)NULL); // when running as a server, trust no env vars char **ee=environ; set evars; while (ee[0]) { evars.insert(ee[0]); ee++; } vbforeach(string s,evars) putenv((char *)(s.substr(0,s.find("="))).c_str()); // we used to just remove these four dangerous ones // putenv((char *)"USER"); // putenv((char *)"HOME"); // putenv((char *)"LOGNAME"); // putenv((char *)"MAIL"); // FIXME if vbp.init() generates any messages, they will go back // over the socket via xinetd vbp.init(); // be user voxbo seteuid(getuid()); setegid(vbp.voxbogid); seteuid(vbp.voxbouid); // live in the queue dir chdir(vbp.queuedir.c_str()); struct passwd *vbpw = getpwuid(vbp.voxbouid); vbp.username=vbpw->pw_name; fname=vbp.rootdir+"/etc/logs/"+vbp.thishost.nickname+".log"; umask(022); FILE *fp = fopen(fname.c_str(),"a"); chown(fname.c_str(),vbp.voxbouid,vbp.voxbogid); if (fp) { dup2(fileno(fp),2); fclose(fp); } else exit(5); // FIXME or maybe it's a good idea // read jobtypes and serverfile (to get local host config). // FIXME: we should probably put the jobtypes off until we're sure // we need them vbp.read_jobtypes(); vbp.read_serverfile(); signal(SIGPIPE,SIG_IGN); // sockets generate random sigpipes // signal(SIGCHLD,SIG_IGN) -- ignoring SIGCHLD prevents zombie // processes if we're not going to wait for forked children to exit. // since we do wait right now, the line is commented out // process command-line arguments if (argc>1) { tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; isecond; // string fname=args[++i]; // if (js.ReadFile(fname)) { // fprintf(stderr,"[E] vbsrvd: couldn't open job file %s\n",fname.c_str()); // exit(5); // } fprintf(stdout,"[I] vbsrvd: running job %05d-%03d\n",js.snum,js.jnum); if (vbp.jobtypemap.count(js.jobtype)==0) { fprintf(stderr,"[E] vbsrvd: %s bad jobtype '%s'\n",timedate().c_str(), js.jobtype.c_str()); exit(105); } js.jt=vbp.jobtypemap[js.jobtype]; fprintf(stderr,"[I] vbsrvd: asked to run job %s\n",js.basename().c_str()); run_voxbo_job(vbp,js); job_cleanup(js); vbsrvd_phone_home(); } else { fprintf(stderr,"[E] vbsrvd: called with invalid arguments\n"); exit(5); } } exit(0); } while ((cnt = read(0,buf,BUFSIZE)) > 0) { buf[cnt]='\0'; // make sure the input buffer is null terminated args.ParseLine(buf); string cmd=vb_toupper(args[0]); if (args.size() < 1) // give up at first invalid request break; else if (cmd=="JOB") { // job to run fprintf(stdout,"ACK"); fputc('\0',stdout); fflush(stdout); VBJobSpec sp; if (!(load_job_spec(sp))) { fprintf(stderr,"[I] %s received job %s\n",timedate().c_str(),sp.basename().c_str()); run_voxbo_job(vbp,sp); job_cleanup(sp); } // vbsrvd_phone_home(); break; } else if (cmd=="PHONEHOME") { fprintf(stdout,"ACK"); fputc('\0',stdout); fflush(stdout); vbsrvd_phone_home(args); } else if (cmd=="BENCHMARK") { server_run_benchmark(args[1],args.Tail(2)); break; } else if (cmd=="TEST") { // test fprintf(stdout,"ACK"); fputc('\0',stdout); fflush(stdout); } else if (cmd=="KILLJOB") { server_kill_job(args); break; } else if (cmd=="QUIT") { // just quit baby break; } } exit(0); } // load up the actual job info and match it with a jobtype int load_job_spec(VBJobSpec &js) { const int MAXBUF=32768; char buf[MAXBUF]; tokenlist args,lines; lines.SetSeparator("\n"); args.SetSeparator(" \t"); lines.SetQuoteChars(""); args.SetQuoteChars(""); js.init(); if (safe_recv(1,buf,MAXBUF,10.0)<8) { printf("NAK"); fputc('\0',stdout); fflush(stdout); return 101; } lines.ParseLine(buf); if (lines.size() == 0) { printf("NAK"); fputc('\0',stdout); fflush(stdout); return 101; } int valid=0; for (size_t i=0; i0) return la[0]; else return 0.0; #endif } void server_kill_job(tokenlist &args) { pid_t parentpid=strtol(args[1]); pid_t childpid=strtol(args[2]); // just in case, never kill init process! if (parentpid<2 || childpid<2) { printf("ACK\n"); fputc('\0',stdout); return; } // definitely kill vbsrvd, probably kill child killpg(parentpid,SIGUSR1); kill(parentpid,SIGUSR1); usleep(100000); kill(childpid,SIGUSR1); usleep(100000); if (kill(childpid,0)==-1 && errno == ESRCH) { printf("ACK\n"); fputc('\0',stdout); return; } // child didn't die, let's throw everything at it, in order killpg(parentpid,SIGHUP); killpg(parentpid,SIGTERM); killpg(parentpid,SIGKILL); kill(childpid,SIGHUP); kill(childpid,SIGINT); kill(childpid,SIGTERM); kill(childpid,SIGKILL); sleep(1); if (kill(childpid,0)==-1 && errno == ESRCH) { printf("ACK\n"); fputc('\0',stdout); return; } fprintf(stderr,"[E] %s process %d wouldn't die\n",timedate().c_str(),(int)childpid); printf("ACK\n"); fputc('\0',stdout); } void job_cleanup(VBJobSpec &js) { // be voxbo user to clean up seteuid(getuid()); setegid(vbp.voxbogid); seteuid(vbp.voxbouid); umask(022); cleanup_update(js); // update the sequence file // notify if necessary if (js.GetState() == XBad || js.GetState() == XWarn || js.GetState() == XSignal) do_errornotify(js); // go back to being whoever we are seteuid(getuid()); setegid(getgid()); } void do_errornotify(VBJobSpec &js) { if (js.email=="none") return; FILE *fp; char str[STRINGLEN]; string msg; msg="email "+js.email+"\n"; switch(js.GetState()) { case XBad: msg+="To: "+js.email+" (Sad VoxBo User)\n"; msg+="Subject: Error in VoxBo Sequence \""+js.seqname+"\" (job "+js.basename()+")\n"; msg+="Reply-To: nobody@nowhere.com\n"; msg+="Return-Path: "+js.email+"\n"; msg+="\n"; break; case XSignal: msg+="To: "+js.email+" (Besieged VoxBo User)\n"; msg+="Subject: VoxBo Sequence \""+js.seqname+"\" (job "+js.basename()+")\n"; msg+="Reply-To: nobody@nowhere.com\n"; msg+="Return-Path: "+js.email+"\n"; msg+="\n"; break; case XWarn: msg+="To: "+js.email+" (Concerned VoxBo User)\n"; msg+="Subject: Warning concerning VoxBo Sequence \""+js.seqname+"\" (job "+js.basename()+")\n"; msg+="Reply-To: nobody@nowhere.com\n"; msg+="Return-Path: "+js.email+"\n"; msg+="\n"; break; case XGood: default: msg+="To: "+js.email+" (Alert VoxBo User)\n"; msg+="Subject: Status Update on VoxBo Sequence \""+js.seqname+"\" (job "+js.basename()+")\n"; msg+="Reply-To: nobody@nowhere.com\n"; msg+="Return-Path: "+js.email+"\n"; msg+="\n"; break; } msg+="Your VoxBo job, described as \""+js.name+",\" returned error code "+ strnum(js.error)+" with the following message:\n\n"; msg+=js.errorstring+"\n\n"+"Here is the log your job generated:\n\n"; fp = fopen(js.logfilename().c_str(),"r"); if (fp) { while(fgets(str,STRINGLEN,fp) != NULL) { for (int i=0; i<(int)js.jt.nomail.size(); i++) { if (strncmp(str,js.jt.nomail[i].c_str(),js.jt.nomail[i].size())) continue; } msg+=str; } fclose(fp); } tell_scheduler(vbp.queuedir,vbp.thishost.nickname,msg); } void cleanup_update(VBJobSpec &js) { // send local finished time and new status to scheduler if (js.GetState()==XGood || js.GetState()==XWarn) { tell_scheduler(vbp.queuedir,vbp.thishost.nickname, (string)"setjobinfo "+strnum(js.snum)+" "+strnum(js.jnum)+ " status D"); tell_scheduler(vbp.queuedir,vbp.thishost.nickname, (string)"jobdone "+strnum(js.snum)+" "+strnum(js.jnum)+ " "+strnum(time(NULL))); } else if (js.GetState()==XRetry) { tell_scheduler(vbp.queuedir,vbp.thishost.nickname, (string)"retry "+strnum(js.snum)+" "+strnum(js.jnum)+ " "+strnum(js.retrycount)); } else { // XBad, XSignal, and XNone tell_scheduler(vbp.queuedir,vbp.thishost.nickname, (string)"setjobinfo "+strnum(js.snum)+" "+strnum(js.jnum)+ " status B"); tell_scheduler(vbp.queuedir,vbp.thishost.nickname, (string)"jobdone "+strnum(js.snum)+" "+strnum(js.jnum)+ " "+strnum(time(NULL))); } } void vbsrvd_phone_home() { tokenlist nojobs; vbsrvd_phone_home(nojobs); } void vbsrvd_phone_home(tokenlist &args) { // update our schedule, number of cpus, etc. vbp.thishost.CheckSchedule(); // load average vbp.thishost.loadaverage=server_check_load(); // update resource counts for those that have commands for (RI rr=vbp.thishost.resources.begin(); rr!=vbp.thishost.resources.end(); rr++) if (rr->second.command.size()) rr->second.cnt=server_check_resource(rr->second.command); // check on directories that are supposed to be non-empty bool dirsok=1; vbforeach(string dd,vbp.thishost.checkdirs) { if (vglob(dd+"/*").size()<1) { dirsok=0; break; } } if (!dirsok) vbp.thishost.status="dead"; else vbp.thishost.status="up"; // check on jobs supposedly running here map foundjobs; VBJobSpec js; js.hostname=vbp.thishost.nickname; for (size_t i=1; i\n"); printf("flags:\n"); printf(" -j process job file\n"); printf(" -h help\n"); printf(" -v version\n"); printf("notes:\n"); printf(" vbsrvd is normally invoked via (x)inetd or internally in single-user\n"); printf(" mode. if you invoke it yourself via the command line, you should \n"); printf(" already know what you're doing.\n"); printf("\n"); } void vbsrvd_version() { printf("VoxBo vbsrvd (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/scheduler/voxbo.cpp000066400000000000000000001600661153177201300177540ustar00rootroot00000000000000 // voxbo.cpp // VoxBo job scheduling // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include "vbutil.h" #include "vbprefs.h" #include "vbjobspec.h" #include "schedlib.h" using namespace std; using boost::format; // GLOBALS! map runningmap; VBPrefs vbp; list hostlist; map seqlist; enum {SERVER_OK,SERVER_DIE}; bool f_debug=0; bool f_running=1; int f_totalcpus=0; // total available CPUs, from host responses const int S_MISSING=180; // seconds since last response before a job is considered missing // prototypes for strictly internal functions int server_sleep(int s); int server_create(); int server_create_inet(); int server_create_unix(); int getvoxbolock(); void returnvoxbolock(); int reassignstdio(string &fname); void fork_send_voxbo_job(VBJobSpec &js,HI &myhost); int send_voxbo_job(int socket,VBJobSpec &js); void send_benchmarks(); void ping_hosts(); void ping_hosts_inet(); void ping_hosts_unix(); void run_jobs(); void update_hostlist(); void check_sent(); void setjobinfo_update_hostlist(VBJobSpec *newjs); void process_vbx(); void process_dropbox(); int process_jobrunning(string hostname,int snum,int jnum,pid_t pid,pid_t childpid,long stime); int process_jobdone(int snum,int jnum,long ftime); int process_setseqinfo(int ss,string newstatusinfo); int process_killsequence(int ss,string newstatus); int process_setjobinfo(int ss,int jj,string newstatusinfo); int process_email(string recipient,string fname); int process_adminemail(string fname); int process_hostupdate(string hh); int process_retry(string line); int do_retry(int snum,int jnum,int generations); int process_saveline(string line); //int send_email(string msg); string handle_server_setsched(tokenlist &args,string username); string handle_server_gimme(tokenlist &args,string username); string handle_server_changejobstatus(tokenlist &args,string username); string handle_server_setseqinfo(tokenlist &args,string username); string handle_server_killsequence(tokenlist &args,string username); int handle_server_sendfile(int ns,string username); void populate_running_jobs(map &seqlist); void handle_server_submit(int ns,string fname); int haltsequence(tokenlist &args,string username); void addrunningjob(VBJobSpec &js,string &hostname); void removerunningjob(jobid jid); void removerunningjob(int snum,int jnum); map availableresources(); int server_add(string nickname); int server_delete(string nickname); void send_hosts(int ns); void send_sequences(int ns); void read_serverlist(); void print_diagnostics(string arg); void vbscheduler_help(); void vbscheduler_version(); VBHost *findhost(string hname); // VBevents are maintained by the running scheduler for about a day class VBevent { public: string type; time_t etime; int32 snum,jnum; VBevent(int32 ss,int32 jj,string ty,time_t ti) {snum=ss;jnum=jj;type=ty;etime=ti;} }; deque dayevents; deque hourevents; int main(int argc,char *argv[]) { string logfile,pidfile; int newpid,mysocket,err; struct stat st; FILE *fp; int f_detach=0; int f_usestdio=1; string f_myqueue; // ignoring SIGCHLD avoids zombies when we don't wait() signal(SIGCHLD,SIG_IGN); // ignoring SIGPIPE avoids issue when popen command is missing signal(SIGPIPE,SIG_IGN); // in case we're going to send stdout and stderr to a file -- kill // the buffers to make sure everything comes out in order setbuf(stdout,(char *)NULL); setbuf(stderr,(char *)NULL); // parse arguments tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; i -1) close(mysocket); unlink(pidfile.c_str()); fprintf(stderr,"[I] %s voxbo scheduler terminated normally on host %s\n", timedate().c_str(),vbp.thishost.nickname.c_str()); returnvoxbolock(); exit(0); } void print_diagnostics(string arg) { string a=vb_tolower(arg); if (a.size()==0) a="all"; if (a=="all" || a=="jt") { printf("===========================> JOBTYPES <===========================\n"); for (TI i=vbp.jobtypemap.begin(); i!=vbp.jobtypemap.end(); i++) i->second.print(); } if (a=="all" || a.substr(0,3)=="seq") { printf("===========================> SEQUENCES <==========================\n"); for (SI seq=seqlist.begin(); seq!=seqlist.end(); seq++) seq->second.print(); } // FIXME replace this? // if (a=="all" || a.substr(0,2)=="sj") { // printf("===========================> JOBSPECS (short) <===================\n"); // for (JLI j=speclist.begin(); j!=speclist.end(); j++) { // printf("[I] DIAG_SJ: %08d-%05d: [%c] jobtype=%s started=%d finished=%d host=%s\n", // j->snum,j->jnum,j->status,j->jobtype.c_str(), // (int)j->startedtime,(int)j->finishedtime, // j->hostname.c_str()); // } // } if (a=="all" || a.substr(0,3)=="job") { printf("===========================> JOBSPECS <===========================\n"); pair js; vbforeach(js,runningmap) { js.second.print(); cout << time(NULL)-js.second.lastreport << endl; } } if (a=="all" || a.substr(0,3)=="hos" || a.substr(0,3)=="ser") { printf("===========================> HOSTS <===========================\n"); for (HI h=hostlist.begin(); h!=hostlist.end(); h++) h->print(); } } int server_create() { return server_create_inet(); } int server_create_inet() { int s,err,yes; struct sockaddr_in addr; s=socket(PF_INET,SOCK_STREAM,0); if (s < 0) return s; yes=1; setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof(yes)); memset(&addr,0,sizeof(addr)); addr.sin_family=PF_INET; addr.sin_port=htons(vbp.serverport+1); addr.sin_addr.s_addr=htonl(INADDR_ANY); err = bind(s,(struct sockaddr *)&addr,sizeof(addr)); if (err == -1) { close(s); return -2; } err = listen(s,10); if (err == -1) { close(s); return -3; } printf("Now listening to port %d\n",vbp.serverport+1); return s; } int server_create_unix() { int s,err; struct sockaddr_un addr; char sockname[1024]; sprintf(sockname,"/tmp/vbsocket.%s",vbp.username.c_str()); unlink(sockname); s=socket(PF_LOCAL,SOCK_STREAM,0); if (s < 0) return s; memset(&addr,0,sizeof(addr)); addr.sun_family=PF_LOCAL; strcpy(addr.sun_path,sockname); err = bind(s,(struct sockaddr *)&addr,sizeof(addr)); if (err == -1) { close(s); return -2; } err = listen(s,10); if (err == -1) { close(s); return -3; } printf("Now listening to UNIX domain socket\n"); return s; } // server_sleep() -- this cute little function waits for someone to // connect to the socket and send a message. it currently is a bit // lacking in the security department. but it will eventually be // rewritten to do cryptographic authentication. int server_sleep(int s) { struct timeval tv; fd_set ff; int err,ns,len; socklen_t ssize; struct sockaddr_in addr; char buf[STRINGLEN]; time_t start_time; tokenlist args; string username; ssize=sizeof(struct sockaddr_in); start_time = time(NULL); // if no socket, complain if (s < 0) { sleep(vbp.queuedelay); printf("error: couldn't create server port, waiting without listening\n"); return SERVER_OK; } while (time(NULL) - start_time < vbp.queuedelay) { FD_ZERO(&ff); FD_SET(s,&ff); tv.tv_sec = vbp.queuedelay; tv.tv_usec = 0; err = select(s+1,&ff,NULL,NULL,&tv); // can we receive? if (err < 1) { sleep(1); continue; } ns=accept(s,(struct sockaddr *)&addr,&ssize); if (ns == -1) { sleep(1); continue; } // FIXME -- here is where we need to do authentication len = safe_recv(ns,buf,STRINGLEN-1,10.0); // receive signon if (len<1) { close(ns); continue; } args.ParseLine(buf); if (args.size()) username=args[0]; send(ns,"ACK",4,0); len = safe_recv(ns,buf,STRINGLEN-1,10.0); // receive instruction if (len == 0) { close(ns); continue; } args.ParseLine(buf); string rmsg; if (args.size() > 0) { string cmd=vb_toupper(args[0]); if (cmd=="DIE") { // DIE send(ns,"ACK",4,0); close(ns); return SERVER_DIE; } else if (cmd=="GIMME") { // GIMME rmsg=handle_server_gimme(args,username); send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="QUEUEON") { f_running=1; send(ns,"ACK",4,0); } else if (cmd=="QUEUEOFF") { f_running=0; send(ns,"ACK",4,0); } else if (cmd=="SUBMIT") { send(ns,"ok",2,0); fprintf(stderr,"[E] somebody sent a SUBMIT\n"); // handle_server_submit(ns,args[1]); } else if (cmd=="SENDFILE") { handle_server_sendfile(ns,username); } else if (cmd=="GIVEBACK") { // GIVEBACK rmsg=handle_server_gimme(args,username); send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="CHANGEJOBSTATUS") { rmsg=handle_server_changejobstatus(args,username); send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="SETSEQINFO") { rmsg=handle_server_setseqinfo(args,username); send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="SETSCHED") { rmsg=handle_server_setsched(args,username); send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="KILLSEQUENCE") { rmsg=handle_server_killsequence(args,username); send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="HOSTS") { // HOSTS send_hosts(ns); } else if (cmd=="SEQUENCES") { // HOSTS send_sequences(ns); } else if (cmd=="ADDSERVER") { // HOSTS if (server_add(args[1])) rmsg="error adding server "+args[1]; else rmsg="server "+args[1]+" added successfully"; send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="DELSERVER") { // HOSTS if (server_delete(args[1])) rmsg="error deleting server "+args[1]; else rmsg="server "+args[1]+" removed successfully"; send(ns,rmsg.c_str(),rmsg.size()+1,0); } else if (cmd=="DIAG") { print_diagnostics(args[1]); } else if (cmd=="TEST") { send(ns,"ACK",4,0); } else if (cmd=="RESET") { printf("\n[I] %s scheduler reset begin\n",timedate().c_str()); hostlist.clear(); seqlist.clear(); runningmap.clear(); vbp.init(); vbp.read_jobtypes(); read_serverlist(); ping_hosts(); read_queue(vbp.queuedir,seqlist); populate_running_jobs(seqlist); printf("[I] %s scheduler reset complete\n\n",timedate().c_str()); } } close(ns); } return SERVER_OK; } void send_hosts(int ns) { // CR-separated list of hosts, each line parseable by // VBHost.frombuffer() for (HI h=hostlist.begin(); h!=hostlist.end(); h++) { if (h->valid==0) continue; if (h->hostname.size()==0) continue; if (h->nickname.size()==0) continue; string buf=h->tobuffer(runningmap); send(ns,buf.c_str(),buf.size(),0); send(ns,"\n",1,0); } send(ns,"\0",1,0); } void send_sequences(int ns) { char buf[STRINGLEN]; string str; for (SI seq=seqlist.begin(); seq!=seqlist.end(); seq++) { seq->second.updatecounts(); sprintf(buf,"[name '%s']",seq->second.name.c_str()); send(ns,buf,strlen(buf),0); sprintf(buf,"[num %d]",seq->second.seqnum); send(ns,buf,strlen(buf),0); sprintf(buf,"[priority %d]",seq->second.priority.priority); send(ns,buf,strlen(buf),0); sprintf(buf,"[owner %s]",seq->second.owner.c_str()); send(ns,buf,strlen(buf),0); sprintf(buf,"[status %c]",seq->second.status); send(ns,buf,strlen(buf),0); sprintf(buf,"[idle %d]",(int)(time(NULL)-seq->second.modtime)); send(ns,buf,strlen(buf),0); sprintf(buf,"[counts %d %d %d %d %d]", seq->second.jobcnt, seq->second.waitcnt, seq->second.runcnt, seq->second.badcnt, seq->second.donecnt); send(ns,buf,strlen(buf),0); send(ns,"[EOS]",5,0); } send(ns,"\0",1,0); } // handle_server_gimme() // GIMME host // GIVEBACK host string handle_server_gimme(tokenlist &args,string username) { VBHost *myhost; string rhost=args[1]; if (!(myhost=findhost(rhost))) return (string)"host "+rhost+" not found"; string gimfile=myhost->nickname+"."+username+".gim"; if (vb_tolower(args[0])=="gimme") { if (args.size()!=3) return (string)"illegal reservation"; if ((int)myhost->reservations.size()>myhost->total_cpus) return (string)"host "+myhost->nickname+" already totally reserved"; time_t deadline=time(NULL)+(strtol(args[2])*3600); string gimfile=myhost->nickname+"."+username+".gim"; umask(022); FILE *fp = fopen(gimfile.c_str(),"w"); if (fp) { fprintf(fp,"%s %ld %ld\n",username.c_str(),(long)time(NULL),(long)deadline); fclose(fp); } VBReservation rr; rr.owner=username; rr.start=time(NULL); rr.end=deadline; myhost->reservations.push_back(rr); return (string)"host "+rhost+" reserved successfully"; } else if (vb_tolower(args[0])=="giveback") { if (args.size()!=2) return (string)"illegal unreservation"; int myres=-1; for (int i=0; i<(int)myhost->reservations.size(); i++) { if (myhost->reservations[i].owner==username) myres=i; } if (myres==-1) return (string)"host "+myhost->nickname+" not currently reserved in your name"; myhost->reservations.erase(myhost->reservations.begin()+myres); unlink(gimfile.c_str()); return (string)"host "+myhost->nickname+" reserved"; } return (string)"unfathomable error"; } void send_benchmarks() { list::iterator bb; for (bb=vbp.benchmarks.begin(); bb!=vbp.benchmarks.end(); bb++) { // invalid name if (bb->name=="") continue; // not yet yet scheduled if (bb->scheduled==0) { // bb->scheduled=time(NULL)+(int)(VBRandom() & 0x1ff)-256; bb->scheduled=time(NULL)+bb->interval; continue; } // scheduled time not yet reached if (bb->scheduled>time(NULL)) continue; // run it! hostlist.sort(cmp_host_random); for(HI host = hostlist.begin(); host != hostlist.end(); host++) { if (host->status!="up") continue; if (host->loadaverage>0.2) continue; // no more excuses, ask this host to benchmark itself int s=safe_connect(&(host->addr),20.0); if (s < 0) continue; // sends this small shouldn't block, so we're okay not to select string msg; msg="BENCHMARK "+bb->name+" "+bb->cmd; send(s,msg.c_str(),msg.size(),0); close(s); bb->scheduled=time(NULL)+bb->interval; break; } } } // update all the hosts statuses, availability, etc void ping_hosts() { ping_hosts_inet(); } void ping_hosts_inet() { for(HI host = hostlist.begin(); host != hostlist.end(); host++) { // currently we don't skip host if it's "down," because we need to // know if jobs that may still be running on the host still are // for dead hosts, if it's been less than two minutes, skip if (host->status=="dead") { if (time(NULL)-host->lastresponse<120) continue; host->lastresponse=time(NULL); // using lastresponse as last check } // skip host if the last update process is still going if (host->updatepid!=0 && kill(host->updatepid,0)!=-1) continue; // skip host if we've had a response in the last 20 seconds -- the // dead check is because we just set lastresponse for dead hosts if (host->lastresponse!=0 && time(NULL)-host->lastresponse<20 && host->status!="dead") continue; host->updatepid=fork(); // child (pid=0) should ping and exit, parent should continue // regardless of whether or not fork was successful if (host->updatepid==0) { // use swap() trick below because clear() doesn't free memory. // note that there's a bad OS interaction here, because if the // pages are copy-on-write, we're better off not clearing // anything. for now, let it pass. // list().swap(seqlist); VBHost hh=*host; // list().swap(hostlist); hh.Ping(runningmap); _exit(0); } } } void ping_hosts_unix() { } void update_hostlist() { for(HI host = hostlist.begin(); host != hostlist.end(); host++) { if (host->lastresponse!=0 && time(NULL)-host->lastresponse>600) { host->status="dead"; host->lastresponse=time(NULL); // stow last check vector snums,jnums; // build list of jobs to mark waiting for (JI j=host->runninglist.begin(); j!= host->runninglist.end(); j++) { snums.push_back(j->snum); jnums.push_back(j->jnum); } // now mark them (can't do this in one step because // process_setjobinfo modifies the host's job list) for (int i=0; i<(int)snums.size(); i++) { printf("[E] %s job %08d-%05d was running on dead host %s\n", timedate().c_str(),snums[i],jnums[i],host->hostname.c_str()); process_setjobinfo(snums[i],jnums[i],"status W"); } } } } void fork_send_voxbo_job(VBJobSpec &js,HI &myhost) { cerr << format("[I] %s sending job %05d-%05d to host %s\n") % timedate().c_str() % js.snum% js.jnum % js.hostname; js.startedtime=time(NULL); js.finishedtime=0; js.serverstartedtime=0; js.serverfinishedtime=0; js.percentdone=-1; // flag startedtime int errs=0; errs+=process_setjobinfo(js.snum,js.jnum,(string)"startedtime "+strnum((int)js.startedtime)); errs+=process_setjobinfo(js.snum,js.jnum,(string)"host "+myhost->nickname); errs+=process_setjobinfo(js.snum,js.jnum,(string)"status R"); if (errs) { cerr << format("[E] %s %d error(s) setting job info for %08d-%05d\n") % timedate() % errs % js.snum % js.jnum; process_setjobinfo(js.snum,js.jnum,(string)"status W"); removerunningjob(js.snum,js.jnum); } pid_t mypid=fork(); if (mypid<0) { // error cerr << format("[E] %s couldn't even fork\n") % timedate(); process_setjobinfo(js.snum,js.jnum,(string)"status W"); removerunningjob(js.snum,js.jnum); return; } else if (mypid==0) { // child // get socket int s=safe_connect(&myhost->addr,3.0); if (s<0) _exit(404); int ret=send_voxbo_job(s,js); _exit(ret); } // we are the parent } int send_voxbo_job(int socket,VBJobSpec &js) { string msg; char tmp[STRINGLEN]; int err; tokenlist args; msg="JOB\n"; err=send(socket,msg.c_str(),msg.length()+1,0); if (err <0) { printf("[E] %s couldn't send to server %s\n", timedate().c_str(),js.basename().c_str()); return 109; } // recv the acknowledgment err=safe_recv(socket,tmp,STRINGLEN-1,10.0); if (err <1) return 102; msg="snum "+strnum(js.snum)+"\n"; msg+="number "+strnum(js.jnum)+"\n"; msg+="uid "+strnum((int)js.uid)+"\n"; msg+="actualcpus "+strnum(js.actualcpus)+"\n"; msg+="email "+js.email+"\n"; msg+="logdir "+js.logdir+"\n"; msg+="seqname "+js.seqname+"\n"; msg+="name "+js.name+"\n"; msg+="jobtype "+js.jobtype+"\n"; msg+="dirname "+js.dirname+"\n"; pair pp; vbforeach(pp,js.arguments) msg+="argument "+pp.first+" "+pp.second+"\n"; msg+="EOJ\n"; err=send(socket,msg.c_str(),msg.length()+1,0); if (err<(int)msg.length()+1) { printf("[E] %s failed to send entire job %s\n", timedate().c_str(),js.basename().c_str()); return 101; } err=safe_recv(socket,tmp,STRINGLEN-1,10.0); if (err <1) { printf("[E] %s no acknowledgment for job %s\n", timedate().c_str(),js.basename().c_str()); return 109; } tmp[err]='\0'; args.ParseLine(tmp); if (args[0]=="NAK") { fprintf(stderr,"[E] %s received NAK from %s for job %s\n", timedate().c_str(),js.hostname.c_str(),js.basename().c_str()); return 122; } // acknowledge the response (w/pid) from the server if we get one if (args[0]!="ACK") fprintf(stderr,"[E] %s received non-ack (%s) from %s for job %s\n", timedate().c_str(),args.Tail(0).c_str(), js.hostname.c_str(),js.basename().c_str()); return 0; } // getvoxbolock() returns 1 if we are able to be the only voxbo, // by locking the log file int getvoxbolock() { struct flock numlock; numlock.l_type = F_WRLCK; numlock.l_start = 0; numlock.l_len = 1; numlock.l_whence = SEEK_SET; if (fcntl(1,F_SETLK,&numlock) == -1) // lock stdout, ie the log file return 0; return 1; } void returnvoxbolock() { struct flock numlock; numlock.l_type = F_UNLCK; numlock.l_start = 0; numlock.l_len = 1; numlock.l_whence = SEEK_SET; fcntl(1,F_SETLK,&numlock); } VBHost * findhost(string hname) { for(HI host = hostlist.begin(); host != hostlist.end(); host++) { if (host->nickname==hname || host->hostname==hname) return &(*(host)); } return NULL; } int reassignstdio(string &logfile) { int fd; close(0); close(1); close(2); FILE *fp = fopen(logfile.c_str(),"a"); if (fp) { fd = fileno(fp); dup2(fd,1); dup2(fd,2); fclose(fp); if (!getvoxbolock()) { fprintf(stderr,"Couldn't lock log file. VoxBo already running?\n"); return 0; } return 1; } else return 0; } int haltsequence(VBSequence &seq) { //fprintf(stderr,"[HALT] halting sequence %d\n",seq.seqnum); for (SMI j=seq.specmap.begin(); j!= seq.specmap.end(); j++) { if (j->second.status!='R') continue; VBHost *hh=findhost(j->second.hostname); if (!hh) continue; //fprintf(stderr,"[HALT] halting job %d on host %s\n",j->second.jnum,hh->nickname.c_str()); hh->SendMsg((string)"KILLJOB "+strnum(j->second.pid)+" "+strnum(j->second.childpid)); } // fprintf(stderr,"[HALT] done halting sequence %d\n",seq.seqnum); return 0; } int handle_server_sendfile(int ns,string) { // receive filename and size char buf[STRINGLEN]; int len=safe_recv(ns,buf,STRINGLEN-1,10.0); if (len<1) return 1; tokenlist args; args.ParseLine(buf); if (args.size()!=3) return 2; fprintf(stderr,"[SENDFILE] name %s size %s\n",args(1),args(2)); int err=receive_file(ns,"/tmp/foo.dat",strtol(args[2])); fprintf(stderr,"receive_file returned %d\n",err); return 0; } string handle_server_changejobstatus(tokenlist &args,string) { if (args.size()!=4) return "[E] malformed job status request"; int seqnum=strtol(args[1]); string from=args[2]; string to=args[3]; int ret=0; if (seqlist.count(seqnum)==0) { return (string)"[E] sequence not found"; } VBSequence *seq=&(seqlist[seqnum]); for(SMI j=seq->specmap.begin(); j!=seq->specmap.end(); j++) { if (j->second.status==from[0] || (from=="*" && j->second.status!=to[0])) ret+=process_setjobinfo(seqnum,j->second.jnum,(string)"status "+to); } if (ret==0) return (string)"[I] sequence successfully updated"; else return (string)"[E] sequence not fully updated"; } string handle_server_setseqinfo(tokenlist &args,string username) { if (args.size()!=4) return "[E] malformed setseqinfo request"; int seqnum=strtol(args[1]); string tag=args[2]; string value=args[3]; if (seqlist.count(seqnum)!=1) return "missing"; if (!((seqlist[seqnum].owner==username) || (vbp.superusers.count(username)))) return "perm"; int ret=process_setseqinfo(seqnum,tag+" "+value); if (ret==0) return "success"; else return "error"; } string handle_server_setsched(tokenlist &args,string username) { // args should be one of the following: // setsched sched seqnums pri max pri2 max2 maxperhost // 0 1 2 3 4 5 6 7 // m/max seqnums max // 012345 seqnums pri // sched seqnums default // sched seqnums offhours // sched seqnums nice // sched seqnums xnice VBpri pp; set seqnums=numberset(args[2]); int validnums=0,invalidnums=0; vector newseqinfo; vbforeach(int s,seqnums) if (seqlist.count(s)) validnums++; else invalidnums--; if (validnums==0) return "[E] no valid sequence numbers specified for scheduling change"; if (args[1]=="sched") { // build just the args tokenlist tmpl=args; args.DeleteFirst(); args.DeleteFirst(); args.DeleteFirst(); if (pp.set(args)) return "[E] invalid scheduling parameters"; newseqinfo.push_back("priority "+strnum(pp.priority)); newseqinfo.push_back("maxjobs "+strnum(pp.maxjobs)); newseqinfo.push_back("priority2 "+strnum(pp.priority2)); newseqinfo.push_back("maxjobs2 "+strnum(pp.maxjobs2)); newseqinfo.push_back("maxperhost "+strnum(pp.maxperhost)); } else if ((args[1]=="m" || args[1]=="max") && args.size()==4) { newseqinfo.push_back("maxjobs "+strnum(strtol(args[3]))); } string status; int succeededcnt=0,failedcnt=0; vbforeach(int s,seqnums) { if (seqlist.count(s)==0) continue; if (seqlist[s].owner!=username && vbp.superusers.count(username)==0) { status+="[E] you are not the owner of sequence "+strnum(s)+"\n"; continue; } bool bad=0; vbforeach(string ss,newseqinfo) { int ret=process_setseqinfo(s,ss); if (ret) bad=1; } if (bad) failedcnt++; else succeededcnt++; } if (succeededcnt) { status+="[I] "+strnum(succeededcnt)+" sequences successfully updated"; if (failedcnt) status+="\n"; } if (failedcnt) status+="[E] "+strnum(succeededcnt)+" sequences could not be updated"; return status; } string handle_server_killsequence(tokenlist &args,string username) { if (args.size()!=3) return "[E] malformed kill request"; int seqnum=strtol(args[1]); string value=args[2]; if (seqlist.count(seqnum)!=1) return "missing"; if (!((seqlist[seqnum].owner==username) || (vbp.superusers.count(username)))) return "perm"; int ret=process_killsequence(seqnum,value); if (ret==0) return "success"; else return "error"; } void handle_server_submit(int ns,string fname) { FILE *numfile; string tmp=vbp.queuedir+"/vb.num"; numfile = fopen(tmp.c_str(),"r+"); if (!numfile) { tmp="[E] couldn't open sequence counter file in "+vbp.queuedir; send(ns,tmp.c_str(),tmp.size(),0); return; } char numdata[STRINGLEN]; if (fgets(numdata,STRINGLEN,numfile) == NULL) { tmp="[E] couldn't get data from counter file in "+vbp.queuedir; send(ns,tmp.c_str(),tmp.size(),0); return; } int seqnum=strtol(numdata); rewind(numfile); fprintf(numfile,"%d\n",seqnum+1); fclose(numfile); char sname[STRINGLEN]; sprintf(sname,"%s/%08d",vbp.queuedir.c_str(),seqnum); VBSequence seq; seq.LoadSequence(fname); if (!seq.valid) { tmp="[E] invalid sequence dir "+fname; send(ns,tmp.c_str(),tmp.size(),0); return; } seq.seqnum=seqnum; for (SMI j=seq.specmap.begin(); j!=seq.specmap.end(); j++) j->second.snum=seqnum; seq.queuedtime=time(NULL); int err=seq.Write(sname); if (err) { tmp="[E] error "+strnum(err)+" writing sequence"; send(ns,tmp.c_str(),tmp.size(),0); return; } else rmdir_force(fname); tmp="[I] sequence "+strnum(seqnum)+" has been submitted"; send(ns,tmp.c_str(),tmp.size(),0); // now just to be safe (and to make sure we know what dir we're in...) seq.LoadSequence(sname); seqlist[seq.seqnum]=seq; return; } int server_add(string sname) { // if it's on the list already, bring it back for (HI h=hostlist.begin(); h!=hostlist.end(); h++) { if (h->nickname==sname || h->hostname==sname) { h->status="up"; h->lastresponse=0; printf("[I] %s marked host %s (%s) up\n",timedate().c_str(), h->nickname.c_str(),h->hostname.c_str()); ping_hosts(); return 0; } } // not on list, let's add it, and update its taken_cpus VBHost hh(sname,sname,vbp.serverport); // find nickname or hostname from vbp.servers pair ss; vbforeach(ss,vbp.servers) { if (ss.first==sname) hh.hostname=ss.second; if (ss.second==sname) hh.nickname==ss.first; } // count running jobs (it might have some after a restart) for (map::iterator vv=runningmap.begin(); vv!=runningmap.end(); vv++) { if (vv->second.hostname==hh.nickname) hh.taken_cpus++; // FIXME always just one cpu } hostlist.push_back(hh); printf("[I] %s added host %s (%s)\n",timedate().c_str(), hh.nickname.c_str(),hh.hostname.c_str()); return 0; } int server_delete(string nickname) { for (HI h=hostlist.begin(); h!=hostlist.end(); h++) { if (h->nickname==nickname) { h->status="down"; printf("[I] %s marked host %s (%s) down\n",timedate().c_str(), nickname.c_str(),h->hostname.c_str()); return 0; } } return 101; } void read_serverlist() { pair ss; vbforeach(ss,vbp.servers) server_add(ss.first); } void process_vbx() { tokenlist line; vglob vg("*.vbx"); if (!vg.size()) return; for (size_t i=0; isecond.snum=seqnum; seq.queuedtime=time(NULL); int err=seq.Write(sname); if (err) { fprintf(stderr,"[E] error %d writing sequence %s\n",err,sname.c_str()); return; } else rmdir_force(vg[i].c_str()); if (f_debug) printf("[I] sequence %d received\n",seqnum); seq.LoadSequence(sname); seqlist[seq.seqnum]=seq; seqnum++; } FILE *nfile=fopen(numfile.c_str(),"w"); if (!nfile) { printf("[E] couldn't open sequence counter file in %s\n",vbp.queuedir.c_str()); return; } fprintf(nfile,"%d\n",seqnum); fclose(nfile); return; } int process_jobrunning(string hostname,int snum,int jnum,pid_t pid,pid_t childpid,long stime) { if (runningmap.count(jobid(snum,jnum))==0) { printf("[E] %s job %08d-%08d running but not in runningmap\n", timedate().c_str(),snum,jnum); return 101; } VBJobSpec *js=&(runningmap[jobid(snum,jnum)]); if (!js) { printf("[E] %s received jobrunning message for non-running job %08d-%05d\n", timedate().c_str(),snum,jnum); return -1; } // update jobspec js->serverstartedtime=stime; js->pid=pid; js->childpid=childpid; if (js->status!='R') { js->status='R'; } // now make sure it's set everywhere (esp. the job files) process_setjobinfo(snum,jnum,"status R"); process_setjobinfo(snum,jnum,(string)"host "+hostname); process_setjobinfo(snum,jnum,(string)"pid "+strnum(pid)); process_setjobinfo(snum,jnum,(string)"childpid "+strnum(childpid)); process_setjobinfo(snum,jnum,(string)"serverstartedtime "+strnum(stime)); return 0; } int process_jobdone(int snum,int jnum,long ftime) { process_setjobinfo(snum,jnum,(string)"serverfinishedtime "+strnum(ftime)); removerunningjob(snum,jnum); return 1; } int process_setjobinfo(int ss,int jj,string newstatusinfo) { // update the file char jobfile[STRINGLEN]; int err; // first append the line to the actual job file sprintf(jobfile,"%08d/%05d.job",ss,jj); if ((err=appendline(jobfile,newstatusinfo))) { printf("[E] %s couldn't update job file %s (%d,%d,%s) [%d]\n", timedate().c_str(),jobfile, ss,jj,newstatusinfo.c_str(),err); return 101; } // seqlist[ss] is our sequence, seqlist[ss].specmap[jj] is our jobspec if (seqlist.count(ss)!=1) { printf("[E] %s seq not in seqlist\n",timedate().c_str()); return 102; } if (seqlist[ss].specmap.count(jj)!=1) { printf("[E] %s jobspec not in seq's speclist\n",timedate().c_str()); return 103; } seqlist[ss].specmap[jj].ParseJSLine(newstatusinfo); seqlist[ss].modtime=time(NULL); // ...and in the runningmap if (runningmap.count(jobid(ss,jj))) runningmap[jobid(ss,jj)].ParseJSLine(newstatusinfo); return 0; } int process_setseqinfo(int ss,string newstatusinfo) { // update the file string seqfile=(format("%08d/info.seq")%ss).str(); if (appendline(seqfile,newstatusinfo)) { printf("[E] %s couldn't update sequence file\n",timedate().c_str()); return 101; } // update it in the seqlist if (seqlist.count(ss)) { seqlist[ss].ParseSeqLine(newstatusinfo); seqlist[ss].modtime=time(NULL); } else printf("[E] %s setseqinfo for non-existent sequence %d\n", timedate().c_str(),ss); return 0; } int process_killsequence(int ss,string newstatus) { printf("[I] %s killing sequence %d with %s\n",timedate().c_str(), ss,newstatus.c_str()); // update the file string seqfile=(format("%08d/info.seq")%ss).str(); if (appendline(seqfile,"status "+newstatus)) { printf("[E] %s couldn't update sequence file\n",timedate().c_str()); return 101; } // update it in the seqlist if (seqlist.count(ss)) { seqlist[ss].ParseSeqLine((string)"status "+newstatus); haltsequence(seqlist[ss]); } else printf("[E] %s setseqinfo for non-existent sequence %d\n", timedate().c_str(),ss); return 0; } int process_hostupdate(string hh) { string hostinfo,field; HI tmph=hostlist.end(); tokenlist args,argx; args.SetQuoteChars("[<(\"'"); argx.SetQuoteChars("[<(\"'"); args.ParseLine(hh); // first argument better be full hostname argx.ParseLine(args[0]); if (argx[0]!="hostname") { printf("[E] %s malformed host update\n",timedate().c_str()); return 101; } string hostname=argx[1]; for (HI h=hostlist.begin(); h!=hostlist.end(); h++) { if (h->hostname==hostname) { tmph=h; } } if (tmph==hostlist.end()) { printf("[E] %s invalid host update from %s\n", timedate().c_str(),hostname.c_str()); return 101; } tmph->resources.clear(); string newstatus; for (size_t i=1; ihostname=argx[1]; else if (field=="nickname") tmph->nickname=argx[1]; else if (field=="currentpri") tmph->currentpri=strtol(argx[1]); else if (field=="job") { if (argx.size()<3) continue; int snum=strtol(argx[1]); int jnum=strtol(argx[2]); // make sure it's in the running list and the seqlist if (runningmap.count(jobid(snum,jnum))<1) continue; if (seqlist.count(snum)<1) continue; if (seqlist[snum].specmap.count(jnum)<1) continue; // update lastreport time in both runningmap and seqlist // printf("XXXXX updating %d %d\n",snum,jnum); runningmap[jobid(snum,jnum)].lastreport=time(NULL); seqlist[snum].specmap[jnum].lastreport=time(NULL); } else if (field=="load") tmph->loadaverage=strtod(argx[1]); else if (field=="resource") { VBResource rr; rr.name=argx[1]; rr.f_global=strtol(argx[2]); rr.cnt=strtol(argx[3]); tmph->resources[rr.name]=rr; } else if (field=="total_cpus") tmph->total_cpus=strtol(argx[1]); else if (field=="status") newstatus=argx[1]; } tmph->Update(); tmph->lastresponse=time(NULL); if ((tmph->status=="dead" || tmph->status=="unknown") && newstatus=="up") tmph->status="up"; else if (newstatus=="dead") tmph->status="dead"; f_totalcpus=0; vbforeach(const VBHost &hh,hostlist) f_totalcpus+=hh.avail_cpus; return 0; } int process_retry(string line) { tokenlist args; args.ParseLine(line); if (args.size()!=3) { printf("[E] %s invalid retry line\n",timedate().c_str()); return 101; } int snum=strtol(args[0]); int jnum=strtol(args[1]); int generations=strtol(args[2]); return do_retry(snum,jnum,generations); } int do_retry(int snum,int jnum,int generations) { // retry this job if (seqlist.count(snum)!=1) return 101; if (seqlist[snum].specmap.count(jnum)!=1) return 102; process_setjobinfo(snum,jnum,"status W"); if (generations) { vbforeach (int wf,seqlist[snum].specmap[jnum].waitfor) do_retry(snum,wf,generations-1); } return 0; } int process_saveline(string line) { printf("[!] %s asked to save line: %s\n",timedate().c_str(),line.c_str()); return 0; } void populate_running_jobs(map &seqlist) { for (SI s=seqlist.begin(); s!=seqlist.end(); s++) { for (SMI j=s->second.specmap.begin(); j!=s->second.specmap.end(); j++) { if (j->second.status == 'R') addrunningjob(j->second,j->second.hostname); } } } int process_adminemail(string fname) { if (vbp.sendmail.size()==0) return 200; FILE *mailpipe; string email; string msg; ifstream fs; char buf[STRINGLEN],cmd[STRINGLEN]; printf("[I] %s emailing %s\n",timedate().c_str(),vbp.sysadmin.c_str()); fs.open(fname.c_str(),ios::in); if (!fs) return 101; fs.getline(buf,STRINGLEN,'\n'); // throw away first line snprintf(cmd,STRINGLEN,"%s -f %s -t",vbp.sendmail.c_str(),vbp.sysadmin.c_str()); mailpipe = popen(cmd,"w"); if (!mailpipe) { fprintf(stderr,"[E] vbsrvd: serious error, couldn't email sysadmin about it\n"); fs.close(); return 101; } fprintf(mailpipe,"To: %s\n",vbp.sysadmin.c_str()); fprintf(mailpipe,"Reply-To: %s\n",vbp.sysadmin.c_str()); while (1) { fs.read(buf,STRINGLEN-1); buf[fs.gcount()]='\0'; if (fs.gcount()) fprintf(mailpipe,"%s",msg.c_str()); if (fs.gcount() slist; typedef pair spair; vbforeach(spair &ss,seqlist) { VBSequence *seq=&(ss.second); if (seq->status!='R') continue; if (seq->priority.maxjobs && seq->priority.maxjobs2 && seq->runcnt >= (seq->priority.maxjobs+seq->priority.maxjobs2)) continue; seq->effectivepriority=seq->priority.priority; if (seq->priority.maxjobs && seq->runcnt>=seq->priority.maxjobs) seq->effectivepriority=seq->priority.priority2; slist.insert(seq->seqnum); } // FIXME this block of code creates a list that is never used // make a copy of the hostlist with all "up" hosts // list myhosts; // map globals; // vbforeach (VBHost &hh,hostlist) { // if (hh.status!="up") continue; // myhosts.push_back(hh); // } // get the list of avail resources map rlist=availableresources(); while (1) { // if we're out of eligible sequences, escape if (slist.size()<1) break; // FIXME no available CPUs? break // find the sequence with the highest priority int maxpri=0; int maxseq=0; VBSequence *seq; vbforeach(int snum,slist) { seq=&(seqlist[snum]); if (seq->effectivepriority>maxpri) { maxseq=seq->seqnum; maxpri=seq->effectivepriority; } } // no jobs have any priority if (maxpri==0) break; // we have our sequence seq=&(seqlist[maxseq]); // build a map of how may of this sequence's jobs are running on each host map hostcnt; for (map::iterator jj=runningmap.begin(); jj!=runningmap.end(); jj++) { if (jj->first.snum!=seq->seqnum) continue; if (hostcnt.count(jj->second.hostname)) hostcnt[jj->second.hostname]++; else hostcnt[jj->second.hostname]=1; } // iterate all jobs, finding ones that we can run int unmet; for (SMI j=seq->specmap.begin(); j!=seq->specmap.end(); j++) { if (j->second.status!='W') continue; VBJobType *jt=&(vbp.jobtypemap[j->second.jobtype]); // check dependencies unmet=0; vbforeach(int32 ww,j->second.waitfor) { if (seq->specmap[ww].status!='D') { unmet=1; break; } } if (unmet) continue; // find a host; first build combined requirement list map reqs=jt->requires; for (map::iterator rr=seq->requires.begin(); rr!=seq->requires.end(); rr++) if (rr->second>reqs[rr->first]) reqs[rr->first]=rr->second; HI myhost=hostlist.end(); for(HI p=hostlist.begin(); p!=hostlist.end(); p++) { if (p->status!="up") continue; p->Update(); // recalc available cpus if (!(p->valid)) continue; if (p->avail_cpus<1) continue; // any available cpus? if (seq->effectivepriority < p->currentpri) continue; if (seq->priority.maxperhost && hostcnt[p->nickname]>=seq->priority.maxperhost) continue; if (j->second.forcedhosts.size() && j->second.forcedhosts.count(p->nickname)==0) continue; // do we have the needed resources? first combine jt-based // and seq-based requires lists unmet=0; for (map::iterator rr=reqs.begin(); rr!=reqs.end(); rr++) { // available on this host? string rname=p->nickname+":"+rr->first; if (rlist.count(rname)) if (rlist[rname]>=rr->second) continue; // available globally? rname="*:"+rr->first; if (rlist.count(rname)) if (rlist[rname]>=rr->second) continue; unmet=1; break; } // if we can't get the resources, try the next host if (unmet) continue; // get out of the host list loop to queue the job myhost=p; break; } // if we have no valid myhost for this job... if (myhost==hostlist.end()) continue; // let's take the resources we're using for (map::iterator rr=reqs.begin(); rr!=reqs.end(); rr++) { if (rr->second==0) continue; // first try locally string rname=myhost->nickname+":"+rr->first; if (rlist.count(rname)) { if (rlist[rname]>=rr->second) { rlist[rname]-=rr->second; continue; } } // then globally rname="*:"+rr->first; if (rlist.count(rname)) { if (rlist[rname]>=rr->second) { rlist[rname]-=rr->second; continue; } } } // since we're going to try to grab this machine, we can do the // following (note that avail_cpus will be updated when we call // addrunningjob) addrunningjob(j->second,myhost->nickname); if (f_debug) cout << format("[D] voxbo: sending to %s\n") % myhost->nickname; fork_send_voxbo_job(j->second,myhost); if (f_debug) cout << format("[D] voxbo: done sending\n"); // if we have a maxperhost, update the host counts if (seq->priority.maxperhost) { if (hostcnt.count(myhost->nickname)) hostcnt[myhost->nickname]++; else hostcnt[myhost->nickname]=1; //cout << myhost->nickname << " : " << hostcnt[myhost->nickname] << endl; // FIXME REMOVE } //cout << "MAX " << seq->priority.maxperhost << endl; // update runcnt and waitcnt, figure out new priority and max seq->runcnt++; seq->waitcnt--; if (seq->priority.maxjobs && (seq->runcnt>=seq->priority.maxjobs)) { // if we can't run jobs under pri2 then we're done with this seq if (seq->priority.priority2<1 || (seq->priority.maxjobs2 && seq->runcnt>=seq->priority.maxjobs2)) { slist.erase(seq->seqnum); break; } // otherwise, make sure we're using pri2. if that means a // change, break out to re-prioritize sequences if (seq->effectivepriority!=seq->priority.priority2) { seq->effectivepriority=seq->priority.priority2; break; } } } // we checked all the jobs, remove this sequence and keep going slist.erase(seq->seqnum); } } // int // send_email(string msg) // { // if (vbp.sendmail.size()==0) // return 200; // FILE *mailpipe; // char str[STRINGLEN]; // string email; // snprintf(str,STRINGLEN,"%s -f %s -t",vbp.sendmail.c_str(),vbp.username.c_str()); // mailpipe = popen(str,"w"); // if (!mailpipe) { // fprintf(stderr,"[E] vbsrvd: serious error, couldn't email sysadmin about it\n"); // return 101; // } // fprintf(mailpipe,"%s\n",msg.c_str()); // pclose(mailpipe); // return 0; // } void addrunningjob(VBJobSpec &js,string &hostname) { js.hostname=hostname; js.lastreport=time(NULL); runningmap[jobid(js.snum,js.jnum)]=js; VBHost *hh; if ((hh=findhost(hostname))!=NULL) { hh->taken_cpus++; // FIXME update for jobs using more than once cpu hh->Update(); } else cout << "couldn't find host " << hostname << endl; } void removerunningjob(int snum,int jnum) { removerunningjob(jobid(snum,jnum)); } void removerunningjob(jobid jid) { if (!runningmap.count(jid)) { cerr << format("[E] voxbo: tried to remove non-running job %08d-%05d\n") % jid.snum % jid.jnum; return; } string hostname=runningmap[jid].hostname; runningmap.erase(jid); for (HI hh=hostlist.begin(); hh!=hostlist.end(); hh++) { if (hh->nickname==hostname || hh->hostname==hostname) { hh->taken_cpus--; hh->Update(); break; } } } // availableresources() returns a map of resource names to the amount // available. the resource names are prepended with the host, as in // mymachine:myresource. for global (not machine-locked) resources, // it's *:myresource. map availableresources() { // FIXME go through hosts, make a list, go through jobs, mod the list map rlist; for (HI hh=hostlist.begin(); hh!=hostlist.end(); hh++) { for (map::iterator ri=hh->resources.begin(); ri!=hh->resources.end(); ri++) { string rname=hh->nickname+":"+ri->second.name; if (ri->second.f_global) rname="*:"+ri->second.name; if (rlist.count(rname)) { if (rlist[rname]second.cnt) rlist[rname]=ri->second.cnt; } else rlist[rname]=ri->second.cnt; } } // now we have a list of all the resources, let's subtract what's running for (map::iterator vv=runningmap.begin(); vv!=runningmap.end(); vv++) { VBJobType jt=vbp.jobtypemap[vv->second.jobtype]; for (map::iterator rr=jt.requires.begin(); rr!=jt.requires.end(); rr++) { string rname=vv->second.hostname+":"+rr->first; if (rlist.count(rname)) { rlist[rname]-=rr->second; continue; } rname=vv->second.hostname+":"+rr->first; if (rlist.count(rname)) { rlist[rname]-=rr->second; continue; } } } return rlist; } // cleanupqueue() -- delete sequences as needed void cleanupqueue(map &seqlist,string qdir) { chdir(qdir.c_str()); for (SI ss=seqlist.begin(); ss!=seqlist.end(); ss++) { VBSequence *seq=&(ss->second); seq->updatecounts(); if (seq->status=='X' && seq->runcnt==0) { // rmdir_force(seq->seqdir); rename(seq->seqdir.c_str(),(seq->seqdir+"_defunct").c_str()); } // if all done, mark as private and remove seq waitfors else if (seq->jobcnt > 0 && seq->donecnt == seq->jobcnt) { remove_seqwait(vbp.queuedir,seq->seqnum); rename(seq->seqdir.c_str(),(seq->seqdir+"_defunct").c_str()); seq->status='X'; } else if (seq->status=='K' && seq->runcnt==0) { rename(seq->seqdir.c_str(),(seq->seqdir+"_defunct").c_str()); seq->status='X'; } // FIXME if it's too old, mark as private // else if ((time(NULL) - seq->queuedtime) > SECONDSINAWEEK) // setseqinfo(seq->seqnum,"status","X"); } // remove sequences with status X from the seqlist set removenums; for (SI ss=seqlist.begin(); ss!=seqlist.end(); ss++) if (ss->second.status=='X') removenums.insert(ss->second.seqnum); vbforeach(int n,removenums) seqlist.erase(n); // remove directories of jobs that should be dead vglob vg(qdir+"/*_defunct"); for (size_t i=0; i js; set r_remove; set r_restart; vbforeach(js,runningmap) { if (removenums.count(js.first.snum)) { // this sequence was just removed printf("[W] %s job %05d-%08d was removed from runninglist after seq removed\n", timedate().c_str(),js.first.snum,js.first.jnum); r_remove.insert(js.first); } // FIXME hardcoded 3 min missing deadline else if ((time(NULL)-js.second.lastreport)>S_MISSING) r_restart.insert(js.first); } vbforeach(jobid ji,r_remove) removerunningjob(ji); vbforeach(jobid ji,r_restart) { printf("[E] %s job %05d-%08d was missing and set to run again\n", timedate().c_str(),js.first.snum,js.first.jnum); process_setjobinfo(ji.snum,ji.jnum,(string)"status W"); removerunningjob(ji); // FIXME should flag the machine as losing jobs and eventually shut it down } } void vbscheduler_help() { printf("\nVoxBo scheduler (v%s)\n",vbversion.c_str()); printf("usage:\n"); printf(" voxbo \n"); printf("flags:\n"); printf(" -l log file\n"); printf(" -d detach\n"); printf(" -x debug\n"); printf(" -q

specify queue directory\n"); // printf(" -s single-user mode\n"); printf(" -h help\n"); printf(" -v version\n"); printf("notes:\n"); printf(" "); printf("\n"); } void vbscheduler_version() { printf("VoxBo scheduler (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/scheduler/voxbo.h000066400000000000000000000036141153177201300174140ustar00rootroot00000000000000 // voxbo.h // VoxBo headers // Copyright (c) 1998,1999 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vbutil.h" #include "vbprefs.h" #include "vbjobspec.h" #define MAXFILENAME 128 #define MAXHOSTS 64 // maximum number of eligible hosts #define MAXFILES 512 // maximum number of files in a job #define MAXTAGLEN 32 // maximum length of scan tag in chars #ifndef STRINGLEN #define STRINGLEN 512 // used widely for lots of stuff #endif voxbo-1.8.5~svn1246/scheduler/voxq.cpp000066400000000000000000001036501153177201300176100ustar00rootroot00000000000000 // voxq.cpp // VoxBo queue utility // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg #include #include "vbutil.h" #include "vbprefs.h" #include "vbjobspec.h" #include #include "voxq.hlp.h" using namespace std; using boost::format; // GLOBALS VBPrefs vbp; list hostlist; list seqlist; int voxq_sequences(tokenlist &args,set flags); void voxq_sequencedetail(tokenlist &args); void voxq_debug(tokenlist &args); void voxq_dumpconfig(tokenlist &args); void voxq_dumpjobtypes(tokenlist &args); void voxq_marksequence(tokenlist &args,string status); void voxq_killsequence(tokenlist &args,string newstatus); void voxq_changejobs(tokenlist &args,char from,char to); void voxq_help(); void voxq_gimme(tokenlist &args,int gim=TRUE); void voxq_cpus(string modename); void voxq_resources(); void voxq_die(); void voxq_reset(); void voxq_server(tokenlist &args); void voxq_queue(tokenlist &args); void voxq_version(); void voxq_whynot(tokenlist &args); void voxq_sched(tokenlist &args); void quit_handler(int); void server2host(string servername,char *hostname); int voxq_send_file(tokenlist &args); int get_scheduler_info(string msg,string &info); int get_hostlist(); int get_sequencelist(); void add_numbers(set &nums,string str); void print_queue(int argc,char **argv); int voxq_tell_scheduler(string msg,string &returnmsg); int get_addr_unix(struct sockaddr_un &addr); int get_addr_inet(struct sockaddr_in &addr); // uid_t euid; int main(int argc,char *argv[]) { umask(022); vbp.init(); vbp.read_serverfile(); tokenlist args,emptylist; args.Transfer(argc-1,argv+1); string modename=vb_tolower(args[0]); if (modename.substr(0,2)=="--") modename=modename.substr(2,string::npos); else if (modename[0]=='-') modename=modename.substr(1,string::npos); args[0]=modename; set flags; // flags.insert("all"); int ret=0; if (args.size()<1 || modename=="h" || modename=="help") voxq_help(); else if (modename=="all"||modename=="a") { voxq_cpus(modename); voxq_sequences(emptylist,flags); } else if (modename=="version"||modename=="v") voxq_version(); else if (modename=="seqs"||modename=="s") ret=voxq_sequences(args,flags); else if (modename=="ss") { flags.insert("all"); ret=voxq_sequences(args,flags); } else if (modename=="resources"||modename=="l") voxq_resources(); else if (modename=="x") voxq_sequencedetail(args); else if (modename=="xx") voxq_sequencedetail(args); else if (modename=="cpus"||modename=="c") voxq_cpus(modename); else if (modename=="gimme" || modename=="g") voxq_gimme(args,TRUE); else if (modename=="giveback"|| modename=="b") voxq_gimme(args,FALSE); else if (modename=="kill"||modename=="k") voxq_killsequence(args,"K"); // kill jobs, mark to be removed else if (modename=="postpone"||modename=="p") voxq_marksequence(args,"P"); // postpone jobs else if (modename=="resume"||modename=="r") voxq_marksequence(args,"R"); // mask as ready else if (modename=="retry"||modename=="t") voxq_changejobs(args,'B','W'); else if (modename=="pushthrough"||modename=="u") voxq_changejobs(args,'B','D'); else if (modename=="whynot"||modename=="j") voxq_whynot(args); else if (modename=="halt" || modename=="y") voxq_killsequence(args,"P"); // kill jobs, mark as P else if (modename=="w") voxq_changejobs(args,'*','W'); else if (modename=="d") voxq_debug(args); // pri/max stuff else if (modename=="sched") voxq_sched(args); else if (modename=="max"||modename=="m") voxq_sched(args); else if (modename.size()==1 && strchr("012345",modename[0])) voxq_sched(args); // SYSADMIN ONLY else if (modename=="die") voxq_die(); else if (modename=="reset") voxq_reset(); else if (modename=="server") voxq_server(args); else if (modename=="queue") voxq_queue(args); else if (modename=="dump") voxq_dumpconfig(args); else if (modename=="jobtypes") voxq_dumpjobtypes(args); else { printf("voxq: unrecognized options, try voxq -help for help\n"); exit(5); } exit(ret); } enum {vb_notfound=0,vb_running=1,vb_postponed=2,vb_killed=3, vb_bad=4,vb_waiting=5,vb_nodata=6}; int voxq_sequences(tokenlist &args,set flags) { if (args.size()>2) { voxq_help(); exit(100); } int myseq=0,ret=vb_notfound; if (args.size()==2) myseq=strtol(args[1]); if (seqlist.size()==0) { if (get_sequencelist()) { printf("[E] voxq: error retrieving queue data\n"); return vb_nodata; } } if (seqlist.size()<1) { printf("The VoxBo queue is empty.\n"); return vb_notfound; } seqlist.sort(); int diecnt=0,postcnt=0; int i=0,skippedcnt=0; int runcnt=0,waitcnt=0,badcnt=0,donecnt=0,jobcnt=0,seqcnt=0; for(list::iterator seq=seqlist.begin(); seq!=seqlist.end(); seq++) { // skip old sequences not owned by us if (seq->owner!=vbp.username && seq->modtime > 60*60*24*2 && flags.count("all")<1) { skippedcnt++; continue; } // if we're only doing one, check if this is it if (myseq>0 && myseq!=seq->seqnum) continue; if (i++ % 20 == 0) { printf("------------------------------------------------------------------------\n"); printf("Sequence Name Num Pri Owner "); printf("Wait Run Bad Done Total\n"); printf("------------------------------------------------------------------------\n"); } // M means the sequence has been moved and will soon be removed if (seq->status=='M') continue; if (seq->name.size()) printf("%-20.20s ",seq->name.c_str()); else printf("%-20.20s ",""); printf("%-5d",seq->seqnum); printf(" %-3d",seq->priority.priority); printf("%-10.10s",seq->owner.c_str()); printf("%-6d",seq->waitcnt); printf("%-6d",seq->runcnt); printf("%-6d",seq->badcnt); printf("%-5d",seq->donecnt); printf("%-6d",seq->jobcnt); runcnt+=seq->runcnt; badcnt+=seq->badcnt; waitcnt+=seq->waitcnt; donecnt+=seq->donecnt; jobcnt+=seq->jobcnt; seqcnt++; if (seq->status == 'K') { printf("[*]"); diecnt++; } else if (seq->status == 'P') { printf("[P]"); postcnt++; } printf("\n"); if (myseq>0) { if (diecnt) ret=vb_killed; else if (seq->badcnt) ret=vb_bad; else if (postcnt) ret=vb_postponed; else if (seq->runcnt) ret=vb_running; else ret=vb_waiting; } } if (seqcnt>1) { printf("------------------------------------------------------------------------\n"); cout << format("%-20.20s %-6d%-6d%-6d%-5d%-6d\n")% "Totals"%waitcnt%runcnt%badcnt%donecnt%jobcnt; } if (seqcnt) printf("------------------------------------------------------------------------\n"); else printf("No active jobs in the queue.\n"); if (skippedcnt) printf("[!] %d idle sequences were omitted (use voxq -ss to include them)\n",skippedcnt); if (diecnt) printf("[*] this sequence has been killed\n"); if (postcnt) printf("[P] this sequence has been postponed\n"); return ret; } void voxq_sequencedetail(tokenlist &args) { int seqnum,hrs,mins,secs,jobnum; if (args.size() != 2 && args.size()!=3) { printf("[E] voxq: wrong number of arguments\n"); return; } jobnum = -1; seqnum=strtol(args[1]); if (args.size() > 1) jobnum = strtol(args[2]); // FIXME the below reads it directly from the queue -- bad! VBSequence seq(vbp,seqnum); if (!seq.valid) { printf("No such valid sequence %d.\n",seqnum); return; } printf(" Number: %d\n",seq.seqnum); printf(" Name: %s\n",seq.name.c_str()); printf(" Status: %c ",seq.status); if (seq.status == 'R') printf("(ready to run)\n"); else if (seq.status == 'P') printf("(postponed)\n"); else if (seq.status == 'K') printf("(killed)\n"); else printf("(mystery status)\n"); // printf(" Priority: %d jobs at pri %d\n",seq.priority.maxjobs,seq.priority.priority); // if (seq.priority.maxjobs) // printf(" Priority2: %d jobs at pri %d\n",seq.priority.maxjobs2,seq.priority.priority2); // printf(" Maxperhost: %d\n",seq.priority.maxperhost); printf(" Priority: %s\n",((string)seq.priority).c_str()); printf(" Owner: %s\n",seq.owner.c_str()); vbforeach(string fh,seq.forcedhosts) printf("Forced Host: %s",fh.c_str()); printf(" jobcount: %d total\n",seq.jobcnt); if (args[0]=="xx") { for (SMI js = seq.specmap.begin(); js!=seq.specmap.end(); js++) { printf("\n"); printf("JOB %d - %s\n",js->second.jnum,js->second.name.c_str()); printf("logfile: %s\n",js->second.logfilename().c_str()); printf(" status: %c ",js->second.status); if (js->second.status == 'R') printf("(running)\n"); else if (js->second.status == 'W') printf("(waiting to run)\n"); else if (js->second.status == 'S') printf("(shipped)\n"); else if (js->second.status == 'B') printf("(bad)\n"); else if (js->second.status == 'D') printf("(done)\n"); else printf("(mystery status)\n"); printf(" type: %s\n",js->second.jobtype.c_str()); if (js->second.startedtime) { GetElapsedTime(js->second.startedtime,time(NULL),hrs,mins,secs); printf(" most recently started %d:%02d:%02d ago (h:m:s) ago on host %s\n", hrs,mins,secs,js->second.hostname.c_str()); if (js->second.finishedtime) { GetElapsedTime(js->second.startedtime,js->second.finishedtime,hrs,mins,secs); printf(" finished +%d:%02d:%02d after being started",hrs,mins,secs); } printf("\n"); } } } else if (args[0]=="x") { set rset,wset,sset,bset,dset,oset; for (SMI js = seq.specmap.begin(); js!=seq.specmap.end(); js++) { if (js->second.status=='W') wset.insert(js->first); else if (js->second.status=='R') rset.insert(js->first); else if (js->second.status=='S') sset.insert(js->first); else if (js->second.status=='B') bset.insert(js->first); else if (js->second.status=='D') dset.insert(js->first); else oset.insert(js->first); } cout << format("what are the jobs in this sequence doing?\n"); if (rset.size()) cout << format("these jobs are running: %s\n")%textnumberset(rset); if (wset.size()) cout << format("these jobs are waiting: %s\n")%textnumberset(wset); if (sset.size()) cout << format("these jobs are shipped: %s\n")%textnumberset(sset); if (bset.size()) cout << format("these jobs are bad: %s\n")%textnumberset(bset); if (dset.size()) cout << format("these jobs are done: %s\n")%textnumberset(dset); if (oset.size()) cout << format("these jobs have unknown status: %s\n")%textnumberset(oset); } else if (args[0]=="ls") { for (SMI js = seq.specmap.begin(); js!=seq.specmap.end(); js++) { printf("JOB %d (%s) [%c]",js->second.jnum,js->second.jobtype.c_str(), js->second.status); if (js->second.startedtime) { GetElapsedTime(js->second.startedtime,time(NULL),hrs,mins,secs); printf(" most recently started %d:%02d:%02d (h:m:s) ago on host %s\n", hrs,mins,secs,js->second.hostname.c_str()); if (js->second.finishedtime) { GetElapsedTime(js->second.startedtime,js->second.finishedtime,hrs,mins,secs); printf(" finished +%d:%02d:%02d after being started",hrs,mins,secs); } printf("\n"); } else printf("\n"); } } } void voxq_debug(tokenlist &args) { int seqnum,hrs,mins,secs,jobnum; if (args.size()!=2 && args.size()!=3) return; jobnum = -1; seqnum=strtol(args[1]); if (args.size()>1) jobnum = strtol(args[2]); VBSequence seq(vbp,seqnum); if (!seq.valid) { printf("No such valid sequence %d.\n",seqnum); return; } printf("Sequence name: %s\n",seq.name.c_str()); printf(" Status: %c\n",seq.status); printf(" Priority: %d\n",seq.priority.priority); printf(" Owner: %s\n",seq.owner.c_str()); printf(" Total jobs: %d\n",seq.jobcnt); printf(" Bad jobs: %d\n",seq.badcnt); for (SMI js = seq.specmap.begin(); js != seq.specmap.end(); js++) { if (js->second.status!='B') continue; printf("\n"); printf("JOB %d - %s\n",js->second.jnum,js->second.name.c_str()); printf(" logfile: %s\n",js->second.logfilename().c_str()); printf(" type: %s\n",js->second.jobtype.c_str()); pair pp; vbforeach(pp,js->second.arguments) printf(" argument: %s=%s\n",pp.first.c_str(),pp.second.c_str()); if (js->second.startedtime) { GetElapsedTime(js->second.startedtime,time(NULL),hrs,mins,secs); printf(" most recently started %d:%02d:%02d (h:m:s) ago on host %s\n", hrs,mins,secs,js->second.hostname.c_str()); if (js->second.finishedtime) { GetElapsedTime(js->second.startedtime,js->second.finishedtime,hrs,mins,secs); printf(" finished +%d:%02d:%02d after being started\n",hrs,mins,secs); } printf("\n"); } // offer options for how to handle this job string resp=vb_tolower(vb_getchar("[v]iew log, [e]dit log, [s]kip, or [q]uit: ")); printf("\n\n"); if (resp=="v") { printf("======================BEGIN LOG FILE======================\n"); string logfile=vbp.queuedir+"/"+js->second.seqdirname()+"/"+ js->second.basename()+".log"; system(str(format("cat %s")%logfile).c_str()); printf("=======================END LOG FILE=======================\n"); } else if (resp=="e") { if (fork()==0) { string editor; editor=getenv("VISUAL"); if (!editor.size()) editor=getenv("EDITOR"); if (!editor.size()) editor="emacs"; system((str(format("%s %s")%editor%js->second.logfilename()).c_str())); } } else if (resp=="s") continue; else if (resp=="q") break; } } void voxq_whynot(tokenlist &) { printf("[E] voxq: whynot is temporarily out of commission\n"); } void voxq_marksequence(tokenlist &args,string status) { int ret; set seqnums,success,errors,commerrs; string returnmsg; for (size_t i=1; iseqnums,success,errors,commerrs; string returnmsg; for (size_t i=1; i ... // see hlp file for more details void voxq_sched(tokenlist &args) { int ret; string returnmsg,tmp; VBpri pp; // error if (args.size()<2) { printf("usage: voxq -sched \n"); printf(" or: -sched \n"); printf(" or: -sched \n"); printf(" or: -m \n"); printf(" or: -# [where # is from 0 to 5]\n"); printf(" note: priority 0 jobs will never run\n"); printf(" note: maxjobs of 0 means no limit\n"); printf(" note: when maxjobs is reached, pri2 is used (it can be 0)\n"); printf(" note: sequence numbers can include ranges and comma-separated\n"); printf(" lists (e.g., 1-5,7-10), but no spaces\n"); return; } // -sched 10101 [interactive] if (args.size()==2 && args[0]=="sched") { string tmps; cout << "(below, use 0 for no limit)\n"; cout << format("max jobs per host [default=%d]: ")%pp.maxperhost; cin >> tmps; if (!tmps.empty()) pp.maxperhost=strtol(tmps); cout << format("max jobs at default priority [default=%d]: ")%pp.maxjobs; cin >> tmps; if (!tmps.empty()) pp.maxjobs=strtol(tmps); cout << format("default priority [default=%d]: ")%pp.priority; cin >> tmps; if (!tmps.empty()) pp.priority=strtol(tmps); if (pp.maxjobs>0) { cout << format("max jobs at secondary priority [default=%d]: ")%pp.maxjobs2; cin >> tmps; if (!tmps.empty()) pp.maxjobs2=strtol(tmps); cout << format("secondary priority [default=%d]: ")%pp.priority2; cin >> tmps; if (!tmps.empty()) pp.priority2=strtol(tmps); } tmps=str(format("setsched %s %s %d %d %d %d %d")%args[0]%args[1]% pp.maxjobs%pp.priority%pp.maxjobs2%pp.priority2%pp.maxperhost); ret=voxq_tell_scheduler(tmps,returnmsg); if (ret) printf("[E] voxq: couldn't communicate with scheduler (%d)\n",ret); else cout << returnmsg << endl; return; } else if (args.size()==2 && args[0].size()==1 && strchr("012345",args[0][0])) { tmp="setsched sched "+args[1]+" "+args[0]; ret=voxq_tell_scheduler(tmp,returnmsg); if (ret) printf("[E] voxq: couldn't communicate with scheduler (%d)\n",ret); else cout << returnmsg << endl; return; } else if (args.size()>2) { tmp="setsched "+args.Tail(0); ret=voxq_tell_scheduler(tmp,returnmsg); if (ret) printf("[E] voxq: couldn't communicate with scheduler (%d)\n",ret); else cout << returnmsg << endl; return; } else { printf("usage: voxq -sched \n"); printf(" or: -sched \n"); printf(" or: -sched \n"); printf(" note: priority 0 jobs will never run\n"); printf(" note: maxjobs of 0 means no limit\n"); printf(" note: when maxjobs is reached, pri2 is used (it can be 0)\n"); printf(" note: sequence numbers can include ranges and comma-separated\n"); printf(" lists (e.g., 1-5,7-10), but no spaces\n"); return; } return; } void voxq_changejobs(tokenlist &args,char from,char to) { int ret; char tostring[2]; set seqnums; char tmp[STRINGLEN]; string returnmsg; for (size_t i=1; i 3)) { printf("[E] voxq: usage: voxq -g [max number of hours]\n"); return; } else if (!gimflag && args.size() != 2) { printf("[E] voxq: usage: voxq -b \n"); return; } if (args.size() == 3) hours = strtol(args[1]); else hours=1; if (gimflag) sprintf(tmp,"GIMME %s %d",args[1].c_str(),hours); else sprintf(tmp,"GIVEBACK %s",args[1].c_str()); int err = voxq_tell_scheduler(tmp,returnmsg); if (!err) printf("%s\n",returnmsg.c_str()); else printf("Couldn't communicate with scheduler (%d).\n",err); } void voxq_die() { int err; string returnmsg; if (!vbp.su) { printf("Sorry, only a VoxBo superuser can kill the scheduler.\n"); return; } err = voxq_tell_scheduler("DIE",returnmsg); switch(err) { case 0: printf("The scheduler has shut down.\n"); break; case 1: printf("Sorry, the scheduler does not appear to be running.\n"); break; case 2: printf("Sorry, we couldn't find the scheduler's IP address.\n"); break; case 3: printf("Sorry, we couldn't send a message to the scheduler.\n"); break; default: printf("Sorry, unexpected error communicating with the scheduler.\n"); break; } } void voxq_reset() { int err; string returnmsg; if (!vbp.su) { printf("Sorry, only a VoxBo superuser can kill the scheduler.\n"); return; } err = voxq_tell_scheduler("RESET",returnmsg); switch(err) { case 0: printf("The scheduler has been asked to reset itself.\n"); break; case 1: printf("Sorry, we couldn't figure out where the scheduler is running.\n"); break; case 2: printf("Sorry, we couldn't find the scheduler's IP address.\n"); break; case 3: printf("Sorry, we couldn't send the RESET message to the scheduler.\n"); break; default: printf("Sorry, unexpected error communicating with the scheduler.\n"); break; } } void voxq_server(tokenlist &args) { if (!vbp.su) { printf("[E] voxq: sorry, you must be a VoxBo superuser to use this command\n"); return; } string cmd=vb_tolower(args[1]); string rmsg; int err; if (cmd=="add" && args.size()==3) { err=voxq_tell_scheduler("ADDSERVER "+args[2],rmsg); printf("%s\n",rmsg.c_str()); } else if ((cmd=="remove"||cmd=="delete") && args.size()==3) { err=voxq_tell_scheduler("DELSERVER "+args[2],rmsg); printf("%s\n",rmsg.c_str()); } else { printf("[E] voxq: --server usage:\n"); printf("[E] voxq --server add \n"); printf("[E] voxq --server remove \n"); return; } } void voxq_queue(tokenlist &args) { if (!vbp.su) { printf("[E] voxq: sorry, you must be a VoxBo superuser to use this command\n"); return; } string cmd=vb_tolower(args[1]); string rmsg; int err; if (cmd=="on") { err=voxq_tell_scheduler("QUEUEON",rmsg); } else if (cmd=="off") err=voxq_tell_scheduler("QUEUEOFF",rmsg); else { printf("[E] voxq: unrecognized command %s\n",cmd.c_str()); return; } if (err) { printf("[E] voxq: error contacting scheduler\n"); return; } printf("%s\n",rmsg.c_str()); } int voxq_send_file(tokenlist &args) { char tmp[STRINGLEN]; int s,err; struct sockaddr_in addr; if ((err=get_addr_inet(addr))) return err; if ((s = safe_connect(&addr,2.0)) < 0) return 103; // send authentication string sprintf(tmp,"%s",vbp.username.c_str()); if (send(s,tmp,strlen(tmp)+1,0) < (int)strlen(tmp)+1) { close(s); return 4; } // receive ACK int cnt = safe_recv(s,tmp,STRINGLEN,10.0); if (cnt <= 3) { close(s); return 4; } // send indication we're sending if (send(s,"SENDFILE",9,0) < 9) { close(s); return 4; } // send file if (send_file(s,args[1])) { close(s); return 4; } // receive ACK cnt = safe_recv(s,tmp,STRINGLEN,10.0); if (cnt <= 0) tmp[0]='\0'; tmp[4]='\0'; close(s); return 0; } int get_hostlist() { if (hostlist.size()) return 0; string hostinfo; VBHost tmph; if (get_scheduler_info("HOSTS",hostinfo)) return 101; // cout << hostinfo << endl; tokenlist args; args.SetSeparator("\n"); args.SetQuoteChars(""); args.ParseLine(hostinfo); // args.print(); for (size_t i=0; isecond.shortname.c_str()); } printf("\n"); } else { printf("\n"); for(TI jt = vbp.jobtypemap.begin(); jt != vbp.jobtypemap.end(); jt++) { printf("\n"); jt->second.print(); } printf("\n"); } } void voxq_cpus(string) { if (get_hostlist()) { printf("[E] voxq: couldn't retrieve list of servers\n"); return; } if (hostlist.size()==0) { printf("No servers currently available.\n"); return; } // FIXME switch to strings and boost::format char tmp[STRINGLEN],hostinfo[STRINGLEN]; char elapsed[STRINGLEN]; int hrs,mins,secs; HI host; char jobdesc[STRINGLEN]; printf("\nServer Load Pri Job Pct Elapsed\n"); // below: for each host, first get status info, then check on what's // running, then check on reservations. only print the host, load, // etc. on the first printed line for(host = hostlist.begin(); host != hostlist.end(); host++) { // only superusers see hosts that haven't responded yet if (host->status=="unknown" && !vbp.su) continue; snprintf(hostinfo,STRINGLEN,"%-11.11s %-3.2f %1d ", host->nickname.c_str(),host->LoadAverage(),host->currentpri); if (host->status=="down") { printf("%-11.11s \n",host->nickname.c_str()); hostinfo[0]=0; } if (host->status=="dead") { printf("%-11.11s \n",host->nickname.c_str()); hostinfo[0]=0; } // now see what's running on this host, across all queues if (host->runninglist.size()==0 && strlen(hostinfo)>0) printf("%-20.20s \n",hostinfo); else { for (JI js=host->runninglist.begin(); js!=host->runninglist.end(); js++) { GetElapsedTime(0,js->startedtime,hrs,mins,secs); if (hrs || mins || secs) sprintf(elapsed,"%d:%02d:%02d",hrs,mins,secs); else sprintf(elapsed,""); if (js->name.size()>0) { string newname; vbforeach(char c,js->name) { if (isprint(c)) newname+=c; } sprintf(jobdesc,"%s (%05d-%05d)",newname.c_str(),js->snum,js->jnum); } else sprintf(jobdesc,"[unnamed job] (%05d-%05d)",js->snum,js->jnum); if (js->percentdone > -1 && js->percentdone < 101) sprintf(tmp,"%d",js->percentdone); else sprintf(tmp,"-"); printf("%-20.20s %-30.30s %3.3s %-8.8s\n", hostinfo,jobdesc,tmp,elapsed); hostinfo[0]=0; // print hostinfo only on first iteration } } // FIXME do something about gimmes here // if no jobs or gimmes, still print something! } printf("\n"); } void voxq_resources() { if (get_hostlist()) return; HI host; tokenlist args; printf("\nServer Load CPU Usage Resources\n"); for(host = hostlist.begin(); host != hostlist.end(); host++) { printf("%-14.14s %-3.2f %d of %d ", host->nickname.c_str(),host->LoadAverage(), host->taken_cpus,host->total_cpus); for (RI rr=host->resources.begin(); rr!=host->resources.end(); rr++) printf("%s(%d) ",rr->second.name.c_str(),rr->second.cnt); printf("\n"); if (host->status=="down") { printf("%s is down\n",host->nickname.c_str()); continue; } if (host->status=="dead") { printf("%s is not responding\n",host->nickname.c_str()); continue; } } printf("\n"); } void server2host(string servername,char *hostname) { if (get_hostlist()) return; hostname[0]=0; for(HI host = hostlist.begin(); host != hostlist.end(); host++) { if (dancmp(host->nickname.c_str(),servername.c_str())) strcpy(hostname,host->hostname.c_str()); } } void add_numbers(set &nums,string str) { set newnums=numberset(str); vbforeach(int32 ii,newnums) nums.insert(ii); } void quit_handler(int) { printf("\n"); exit(5); } int get_addr_inet(struct sockaddr_in &addr) { struct sockaddr_in *xaddr=(struct sockaddr_in *)&(addr); struct hostent *hp; tokenlist args; args.ParseFirstLine(vbp.rootdir+"/etc/scheduler.pid"); if (args.size() < 2) return 101; // set up the host address memset(&addr,0,sizeof(struct sockaddr_in)); xaddr->sin_family=AF_INET; xaddr->sin_port=htons(vbp.serverport+1); hp = gethostbyname(args[0].c_str()); if (!hp) return 102; memcpy(&xaddr->sin_addr,hp->h_addr_list[0],hp->h_length); return 0; } int get_addr_unix(struct sockaddr_un &addr) { // FIXME non-functional! return -1; struct sockaddr_un *xaddr=(struct sockaddr_un *)&(addr); tokenlist args; char sockname[1024]; printf(sockname,"/tmp/vbsocket.%s",vbp.username.c_str()); // set up the host address memset(&addr,0,sizeof(struct sockaddr_un)); xaddr->sun_family=AF_LOCAL; strcpy(xaddr->sun_path,sockname); return 0; } int voxq_tell_scheduler(string msg,string &returnmsg) { char tmp[STRINGLEN]; int s,err; struct sockaddr_in addr; if ((err=get_addr_inet(addr))) return err; if ((s = safe_connect(&addr,4.0)) < 0) return 103; // send authentication string sprintf(tmp,"%s",vbp.username.c_str()); if (send(s,tmp,strlen(tmp)+1,0) < (int)strlen(tmp)+1) { close(s); return 4; } // receive ACK int cnt = safe_recv(s,tmp,STRINGLEN,10.0); if (cnt <= 3) { close(s); return 4; } // send message if (send(s,msg.c_str(),msg.size()+1,0) < (int)msg.size()+1) { close(s); return 4; } // receive ACK cnt = safe_recv(s,tmp,STRINGLEN,10.0); if (cnt <= 1) tmp[0]='\0'; returnmsg=tmp; close(s); return 0; } void voxq_help() { cout << boost::format(help1) % vbversion; if (vbp.su) cout << boost::format(help2); printf("\n can be a single sequence number, a range, or both (e.g., 1-3,7-10)\n"); printf("\n"); } void voxq_version() { printf("VoxBo voxq (v%s)\n",vbversion.c_str()); } voxbo-1.8.5~svn1246/scheduler/voxq1.hlp000066400000000000000000000042461153177201300176730ustar00rootroot00000000000000 VoxBo voxq (v%s)\n",vbversion.c_str()); usage: voxq -a show all sequences and servers voxq -c show status of voxbo servers voxq -l show resource info for all servers voxq -s [seq] show sequences (or just seq) currently in queue voxq -g [hrs=1] gimme server (shut down queueing) voxq -b giveback server (restart queueing) voxq -d debug sequence (see bad log files) voxq -k kill sequence (permanent) voxq -y halt a running sequence voxq -p postpone a sequence voxq -r resume a postponed sequence voxq -t retry a sequence (set bad jobs to run) voxq -u mark bad jobs in a sequence as done voxq -w do-over -- mark all jobs as waiting voxq -m set maxjobs for a sequence voxq -sched set scheduling parameters (see below) voxq -x [job=all] examine sequence in detail voxq -h get help (this message) voxq -v print voxbo version information # voxq -j why won't my jobs run? notes: can be a single sequence number, a range, or both (e.g., 1-3,7-10) -sched sets the priority and other scheduling parameters for one or more sequences. The first argument is the sequence number (or set or numbers) you want d to modify. The rest set the policy, as follows: -sched 3 run an unlimited number of jobs at priority 3 -sched 2 3 run no more than 2 jobs at a time, at priority 3 -sched 2 3 0 1 run 2 jobs at pri 3, then unlimited additional jobs at priority 1 (zero means unlimited) -sched 2 3 0 1 2 same as the above, but no more than 2 per server -sched default set to current default -sched offhours set to configuration for off-hours processing -sched nice set to colleague-friendly policy -sched xnice set to very colleague-friendly policy -sched hold set not to run until further notice voxbo-1.8.5~svn1246/scheduler/voxq2.hlp000066400000000000000000000004621153177201300176700ustar00rootroot00000000000000(sysadmin only:) voxq --die ask voxbo to die voxq --reset ask voxbo to reread config voxq --dump dump voxbo config info voxq --jobtypes describe registered jobtypes voxq --queue [on/off] turn job running on or off voxq --server add/remove voxbo-1.8.5~svn1246/scripts/000077500000000000000000000000001153177201300156135ustar00rootroot00000000000000voxbo-1.8.5~svn1246/scripts/Makefile000066400000000000000000000010361153177201300172530ustar00rootroot00000000000000 # Makefile for shell scripts and other simple things -include ../make_vars.txt include ../make_stuff.txt SHSCRIPTS=newprep.sh oldprep.sh minprep.sh makevlsm.sh vbinstall.sh SHSCRIPTS+=spm8_coreg.sh spm8_realign.sh spm8_segment.sh spm8_warp.sh spm8_reslice.sh SHSCRIPTS+=dcmcrawl.sh BINSCRIPTS := $(basename $(SHSCRIPTS)) .PHONY: default install default: $(BINSCRIPTS) # turn the .sh files into unsuffixed executables $(BINSCRIPTS): % : %.sh cp $< $@ install: cp -f $(BINSCRIPTS) $(VB_BINDIR) clean: rm -f $(CLEANME) $(BINSCRIPTS) voxbo-1.8.5~svn1246/scripts/bigprep.vbp000066400000000000000000000026411153177201300177570ustar00rootroot00000000000000 # script bigprep.vbp # jobtypes are found in /usr/local/VoxBo/etc/jobtypes # globals for this script: # DIR - target directory for processed data # rawdir - directory of raw data # firstrun - eventual path to first run in processed data # thresh - absolute threshold value # anat - sample anatomical in rawdir # func - sample functional in rawdir # dummies - number of dummy images per scan # setup runonce shellcommand "mkdir -p $DIR" runonce shellcommand "mkdir -p $adir" runonce vb2cub $rawdir/$rawanat $adir/Anatomical.cub runonce shellcommand "tes2cub $rawdir/$rawfunc $adir/Functional.cub" runonce newprep $adir # calc params runonce spm2_norm_calc $adir $paramfile $anat $refvol $xa $ya $za $bb_anat # make ndisplay.cub runonce spm2_norm_apply3d $adir $adir/$paramfile $anat nDisplay.cub $xa $ya $zf $bb_disp # apply to scout image runonce spm2_norm_apply3d $adir $adir/$paramfile $func n$func $xf $yf $zf $bb_func # process the data shellcommand "mkdir -p $run" shellcommand "vb2tes $rawdir/$src $run/$run.tes -e $dummies" slicecorrect $run/$run.tes $run/$run.tes 1 orient $run/$run.tes $run/$run.tes RPI runonce extractref $firstrun $adir/FirstEPI.cub #realign $run/$run.tes $run/$run.tes 0.5 $adir/FirstEPI.cub spm2_realign $run $adir/FirstEPI.cub $run.tes $run.tes smooth $run/$run.tes $run/$run.tes 3 3 3 threshold $run/$run.tes $run/$run.tes $thresh calcgs $run/$run.tes $run/$run.tes calcps $run/$run.tes $run/$run.tes voxbo-1.8.5~svn1246/scripts/bigprep_example.vbp000066400000000000000000000030721153177201300214710ustar00rootroot00000000000000 script bigprep.vbp # subject data SEQUENCENAME "sequence name for job queue" EMAIL nobody@nowhere.com PRIORITY 2 LOGGING 1 # DIR should be the root for that subject's data DIR /jet/kimberg/newdemo/data/sample # where the raw data are globals rawdir=/jet/raw/kimberg/stability/n1_scan1 # for thresholding globals thresh=200 globals firstrun=ch1/ch1.tes # name of anatomical in raw data dir globals anat=0006_t1_mpr_AX_MPRAGE # name of sample functional in raw data dir globals func=0007_ep2d_pace # list of dummy scans to be excluded (e.g., 0-4 for six dummies) globals dummies=0-4 # SPM2 NORMALIZATION-RELATED # desired voxel sizes in mm for normalized functional data globals xa=1 globals ya=1 globals za=1 # desired voxel sizes in mm for normalized anatomical data globals xf=3 globals yf=3 globals zf=3 # anatomy directory (full path or relative to DIR) globals adir=/jet/kimberg/demo/data/aaa/Anatomy # reference T1 for normalization globals refvol=/usr/local/spm2/templates/T1.mnc globals paramfile=spm2_norm_params.mat globals anat=Anatomical.cub globals func=Functional.cub # below bounding boxes are for 1x1x1/3x3x3 -- if that's not you, good # luck! globals "bb_anat=[-79,-112,-51;79,76,86]" globals "bb_func=[-78,-111,-50;78,75,85]" globals "bb_disp=[-79,-112,-50;79,76,85]" globals email=$EMAIL # each FILE line has a run name and a source in the raw data dir. if # you set run=foo, then your tes file will end up called # DIR/foo/foo.tes FILE run=ch1 src=0010_MoCoSeries FILE run=ch2 src=0012_MoCoSeries FILE run=perf src=0014_MoCoSeries FILE run=ch3 src=0016_MoCoSeries voxbo-1.8.5~svn1246/scripts/dcmcrawl.sh000077500000000000000000000020551153177201300177500ustar00rootroot00000000000000#!/bin/bash # crawl directories, using dcmsplit to anonymize data printhelp() { echo " " echo "VoxBo dcmcrawl" echo "summary: crawl directories, running dcmsplit on all the files" echo "usage:" echo " dcmcrawl " echo "the following flags are honored:" echo "notes:" echo " " } if [[ $# -lt 2 ]] ; then printhelp; exit; fi STAMPDIR=$1 FILESYSTEM=$2 FNAME=`echo ${FILESYSTEM} | tr "/" "_"` DATE=`date +%Y_%m_%d` LOGFILE=${STAMPDIR}/${FNAME}_${DATE} if [[ -e ${STAMPDIR}/${FNAME}_crawl1.dat ]] ; then T1=${STAMPDIR}/${FNAME}_crawl1.dat T2=${STAMPDIR}/${FNAME}_crawl2.dat PAT="-cnewer ${T1}" elif [[ -e ${STAMPDIR}/${FNAME}_crawl2.dat ]] ; then T2=${STAMPDIR}/${FNAME}_crawl1.dat T1=${STAMPDIR}/${FNAME}_crawl2.dat PAT="-cnewer ${T1}" else T2=${STAMPDIR}/${FNAME}_crawl1.dat PAT="-readable" # find /${FILESYSTEM} -name \* -print | xargs -r file fi touch ${T2} find /${FILESYSTEM} ${PAT} -type f -print | xargs -r dcmsplit -m > ${LOGFILE} # log the output of dcmsplit if [[ -n ${T1} ]] ;then rm ${T1} fi voxbo-1.8.5~svn1246/scripts/examples/000077500000000000000000000000001153177201300174315ustar00rootroot00000000000000voxbo-1.8.5~svn1246/scripts/examples/mkstatimg_example.vbs000066400000000000000000000004131153177201300236560ustar00rootroot00000000000000 script mkstatimg.scp priority 1 element data STEM=/jet/kimberg/demo/glms/subjects/aaa/aaa CONTRAST=[1] SCALE=2 OUTFILE=/home/kimberg/foo1.img end element data STEM=/jet/kimberg/demo/glms/subjects/bbb/bbb CONTRAST=[1] SCALE=2 OUTFILE=/home/kimberg/foo2.img end go voxbo-1.8.5~svn1246/scripts/makehelp.sh000077500000000000000000000057741153177201300177550ustar00rootroot00000000000000#!/bin/bash # for bin in `ls /usr/local/VoxBo/bin` ; do # echo $bin " > " $bin.out >> makehelp.sh ; # done analyzeinfo > analyzeinfo.out calcgs > calcgs.out calcps > calcps.out comptraces > comptraces.out cub2pngs > cub2pngs.out dcmsplit > dcmsplit.out dicominfo > dicominfo.out # display_dataset > display_dataset.out # extractmask > extractmask.out # ffinfo > ffinfo.out fillmask > fillmask.out gcheck > gcheck.out gds > gds.out gdw -h > gdw.out # getdata > getdata.out glm -h > glm.out glminfo > glminfo.out imginfo > imginfo.out # idlfree > idlfree.out # makeLittleEndian.sh > makeLittleEndian.sh.out makematk > makematk.out makematkg > makematkg.out makevlsm > makevlsm.out merge3d > merge3d.out # minprep.sh > minprep.sh.out # newprep.sh > newprep.sh.out niftiinfo > niftiinfo.out norm > norm.out # oldprep.sh > oldprep.sh.out permstep > permstep.out # plotfdr > plotfdr.out # print_dataset > print_dataset.out # putdata > putdata.out realign > realign.out resample > resample.out setorigin > setorigin.out sliceacq > sliceacq.out sortmvpm > sortmvpm.out spm8_coreg > spm8_coreg.out spm8_realign > spm8_realign.out spm8_reslice > spm8_reslice.out spm8_segment > spm8_segment.out spm8_warp > spm8_warp.out submit_sequence > submit_sequence.out sumrfx > sumrfx.out tes2cub > tes2cub.out tesjoin > tesjoin.out tesplit > tesplit.out txt2num > txt2num.out vb2cub > vb2cub.out vb2img > vb2img.out vb2imgs > vb2imgs.out vb2tes > vb2tes.out vb2vmp > vb2vmp.out vbbatch > vbbatch.out vbcfx > vbcfx.out vbcmp > vbcmp.out # vbconf > vbconf.out vbconv > vbconv.out vbdumpstats > vbdumpstats.out vbfdr > vbfdr.out vbfilter > vbfilter.out vbfit > vbfit.out vbhdr > vbhdr.out vbi > vbi.out vbim > vbim.out vbimagemunge > vbimagemunge.out vbinterpolate > vbinterpolate.out vblock > vblock.out vbmakefilter > vbmakefilter.out vbmakeglm > vbmakeglm.out # vbmakeprep > vbmakeprep.out vbmakeregress > vbmakeregress.out vbmakeresid > vbmakeresid.out vbmaskcompare > vbmaskcompare.out vbmaskinfo > vbmaskinfo.out vbmaskmunge > vbmaskmunge.out vbmerge4d > vbmerge4d.out vbmm2 > vbmm2.out vbmunge > vbmunge.out vborient > vborient.out vboverlap > vboverlap.out vbpermgen -h > vbpermgen.out vbperminfo > vbperminfo.out vbpermmat > vbpermmat.out vbpermvec > vbpermvec.out # vbprefs > vbprefs.out vbprep > vbprep.out # vbqa > vbqa.out vbregion > vbregion.out vbregress > vbregress.out vbrename > vbrename.out vbrender > vbrender.out # vbri vbscoregen > vbscoregen.out # vbscale # vbscoregen vbse > vbse.out vbshift > vbshift.out vbsim > vbsim.out vbsmooth > vbsmooth.out # vbsrvd > vbsrvd.out vbstatmap > vbstatmap.out vbtcalc -h > vbtcalc.out vbthresh > vbthresh.out vbtmap > vbtmap.out vbtool > vbtool.out vbvec2hdr > vbvec2hdr.out vbview2 -h > vbview2.out vbvolregress > vbvolregress.out vbxts > vbxts.out vecsplit > vecsplit.out vecview > vecview.out voxbo -h > voxbo.out voxq > voxq.out voxbo-1.8.5~svn1246/scripts/makerateset.sh000077500000000000000000000005461153177201300204640ustar00rootroot00000000000000#!/bin/bash LEFTFILE=ch2.nii.gz RIGHTFILE=anat.nii.gz printhelp() { echo "makerateset.sh template patient masks..." } if [[ $# -lt 3 ]] ; then printhelp; exit; fi for file in ${@} ; do echo image ${file%%.*} $file done echo echo left ${1%%.*} echo right ${2%%.*} echo for file in ${@:3} ; do echo mask ${file%%.*} done echo echo randomize voxbo-1.8.5~svn1246/scripts/makerfx_nonorm.vbp000066400000000000000000000014171153177201300213540ustar00rootroot00000000000000 # script makerfx_nonorm.vbp #make the rfx dir, in case it doesn't exist runonce shellcommand "/bin/mkdir -p $rfxdir" # make statmap from each glm vbstatmap $glmdir $rfxdir/$tag_map.cub "$contrast" $scale # copy mask to dir shellcommand "vbmaskmunge $glmdir/*.prm -o $rfxdir/$tag_mask.cub" # merge the masks into the rfx ubermask runonce shellcommand "vbmaskmunge $rfxdir/*_mask.cub -i -o $rfxdir/ubermask.cub" # merge the stat maps into a full.tes runonce shellcommand "vb2tes -m $rfxdir/full_$tesname.tes $rfxdir/*_map.cub" # create coverage map runonce shellcommand "vbmaskmunge -n $rfxdir/*_mask.cub -o $rfxdir/coverage_$tesname.cub" # apply ubermask to full tes runonce shellcommand "vbmaskmunge $rfxdir/ubermask.cub -a $rfxdir/full_$tesname.tes -o $rfxdir/$tesname.tes" voxbo-1.8.5~svn1246/scripts/makerfx_spm2norm.vbp000066400000000000000000000026731153177201300216260ustar00rootroot00000000000000 # script makerfx_spm2norm.vbp #make the rfx dir, in case it doesn't exist runonce shellcommand "/bin/mkdir -p $rfxdir" # make statmap from each glm vbstatmap $glmdir $rfxdir/$tag_map.cub "$contrast" $scale # copy mask to dir shellcommand "vbmaskmunge $glmdir/*.prm -o $rfxdir/$tag_mask.cub" # copy the origin to the map setorigin $adir/$func $rfxdir/$tag_map.cub # copy all headers to the map (to get origin and voxel sizes) shellcommand "vbhdr -c $adir/$func $rfxdir/$tag_map.cub" # copy all headers to the mask (to get origin and voxel sizes) shellcommand "vbhdr -c $adir/$func $rfxdir/$tag_mask.cub" # normalize each stat map spm2_norm_apply3d $rfxdir $adir/$paramfile $tag_map.cub $tag_nmap.cub $xf $yf $zf $bb_func # normalize each mask spm2_norm_apply3d $rfxdir $adir/$paramfile $tag_mask.cub $tag_nmask.cub $xf $yf $zf $bb_func # quantize each normalized mask shellcommand "vbmaskmunge -t 0.5 -q $rfxdir/$tag_nmask.cub -o $rfxdir/$tag_nmask.cub" # merge the normalized masks into the rfx ubermask runonce shellcommand "vbmaskmunge $rfxdir/*_nmask.cub -i -o $rfxdir/ubermask.cub" # merge the stat maps into a full.tes runonce shellcommand "vb2tes -m $rfxdir/full_$tesname.tes $rfxdir/*_nmap.cub" # create coverage map runonce shellcommand "vbmaskmunge -n $rfxdir/*_nmask.cub -o $rfxdir/coverage_$tesname.cub" # apply ubermask to full tes runonce shellcommand "vbmaskmunge $rfxdir/ubermask.cub -a $rfxdir/full_$tesname.tes -o $rfxdir/$tesname.tes" voxbo-1.8.5~svn1246/scripts/makevlsm.sh000077500000000000000000000060241153177201300177730ustar00rootroot00000000000000#!/bin/bash # some defaults DEST=permdir # destination for permutations PERMS=0 # number of permutations LESIONFILE=lesions.nii.gz # name of the 4D file containing lesion maps SCOREFILE=scores.ref # name of the 1D file containing your scores BATCH=0 TRUE=true.nii.gz printhelp() { echo " " echo "VoxBo makevlsm" echo "summary: script for running simple VLSM analyses" echo "usage:" echo " makevlsm " echo "the following flags are honored:" echo " -b submit to voxbo queue" echo " -d set destination dir for permutations (default: permdir)" echo " -p set number of permutations (default: 0)" echo " -o set filename for unpermuted map (default: true.nii.gz)" echo " -l set name of 4D lesion map file (default: lesions.nii.gz)" echo " -s set name of score file (default: scores.ref)" echo " -w use welch's instead of regular t-test" echo " -z generate z maps, not t maps" echo " -q set FDR criterion" echo " -n set minimum number of patients per voxel (default: 2)" echo " -m set inclusion mask (nonzero voxels are included)" echo " -f flip sign of t map" echo "notes:" echo " Look at the defaults above. If you're happy with them, then you can" echo " just run makevlsm with no arguments." echo " " echo " The -q option causes vbtmap to print an FDR threshold at the terminal." echo " Usually you wouldn't use it along with -b." echo " " } if [[ $# -lt 1 ]] ; then printhelp; exit; fi while getopts hbd:p:s:l:n:wzm:fgq:o: opt; do case "$opt" in h) printhelp; exit; ;; g) ;; b) BATCH=1 ;; d) DEST=$OPTARG ;; p) PERMS=$OPTARG ;; l) LESIONFILE=$OPTARG ;; o) TRUE=$OPTARG ;; s) SCOREFILE=$OPTARG ;; m) FLAGS+="-m $OPTARG " ;; w) FLAGS+="-w " ;; z) FLAGS+="-z " ;; n) FLAGS+="-n $OPTARG " ;; f) FLAGS+="-f " ;; q) FLAGS+="-q $OPTARG " ;; \\?) echo "argh!" ;; esac done NTES=`vbi -d $LESIONFILE | cut --delimiter=' ' --fields=3 | cut --delimiter='x' --fields=4` NVEC=`vbi -d $SCOREFILE | cut --delimiter=' ' --fields=3` if [[ $NTES -ne $NVEC ]] ; then echo "[E] makevlsm: the number of volumes does not match the number of scores" exit 22 fi if [[ $PERMS -gt 0 ]] ; then vbpermmat perms.mat $PERMS $LESIONFILE data mkdir -p $DEST fi if [[ BATCH -gt 0 ]] ; then vbbatch -f vlsmbatch vbbatch -m 500 -a vlsmbatch -c "vbtmap $LESIONFILE $SCOREFILE ${TRUE} $FLAGS" x vbbatch -m 500 -a vlsmbatch -c "vbtmap $LESIONFILE $SCOREFILE $DEST/cube_IND.nii.gz $FLAGS -op perms.mat IND" -d $PERMS vbbatch -m 500 -s vlsmbatch else echo "[I] makevlsm: Building unpermuted volume as ${TRUE}" vbtmap $LESIONFILE $SCOREFILE ${TRUE} $FLAGS for (( IND=0 ; IND < $PERMS ; IND++ )) do indstr=`printf %05d $IND` echo "[I] makevlsm: Building permuted volume $IND as $DEST/cube_${indstr}.nii.gz" vbtmap $LESIONFILE $SCOREFILE $DEST/cube_${indstr}.nii.gz $FLAGS -op perms.mat $IND done fi voxbo-1.8.5~svn1246/scripts/minprep.sh000077500000000000000000000024501153177201300176250ustar00rootroot00000000000000#!/bin/bash # minprep.sh - This script assumes you pass it one or more directory # names that themselves contain Anatomy directories. Each such # directory must contain an Anatomical.cub file and a Functional.cub # file, containing the high-res anatomical data in the former and a # sample of your functional data in the latter. Each file must # contain an absolute corner position and voxel sizes. TDIR=/usr/local/VoxBo/elements/templates PWD=`pwd` BPWD=`basename $PWD` if (( $# > 0)) ; then ADIRS=$* elif [ "$BPWD" == "Anatomy" ] ; then ADIRS="." elif [ -d "Anatomy" ] ; then ADIRS="Anatomy" else echo 'argh' exit 255 fi for DIR in $ADIRS ; do if [ -d "$DIR/Anatomy" ] ; then ADIR=$DIR/Anatomy else ADIR=$DIR ; fi # Copy the estimated origin from Anatomical.cub to Functional.cub and back. This ensures # that the origin on Norm will be on an EPI voxel boundary setorigin -m $ADIR/Anatomical.cub $ADIR/Functional.cub if (($? > 0)) ; then exit 101 ; fi setorigin -m $ADIR/Functional.cub $ADIR/Anatomical.cub if (($? > 0)) ; then exit 101 ; fi # create a Display.cub that's in the same space as the functional images resample $ADIR/Anatomical.cub $ADIR/Display.cub -ra $ADIR/Functional.cub if (($? > 0)) ; then exit 107 ; fi echo "minprep.sh: Done with directory '$ADIR'" done voxbo-1.8.5~svn1246/scripts/newprep.sh000077500000000000000000000042101153177201300176270ustar00rootroot00000000000000#!/bin/bash # newprep.sh - This script assumes you pass it one or more directory # names that themselves contain Anatomy directories. Each such # directory must contain an Anatomical.cub file and a Functional.cub # file, containing the high-res anatomical data in the former and a # sample of your functional data in the latter. Each file must # contain an absolute corner position and voxel sizes. TDIR=/usr/local/VoxBo/elements/templates PWD=`pwd` BPWD=`basename $PWD` if (( $# > 0)) ; then ADIRS=$* elif [ "$BPWD" == "Anatomy" ] ; then ADIRS="." elif [ -d "Anatomy" ] ; then ADIRS="Anatomy" else echo 'argh' exit 255 fi for DIR in $ADIRS ; do if [ -d "$DIR/Anatomy" ] ; then ADIR=$DIR/Anatomy else ADIR=$DIR ; fi # Copy the estimated origin from Anatomical.cub to Functional.cub and back. This ensures # that the origin on Norm will be on an EPI voxel boundary setorigin -m $ADIR/Anatomical.cub $ADIR/Functional.cub if (($? > 0)) ; then exit 101 ; fi setorigin -m $ADIR/Functional.cub $ADIR/Anatomical.cub if (($? > 0)) ; then exit 101 ; fi # Now calculate norm params and apply as a test to Anatomical.cub norm -calc -r $TDIR/single_subj_T1.cub -p $ADIR/NormParams.ref $ADIR/Anatomical.cub if (($? > 0)) ; then exit 101 ; fi norm -apply -p $ADIR/NormParams.ref -o $ADIR/nAnatomical.cub $ADIR/Anatomical.cub if (($? > 0)) ; then exit 101 ; fi # Finally, the more mundane stuff... # create a Display.cub that's in the same space as the functional images resample $ADIR/Anatomical.cub $ADIR/Display.cub -ra $ADIR/Functional.cub if (($? > 0)) ; then exit 107 ; fi # normalize the display locs, just for kicks norm -apply -p $ADIR/NormParams.ref -z $ADIR/Functional.cub -o $ADIR/nDisplay.cub $ADIR/Anatomical.cub if (($? > 0)) ; then exit 109 ; fi # create a coverage version called cDisplay.cub norm -apply -p $ADIR/NormParams.ref -o $ADIR/cDisplay.cub $ADIR/Display.cub if (($? > 0)) ; then exit 109 ; fi # normalize the EPIs, just for kicks norm -apply -p $ADIR/NormParams.ref -o $ADIR/nFunctional.cub $ADIR/Functional.cub if (($? > 0)) ; then exit 109 ; fi echo "newprep.sh: Done with directory '$ADIR'" done voxbo-1.8.5~svn1246/scripts/oldprep.sh000077500000000000000000000043131153177201300176200ustar00rootroot00000000000000#!/bin/bash # preplocs.sh - This script assumes you pass it one or more directory # names that themselves contain Anatomy directories. Each such # directory must contain an Norm.cub file and a EPI.cub # file, containing the high-res anatomical data in the former and a # sample of your functional data in the latter. Each file must # contain an absolute corner position and voxel sizes. TDIR=/usr/local/VoxBo/elements/templates PWD=`pwd` BPWD=`basename $PWD` if (( $# > 0)) ; then ADIRS=$* elif [ "$BPWD" == "Anatomy" ] ; then ADIRS="." elif [ -d "Anatomy" ] ; then ADIRS="Anatomy" else echo 'argh' exit 255 fi for DIR in $ADIRS ; do if [ -d "$DIR/Anatomy" ] ; then ADIR=$DIR/Anatomy else ADIR=$DIR ; fi ## cropping now done in copylocs.sh # crop the sample EPI in preparation for origin setting # resample $ADIR/EPI.cub $ADIR/EPI.cub -xx 12 1 40 # if (($? > 0)) ; then exit 108 ; fi # Copy the estimated origin from Norm.cub to EPI.cub and back. This ensures # that the origin on Norm will be on an EPI voxel boundary setorigin -m $ADIR/Norm.cub $ADIR/EPI.cub if (($? > 0)) ; then exit 101 ; fi setorigin -m $ADIR/EPI.cub $ADIR/Norm.cub if (($? > 0)) ; then exit 101 ; fi # Now calculate norm params and apply as a test to Norm.cub norm -calc -r $TDIR/single_subj_T1.cub -p $ADIR/NormParams.ref $ADIR/Norm.cub if (($? > 0)) ; then exit 101 ; fi norm -apply -p $ADIR/NormParams.ref -o $ADIR/nNorm.cub $ADIR/Norm.cub if (($? > 0)) ; then exit 101 ; fi # Finally, the more mundane stuff... # create a Display.cub that's in the same space as the functional images resample $ADIR/Norm.cub $ADIR/Display.cub -ra $ADIR/EPI.cub if (($? > 0)) ; then exit 107 ; fi # normalize the display locs, just for kicks norm -apply -p $ADIR/NormParams.ref -z $ADIR/EPI.cub -o $ADIR/nDisplay.cub $ADIR/Norm.cub if (($? > 0)) ; then exit 109 ; fi # create a coverage version called cDisplay.cub norm -apply -p $ADIR/NormParams.ref -o $ADIR/cDisplay.cub $ADIR/Display.cub if (($? > 0)) ; then exit 109 ; fi # normalize the EPIs, just for kicks norm -apply -p $ADIR/NormParams.ref -o $ADIR/nEPI.cub $ADIR/EPI.cub if (($? > 0)) ; then exit 109 ; fi echo "preplocs.sh: Done with directory '$ADIR'" done voxbo-1.8.5~svn1246/scripts/paasify.sh000077500000000000000000000046331153177201300176140ustar00rootroot00000000000000#!/bin/bash # script to do perfusion processing # defaults #MATLABPATH=/usr/local/spm8 #SPM8_MATLAB_CMD="matlab2009b -nodesktop" MPRAGE=mprage.nii PERF=perf.nii WMASK=wmask.nii FSLOUTPUTTYPE=NIFTI # for spm-compatibility # FIXME test return codes at every step # reset orientation info to sane defaults vbim $MPRAGE -setspace -write $MPRAGE vbim $PERF -setspace -write4d $PERF vbim $WMASK -setspace -write $WMASK # remove existing files from previous runs that could confuse things rm -f *perf1* rperf* mperf* *.mat meanperf* [wm]mprage.nii *perfmap* *~ *.ps rp_*.txt # coreg perf to mprage using FLIRT #flirt -cost normmi -in $PERF -ref $MPRAGE -out cperf.nii -omat perf2mprage.mat # coreg perf to mprage using resample #resample perf.tes cperf.tes -ref mprage.cub # coreg perf to mprage using spm vbim perf.nii -include 0 -write perf1.nii spm8_coreg -r $MPRAGE -i perf1.nii vbim perf.nii -setspace perf1.nii -write4d perf.nii # for convenience, extract perf1 #vbim cperf.nii -include 0 -setspace -write perf1.nii #vbim $PERF -setspace -write4d $PERF # segment first volume of PERF for the sole purpose of bias correction # (producing mperf.nii), remove extraneous normalized version # (wperf.nii). we do this first so that we aren't going to mess with # PERF's coregistration. spm8_segment -i perf.nii,1 -o tmp.nii -p tmp.mat #rm -f wperf.nii tmp.mat tmp.nii # get perf denominator #denom=`calcperf -t 4000 -m $WMASK perf1.nii` denom=`calcperf -t 4000 -m $WMASK mperf.nii` echo "DENOM: " $denom #rm mperf.nii # reset NIfTI headers on input files to sane defaults vbim $MPRAGE -setspace -write $MPRAGE #vbim $PERF -setspace -write4d $PERF vbim $WMASK -setspace -write $WMASK # extract the first volume as a reference for realignment # don't need to do this, we can just use "foo.nii,1" within spm # vbim $PERF -include 0 -write perf1.nii # coregister first perf volume to mprage #spm8_coreg -r $MPRAGE -i perf1.nii # realign and reslice the single perf volume spm8_realign -i perf.nii -r perf1.nii #flirt -in cperf.nii -ref perf1.nii -out rperf.nii # get the perf data, reduce it to a perf map vbim rperf.nii -convert double -oddeven -average -div $denom -write perfmap.nii # the following may be necessary, but shouldn't be, since we resliced vbim perfmap.nii -setspace perf1.nii -write perfmap.nii # normalize (segment) mprage spm8_segment -i $MPRAGE -p sn_seg.mat # normalize perf map spm8_warp -i perfmap.nii -p sn_seg.mat -b t1 voxbo-1.8.5~svn1246/scripts/plotfdr.sh000066400000000000000000000024751153177201300176310ustar00rootroot00000000000000#!/usr/bin/python # fdrscript.sh # The FDR-controlling threshold (see Genovese et al., 2002) # corresponds to the largest p value that is less than i/V * q, where # q is the desired false discovery rate and i is the index of the p # value in the sorted list of all p values from 1 to V. # This script takes a vector of (we hope) p values, sanity checks it, # sorts it, and then graphs it against the FDR line using matplotlib. from pylab import * y=[] f=open('pfile.ref','r') unconv=0 tmp=0.0 for line in f: try: tmp=float(line) except ValueError: print '[W] plotfdr: unconverted line: '+line.strip() unconv=unconv+1 if unconv > 8: print '[E] plotfdr: too many non-numeric values, exiting' exit(101) continue if (tmp == nan or tmp==inf or tmp==-inf): print '[E] plotfdr: encountered non-finite value, exiting' exit(101) if tmp>1.0 or tmp<0.0: print '[E] plotfdr: found invalid p value '+line.strip()+', exiting' exit(100) y.append(float(line)) f.close() print 'read',len(y),'values' y.sort() x=arange(1,len(y)+1,1) plot(x,y,linewidth=1.0) y=0.01*x/len(x) plot(x,y,linewidth=0.5) y=0.05*x/len(x) plot(x,y,linewidth=0.5) xlabel('ordinal position of p value') ylabel('actual p value') title('haha') grid(True) show() voxbo-1.8.5~svn1246/scripts/rfx_example.vbp000066400000000000000000000025031153177201300206360ustar00rootroot00000000000000 # for spm2norm script makerfx_spm2norm.vbp # for no normalization, use the following script line instead and # don't worry about voxel sizes, bounding box, or parameters # script makerfx_nonorm.vbp # data SEQUENCENAME "spm2 rfx test" DIR /data/my/rfx/directory PRIORITY 2 LOGGING 1 # voxel sizes for normalized data globals xf=3 globals yf=3 globals zf=3 globals rfxdir=/data/my/rfx/directory globals paramfile=spm2_norm_params.mat globals func=Functional.cub globals "bb_func=[-78,-111,-50;78,75,85]" # the below variables specify the contrast. if needed, they can be # specified on the FILE line (e.g., if need to vary the contrast by # subject) # contrast vector - the quotes are necessary if the contrast has multiple elements globals "contrast=1" # any scale supported by vbstatmap is okay globals scale=rb # root name for your tes file globals tesname=mytes # for the FILE lines, specify the glm directory and anatomy directory # for each subject. each tag must be unique, and the alphabetic order # determines the order in your rfx tex file. i know this is clumsy, # it will be fixed at some point. FILE tag=00 glmdir=/data/mystudy/myglm1 adir=/data/mystudy/data/sub1/Anatomy FILE tag=01 glmdir=/data/mystudy/myglm1 adir=/data/mystudy/data/sub1/Anatomy FILE tag=02 glmdir=/data/mystudy/myglm1 adir=/data/mystudy/data/sub1/Anatomy voxbo-1.8.5~svn1246/scripts/runperms.sh000066400000000000000000000006411153177201300200230ustar00rootroot00000000000000#!/bin/bash # This bash script is meant to demonstrate how we can run a simple # permutation test. You need to edit the following variables and then # edit the vbvolregress line below. DEST=perm_dir # destination for permutations COUNT=10 # number of permutations for (( iter=1 ; iter<=$COUNT ; iter++ )) ; do echo vbregress -iv -iv -iv -dv -c \"foo t vec 1 0 0\" -o perm_dir/cube_$iter.nii.gz done voxbo-1.8.5~svn1246/scripts/spm2_normcalc.vbp000066400000000000000000000015351153177201300210670ustar00rootroot00000000000000 # script spm2_normcalc.vbp # expects globals: # xa,ya,za - anatomical voxel sizes in mm # xf,yf,zf - functional voxel sizes in mm # adir - anatomy directory # refvol - reference volume # paramfile - just the name, it will be in the anat directory # anat - anatomy file name (e.g., Anatomical.cub) # func - functional sample name (e.g., Functional.cub) # bb_anat - bounding box for anatomical # bb_func - bounding box for functional # bb_disp - bounding box for display image # calc params runonce spm2_norm_calc $adir $paramfile $anat $refvol $xa $ya $za $bb_anat # make ndisplay.cub runonce spm2_norm_apply3d $adir $adir/$paramfile $anat nDisplay.cub $xa $ya $zf $bb_disp # apply to scout image runonce spm2_norm_apply3d $adir $adir/$paramfile $func n$func $xf $yf $zf $bb_func # notify runonce notify $email "Your normalization job is completely done." voxbo-1.8.5~svn1246/scripts/spm2normcalc_example.vbp000066400000000000000000000010031153177201300224310ustar00rootroot00000000000000 script spm2_normcalc.vbp SEQUENCENAME "spm2 norm test" DIR /tmp PRIORITY 2 LOGGING 1 EMAIL nobody@nowhere.com globals xa=1 globals ya=1 globals za=1 globals xf=3 globals yf=3 globals zf=3 globals adir=/data/subject/Anatomy globals refvol=/usr/local/spm2/templates/T1.mnc globals paramfile=spm2_norm_params.mat globals anat=Anatomical.cub globals func=Functional.cub globals "bb_anat=[-79,-112,-51;79,76,86]" globals "bb_func=[-78,-111,-50;78,75,85]" globals "bb_disp=[-79,-112,-50;79,76,85]" globals email=$EMAIL voxbo-1.8.5~svn1246/scripts/spm8_coreg.sh000066400000000000000000000044301153177201300202160ustar00rootroot00000000000000#!/bin/bash # run SPM8 coregistration # see spm8/config/spm_run_coreg_estwrite.m if [[ "$MATLABPATH" =~ spm8 && -z "$SPM8PATH" ]] ; then SPM8PATH="$MATLABPATH"; fi if [[ -z "$SPM8PATH" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8PATH" && -d /usr/local/spm8 ]] ; then SPM8PATH=/usr/local/spm8; fi if [[ -z "$SPM8PATH" && -d /usr/lib/spm8 ]] ; then SPM8PATH=/usr/share/matlab/site/m/spm8; fi if [[ -z "$SPM8CMD" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8CMD" ]] ; then SPM8CMD='matlab -nodesktop -nosplash -nojvm'; fi # defaults MATLABPATH=$SPM8PATH SPM8_MATLAB_CMD=$SPM8CMD # formerly "/usr/local/bin/matlab2009b -nodesktop -nosplash -nojvm" INFILE='3dfile.nii' REF='ref.nii' printhelp() { echo " " echo "VoxBo spm8_segment script" echo "summary: script for running SPM8 coregistration" echo "usage:" echo " spm8_segment " echo "the following flags are honored:" echo " -r filename of reference volume" echo " -i filename of 3D volume to coregister" echo " -h print this help" echo " " } if [[ $# -lt 2 ]] ; then printhelp; exit; fi while getopts hr:i: opt; do case "$opt" in h) printhelp; exit; ;; i) INFILE=$OPTARG ;; r) REF=$OPTARG ;; \\?) echo "argh!" ;; esac done DIR=$(dirname $INFILE) FNAME=$(basename $INFILE) echo "+---------------------------------+" echo "| SPM8 coregistration bash script |" echo "+---------------------------------+" echo " infile: " $INFILE echo " ref: " $REF $SPM8_MATLAB_CMD << EOF spm_defaults; global defaults; cflags1.cost_fun = 'nmi'; cflags1.sep = [4 2]; cflags1.tol = [0.02 0.02 0.02 0.001 0.001 0.001 0.01 0.01 0.01 0.001 0.001 0.001]; cflags1.fwhm = [7 7]; cflags2.prefix = 'r'; cflags2.interp = 1; cflags2.wrap = [0 0 0]; cflags2.mask = 0; cflags2.mean = 0; cflags2.which=1; % spm_coreg returns a rigid body rotation x=spm_coreg('$REF','$INFILE',cflags1) newspace=inv(spm_matrix(x))*spm_get_space('$INFILE') spm_get_space('$INFILE',newspace) P=strvcat('$REF','$INFILE') spm_reslice(P,cflags2) EOF echo if [[ ! -f $DIR/r$FNAME ]] ; then exit 1 ; fi if [[ -n $OUTFILE ]] ; then mv $DIR/w$FNAME $DIR/$OUTFILE mv $DIR/w${FNAME%.*}.mat ${OUTFILE%.*}.mat fi exit 0 voxbo-1.8.5~svn1246/scripts/spm8_realign.sh000066400000000000000000000044411153177201300205420ustar00rootroot00000000000000#!/bin/bash # realign one or more time series volumes to a specific reference # image using SPM8 if [[ "$MATLABPATH" =~ spm8 && -z "$SPM8PATH" ]] ; then SPM8PATH="$MATLABPATH"; fi if [[ -z "$SPM8PATH" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8PATH" && -d /usr/local/spm8 ]] ; then SPM8PATH=/usr/local/spm8; fi if [[ -z "$SPM8PATH" && -d /usr/lib/spm8 ]] ; then SPM8PATH=/usr/share/matlab/site/m/spm8; fi if [[ -z "$SPM8CMD" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8CMD" ]] ; then SPM8CMD='matlab -nodesktop -nosplash -nojvm'; fi # some defaults MATLABPATH=$SPM8PATH SPM8_MATLAB_CMD=$SPM8CMD # formerly "/usr/local/bin/matlab2009b -nodesktop -nosplash -nojvm" REF='ref.nii' INFILE='data.nii' OUTFILE= printhelp() { echo " " echo "VoxBo spm8_realign script" echo "summary: script for realigning using SPM8" echo "usage:" echo " spm8_realign " echo "the following flags are honored:" echo " -i file to realign" echo " -r 3D ref volume" echo " -o set output file name (default: r is prepended)" echo " -h print this help" echo " " } if [[ $# -lt 3 ]] ; then printhelp; exit; fi while getopts ho:i:r: opt; do case "$opt" in h) printhelp; exit; ;; i) INFILE=$OPTARG ;; r) REF=$OPTARG ;; o) OUTFILE=$OPTARG ;; \\?) echo "argh!" ;; esac done DIR=`dirname $INFILE` FNAME=`basename $INFILE` echo "+------------------------------+" echo "| SPM8 realignment bash script |" echo "+------------------------------+" echo " ref: " $REF if [[ -n $OUTFILE ]] ; then echo "outfile: " $OUTFILE else echo "outfile: " $DIR/r$FNAME fi $SPM8_MATLAB_CMD << EOF spm_defaults; global defaults; rflags1.quality = 1; rflags1.weight = {''}; rflags1.interp = 2; rflags1.wrap = [0 0 0]; rflags1.sep = 4; rflags1.fwhm = 5; rflags1.rtm = 0; rflags2.prefix = 'r'; rflags2.mask = 1; rflags2.interp = 4; rflags2.wrap = [0 0 0]; rflags2.which = 2; refplus=strvcat('$REF','$INFILE'); spm_realign(refplus,rflags1) spm_reslice('$INFILE',rflags2) exit EOF echo if [[ ! -f $DIR/r$FNAME ]] ; then exit 1 ; fi if [[ -n $OUTFILE ]] ; then # DIR2=`dirname $OUTFILE` mv $DIR/r$FNAME $OUTFILE mv $DIR/r${FNAME%.*}.mat ${OUTFILE%.*}.mat fi exit 0 voxbo-1.8.5~svn1246/scripts/spm8_reslice.sh000077500000000000000000000040061153177201300205470ustar00rootroot00000000000000#!/bin/bash # run SPM8 reslice # see spm8/??? if [[ "$MATLABPATH" =~ spm8 && -z "$SPM8PATH" ]] ; then SPM8PATH="$MATLABPATH"; fi if [[ -z "$SPM8PATH" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8PATH" && -d /usr/local/spm8 ]] ; then SPM8PATH=/usr/local/spm8; fi if [[ -z "$SPM8PATH" && -d /usr/lib/spm8 ]] ; then SPM8PATH=/usr/share/matlab/site/m/spm8; fi if [[ -z "$SPM8CMD" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8CMD" ]] ; then SPM8CMD='matlab -nodesktop -nosplash -nojvm'; fi # defaults MATLABPATH=$SPM8PATH SPM8_MATLAB_CMD=$SPM8CMD # formerly "/usr/local/bin/matlab2009b -nodesktop -nosplash -nojvm" INFILE='3dfile.nii' REF='ref.nii' OUTFILE= printhelp() { echo " " echo "VoxBo spm8_reslice script" echo "summary: script for reslicing an image in SPM8" echo "usage:" echo " spm8_reslice " echo "the following flags are honored:" echo " -r filename of reference volume" echo " -i filename of volume to reslice" echo " -o filename for output" echo " -h print this help" echo " " } if [[ $# -lt 2 ]] ; then printhelp; exit; fi while getopts hr:i:o: opt; do case "$opt" in h) printhelp; exit; ;; i) INFILE=$OPTARG ;; r) REF=$OPTARG ;; o) OUTFILE=$OPTARG ;; \\?) echo "argh!" ;; esac done DIR=`dirname $INFILE` FNAME=`basename $INFILE` echo "+---------------------------------+" echo "| SPM8 coregistration bash script |" echo "+---------------------------------+" echo " infile: " $INFILE echo " ref: " $REF echo "outfile: " $OUTFILE $SPM8_MATLAB_CMD << EOF spm_defaults; global defaults; cflags2.prefix = 'r'; cflags2.interp = 1; cflags2.wrap = [0 0 0]; cflags2.mask = 0; cflags2.mean = 0; cflags2.which=1; P=strvcat('$REF','$INFILE') spm_reslice(P,cflags2) EOF echo if [[ ! -f $DIR/r$FNAME ]] ; then exit 1 ; fi if [[ -n $OUTFILE ]] ; then mv $DIR/w$FNAME $DIR/$OUTFILE mv $DIR/w${FNAME%.*}.mat ${OUTFILE%.*}.mat fi exit 0 voxbo-1.8.5~svn1246/scripts/spm8_segment.sh000066400000000000000000000067531153177201300205730ustar00rootroot00000000000000#!/bin/bash # run SPM8 unified segmentation # TODO: # accept bounding box argument # see spm_preproc.m # see spm_preproc_write.m if [[ "$MATLABPATH" =~ spm8 && -z "$SPM8PATH" ]] ; then SPM8PATH="$MATLABPATH"; fi if [[ -z "$SPM8PATH" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8PATH" && -d /usr/local/spm8 ]] ; then SPM8PATH=/usr/local/spm8; fi if [[ -z "$SPM8PATH" && -d /usr/lib/spm8 ]] ; then SPM8PATH=/usr/share/matlab/site/m/spm8; fi if [[ -z "$SPM8CMD" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8CMD" ]] ; then SPM8CMD='matlab -nodesktop -nosplash -nojvm'; fi # defaults MATLABPATH=$SPM8PATH SPM8_MATLAB_CMD=$SPM8CMD # formerly "/usr/local/bin/matlab2009b -nodesktop -nosplash -nojvm" PARAMFILE='seg.mat' INFILE='mprage.nii' OUTFILE= TDIR="/usr/local/spm8/tpm" printhelp() { echo " " echo "VoxBo spm8_segment script" echo "summary: script for running SPM8 unified segmentation" echo "usage:" echo " spm8_segment " echo "the following flags are honored:" echo " -p parameter file to write (default: seg.mat)" echo " -o normalized file to write (default: wmprage.nii)" echo " -t dir containing template (default: /usr/local/spm8/tpm)" echo " -i 3D volume to segment" echo " -h print this help" echo "notes:" echo " This script uses SPM8's unified segmentation to calculate a warp" echo " from your volume to the template included with SPM8." echo " " echo " Note that the template is segmented, and composed of three files:" echo " gray.nii, white.nii, and csf.nii" echo " " echo " SPM8 handles uncompressed NIfTI files." echo " " } if [[ $# -lt 2 ]] ; then printhelp; exit; fi while getopts ho:p:i: opt; do case "$opt" in h) printhelp; exit; ;; i) INFILE=$OPTARG ;; o) OUTFILE=$OPTARG ;; t) TDIR=$OPTARG ;; p) PARAMFILE=$OPTARG ;; \\?) echo "argh!" ;; esac done DIR=`dirname $INFILE` FNAME=`basename $INFILE` echo "+---------------------------------------+" echo "| SPM8 unified segmentation bash script |" echo "+---------------------------------------+" echo " infile: " $INFILE if [[ -n $OUTFILE ]] ; then echo "outfile: " $OUTFILE else echo "outfile: " $DIR/w$FNAME fi echo " params: " $PARAMFILE $SPM8_MATLAB_CMD << EOF spm_defaults; global defaults; opts0.tpm=char('$TDIR/grey.nii','$TDIR/white.nii','$TDIR/csf.nii'); opts0.ngaus = [2 2 2 4]; opts0.warpreg = 1; opts0.warpco = 25; opts0.biasreg = 0.0001; opts0.biasfwhm = 60; opts0.regtype = 'mni'; opts0.fudge = 5; opts0.samp = 3; opts0.msk = ''; opts1.biascor=1; opts1.cleanup=0; % three parts of GM/WM/CSF arg are for: native, modulated, unmodulated opts1.GM=[0 0 1]; opts1.WM=[0 0 1]; opts1.CSF=[0 0 1]; P=spm_vol('$INFILE') res=spm_preproc(P,opts0) [p,ip]=spm_prep2sn(res) % save the forward params fn = fieldnames(p); for i=1:length(fn), eval([fn{i} '= p.' fn{i} ';']); end; save('$PARAMFILE',fn{:}); % in case i want the inverse params later fn = fieldnames(ip); for i=1:length(fn), eval([fn{i} '= ip.' fn{i} ';']); end; save('seg_inv_sn.mat',fn{:}); % write the segmented and bias corrected files spm_preproc_write(p,opts1) % now warp it opts3.bb=[Inf]; % means to use template bb opts3.vox=[1 1 1]; opts3.wrap=[0 0 0]; spm_write_sn('$INFILE',p,opts3) EOF echo if [[ ! -f $DIR/w$FNAME ]] ; then exit 1 ; fi if [[ -n $OUTFILE ]] ; then mv $DIR/w$FNAME $OUTFILE mv $DIR/w${FNAME%.*}.mat ${OUTFILE%.*}.mat fi exit 0 voxbo-1.8.5~svn1246/scripts/spm8_warp.sh000077500000000000000000000067471153177201300201100ustar00rootroot00000000000000#!/bin/bash # run SPM8 unified segmentation # TODO: # accept bounding box argument # see spm_preproc.m # see spm_preproc_write.m if [[ "$MATLABPATH" =~ spm8 && -z "$SPM8PATH" ]] ; then SPM8PATH="$MATLABPATH"; fi if [[ -z "$SPM8PATH" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8PATH" && -d /usr/local/spm8 ]] ; then SPM8PATH=/usr/local/spm8; fi if [[ -z "$SPM8PATH" && -d /usr/lib/spm8 ]] ; then SPM8PATH=/usr/share/matlab/site/m/spm8; fi if [[ -z "$SPM8CMD" && -r /etc/voxbo/setpaths.sh ]] ; then . /etc/voxbo/setpaths.sh; fi if [[ -z "$SPM8CMD" ]] ; then SPM8CMD='matlab -nodesktop -nosplash -nojvm'; fi # defaults MATLABPATH=$SPM8PATH SPM8_MATLAB_CMD=$SPM8CMD # formerly "/usr/local/bin/matlab2009b -nodesktop -nosplash -nojvm" PARAMFILE='seg.mat' INFILE='mprage.nii' OUTFILE='' BBNAME="t2" BB="[-78,-111,-50;80,77,86]" VOX="[1 1 1]" printhelp() { echo " " echo "VoxBo spm8_warp script" echo "summary: script for applying SPM8 norm/segment params to an image" echo "usage:" echo " spm8_warp " echo "the following flags are honored:" echo " -p name for parameter file to be used" echo " -i filename of volume to warp" echo " -o filename of output volume" echo " -b see below" echo " -h print this help" echo "notes:" echo " This script uses SPM8's unified segmentation to calculate a warp" echo " from your volume to the template included with SPM8." echo " " echo " Note that the template is segmented, and composed of three files:" echo " gray.nii, white.nii, and csf.nii" echo " " echo " the -b argument specifies the voxel sizes and bounding box:" echo " t1 -- template space in 1mm" echo " t2 -- template space in 2mm" echo " t3 -- template space in 3mm" echo " s1 -- SPM bounding box in 1mm" echo " s3 -- SPM bounding box in 3mm" echo " " echo " SPM8 handles uncompressed NIfTI files." echo " " } if [[ $# -lt 2 ]] ; then printhelp; exit; fi while getopts hp:i:o:b: opt; do case "$opt" in h) printhelp; exit; ;; i) INFILE=$OPTARG; ;; o) OUTFILE=$OPTARG ;; b) BBNAME=$OPTARG ;; p) PARAMFILE=$OPTARG ;; \\?) echo "argh!" ;; esac done DIR=`dirname $INFILE` FNAME=`basename $INFILE` if [[ $BBNAME == "s1" ]] ; then # voxbo 1mm 159x189x136 echo s1 BB="[-78,-111,-50;80,77,86]" VOX="[1 1 1]" elif [[ $BBNAME == "s3" ]] ; then # voxbo 3mm 53x63x46 echo s3 BB="[-78,-111,-51;78,75,84]" VOX="[3 3 3]" elif [[ $BBNAME == "t1" ]] ; then # SPM2 template 1mm (cf ch2) echo t1 BB="[-90,-126,-72;90,90,108]" VOX="[1 1 1]" elif [[ $BBNAME == "t2" ]] ; then # SPM2 template 2mm (cf ch2) echo t2 BB="[-90,-126,-72;90,90,108]" VOX="[2 2 2]" elif [[ $BBNAME == "t3" ]] ; then # SPM2 template 3mm (cf ch2) echo t3 BB="[-90,-126,-72;90,90,108]" VOX="[3 3 3]" else echo "[E] invalid BB name" exit 22 fi echo "+------------------------------+" echo "| SPM8 warp (warp) bash script |" echo "+------------------------------+" echo " infile: " $INFILE if [[ -n $OUTFILE ]] ; then echo "outfile: " $OUTFILE else echo "outfile: " $DIR/w$FNAME fi echo " params: " $PARAMFILE $SPM8_MATLAB_CMD << EOF spm_defaults; global defaults; p=load('$PARAMFILE'); opts3.bb=$BB; opts3.vox=$VOX; opts3.wrap=[0 0 0]; spm_write_sn('$INFILE',p,opts3) EOF echo if [[ ! -f $DIR/w$FNAME ]] ; then exit 1 ; fi if [[ -n $OUTFILE ]] ; then mv $DIR/w$FNAME $OUTFILE mv $DIR/w${FNAME%.*}.mat ${OUTFILE%.*}.mat fi exit 0 voxbo-1.8.5~svn1246/scripts/vb_anonymize.sh000066400000000000000000000020421153177201300206450ustar00rootroot00000000000000 # maybe use susan??? # register directly to ch2 using ANTS ANTS 3 -m PR["ch2.nii.gz","mprage.nii.gz",1,3] -i 2x1x1 -o STRIP -t SyN[0.5] -r Gauss[3,0] # warp to ch2 just to see if it worked WarpImageMultiTransform 3 mprage.nii.gz wmprage.nii.gz -R ch2.nii.gz STRIPWarp STRIPAffine.txt #WarpImageMultiTransform 3 ch2.nii.gz wch2.nii.gz -R mprage.nii.gz STRIPWarp STRIPAffine.txt # ch2mask created by using spm8segment on ch2 (!), then using vbim thusly: # vbim c[123]* -convert float -sum -quantize 1 -info -smoothvox 3 3 3 -info\ # -thresh 0.2 -quantize 1 -convert byte -write sch2mask.nii # map ch2's gray/white/csf map back onto our image WarpImageMultiTransform 3 sch2mask.nii smask.nii.gz -R mprage.nii.gz -i STRIPAffine.txt STRIPInverseWarp # blur and quantize again, and mask original image using vbim vbim smask.nii.gz -thresh 0.2 -quantize 1 -smoothvox 3 3 3 -thresh 0.2 -quantize 1 -convert byte -write smask2.nii.gz # inspect! # apply smask2 to mprage vbim mprage.nii.gz -mask smask2.nii.gz -write mmmprage.nii.gz # inspect again! voxbo-1.8.5~svn1246/scripts/vbinstall.sh000077500000000000000000000053641153177201300201600ustar00rootroot00000000000000#!/bin/bash # VoxBo install script # some defaults DEST=/usr/local/VoxBo VOXBOUSER=voxbo printhelp() { echo " " echo "VoxBo install" echo "summary: minimal VoxBo install tasks" echo "usage:" echo " makevlsm " echo "the following flags are honored:" echo " -d destination directory (default: /usr/local/VoxBo)" echo " -u VoxBo user (default: voxbo)" echo "notes:" echo " This script sets proper permissions for a VoxBo installation and" echo " creates some minimal files if missing. It doesn't overwrite existing" echo " configuration files, so you can use it to fix an existing installation" echo " or to initialize a new one." echo " " } while getopts hd:u: opt; do case "$opt" in h) printhelp; exit; ;; # b) BATCH=1 ;; d) DEST=$OPTARG ;; u) VOXBOUSER=$OPTARG ;; \\?) echo "argh!" ;; esac done # set temporary umask for anything we create umask 022 # make sure major directories are in place mkdir -p $DEST/bin $DEST/drop $DEST/elements $DEST/etc $DEST/misc $DEST/pros\ $DEST/queue $DEST/scripts $DEST/etc/logs $DEST/etc/servers $DEST/etc/jobtypes if (($? > 0)) ; then echo "VoxBo install failed creating directories" exit 109 fi ###################### defaults if [[ ! -e $DEST/etc/defaults ]] ; then echo "creating defaults" cat > $DEST/etc/defaults < $DEST/etc/serverlist < $DEST/etc/servers/sample < $DEST/queue/vb.num < $DEST/etc/jobtypes/shellcommand.vjt < #include #include #include //#include DBdata srvSession::dbs; int32 currentUser = 0; // Initialize server session void srvSession::init() { clientID = 0; gnutls_init(&g_session, GNUTLS_SERVER); gnutls_priority_set_direct(g_session, "NORMAL:+SRP", NULL); } // Quit server session void srvSession::exit() { permissions.clear(); gnutls_bye(g_session, GNUTLS_SHUT_WR); close(sd); gnutls_deinit(g_session); } /* Send global map variables to client side * Returns -1 if score types are not sent out to client; * returns -2 if score names are not sent out to client; * returns -3 if brain region names are not sent out to client; * returns -4 if brain region synonyms are not sent out to client; * returns -5 if brain region relationships are not sent out to client. */ int srvSession::sendGlobalMaps() { if (sendTypes()) return -1; if (sendScoreNames()) return -2; if (sendRegionNames()) return -3; if (sendSynonyms()) return -4; if (sendRegionRelations()) return -5; return 0; } /* Send patient list to client side. * Returns 0 if patient list is sent out to client, * or no patient list is available and the message is sent out to client; * returns -1 if error occurs when searching patient list and error message is not sent out successfully; * returns 1 if error occurs when searching patient list but error message is sent out successfully; * returns -2 if no_patientlist message is not sent out successfully; * returns -3 if patient list data are not sent out successfully. */ int srvSession::sendPatientList() { vector vec; int foo = getPatientList(dbs.userDB, dbs.patientListDB, NULL, clientID, vec); if (foo) { statMsg = "no_data: db error code " + strnum(foo); if (sendStatMsg()) return -1; return 1; } else if (!vec.size()) { statMsg = "no_patientlist"; if (sendStatMsg()) return -2; return 0; } int32 dat_size = getSize(vec); char buffer[dat_size]; serialize(vec, buffer); if (sendData(dat_size, buffer)) { statMsg = "Error when sending patient list from server to client: " + statMsg; return -3; } return 0; } /* Send data from server to client. * Returns -1 if data size message not sent out successfully; * returns -2 id data not sent out successfully; * retunrs 0 if everything is ok. */ int srvSession::sendData(int32 dat_size, char* buffer) { // First send a message that has buffer size info string tmpMsg = "server_data_size: " + num2str(dat_size); if (sendMessage(g_session, tmpMsg)) { statMsg = "failed to send data size"; return -1; } // Now send the real data if (sendBuffer(g_session, dat_size, buffer)) { statMsg = "Failed to send data"; return -2; } return 0; } /* Build DBtype data buffer and send it to client side. * Returns 0 if everything is ok; * returns -1 for sending error. */ int srvSession::sendTypes() { vector vec; map::const_iterator iter; int32 dat_size = 0; for (iter = dbs.typemap.begin(); iter != dbs.typemap.end(); ++iter) { vec.push_back(iter->second); dat_size += iter->second.getSize(); } char buffer[dat_size]; serialize(vec, buffer); if (sendData(dat_size, buffer)) { statMsg = "Error when sending score types to client: " + statMsg; return -1; } return 0; } /* Build DBscorename data buffer and send it to client side * Returns 0 if everything is ok; * returns -1 for sending error. */ int srvSession::sendScoreNames() { vector vec; map::const_iterator iter; int32 dat_size = 0; for (iter = dbs.scorenames.begin(); iter != dbs.scorenames.end(); ++iter) { vec.push_back(iter->second); dat_size += iter->second.getSize(); } char buffer[dat_size]; serialize(vec, buffer); if (sendData(dat_size, buffer)) { statMsg = "Error when sending score names to client: " + statMsg; return -1; } return 0; } /* Build brain region names data buffer and send it to client side * Returns 0 if everything is ok; * returns -1 for sending error. */ int srvSession::sendRegionNames() { vector vec; map::const_iterator iter; int32 dat_size = 0; for (iter = dbs.regionNameMap.begin(); iter != dbs.regionNameMap.end(); ++iter) { vec.push_back(iter->second); dat_size += iter->second.getSize(); } char* buffer = new char[dat_size]; serialize(vec, buffer); if (sendData(dat_size, buffer)) { statMsg = "Error when sending brain region names to client: " + statMsg; delete [] buffer; return -1; } delete [] buffer; return 0; } /* Build synonyms data buffer and send it to client side. * Returns 0 if everything is ok; * returns -1 for sending error. */ int srvSession::sendSynonyms() { vector vec; map::const_iterator iter; int32 dat_size = 0; for (iter = dbs.synonymMap.begin(); iter != dbs.synonymMap.end(); ++iter) { vec.push_back(iter->second); dat_size += iter->second.getSize(); } char buffer[dat_size]; serialize(vec, buffer); if (sendData(dat_size, buffer)) { statMsg = "Error when sending brain region synonyms to client: " + statMsg; return -1; } return 0; } /* Build region relationships data buffer and send it to client side. * Returns 0 if everything is ok; * returns -1 for sending error. */ int srvSession::sendRegionRelations() { vector vec; map::const_iterator iter; int32 dat_size = 0; for (iter = dbs.regionRelationMap.begin(); iter != dbs.regionRelationMap.end(); ++iter) { vec.push_back(iter->second); dat_size += iter->second.getSize(); } char buffer[dat_size]; serialize(vec, buffer); if (sendData(dat_size, buffer)) { statMsg = "Error when sending brain region relationships to client: " + statMsg; return -1; } return 0; } // Serve client's requests based on message from client void srvSession::serve(const char* inputMsg) { cout << "message from client: " << inputMsg << endl; // for debugging purpose only // Do nothing if the client logs out if (strcmp(inputMsg, "logout") == 0) return; c_tokens.clear(); c_tokens.SetSeparator(" "); c_tokens.ParseLine(inputMsg); // client request of user info int stat = 0; if (c_tokens[0] == "req_usr_info:" && c_tokens.size() == 2) { stat = sendUsrInfo(); } // client request of unique ID else if (c_tokens[0] == "req_id:" && c_tokens.size() == 2) { stat = sendID(); } // client request of server's current time stamp else if (c_tokens[0] == "req_time" && c_tokens.size() == 1) { stat = sendTime(); } // client request of patient search else if (c_tokens[0] == "search_patient:") { stat = sendPatientMatches(); } // client request of all score values of a certain patient that he/she is permitted to access else if (c_tokens[0] == "req_patient:" && c_tokens.size() == 2) { stat = sendPatientScores(); } // Client sends new/updated user info data else if (c_tokens[0] == "put_new_user:" && c_tokens.size() == 2) { stat = recvNewUsr(); } // Client sends new or updated score name data else if (c_tokens[0] == "put_scorename:" && c_tokens.size() == 2) { stat = recvScoreNames(); } // Client sends new patient data else if (c_tokens[0] == "put_patient:" && c_tokens.size() == 4) { stat = recvNewPatient(); } // Client sends new or updated score value record else if (c_tokens[0] == "put_scorevalue:" && c_tokens.size() == 2) { stat = recvScoreValues(); } // Client sends new or updated session data else if (c_tokens[0] == "put_session:" && c_tokens.size() == 2) { stat = recvSessions(); } // Client sends new patient list data else if (c_tokens[0] == "put_patientlist:" && c_tokens.size() == 2) { stat = recvPatientList(true); } // Client sends modified patient list data else if (c_tokens[0] == "put_patientlist:" && c_tokens.size() == 2) { stat = recvPatientList(false); } // // more options to come ... // else { statMsg = (string) "Client message not understandable: " + inputMsg; stat = sendStatMsg(); } // print out status message (for debug only) if (stat) cout << statMsg << endl; } /* Send a feedback message back to client after receiving a put message * from client to tell the client server's operation status. * Returns 0 if message is sent out; returns 1 otherwise. */ int srvSession::sendStatMsg() { if (sendMessage(g_session, statMsg)) { statMsg += "(failed to send message to client)"; return 1; } statMsg += "(message sent to client)"; return 0; } /* Send user information to client. * Message syntax check ignored !!! * Returns 0 if everything is ok; * retunrs -1 if user is not found and message is not sent out successfully; * returns 1 if user is not found but message is sent out successfully; * returns -2 if error occurs when browsing user table, and error message is not sent out successfully; * returns 2 if error occurs when browsing user table, but error message is sent out successfully; * returns 3 if user data is not sent out successfully. */ int srvSession::sendUsrInfo() { userRec myInfo; DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int foo = getUser(dbs.userDB, txn, c_tokens[1], myInfo); if (foo != 1) { if (foo == 0) { txn->commit(0); statMsg = "no_data: User not found"; if (sendStatMsg()) return -1; return 1; } else { txn->abort(); statMsg = "no_data: DB error " + num2str(foo); if (sendStatMsg()) return -2; return 2; } } txn->commit(0); int data_size = myInfo.getSize(); char data_buf[data_size]; myInfo.serialize(data_buf); // Send data to client if (sendData(data_size, data_buf)) { statMsg = "Error when sending user data to client: " + statMsg; return 3; } return 0; } /* Send unique IDs to client side. * Returns 0 if everything is ok; * returns -1 if request from client is invalid and error message is not sent out successfully; * returns 1 if request from client is invalid but error message is sent out successfully; * returns -2 if error occurs when getting ID from db and error message is not sent out successfully; * returns 2 if error occurs when getting ID from db but error message is sent out successfully; * returns -3 if size of data is not sent out successfully; * returns -4 if data are not sent out successfully. */ int srvSession::sendID() { int32 id_num; bool conv_stat = str2num(c_tokens[1], id_num); if (!conv_stat || id_num <= 0) { statMsg = "no_data: Invalid number from client: " + c_tokens[1]; if (sendStatMsg()) return -1; return 1; } DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int32 startID = getSysID(dbs.sysDB, txn, id_num); if (startID <= 0) { txn->abort(); statMsg = "no_data: DB error"; if (sendStatMsg()) return -2; return 2; } txn->commit(0); dbs.sysDB.getDb().sync(0); // write data on disk now statMsg = "server_data_size: " + num2str(sizeof(startID)); if (sendStatMsg()) { statMsg = "Error when sending ID to client: failed to send data size message"; return -3; } if (ntohs(1) == 1) swap(&startID); if (gnutls_record_send(g_session, &startID, sizeof(startID)) != sizeof(startID)) { statMsg = "Error when sending ID to client: failed to send data"; return 4; } return 0; } /* Send server's current time stamp to client side. * Return 0 if everything is ok; * returns -1 if time stamp can not be sent to client; */ int srvSession::sendTime() { int32 t_stamp = time(NULL); if (ntohs(1) == 1) swap(&t_stamp); if (gnutls_record_send(g_session, &t_stamp, sizeof(t_stamp)) != sizeof(t_stamp)) { statMsg = "Failed to send time stamp to client"; return -1; } return 0; } /* This function checks and parses client message. * If the syntax error is found, set the error msg and return false; * otherwise set the search tags and retuirn true. */ bool srvSession::parsePatientSearch(patientSearchTags& tags) { tags.init(); if (c_tokens.size() < 5 || c_tokens.size() == 6) { tags.err_msg.append("can not understand client message."); return false; } if (c_tokens[1] != "case_sensitive" && c_tokens[1] != "case_insensitive") { tags.err_msg.append("can not understand case_sensitivity tag "); tags.err_msg.append(c_tokens[1]); return false; } if (c_tokens[2] != "any") { int32 dat_size; bool conv_stat = str2num(c_tokens[2], dat_size); if (!conv_stat || dat_size <= 0) { tags.err_msg.append("invalid score ID "); tags.err_msg.append(c_tokens[2]); return false; } } if (c_tokens[3] != "equal" && c_tokens[3] != "include" && c_tokens[3] != "wildcard") { tags.err_msg.append("unknown relationship string "); tags.err_msg.append(c_tokens[3]); return false; } if (c_tokens[1] == "case_sensitive") tags.case_sensitive = true; else tags.case_sensitive = false; if (c_tokens[2] == "any") tags.scoreName = ""; else { tags.scoreName = c_tokens[2]; } tags.relationship = c_tokens[3]; tags.searchStr = c_tokens[4]; if (c_tokens.size() == 5) return true; if (c_tokens[5] != "among") { tags.err_msg.append("can not understand client message."); return false; } for (size_t i = 6; i < c_tokens.size(); i++) { int32 pID; bool conv_stat = str2num(c_tokens[i], pID); if (!conv_stat || pID <= 0) { tags.err_msg.append("Unknown patient ID string: ").append(c_tokens[i]); tags.patientIDs.clear(); return false; } tags.patientIDs.push_back(pID); } return true; } /* Get a brief list of patients that matched cleint search criteria. * Returns 0 if patient is found and data are sent out successfully, * or no patient is found and message is sent out successfully; * returns -1 if permission is denied and error message is not sent out successfully; * returns 1 if permission is denied but error message is sent out successfully; * returns -2 if search criterion is invalid and error message is not sent out successfully; * returns 2 if search criterion is invalid but error message is sent out successfully; * returns -3 if error occurs when searching patient and error message is not sent out successfully; * returns 3 if error occurs when searching patient but error message is sent out successfully; * returns -4 if no patient is found in db and message is not sent out successfully; * returns -5 if patient is found but data are not sent out successfully. */ int srvSession::sendPatientMatches() { if (!permissions.size()) { statMsg = "Permission denied"; if (sendStatMsg()) return -1; return 1; } patientSearchTags ps_tags; if (!parsePatientSearch(ps_tags)) { statMsg = ps_tags.err_msg; if (sendStatMsg()) return -2; return 2; } DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); vector currentPatients; int foo = searchPatients(dbs.scoreValueDB, txn, ps_tags, permissions, currentPatients); if (foo < 0) { txn->abort(); statMsg = "no_data: DB error "; if (sendStatMsg()) return -3; return 3; } txn->commit(0); if (!currentPatients.size()) { statMsg = "no_data: Patient not found"; if (sendStatMsg()) return -4; return 0; } int32 dat_size = getSize(currentPatients); char dat_buffer[dat_size]; serialize(currentPatients, dat_buffer); if (sendData(dat_size, dat_buffer)) { statMsg = "Error when sending patient search results to client: " + statMsg; return -5; } return 0; } /* Get all scores of a certain patient. * Returns 0 if everything is ok; * returns -1 if permission is denied, and error message is not sent out successfully; * returns 1 if permission is denied, but error message is sent out successfully; * returns -2 if patient ID is invalid, and error message is not sent out successfully; * returns 2 if patient ID is invalid, but error message is sent out successfully; * returns -3 if error occurs when searching score value table, and error message is not sent out successfully; * returns 3 if error occurs when searching score value table, but error message is sent out successfully; * returns -4 if no score value record is found, and error message is not sent out successfully; * returns 4 if no score value record is found, but error message is sent out successfully; * returns -5 if data size message is not sent out successfully; * returns -6 if score value data are not sent out successfully; * returns -7 if no session is available, and the message is not sent out successfully; * returns -8 if error occurs when searching session table, and error message is not sent out successfully; * returns 8 if error occurs when searching session table, but error message is sent out successfully; * returns -9 if session data are not sent out successfully. */ int srvSession::sendPatientScores() { if (!permissions.size()) { statMsg = "Permission denied"; if (sendStatMsg()) return -1; return 1; } // send error message to client if patient ID is invalid or score values not found int32 pID; bool conv_stat = str2num(c_tokens[1], pID); if (!conv_stat || pID <= 0) { statMsg = "no_data: Invalid patient ID " + c_tokens[1]; if (sendStatMsg()) return -2; return 2; } // get score values set sid_set; DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); Dbc* cursorp = NULL; if (dbs.scoreValueDB.getDb().cursor(txn, &cursorp, 0)) { txn->abort(); statMsg = "no_data: db error when searching score value table"; if (sendStatMsg()) return -3; return 3; } // Iterate over score values table Dbt key, data; int ret; int32 status = 0; while ((ret = cursorp->get(&key, &data, DB_NEXT_NODUP)) == 0) { DBscorevalue svData; svData.deserializeHdr(data.get_data()); if (pID != svData.patient || svData.deleted) continue; string tmpPerm = getMaxPerm(svData, permissions); if (tmpPerm.empty()) continue; /* Add session IDs into session_list vector (session 0 is ignored here * because this session doesn't exist in session table anyway) */ int32 sess_id = svData.sessionid; if (sess_id) sid_set.insert(sess_id); // Add real score value records into DBscorevalue vector. status = 1; uint32 dat_size = data.get_size(); statMsg = "scorevalue: " + num2str(dat_size) + " " + tmpPerm; if (sendStatMsg()) { cursorp->close(); txn->abort(); return -4; } if (sendBuffer(g_session, dat_size, (char*) data.get_data())) { statMsg = "Error when sending score value to client"; cursorp->close(); txn->abort(); return -4; } } // Returns -1 if ret is non-zero and it doesn't reach the end of table if (ret && ret != DB_NOTFOUND) { cursorp->close(); txn->abort(); statMsg = "no_data: db error when searching score value table"; if (sendStatMsg()) return -3; return 3; } cursorp->close(); if (status == 0) { txn->commit(0); statMsg = "no_scorevalue"; if (sendStatMsg()) return -5; return 5; } // If session ID list is empty, tell client that no session info sent out if (sid_set.size() == 0) { txn->commit(0); statMsg = "no_session"; if (sendStatMsg()) return -7; return 0; } // get related DBsession vector sessList; int32 dat_size = getSessions(dbs.sessionDB, txn, sid_set, sessList); // Note that dat_size may be zero if all score values are static if (dat_size <= 0) { txn->abort(); statMsg = "no_data: Session record not found"; if (sendStatMsg()) return -8; return 8; } txn->commit(0); // send session data to client char sess_buff[dat_size]; serialize(sessList, sess_buff); if (sendData(dat_size, sess_buff)) { statMsg = "Error when sending patient session data to client: " + statMsg; return -9; } return 0; } /* Receive updated user information data from client. * Returns 0 if everything is ok; * returns -1 if data size from client is invalid, and this error message is not sent out successfully; * returns 1 if data size from client is invalid, but this error message is sent out successfully; * returns -2 if user data is not received, and this error error message is not sent out successfully; * returns 2 if user data is not received, but this error error message is sent out successfully; * returns -3 if user account received already exists, and this error message is not sent out successfully; * returns 3 if user account received already exists, but this error message is sent out successfully; * returns -4 if error occurs when searching user table, and error message is not sent out successfully; * returns 4 if error occurs when searching user table, but error message is sent out successfully; * returns -5 if db error occurs when updating system time stamp, and error message is not sent out successfully; * returns 5 if db error occurs when updating system time stamp, but error message is sent out successfully; * returns -6 if server confirmation message is not sent out successfully. */ int srvSession::recvNewUsr() { int32 dat_size; bool conv_stat = str2num(c_tokens[1], dat_size); if (!conv_stat || dat_size <= 0) { statMsg = "Invalid buffer size from client: " + c_tokens[1]; if (sendStatMsg()) return -1; return 1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { statMsg = "Failed to receive new user data from client"; if (sendStatMsg()) return -2; return 2; } DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); int stat = addUser(dbs.userDB, dbs.sysDB, txn, buffer); if (stat == 1) { txn->commit(0); statMsg = "Account already exists."; if (sendStatMsg()) return -3; return 3; } if (stat) { txn->abort(); statMsg = "DB error when adding records into user table"; if (sendStatMsg()) return -4; return 4; } if (setSysUpdate(dbs.sysDB, txn, statMsg)) { txn->abort(); statMsg = "DB error when updating time stamp in system table: " + statMsg; if (sendStatMsg()) return -5; return 5; } txn->commit(0); statMsg = "success"; if (sendStatMsg()) return -6; dbs.sysDB.getDb().sync(0); dbs.userDB.getDb().sync(0); // write data on disk now return 0; } /* Receive score name data from client side. * Returns 0 if everything is ok; * returns -1 if data size from client is invalid, and this error message is not sent out successfully; * returns 1 if data size from client is invalid, but this error message is sent out successfully; * returns -2 if data is not received, and this error error message is not sent out successfully; * returns 2 if data is not received, but this error error message is sent out successfully; * returns -3 if error occurs when searching db, and error message is not sent out successfully; * returns 3 if error occurs when searching db, but error message is sent out successfully; * returns -4 if db error occurs when updating system time stamp, and error message is not sent out successfully; * returns 4 if db error occurs when updating system time stamp, but error message is sent out successfully; * returns -5 if server confirmation message is not sent out successfully. */ int srvSession::recvScoreNames() { int32 dat_size; bool conv_stat = str2num(c_tokens[1], dat_size); if (!conv_stat || dat_size <= 0) { statMsg = "Invalid score name data size from client: " + c_tokens[1]; if (sendStatMsg()) return -1; return 1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { statMsg = "Failed to receive score names from client"; if (sendStatMsg()) return -2; return 2; } vector snList; deserialize(dat_size, buffer, snList); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); if (addScoreName(dbs.scoreNameDB, txn, snList)) { txn->abort(); statMsg = "DB error when adding score name record into score name table"; if (sendStatMsg()) return -3; return 3; } if (setSysUpdate(dbs.sysDB, txn, statMsg)) { txn->abort(); statMsg = "DB error when updating time stamp in system table: " + statMsg; if (sendStatMsg()) return -4; return 4; } txn->commit(0); dbs.scoreNameDB.getDb().sync(0); dbs.sysDB.getDb().sync(0); // Update score name maps on server side vbforeach(DBscorename sn, snList) { dbs.add_scorename(sn); } statMsg = "success"; if (sendStatMsg()) return -5; return 0; } /* Receive updated patient score data from client. * Returns 0 if everything is ok; * returns -1 if data size from client is invalid, and error message is not sent out successfully; * returns 1 if data size from client is invalid, but error message is sent out successfully; * returns -2 if patient data received are invalid, and error message is not sent out successfully; * returns 2 if patient data from client are invalid, but error message is sent out successfully; * returns -3 if db error occurs when adding patient, and error message is not sent out successfully; * returns 3 if db error occurs when adding patient, but error message is sent out successfully; * returns -4 if db error occurs when adding sessions, and error message is not sent out successfully; * returns 4 if db error occurs when adding sessions, but error message is sent out successfully; * returns -5 if score value data size received is invalid, and error message is not sent out successfully; * returns 5 if score value data size received is invalid, but error message is sent out successfully; * returns -6 if score value data received are invalid, and error message is not sent out successfully; * returns 6 if score value data received are invalid, but error message is sent out successfully; * returns -7 if db error occurs when adding score value, and error message is not sent out successfully; * returns 7 if db error occurs when adding score value, but error message is sent out successfully; * returns -8 if db error occurs when updating system time stamp, and error message is not sent out successfully; * returns 8 if db error occurs when updating system time stamp, but error message is sent out successfully; * returns -9 if server confirmation message is not sent out successfully. */ int srvSession::recvNewPatient() { int32 p_size, s_size, sv_num; if (!chkPatientDatSize(p_size, s_size, sv_num)) { if (sendStatMsg()) return -1; return 1; } int32 dat_size = p_size + s_size; char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { statMsg = "Failed to receive patient data from client"; if (sendStatMsg()) return -2; return 2; } time_t t_stamp = time(NULL); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); // Add patient data (if it is available) if (p_size) { patientRec newPatient(buffer); if (addPatient(dbs.patientDB, txn, newPatient)) { txn->abort(); statMsg = "DB error when adding new patient record"; if (sendStatMsg()) return -3; return 3; } } // Add session data (if it is available) if (s_size) { vector sList; deserialize(s_size, buffer + p_size, sList); if (addSession(dbs.sessionDB, txn, sList, t_stamp)) { txn->abort(); statMsg = "DB error when adding new session record"; if (sendStatMsg()) return -4; return 4; } } // Add score value data (if it is available) int32 db_time = t_stamp; if (ntohs(1) == 1) swap(&db_time); for (int i = 0; i < sv_num; i++) { uint32 sv_size = 0; if (gnutls_record_recv(g_session, &sv_size, sizeof(uint32)) != sizeof(uint32)) { txn->abort(); statMsg = "Failed to receive size of score value data from client"; if (sendStatMsg()) return -5; return 5; } if (ntohs(1) == 1) swap(&sv_size); char* sv_dat = new char[sv_size]; if (recvBuffer(g_session, sv_size, sv_dat)) { txn->abort(); statMsg = "Failed to receive score value data from client"; if (sendStatMsg()) return -6; return 6; } *((int32*) sv_dat) = db_time; // set the new time stamp int32 sv_id = *((int32*) (sv_dat + sizeof(int32))); // get score value ID if (ntohs(1) == 1) swap(&sv_id); Dbt db_key(&sv_id, sizeof(int32)); Dbt db_data(sv_dat, sv_size); if (dbs.scoreValueDB.getDb().put(txn, &db_key, &db_data, 0)) { txn->abort(); statMsg = "DB error when adding score value data"; if (sendStatMsg()) return -7; return 7; } } if (setSysUpdate(dbs.sysDB, txn, t_stamp, statMsg)) { txn->abort(); statMsg = "DB error when updating time stamp in system table: " + statMsg; if (sendStatMsg()) return -8; return 8; } txn->commit(0); dbs.patientDB.getDb().sync(0); dbs.sessionDB.getDb().sync(0); dbs.scoreValueDB.getDb().sync(0); dbs.sysDB.getDb().sync(0); statMsg = "updated:" + num2str(t_stamp); if (sendStatMsg()) return -9; return 0; } /* This function checks the three tokens in lcient message to * make sure they are all valid numeric values. * Returns true if they are valid, false otherwise. */ bool srvSession::chkPatientDatSize(int32& p_size, int32& s_size, int32& sv_num) { bool conv_stat = str2num(c_tokens[1], p_size); if (!conv_stat || p_size < 0) { statMsg = "Invalid patient data size from client: " + c_tokens[1]; return false; } conv_stat = str2num(c_tokens[2], s_size); if (!conv_stat || s_size < 0) { statMsg = "Invalid session data size from client: " + c_tokens[2]; return false; } conv_stat = str2num(c_tokens[3], sv_num); if (!conv_stat || sv_num < 0) { statMsg = "Invalid number of score value record from client: " + c_tokens[3]; return false; } return true; } /* Receive updated patient score data from client. * Returns 0 if everything is ok; * returns -1 if number of score values received is invalid, and error message is not sent out successfully; * returns 1 if number of score values received is invalid, but error message is sent out successfully; * returns -2 if score value data size received is invalid, and error message is not sent out successfully; * returns 2 if score value data size received is invalid, but error message is sent out successfully; * returns -3 if score value data received are invalid, and error message is not sent out successfully; * returns 3 if score value data received are invalid, but error message is sent out successfully; * returns -4 if db error occurs when adding score value, and error message is not sent out successfully; * returns 4 if db error occurs when adding score value, but error message is sent out successfully; * returns -5 if db error occurs when updating system time stamp, and error message is not sent out successfully; * returns 5 if db error occurs when updating system time stamp, but error message is sent out successfully; * returns -6 if server confirmation message is not sent out successfully. */ int srvSession::recvScoreValues() { int32 sv_num; bool conv_stat = str2num(c_tokens[1], sv_num); if (!conv_stat || sv_num <= 0) { statMsg = "Invalid number of score value record from client: " + c_tokens[1]; if (sendStatMsg()) return -1; return 1; } int32 t_stamp = time(NULL); if (ntohs(1) == 1) swap(&t_stamp); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); for (int i = 0; i < sv_num; i++) { uint32 sv_size = 0; if (gnutls_record_recv(g_session, &sv_size, sizeof(uint32)) != sizeof(uint32)) { txn->abort(); statMsg = "Failed to receive size of score value data from client"; if (sendStatMsg()) return -2; return 2; } if (ntohs(1) == 1) swap(&sv_size); char* sv_dat = new char[sv_size]; if (recvBuffer(g_session, sv_size, sv_dat)) { txn->abort(); statMsg = "Failed to receive score value data from client"; if (sendStatMsg()) return -3; return 3; } *((int32*) sv_dat) = t_stamp; // set new time stamp int32 sv_id = *((int32*) (sv_dat + sizeof(int32))); // get score value ID if (ntohs(1) == 1) swap(&sv_id); Dbt db_key(&sv_id, sizeof(int32)); Dbt db_data(sv_dat, sv_size); if (dbs.scoreValueDB.getDb().put(txn, &db_key, &db_data, 0)) { txn->abort(); statMsg = "DB error when adding score value data"; if (sendStatMsg()) return -4; return 4; } } if (setSysUpdate(dbs.sysDB, txn, t_stamp, statMsg)) { txn->abort(); statMsg = "DB error when updating time stamp in system table: " + statMsg; if (sendStatMsg()) return -5; return 5; } txn->commit(0); dbs.scoreValueDB.getDb().sync(0); dbs.sysDB.getDb().sync(0); statMsg = "updated:" + num2str(t_stamp); if (sendStatMsg()) return -6; return 0; } /* Receive patient session data from client side and add them into database. * Returns 0 if everything is ok; * returns -1 if data size from client is invalid, and error message is not sent out successfully; * returns 1 if data size from client is invalid, but error message is sent out successfully; * returns -2 if data from client are invalid, and error message is not sent out successfully; * returns 2 if data from client are invalid, but error message is sent out successfully; * returns -3 if db error occurs when adding sessions, and error message is not sent out successfully; * returns 3 if db error occurs when adding sessions, but error message is sent out successfully; * returns -4 if db error occurs when updating system time stamp, and error message is not sent out successfully; * returns 4 if db error occurs when updating system time stamp, but error message is sent out successfully; * returns -5 if server confirmation message is not sent out successfully. */ int srvSession::recvSessions() { int32 dat_size; bool conv_stat = str2num(c_tokens[1], dat_size); if (!conv_stat || dat_size <= 0) { statMsg = "Invalid buffer size from client: " + c_tokens[1]; if (sendStatMsg()) return -1; return 1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { statMsg = "Failed to receive patient session data from client"; if (sendStatMsg()) return -2; return 2; } vector sList; deserialize(dat_size, buffer, sList); time_t t_stamp = time(NULL); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); if (addSession(dbs.sessionDB, txn, sList, t_stamp)) { txn->abort(); statMsg = "DB error when adding patient session data"; if (sendStatMsg()) return -3; return 3; } if (setSysUpdate(dbs.sysDB, txn, t_stamp, statMsg)) { txn->abort(); statMsg = "DB error when updating time stamp in system table: " + statMsg; if (sendStatMsg()) return -4; return 4; } txn->commit(0); dbs.sessionDB.getDb().sync(0); dbs.sysDB.getDb().sync(0); statMsg = "updated:" + num2str(t_stamp); if (sendStatMsg()) return -5; return 0; } /* Receive patient list data from client side. * The parameter shows whether it is a new patient list or updated patient list record. * Returns 0 if everything is ok; * returns -1 if data size from client is invalid, and error message is not sent out successfully; * returns 1 if data size from client is invalid, but error message is sent out successfully; * returns -2 if data from client are invalid, and error message is not sent out successfully; * returns 2 if data from client are invalid, but error message is sent out successfully; * returns -3 if db error occurs when adding patient list, and error message is not sent out successfully; * returns 3 if db error occurs when adding patient list, but error message is sent out successfully; * returns -4 if db error occurs when updating system time stamp, and error message is not sent out successfully; * returns 4 if db error occurs when updating system time stamp, but error message is sent out successfully; * returns -5 if server confirmation message is not sent out successfully. */ int srvSession::recvPatientList(bool isNew) { int32 dat_size; bool conv_stat = str2num(c_tokens[1], dat_size); string server_msg; if (!conv_stat || dat_size <= 0) { server_msg = "Invalid buffer size from client: " + c_tokens[1]; if (sendStatMsg()) return -1; return 1; } char buffer[dat_size]; if (recvBuffer(g_session, dat_size, buffer)) { statMsg = "Failed to receive patient list data from client"; if (sendStatMsg()) return -2; return 2; } DBpatientlist inputRec(buffer); time_t t_stamp = time(NULL); if (isNew) inputRec.runDate.setUnixTime(t_stamp); else inputRec.modDate.setUnixTime(t_stamp); DbTxn* txn = NULL; dbs.env.getEnv()->txn_begin(NULL, &txn, 0); if (addPatientList(dbs.patientListDB, txn, inputRec)) { txn->abort(); statMsg = "DB error when adding patient list data"; if (sendStatMsg()) return -3; return 3; } if (setSysUpdate(dbs.sysDB, txn, t_stamp, statMsg)) { txn->abort(); statMsg = "DB error when updating time stamp in system table: " + statMsg; if (sendStatMsg()) return -4; return 4; } txn->commit(0); dbs.patientListDB.getDb().sync(0); dbs.sysDB.getDb().sync(0); statMsg = "updated:" + num2str(t_stamp); if (sendStatMsg()) return -5; return 0; } // This function is based on Dan's sample code int srp_credfunction(gnutls_session,const char* username,gnutls_datum* salt, gnutls_datum* verifier, gnutls_datum* generator, gnutls_datum* prime) { // retrieve user data from bdb string account_str(username); userRec uData; int foo = getUser(srvSession::dbs.userDB, NULL, account_str, uData); if (foo != 1) { return -1; } // copy salt salt->size = 4; salt->data = (unsigned char*) gnutls_malloc(4); if (!salt->data) return -1; memcpy(salt->data, uData.getSalt().data, 4); // copy stock generator generator->size = gnutls_srp_1024_group_generator.size; generator->data = (unsigned char*) gnutls_malloc(generator->size); if (!generator->data) return -1; memcpy(generator->data, gnutls_srp_1024_group_generator.data, generator->size); // copy stock prime prime->size = gnutls_srp_1024_group_prime.size; prime->data = (unsigned char*) gnutls_malloc(prime->size); if (!prime->data) return -1; memcpy(prime->data, gnutls_srp_1024_group_prime.data, prime->size); // copy verifier verifier->size = uData.getVerifier().size; verifier->data = (unsigned char*) gnutls_malloc(verifier->size); if (!verifier->data) return -1; memcpy(verifier->data, uData.getVerifier().data,verifier->size); // Added by Dongbo, record user ID so that permissions can be loaded for this user currentUser = uData.getID(); return 0; } /* Copied from Dan. * Needs a lot of tweaking in the future. * Returns 0 if everythign is ok; * returns 1 if server can not open env or db files, or fails to set up global maps * returns -1 if bind fails; * returns -2 if listen fails; * returns -3 if global maps are not sent to client successfully; */ int startServer(const string& envHome, int32 port_no) { // open env and db files srvSession::dbs.dirname = envHome; if (srvSession::dbs.open()) { cout << srvSession::dbs.errMsg << endl; srvSession::dbs.close(); return 1; } // create socket and accept gnutls connection from client int err; struct sockaddr_in sa_serv; struct sockaddr_in sa_cli; socklen_t client_len; char topbuf[512]; int yes=1; gnutls_srp_server_credentials_t srpcred; printf("SERVER STARTED\n"); gnutls_global_init(); gnutls_global_init_extra(); gnutls_srp_allocate_server_credentials(&srpcred); gnutls_srp_set_server_credentials_function(srpcred, srp_credfunction); // create the socket, make it reusable after exit int srv_socket = socket(PF_INET, SOCK_STREAM, 0); if (srv_socket < 0) return srv_socket; setsockopt(srv_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); // create socket address, bind to our socket memset(&sa_serv, 0, sizeof(sa_serv)); sa_serv.sin_family = AF_INET; sa_serv.sin_port = htons(port_no); sa_serv.sin_addr.s_addr = htonl(INADDR_ANY); err = bind(srv_socket, (struct sockaddr*)&sa_serv, sizeof(sa_serv)); if (err == -1) { close(srv_socket); return -1; } // express willingness to listen for up to 16 queued connections err = listen(srv_socket, 16); // how much of a backlog should we allow? if (err == -1) { close(srv_socket); return -2; } printf("Now listening to port %d\n", port_no); client_len = sizeof(sa_cli); printf("server waiting for connection\n"); list sessions; while(1) { fd_set myset; FD_ZERO(&myset); FD_SET(srv_socket, &myset); int highestsocket = srv_socket; for (list::iterator si = sessions.begin(); si != sessions.end(); ++si) { FD_SET(si->sd, &myset); if (si->sd > highestsocket) highestsocket = si->sd; } struct timeval mytv; mytv.tv_sec = 5; // wait 5 seconds before looping mytv.tv_usec = 0; int ret = select(highestsocket + 1, &myset, NULL, NULL, &mytv); if (ret <= 0) continue; // this is actually an error condition, we might have lost the socket if (FD_ISSET(srv_socket, &myset)) { // handle new connection stuff here cout << "New connection " << sessions.size() + 1 << endl; // Create new session, push on back of list, get ptr to gnutls session struct srvSession currentConnx; currentConnx.init(); gnutls_credentials_set(currentConnx.g_session, GNUTLS_CRD_SRP, srpcred); currentConnx.sd = accept(srv_socket, (struct sockaddr*) &sa_cli, &client_len); printf ("- connection from %s, port %d\n", inet_ntop(AF_INET, &sa_cli.sin_addr, topbuf, sizeof(topbuf)), ntohs(sa_cli.sin_port)); gnutls_transport_set_ptr(currentConnx.g_session, (gnutls_transport_ptr_t) currentConnx.sd); printf("transport ptr set, about to handshake\n"); int hs_stat = gnutls_handshake(currentConnx.g_session); // srp_credfunction() is called here! printf("handshook, or not\n"); if (hs_stat < 0) { close(currentConnx.sd); gnutls_deinit(currentConnx.g_session); fprintf(stderr, "*** Handshake has failed (%s)\n\n", gnutls_strerror(hs_stat)); continue; } printf ("- Handshake completed\n"); currentConnx.clientID = currentUser; if (currentConnx.sendGlobalMaps()) { cout << currentConnx.statMsg << endl; continue; // Make sure global maps are sent out to client side successfully } if (currentConnx.sendPatientList()) { cout << currentConnx.statMsg << endl; continue; // Make sure global maps are sent out to client side successfully } int foo = getPerm(srvSession::dbs.userDB, srvSession::dbs.permDB, NULL, currentConnx.clientID, currentConnx.permissions); if (foo) { printf("*** Error code %d: fails to retrieve user permissions\n", foo); continue; } sessions.push_back(currentConnx); } for (list::iterator si = sessions.begin(); si != sessions.end(); si++) { if (!FD_ISSET(si->sd, &myset)) continue; // handle this session here char msg_buffer[MSG_SIZE + 1]; memset(msg_buffer, 0, MSG_SIZE); int ret2 = gnutls_record_recv(si->g_session, msg_buffer, MSG_SIZE); if (ret2 > 0) { si->serve(msg_buffer); } else if (ret2 == 0) { printf ("\n- Peer has closed the GNUTLS connection\n"); si->exit(); sessions.erase(si); break; // important!!! Without this line server's response will be late } else { fprintf (stderr, "*** corrupted data(%d), closing connection\n", ret2); si->exit(); sessions.erase(si); break; // important!!! Without this line server's response will be late } } } close(srv_socket); gnutls_srp_free_server_credentials(srpcred); gnutls_global_deinit(); if (srvSession::dbs.close()) { cout << "Failed to close DB env and files" << endl; return -1; } return 0; } /* Print out usage message on the screen */ void usage() { printf("Usage: server \n"); printf(" db_dir: optional db directory (default is ../env)\n"); printf(" port#: optional port number (default is 5556)\n"); } /* Call this function to close env and dbs when server is terminated in abnormal way. * Without this signal handler, the program may get this error when terminated by Ctrl-C repeatedly: * "unable to allocate memory for mutex; resize mutex region. * Error opening database file: namespace.db * Failed to open brain region namespace db * Database handles still open at environment close * Error closing db enviroment * Segmentation fault" * It is dangerous to close the server but leaves env and DBs still open. */ void handleSIG(int) { if (srvSession::dbs.close()) { cout << "Failed to close DB env and files" << endl; exit(1); } exit(0); } /* Simple main function to start the server */ int main(int argc, char* argv[]) { // QApplication app(argc, argv); //signal(SIGINT, handleSIG); if (argc != 1 && argc != 3) { usage(); exit(1); } int32 port_no; string envHome; // If there is no argument, set the default dir location and port number if (argc == 1) { envHome = "../env"; port_no = 5556; } else { envHome = string(argv[1]); port_no = atoi(argv[2]); if (port_no < 1024) { usage(); exit(1); } } if (startServer(envHome, port_no)) exit(1); return 0; } voxbo-1.8.5~svn1246/server/server.h000066400000000000000000000026561153177201300171220ustar00rootroot00000000000000#ifndef SERVER_H #define SERVER_H #include #include #include #include "bdb_tab.h" #include "dbdata.h" #include "db_util.h" #include "tokenlist.h" // Server session class class srvSession { friend int startServer(const string&, int); friend void handleSIG(int); friend int srp_credfunction(gnutls_session, const char*, gnutls_datum*, gnutls_datum*, gnutls_datum*, gnutls_datum*); public: void init(); void exit(); void serve(const char*); int sendGlobalMaps(); int sendPatientList(); int sendUsrInfo(); int sendID(); int sendTime(); int sendPatientMatches(); int sendPatientScores(); gnutls_session_t g_session; int sd; int32 clientID; map permissions; private: bool parsePatientSearch(patientSearchTags&); int recvNewUsr(); int recvScoreNames(); int recvNewPatient(); bool chkPatientDatSize(int32&, int32&, int32&); int recvScoreValues(); int recvSessions(); int recvPatientList(bool); int sendData(int32, char*); int sendStatMsg(); int sendTypes(); int sendScoreNames(); int sendRegionNames(); int sendSynonyms(); int sendRegionRelations(); tokenlist c_tokens; string statMsg; static DBdata dbs; }; void usage(); void handleSIG(int); int startServer(const string&, int32); int srp_credfunction(gnutls_session, const char*, gnutls_datum*, gnutls_datum*, gnutls_datum*, gnutls_datum*); #endif voxbo-1.8.5~svn1246/stand_alone/000077500000000000000000000000001153177201300164135ustar00rootroot00000000000000voxbo-1.8.5~svn1246/stand_alone/Makefile000066400000000000000000000103151153177201300200530ustar00rootroot00000000000000 # Makefile for stand-alone stuff -include ../make_vars.txt include ../make_stuff.txt VBLIBS=$(VBLIBS2) CALCGSPS_OBJECTS=calc_gs_ps.o timeseries.o utils.o koshutil.o SLICE_ACQ_OBJECTS=utils.o koshutil.o TESPLIT_OBJECTS=utils.o koshutil.o TESJOIN_OBJECTS=$(TESPLIT_OBJECTS) REGRESSION_OBJECTS=regression.o utils.o koshutil.o PERMUTATION_OBJECTS=perm.o utils.o time_series_avg.o koshutil.o LIBS=$(LDFLAGS) $(LIBDIRS) -lvbglm -lvbprefs -lvbio -lvbutil -lz -lpng $(GSL_LIBS) $(DLLIB) ALLBINS= calcgs calcps sliceacq tesplit tesjoin makematkg makematk\ comptraces permstep vbregress vbpermmat OUT=tesregstart tesregfinish tesregstep assembleps vbvolregress ifeq ($(VB_TARGET),all) BINS=$(ALLBINS) else ifeq ($(VB_TARGET),spm) BINS=$(ALLBINS) else BINS=vbpermmat endif # the main targets all: $(BINS) install: $(BINS) ifdef BINS cp -Pf $(BINS) $(VB_BINDIR) else @echo "Nothing to install." endif clean: rm -f $(CLEANME) $(ALLBINS) $(VBLIBS): +make -C ../lib $@ # THE SHARED OBJECT X_LD_FLAGS= -shared --warn-once -Xlinker -noinhibit-exec LIB_VOXBO=../lib ifndef $(IDL_DIR) IDL_DIR=/usr/local/rsi/idl/ endif IDL_VERSION_MAJOR=$(shell grep IDL_VERSION_MAJOR $(IDL_DIR)/external/export.h | cut -d" " -f3) IDL_VERSION_MINOR=$(shell grep IDL_VERSION_MINOR $(IDL_DIR)/external/export.h | cut -d" " -f3) INCLUDES= -I./ -I ../lib -I $(IDL_DIR)/external INCLUDE_FILES= $(LIB_VOXBO)/genericexcep.h $(LIB_VOXBO)/stringtokenizer.h $(LIB_VOXBO)/vbutil.h vb_common_incs.h time_series_avg.h $(LIB_VOXBO)/vbutil.o: $(LIB_VOXBO)/vbutil.cpp $(LIB_VOXBO)/vbutil.h $(CXX) $(CXXFLAGS) -o $(@) $(LIB_VOXBO)/$(@F:.o=.cpp) $(INCLUDES) $(LIB_VOXBO)/stringtokenizer.o: $(LIB_VOXBO)/stringtokenizer.cpp $(LIB_VOXBO)/stringtokenizer.h $(LIB_VOXBO)/genericexcep.h $(CXX) $(CXXFLAGS) -o $(@) $(LIB_VOXBO)/$(@F:.o=.cpp) $(INCLUDES) $(LIB_VOXBO)/genericexcep.o: $(LIB_VOXBO)/genericexcep.cpp $(LIB_VOXBO)/genericexcep.h $(CXX) $(CXXFLAGS) -o $(@) $(LIB_VOXBO)/$(@F:.o=.cpp) $(INCLUDES) # THE EXECUTABLES calcgs: $(CALCGSPS_OBJECTS) calcgs.cpp $(CXX) -o $(@) $(@).cpp $(CALCGSPS_OBJECTS) $(CXXFLAGS) $(LIBS) calcps: $(CALCGSPS_OBJECTS) calcps.cpp $(CXX) -o $(@) $(@).cpp $(CALCGSPS_OBJECTS) $(CXXFLAGS) $(LIBS) sliceacq: $(SLICE_ACQ_OBJECTS) sliceacq.cpp $(CXX) -o $(@) $(@).cpp $(SLICE_ACQ_OBJECTS) $(CXXFLAGS) $(LIBS) tesplit: $(TESPLIT_OBJECTS) tesplit.cpp $(CXX) -o $(@) $(@).cpp $(TESPLIT_OBJECTS) $(CXXFLAGS) $(LIBS) tesjoin: $(TESJOIN_OBJECTS) tesjoin.cpp $(CXX) -o $(@) $(@).cpp $(TESJOIN_OBJECTS) $(CXXFLAGS) $(LIBS) tesregstep: $(REGRESSION_OBJECTS) tesregstep.cpp $(CXX) -o $(@) $(@).cpp $(REGRESSION_OBJECTS) $(CXXFLAGS) $(LIBS) tesregstart: $(REGRESSION_OBJECTS) tesregstart.cpp $(CXX) -o $(@) $(@).cpp $(REGRESSION_OBJECTS) $(CXXFLAGS) $(LIBS) tesregfinish: $(REGRESSION_OBJECTS) tesregfinish.cpp $(CXX) -o $(@) $(@).cpp $(REGRESSION_OBJECTS) $(CXXFLAGS) $(LIBS) makematkg: $(REGRESSION_OBJECTS) makematkg.cpp $(CXX) -o $(@) $(@).cpp $(REGRESSION_OBJECTS) $(CXXFLAGS) $(LIBS) makematk: $(REGRESSION_OBJECTS) makematk.cpp $(CXX) -o $(@) $(@).cpp $(REGRESSION_OBJECTS) $(CXXFLAGS) $(LIBS) assembleps: $(REGRESSION_OBJECTS) assembleps.cpp $(CXX) -o $(@) $(@).cpp $(REGRESSION_OBJECTS) $(CXXFLAGS) $(LIBS) comptraces: $(REGRESSION_OBJECTS) comptraces.cpp $(CXX) -o $(@) $(@).cpp $(REGRESSION_OBJECTS) $(CXXFLAGS) $(LIBS) permstep: $(PERMUTATION_OBJECTS) permstep.cpp $(CXX) -o $(@) $(@).cpp $(PERMUTATION_OBJECTS) $(CXXFLAGS) $(LIBS) vbpermmat: $(PERMUTATION_OBJECTS) vbpermmat.cpp $(CXX) -o $(@) $(@).cpp $(PERMUTATION_OBJECTS) $(CXXFLAGS) $(LIBS) vbregress: vbregress.o $(VBLIBS) $(CXX) -o vbregress vbregress.o $(CXXFLAGS) $(LIBS) # THE TOPLEVEL OBJECTS koshutil.o: koshutil.cpp koshutil.h $(CXX) -c koshutil.cpp $(CXXFLAGS) utils.o: utils.cpp utils.h $(CXX) -c utils.cpp $(CXXFLAGS) calc_gs_ps.o: calc_gs_ps.cpp calc_gs_ps.h $(VBLIBS) $(CXX) -c calc_gs_ps.cpp $(CXXFLAGS) timeseries.o: timeseries.cpp timeseries.h $(CXX) -c timeseries.cpp $(CXXFLAGS) regression.o: regression.cpp regression.h $(CXX) -c regression.cpp $(CXXFLAGS) vbregress.o: vbregress.cpp $(CXX) -c vbregress.cpp $(CXXFLAGS) time_series_avg.o: time_series_avg.cpp time_series_avg.h $(CXX) -c time_series_avg.cpp $(CXXFLAGS) perm.o: perm.cpp perm.h $(CXX) -c perm.cpp $(CXXFLAGS) voxbo-1.8.5~svn1246/stand_alone/assembleps.cpp000066400000000000000000000122101153177201300212510ustar00rootroot00000000000000 // assembleps.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee #include #include "regression.h" #include "vb_common_incs.h" using namespace std; void usage(const unsigned short exitValue, char *progName); /********************************************************************* * This program assembles the partial ref files. * *********************************************************************/ int main(int argc, char *argv[]) { SEGV_HANDLER string matrixStemName; if (argc == 1) usage(1, argv[0]); /********************************************************************* * Now processing the command line options. * * * * -h ==> Display usage information. * * -m ==> Specifies the matrix stem name. * * -s ==> Specifies the number of step for the regression. * * -v ==> Print out the gobal VoxBo version number. * * * * VARIABLES: * * printHelp - a flag, used to determine if the "-h" command line * * option was used or not. * * printVersion - a flag, used to determine if the "-v" command line * * option was used or not. * * numSteps - the number of total regression steps. * *********************************************************************/ unsigned long numSteps = 0; arghandler a; a.setArgs("-h", "--help", 0); a.setArgs("-m", "--matrixstemname", 1); a.setArgs("-s", "--steps", 1); a.setArgs("-v", "--version", 0); a.parseArgs(argc, argv); string errstring = a.badArg(); if (errstring.size()) { errstring = "[E] unknown flag: " + errstring; printErrorMsg(VB_ERROR, errstring.c_str()); exit(-1); } if (a.flagPresent("-h")) usage(0, argv[0]); matrixStemName = a.getFlaggedArgs("-m")[0]; numSteps = atoi(a.getFlaggedArgs("-s")[0].c_str()); if (numSteps == 0) numSteps = atoi(a.getFlaggedArgs("-s")[0].c_str()); if (a.flagPresent("-v")) printf("\nVoxBo v%s\n",vbversion.c_str()); if (matrixStemName.size() == 0) { ostringstream errorMsg; errorMsg << "Must specify the matrix stem name, using the \"-m\" option."; printErrorMsgAndExit(VB_ERROR, errorMsg, 1); } if (numSteps == 0) { ostringstream errorMsg; errorMsg << "Number of regression steps [" << numSteps << "] must be a positive integer."; printErrorMsgAndExit(VB_ERROR, errorMsg, 1); } assembleResidualPS(matrixStemName, numSteps); return 0; } /********************************************************************* * This function calls genusage() to print out the usage information. * * * * INPUTS: * * ------- * * progName: String holding the program name. * * * * OUTPUTS: * * -------- * * None. * *********************************************************************/ void usage(const unsigned short exitValue, char *progName) { printf("\nVoxBo assembleps (v%s)\n",vbversion.c_str()); printf("summary: "); printf(" This program assembles the partial ref files.\n"); printf("usage:\n"); printf(" assembleps -h -m[matrix stem name] -s[number of steps] -e -v\n"); printf("flags:\n"); printf(" -h Print usage information. Optional.\n"); printf(" -m Specify the matrix stem name. Required.\n"); printf(" -s The total number of regression steps.\n"); printf(" Must be a positive integer. Required.\n"); printf(" -v Global VoxBo version number. Optional.\n\n"); exit(-1); } voxbo-1.8.5~svn1246/stand_alone/calc_gs_ps.cpp000066400000000000000000000610031153177201300212140ustar00rootroot00000000000000 // calc_gs_ps.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee using namespace std; /********************************************************************* * This file implements the classes for CalcGS and CalcPs. * *********************************************************************/ #include "calc_gs_ps.h" const string CalcGs::gsHeader1 = ";VB98\n;REF1\n;\n; Global signal calculated from "; const string CalcGs::gsHeader2 = "\n; on "; const string CalcGs::gsHeader3 = "\n;\n; This is the average of all (brain) voxel time-series\n; normalized to have unit variance.\n;\n"; CalcGs::CalcGs(const string& tFile) { this->init(tFile); } CalcGs::CalcGs(const char *tFile) { this->init(tFile); } CalcGs::CalcGs(const CalcGs& c) { this->gsFile = c.gsFile; this->unitVar = c.unitVar; this->oldMean = c.oldMean; this->oldStdDev = c.oldStdDev; this->sigArr = c.sigArr; this->gsTes = c.gsTes; this->gsTSeries = c.gsTSeries; this->timeStr = c.timeStr; } void CalcGs::init(const string& tFile) { this->gsTes = Tes(tFile); if (!this->gsTes.data_valid) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] The input 4D data file [" << tFile << "] has invalid data."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } /********************************************************************* * Now we have to add the current date and time to the header that * * will be written to the gsFile (the output file). For example, if * * if this program was invoked on a 4D data file on May 24, 1998 * * 16:28:47, we need to add the following line to the header: * * * * Sun_May_24_16:28:47_1998 * * * *********************************************************************/ this->timeStr=timedate(); /********************************************************************* * The header of the output file must resemble the following: * * * * ;VB98 * * ;REF1 * * ; * * ; Global signal calculated from lattin02/lattin02.tes * * ; on Mon_Feb_26_15:45:49_2001 * * ; * * ; This is the average of all (brain) voxel time-series * * ; normalized to have unit variance. * * ; * * * * * * * * (NOTE: The preceding 3 blank lines are a part of the header.) * * The 2 variable parts of the header are the subdirectory and 4D data* * file name, e.g., "lattin02/lattin02.tes" and the date and time of * * when this class was instantiated (which roughly matches the date * * and time of when a program using this class was invoked), e.g., * * "Mon_Feb_26_15:45:49_2001". The 3 constant parts of the headers * * are: * * 1. From the first character of the header to the space character * * immediately before the subdirectory and 4D data file name. This * * is what the static data member gsHeader1 has been set to. * * 2. The character immediately after the subdirectory and 4D data * * file name to the space character immediately before the date and* * time. The static data member gsHeader2 has been assigned to * * this part. * * 3. The new line immediately after the date and time to the new * * line that defines the last line (which, in fact is blank) of * * the header. The static data member gsHeader3 has been assigned * * this part. * * * * We have already calculated the date and time. Now we need to * * figure out the subdirectory and file name. * * * * The GS output file name will consist of the 4D data file name * * (without the ".tes" part) concatenated with "_GS.ref". * *********************************************************************/ this->gsFile = xdirname(tFile) + "/" + xfilename(xrootname(tFile)) + "_GS.ref"; this->unitVar = false; this->gsTSeries = Tes(this->gsTes.filename); this->oldMean = 0.0; this->oldStdDev = 0.0; } CalcGs::~CalcGs() { } string CalcGs::getTesFile() const { return this->gsTes.filename; } string CalcGs::getGsFile() const { return this->gsFile; } void CalcGs::getSignals() { this->sigArr.resize(this->gsTes.dimt); /********************************************************************* * Say we have: * * * * dimt = 3, dimx = dimy = dimz = 2 * * * * This then implies that the data member "data" (which is an array) * * of the object this->gsTes looks like the signal column: * * * * TIME, XYZ coord. SIGNAL VALUE * * ---------------- ------------ * * [t0 x0 y0 z0] ------> s0 * * [t1 x0 y0 z0] ------> s1 * * [t2 x0 y0 z0] ------> s2 * * * * [t0 x1 y0 z0] ------> s3 * * [t1 x1 y0 z0] ------> s4 * * [t2 x1 y0 z0] ------> s5 * * * * [t0 x0 y1 z0] ------> s6 * * [t1 x0 y1 z0] ------> s7 * * [t2 x0 y1 z0] ------> s8 * * * * [t0 x1 y1 z0] ------> s9 * * [t1 x1 y1 z0] ------> s10 * * [t2 x1 y1 z0] ------> s11 * * * * [t0 x0 y0 z1] ------> s12 * * [t1 x0 y0 z1] ------> s13 * * [t2 x0 y0 z1] ------> s14 * * * * [t0 x1 y0 z1] ------> s15 * * [t1 x1 y0 z1] ------> s16 * * [t2 x1 y0 z1] ------> s17 * * * * [t0 x0 y1 z1] ------> s18 * * [t1 x0 y1 z1] ------> s19 * * [t2 x0 y1 z1] ------> s20 * * * * [t0 x1 y1 z1] ------> s21 * * [t1 x1 y1 z1] ------> s22 * * [t2 x1 y1 z1] ------> s23 * * * * (Of course, if all the signal values are zero for a particular time* * series, then the time series does not get stored.) * * This then means that sigArr's length is 3 and we want to * * populate sigArr in the following way: * * * * sigArr[0] = s0 + s3 + s6 + s9 + s12 + s15 + s18 + s21 * * sigArr[1] = s1 + s4 + s7 + s10 + s13 + s16 + s19 + s22 * * sigArr[2] = s2 + s5 + s8 + s11 + s14 + s17 + s20 + s23 * * * * Each time series will be read in (for example, the signal values * * {s0, s1, s2} comprise the time series t0) and then added to the * * array this->sigArr. NOTE: This class' TimeSeries data member is * * used to read in the time series values. * *********************************************************************/ /********************************************************************* * A time series will be read into tempSigArr. We need to do some * * manipulation to the time series before it is added to this->sigArr * * and the manipulations will be carried out in signal. NOTE: The * * logic for processing time series is derived from the IDL * * procedure CalcGSPS, found in VoxBo_DataPrep.pro. Both tempSigArr * * and signal are now declared and their elements will all be zero. * *********************************************************************/ VB_Vector tempSigArr(this->gsTes.dimt); VB_Vector signal(this->gsTes.dimt); /********************************************************************* * The following while loop is used to retrieve each time series into * * tempSigArr and then the body of the while loop processes the * * signal values. The while loop will exit when zero is returned by * * this->gsTSeries.getCurrentTimeSeries(). * *********************************************************************/ while ( this->gsTSeries.getCurrentTimeSeries(tempSigArr.getData()) ) { signal += tempSigArr; double total = signal.getVectorSum() / (double ) this->gsTes.dimt; signal -= total; } signal /= this->gsTes.realvoxels; sigArr += signal; } /********************************************************************* * This method writes the *_GS.ref file. If for some reason, the time * * series signal values fail to be read from the 4D data file, 0 is * * returned. Otherwise, 1 is returned. * *********************************************************************/ int CalcGs::printGsData() { ofstream outFile(this->gsFile.c_str()); if (!outFile) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] Unable to open [" << this->gsFile << "] to write header."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 7); } if (this->unitVar) { outFile << CalcGs::gsHeader1 << xdirname(this->gsTes.filename) << "/" << xfilename(this->gsTes.filename) << CalcGs::gsHeader2 << this->timeStr << CalcGs::gsHeader3; outFile << "; stdev " << oldStdDev << endl; outFile << "; mean " << oldMean << endl << endl << endl; } else { outFile << CalcGs::gsHeader1 << xdirname(this->gsTes.filename) << "/" << xfilename(this->gsTes.filename) << CalcGs::gsHeader2 << this->timeStr << "\n;\n; This is the average of all (brain) voxel time-series\n; not normalized to have unit variance.\n;\n\n\n"; } if (this->sigArr.getLength() == 0) this->getSignals(); if (this->sigArr.getLength() > 0) { outFile << setprecision(GS_PRECISION); for (int i = 0; i < this->gsTes.dimt; i++) { outFile.width(FIELD_WIDTH); outFile << this->sigArr[i] << endl; } outFile.close(); return (1); } return (0); } /********************************************************************* * This method normalizes this->sigArr to have unit variance. If for * * some reason, the signal values fail to be retrieved from the 4D * * data file, 0 is returned. Otherwise, 1 is returned. * *********************************************************************/ int CalcGs::normalizeVariance() { if (this->sigArr.getLength() == 0) this->getSignals(); double stanDev = sqrt(this->sigArr.getVariance()); this->oldStdDev = stanDev; this->oldMean = this->sigArr.getVectorMean(); if (this->sigArr.getLength() > 0) { this->sigArr.unitVariance(); this->unitVar = true; return (1); } return (0); } const string CalcPs::psHeader1 = ";VB98\n;REF1\n;\n; Grand mean power spectrum calculated from "; const string CalcPs::psHeader2 = "\n; on "; const string CalcPs::psHeader3 = "\n;\n; This is the average of all (brain) voxel power-spectra\n;\n\n\n"; CalcPs::CalcPs(const string& tFile) { this->init(tFile); } CalcPs::CalcPs(const char *tFile) { this->init(tFile); } CalcPs::CalcPs(const CalcPs& c) { this->tesFile = c.tesFile; this->psFile = c.psFile; this->sigArr = c.sigArr; this->timeStr = c.timeStr; this->psTes = c.psTes; this->psTSeries = c.psTSeries; } void CalcPs::init(const string& tFile) { this->tesFile = tFile; this->psTes = Tes(tFile); if (!this->psTes.data_valid) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] The input 4D data file [" << tFile << "] could not be read."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } /********************************************************************* * Now we have to add the current date and time to the header that * * will be written to the psFile (the output file). For example, if * * if this program was invoked on a 4D data file on May 24, 1998 * * 16:28:47, we need to add the following line to the header: * * * * Sun_May_24_16:28:47_1998 * * * *********************************************************************/ this->timeStr=timedate(); /********************************************************************* * The header of the output file must resemble the following: * * * * ;VB98 * * ;REF1 * * ; * * ; Grand mean power spectrum calculated from lattin02/lattin02.tes * * ; on Mon_Feb_26_15:45:49_2001 * * ; * * ; This is the average of all (brain) voxel power-spectra * * ; * * * * * * * * (NOTE: The preceding 3 blank lines are a part of the header.) * * The 2 variable parts of the header are the subdirectory and 4D data* * file name, e.g., "lattin02/lattin02.tes" and the date and time of * * when this class was instantiated (which roughly matches the date * * and time of when a program using this class was invoked), e.g., * * "Mon_Feb_26_15:45:49_2001". The 3 constant parts of the headers * * are: * * 1. From the first character of the header to the space character * * immediately before the subdirectory and 4D data file name. This * * is what the static data member psHeader1 has been set to. * * 2. The character immediately after the subdirectory and 4D data * * file name to the space character immediately before the date and* * time. The static data member psHeader2 has been assigned to * * this part. * * 3. The new line immediately after the date and time to the new * * line that defines the last line (which, in fact is blank) of * * the header. The static data member psHeader3 has been assigned * * this part. * * * * We have already calculated the date and time. Now we need to * * figure out the subdirectory and file name. * *********************************************************************/ /********************************************************************* * The output file name will consist of the 4D data file name (without* * the ".tes" part) concatenated with "_PS.ref". * *********************************************************************/ this->psFile = xdirname(tFile) + "/" + xfilename(xrootname(tFile)) + "_PS.ref"; this->psTSeries = TimeSeries(this->tesFile); } CalcPs::~CalcPs() { } string CalcPs::getTesFile() const { return this->psTes.filename; } string CalcPs::getPsFile() const { return this->psFile; } void CalcPs::getSignals() { /********************************************************************* * Now resizing the vector that will hold the Grand Mean Power * * Spectrum. Then the array is initialized to all zeros. * *********************************************************************/ this->sigArr.resize(this->psTes.dimt); /********************************************************************* * A time series will be read into tempSigArr. We need to do some * * manipulation to the time series before it is added to * * this->sigArr and the manipulations will be carried out in * * signal. NOTE: The logic for processing time series is derived * * from the IDL procedure CalcPSPS, found in VoxBo_DataPrep.pro. The * * data member this->psTSeries is used to retrieve each of the time * * series. Both tempSigArr and signal are declared and all of their * * elements will be zero. * *********************************************************************/ VB_Vector tempSigArr(this->psTes.dimt); VB_Vector signal(this->psTes.dimt); /********************************************************************* * The following while loop is used to retrieve each time series. The * * body of the while loop processes the signal values in a time * * series. * *********************************************************************/ while ( this->psTSeries.getCurrentTimeSeries(tempSigArr.getData()) ) { double total = tempSigArr.getVectorSum() / (double ) this->psTes.dimt; tempSigArr -= total; signal = tempSigArr; this->getPowerSpectrum(signal); signal /= (double ) this->psTes.realvoxels; this->sigArr += signal; } } /********************************************************************* * This method writes the *_PS.ref file. If for some reason, the time * * series signal values fail to be read from the 4D data file, 0 is * * returned. Otherwise, 1 is returned. * *********************************************************************/ int CalcPs::printPsData() { ofstream outFile(this->psFile.c_str()); if (!outFile) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] Unable to open [" << this->psFile << "] to write header."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 7); } outFile << CalcPs::psHeader1 << xdirname(this->psTes.filename) << "/" << xfilename(this->psTes.filename) << CalcPs::psHeader2 << this->timeStr << CalcPs::psHeader3; if (this->sigArr.getLength() == 0) this->getSignals(); if (this->sigArr.getLength() > 0) { outFile << setprecision(GS_PRECISION); for (int i = 0; i < this->psTes.dimt; i++) { outFile.width(FIELD_WIDTH); outFile << this->sigArr[i] << endl; } outFile.close(); return (1); } return (0); } /********************************************************************* * This method places the results from the computation: * * * * FFT(inputArr) * ComplexConjugate(FFT(inputArr)) * * * * (where "*" represents multiplication of corresponding elements * * from the two arrays) into inputArr[]. The above computation is * * carried out by the following steps: * * * * 1. FFT of inputArr[] which equals a vector of the form: * * * * a(1) + ib(1) * * a(2) + ib(2) * * a(3) + ib(3) * * . * * . * * . * * a(n) + ib(n), where i = sqrt(-1). * * * * 2. Note that the complex conjugate of the above vector is: * * * * a(1) - ib(1) * * a(2) - ib(2) * * a(3) - ib(3) * * . * * . * * . * * a(n) - ib(n) * * * * 3. Now element by element multiplication of the vector from (1) * * and the vector from (2) is simply: * * * * a(1)^2 + b(1)^2 * * a(2)^2 + b(2)^2 * * a(3)^2 + b(3)^2 * * . * * . * * . * * a(n)^2 + b(n)^2 * * * * Each element is the square of the modulus of each complex * * number found in the vector from step (1). * * * * INPUTS: * * -------------------------------------------------------------------* * inputArr - pointer to an array of floats. * *********************************************************************/ void CalcPs::getPowerSpectrum(VB_Vector& inputArr) { VB_Vector realPart(inputArr.getLength()); VB_Vector imagPart(inputArr.getLength()); inputArr.fft(realPart, imagPart); realPart.elementByElementMult(realPart); imagPart.elementByElementMult(imagPart); inputArr = realPart + imagPart; } voxbo-1.8.5~svn1246/stand_alone/calc_gs_ps.h000066400000000000000000000170431153177201300206660ustar00rootroot00000000000000 // calg_gs_ls.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee #ifndef CALC_GS_PS_H #define CALC_GS_PS_H /********************************************************************* * This header file defines the classes CalcGs and CalcPs. * *********************************************************************/ #include #include #include #include #include #include #include #include #include #include "vb_common_incs.h" #include "timeseries.h" const int FIELD_WIDTH = 13; const int GS_PRECISION = 7; class CalcGs { private: /********************************************************************* * DATA MEMBERS: * * ------------------------------------------------------------------ * * * * gsFile - name of the output GS file. * * gsTes - a Tes object, instantiated by using the 4D data file name. * * timeStr - a C++ string, used to hold the date and time of * * when the current CalcGs object was instantiated. * * sigArr - will hold the sum of the modified time series signal * * values. * * unitVar - if true, then the user has chosen for this->sigArr to * * have unit variance. * * gsTSeries - a TimeSeries object; used to process the signal values * * from the 4D data file. * * oldMean - if the user chose for the global spectrum to have unit * * variance, then the mean prior to making the power * * spectrum have unit variance will be stored in oldMean. * * oldStdDev - if the user chose for the global spectrum to have unit * * variance, then the standard deviation prior to making * * the power spectrum have unit variance will be stored * * in oldMean. * * gsHeader1 - first part of the header for the GS file. * * gsHeader2 - second part of the header for the GS file. * * gsHeader3 - third part of the header for the GS file. * *********************************************************************/ string gsFile; Tes gsTes; string timeStr; VB_Vector sigArr; bool unitVar; TimeSeries gsTSeries; double oldMean; double oldStdDev; static const string gsHeader1; static const string gsHeader2; static const string gsHeader3; /********************************************************************* * PRIVATE METHODS: * * ------------------------------------------------------------------ * * * * init() - initializes those data members not initialized by the * * regular constructors. * * getSignals() - gets the time series signal values from the 4D data * * file. * * getMeanForGS() - computes the mean of this->sigArr. * * getVarianceForGS() - computes the variance of this->sigArr. * *********************************************************************/ void init(const string& tFile); void getSignals(); public: CalcGs(const string& tFile); CalcGs(const char *tFile); CalcGs(const CalcGs& c); // Copy constructor. ~CalcGs(); string getGsFile() const; string getTesFile() const; /********************************************************************* * PUBLIC METHODS: * * ------------------------------------------------------------------ * * * * normalizeVariance() - normalizes this->sigArr to have unit * * variance. * * printGsData() - prints out the GS information to a file. * *********************************************************************/ int normalizeVariance(); int printGsData(); }; class CalcPs { private: /********************************************************************* * DATA MEMBERS: * * ------------------------------------------------------------------ * * * * tesFile - holds the name of the 4D data file whose PS is to be * * computed. * * psFile - name of the output PS file. * * psTes - A Tes object, instantiated by using the 4D data file name. * * timeStr - a C-style string, used to hold the date and time of * * when the current CalcPs object was instantiated. * * sigArr - will hold the Grand Mean Power Spectrum. * * psTSeries - A TimeSeries object; used to process the signal values * * from the 4D data file. * * psHeader1 - first part of the header for the PS file. * * psHeader2 - second part of the header for the PS file. * * psHeader3 - third part of the header for the PS file. * *********************************************************************/ string tesFile; string psFile; Tes psTes; string timeStr; VB_Vector sigArr; TimeSeries psTSeries; static const string psHeader1; static const string psHeader2; static const string psHeader3; /********************************************************************* * PRIVATE METHODS: * * ------------------------------------------------------------------ * * * * init() - initializes those data members not initialized by the * * regular constructors. * * getSignals() - gets the time series signal values from the 4D data * * file. * *********************************************************************/ void init(const string& tesFile); void getSignals(); void getPowerSpectrum(VB_Vector& inputArr); public: CalcPs(const string& tFile); CalcPs(const char *tFile); CalcPs(const CalcPs& c); // Copy constructor. ~CalcPs(); string getTesFile() const; string getPsFile() const; int printPsData(); }; #endif // CALC_GS_PS_H voxbo-1.8.5~svn1246/stand_alone/calcgs.cpp000066400000000000000000000142241153177201300203560ustar00rootroot00000000000000 // calcgs.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee /********************************************************************* * calcgs.cpp * * VoxBo CalcGS utility. * * K. Banerjee 03/06/2001 * * * * This program computes the Global Spectrum of the input 4D data * * file. * * * * INPUTS: * * ------- * * 4D data file name. Required. * * Flag to specify if the GS should have unit variance or not. * * Optional. * * * * OUTPUTS: * * -------- * * The Global spectrum is written to a file called *_GS.ref where * * "*" represents the input 4D data file name without the ".tes" * * extension. * *********************************************************************/ void usage(const unsigned short exitValue, char *progName); #include #include #include "calc_gs_ps.h" int main(int argc, char *argv[], char *[]) { SEGV_HANDLER /********************************************************************* * VARIABLES: TYPE: DESCRIPTION: * * ---------- ----- ------------ * * unitVar bool TRUE if the user wants the GS to have * * unit variance. * * printHelp bool Will be set to TRUE is the user omits * * required options or wants usage * * information printed out. * * printVersion bool Will be set to TRUE is the user wants * * the global VoxBo version printed. * *********************************************************************/ bool unitVar = false; string tesFile; if (argc == 1) usage(1, argv[0]); /********************************************************************* * Now processing the command line options. * * * * -h ==> Display usage information. * * -i ==> Specifies the input 4D data file. * * -u ==> The unit variance flag. * * -v ==> Print global VoxBo version. * *********************************************************************/ arghandler a; a.setArgs("-h", "--help", 0); a.setArgs("-i", "--inputfile", 1); a.setArgs("-u", "--unitvariance", 1); a.setArgs("-v", "--version", 0); a.parseArgs(argc, argv); string errstring = a.badArg(); if (errstring.size()) { errstring = "[E] unknown flag: " + errstring; printErrorMsg(VB_ERROR, errstring.c_str()); exit(-1); } if (a.flagPresent("-h")) usage(0, argv[0]); tesFile = a.getFlaggedArgs("-i")[0]; unitVar = atoi(a.getFlaggedArgs("-u")[0].c_str()); if (a.flagPresent("-v")) printf("\nVoxBo v%s\n",vbversion.c_str()); if (tesFile.size() == 0) { cerr << "ERROR: Must specify the input 4D data file name." << endl; usage(1, argv[0]); } CalcGs myGs(tesFile); if (unitVar) { myGs.normalizeVariance(); } myGs.printGsData(); return 0; } /********************************************************************* * This function calls genusage() to write out the usage information. * * * * INPUTS: * * ------- * * exitValue: The desired exit value. * * progName: String holding the program name. * * * * OUTPUTS: * * -------- * * None. * *********************************************************************/ void usage(const unsigned short, char *) { printf("\nVoxBo calcgs (v%s)\n",vbversion.c_str()); printf("summary: "); printf(" Calc GS routine for VoxBo.\n"); printf("usage:\n"); printf(" calcgs -h -i[4D data file name] -u -v\n"); printf("flags:\n"); printf(" -h Print usage information. Optional.\n"); printf(" -i <4D data file> Specify the input 4D data file. Required.\n"); printf(" -u Unit variance flag for GS. Optional.\n"); printf(" -v Global VoxBo version number. Optional.\n\n"); exit(-1); } voxbo-1.8.5~svn1246/stand_alone/calcps.cpp000066400000000000000000000101201153177201300203560ustar00rootroot00000000000000 // calcps.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee /********************************************************************* * calcps.cpp * * VoxBo CalcPS utility. * * K. Banerjee 03/06/2001 * * * * This program computes the Grand Mean Power Spectrum of the input * * 4D data file. * * * * INPUTS: * * ------- * * 4D data file name. Required. * * * * OUTPUTS: * * -------- * * The Power spectrum is written to a file called *_PS.ref where * * "*" represents the input 4D data file name without the ".tes" * * extension. * *********************************************************************/ void usage(const unsigned short exitValue, char *progName); #include "calc_gs_ps.h" int main(int argc, char *argv[]) { SEGV_HANDLER string tesFile; if (argc == 1) usage(1, argv[0]); /********************************************************************* * Now processing the command line options. * * -h ==> Display usage information. * * -i ==> Specifies the input 4D data file. * * -v ==> Print global VoxBo version. * *********************************************************************/ arghandler a; a.setArgs("-h", "--help", 0); a.setArgs("-i", "--inputfile", 1); a.setArgs("-v", "--version", 0); a.parseArgs(argc, argv); string errstring = a.badArg(); if (errstring.size()) { errstring = "[E] unknown flag: " + errstring; printErrorMsg(VB_ERROR, errstring.c_str()); exit(-1); } if (a.flagPresent("-h")) usage(0, argv[0]); tesFile = a.getFlaggedArgs("-i")[0]; if (a.flagPresent("-v")) printf("\nVoxBo v%s\n",vbversion.c_str()); if (tesFile.length() == 0) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] Must specify the input 4D data file name."; printErrorMsg(VB_ERROR, errorMsg.str()); usage(1, argv[0]); } CalcPs myPs(tesFile); myPs.printPsData(); return 0; } void usage(const unsigned short, char *) { printf("\nVoxBo calcps (v%s)\n",vbversion.c_str()); printf("summary: "); printf(" Calc PS routine for VoxBo.\n"); printf("usage:\n"); printf(" calcps -h -i[4D data file name] -v\n"); printf("flags:\n"); printf(" -h Print usage information. Optional.\n"); printf(" -i <4D data file> Specify the input 4D data file. Required.\n"); printf(" -v Global VoxBo version number. Optional.\n\n"); exit(-1); } voxbo-1.8.5~svn1246/stand_alone/comptraces.cpp000066400000000000000000000067041153177201300212660ustar00rootroot00000000000000 // comptraces.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee #include #include "regression.h" #include "vb_common_incs.h" using namespace std; void usage(const unsigned short exitValue, char *progName); int main(int argc, char *argv[]) { SEGV_HANDLER string matrixStemName; if (argc == 1) usage(1, argv[0]); /********************************************************************* * Now processing the command line options. * * * * -h ==> Display usage information. * * -m ==> Specifies the matrix stem name. * * -v ==> Print out the gobal VoxBo version number. * * * * VARIABLES: * * printHelp - a flag, used to determine if the "-h" command line * * option was used or not. * * printVersion - a flag, used to determine if the "-v" command line * * option was used or not. * *********************************************************************/ arghandler a; a.setArgs("-h", "--help", 0); a.setArgs("-m", "--matrixstemname", 1); a.setArgs("-v", "--version", 0); a.parseArgs(argc, argv); string errstring = a.badArg(); if (errstring.size()) { errstring = "[E] unknown flag: " + errstring; printErrorMsg(VB_ERROR, errstring.c_str()); exit(-1); } if (a.flagPresent("-h")) usage(0, argv[0]); matrixStemName = a.getFlaggedArgs("-m")[0]; if (a.flagPresent("-v")) printf("\nVoxBo v%s\n",vbversion.c_str()); if (matrixStemName.size() == 0) { ostringstream errorMsg; errorMsg << "Must specify the matrix stem name, using the \"-m\" option."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } computeTraces(matrixStemName); printf("[I] comptraces: success\n"); return 0; } void usage(const unsigned short, char *) { printf("\nVoxBo comptraces (v%s)\n",vbversion.c_str()); printf("summary: "); printf(" Write out the traces file for regression.\n"); printf("usage:\n"); printf(" comptraces -h -m[matrix stem name] -v\n"); printf("flags:\n"); printf(" -h Print usage information. Optional.\n"); printf(" -m Specify the matrix stem name. Required.\n"); printf(" -v Global VoxBo version number. Optional.\n\n"); exit(-1); } voxbo-1.8.5~svn1246/stand_alone/koshutil.cpp000066400000000000000000001405671153177201300207760ustar00rootroot00000000000000 // koshutil.cpp // stuff used only in stand_alone // Copyright (c) 1998-2003 by The VoxBo Development Team // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // code contributed by Kosh Banerjee and Thomas King using namespace std; #include "vbutil.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "koshutil.h" /********************************************************************* * This function is used to make sure that the input string fileName * * ends in ".tes". * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * fileName string string object holding the file * * name. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * N/A bool true is fileName ends in * * ".tes", false otherwise. * *********************************************************************/ bool validateTesFileName(const string fileName) { if ( (fileName.at(fileName.length() - 1) != 's') || (fileName.at(fileName.length() - 2) != 'e') || (fileName.at(fileName.length() - 3) != 't') || (fileName.at(fileName.length() - 4) != '.') ) { return false; } // if return true; } // bool validateTesFileName(const string fileName) /********************************************************************* * This function prints out usage information (to stderr) for a * * program and then exits with the specified exit value. It is meant * * to be called from a "main" program. All parameters for this * * function, except for the first, are meant to be C-style strings, * * i.e., "const char *". The first parameter is the desired exit * * value, the second parameter must be the program name (when called * * from a "main" program, just use argv[0] and progName must not be * * of type "const char *" but of type "char *" because basename() * * takes an argument of type "char *"), the third parameter should be * * a short description of the program, the fourth parameter should be * * a string with basic usage information, and the last parameter * * *must* be the empty string (""). The fifth through the * * penultimate parameters should be one line descriptions of each * * option used by the program. Here's an example call: * * * * genusage(1, argv[0], "-Adds two integers and displays the sum.", * * "-i[first integer] -j[second integer]", * * "-i Specify 1st int. Required.", * * "-j Specify 2nd int. Required.", * * ""); // Note the empty string as the last parameter. * * * * Here's is the output from the example call: * * * * main -Adds two integers and displays the sum. * * * * usage: main -i[first integer] -j[second integer] * * flags: * * -i Specify 1st int. Required. * * -j Specify 2nd int. Required. * *********************************************************************/ void genusage(const unsigned short exitValue, char *progName, const char *desc, const char *basicInfo, ...) { /********************************************************************* * A va_list variable is required to process the variable number of * * parameters used by this function. * *********************************************************************/ va_list argp; /********************************************************************* * str will point to parameters for this function. * *********************************************************************/ const char *str; /********************************************************************* * Calling va_start() to initialize argp to be used by va_arg() and * * va_end(). The second argument to va_start() must be the last known * * argument passed to this function. * *********************************************************************/ va_start(argp, basicInfo); /********************************************************************* * Now printing out the program name, its short description, and its * * basic usage information to stderr. * *********************************************************************/ cout << endl << xfilename(progName) << " "; cout << desc << endl << endl; cout << "usage: " << xfilename(progName) << " " << basicInfo << endl; cout << "flags:" << endl; /********************************************************************* * The following while loop is used to print out the one line * * descriptions of the options used by the program. Program flow will * * leave the while loop when the empty string is encountered. * *********************************************************************/ while ( (str = va_arg(argp, const char *)) ) { if (strlen(str) == 0) { break; } // if cout << str << endl; } // while /********************************************************************* * Now calling va_end() since we are done with processing the * * variable list of arguments. * *********************************************************************/ va_end(argp); /********************************************************************* * Now exiting from the program. * *********************************************************************/ exit(exitValue); } // void genusage(const unsigned short exitValue, char *progName, const char *desc, const char *basicInfo, ...) /********************************************************************* * This function processes the command line options passed to the * * main function. * * * * INPUTS: * * ------- * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * argc int argc from main. * * argv[] char ** argv[] from main. * * options char * The list of valid command line * * options, as a C-style string, * * e.g., ":ab:c:h". * * format char * A C-style string that specifies * * the type for each command line * * option. * * * * The allowable characters for the format string are: * * * * b ==> bool * * c ==> char * * C ==> unsigned char * * s ==> short * * u ==> unsigned short * * i ==> int * * I ==> unsigned int * * l ==> long * * L ==> unsigned long * * f ==> float * * d ==> double * * S ==> char[] (A C-style string) * * Z ==> C++ string object * * * * The remaining inputs to processOpts() are pointers to variables * * of the appropriate type. * * * * Say that options is ":ab:c:h". This means that the allowable * * command line options for main are "-a", "-b", "-c", and "-h", and * * further, options "-b" and "-c" require arguments. Therefore, the * * program could possibly be called from the command line as: * * * * myprog -a -b23 -c"ABCDEFG" -h * * * * For those command line options that do not require an argument * * ("-a" and "-h" above), they are treated as flags and are viewed by* * processOpts() as being boolean variables. Therefore, considering * * the above example, the "argument" for "-a" is of type bool, the * * argument for "-b" is of type short, the argument for "-c" is of * * type C-style string, and the "argument" for "-h" is also of type * * bool. This implies that the call to processOpts() must be: * * * * processOpts(argc, argv, ":ab:c:h", "bsSb", &my_bool1, &my_int, * * my_string, &my_bool2); * * * * where: * * my_bool1 - previously declared bool variable. * * my_int - previously declared short variable. * * my_string - previously declared char[] variable. * * my_bool2 - previously declared bool variable. * * * * NOTE: The options parameter to processOpts() is ":ab:c:h" and it * * implies that there are 4 distinct possible options for * * main(). This means that the parameter format must contain * * exactly 4 characters, and that the format parameter is then * * followed by 4 pointer variables. * * * * OUTPUTS: * * -------- * * The pointer input variables (those input variables after * * char *format) have values assigned to them, as determined from * * argv (by getopt()). * *********************************************************************/ void processOpts(int argc, char *argv[], const char *options, const char *format, ...) { /********************************************************************* * Declaring local variables of type pointer to each of the allowed * * primitive types (within the context of this function, a C-style * * string and a C++ string object, are considered a primitive types). * * Also, initializing each of these pointers to NULL, except for * * S_C_string, which is set to the empty string. * *********************************************************************/ bool *b_bool = NULL; char *c_char = NULL; unsigned char *C_unsigned_char = NULL; short *s_short = NULL; unsigned short *u_unsigned_short = NULL; int *i_int = NULL; unsigned int *I_unsigned_int = NULL; long *l_long = NULL; unsigned long *L_unsigned_long = NULL; float *f_float = NULL; double *d_double = NULL; string *cpp_string = NULL; char S_C_string[OPT_STRING_LENGTH]; memset (S_C_string, 0, OPT_STRING_LENGTH); /********************************************************************* * Now declaring an array of type optInfo structs to hold information * * about the command line options used by the program. Note that the * * length of the array is equal to the number of available options * * for the program, which also equals the length of char *format. * *********************************************************************/ optInfo optInfoArr[strlen(format)]; /********************************************************************* * optCount is used to count the number of options in char *options. * * Basically, this means count all the characters in char *options * * except ':'. These two numbers must be equal to each other. * *********************************************************************/ unsigned int optCount = 0; /********************************************************************* * The following for lop is used to count the number of options. The * * for loop is started at 1 (instead of 0) because the first character* * of char *options[] is always ':'. * *********************************************************************/ for (unsigned int i = 1; i < strlen(options); i++) { /********************************************************************* * If options[i] is not ':', then optCount is incremented. * *********************************************************************/ if (options[i] != ':') { optCount++; } // if } // for /********************************************************************* * If the number of options does not equal the number of format * * specifiers, then an error message is printed and this program * * exits. Here is an example when the number of options does not equal* * the number of format specifiers: * * * * char *options is: ":ab:c:" (number of options = 3) * * char *format is: "bfdS" (number of format specifiers = 4) * *********************************************************************/ if (optCount != strlen(format)) { ostringstream errorMsg; errorMsg << "FUNCTION [" << __FUNCTION__ << "]. The number of options [" << optCount << "] does not equal the number of format specifiers [" << strlen(format) << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); exit(1); } // if /********************************************************************* * The following for loop is used to initialize the the array * * optInfoArr[]. i is used to index the array and j is used to index * * char *options. Recall that the options string for getopt() always * * has ':' as the first character. This is why j is initialized to 1 * * and not zero. * *********************************************************************/ unsigned int j = 1; for (unsigned int i = 0; i < strlen(format); i++) { /********************************************************************* * Now assigning the name of the option, e.g., if char *options is * * ":a:bc:h", then the option names are 'a', 'b', 'c', and 'h', to the* * optName field. * *********************************************************************/ optInfoArr[i].optName = options[j]; /********************************************************************* * If j is less than (strlen(options) - 1), this means that options[j]* * is not the last character in char *options[]. Therefore, * * options[j+1] can be accessed. We want to access options[j+1] to see* * if it is ':', in which case, the option requires an argument. * *********************************************************************/ if ( (j < (strlen(options) - 1)) && (options[j+1] == ':') ) { optInfoArr[i].requiredArg = true; /********************************************************************* * Incrementing j because we know that the next character in * * char *options is ':'. * *********************************************************************/ j++; } // if else { /********************************************************************* * If program flow ends up here, then we know that an argument is not * * required for this option. * *********************************************************************/ optInfoArr[i].requiredArg = false; } // else /********************************************************************* * Incrementing j so the next character in char *options can be * * accessed. * *********************************************************************/ j++; /********************************************************************* * Now assigning the type information to the typeArg field and setting* * optPresent to the default value of false. * *********************************************************************/ optInfoArr[i].typeArg = format[i]; optInfoArr[i].optPresent = false; } // for i /********************************************************************* * A va_list variable is required to process the variable list of * * parameters used by this function. optChar will hold the output from* * getopt(). * *********************************************************************/ va_list ap; char optChar; /********************************************************************* * The following while loop is used to traverse argv and process the * * command line options for this program. After the last command line * * option is encountered, getopt() will return -1. * *********************************************************************/ while ((optChar = getopt(argc, argv, options)) != -1) { /********************************************************************* * If optChar is not a valid command line option, then an error * * message is printed out and then this program exits. * *********************************************************************/ if (!validateOptChar(optChar, options)) { printErrorMsg(VB_ERROR, "Invalid command line option used."); exit(1); } // if /********************************************************************* * Now optChar holds one of the command line parameters. The following* * for loop is used to determine which one. The array optInfoArr[] is * * traversed until the correct command line character is encountered. * *********************************************************************/ for (unsigned int i = 0; i < strlen(format); i++) { /********************************************************************* * If optInfoArr[i].optName is equal to optChar, then we have found * * the correct struct in the array optInfoArr[]. * *********************************************************************/ if (optInfoArr[i].optName == optChar) { /********************************************************************* * If optInfoArr[i].optName requires an argument, then go ahead and * * copy optarg into optInfoArr[i].optArg. * *********************************************************************/ if (optInfoArr[i].requiredArg) { optInfoArr[i].optArg = optarg; } // if /********************************************************************* * If program flow ends up here, then optInfoArr[i].optName does not * * require an argument. Therefore, optInfoArr[i].optName is treated * * as a flag, i.e., a boolean variable, and by default, it is set to * * true. * *********************************************************************/ else { optInfoArr[i].optArg = "true"; } // else /********************************************************************* * Since we have found the appropriate command line option in * * optInfoArr[], optInfoArr[i].optPresent is set to true. Also, we * * out of the preceding for loop. * *********************************************************************/ optInfoArr[i].optPresent = true; break; } // if } // for i } // while /********************************************************************* * The following for loop is used to print out the contents of * * optInfoArr[], used for debugging. Normally, it should be commented * * out. * *********************************************************************/ // for (int i = 0; i < strlen(format) ; i++)*/ // {*/ // printOptInfo(optInfoArr[i]);*/ // } // for i*/ /********************************************************************* * Calling va_start() to initialize ap to be used by va_arg() and * * va_end(). The second argument to va_start() must be the last known * * argument passed to this function. * *********************************************************************/ va_start(ap, format); /********************************************************************* * The following for loop is used to actually assign the proper values* * to the variable list of pointer parameters passed into this * * function. This for loop traverses optInfoArr[]. * *********************************************************************/ for (unsigned int i = 0; i < strlen(format); i++) { /********************************************************************* * If the option is actually present in argv, then go ahead and * * process it, i.e., determine its type and assign the option the * * appropriate value. * *********************************************************************/ /********************************************************************* * The following "if" is used to see if the option is actually * * present. If it is, then a switch block is used to process the * * option. * *********************************************************************/ if (optInfoArr[i].optPresent) { /********************************************************************* * The following switch block is used to determine the type of the * * command line option. * *********************************************************************/ switch(optInfoArr[i].typeArg) { case 'b': /********************************************************************* * This case block is for bool. va_arg(ap, bool *) will return the * * appropriate pointer to one of the boolean pointers from the * * variable list of parameters passed to this function and it gets * * stored in b_bool. Then b_bool is assigned true (which is the * * default for these types of "flag" variables). * *********************************************************************/ b_bool = va_arg(ap, bool *); (*b_bool) = true; break; case 'c': /********************************************************************* * This case block is for char. va_arg(ap, char *) will return the * * appropriate pointer to one of the char pointers from the * * variable list of parameters passed to this function and it gets * * stored in c_char. Then c_char is assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ c_char = va_arg(ap, char *); (*c_char) = optInfoArr[i].optArg[0]; break; case 'C': /********************************************************************* * This case block is for unsigned char. va_arg(ap, unsigned char *) * * will return the appropriate pointer to one of the unsigned char * * pointers from the variable list of parameters passed to this * * function and it gets stored in C_unsigned_char. Then * * C_unsigned_char is assigned assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ C_unsigned_char = va_arg(ap, unsigned char *); (*C_unsigned_char) = optInfoArr[i].optArg[0]; break; case 's': /********************************************************************* * This case block is for short. va_arg(ap, short *) will return the * * appropriate pointer to one of the short pointers from the * * variable list of parameters passed to this function and it gets * * stored in s_short. Then s_short is assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ s_short = va_arg(ap, short *); (*s_short) = (short) strtol(optInfoArr[i].optArg.c_str()); break; case 'u': /********************************************************************* * This case block is for unsigned short. va_arg(ap, unsigned short *)* * will return the appropriate pointer to one of the unsigned short * * pointers from the variable list of parameters passed to this * * function and it gets stored in u_unsigned_short. Then * * u_unsigned_short is assigned assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ u_unsigned_short = va_arg(ap, unsigned short *); (*u_unsigned_short) = (unsigned short) strtol(optInfoArr[i].optArg.c_str()); break; case 'i': /********************************************************************* * This case block is for int. va_arg(ap, int *) will return the * * appropriate pointer to one of the int pointers from the * * variable list of parameters passed to this function and it gets * * stored in i_int. Then i_int is assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ i_int = va_arg(ap, int *); (*i_int) = strtol(optInfoArr[i].optArg.c_str()); break; case 'I': /********************************************************************* * This case block is for unsigned int. va_arg(ap, unsigned int *) * * will return the appropriate pointer to one of the unsigned int * * pointers from the variable list of parameters passed to this * * function and it gets stored in I_unsigned_int. Then * * I_unsigned_int is assigned assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ I_unsigned_int = va_arg(ap, unsigned int *); (*I_unsigned_int) = (unsigned int) strtol(optInfoArr[i].optArg.c_str()); break; case 'l': /********************************************************************* * This case block is for long. va_arg(ap, long *) will return the * * appropriate pointer to one of the long pointers from the * * variable list of parameters passed to this function and it gets * * stored in l_long. Then l_long is assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ l_long = va_arg(ap, long *); (*l_long) = strtol(optInfoArr[i].optArg.c_str()); break; case 'L': /********************************************************************* * This case block is for unsigned long. va_arg(ap, unsigned long *) * * will return the appropriate pointer to one of the unsigned long * * pointers from the variable list of parameters passed to this * * function and it gets stored in L_unsigned_long. Then * * L_unsigned_long is assigned assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ L_unsigned_long = va_arg(ap, unsigned long *); (*L_unsigned_long) = (unsigned long) strtol(optInfoArr[i].optArg.c_str()); break; case 'f': /********************************************************************* * This case block is for float. va_arg(ap, float *) will return the * * appropriate pointer to one of the float pointers from the * * variable list of parameters passed to this function and it gets * * stored in f_float. Then f_float is assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ f_float = va_arg(ap, float *); (*f_float) = (float) atof(optInfoArr[i].optArg.c_str()); break; case 'd': /********************************************************************* * This case block is for double. va_arg(ap, double *) will return the* * appropriate pointer to one of the double pointers from the * * variable list of parameters passed to this function and it gets * * stored in d_double. Then d_double is assigned the value from * * optInfoArr[i].optArg[0]. * *********************************************************************/ d_double = va_arg(ap, double *); (*d_double) = (float) atof(optInfoArr[i].optArg.c_str()); break; case 'S': /********************************************************************* * This case block is for char[]. va_arg(ap, char *) will return the * * appropriate pointer to one of the char[] pointers from the * * variable list of parameters passed to this function. Then strcpy() * * is used to store optInfoArr[i].optArg in the char[] pointer. * *********************************************************************/ strcpy(va_arg(ap, char *), optInfoArr[i].optArg.c_str()); break; case 'Z': /********************************************************************* * This case block is for string. va_arg(ap, string *) will return * * the appropriate pointer to one of the string pointers from the * * variable list of parameters passed to this function and it gets * * stored in cpp_string. Then cpp_string is assigned * * string(optInfoArr[i].optArg). * *********************************************************************/ cpp_string = va_arg(ap, string *); (*cpp_string) = optInfoArr[i].optArg; break; default: ostringstream errorMsg; errorMsg << "FUNCTION [" << __FUNCTION__ << "]. Unknown primitive type for processOpts: [" << optInfoArr[i].typeArg << "] in option number [" << i << "]. Option name: [" << optInfoArr[i].optName << "] Exiting."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); break; } // switch } // if /********************************************************************* * If program flow ends up here, then the option is not present, so * * we need to skip over the corresponding variable in the variable * * list of arguments. * *********************************************************************/ else { (void ) va_arg(ap, void *); } // else } // for i /********************************************************************* * Now calling va_end() since we are done with processing the * * variable list of arguments. * *********************************************************************/ va_end(ap); } // void processOpts(int argc, char *argv[], char *options, char *format, ...) /********************************************************************* * This function is used to make sure that the input character opt * * appears in the list of characters pointed to by *options. If opt * * is not present in *options, then false is returned. Otherwise true * * is returned. * *********************************************************************/ bool validateOptChar(const char opt, const char *options) { for (unsigned int i = 0; i < strlen(options); i++) { if (opt == options[i]) { return true; } // if } // for i /********************************************************************* * If program flow ends up here, then opt is not present in options[].* * Therefore, false is returned. * *********************************************************************/ return false; } // bool validateOptChar(const char opt, const char *options) /********************************************************************* * This function uses the input regular expression to validate the * * input string. If the input regular expression matches the input * * string, then true is returned. Otherwise, false is returned. * * This function is derived from mygrep.c by: * * Ben Tindale * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * regularExp const char * The regular expression, as a * * C-style string. * * theString const char * The C-style string to be * * validated. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * true bool If the string is valid. * * false bool If the string is invalid. * *********************************************************************/ bool validateString(const char *regularExp, const char *theString) { /********************************************************************* * Declaring and clearing regex. regex will hold the "compiled" * * regular expression. * *********************************************************************/ regex_t regex; memset(®ex, 0, sizeof(regex_t)); /********************************************************************* * Now compiling the regular expression. err will hold the return * * value from the call to regcomp(). If err is not zero, then an error* * occurred. * *********************************************************************/ int err = 0; if ( (err = regcomp(®ex, regularExp, 0)) != 0 ) { /********************************************************************* * If program flow ends up here, then an error occurred when trying * * to compile the regular expression. The first call to regerror() is * * used to get the length of a NULL terminated C-style string * * sufficiently long enough to hold the error message. * *********************************************************************/ int len = regerror(err, ®ex, NULL, 0); /********************************************************************* * regexErr[] is used to hold the error message. regerror() is then * * called (for a second time) to populate regexErr[] with the error * * message. * *********************************************************************/ char regexErr[len]; regerror(err, ®ex, regexErr, len); /********************************************************************* * The regular expression compilation error message is printed out and* * then this program exits. * *********************************************************************/ ostringstream errorMsg; errorMsg << "Compiling regular expression: [" << regexErr << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); exit(1); } // if size_t no_sub = 1; regmatch_t *result; if((result = (regmatch_t *) malloc(sizeof(regmatch_t) * no_sub))==0) { perror("Unable to allocate memory for a regmatch_t."); exit(1); } // if if (regexec(®ex, theString, no_sub, result, REG_NOSUB) == 0) { regfree(®ex); return true; } // if regfree(®ex); return false; } // bool validateString(const char *regularExp, const char *theString) /********************************************************************* * This function uses the input regular expression to validate the * * input string. If the input regular expression matches the input * * string, then true is returned. Otherwise, false is returned. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * regularExp const char * The regular expression, as a * * C-style string. * * theString const string The string object to be * * validated. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * true bool If the string is valid. * * false bool If the string is invalid. * *********************************************************************/ bool validateString(const char *regularExp, const string theString) { /********************************************************************* * Returing the value of validateString(const char *, const char *). * *********************************************************************/ return validateString(regularExp, theString.c_str()); } // bool validateString(const char *regularExp, const string theString) /********************************************************************* * This function modifies the input C-style string with another * * C-style string meant to be used as a unique temporary file name. * * The last 6 characters of the input C-style string must be "XXXXXX".* * The sequence of "XXXXXX" are the characters that get modified to * * create a unique temporary file name. The input variable length is * * the length of the array tempFile[]. NOTE: The input variable length* * is *not* the string length of tempFile[]. Unpon success, 0 is * * returned. Otherwise, -1 is returned. * *********************************************************************/ int getTempFileName(char *tempFile, const size_t length) { /********************************************************************* * Declaring a needed integer constant. * *********************************************************************/ const size_t SIX = 6; /********************************************************************* * It is expected that the last 6 characters of tempFile[] are * * "XXXXXX". We now check to see if this is indeed the case. If not, * * then "XXXXXX" will be appended to tempFile[]. This assumes that * * tempFile[] has sufficient space remaining to append the 6 X's. * * * * last6[] is declared and cleared. Then the last 6 charactes from * * tempFile[] are copied to it, if the string length of tempFile is * * >= 6. * *********************************************************************/ char last6[SIX + 1]; memset(last6, 0, SIX + 1); if (strlen(tempFile) >= SIX) { strncpy(last6, tempFile + (strlen(tempFile) - SIX), SIX); } // if /********************************************************************* * Checking to see if the last 6 characters of tempFile[] are * * "XXXXXX". * *********************************************************************/ if (strcmp(last6, "XXXXXX") != 0) { /********************************************************************* * If tempFile[] has room for 6 more characters, then "XXXXXX" is * * appended to it. NOTE: This may result in tempFile[] having more * * then 6 X's at the end. * *********************************************************************/ if ( (strlen(tempFile) + SIX) < length ) { strcat(tempFile, "XXXXXX"); } // if /********************************************************************* * If program flow ends up here, then tempFile[] does not have room * * for 6 more characters. Therefore, an error message is sent to * * stderr and -1 is returned. * *********************************************************************/ else { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] File: [" << __FILE__ << "] Function: [" << __FUNCTION__ << "] Invalid tempFile [" << tempFile << "] for temporary file name. insufficient space to append \"XXXXXX\"."; printErrorMsg(VB_ERROR, errorMsg.str()); return -1; } // else } // if /********************************************************************* * errno is set to 0. If the call to mkstemp() has an error, errno * * will be set to the appropriate error code. * *********************************************************************/ errno = 0; /********************************************************************* * If an error occurs in mkstemp(), then -1 will be returned. In that * * case, an appropriate error message will be sent to stderr, as * * determined by strerror(). NOTE: mkstemp(), upon success, returns * * an open file descriptor and creates an empty file. The file * * descriptor is stored in fd. ALSO NOTE: If the user does not have * * write permission in the current directory, mkstemp() will fail. * *********************************************************************/ int fd = mkstemp(tempFile); if (fd == -1) { /********************************************************************* * The apropriate error message is sent to stderr. * *********************************************************************/ ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] File: [" << __FILE__ << "] Function: [" << __FUNCTION__ << "] Unable to create temporary file name from tempFile [" << tempFile << "] due to: [" << strerror(errno) << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); /********************************************************************* * Since an error occurred, -1 is returned. * *********************************************************************/ return -1; } // if /********************************************************************* * If program flow ends up here, then we were successful in * * creating a temporary file name. Therefore, the file is closed, * * deleted, and 0 is returned. If the call to unlink() results in an * * error, then an appropriate error message is sent to stderr. errno * * is set to zero. If unlink() has an error, errno will be set to a * * non-zero value, i.e., the appropriate error code. * *********************************************************************/ close(fd); errno = 0; if (unlink(tempFile) == -1) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] File: [" << __FILE__ << "] Function: [" << __FUNCTION__ << "] Unable to delete temporary file from tempFile [" << tempFile << "] due to: [" << strerror(errno) << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); } // if return 0; } // int getTempFileName(char *tempFile, const size_t length) /********************************************************************* * This function modifies the input string object so that it can be * * used as a tempoarary file name. * *********************************************************************/ int getTempFileName(string& tempFile) { /********************************************************************* * Declaring a needed constant. * *********************************************************************/ const int SIX = 6; /********************************************************************* * The C-style string part of tempFile will be copied to tempString[] * * since it is not directly modifiable. tempString[] is declared and * * then zeroed out. * *********************************************************************/ char tempString[tempFile.length() + 1 + SIX]; memset(tempString, 0, tempFile.length() + 1 + SIX); /********************************************************************* * The C-style string part of tempFile is copied to tempString[]. * *********************************************************************/ strcpy(tempString, tempFile.c_str()); /********************************************************************* * retValue is used to hold the return value from * * getTempFileName(char *, size_t). If retVal is non-zero, then we * * were unsuccessful in creating a unique temporary file name. * *********************************************************************/ int retValue = getTempFileName(tempString, tempFile.length() + 1 + SIX); /********************************************************************* * If retVal is 0, then tempString is assigned to tempFile. * *********************************************************************/ if (!retValue) { tempFile = tempString; } // if /********************************************************************* * Returning retVal. * *********************************************************************/ return retValue; } // int getTempFileName(string& tempFile) short getScreenCols() { return 72; } voxbo-1.8.5~svn1246/stand_alone/koshutil.h000066400000000000000000000110311153177201300204220ustar00rootroot00000000000000 // koshutil.h // walling off some kosh functions // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Dan Kimberg // substantial code merged in from Kosh Banerjee using namespace std; #ifndef KOSHUTIL_H #define KOSHUTIL_H #include #include #include #include #include #include #include // For getopt(). #include // For definition of struct winsize. #include // For definition of struct winsize. #include #include "vbutil.h" #include "tokenlist.h" #include "genericexcep.h" #include "vbversion.h" /********************************************************************* * Some misc. utility function prototypes. * *********************************************************************/ bool validateTesFileName(const string fileName); void genusage(const unsigned short exitValue, char *progName, const char *desc, const char *basicInfo, ...); void processOpts(int argc,char *argv[], const char *options, const char *format,...); bool validateOptChar(const char opt, const char *options); /********************************************************************* * Prototypes for validating a string using a regular expression. * *********************************************************************/ bool validateString(const char *regularExp, const char *theString); bool validateString(const char *regularExp, const string theString); /********************************************************************* * These functions modify the input style string with another string * * string meant to be used as a unique temporary file name. The last * * 6 characters of the input string must be "XXXXXX". * *********************************************************************/ int getTempFileName(char *tempFile, const size_t length); int getTempFileName(string& tempFile); /********************************************************************* * OPEN_SPATIAL_LOOPS is #define'd. * *********************************************************************/ #define OPEN_SPATIAL_LOOPS(X) for (int indexZ = 0; indexZ < (X).dimz; indexZ++) \ { \ for (int indexY = 0; indexY < (X).dimy; indexY++) \ { \ for (int indexX = 0; indexX < (X).dimx; indexX++) \ { /********************************************************************* * OPEN_SPATIAL_LOOPS_PTR is #define'd. * *********************************************************************/ #define OPEN_SPATIAL_LOOPS_PTR(X) for (int indexZ = 0; indexZ < (X)->dimz; indexZ++) \ { \ for (int indexY = 0; indexY < (X)->dimy; indexY++) \ { \ for (int indexX = 0; indexX < (X)->dimx; indexX++) \ { /********************************************************************* * CLOSE_SPATIAL_LOOPS is #define'd to close off the open braces from * * OPEN_SPATIAL_LOOPS. * *********************************************************************/ #define CLOSE_SPATIAL_LOOPS }}} /********************************************************************* * Template function for the maximum. * *********************************************************************/ template T max(T i, S j) { if (i >= (T ) j) { return i; } // if return (T ) j; } // template T max(T i, S j) /********************************************************************* * Template function for the minimum. * *********************************************************************/ template T min(T i, S j) { if (i <= (T ) j) { return i; } // if return (T ) j; } // template T min(T i, S j) #endif // KOSHUTIL_H voxbo-1.8.5~svn1246/stand_alone/makematk.cpp000066400000000000000000000066451153177201300207240ustar00rootroot00000000000000 // makematk.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee #include #include "regression.h" #include "vb_common_incs.h" using namespace std; void usage(const unsigned short exitValue, char *progName); int main(int argc, char *argv[]) { SEGV_HANDLER string matrixStemName; if (argc == 1) usage(1, argv[0]); /********************************************************************* * Now processing the command line options. * * * * -h ==> Display usage information. * * -m ==> Specifies the matrix stem name. * * -v ==> Print out the gobal VoxBo version number. * * * * VARIABLES: * * printHelp - a flag, used to determine if the "-h" command line * * option was used or not. * * printVersion - a flag, used to determine if the "-v" command line * * option was used or not. * *********************************************************************/ arghandler a; a.setArgs("-h", "--help", 0); a.setArgs("-m", "--matrixstemname", 1); a.setArgs("-v", "--version", 0); a.parseArgs(argc, argv); string errstring = a.badArg(); if (errstring.size()) { errstring = "[E] unknown flag: " + errstring; printErrorMsg(VB_ERROR, errstring.c_str()); exit(-1); } if (a.flagPresent("-h")) usage(0, argv[0]); matrixStemName = a.getFlaggedArgs("-m")[0]; if (a.flagPresent("-v")) printf("\nVoxBo v%s\n",vbversion.c_str()); if (matrixStemName.size() == 0) { ostringstream errorMsg; errorMsg << "Must specify the matrix stem name, using the \"-m\" option."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } makeMatrixK(matrixStemName); printf("[I] makematk: success\n"); return 0; } void usage(const unsigned short, char *) { printf("\nVoxBo makematk (v%s)\n",vbversion.c_str()); printf("summary: "); printf(" Make the K matrix.\n"); printf("usage:\n"); printf(" makematk -h -m[matrix stem name] -v\n"); printf("flags:\n"); printf(" -h Print usage information. Optional.\n"); printf(" -m Specify the matrix stem name. Required.\n"); printf(" -v Global VoxBo version number. Optional.\n\n"); exit(-1); } voxbo-1.8.5~svn1246/stand_alone/makematkg.cpp000066400000000000000000000072001153177201300210570ustar00rootroot00000000000000 // makematkg.cpp // Copyright (c) 1998-2002 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee #include #include "regression.h" #include "vb_common_incs.h" using namespace std; void usage(const unsigned short exitValue, char *progName); /********************************************************************* * This program finishes off Tes regression. * *********************************************************************/ int main(int argc, char *argv[]) { SEGV_HANDLER string matrixStemName; if (argc == 1) usage(1, argv[0]); /********************************************************************* * Now processing the command line options. * * * * -h ==> Display usage information. * * -m ==> Specifies the matrix stem name. * * -v ==> Print out the gobal VoxBo version number. * * * * VARIABLES: * * printHelp - a flag, used to determine if the "-h" command line * * option was used or not. * * printVersion - a flag, used to determine if the "-v" command line * * option was used or not. * *********************************************************************/ arghandler a; a.setArgs("-h", "--help", 0); a.setArgs("-m", "--matrixstemname", 1); a.setArgs("-v", "--version", 0); a.parseArgs(argc, argv); string errstring = a.badArg(); if (errstring.size()) { errstring = "[E] unknown flag: " + errstring; printErrorMsg(VB_ERROR, errstring.c_str()); exit(-1); } if (a.flagPresent("-h")) usage(0, argv[0]); matrixStemName = a.getFlaggedArgs("-m")[0]; if (a.flagPresent("-v")) printf("\nVoxBo v%s\n",vbversion.c_str()); if (matrixStemName.size() == 0) { ostringstream errorMsg; errorMsg << "Must specify the matrix stem name, using the \"-m\" option."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } makeMatrixKG(matrixStemName); printf("[I] makematkg: success.\n"); return 0; } void usage(const unsigned short, char *) { printf("\nVoxBo makematkg (v%s)\n",vbversion.c_str()); printf("summary: "); printf(" Make the KG matrix.\n"); printf("usage:\n"); printf(" makematkg -h -m[matrix stem name] -v\n"); printf("flags:\n"); printf(" -h Print usage information. Optional.\n"); printf(" -m Specify the matrix stem name. Required.\n"); printf(" -v Global VoxBo version number. Optional.\n\n"); exit(-1); } voxbo-1.8.5~svn1246/stand_alone/perm.cpp000066400000000000000000002207651153177201300200760ustar00rootroot00000000000000 // perm.cpp // // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee /********************************************************************* * Required include file. * *********************************************************************/ #include "perm.h" /********************************************************************* * This function sets up the permutation analysis. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * matrixStemName const string& The absolute path to the GLM * * directory prepended to the * * basename of the GLM directory. * * permDir const string& The permutation directory. * * method vb_orderperm or vb_signperm * * * OUTPUT VARIABLES: * * ----------------- * * The permutation matrix file is written out. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ int permStart(permclass pc) { struct stat st; string mypermdir=xdirname(pc.stemname)+"/"+pc.permdir; if (!(vb_direxists(mypermdir+"/iterations"))) { if (createfullpath(mypermdir)) return 207; if (createfullpath(mypermdir+"/iterations")) return 207; } rmdir_force(mypermdir+"/logs"); mkdir((mypermdir+"/logs").c_str(), 0755); // if there's already a matrix, we keep it, so we're done if (stat((mypermdir+"/permutations.mat").c_str(),&st)==0) return 0; VB_permtype method = pc.method; if (pc.stemname.empty()) return 200; if (pc.permdir.empty()) return 201; map > permHash; Tes paramTes; paramTes.ReadHeader(pc.stemname+".prm"); if (!paramTes.header_valid) return 202; const string gMatrixFile(pc.stemname + ".G"); if (!utils::isFileReadable(gMatrixFile)) return 203; VBMatrix gMatrix; if (gMatrix.ReadHeader(gMatrixFile)) return 204; const unsigned long orderG = gMatrix.m; unsigned long numPerms = MAX_PERMS; map >signHash; switch(method) { case vb_orderperm: { gsl_permutation *v = gsl_permutation_calloc(orderG); if (!v) return 205; if (orderG <= PERMUTATION_LIMIT) { numPerms = (size_t ) lrint(exp(gamma(orderG + 1))); do { inHash(permHash, v); } while (gsl_permutation_next(v) == GSL_SUCCESS); } else { inHash(permHash, v); initRNG(pc.rngseed); for (size_t i = 1; i < numPerms; i++) { randPerm(v); while (inHash(permHash, v)) randPerm(v); } freeRNG(); if (v) gsl_permutation_free(v); } } break; case vb_signperm: { short *signPerm = new short[orderG]; if (orderG <= SIGN_PERMUTATION_LIMIT) { numPerms = (1 << (orderG - 1)); for (size_t i = 0; i < numPerms; i++) { for (size_t j = 0; j < orderG; j++) signPerm[j] = (utils::getBit(i, j) * -2) + 1; inSignHash(signHash, signPerm, orderG); } } else { initRNG(pc.rngseed); for (size_t i = 0; i < numPerms; i++) { randSignPerm(signPerm, orderG); while (inSignHash(signHash, signPerm, orderG)) randSignPerm(signPerm, orderG); } freeRNG(); } if (signPerm) delete signPerm; signPerm = 0; } break; default: return 206; break; } VBMatrix permMat(orderG, numPerms); if (!permMat.rowdata) return 208; VB_Vector vec(orderG); size_t colIndex = 0; switch(method) { case vb_orderperm: { map >::iterator mItr; for (mItr = permHash.begin(); mItr != permHash.end(); mItr++) { for (size_t i = 0; i < mItr->second.size(); i++) { for (size_t k = 0; k < orderG; k++) vec[k] = mItr->second[i]->data[k]; permMat.SetColumn(colIndex, vec); colIndex++; } } freePermHash(permHash); } break; case vb_signperm: { map >::iterator mItr; for (mItr = signHash.begin(); mItr != signHash.end(); mItr++) { for (size_t i = 0; i < mItr->second.size(); i++) { for (size_t k = 0; k < orderG; k++) vec[k] = mItr->second[i][k]; if (orderG <= SIGN_PERMUTATION_LIMIT) permMat.SetColumn(rankSignPerm(mItr->second[i], orderG), vec); else { permMat.SetColumn(colIndex, vec); colIndex++; } } } freeSignHash(signHash); } break; default: break; } permMat.filename=mypermdir+"/permutations.mat"; if (permMat.WriteFile()) return 210; permMat.clear(); return 0; } VBMatrix createPermMatrix(int nperms,int ndata,VB_permtype method,uint32 rngseed) { VBMatrix permMat(ndata,nperms); VBMatrix errormat(1,1); if (!permMat.valid()) { permMat.clear(); return permMat; } map > permHash; map >signHash; gsl_permutation *v; short *signPerm; switch(method) { case vb_orderperm: v = gsl_permutation_calloc(ndata); if (!v) return errormat; if (ndata <= PERMUTATION_LIMIT) { nperms = (size_t ) lrint(exp(gamma(ndata + 1))); do { inHash(permHash, v); } while (gsl_permutation_next(v) == GSL_SUCCESS); } else { inHash(permHash, v); initRNG(rngseed); for (int i=1; i >::iterator mItr; for (mItr = permHash.begin(); mItr != permHash.end(); mItr++) { for (size_t i=0; isecond.size(); i++) { for (int k = 0; k < ndata; k++) vec[k] = mItr->second[i]->data[k]; permMat.SetColumn(colIndex, vec); colIndex++; } } freePermHash(permHash); } break; default: map >::iterator mItr; for (mItr = signHash.begin(); mItr != signHash.end(); mItr++) { for (size_t i = 0; i < mItr->second.size(); i++) { for (int k=0; ksecond[i][k]; if (ndata <= SIGN_PERMUTATION_LIMIT) permMat.SetColumn(rankSignPerm(mItr->second[i], ndata), vec); else { permMat.SetColumn(colIndex, vec); colIndex++; } } } freeSignHash(signHash); break; } return permMat; } /********************************************************************* * This function computes the factorial of the input non-negative * * integer. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * n const size_t The integer whose factorial is * * to be computed. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * n! size_t * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ size_t factorial(const size_t n) { /********************************************************************* * If n is 0 or 1, then we simply return 1. * *********************************************************************/ if (n <= 1) { return 1; } // if /********************************************************************* * If program flow ends up here, then n >= 2. * *********************************************************************/ else { /********************************************************************* * fact is initialized to 1. * *********************************************************************/ size_t fact = 1; /********************************************************************* * The following for loop is sued to compute the product: * * (2)(3)...(n) * *********************************************************************/ for (size_t i = 2; i <= n; i++) { fact *= i; } // for i /********************************************************************* * Now returning n!. * *********************************************************************/ return fact; } // else } // size_t factorial(const size_t n) /********************************************************************* * This function simply writes out the elements of the input GSL * * permutation. * *********************************************************************/ void printGSLPerm(const gsl_permutation *pi) { gsl_permutation_fprintf(stdout, pi, "%u "); cout << endl; } // void printGSLPerm(const gsl_permutation *pi) // pick a random permutation void randPerm(gsl_permutation *pi) { gsl_ran_shuffle (theRNG, pi->data, pi->size,sizeof(size_t)); } /********************************************************************* * This function simply increments the elements of the input * * permutation. * *********************************************************************/ void incPerm(gsl_permutation *pi) { for (size_t i = 0; i < pi->size; i++) { pi->data[i]++; } // for i } // void incPerm(gsl_permutation *pi) /********************************************************************* * This function returns true if the two input permutations are equal.* * Otherwise, false is returned. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * p1 const gsl_permutation * The first of the two * * permutations to be * * compared. * * p2 const gsl_permutation * The second of the two * * permutations to be * * compared. * * begin const size_t The index at which the * * comparison starts. The default * * value is 0. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * If the two permutations are equal, then true is returned. * * Otherwise, false is returned. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ bool arePermsEqual(const gsl_permutation *p1, const gsl_permutation *p2, const size_t begin) { /********************************************************************* * If the two input permutations are of different sizes, then false is* * returned. * *********************************************************************/ if (p1->size != p2->size) { return false; } // false /********************************************************************* * The following for loop is used to compare each element of the two * * input permutations, starting that the index begin. NOTE: Since we * * are comparing permutations, we only have to compare the elements * * up to, and including, index (p1->size - 2). * *********************************************************************/ for (size_t i = begin; i < (p1->size - 1); i++) { /********************************************************************* * If the two permutations elements are not equal, then false is * * returned. * *********************************************************************/ if (p1->data[i] != p2->data[i]) { return false; } // if } // for i /********************************************************************* * If program flow ends up here, then the two input permutations are * * equal. Therefore, true is returned. * *********************************************************************/ return true; } // bool arePermsEqual(const gsl_permutation *p1, // const gsl_permutation *p2, const size_t begin) /********************************************************************* * This function checks to see if the input permutation rank is valid * * or not. If the input rank is not valid, then an appropriate error * * message is printed and then this program exits. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * r const size_t The input permutation rank. * * n const size_t The size of the permutation. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void verifyPermRank(const size_t r, const size_t n) { /********************************************************************* * If now check to see if r is <= to (n! - 1) (since r must be in * * [0, 1, ..., n! - 1]). However, to avoid computing large numbers, * * we use the natural log function. Moreover, we compare log(r + 1) * * to log(n!) (which is given by gamma(n + 1)) knowing that log() is * * monotonically increasing. * *********************************************************************/ if ( log((double ) (r + 1)) > gamma((double ) (n + 1))) { ostringstream errorMsg; errorMsg << "The index of the desired permutation [" << r << "] is greater than (" << n << "! - 1)."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if } // void verifyPermRank(const size_t r, const size_t n) /********************************************************************* * This function computes the i'th permutation on n letters, where * * 0 <= i <= (n! - 1). This implementation is based on the paper: * * * * "Ranking and Unranking Permutations in Linear Time" by * * Wendy Myrvold (wendym@csr.uvic.ca) and * * Frank Ruskey (frusky@csr.uvic.ca) * * * * The computed permutation is saved to the input gsl_perumation * * struct. A valid permutation in a gsl_permutation struct means that * * each of the integers {0, 1, ..., n - 1} appears exactly once. The * * advantage of this function is that no factorials are computed; the * * disadvantage is that this function is recursive. * * * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * n const size_t The length of the permutation. * * r const size_t The index of the desired * * permutation. * * pi gsl_permutation * The struct into which the * * computed permutation is * * stored. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void unrank1(const size_t n, const size_t r, gsl_permutation *pi) { /********************************************************************* * If we are in the first call to this function, then n must equal * * pi->size. Therefore, we ensure that r <= (n! - 1). * *********************************************************************/ if (n == pi->size) { verifyPermRank(r, pi->size); } // if /********************************************************************* * Now recursively constructing the desired permutation. NOTE: The * * recursion stops when the input parameter n is 0. * *********************************************************************/ if (n) { gsl_permutation_swap(pi, n - 1, (r % n)); unrank1(n - 1, (r / n), pi); } // if } // void unrank1(const size_t n, const size_t r, gsl_permutation *pi) /********************************************************************* * This function computes the rank of the input permutation. This * * implementation is based on the paper: * * * * "Ranking and Unranking Permutations in Linear Time" by * * Wendy Myrvold (wendym@csr.uvic.ca) and * * Frank Ruskey (frusky@csr.uvic.ca) * * * * The advantage of this function is that no factorials are computed; * * the disadvantage is that this function is recursive. NOTE: In the * * first call to this function, pi must be the identity permutation. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * n const size_t The length of the permutation. * * pi gsl_permutation * The input permutation. * * piInv gsl_permutation * The inverse of the input * * permutation. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * The rank of the input permutation. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ size_t rank1(const size_t n, gsl_permutation *pi, gsl_permutation *piInv) { /********************************************************************* * If n is 1, we return 0, halting the recursion. * *********************************************************************/ if (n == 1) { return 0; } // if /********************************************************************* * We now recursively compute the rank of the input permutation pi. * *********************************************************************/ size_t s = pi->data[n - 1]; gsl_permutation_swap(pi, n - 1, piInv->data[n - 1]); gsl_permutation_swap(piInv, s, n - 1); return (s + (n * rank1(n - 1, pi, piInv))); } // size_t rank1(const size_t n, gsl_permutation *pi, // gsl_permutation *piInv) /********************************************************************* * This function checks to see if the input permutation already * * exists in the input permutation hash table or not. If the * * is not yet in the hash table, it is added to the hash table. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * permHash map > * * The input permutation hash * * table. * * pi const gsl_permutation * The input permutation. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * If the input permutation is not in the input permutation hash * * table, then false is returned. Otherwise, true is returned. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ bool inHash(map >&permHash, gsl_permutation *pi) { gsl_permutation *rho = NULL; if (permHash.count(pi->data[0]) == 0) { vector permVec; rho = gsl_permutation_alloc(pi->size); gsl_permutation_memcpy(rho, pi); permVec.push_back(rho); permHash.insert(pair >(pi->data[0], permVec)); return false; } for (size_t i = 0; i < permHash[pi->data[0]].size(); i++) if (arePermsEqual(pi, permHash[pi->data[0]][i], 1)) return true; rho = gsl_permutation_alloc(pi->size); gsl_permutation_memcpy(rho, pi); permHash[pi->data[0]].push_back(rho); return false; } void initRNG(uint32 rngseed) { gsl_rng_env_setup(); const gsl_rng_type *T; if (getenv("GSL_RNG_TYPE")) T = gsl_rng_default; else T = gsl_rng_taus113; theRNG = gsl_rng_alloc(T); if (rngseed==0) rngseed=VBRandom(); gsl_rng_set(theRNG,rngseed); } void freeRNG() { if (theRNG) gsl_rng_free(theRNG); } void availableGSLRNGs() { const gsl_rng_type **t, **t0; t0 = gsl_rng_types_setup(); cout << "AVAILABLE GSL RNG's:" << endl; for (t = t0; *t != NULL; t++) { cout << (*t)->name << endl; } // for t } // void availableGSLRNGs() /********************************************************************* * This function prints out the contents of the input map container, * * which is used has a hash table for a set of GSL permutations. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * theHash map >& * * The input map container. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void printHash(map >& theHash) { /********************************************************************* * An iterator is instantiated to the beginning of the map. * *********************************************************************/ map >::iterator mItr; /********************************************************************* * hashSize is initialized to 0. It will be used to cound up the * * number of GSL permutations in the input map. * *********************************************************************/ size_t hashSize = 0; /********************************************************************* * Printing out a separator line. * *********************************************************************/ cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; /********************************************************************* * The following for loop iterates through the map container. * *********************************************************************/ for (mItr = theHash.begin(); mItr != theHash.end(); mItr++) { /********************************************************************* * Incrementing hashSize. * *********************************************************************/ hashSize += mItr->second.size(); /********************************************************************* * This for loop iterates through the vector container pointed to by * * mItr. * *********************************************************************/ for (size_t i = 0; i < mItr->second.size(); i++) { /********************************************************************* * Now printing out the GSL permutation. * *********************************************************************/ printGSLPerm(mItr->second[i]); } // for i } // for mItr /********************************************************************* * Printing out the map size, hashSize, and a separator line to * * "close off" the printing of the map container. * *********************************************************************/ cout << "MAP SIZE = [" << theHash.size() << "]" << endl; cout << "HASH SIZE = [" << hashSize << "]" << endl; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; } // void printHash(map >& theHash) /********************************************************************* * This function frees the memory allocated to the gsl_permutation * * structs contained in the input map container. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * theHash map >& * * The input map container. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void freePermHash(map >& theHash) { map >::iterator mItr; for (mItr = theHash.begin(); mItr != theHash.end(); mItr++) for (size_t i = 0; i < mItr->second.size(); i++) if (mItr->second[i]) gsl_permutation_free(mItr->second[i]); } /********************************************************************* * This function returns true if the two input sign permutations are * * equal. Otherwise, false is returned. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * p1 const short * The first of the two sign * * permutations to be compared. * * p2 const short * The second of the two sign * * permutations to be compared. * * len const size_t The length of both input sign * * permutations. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * If the two permutations are equal, then true is returned. * * Otherwise, false is returned. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ bool areSignsEqual(const short *arr1, const short *arr2, const size_t len) { /********************************************************************* * If both arr1 and arr2 contain the same address, then true is * * returned. * *********************************************************************/ if (arr1 == arr2) { return true; } // if /********************************************************************* * The following for loop is used to compare the corresponding * * elements of the two sign permutations. * *********************************************************************/ for (size_t i = 0; i < len; i++) { /********************************************************************* * If the two corresponding elements are not equal, then false is * * returned. * *********************************************************************/ if (arr1[i] != arr2[i]) { return false; } // if } // for i /********************************************************************* * If program flow ends up here, then no differences were found * * between the two input sign permutations. Therefore, true is * * is returned. * *********************************************************************/ return true; } // bool areSignsEqual(const short *arr1, const short *arr2, const size_t len) /********************************************************************* * This function checks to see if the input short array of 1's and * * -1's (a sign permutation array) already exists in the input sign * * permutation hash table or not. If the short array is not yet in * * the hash table, it is added to the hash table. NOTE: The key used * * in the input map container, i.e., the input sign permutation hash * * table, is the sum of the elements of the sign permutation. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * signHash map > The input sign * * permutation hash * * table. * * * * pi short * The input sign permutation. * * * * len const size_t The length of the input sign * * permutation. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * If the input sign permutation is not in the input permutation hash * * table, then false is returned. Otherwise, true is returned. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ bool inSignHash(map > &signHash, short *pi, const size_t len) { /********************************************************************* * rho will be used to copy pi, if the need arises. * *********************************************************************/ short *rho = NULL; long sum=0; for (size_t i=0; i permVec; rho = new short[len]; if (!rho) { ostringstream errorMsg; errorMsg << "Unable to allocate memory for size [" << len << "] sign permutation."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if memcpy(rho, pi, sizeof(short) * len); permVec.push_back(rho); signHash.insert(pair >(sum, permVec)); return false; } // if /********************************************************************* * The following for loop is used to check each element of the * * signHash map container. The sum of the elements of pi is used as * * the key for the signHash map. So using the map's [] operator, we * * compare pi to each sign permutation in the map whose first element * * is the same as the sum of the elements of pi. * *********************************************************************/ for (size_t i = 0; i < signHash[sum].size(); i++) { /********************************************************************* * If pi equals the sign permutation itr->second[i], then true is * * returned. * *********************************************************************/ if (areSignsEqual(pi, signHash[sum][i], len)) { return true; } // if } // for /********************************************************************* * If program flow ends up here, then pi is not in the hash table. So * * we add pi to the hash table (at hash slot itr) and return false. * *********************************************************************/ rho = new short[len]; if (!rho) { ostringstream errorMsg; errorMsg << "Unable to allocate memory for size [" << len << "] sign permutation."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if memcpy(rho, pi, sizeof(short) * len); signHash[sum].push_back(rho); return false; } // bool inSignHash(map > &signHash, // short *pi, const size_t len) /********************************************************************* * This function frees the memory allocated to the sign permutations * * contained in the input map container. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * theHash map >& * * The input map container. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void freeSignHash(map >& theHash) { /********************************************************************* * An iterator is instantiated to the beginning of the map. * *********************************************************************/ map >::iterator mItr; /********************************************************************* * The following for loop iterates through the map container. * *********************************************************************/ for (mItr = theHash.begin(); mItr != theHash.end(); mItr++) { /********************************************************************* * This for loop iterates through the vector container pointed to by * * mItr. * *********************************************************************/ for (size_t i = 0; i < mItr->second.size(); i++) { /********************************************************************* * Now freeing the previously allocated memory. * *********************************************************************/ delete mItr->second[i]; mItr->second[i] = 0; } // for i } // for mItr } // void freeSignHash(map >& theHash) /********************************************************************* * This function prints out the contents of the input map container, * * which is used has a hash table for a set of sign permutations. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * theHash map >& * * The input map container. * * len const size_t The length of each sign * * permutation in the map * * container. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void printSignHash(map >& theHash, const size_t len) { /********************************************************************* * An iterator is instantiated to the beginning of the map. * *********************************************************************/ map >::iterator mItr; /********************************************************************* * hashSize is initialized to 0. It will be used to cound up the * * number of sign permutations in the input map. * *********************************************************************/ size_t hashSize = 0; /********************************************************************* * Printing out a separator line. * *********************************************************************/ cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; /********************************************************************* * The following for loop iterates through the map container. * *********************************************************************/ for (mItr = theHash.begin(); mItr != theHash.end(); mItr++) { /********************************************************************* * Incrementing hashSize. * *********************************************************************/ hashSize += mItr->second.size(); /********************************************************************* * This for loop iterates through the vector container pointed to by * * mItr. * *********************************************************************/ for (size_t i = 0; i < mItr->second.size(); i++) { /********************************************************************* * Now printing out the sign permutation. * *********************************************************************/ printSignPerm(mItr->second[i], len); } // for i } // for mItr /********************************************************************* * Printing out the map size, hashSize, and a separator line to * * "close off" the printing of the map container. * *********************************************************************/ cout << "MAP SIZE = [" << theHash.size() << "]" << endl; cout << "HASH SIZE = [" << hashSize << "]" << endl; cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; } // void printSignHash(map >& theHash, const size_t len) /********************************************************************* * This function prints out the input sign permutation. * *********************************************************************/ void printSignPerm(const short *thePerm, const size_t len) { /********************************************************************* * The following for loop is used to print out the values from * * thePerm. * *********************************************************************/ for (size_t i = 0; i < len; i++) { cout.width(2); cout.fill(' '); cout << thePerm[i]; if (i != (len - 1)) { cout << " "; } // if } // for i cout << endl; } // void printSignPerm(const short *thePerm, const size_t len) /********************************************************************* * This function constructs a random sign permutation and stores it * * in the input short array. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * pi short * The generated random sign * * permutation will be stored * * in this variable. * * len const size_t The length of the sign * * permutation. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void randSignPerm(short *pi, const size_t len) { /********************************************************************* * The following for loop is used to generate the random sign * * permutation. NOTE: The variable theRNG is a gloabl variable. * *********************************************************************/ for (size_t i = 0; i < len; i++) { /********************************************************************* * We use gsl_rng_uniform_int() to get a random integer in [0, 1]. * * The random inetegr is first multiplied by -2 and 1 is added. This * * will yield a random 1 or -1. * *********************************************************************/ pi[i] = (gsl_rng_uniform_int(theRNG, 2) * -2) + 1; } // for i } // void randSignPerm(short *pi, const size_t len) /********************************************************************* * This function determines the ran of the input sign permutation. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * signPerm const short * The sign permutation. * * len const size_t The length of the sign * * permutation. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * N/A size_t The rank of the input sign * * permutation. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ size_t rankSignPerm(const short *signPerm, const size_t len) { /********************************************************************* * The rank is initialized to 0. * *********************************************************************/ size_t rank = 0; /********************************************************************* * The following for loop traverses signPerm. * *********************************************************************/ for (size_t i = 0; i < len; i++) { /********************************************************************* * The following steps are carried out to compute the rank. * * * * 1. We view the sign permutation as a binary representation of an * * integer. * * 2. The 1's are viewed as zeros and the -1's are viewed as ones. * * 3. We then determine the rank by computing the integer represented * * by the sign permutation. * * * * EXAMPLE SIGN PERMUTATION RANK * * ----------------------------------------------------------------- * * [1, 1, 1] ==> ((2^0) * 0) + ((2^1) * 0) + ((2^2) * 0) = 0 * * [-1, 1, -1] ==> ((2^0) * 1) + ((2^1) * 0) + ((2^2) * 1) = 5 * * [-1, -1, -1] ==> ((2^0) * 1) + ((2^1) * 1) + ((2^2) * 1) = 7 * * * * If signPerm[i] is 1, we don't need to increment rank. Therefore, * * the following if block only adds the i'th power of 2 when * * signPerm is -1. * *********************************************************************/ if (signPerm[i] == -1) { rank += (1 << i); } // if } // for i /********************************************************************* * Now returning the rank. * *********************************************************************/ return rank; } // size_t rankSignPerm(const short *signPerm, const size_t len) /********************************************************************* * This function performs a single step of a permutation analysis. * * Specifically, the following tasks are carried out: * * * * 1. Loads the permutation matrix. * * 2. Reads the appripriate GLM files. * * 3. Does a regression to create a new *.prm files for the * * particualr permutation. * * 4. Calls makeStatCub() to create a statistical image for that * * *.prm file. * * 5. Stores the appripriate maximum value for that image. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * matrixStemName const string& The matrix stem name. * * * * permDir const string& The permutation directory. * * * * permIndex const unsigned The permutation index. * * short * * * * method VB_permtype * * * contrasts VB_Vector& The contrast array. * * * * scale const unsigned Inidcates the type of statistic * * short that will be computed. * * * * pseudoT VB_Vector& If the number of elements in * * this VB_Vector object is 3, then the * * error cube will be smoothed by * * the kernel returned by * * makeSmoothKernel(). * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * Writes out a new *.prm file. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ int permStep(string& matrixStemName, const string& permDir, const unsigned short permIndex, VB_permtype method, VBContrast &contrast,VB_Vector& pseudoT, int exhaustive) throw() { if (matrixStemName.size() == 0) return 100; if (permDir.size() == 0) return 101; string mypermdir=xdirname(matrixStemName)+"/"+permDir; Tes paramTes = Tes(matrixStemName + ".prm"); if (!paramTes.data_valid) return 103; string tempString = paramTes.GetHeader("DataScale:"); // Cube statCube; int err = 0; // set up our GLM structure GLMInfo glmi; glmi.setup(matrixStemName); glmi.contrast=contrast; glmi.pseudoT=pseudoT; //method 0 just returns the unpermuted stat cube if (method == vb_noperm) { glmi.calc_stat_cube(); // err=makeStatCub(statCube, NULL, matrixStemName,contrast,pseudoT,paramTes,.01); string sfile=(format("%s/permcube_%06d.cub.gz")%mypermdir%permIndex).str(); if (glmi.statcube.WriteFile(sfile)) return 128; else return err; } size_t brainCount = 0; vector brainPoints; vector noBrainPoints; MaskXYZCoord spatialCoords; for (long i = 0; i < paramTes.voxels; i++) { setMaskCoords(&spatialCoords, i, paramTes.dimx, paramTes.dimy, paramTes.dimz); if (paramTes.GetMaskValue(spatialCoords.x, spatialCoords.y, spatialCoords.z)) { brainCount++; brainPoints.push_back(i); } else noBrainPoints.push_back(i); } if (!brainCount) return 104; vector tesList; utils::readInTesFiles(matrixStemName, tesList); if (!tesList.size()) return 105; string gMatrixFile = matrixStemName + ".G"; if (!utils::isFileReadable(gMatrixFile)) return 106; VBMatrix gMatrix(gMatrixFile); if (!gMatrix.valid()) return 107; const unsigned long orderG = gMatrix.m; const unsigned long rankG = gMatrix.n; VB_Vector traces = VB_Vector(matrixStemName + ".traces"); if (!traces.getState()) return 108; double traceRV = traces[0]; string vMatrixFile = matrixStemName + ".V"; if (!utils::isFileReadable(vMatrixFile)) return 109; VBMatrix vMatrix(vMatrixFile); if (!vMatrix.valid()) return 110; if (gMatrix.m != vMatrix.m) return 111; string f1MatrixFile = matrixStemName + ".F1"; if (!utils::isFileReadable(f1MatrixFile)) return 112; VBMatrix origF1(f1MatrixFile); if (!origF1.valid()) return 113; if (vMatrix.m != origF1.n) return 114; string f3MatrixFile = matrixStemName + ".F3"; if (!utils::isFileReadable(f3MatrixFile)) return 116; VBMatrix origF3(f3MatrixFile); if (!origF3.valid()) return 117; if (origF1.m != origF3.n) return 118; if (origF1.n != origF3.m) return 119; vector contrastF1(origF1.n, 0.0); vector contrastF3(origF1.n, 0.0); for (size_t i = 0; i < (size_t ) origF1.m; i++) for (size_t j = 0; j < (size_t ) origF1.n; j++) { contrastF1[j] += origF1(i, j) * contrast.contrast[i]; contrastF3[j] += origF3(j, i) * contrast.contrast[i]; } double origFact = 0.0; for (int num = 0; num < (int)origF1.n; num++) origFact += (contrastF1[num] * contrastF3[num]); string permMatrixFile = mypermdir+"/permutations.mat"; if (!utils::isFileReadable(permMatrixFile)) return 120; VBMatrix permMatrix(permMatrixFile); if (!permMatrix.valid()) return 121; if (permIndex >= permMatrix.n) return 123; VB_Vector permArray(permMatrix.GetColumn(permIndex)); vector betasOfInt; vector betasToPermute; for (unsigned short i = 0; i < gMatrix.header.size(); i++) { if (gMatrix.header[i].size() > 0) { tokenlist args; args.ParseLine(gMatrix.header[i]); if ((args[0]=="Parameter:") && ((args[2]=="Interest") || (args[2]=="KeepNoInterest"))) betasOfInt.push_back(strtol(args[1])); if (args[0]=="Parameter:" && args[2]=="Interest") betasToPermute.push_back(strtol(args[1])); } } if (betasOfInt.size() == 0) return 124; betasOfInt.push_back(rankG); paramTes.SetVolume(paramTes.dimx, paramTes.dimy, paramTes.dimz, betasOfInt.size(), vb_double); gsl_matrix *G = gsl_matrix_calloc(gMatrix.m, gMatrix.n); for (int x = 0; x < (int)gMatrix.m; x++) for (int y = 0; y < (int)gMatrix.n; y++) gsl_matrix_set(G, x, y, gMatrix(x, y)); gsl_matrix *permuteG = gsl_matrix_calloc(G->size1, G->size2); for (int x = 0; x < (int)G->size1; x++) for (int y = 0; y < (int)G->size2; y++) gsl_matrix_set(permuteG, x, y, gsl_matrix_get(G, x, y)); if ( (betasToPermute.size()) && (method == vb_orderperm) ) { for (size_t covarIndex = 0; covarIndex < betasToPermute.size(); covarIndex++) { VB_Vector tempVec(permuteG->size1); for (size_t k = 0; k < (size_t ) tempVec.size(); k++) tempVec[k] = gsl_matrix_get(G, (size_t ) permArray[k], betasToPermute[covarIndex]); for (size_t k = 0; k < (size_t ) tempVec.size(); k++) gsl_matrix_set(permuteG, k, betasToPermute[covarIndex], tempVec[k]); } } double fact = 0.0; gsl_matrix *R = gsl_matrix_calloc(G->size1, G->size1); if (!R) return 126; gsl_matrix *F1 = gsl_matrix_calloc(G->size2, G->size1); if (!F1) return 127; err=doFactR(matrixStemName,permDir,contrast.contrast,permuteG,vMatrix, &fact,R,F1); if (err) return err; if (G) gsl_matrix_free(G); if(permuteG) gsl_matrix_free(permuteG); Tes tesData; double numChunks = 1.0; if (tesList.size() > 1) numChunks = ceil(( ((float ) orderG) * ((float ) brainCount) ) / 2000000.0); else tesData.ReadFile(tesList[0]); long startPoint = 0, endPoint = brainCount - 1; vector > chunkData; for (size_t loopChunk = 0; loopChunk < numChunks; loopChunk++) { if (loopChunk) { cout.precision(2); cout << setw(2) << "Percent Done: " << double(loopChunk)/double(numChunks) << endl; } if (tesList.size() > 1) { startPoint = long(((float ) brainCount / numChunks) * ((float ) loopChunk)); endPoint = long(((float ) brainCount / numChunks) * ((float ) loopChunk + 1.0) - 1.0); if (((float ) loopChunk) >= ((float ) numChunks - 1)) endPoint = brainCount - 1; vector theRegion; for (int i = startPoint; i <= (int) endPoint; i++) theRegion.push_back(brainPoints[i]); unsigned short stat = regionalTimeSeries(theRegion, tesList, chunkData, !strncmp(tempString.c_str(),"mean",4)); if (stat) exit(stat); } gsl_matrix *signal = gsl_matrix_calloc(1, orderG); gsl_matrix *transSignalF1 = gsl_matrix_calloc(F1->size1, signal->size1); gsl_matrix *residuals = gsl_matrix_calloc(R->size1, signal->size1); gsl_matrix *betas = gsl_matrix_calloc(1, F1->size2+1); gsl_matrix *ErrorSq = gsl_matrix_calloc(residuals->size2, residuals->size2); double signalValue = 0.0; for (int i = startPoint; i <= (int)endPoint; i++) { setMaskCoords(&spatialCoords, brainPoints[i], paramTes.dimx, paramTes.dimy, paramTes.dimz); if (tesList.size() == 1) { // if tesList.size() is 1, we've already read the whole tes // file and can use GetTimeSeries here (much faster) // tesData.ReadTimeSeries(tesList[0], spatialCoords.x, spatialCoords.y, spatialCoords.z); tesData.GetTimeSeries(spatialCoords.x, spatialCoords.y, spatialCoords.z); for (int elementNumber = 0; elementNumber < (int)orderG; elementNumber++) { signalValue = tesData.timeseries[elementNumber]; if (method == vb_signperm) signalValue*= permArray[elementNumber]; gsl_matrix_set(signal, 0, elementNumber, signalValue); } } else for (int elementNumber = 0; elementNumber < (int)orderG; elementNumber++) { signalValue = chunkData[i - startPoint][elementNumber]; if (method == vb_signperm) signalValue*= permArray[elementNumber]; gsl_matrix_set(signal, 0, elementNumber, signalValue); } gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, F1, signal, 0.0, transSignalF1); gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, R, signal, 0.0, residuals); gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, residuals, residuals, 0.0, ErrorSq); gsl_matrix_scale(ErrorSq, (1/traceRV)); gsl_matrix_scale(ErrorSq, fact/origFact); for (size_t b = 0; b < (size_t ) F1->size1; b++) gsl_matrix_set(betas, 0, b, gsl_matrix_get(transSignalF1, b, 0)); gsl_matrix_set(betas, 0, F1->size1, gsl_matrix_get(ErrorSq, 0, 0)); for (size_t t = 0; t < (unsigned int)betasOfInt.size(); t++) { //cout << t<<" "<size2, permuteG->size2); if (!Gtg) return 129; gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, permuteG, permuteG, 0.0, Gtg); gsl_matrix *invGtg = gsl_matrix_calloc(permuteG->size2, permuteG->size2); if (!invGtg) return 130; gsl_permutation *LUPerm = gsl_permutation_calloc(Gtg->size2); if (!LUPerm) return 131; int permSign = 0; gsl_linalg_LU_decomp(Gtg, LUPerm, &permSign); if (gsl_linalg_LU_invert(Gtg, LUPerm, invGtg) != GSL_SUCCESS) return 132; gsl_permutation_free(LUPerm); gsl_matrix *Ggtg = gsl_matrix_calloc(permuteG->size2, permuteG->size1); if (!Ggtg) return 133; gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, invGtg, permuteG, 0.0, Ggtg); gsl_matrix_memcpy(F1, Ggtg); //begin: create R by R=(-1)*(PermuteG##Fac1) and R(indgen(OrderG)*(OrderG+1L))=1+R(indgen(OrderG)*(OrderG+1L)) gsl_matrix *rMat = gsl_matrix_calloc(permuteG->size1, permuteG->size1); if (!rMat) return 134; gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, -1.0, permuteG, F1, 0.0, rMat); for (size_t i = 0; i < permuteG->size1; i++) gsl_matrix_set(rMat, i, i, 1.0 + gsl_matrix_get(rMat, i, i)); gsl_matrix_memcpy(R, rMat); //begin: Fac3=V##PermuteG##(invert(transpose(PermuteG)##PermuteG)) gsl_matrix *v = gsl_matrix_calloc(V.m, V.n); for (int x = 0; x < (int)V.m; x++) for (int y = 0; y < (int)V.n; y++) gsl_matrix_set(v, x, y, V(x, y)); gsl_matrix *Gtvt = gsl_matrix_calloc(permuteG->size1, permuteG->size2); if (!Gtvt) return 135; gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, permuteG, invGtg, 0.0, Gtvt); gsl_matrix *F3 = gsl_matrix_calloc(V.m, permuteG->size2); if (!F3) return 136; gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, v, Gtvt, 0.0, F3); //begin: ContrastArray##Fac1##Fac3##transpose(ContrastArray) gsl_matrix *contrastMatrix = gsl_matrix_calloc(1, contrasts.size()); gsl_matrix *result1 = gsl_matrix_calloc(contrastMatrix->size1, F1->size2); gsl_matrix *result2 = gsl_matrix_calloc(result1->size1, F3->size2); gsl_matrix *result3 = gsl_matrix_calloc(result2->size1, contrastMatrix->size1); for (uint32 index = 0; index < contrasts.size(); index++) gsl_matrix_set(contrastMatrix, 0, index, contrasts[index]); gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, contrastMatrix, F1, 0.0, result1); gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, result1, F3, 0.0, result2); gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, result2, contrastMatrix, 0.0, result3); *fact = gsl_matrix_get(result3, 0, 0); if (result1) gsl_matrix_free(result1); if (result2) gsl_matrix_free(result2); if (result3) gsl_matrix_free(result3); if (contrastMatrix) gsl_matrix_free(contrastMatrix); if (rMat) gsl_matrix_free(rMat); if (invGtg) gsl_matrix_free(invGtg); if (Gtvt) gsl_matrix_free(Gtvt); if (Ggtg) gsl_matrix_free(Ggtg); if (Gtg) gsl_matrix_free(Gtg); if (v) gsl_matrix_free(v); return 0; } permclass::permclass() { stemname=""; permdir=""; scale=""; method=vb_orderperm; nperms=0; contrast=""; pseudotlist.clear(); filename=""; m_prmTimeStamp = ""; rngseed=0; } permclass::~permclass(){;} void permclass::AddPrmTimeStamp(string matrixStemName) { Tes prm(matrixStemName+".prm"); m_prmTimeStamp = prm.GetHeader("TimeStamp:"); return; } string permclass::GetPrmTimeStamp() { return m_prmTimeStamp; } void permclass::SavePermClass() { ofstream out; string pst; string file =xdirname(stemname)+"/"+permdir+"/perminfo.txt"; out.open(file.c_str(), ios::out); out << "stemname " << stemname << endl; out << "permdir " << permdir << endl; out << "method " << methodstring(method) << endl; out << "pseudotkernel " << pseudotlist << endl; out << "contrast " << contrast << endl; out << "prmid " << m_prmTimeStamp << endl; out.close(); return; } // FIXME LoadPermClass still not used, but it could be void permclass::LoadPermClass() { tokenlist lines; lines.ParseFile(filename); vbforeach(string line,lines) { tokenlist args(line); string tag=vb_tolower(args[0]); tag=xstripwhitespace(tag," \t\n\r:"); // strip whitespace and colons! if (tag=="stemname") stemname=args.Tail(); else if (tag=="permdir") permdir=args.Tail(); else if (tag=="method") method=methodtype(args[1]); // FIXME else if (tag=="pseudotkernel") else if (tag=="contrast") contrast=args.Tail(); else if (tag=="prmid") m_prmTimeStamp=args.Tail(); } } void permclass::SetFileName(string fname) { filename=fname; return; } void permclass::Clear() { stemname=""; permdir=""; scale=""; method=vb_orderperm; nperms=0; contrast=""; pseudotlist.clear(); filename=""; m_prmTimeStamp = ""; return; } string permclass::methodstring(const VB_permtype pt) { if (pt==vb_noperm) return "noperm"; if (pt==vb_orderperm) return "orderperm"; if (pt==vb_signperm) return "signperm"; return "noperm"; } VB_permtype permclass::methodtype(const string tp) { string tpx=vb_tolower(xstripwhitespace(tp)); if (tpx=="0" || tpx=="noperm") return vb_noperm; if (tpx=="1" || tpx=="orderperm") return vb_orderperm; if (tpx=="2" || tpx=="signperm") return vb_signperm; return vb_noperm; } void permclass::Print() { string pst; cout << "matrix stem name: " << stemname << endl; cout << "perm directory: " << permdir << endl; cout << "method: " << methodstring(method) << endl; cout << "scale: " << scale << endl; cout << "pseudot values: " << pseudotlist << endl; cout << "contrast: " << contrast << endl; cout << "prm timestamp: " << m_prmTimeStamp << endl; return; } voxbo-1.8.5~svn1246/stand_alone/perm.h000066400000000000000000000255071153177201300175400ustar00rootroot00000000000000 // perm.h // // Copyright (c) 1998-2004 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee /********************************************************************* * Include guard. * *********************************************************************/ #ifndef PERM_H #define PERM_H /********************************************************************* * Required include files. * *********************************************************************/ #include #include #include #include #include "utils.h" #include "time_series_avg.h" #include "makestatcub.h" #include "glmutil.h" #include enum VB_permtype {vb_noperm,vb_orderperm,vb_signperm}; class permclass { public: permclass(); ~permclass(); void AddPrmTimeStamp(string matrixStemName); string GetPrmTimeStamp(); void SetFileName(string filename); void SavePermClass(); void LoadPermClass(); void Clear(); void Print(); string stemname; string permdir; string m_prmTimeStamp; string scale; VB_permtype method; int nperms; string contrast; string pseudotlist; string filename; uint32 rngseed; static string methodstring(const VB_permtype pt); static VB_permtype methodtype(const string tp); }; /********************************************************************* * Using the standard namespace. * *********************************************************************/ using namespace std; /********************************************************************* * Needed constants. * *********************************************************************/ const unsigned short MAX_PERMS = 1000; const unsigned short PERMUTATION_LIMIT = 6; const unsigned short SIGN_PERMUTATION_LIMIT = 11; /********************************************************************* * Needed external variable. * *********************************************************************/ extern gsl_rng *theRNG; /* >>>>>>>>>>>> FUNCTION PROTOTYPES <<<<<<<<<<<< */ /********************************************************************* * This function initializes the global variable theRNG. * *********************************************************************/ void initRNG(uint32 rngseed); /********************************************************************* * This function deallocates the global variable theRNG. * *********************************************************************/ void freeRNG(); /********************************************************************* * This function sets up the permutation analysis matrix. * *********************************************************************/ int permStart(permclass pc); /********************************************************************* * This function computes the factorial of the input integer. * *********************************************************************/ size_t factorial(const size_t n); /********************************************************************* * This function prints the elements of the input permutation in * * GSL form, i.e., each element is in {0, 1, 2, ..., n - 1}. * *********************************************************************/ void printGSLPerm(const gsl_permutation *pi); /********************************************************************* * This function computes a random permutation. * *********************************************************************/ void randPerm(gsl_permutation *pi); /********************************************************************* * This function increments the elements of the input permutation. * *********************************************************************/ void incPerm(gsl_permutation *pi); /********************************************************************* * This function prints the name of the GSL random number generator. * *********************************************************************/ void printRNGName(gsl_rng *theRNG); /********************************************************************* * This function determines if the two input permutations are equal * * or not. * *********************************************************************/ bool arePermsEqual(const gsl_permutation *p1, const gsl_permutation *p2, const size_t begin = 0); /********************************************************************* * This function checks to see if r is <= (n! - 1). * *********************************************************************/ void verifyPermRank(const size_t r, const size_t n); /********************************************************************* * This function creates the specified permutation. * *********************************************************************/ void unrank1(const size_t n, const size_t r, gsl_permutation *pi); /********************************************************************* * This function computes the rank of the input permutation. * *********************************************************************/ size_t rank1(const size_t n, gsl_permutation *pi, gsl_permutation *piInv); /********************************************************************* * This function determines if the permutation pi is already in the * * the permutation hash table or not. * *********************************************************************/ bool inHash(map > &permHash, gsl_permutation *pi); /********************************************************************* * This function prints out a list of the available GSL random number * * generators. * *********************************************************************/ void availableGSLRNGs(); /********************************************************************* * This function prints out the contents of the input map container. * *********************************************************************/ void printHash(map >& theHash); /********************************************************************* * This function frees the memory allocated to the gsl_permutation * * structs contained in the map. * *********************************************************************/ void freePermHash(map >& theHash); /********************************************************************* * This function returns true if the 2 input sign permutation arrays * * are equal. Otherwise, false is returned. * *********************************************************************/ bool areSignsEqual(const short *arr1, const short *arr2, const size_t len); /********************************************************************* * This function retutns true if the input sign permutation is already* * in the input sign permutation hash table. Otherwise, the input * * permutation is added to the hash table and false is returned. * *********************************************************************/ bool inSignHash(map > &signHash, short *pi, const size_t len); /********************************************************************* * This function frees the memory allocated to the elements in the * * input map container (which are sign permutation arrays). * *********************************************************************/ void freeSignHash(map >& theHash); /********************************************************************* * This function prints the elements in the input map container * * (which are sign permutation arrays). * *********************************************************************/ void printSignHash(map >& theHash, const size_t len); /********************************************************************* * This function prints out the input sign permutation array. * *********************************************************************/ void printSignPerm(const short *thePerm, const size_t len); /********************************************************************* * This function generates a random sign permutation. * *********************************************************************/ void randSignPerm(short *pi, const size_t len); /********************************************************************* * This function computes the "rank" of a sign permutation. * *********************************************************************/ size_t rankSignPerm(const short *signPerm, const size_t len); /********************************************************************* * This function carries out a single permutation analysis step. * *********************************************************************/ int permStep(string& matrixStemName, const string& permDir, const unsigned short permIndex, VB_permtype method, VBContrast &contrast,VB_Vector& pseudoT, int exhaustive) throw(); /********************************************************************* * This function computes the permutation R matrix and fact value. * *********************************************************************/ int doFactR(const string& matrixStemName, const string& permDir, VB_Vector& contrasts, gsl_matrix *permuteG, VBMatrix& vMatrixFile, double *fact, gsl_matrix *R, gsl_matrix *F1) throw(); // DYK: added function to create perm matrix to spec VBMatrix createPermMatrix(int nperms,int ndata,VB_permtype method,uint32 seed); /* >>>>>>>>>>>> END FUNCTION PROTOTYPES <<<<<<<<<<<< */ #endif // PERM_H voxbo-1.8.5~svn1246/stand_alone/permstep.cpp000066400000000000000000000232261153177201300207630ustar00rootroot00000000000000 // permstep.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee // modified a bit by Dan Kimberg #include #include "perm.h" using namespace std; void usage(const unsigned short exitValue, char *progName); gsl_rng *theRNG = NULL; int main(int argc, char *argv[]) { SEGV_HANDLER GSL_ERROR_HANDLER_OFF if (argc == 1) { usage(1, argv[0]); exit(-1); } string matrixStemName; string permDir; int exhaustive = 0; VB_Vector pseudoT; VB_permtype method = vb_noperm; int permIndex = 0; string contrast; GLMInfo glmi; tokenlist args; args.Transfer(argc-1,argv+1); for (size_t i=0; i ret; ret=strtolx(args[++i]); if (ret.first) { cout << "[E] permstep: invalid perm index\n"; exit(101); } permIndex=ret.second; } else if (args[i]=="-c" && i Specify the matrix stem name. Required.\n"); printf(" -d Permutation directory name. Required.\n"); printf(" -t Permutation type: 0/none, 1/order, or 2/sign\n"); printf(" -c contrast values, in quotes. Required.\n"); printf(" -p pseudoT kernel, in quotes. Required.\n"); printf(" -v Global VoxBo version number. Optional.\n"); printf(" -e Produce cubes and their inverses. Optional.\n"); printf(" -n index of permutation to be generated. Optional.\n"); printf("notes: \n"); printf(" /1 and /2 force one tailed and two tailed, and\n"); printf(" note that VoxBo defaults to one tailed testing\n"); printf(" -v Global VoxBo version number. Optional.\n\n"); exit(-1); } voxbo-1.8.5~svn1246/stand_alone/regression.cpp000066400000000000000000001260261153177201300213060ustar00rootroot00000000000000 // regression.cpp // Copyright (c) 1998-2002 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee /********************************************************************* * Required include file. * *********************************************************************/ #include "regression.h" /********************************************************************* * Using the std namespace. * *********************************************************************/ using namespace std; /********************************************************************* * This function reads in names of Tes files from the "*.sub" file * * found in the directory specified by the input argument * * matrixStemName. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * matrixStemName const string & Specifies the directory in * * which the "*.sub" file exists. * * tesList vector & The container for the Tes * * files. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void readInTesFiles(const string &matrixStemName, vector &tesList) throw() { /********************************************************************* * Assembling the name for the *.sub file. * *********************************************************************/ string subFile = matrixStemName + ".sub"; /********************************************************************* * Now making sure that the *.sub file is process readable. If it * * is not readable, then this program will exit. * *********************************************************************/ if (!isFileReadable(subFile)) { ostringstream errorMsg; errorMsg << "The sub file: [" << subFile << "] is not readable."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * If the file format of subFile is not a VoxBo text file, then an * * unrecoverable error has occurred. Therefore, an error message is * * assembled, printed, and then this program exits. * *********************************************************************/ if (utils::refOrTextOrMat(subFile) != utils::TXT_TYPE) { ostringstream errorMsg; errorMsg << "The file [" << subFile << "] is not a VoxBo text file."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * Now we read the Tes file names from subFile. First, an input stream* * is created. * *********************************************************************/ ifstream subFileStream(subFile.c_str(), ios::in); /********************************************************************* * If we were unable to open subFile for reading, then we have an * * unrecoverable error. An error message is printed and then this * * program exits. * *********************************************************************/ if (!subFileStream) { ostringstream errorMsg; errorMsg << "The file [" << subFile << "] could not be opened for reading."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * inputLine[] is used to hold a line read in from subFileStream. It * * is declared and then cleared. * *********************************************************************/ char inputLine[STRINGLEN]; memset(inputLine, 0, STRINGLEN); while (subFileStream.getline(inputLine, STRINGLEN)) { /********************************************************************* * If the first character in inputLine[] is a ';' or inputLine[] is * * empty, then the line is ignored. * *********************************************************************/ if ( (inputLine[0] == ';') || (strlen(inputLine) == 0) ) { continue; } // if /********************************************************************* * The following for loop is used to determine the index of the first * * non-whitespace character in inputLine[]. * *********************************************************************/ unsigned short nwsIndex = 0; unsigned short commentIndex = 0; for (; nwsIndex < strlen(inputLine); nwsIndex++) { if (!isspace(inputLine[nwsIndex])) { break; } // if } // for nwsIndex /********************************************************************* * If nwsIndex equals strlen(inputLine), then inputLine[] consists * * solely of white space. Therefore, we simply continue. * *********************************************************************/ if (nwsIndex == strlen(inputLine)) { continue; } // if /********************************************************************* * The next step is to find out where a possible trailing comment * * begins in inputLine[]. * *********************************************************************/ for (commentIndex = nwsIndex; commentIndex < strlen(inputLine); commentIndex++) { if ( (inputLine[commentIndex] == ';') || (inputLine[commentIndex] == '#') ) { break; } // if } // for commentIndex /********************************************************************* * If nwsIndex equals commentIndex, then we don't have any usable * * information in inputLine[]. Therefore, we simply continue. * *********************************************************************/ if (nwsIndex == commentIndex) { continue; } // if /********************************************************************* * Now the "good part" of inputLine[] is copied to editedLine, i.e., * * editedLine will not have any leading white space nor will it have * * and trailing comments. * *********************************************************************/ char *editedLine = new char[commentIndex - nwsIndex + 1]; memset(editedLine, 0, commentIndex - nwsIndex + 1); memcpy(editedLine, inputLine + nwsIndex, commentIndex - nwsIndex); if (access(editedLine,R_OK)) { /********************************************************************* * Some *.sub files don't list the Tes files with the ".tes" suffix. * * Therefore, we now append ".tes" to editedLine and then check to * * see if that file is readable or not. If that file is not readable, * * a warning message is printed out. * *********************************************************************/ if (access(((string)editedLine+".tes").c_str(),R_OK)) { char resolvedPath[PATH_MAX]; memset(resolvedPath, 0, PATH_MAX); ostringstream errorMsg; errorMsg << "The file [" << string(editedLine) << ".tes" << "] is not readable due to: [" << editedLine << ".tes" << "]."; printErrorMsg(VB_WARNING, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__); } // if /********************************************************************* * If (editedLine + ".tes") is readable, then it is added to tesList. * *********************************************************************/ else { tesList.push_back(string(editedLine) + ".tes"); } // else } // if /********************************************************************* * If the file in editedLine is readable, it is added to tesList. * *********************************************************************/ else { tesList.push_back(string(editedLine)); } // else delete [] editedLine; editedLine=0; } // while /********************************************************************* * Now closing subFileStream. * *********************************************************************/ subFileStream.close(); } // void readInTesFiles(const string &matrixStemName, // vector &tesList) throw() /********************************************************************* * This routine generates the "K" matrix, which contains the * * representation of temporal autocorrelation under the * * null-hypothesis. Currently, the only option available to the user * * for the estimation of intrinsic temporal autocorrelation is the * * average data PS. Therefore, the K matrix must reflect this model * * and the exogenous filter. This function is ported from the IDL * * procedure MakeMatrixK, found in VoxBo_GLM.pro. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * matrixStemName const string& The full path to the GLM * * directory. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void makeMatrixK(const string& matrixStemName) throw() { /********************************************************************* * If matrixStemName is the empty string, then an error message is * * printed and then this program exits. * *********************************************************************/ if (matrixStemName.size() == 0) { ostringstream errorMsg; errorMsg << "LINE: [" << __LINE__ << "] FUNCTION: [" << __FUNCTION__ << "] The matrixStemName is empty."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if string gMatrixFile(matrixStemName + ".G"); VBMatrix gMatrix(gMatrixFile); if (!gMatrix.valid()) { ostringstream errorMsg; errorMsg << "Could not instantiate the G matrix from the file [" << gMatrixFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } /********************************************************************* * Assigning orderG. * *********************************************************************/ unsigned long orderG = gMatrix.m; string intrinCorFile(matrixStemName + ".IntrinCor"); VB_Vector intrinCor(intrinCorFile); string exoFiltFile(matrixStemName + ".ExoFilt"); VB_Vector exoFilt(exoFiltFile); if (!intrinCor.getState() || !exoFilt.getState()) { cout << "[E] error reading either intrincor or exofilt file\n"; exit(101); } /********************************************************************* * If the length of exoFilt does not equal orderG, then an error * * message is printed and then this program exits. * *********************************************************************/ if (exoFilt.getLength() != orderG) { ostringstream errorMsg; errorMsg << "Exogenous filter length [" << exoFilt.getLength() << "] from file [" << exoFiltFile << "] does not match G matrix [" << orderG << "] from file [" << gMatrixFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * Preparing the filters by: * * * * 1. Scaling each filter so that it's maximum element is 1. * * 2. Setting the zeroth element to 1 (to preserve the mean of the * * signal). * *********************************************************************/ intrinCor.getPS(); intrinCor.applyFunction(sqrt); intrinCor.scaleInPlace(1.0 / intrinCor.getMaxElement()); intrinCor[0] = 1.0; exoFilt.getPS(); exoFilt.applyFunction(sqrt); exoFilt.scaleInPlace(1.0 / exoFilt.getMaxElement()); exoFilt[0] = 1.0; /********************************************************************* * Now instantiating the K matrix (with data type of double). The K * * matrix will be the identity matrix convolved with intrinCor and * * exoFilt. * *********************************************************************/ VBMatrix kMatrix(orderG, orderG); /********************************************************************* * If the kMatrix is not in a valid state, then an error message is * * printed and then this program exits. * *********************************************************************/ if (!kMatrix.valid()) { ostringstream errorMsg; errorMsg << "Could not instantiate a valid K matrix."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * We will need to compute the FFT of each row of kMatrix. To that * * end, realPart will hold the real part of the FFT and imagPart will * * hold the imaginary part of the FFT. * *********************************************************************/ VB_Vector realPart(orderG); VB_Vector imagPart(orderG); /********************************************************************* * We will need to compute the inverse FFT (IFFT) of realPart and * * and imagPart. To that end, realPartReal will hold the real part of * * realPart's IFFT; realPartImag will hold the imaginary part of * * realPart's IFFT; imagPartReal will hold the real part of imagPart's* * IFFT; imagPartImag will hold the imaginary part of imagPart's * * IFFT. * *********************************************************************/ VB_Vector realPartReal(orderG); VB_Vector realPartImag(orderG); VB_Vector imagPartReal(orderG); VB_Vector imagPartImag(orderG); /********************************************************************* * cornerValRecip will hold the reciprocal of the K matrix's [0, 0] * * entry. * *********************************************************************/ double cornerValRecip = 0.0; /********************************************************************* * The following for loop is used to "convolve" the K matrix with * * intrinCor and exoFilt (but first, each row of the K matrix is * * turned into the corresponding row of the identity matrix). * *********************************************************************/ for (unsigned long rowIndex = 0; rowIndex < orderG; rowIndex++) { /********************************************************************* * The next 2 lines create a VB_Vector object that holds row number * * rowIndex from the identity matrix. * *********************************************************************/ VB_Vector kMatrixRow(orderG); kMatrixRow[rowIndex] = 1.0; /********************************************************************* * We now compute the FFT of kMatrixRow. * *********************************************************************/ kMatrixRow.fft(realPart, imagPart); /********************************************************************* * Now element-by-element multiplication is carried out between the * * FFT of tempVec, intrinCor, and exoFilt. * *********************************************************************/ realPart.elementByElementMult(intrinCor); imagPart.elementByElementMult(intrinCor); realPart.elementByElementMult(exoFilt); imagPart.elementByElementMult(exoFilt); /********************************************************************* * Now the inverse FFT of realPart and imagPart are computed. * *********************************************************************/ realPart.ifft(realPartReal, realPartImag); imagPart.ifft(imagPartReal, imagPartImag); /********************************************************************* * At this point, we no longer need the values in realPart. Therefore,* * realPart is resued to hold the real part of the inverse FFT of * * (realPart + i*imagPart). * *********************************************************************/ realPart = realPartReal - imagPartImag; /********************************************************************* * If we are working on the first row of the K matrix, we get the * * reciporcal of its [0, 0] entry. * *********************************************************************/ if (rowIndex == 0) { cornerValRecip = 1.0 / realPart[0]; } // if /********************************************************************* * We normalize this row of the K matrix and place it in the K matrix.* *********************************************************************/ realPart.scaleInPlace(cornerValRecip); kMatrix.SetRow(rowIndex, realPart); } // for rowIndex /********************************************************************* * Setting the K matrix file name. * *********************************************************************/ kMatrix.filename=matrixStemName + ".K"; /********************************************************************* * Adding the "DateCreated:" and "TaskTag:" header lines. * *********************************************************************/ kMatrix.AddHeader(string("DateCreated:\t") + timedate()); kMatrix.AddHeader(string("TaskTag:\t") + "K matrix"); /********************************************************************* * If writing out the K matrix file fails, then an error message is * * printed and then this program exits. * *********************************************************************/ if (kMatrix.WriteFile()) { ostringstream errorMsg; errorMsg << "Unable to write the K matrix file [" << matrixStemName + ".K" << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if } // void makeMatrixK(const string& matrixStemName) throw() bool isFileReadable(const string& fileName) throw() { if (access(fileName.c_str(),R_OK)) return false; return true; } /********************************************************************* * This function checks to see if the input Tes dimensions match the * * dimensions of the input Tes object. If the time dimensions do not * * match, 1 is returned. If the X dimensions do not match, 2 is * * returned. If the Y dimensions do not match, 3 is returned. If the * * Z dimensions do not match, 4 is returned. Also, an appropriate * * error message is printed out if a dimension does not match. If * * all dimensions match, 0 is returned. NOTE: It is up to the * * calling function to decide what to do if a dimension does not * * match. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * dimT const unsigned short The input time dimension. * * dimX const unsigned short The X time dimension. * * dimY const unsigned short The Y time dimension. * * dimZ const unsigned short The Z time dimension. * * theTes const Tes& The input Tes object. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * 0 const unsigned short If all dimensions match. * * 1 const unsigned short If time dimensions do not * * match. * * 2 const unsigned short If the X dimensions do not * * match. * * 3 const unsigned short If the Y dimensions do not * * match. * * 4 const unsigned short If the Z dimensions do not * * match. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ unsigned short checkTesDims(const unsigned short dimT, const unsigned short dimX, const unsigned short dimY, const unsigned short dimZ, const Tes& theTes) throw() { /********************************************************************* * Checking the time dimensions. * *********************************************************************/ if (dimT != theTes.dimt) { ostringstream errorMsg; errorMsg << "The input time dimension [" << dimT << "] does not match the time dimension of the input Tes file [" << theTes.filename << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); return 1; } // if /********************************************************************* * Checking the X dimensions. * *********************************************************************/ if (dimX != theTes.dimx) { ostringstream errorMsg; errorMsg << "The input X dimension [" << dimX << "] does not match the X dimension of the input Tes file [" << theTes.filename << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); return 2; } // if /********************************************************************* * Checking the Y dimensions. * *********************************************************************/ if (dimY != theTes.dimy) { ostringstream errorMsg; errorMsg << "The input Y dimension [" << dimY << "] does not match the Y dimension of the input Tes file [" << theTes.filename << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); return 3; } // if /********************************************************************* * Checking the Z dimensions. * *********************************************************************/ if (dimZ != theTes.dimz) { ostringstream errorMsg; errorMsg << "The input Z dimension [" << dimZ << "] does not match the Z dimension of the input Tes file [" << theTes.filename << "]."; printErrorMsg(VB_ERROR, errorMsg.str()); return 4; } // if /********************************************************************* * At this point, all the dimensions match. Therefore, 0 is returned. * *********************************************************************/ return 0; } // const unsigned short checkTesDims(const unsigned short dimT, // const unsigned short dimX, const unsigned short dimY, // const unsigned short dimZ, const Tes& theTes) throw() unsigned short shiftLeft(const unsigned short index, const unsigned short dimIndex) { if (index == 0) { return (dimIndex - 1); } // if return (index - 1); } // const unsigned short shiftLeft(const unsigned short index, // const unsigned short dimIndex) /********************************************************************* * This routine generates the "KG" matrix, which contains covariates * * that reflect both endogenous and exogenous smoothing. This * * function is ported from the IDL procedure MakeMatrixKG, found in * * VoxBo_GLM.pro. * * * * INPUT VARIABLES: TYPE: DESCRIPTION: * * ---------------- ----- ------------ * * matrixStemName const string& The full path to the GLM * * directory. * * * * OUTPUT VARIABLES: TYPE: DESCRIPTION: * * ----------------- ----- ------------ * * None. * * * * EXCEPTIONS THROWN: * * ------------------ * * None. * *********************************************************************/ void makeMatrixKG(const string& matrixStemName) throw() { string gMatrixFile(matrixStemName + ".G"); /********************************************************************* * Now a VBMatrix object is instantiated from gMatrixFile. If that * * fails, then we have an unrecoverable error. Therefore, an error * * message is printed and then this program exits. * *********************************************************************/ VBMatrix gMatrix(gMatrixFile); if (!gMatrix.valid()) { ostringstream errorMsg; errorMsg << "Could not instantiate the G matrix from the file [" << gMatrixFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * Assigning orderG and rankG. * *********************************************************************/ const unsigned long orderG = gMatrix.m; const unsigned long rankG = gMatrix.n; string exoFiltFile(matrixStemName + ".ExoFilt"); VB_Vector exoFilt(exoFiltFile); /********************************************************************* * If the length of exoFilt does not equal orderG, then an error * * message is printed and then this program exits. * *********************************************************************/ //if (exoFilt.getLength() == 0) //TGK: if file exists but no vector, copy G to KG // flagNoExoFilt = 1; /*else*/ if (exoFilt.getLength() != orderG) { //TGK: if orderG is just wrong, it's an error ostringstream errorMsg; errorMsg << "Exogenous filter length [" << exoFilt.getLength() << "] from file [" << exoFiltFile << "] does not match G matrix [" << orderG << "] from file [" << gMatrixFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /* if (flagNoExoFilt) { //TGK: if no exofilt, we can use G for KG VBMatrix emptykgMatrix(gMatrix); emptykgMatrix.MakeInCore(); if (!emptykgMatrix.valid) { ostringstream errorMsg; errorMsg << "Could not instantiate a valid KG matrix."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } emptykgMatrix.SetFileName(matrixStemName + ".KG"); emptykgMatrix.AddHeader(string("DateCreated:\t") + timedate()); emptykgMatrix.AddHeader(string("TaskTag:\t") + "KG matrix"); if (emptykgMatrix.WriteData()) { ostringstream errorMsg; errorMsg << "Unable to write the K matrix file [" << matrixStemName + ".KG" << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } return; } */ /********************************************************************* * Preparing the exogenous filter by: * * * * 1. Scaling each filter so that it's maximum element is 1. * * 2. Setting the zeroth element to 1 (to preserve the mean of the * * signal). * *********************************************************************/ exoFilt.getPS(); exoFilt.applyFunction(sqrt); exoFilt[0] = 1.0; /********************************************************************* * Now instantiating the KG matrix (with data type of double). The KG * * matrix will be the G matrix convolved with exoFilt. * *********************************************************************/ VBMatrix kgMatrix(orderG, rankG); /********************************************************************* * If the kgMatrix is not in a valid state, then an error message is * * printed and then this program exits. * *********************************************************************/ if (!kgMatrix.valid()) { ostringstream errorMsg; errorMsg << "Could not instantiate a valid KG matrix."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * We will need to compute the FFT of each row of kgMatrix. To that * * end, realPart will hold the real part of the FFT and imagPart will * * hold the imaginary part of the FFT. * *********************************************************************/ VB_Vector realPart(rankG); VB_Vector imagPart(rankG); /********************************************************************* * We will need to compute the inverse FFT (IFFT) of realPart and * * and imagPart. To that end, realPartReal will hold the real part of * * realPart's IFFT; realPartImag will hold the imaginary part of * * realPart's IFFT; imagPartReal will hold the real part of imagPart's* * IFFT; imagPartImag will hold the imaginary part of imagPart's * * IFFT. * *********************************************************************/ VB_Vector realPartReal(rankG); VB_Vector realPartImag(rankG); VB_Vector imagPartReal(rankG); VB_Vector imagPartImag(rankG); /********************************************************************* * The following for loop is used to "convolve" the G matrix with * * intrinCor and exoFilt (but first, each row of the K matrix is * * turned into the corresponding row of the identity matrix). * *********************************************************************/ for (unsigned long colIndex = 0; colIndex < rankG; colIndex++) { /********************************************************************* * We now fetch column number colIndex from the G matrix and * * instantiate a VB_Vector. * *********************************************************************/ VB_Vector gMatrixCol(gMatrix.GetColumn(colIndex)); /********************************************************************* * We now compute the FFT of gMatrixCol. * *********************************************************************/ gMatrixCol.fft(realPart, imagPart); /********************************************************************* * Now element-by-element multiplication is carried out between the * * FFT of tempVec, intrinCor, and exoFilt. * *********************************************************************/ realPart.elementByElementMult(exoFilt); imagPart.elementByElementMult(exoFilt); /********************************************************************* * Now the inverse FFT of realPart and imagPart are computed. * *********************************************************************/ realPart.ifft(realPartReal, realPartImag); imagPart.ifft(imagPartReal, imagPartImag); /********************************************************************* * We now set column number colIndex in the KG matrix with the real * * real part of the inverse FFT of (realPart + i*imagPart). * *********************************************************************/ kgMatrix.SetColumn(colIndex, realPartReal - imagPartImag); } // for colIndex /********************************************************************* * Setting the K matrix file name. * *********************************************************************/ kgMatrix.filename=matrixStemName + ".KG"; /********************************************************************* * Adding the "DateCreated:" and "TaskTag:" header lines. * *********************************************************************/ kgMatrix.AddHeader(string("DateCreated:\t") + timedate()); kgMatrix.AddHeader(string("TaskTag:\t") + "KG matrix"); /********************************************************************* * If writing out the K matrix file fails, then an error message is * * printed and then this program exits. * *********************************************************************/ if (kgMatrix.WriteFile()) { ostringstream errorMsg; errorMsg << "Unable to write the K matrix file [" << matrixStemName + ".KG" << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if } // void makeMatrixKG(const string& matrixStemName) throw() /********************************************************************* * This function writes out the file matrixStemName + ".traces". * *********************************************************************/ void computeTraces(const string& matrixStemName) { string gMatrixFile(matrixStemName + ".G"); /********************************************************************* * Now a VBMatrix object is instantiated from gMatrixFile. If that * * fails, then we have an unrecoverable error. Therefore, an error * * message is printed and then this program exits. * *********************************************************************/ VBMatrix gMatrix(gMatrixFile); if (!gMatrix.valid()) { ostringstream errorMsg; errorMsg << "Could not instantiate the G matrix from the file [" << gMatrixFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * Assigning orderG. * *********************************************************************/ const long orderG = gMatrix.m; /********************************************************************* * Declaring the traces Vec object and then initializing it to all * * zeros. * *********************************************************************/ VB_Vector traces(3); traces*=3.0; string rvMatrixFile(matrixStemName + ".RV"); /********************************************************************* * Now a VBMatrix object is instantiated from rvMatrixFile. If that * * fails, then we have an unrecoverable error. Therefore, an error * * message is printed and then this program exits. * *********************************************************************/ VBMatrix rvMatrix(rvMatrixFile); if (!rvMatrix.valid()) { ostringstream errorMsg; errorMsg << "Could not instantiate the RV matrix from the file [" << rvMatrixFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * If the number of rows in the RV matrix does not equal the number * * of rows in the G matrix, we have an unrecoverable error. Therefore,* * an error message is printed and then this program exits. * *********************************************************************/ if (rvMatrix.m != orderG) { ostringstream errorMsg; errorMsg << "The number of rows [" << rvMatrix.m << "] for the RV matrix [" << rvMatrixFile << "] does not equal the number of rows [" << orderG << "] for the G matrix [" << matrixStemName << ".G]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * The following for loop is used to assign the trace of the RV * * matrix to traces[0]. * *********************************************************************/ for (long i = 0; i < rvMatrix.n; i++) { traces[0] += rvMatrix(i, i); } // for i string rvrvMatrixFile(matrixStemName + ".RVRV"); /********************************************************************* * Now a VBMatrix object is instantiated from rvrvMatrixFile. If that * * fails, then we have an unrecoverable error. Therefore, an error * * message is printed and then this program exits. * *********************************************************************/ VBMatrix rvrvMatrix(rvrvMatrixFile); if (!rvrvMatrix.valid()) { ostringstream errorMsg; errorMsg << "Could not instantiate the RVRV matrix from the file [" << rvrvMatrixFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * If the number of rows in the RVRV matrix does not equal the number * * of rows in the G matrix, we have an unrecoverable error. Therefore,* * an error message is printed and then this program exits. * *********************************************************************/ if (rvrvMatrix.m != orderG) { ostringstream errorMsg; errorMsg << "The number of rows [" << rvrvMatrix.m << "] for the RVRV matrix [" << rvrvMatrixFile << "] does not equal the number of rows [" << orderG << "] for the G matrix [" << matrixStemName << ".G]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if /********************************************************************* * The following for loop is used to assign the trace of the RVRV * * matrix to traces[1]. However, all the diagonal elements of the * * RVRV matrix must be non-zero. If a zero valued diagonal element is * * found, then this program exits after printing an error message. * *********************************************************************/ for (long i = 0; i < rvrvMatrix.n; i++) { if (rvrvMatrix(i, i) != 0.0) { traces[1] += rvrvMatrix(i, i); } // if else { ostringstream errorMsg; errorMsg << "Found a zero diagonal entry for the RVRV matrix [" << rvrvMatrixFile << "] at [" << i << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // else } // for i /********************************************************************* * Now deleting the RV and RVRV matrix files. If an error occurs with * * unlink(), a warning message is printed. * *********************************************************************/ errno = 0; if (unlink(rvMatrixFile.c_str())) { ostringstream errorMsg; errorMsg << "Unable to remove the file [" << matrixStemName + ".RV" << "] due to: [" << strerror(errno) << "]."; printErrorMsg(VB_WARNING, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__); } // if errno = 0; if (unlink(rvrvMatrixFile.c_str())) { ostringstream errorMsg; errorMsg << "Unable to remove the file [" << matrixStemName + ".RVRV" << "] due to: [" << strerror(errno) << "]."; printErrorMsg(VB_WARNING, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__); } // if /********************************************************************* * Now assigning trace[2], which is the effective degree of freedom. * *********************************************************************/ traces[2] = (traces[0] * traces[0]) / traces[1]; /********************************************************************* * Adding the appropriate header lines and then writing out the Vec * * file. If an error occurs during the the write, an error message is * * printed and then this program exits. * *********************************************************************/ traces.AddHeader(""); traces.AddHeader(" Traces calculated on " + timedate()); traces.AddHeader(" Trace RV, TraceRVRV, and effdf (=TraceRV^2/TraceRVRV)"); traces.AddHeader(""); if (traces.WriteFile(matrixStemName + ".traces")) { ostringstream errorMsg; errorMsg << "Unable to write Vec file [" << matrixStemName << ".traces]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), __LINE__, __FUNCTION__, __FILE__, 1); } // if } // void computeTraces(const string& matrixStemName) voxbo-1.8.5~svn1246/stand_alone/regression.h000066400000000000000000000033731153177201300207520ustar00rootroot00000000000000 // regression.h // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee #ifndef REGRESSION_H #define REGRESSION_H #include #include #include #include "vb_common_incs.h" #include void readInTesFiles(const string &matrixStemName,vector &tesList) throw(); void makeMatrixK(const string& matrixStemName) throw(); void makeMatrixKG(const string& matrixStemName) throw(); void makeMatrixF3(const string& matrixStemName) throw(); bool isFileReadable(const string& fileName) throw(); unsigned short checkTesDims(const unsigned short dimT, const unsigned short dimX, const unsigned short dimY, const unsigned short dimZ, const Tes& theTes) throw(); unsigned short shiftLeft(const unsigned short index, const unsigned short dimIndex); void computeTraces(const string& matrixStemName); #endif // REGRESSION_H voxbo-1.8.5~svn1246/stand_alone/sliceacq.cpp000066400000000000000000001713661153177201300207210ustar00rootroot00000000000000 // sliceacq.cpp // Copyright (c) 1998-2010 by The VoxBo Development Team // This file is part of VoxBo // // VoxBo 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. // // VoxBo 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 VoxBo. If not, see . // // For general information on VoxBo, including the latest complete // source code and binary distributions, manual, and associated files, // see the VoxBo home page at: http://www.voxbo.org/ // // original version written by Kosh Banerjee // modified slightly by Dan Kimberg, to fix little issues /********************************************************************* * This program carries out Slice Acquisition Correction. To carry * * out this task, 2 quantities will have to be either specified by * * the user or have to be determined by this program. These two * * quantities are: * * * * sliceTime * * firstSliceTime * * * * The hierarchy to determine the above two quantities is: * * 1) The user specifies them on the command line. * * 2) This program reads the Slice Acquisition configuration file. * * 3) firstSliceTime is set to 0 and sliceTime to TR/dimZ. * *********************************************************************/ #include "sliceacq.h" /********************************************************************* * Need a global VBPrefs object named vbp. vbp is used to determine * * the VoxBo root directory. * *********************************************************************/ VBPrefs vbp; void usage(const unsigned short exitValue, char *progName); int main(int argc, char *argv[]) { tesHeaderInfo reqHeaderInfo; reqHeaderInfo.tr = 0; reqHeaderInfo.pulseSeq = ""; reqHeaderInfo.fieldStrength = 0.0; string paramFilePath; string tesFile; string outFile; /********************************************************************* * VARIABLES: * * redo - flag used to determine if the input 4D data file is to be * * corrected, even though is has already been corrected. The * * default is to not recorrect a 4D data file. * * alreadyCorrected - will be set to true if the input 4D data file * * has already been corrected. * * dimT - the maximum value of the time dimension in the 4D data file.* * dimX - the maximum value of the X dimension in the 4D data file. * * dimY - the maximum value of the Y dimension in the 4D data file. * * dimZ - the maximum value of the Z dimension in the 4D data file. * * sliceTime - used to hold the user specified value of slice time. * * firstSliceTime - time when the first slice was taken in ms. * *********************************************************************/ bool redo = false; bool alreadyCorrected = false; unsigned int dimT = 0; unsigned int dimX = 0; unsigned int dimY = 0; unsigned int dimZ = 0; double sliceTime = 0.0; double firstSliceTime = -1.0; /********************************************************************* * If no command line options have been used, then usage information * * is displayed and the program exits. * *********************************************************************/ if (argc == 1) { usage(1, argv[0]); } // if /********************************************************************* * Now processing the command line options. * * -h ==> Display usage information. * * -i ==> Specifies the input 4D data file. * * -o ==> Specifies the output 4D data file name. * * -r ==> Override the default of not correcting a file if it has * * already been corrected. * * -s ==> Used to specify the slice time. * * -t ==> Time when the first slice was taken in milliseconds. * * -c ==> User sepcified TR, in milliseconds. * * -p ==> Specify the configuration file. * * -v ==> Print out the gobal VoxBo version number. * * * * Now processing the command line options. printHelp is a flag * * variable, used to determine if the "-h" command line option was * * used or not. printVersion is a flag variable, used to determine if * * the "-v" command line option was used or not. * *********************************************************************/ bool printHelp = false; bool printVersion = false; bool interleaved = false; // DYK int userTR = -1; // DYK added interleaved processOpts(argc, argv, ":hi:o:rs:t:c:vp:n", "bZZbddibZb", &printHelp, &tesFile, &outFile, &redo, &sliceTime, &firstSliceTime, &userTR, &printVersion, ¶mFilePath,&interleaved); /********************************************************************* * Now checking to see if usage information needs to be printed. * *********************************************************************/ if (printHelp) { usage(0, argv[0]); } // if /********************************************************************* * Now checking to see if the global VoxBo version needs to be * * printed. * *********************************************************************/ if (printVersion) { printf("\nVoxBo v%s\n",vbversion.c_str()); } // if /********************************************************************* * If just sliceTime was specified at the command line (and not * * firstSliceTime), then firstSliceTime is assumed to be zero. * *********************************************************************/ if ( (sliceTime > 0.0) && (firstSliceTime == -1.0) ) { firstSliceTime = 0.0; } // if /********************************************************************* * If the input 4D data file has not been specified, then an error * * message is sent to stderr, and then usage information is * * displayed. * *********************************************************************/ if (tesFile.size() == 0) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] Must specify the input 4D data file name."; printErrorMsg(VB_ERROR, errorMsg.str()); usage(1, argv[0]); } // if /********************************************************************* * If an output file name was not specified at the command line, then * * the default value of the input 4D data file is assigned. * *********************************************************************/ if (outFile.size() == 0) { outFile = tesFile; } // if /********************************************************************* * instantiating a Tes object from tesFile. * *********************************************************************/ Tes theTes(tesFile); /********************************************************************* * If theTes has invalid data, then an error message is printed and * * then this program exits. * *********************************************************************/ if (!theTes.data_valid) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] Invalid data for Tes file [" << tesFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } // if /********************************************************************* * If theTes has an invalid header, then an error message is printed * * and then this program exits. * *********************************************************************/ if (!theTes.header_valid) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] Invalid header for Tes file [" << tesFile << "]."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } // if // DYK grab TR info reqHeaderInfo.tr=theTes.voxsize[3]; /********************************************************************* * The following for loop is used to traverse the string objects in * * the header data member of the Tes class to see if the input 4D data* * file has already been corrected or not, and to get the values of * * TR, PulseSeq, and FieldStrength. * *********************************************************************/ for (int i = 0; i < (int ) theTes.header.size(); i++) { /********************************************************************* * tempStr is assigned theTes.header[i]. * *********************************************************************/ string tempStr = theTes.header[i]; /********************************************************************* * If tempStr is non-empty, then we can get tokens from it, using a * * space and a tab as field delimiters. * *********************************************************************/ if (tempStr.length() > 0) { tokenlist strToken(tempStr); /********************************************************************* * Now if "AcqCorrect:" is in tempStr, then the input 4D data file * * has already been corrected. * *********************************************************************/ if (strToken[0] == "AcqCorrect:") { /********************************************************************* * alreadyCorrected is set to true since the input 4D data file has * * already been corrected. * *********************************************************************/ alreadyCorrected = true; } // if /********************************************************************* * If the current header line holds the TR value, then it is assigned * * to reqHeaderInfo.tr. NOTE: The TR value will be the second token * * (token number 1) in the header line. * *********************************************************************/ // DYK: TR now in voxsize[3] // else if (strToken.getToken(0) == "TR(msecs):") // { // reqHeaderInfo.tr = atoi(strToken.getToken(1).c_str()); // } // else if /********************************************************************* * If the current header line holds the PulseSeq value, then it is * * assigned to reqHeaderInfo.pulseSeq. NOTE: The PulseSeq value will * * be the second token (token number 1) in the header line. * *********************************************************************/ else if (strToken[0] == "PulseSeq:") { reqHeaderInfo.pulseSeq = strToken[1]; } // else if /********************************************************************* * If the current header line holds the FieldStrength value, then it * * is assigned to reqHeaderInfo.fieldStrength. NOTE: The Field * * Strength value will be the second token (token number 1) in the * * header line. * *********************************************************************/ else if (strToken[0] == "FieldStrength:") reqHeaderInfo.fieldStrength = strtod(strToken[1]); } // if } // for i /********************************************************************* * If the user supplied a TR value at the command line, then * * reqHeaderInfo.tr is set to that value. * *********************************************************************/ if (userTR > 0) { reqHeaderInfo.tr = userTR; } // if /********************************************************************* * If just firstSliceTime was specified at the command line (and not * * sliceTime), then sliceTIme is set to (tr - fileSliceTIme)/dimZ. * *********************************************************************/ if ( (sliceTime <= 0.0) && (firstSliceTime >= 0.0) ) { sliceTime = (reqHeaderInfo.tr - firstSliceTime) / dimZ; } // if /********************************************************************* * If the input 4D data file has already been corrected and the redo * * flag was not used, then an error message in printed out and this * * program exits. * *********************************************************************/ if ( (alreadyCorrected == true) && (redo == false) ) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] The 4D data file [" << tesFile << "] has already been corrected."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } // if /********************************************************************* * Now assigning dimT, dimX, dimY, and dimZ. * *********************************************************************/ dimT = theTes.dimt; dimX = theTes.dimx; dimY = theTes.dimy; dimZ = theTes.dimz; /********************************************************************* * If the user did not specify sliceTime nor firstSliceTime on the * * command line, then we need to determine these quantities. * *********************************************************************/ if ( (sliceTime <= 0.0) && (firstSliceTime == -1.0) ) { /********************************************************************* * Now checking to see if the user specified a parameter file. If the * * user did not specify a parameter file (at the command line), then * * the default value is used. * *********************************************************************/ if (paramFilePath.size() == 0) { vbp.init(); paramFilePath = vbp.rootdir + "etc/sliceacq.cfg"; } // if /********************************************************************* * Now getting the slice time and time of first slice from the Slice * * Acquisition parameters file. * *********************************************************************/ int pauseFlag = 0; readParamFile(paramFilePath, reqHeaderInfo.pulseSeq, reqHeaderInfo.fieldStrength, &sliceTime, &pauseFlag, reqHeaderInfo.tr, dimZ); /********************************************************************* * If sliceTime > 0, then it was successfully determined from the * * Slice Acquisition configuration file. In that case, we check * * pauseFlag to see how to set firstSliceTime. * *********************************************************************/ if (sliceTime > 0.0) { /********************************************************************* * If pauseFlag is zero, then there was no pause. This implies that * * firstSliceTime is zero. * *********************************************************************/ if (!pauseFlag) { firstSliceTime = 0.0; } // if /********************************************************************* * If pauseFlag is one, then there was a pause. firstSliceTime is set * * accordingly. * *********************************************************************/ else { firstSliceTime = (double ) reqHeaderInfo.tr - ((double ) dimZ * sliceTime); } // else } // if /********************************************************************* * If sliceTime is still zero after the call to readParamFile(), then * * we were unable to look it up from the configuration file. * * it is assumed that firstSliceTime is 0 (no pause) and sliceTime is * * set to TR/dimZ. * *********************************************************************/ else { firstSliceTime = 0.0; sliceTime = (double ) reqHeaderInfo.tr / (double ) dimZ; } // else } // if /********************************************************************* * The the correction parameter values are invalid, then an error * * message is printed and then this program exits. * *********************************************************************/ if (!sanityCheckOfValues(sliceTime, firstSliceTime, reqHeaderInfo.tr, dimZ)) { ostringstream errorMsg; errorMsg << "Line Number [" << __LINE__ << "] Correction parameter values are not valid: TR = [" << reqHeaderInfo.tr << "] dimZ = [" << dimZ << "] sliceTime = [" << sliceTime << "] firstSliceTime = [" << firstSliceTime << "]."; // DYK if (interleaved) errorMsg << " Order is interleaved."; else errorMsg << " Order is ascending."; printErrorMsgAndExit(VB_ERROR, errorMsg.str(), 1); } // if /********************************************************************* * If the correction parameter values are valid, they are simply * * printed out. * *********************************************************************/ else { ostringstream errorMsg; errorMsg << "Correction parameter values are: TR = [" << reqHeaderInfo.tr << "] dimZ = [" << dimZ << "] sliceTime = [" << sliceTime << "] firstSliceTime = [" << firstSliceTime << "]."; // DYK if (interleaved) errorMsg << " Order is interleaved."; else errorMsg << " Order is ascending."; printErrorMsg(VB_INFO, errorMsg.str()); } // else /********************************************************************* * Now declaring two VB_Vector objects. * *********************************************************************/ VB_Vector timeAcquired(dimZ); VB_Vector shiftAmount(dimZ); /********************************************************************* * The following for loop is used to assign values to timeAcquired[] * * and shiftAmount[]. * *********************************************************************/ // DYK: added the following to handle interleaved or not for (unsigned int i=0; i Specify the input 4D data file. Required.", "-o Specify the output file name. Optional.", " Default output file name is the input 4D data file", " name.", "-s Specify the slice time in milliseconds.", " Values <= 0 are treated as if the slice time was not", " specified. Optional.", "-t