diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fe41843 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +build/ +dist/ +docSRC/_build/ + +*.c +*.cpp +*.so +*.pyc diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + 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 +. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..5231a89 --- /dev/null +++ b/INSTALL @@ -0,0 +1,50 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +To use the Python interface, you need the All Scale Tomographic Reconstruction Antwerp Toolbox: +https://code.google.com/p/astra-toolbox/ +Please install the ASTRA toolbox first. + +Other requirements: Cython (version >= 0.13), NumPy + +Use install.sh to install the Python interface to the ASTRA toolbox. +Only run install.sh as ./install.sh in the base directory of the interface code. +You need write permission to the $PYTHON_PATH directory. +We recommend using a Python virtualenv if root access is impossible. +The Python interface to the ASTRA Toolbox uses Python version 2. + +Usage: ./install.sh [-i astra_include_path] [-l astra_library_path] [-p python_executable_path] [-c cuda_path] + + -i astra_include_path: specify path to astra header files (without trailing astra/) (Optional) + -l astra_library_path: specify parent path of astra library file (Optional) + -p python_executable_path: specify path to python executable (Optional) + -c cuda_path: path to CUDA (Optional) + -h: print this help (Optional) + +Note that the paths only have to be specified if they are not already in your $LD_LIBRARY_PATH, etcetera. + +When compiling with CUDA, the astra_include_path should be set to the 'include' directory of the ASTRA toolbox +source. diff --git a/LICENSE b/LICENSE new file mode 120000 index 0000000..d24842f --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +COPYING \ No newline at end of file diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..1a6ba04 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,116 @@ +# file GENERATED by distutils, do NOT edit +COPYING +INSTALL +README +builder.py +install.sh +astra/ASTRAProjector.py +astra/PyAlgorithmFactory.pxd +astra/PyAlgorithmManager.pxd +astra/PyData2DManager.pxd +astra/PyData3DManager.pxd +astra/PyIncludes.pxd +astra/PyMatrixManager.pxd +astra/PyProjector2DFactory.pxd +astra/PyProjector2DManager.pxd +astra/PyXMLDocument.pxd +astra/__init__.py +astra/algorithm.py +astra/algorithm_c.cpp +astra/algorithm_c.pyx +astra/astra.py +astra/astra_c.cpp +astra/astra_c.pyx +astra/creators.py +astra/data2d.py +astra/data2d_c.cpp +astra/data2d_c.pyx +astra/data3d.py +astra/data3d_c.cpp +astra/data3d_c.pyx +astra/extrautils.c +astra/extrautils.pyx +astra/functions.py +astra/matlab.py +astra/matrix.py +astra/matrix_c.cpp +astra/matrix_c.pyx +astra/projector.py +astra/projector_c.cpp +astra/projector_c.pyx +astra/utils.cpp +astra/utils.pxd +astra/utils.pyx +doc/.buildinfo +doc/ASTRAProjector.html +doc/algorithm.html +doc/creators.html +doc/data2d.html +doc/data3d.html +doc/functions.html +doc/genindex.html +doc/index.html +doc/matlab.html +doc/matrix.html +doc/objects.inv +doc/projector.html +doc/py-modindex.html +doc/search.html +doc/searchindex.js +doc/_modules/index.html +doc/_modules/astra/ASTRAProjector.html +doc/_modules/astra/algorithm.html +doc/_modules/astra/creators.html +doc/_modules/astra/data2d.html +doc/_modules/astra/data3d.html +doc/_modules/astra/functions.html +doc/_modules/astra/matlab.html +doc/_modules/astra/matrix.html +doc/_modules/astra/projector.html +doc/_sources/ASTRAProjector.txt +doc/_sources/algorithm.txt +doc/_sources/creators.txt +doc/_sources/data2d.txt +doc/_sources/data3d.txt +doc/_sources/functions.txt +doc/_sources/index.txt +doc/_sources/matlab.txt +doc/_sources/matrix.txt +doc/_sources/projector.txt +doc/_static/ajax-loader.gif +doc/_static/basic.css +doc/_static/comment-bright.png +doc/_static/comment-close.png +doc/_static/comment.png +doc/_static/default.css +doc/_static/doctools.js +doc/_static/down-pressed.png +doc/_static/down.png +doc/_static/file.png +doc/_static/jquery.js +doc/_static/minus.png +doc/_static/plus.png +doc/_static/pygments.css +doc/_static/searchtools.js +doc/_static/sidebar.js +doc/_static/underscore.js +doc/_static/up-pressed.png +doc/_static/up.png +doc/_static/websupport.js +examples/phantom.mat +examples/s001_sinogram_par2d.py +examples/s002_data2d.py +examples/s003_gpu_reconstruction.py +examples/s004_cpu_reconstruction.py +examples/s005_3d_geometry.py +examples/s006_3d_data.py +examples/s007_3d_reconstruction.py +examples/s008_gpu_selection.py +examples/s009_projection_matrix.py +examples/s010_supersampling.py +examples/s011_object_info.py +examples/s012_masks.py +examples/s013_constraints.py +examples/s014_FBP.py +examples/s015_fp_bp.py +examples/s016_plots.py diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..a0cdf3a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,7 @@ +include INSTALL +include COPYING +include install.sh +recursive-include examples *.py *.mat +recursive-include astra *.pyx *.pxd +recursive-include doc * + diff --git a/README b/README new file mode 120000 index 0000000..842bf0e --- /dev/null +++ b/README @@ -0,0 +1 @@ +INSTALL \ No newline at end of file diff --git a/astra/ASTRAProjector.py b/astra/ASTRAProjector.py new file mode 100644 index 0000000..7553a7c --- /dev/null +++ b/astra/ASTRAProjector.py @@ -0,0 +1,139 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + + +import creators as ac +import math +import data2d + + +class ASTRAProjector2DTranspose(): + """Implements the ``proj.T`` functionality. + + Do not use directly, since it can be accessed as member ``.T`` of + an :class:`ASTRAProjector2D` object. + + """ + def __init__(self, parentProj): + self.parentProj = parentProj + + def __mul__(self, data): + return self.parentProj.backProject(data) + + +class ASTRAProjector2D(object): + """Helps with various common ASTRA Toolbox 2D operations. + + This class can perform several often used toolbox operations, such as: + + * Forward projecting + * Back projecting + * Reconstructing + + Note that this class has a some computational overhead, because it + copies a lot of data. If you use many repeated operations, directly + using the PyAstraToolbox methods directly is faster. + + You can use this class as an abstracted weight matrix :math:`W`: multiplying an instance + ``proj`` of this class by an image results in a forward projection of the image, and multiplying + ``proj.T`` by a sinogram results in a backprojection of the sinogram:: + + proj = ASTRAProjector2D(...) + fp = proj*image + bp = proj.T*sinogram + + :param proj_geom: The projection geometry. + :type proj_geom: :class:`dict` + :param vol_geom: The volume geometry. + :type vol_geom: :class:`dict` + :param proj_type: Projector type, such as ``'line'``, ``'linear'``, ... + :type proj_type: :class:`string` + :param useCUDA: If ``True``, use CUDA for calculations, when possible. + :type useCUDA: :class:`bool` + """ + + def __init__(self, proj_geom, vol_geom, proj_type, useCUDA=False): + self.vol_geom = vol_geom + self.recSize = vol_geom['GridColCount'] + self.angles = proj_geom['ProjectionAngles'] + self.nDet = proj_geom['DetectorCount'] + nexpow = int(pow(2, math.ceil(math.log(2 * self.nDet, 2)))) + self.filterSize = nexpow / 2 + 1 + self.nProj = self.angles.shape[0] + self.proj_geom = proj_geom + self.proj_id = ac.create_projector(proj_type, proj_geom, vol_geom) + self.useCUDA = useCUDA + self.T = ASTRAProjector2DTranspose(self) + + def backProject(self, data): + """Backproject a sinogram. + + :param data: The sinogram data or ID. + :type data: :class:`numpy.ndarray` or :class:`int` + :returns: :class:`numpy.ndarray` -- The backprojection. + + """ + vol_id, vol = ac.create_backprojection( + data, self.proj_id, self.useCUDA, True) + data2d.delete(vol_id) + return vol + + def forwardProject(self, data): + """Forward project an image. + + :param data: The image data or ID. + :type data: :class:`numpy.ndarray` or :class:`int` + :returns: :class:`numpy.ndarray` -- The forward projection. + + """ + sin_id, sino = ac.create_sino(data, self.proj_id, self.useCUDA, True) + data2d.delete(sin_id) + return sino + + def reconstruct(self, data, method, **kwargs): + """Reconstruct an image from a sinogram. + + :param data: The sinogram data or ID. + :type data: :class:`numpy.ndarray` or :class:`int` + :param method: Name of the reconstruction algorithm. + :type method: :class:`string` + :param kwargs: Additional named parameters to pass to :func:`astra.creators.create_reconstruction`. + :returns: :class:`numpy.ndarray` -- The reconstruction. + + Example of a SIRT reconstruction using CUDA:: + + proj = ASTRAProjector2D(...) + rec = proj.reconstruct(sinogram,'SIRT_CUDA',iterations=1000) + + """ + kwargs['returnData'] = True + rec_id, rec = ac.create_reconstruction( + method, self.proj_id, data, **kwargs) + data2d.delete(rec_id) + return rec + + def __mul__(self, data): + return self.forwardProject(data) diff --git a/astra/PyAlgorithmFactory.pxd b/astra/PyAlgorithmFactory.pxd new file mode 100644 index 0000000..e235f00 --- /dev/null +++ b/astra/PyAlgorithmFactory.pxd @@ -0,0 +1,36 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string +from libcpp cimport bool +from PyIncludes cimport * + +cdef extern from "astra/AstraObjectFactory.h" namespace "astra": + cdef cppclass CAlgorithmFactory: + CAlgorithmFactory() + CAlgorithm *create(string) + +cdef extern from "astra/AstraObjectFactory.h" namespace "astra::CAlgorithmFactory": + cdef CAlgorithmFactory* getSingletonPtr() diff --git a/astra/PyAlgorithmManager.pxd b/astra/PyAlgorithmManager.pxd new file mode 100644 index 0000000..9a1bc17 --- /dev/null +++ b/astra/PyAlgorithmManager.pxd @@ -0,0 +1,40 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string +from libcpp cimport bool +from PyIncludes cimport * + +cdef extern from "astra/AstraObjectManager.h" namespace "astra": + cdef cppclass CAlgorithmManager: + int store(CAlgorithm *) + CAlgorithm * get(int) + void remove(int) + void clear() + string info() + +cdef extern from "astra/AstraObjectManager.h" namespace "astra::CAlgorithmManager": + cdef CAlgorithmManager* getSingletonPtr() + diff --git a/astra/PyData2DManager.pxd b/astra/PyData2DManager.pxd new file mode 100644 index 0000000..3ea4e3b --- /dev/null +++ b/astra/PyData2DManager.pxd @@ -0,0 +1,39 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string + +from PyIncludes cimport * + +cdef extern from "astra/AstraObjectManager.h" namespace "astra": + cdef cppclass CData2DManager: + string info() + void clear() + void remove(int i) + int store(CFloat32Data2D *) + CFloat32Data2D * get(int i) + +cdef extern from "astra/AstraObjectManager.h" namespace "astra::CData2DManager": + cdef CData2DManager* getSingletonPtr() diff --git a/astra/PyData3DManager.pxd b/astra/PyData3DManager.pxd new file mode 100644 index 0000000..048b0c5 --- /dev/null +++ b/astra/PyData3DManager.pxd @@ -0,0 +1,39 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string + +from PyIncludes cimport * + +cdef extern from "astra/AstraObjectManager.h" namespace "astra": + cdef cppclass CData3DManager: + string info() + void clear() + void remove(int i) + int store(CFloat32Data3D *) + CFloat32Data3D * get(int i) + +cdef extern from "astra/AstraObjectManager.h" namespace "astra::CData3DManager": + cdef CData3DManager* getSingletonPtr() diff --git a/astra/PyIncludes.pxd b/astra/PyIncludes.pxd new file mode 100644 index 0000000..154495c --- /dev/null +++ b/astra/PyIncludes.pxd @@ -0,0 +1,215 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp cimport bool +from libcpp.string cimport string +from PyXMLDocument cimport XMLNode + +cdef extern from "astra/Globals.h" namespace "astra": + ctypedef float float32 + ctypedef double float64 + ctypedef unsigned short int uint16 + ctypedef signed short int sint16 + ctypedef unsigned char uchar8 + ctypedef signed char schar8 + ctypedef int int32 + ctypedef short int int16 + +cdef extern from "astra/Config.h" namespace "astra": + cdef cppclass Config: + Config() + XMLNode *self + +cdef extern from "astra/VolumeGeometry2D.h" namespace "astra": + cdef cppclass CVolumeGeometry2D: + bool initialize(Config) + int getGridColCount() + int getGridRowCount() + int getGridTotCount() + float32 getWindowLengthX() + float32 getWindowLengthY() + float32 getWindowArea() + float32 getPixelLengthX() + float32 getPixelLengthY() + float32 getPixelArea() + float32 getWindowMinX() + float32 getWindowMinY() + float32 getWindowMaxX() + float32 getWindowMaxY() + + +cdef extern from "astra/Float32VolumeData2D.h" namespace "astra": + cdef cppclass CFloat32VolumeData2D: + CFloat32VolumeData2D(CVolumeGeometry2D*) + CVolumeGeometry2D * getGeometry() + int getWidth() + int getHeight() + void changeGeometry(CVolumeGeometry2D*) + + + +cdef extern from "astra/ProjectionGeometry2D.h" namespace "astra": + cdef cppclass CProjectionGeometry2D: + CProjectionGeometry2D() + bool initialize(Config) + int getDetectorCount() + int getProjectionAngleCount() + bool isOfType(string) + float32 getProjectionAngle(int) + float32 getDetectorWidth() + +cdef extern from "astra/Float32Data2D.h" namespace "astra::CFloat32Data2D": + cdef enum EDataType: + BASE,PROJECTION,VOLUME + +cdef extern from "astra/Float32Data2D.h" namespace "astra": + cdef cppclass CFloat32Data2D: + bool isInitialized() + int getSize() + float32 *getData() + float32 **getData2D() + int getWidth() + int getHeight() + EDataType getType() + + + + +cdef extern from "astra/SparseMatrixProjectionGeometry2D.h" namespace "astra": + cdef cppclass CSparseMatrixProjectionGeometry2D: + CSparseMatrixProjectionGeometry2D() + +cdef extern from "astra/FanFlatProjectionGeometry2D.h" namespace "astra": + cdef cppclass CFanFlatProjectionGeometry2D: + CFanFlatProjectionGeometry2D() + +cdef extern from "astra/FanFlatVecProjectionGeometry2D.h" namespace "astra": + cdef cppclass CFanFlatVecProjectionGeometry2D: + CFanFlatVecProjectionGeometry2D() + +cdef extern from "astra/ParallelProjectionGeometry2D.h" namespace "astra": + cdef cppclass CParallelProjectionGeometry2D: + CParallelProjectionGeometry2D() + + +cdef extern from "astra/Float32ProjectionData2D.h" namespace "astra": + cdef cppclass CFloat32ProjectionData2D: + CFloat32ProjectionData2D(CProjectionGeometry2D*) + CProjectionGeometry2D * getGeometry() + void changeGeometry(CProjectionGeometry2D*) + int getDetectorCount() + int getAngleCount() + +cdef extern from "astra/Algorithm.h" namespace "astra": + cdef cppclass CAlgorithm: + bool initialize(Config) + void run(int) + bool isInitialized() + +cdef extern from "astra/ReconstructionAlgorithm2D.h" namespace "astra": + cdef cppclass CReconstructionAlgorithm2D: + bool getResidualNorm(float32&) + +cdef extern from "astra/Projector2D.h" namespace "astra": + cdef cppclass CProjector2D: + bool isInitialized() + CProjectionGeometry2D* getProjectionGeometry() + CVolumeGeometry2D* getVolumeGeometry() + CSparseMatrix* getMatrix() + +cdef extern from "astra/SparseMatrix.h" namespace "astra": + cdef cppclass CSparseMatrix: + CSparseMatrix(unsigned int,unsigned int,unsigned long) + unsigned int m_iWidth + unsigned int m_iHeight + unsigned long m_lSize + bool isInitialized() + float32* m_pfValues + unsigned int* m_piColIndices + unsigned long* m_plRowStarts + +cdef extern from "astra/Float32Data3DMemory.h" namespace "astra": + cdef cppclass CFloat32Data3DMemory: + CFloat32Data3DMemory() + bool isInitialized() + int getSize() + int getWidth() + int getHeight() + int getDepth() + void updateStatistics() + float32 *getData() + float32 ***getData3D() + + +cdef extern from "astra/VolumeGeometry3D.h" namespace "astra": + cdef cppclass CVolumeGeometry3D: + CVolumeGeometry3D() + bool initialize(Config) + +cdef extern from "astra/ProjectionGeometry3D.h" namespace "astra": + cdef cppclass CProjectionGeometry3D: + CProjectionGeometry3D() + bool initialize(Config) + + +cdef extern from "astra/Float32VolumeData3DMemory.h" namespace "astra": + cdef cppclass CFloat32VolumeData3DMemory: + CFloat32VolumeData3DMemory(CVolumeGeometry3D*) + + +cdef extern from "astra/ParallelProjectionGeometry3D.h" namespace "astra": + cdef cppclass CParallelProjectionGeometry3D: + CParallelProjectionGeometry3D() + +cdef extern from "astra/ParallelVecProjectionGeometry3D.h" namespace "astra": + cdef cppclass CParallelVecProjectionGeometry3D: + CParallelVecProjectionGeometry3D() + +cdef extern from "astra/ConeProjectionGeometry3D.h" namespace "astra": + cdef cppclass CConeProjectionGeometry3D: + CConeProjectionGeometry3D() + bool initialize(Config) + +cdef extern from "astra/ConeVecProjectionGeometry3D.h" namespace "astra": + cdef cppclass CConeVecProjectionGeometry3D: + CConeVecProjectionGeometry3D() + +cdef extern from "astra/Float32ProjectionData3DMemory.h" namespace "astra": + cdef cppclass CFloat32ProjectionData3DMemory: + CFloat32ProjectionData3DMemory(CProjectionGeometry3D*) + CFloat32ProjectionData3DMemory(CConeProjectionGeometry3D*) + +cdef extern from "astra/Float32Data3D.h" namespace "astra": + cdef cppclass CFloat32Data3D: + CFloat32Data3D() + bool isInitialized() + int getSize() + int getWidth() + int getHeight() + int getDepth() + void updateStatistics() + + + diff --git a/astra/PyMatrixManager.pxd b/astra/PyMatrixManager.pxd new file mode 100644 index 0000000..e14325e --- /dev/null +++ b/astra/PyMatrixManager.pxd @@ -0,0 +1,39 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string + +from PyIncludes cimport * + +cdef extern from "astra/AstraObjectManager.h" namespace "astra": + cdef cppclass CMatrixManager: + string info() + void clear() + void remove(int i) + int store(CSparseMatrix *) + CSparseMatrix * get(int i) + +cdef extern from "astra/AstraObjectManager.h" namespace "astra::CMatrixManager": + cdef CMatrixManager* getSingletonPtr() diff --git a/astra/PyProjector2DFactory.pxd b/astra/PyProjector2DFactory.pxd new file mode 100644 index 0000000..7e30142 --- /dev/null +++ b/astra/PyProjector2DFactory.pxd @@ -0,0 +1,35 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string +from libcpp cimport bool +from PyIncludes cimport * + +cdef extern from "astra/AstraObjectFactory.h" namespace "astra": + cdef cppclass CProjector2DFactory: + CProjector2D *create(Config) + +cdef extern from "astra/AstraObjectFactory.h" namespace "astra::CProjector2DFactory": + cdef CProjector2DFactory* getSingletonPtr() diff --git a/astra/PyProjector2DManager.pxd b/astra/PyProjector2DManager.pxd new file mode 100644 index 0000000..ad6a23c --- /dev/null +++ b/astra/PyProjector2DManager.pxd @@ -0,0 +1,39 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string + +from PyIncludes cimport * + +cdef extern from "astra/AstraObjectManager.h" namespace "astra": + cdef cppclass CProjector2DManager: + string info() + void clear() + void remove(int i) + int store(CProjector2D *) + CProjector2D * get(int i) + +cdef extern from "astra/AstraObjectManager.h" namespace "astra::CProjector2DManager": + cdef CProjector2DManager* getSingletonPtr() diff --git a/astra/PyXMLDocument.pxd b/astra/PyXMLDocument.pxd new file mode 100644 index 0000000..69781f1 --- /dev/null +++ b/astra/PyXMLDocument.pxd @@ -0,0 +1,65 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +from libcpp.string cimport string +from libcpp cimport bool +from libcpp.list cimport list +from libcpp.vector cimport vector + +cdef extern from "astra/Globals.h" namespace "astra": + ctypedef float float32 + ctypedef double float64 + ctypedef unsigned short int uint16 + ctypedef signed short int sint16 + ctypedef unsigned char uchar8 + ctypedef signed char schar8 + ctypedef int int32 + ctypedef short int int16 + +cdef extern from "astra/XMLNode.h" namespace "astra": + cdef cppclass XMLNode: + string getName() + XMLNode *addChildNode(string name) + XMLNode *addChildNode(string, string) + void addAttribute(string, string) + void addAttribute(string, float32) + void addOption(string, string) + bool hasOption(string) + string getAttribute(string) + list[XMLNode *] getNodes() + vector[float32] getContentNumericalArray() + string getContent() + bool hasAttribute(string) + +cdef extern from "astra/XMLDocument.h" namespace "astra": + cdef cppclass XMLDocument: + void saveToFile(string sFilename) + XMLNode *getRootNode() + +cdef extern from "astra/XMLDocument.h" namespace "astra::XMLDocument": + cdef XMLDocument *createDocument(string rootname) diff --git a/astra/__init__.py b/astra/__init__.py new file mode 100644 index 0000000..bdf9bc5 --- /dev/null +++ b/astra/__init__.py @@ -0,0 +1,37 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +import matlab as m +from creators import astra_dict,create_vol_geom, create_proj_geom, create_backprojection, create_sino, create_reconstruction, create_projector,create_sino3d_gpu +from functions import data_op, add_noise_to_sino,clear +from extrautils import clipCircle +from ASTRAProjector import ASTRAProjector2D +import data2d +import astra +import data3d +import algorithm +import projector +import matrix + diff --git a/astra/algorithm.py b/astra/algorithm.py new file mode 100644 index 0000000..4998d7e --- /dev/null +++ b/astra/algorithm.py @@ -0,0 +1,76 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import algorithm_c as a + +def create(config): + """Create algorithm object. + + :param config: Algorithm options. + :type config: :class:`dict` + :returns: :class:`int` -- the ID of the constructed object. + + """ + return a.create(config) + +def run(i, iterations=0): + """Run an algorithm. + + :param i: ID of object. + :type i: :class:`int` + :param iterations: Number of iterations to run. + :type iterations: :class:`int` + + """ + return a.run(i,iterations) + +def get_res_norm(i): + """Get residual norm of algorithm. + + :param i: ID of object. + :type i: :class:`int` + :returns: :class:`float` -- The residual norm. + + """ + + return a.get_res_norm(i) + +def delete(ids): + """Delete a matrix object. + + :param ids: ID or list of ID's to delete. + :type ids: :class:`int` or :class:`list` + + """ + return a.delete(ids) + +def clear(): + """Clear all matrix objects.""" + return a.clear() + +def info(): + """Print info on matrix objects in memory.""" + return a.info() diff --git a/astra/algorithm_c.pyx b/astra/algorithm_c.pyx new file mode 100644 index 0000000..b945fac --- /dev/null +++ b/astra/algorithm_c.pyx @@ -0,0 +1,105 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +# distutils: language = c++ +# distutils: libraries = astra + +from PyIncludes cimport * + +cimport PyAlgorithmManager +from PyAlgorithmManager cimport CAlgorithmManager + +cimport PyAlgorithmFactory +from PyAlgorithmFactory cimport CAlgorithmFactory + +cimport PyXMLDocument +from PyXMLDocument cimport XMLDocument + +cimport utils + +cdef CAlgorithmManager * manAlg = PyAlgorithmManager.getSingletonPtr() + +cdef extern from *: + CReconstructionAlgorithm2D * dynamic_cast_recAlg "dynamic_cast" (CAlgorithm * ) except NULL + + +def create(config): + cdef XMLDocument * xml = utils.dict2XML('Algorithm', config) + cdef Config cfg + cdef CAlgorithm * alg + cfg.self = xml.getRootNode() + alg = PyAlgorithmFactory.getSingletonPtr( + ).create(cfg.self.getAttribute("type")) + if alg == NULL: + del xml + raise Exception("Unknown algorithm.") + if not alg.initialize(cfg): + del xml + del alg + raise Exception("Algorithm not initialized.") + del xml + return manAlg.store(alg) + +cdef CAlgorithm * getAlg(i) except NULL: + cdef CAlgorithm * alg = manAlg.get(i) + if alg == NULL: + raise Exception("Unknown algorithm.") + if not alg.isInitialized(): + raise Exception("Algorithm not initialized.") + return alg + + +def run(i, iterations=0): + cdef CAlgorithm * alg = getAlg(i) + alg.run(iterations) + + +def get_res_norm(i): + cdef CReconstructionAlgorithm2D * pAlg2D + cdef CAlgorithm * alg = getAlg(i) + cdef float32 res = 0.0 + pAlg2D = dynamic_cast_recAlg(alg) + if pAlg2D == NULL: + raise Exception("Operation not supported.") + if not pAlg2D.getResidualNorm(res): + raise Exception("Operation not supported.") + return res + + +def delete(ids): + try: + for i in ids: + manAlg.remove(i) + except TypeError: + manAlg.remove(ids) + + +def clear(): + manAlg.clear() + + +def info(): + print manAlg.info() diff --git a/astra/astra.py b/astra/astra.py new file mode 100644 index 0000000..edfb6a4 --- /dev/null +++ b/astra/astra.py @@ -0,0 +1,51 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra_c as a + +def credits(): + """Print credits of the ASTRA Toolbox.""" + return a.credits() + + +def use_cuda(): + """Test if CUDA is enabled. + + :returns: :class:`bool` -- ``True`` if CUDA is enabled. + """ + return a.use_cuda() + + +def version(printToScreen=False): + """Check version of the ASTRA Toolbox. + + :param printToScreen: If ``True``, print version string. If ``False``, return version integer. + :type printToScreen: :class:`bool` + :returns: :class:`string` or :class:`int` -- The version string or integer. + + """ + + return a.version(printToScreen) diff --git a/astra/astra_c.pyx b/astra/astra_c.pyx new file mode 100644 index 0000000..b944f96 --- /dev/null +++ b/astra/astra_c.pyx @@ -0,0 +1,61 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +from libcpp.string cimport string +from libcpp cimport bool +cdef extern from "astra/Globals.h" namespace "astra": + int getVersion() + string getVersionString() + bool cudaEnabled() + + +def credits(): + print "All Scale Tomographic Reconstruction Antwerp Toolbox (ASTRA-Toolbox) was developed at the University of Antwerp by" + print " * Prof. dr. Joost Batenburg" + print " * Andrei Dabravolski" + print " * Gert Merckx" + print " * Willem Jan Palenstijn" + print " * Tom Roelandts" + print " * Prof. dr. Jan Sijbers" + print " * dr. Wim van Aarle" + print " * Sander van der Maar" + print " * dr. Gert Van Gompel" + print "" + print "Python interface written by" + print " * Daniel M. Pelt (CWI, Amsterdam)" + + +def use_cuda(): + return cudaEnabled() + + +def version(printToScreen=False): + if printToScreen: + print getVersionString() + else: + return getVersion() diff --git a/astra/creators.py b/astra/creators.py new file mode 100644 index 0000000..f9ec91d --- /dev/null +++ b/astra/creators.py @@ -0,0 +1,500 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import numpy as np +import math +import data2d +import data3d +import projector +import algorithm + +def astra_dict(intype): + """Creates a dict to use with the ASTRA Toolbox. + + :param intype: Type of the ASTRA object. + :type intype: :class:`string` + :returns: :class:`dict` -- An ASTRA dict of type ``intype``. + + """ + if intype == 'SIRT_CUDA2': + intype = 'SIRT_CUDA' + print 'SIRT_CUDA2 has been deprecated. Use SIRT_CUDA instead.' + elif intype == 'FP_CUDA2': + intype = 'FP_CUDA' + print 'FP_CUDA2 has been deprecated. Use FP_CUDA instead.' + return {'type': intype} + +def create_vol_geom(*varargin): + """Create a volume geometry structure. + +This method can be called in a number of ways: + +``create_vol_geom(N)``: + :returns: A 2D volume geometry of size :math:`N \\times N`. + +``create_vol_geom((M, N))``: + :returns: A 2D volume geometry of size :math:`M \\times N`. + +``create_vol_geom(M, N)``: + :returns: A 2D volume geometry of size :math:`M \\times N`. + +``create_vol_geom(M, N, minx, maxx, miny, maxy)``: + :returns: A 2D volume geometry of size :math:`M \\times N`, windowed as :math:`minx \\leq x \\leq maxx` and :math:`miny \\leq y \\leq maxy`. + +``create_vol_geom((M, N, Z))``: + :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`. + +``create_vol_geom(M, N, Z)``: + :returns: A 3D volume geometry of size :math:`M \\times N \\times Z`. + +""" + vol_geom = {'option': {}} + # astra_create_vol_geom(row_count) + if len(varargin) == 1 and isinstance(varargin[0], int) == 1: + vol_geom['GridRowCount'] = varargin[0] + vol_geom['GridColCount'] = varargin[0] + vol_geom['option']['WindowMinX'] = -varargin[0] / 2 + vol_geom['option']['WindowMaxX'] = varargin[0] / 2 + vol_geom['option']['WindowMinY'] = -varargin[0] / 2 + vol_geom['option']['WindowMaxY'] = varargin[0] / 2 + # astra_create_vol_geom([row_count col_count]) + elif len(varargin) == 1 and len(varargin[0]) == 2: + vol_geom['GridRowCount'] = varargin[0][0] + vol_geom['GridColCount'] = varargin[0][1] + vol_geom['option']['WindowMinX'] = -varargin[0][1] / 2 + vol_geom['option']['WindowMaxX'] = varargin[0][1] / 2 + vol_geom['option']['WindowMinY'] = -varargin[0][0] / 2 + vol_geom['option']['WindowMaxY'] = varargin[0][0] / 2 + # astra_create_vol_geom([row_count col_count slice_count]) + elif len(varargin) == 1 and len(varargin[0]) == 3: + vol_geom['GridRowCount'] = varargin[0][0] + vol_geom['GridColCount'] = varargin[0][1] + vol_geom['GridSliceCount'] = varargin[0][2] + vol_geom['option']['WindowMinX'] = -varargin[0][1] / 2 + vol_geom['option']['WindowMaxX'] = varargin[0][1] / 2 + vol_geom['option']['WindowMinY'] = -varargin[0][0] / 2 + vol_geom['option']['WindowMaxY'] = varargin[0][0] / 2 + vol_geom['option']['WindowMinZ'] = -varargin[0][2] / 2 + vol_geom['option']['WindowMaxZ'] = varargin[0][2] / 2 + # astra_create_vol_geom(row_count, col_count) + elif len(varargin) == 2: + vol_geom['GridRowCount'] = varargin[0] + vol_geom['GridColCount'] = varargin[1] + vol_geom['option']['WindowMinX'] = -varargin[1] / 2 + vol_geom['option']['WindowMaxX'] = varargin[1] / 2 + vol_geom['option']['WindowMinY'] = -varargin[0] / 2 + vol_geom['option']['WindowMaxY'] = varargin[0] / 2 + # astra_create_vol_geom(row_count, col_count, min_x, max_x, min_y, max_y) + elif len(varargin) == 6: + vol_geom['GridRowCount'] = varargin[0] + vol_geom['GridColCount'] = varargin[1] + vol_geom['option']['WindowMinX'] = varargin[2] + vol_geom['option']['WindowMaxX'] = varargin[3] + vol_geom['option']['WindowMinY'] = varargin[4] + vol_geom['option']['WindowMaxY'] = varargin[5] + # astra_create_vol_geom(row_count, col_count, slice_count) + elif len(varargin) == 3: + vol_geom['GridRowCount'] = varargin[0] + vol_geom['GridColCount'] = varargin[1] + vol_geom['GridSliceCount'] = varargin[2] + return vol_geom + + +def create_proj_geom(intype, *args): + """Create a projection geometry. + +This method can be called in a number of ways: + +``create_proj_geom('parallel', detector_spacing, det_count, angles)``: + +:param detector_spacing: Distance between two adjacent detector pixels. +:type detector_spacing: :class:`float` +:param det_count: Number of detector pixels. +:type det_count: :class:`int` +:param angles: Array of angles in radians. +:type angles: :class:`numpy.ndarray` +:returns: A parallel projection geometry. + + +``create_proj_geom('fanflat', det_width, det_count, angles, source_origin, source_det)``: + +:param det_width: Size of a detector pixel. +:type det_width: :class:`float` +:param det_count: Number of detector pixels. +:type det_count: :class:`int` +:param angles: Array of angles in radians. +:type angles: :class:`numpy.ndarray` +:param source_origin: Position of the source. +:param source_det: Position of the detector +:returns: A fan-beam projection geometry. + +``create_proj_geom('fanflat_vec', det_count, V)``: + +:param det_count: Number of detector pixels. +:type det_count: :class:`int` +:param V: Vector array. +:type V: :class:`numpy.ndarray` +:returns: A fan-beam projection geometry. + +``create_proj_geom('parallel3d', detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles)``: + +:param detector_spacing_*: Distance between two adjacent detector pixels. +:type detector_spacing_*: :class:`float` +:param det_row_count: Number of detector pixel rows. +:type det_row_count: :class:`int` +:param det_col_count: Number of detector pixel columns. +:type det_col_count: :class:`int` +:param angles: Array of angles in radians. +:type angles: :class:`numpy.ndarray` +:returns: A parallel projection geometry. + +``create_proj_geom('cone', detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles, source_origin, source_det)``: + +:param detector_spacing_*: Distance between two adjacent detector pixels. +:type detector_spacing_*: :class:`float` +:param det_row_count: Number of detector pixel rows. +:type det_row_count: :class:`int` +:param det_col_count: Number of detector pixel columns. +:type det_col_count: :class:`int` +:param angles: Array of angles in radians. +:type angles: :class:`numpy.ndarray` +:param source_origin: Distance between point source and origin. +:type source_origin: :class:`float` +:param source_det: Distance between the detector and origin. +:type source_det: :class:`float` +:returns: A cone-beam projection geometry. + +``create_proj_geom('cone_vec', det_row_count, det_col_count, V)``: + +:param det_row_count: Number of detector pixel rows. +:type det_row_count: :class:`int` +:param det_col_count: Number of detector pixel columns. +:type det_col_count: :class:`int` +:param V: Vector array. +:type V: :class:`numpy.ndarray` +:returns: A cone-beam projection geometry. + +``create_proj_geom('parallel3d_vec', det_row_count, det_col_count, V)``: + +:param det_row_count: Number of detector pixel rows. +:type det_row_count: :class:`int` +:param det_col_count: Number of detector pixel columns. +:type det_col_count: :class:`int` +:param V: Vector array. +:type V: :class:`numpy.ndarray` +:returns: A parallel projection geometry. + +``create_proj_geom('sparse_matrix', det_width, det_count, angles, matrix_id)``: + +:param det_width: Size of a detector pixel. +:type det_width: :class:`float` +:param det_count: Number of detector pixels. +:type det_count: :class:`int` +:param angles: Array of angles in radians. +:type angles: :class:`numpy.ndarray` +:param matrix_id: ID of the sparse matrix. +:type matrix_id: :class:`int` +:returns: A projection geometry based on a sparse matrix. + +""" + if intype == 'parallel': + if len(args) < 3: + raise Exception( + 'not enough variables: astra_create_proj_geom(parallel, detector_spacing, det_count, angles)') + return {'type': 'parallel', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2]} + elif intype == 'fanflat': + if len(args) < 5: + raise Exception('not enough variables: astra_create_proj_geom(fanflat, det_width, det_count, angles, source_origin, source_det)') + return {'type': 'fanflat', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2], 'DistanceOriginSource': args[3], 'DistanceOriginDetector': args[4]} + elif intype == 'fanflat_vec': + if len(args) < 2: + raise Exception('not enough variables: astra_create_proj_geom(fanflat_vec, det_count, V)') + if not args[1].shape[1] == 6: + raise Exception('V should be a Nx6 matrix, with N the number of projections') + return {'type':'fanflat_vec', 'DetectorCount':args[0], 'Vectors':args[1]} + elif intype == 'parallel3d': + if len(args) < 5: + raise Exception('not enough variables: astra_create_proj_geom(parallel3d, detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles)') + return {'type':'parallel3d', 'DetectorSpacingX':args[0], 'DetectorSpacingY':args[1], 'DetectorRowCount':args[2], 'DetectorColCount':args[3],'ProjectionAngles':args[4]} + elif intype == 'cone': + if len(args) < 7: + raise Exception('not enough variables: astra_create_proj_geom(cone, detector_spacing_x, detector_spacing_y, det_row_count, det_col_count, angles, source_origin, source_det)') + return {'type': 'cone','DetectorSpacingX':args[0], 'DetectorSpacingY':args[1], 'DetectorRowCount':args[2],'DetectorColCount':args[3],'ProjectionAngles':args[4],'DistanceOriginSource': args[5],'DistanceOriginDetector':args[6]} + elif intype == 'cone_vec': + if len(args) < 3: + raise Exception('not enough variables: astra_create_proj_geom(cone_vec, det_row_count, det_col_count, V)') + if not args[2].shape[1] == 12: + raise Exception('V should be a Nx12 matrix, with N the number of projections') + return {'type': 'cone_vec','DetectorRowCount':args[0],'DetectorColCount':args[1],'Vectors':args[2]} + elif intype == 'parallel3d_vec': + if len(args) < 3: + raise Exception('not enough variables: astra_create_proj_geom(parallel3d_vec, det_row_count, det_col_count, V)') + if not args[2].shape[1] == 12: + raise Exception('V should be a Nx12 matrix, with N the number of projections') + return {'type': 'parallel3d_vec','DetectorRowCount':args[0],'DetectorColCount':args[1],'Vectors':args[2]} + elif intype == 'sparse_matrix': + if len(args) < 4: + raise Exception( + 'not enough variables: astra_create_proj_geom(sparse_matrix, det_width, det_count, angles, matrix_id)') + return {'type': 'sparse_matrix', 'DetectorWidth': args[0], 'DetectorCount': args[1], 'ProjectionAngles': args[2], 'MatrixID': args[3]} + else: + raise Exception('Error: unknown type ' + intype) + + +def create_backprojection(data, proj_id, useCUDA=False, returnData=True): + """Create a backprojection of a sinogram (2D). + +:param data: Sinogram data or ID. +:type data: :class:`numpy.ndarray` or :class:`int` +:param proj_id: ID of the projector to use. +:type proj_id: :class:`int` +:param useCUDA: If ``True``, use CUDA for the calculation. +:type useCUDA: :class:`bool` +:param returnData: If False, only return the ID of the backprojection. +:type returnData: :class:`bool` +:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the backprojection. Otherwise, returns a tuple containing the ID of the backprojection and the backprojection itself, in that order. + +""" + proj_geom = projector.projection_geometry(proj_id) + vol_geom = projector.volume_geometry(proj_id) + if isinstance(data, np.ndarray): + sino_id = data2d.create('-sino', proj_geom, data) + else: + sino_id = data + vol_id = data2d.create('-vol', vol_geom, 0) + + algString = 'BP' + if useCUDA: + algString = algString + '_CUDA' + + cfg = astra_dict(algString) + if not useCUDA: + cfg['ProjectorId'] = proj_id + cfg['ProjectionDataId'] = sino_id + cfg['ReconstructionDataId'] = vol_id + alg_id = algorithm.create(cfg) + algorithm.run(alg_id) + algorithm.delete(alg_id) + + if isinstance(data, np.ndarray): + data2d.delete(sino_id) + + if returnData: + return vol_id, data2d.get(vol_id) + else: + return vol_id + + +def create_sino(data, proj_id, useCUDA=False, returnData=True, gpuIndex=None): + """Create a forward projection of an image (2D). + +:param data: Image data or ID. +:type data: :class:`numpy.ndarray` or :class:`int` +:param proj_id: ID of the projector to use. +:type proj_id: :class:`int` +:param useCUDA: If ``True``, use CUDA for the calculation. +:type useCUDA: :class:`bool` +:param returnData: If False, only return the ID of the forward projection. +:type returnData: :class:`bool` +:param gpuIndex: Optional GPU index. +:type gpuIndex: :class:`int` +:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the forward projection. Otherwise, returns a tuple containing the ID of the forward projection and the forward projection itself, in that order. + +""" + + proj_geom = projector.projection_geometry(proj_id) + vol_geom = projector.volume_geometry(proj_id) + if isinstance(data, np.ndarray): + volume_id = data2d.create('-vol', vol_geom, data) + else: + volume_id = data + sino_id = data2d.create('-sino', proj_geom, 0) + algString = 'FP' + if useCUDA: + algString = algString + '_CUDA' + cfg = astra_dict(algString) + if not useCUDA: + cfg['ProjectorId'] = proj_id + if not gpuIndex==None: + cfg['option']={'GPUindex':gpuIndex} + cfg['ProjectionDataId'] = sino_id + cfg['VolumeDataId'] = volume_id + alg_id = algorithm.create(cfg) + algorithm.run(alg_id) + algorithm.delete(alg_id) + + if isinstance(data, np.ndarray): + data2d.delete(volume_id) + if returnData: + return sino_id, data2d.get(sino_id) + else: + return sino_id + +def create_sino3d_gpu(data, proj_geom, vol_geom, returnData=True, gpuIndex=None): + """Create a forward projection of an image (3D). + +:param data: Image data or ID. +:type data: :class:`numpy.ndarray` or :class:`int` +:param proj_geom: Projection geometry. +:type proj_geom: :class:`dict` +:param vol_geom: Volume geometry. +:type vol_geom: :class:`dict` +:param returnData: If False, only return the ID of the forward projection. +:type returnData: :class:`bool` +:param gpuIndex: Optional GPU index. +:type gpuIndex: :class:`int` +:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the forward projection. Otherwise, returns a tuple containing the ID of the forward projection and the forward projection itself, in that order. + +""" + + if isinstance(data, np.ndarray): + volume_id = data3d.create('-vol', vol_geom, data) + else: + volume_id = data + sino_id = data3d.create('-sino', proj_geom, 0) + algString = 'FP3D_CUDA' + cfg = astra_dict(algString) + if not gpuIndex==None: + cfg['option']={'GPUindex':gpuIndex} + cfg['ProjectionDataId'] = sino_id + cfg['VolumeDataId'] = volume_id + alg_id = algorithm.create(cfg) + algorithm.run(alg_id) + algorithm.delete(alg_id) + + if isinstance(data, np.ndarray): + data3d.delete(volume_id) + if returnData: + return sino_id, data3d.get(sino_id) + else: + return sino_id + + +def create_reconstruction(rec_type, proj_id, sinogram, iterations=1, use_mask='no', mask=np.array([]), use_minc='no', minc=0, use_maxc='no', maxc=255, returnData=True, filterType=None, filterData=None): + """Create a reconstruction of a sinogram (2D). + +:param rec_type: Name of the reconstruction algorithm. +:type rec_type: :class:`string` +:param proj_id: ID of the projector to use. +:type proj_id: :class:`int` +:param sinogram: Sinogram data or ID. +:type sinogram: :class:`numpy.ndarray` or :class:`int` +:param iterations: Number of iterations to run. +:type iterations: :class:`int` +:param use_mask: Whether to use a mask. +:type use_mask: ``'yes'`` or ``'no'`` +:param mask: Mask data or ID +:type mask: :class:`numpy.ndarray` or :class:`int` +:param use_minc: Whether to force a minimum value on the reconstruction pixels. +:type use_minc: ``'yes'`` or ``'no'`` +:param minc: Minimum value to use. +:type minc: :class:`float` +:param use_maxc: Whether to force a maximum value on the reconstruction pixels. +:type use_maxc: ``'yes'`` or ``'no'`` +:param maxc: Maximum value to use. +:type maxc: :class:`float` +:param returnData: If False, only return the ID of the reconstruction. +:type returnData: :class:`bool` +:param filterType: Which type of filter to use for filter-based methods. +:type filterType: :class:`string` +:param filterData: Optional filter data for filter-based methods. +:type filterData: :class:`numpy.ndarray` +:returns: :class:`int` or (:class:`int`, :class:`numpy.ndarray`) -- If ``returnData=False``, returns the ID of the reconstruction. Otherwise, returns a tuple containing the ID of the reconstruction and reconstruction itself, in that order. + +""" + proj_geom = projector.projection_geometry(proj_id) + if isinstance(sinogram, np.ndarray): + sino_id = data2d.create('-sino', proj_geom, sinogram) + else: + sino_id = sinogram + vol_geom = projector.volume_geometry(proj_id) + recon_id = data2d.create('-vol', vol_geom, 0) + cfg = astra_dict(rec_type) + if not 'CUDA' in rec_type: + cfg['ProjectorId'] = proj_id + cfg['ProjectionDataId'] = sino_id + cfg['ReconstructionDataId'] = recon_id + cfg['options'] = {} + if use_mask == 'yes': + if isinstance(mask, np.ndarray): + mask_id = data2d.create('-vol', vol_geom, mask) + else: + mask_id = mask + cfg['options']['ReconstructionMaskId'] = mask_id + if not filterType == None: + cfg['FilterType'] = filterType + if not filterData == None: + if isinstance(filterData, np.ndarray): + nexpow = int( + pow(2, math.ceil(math.log(2 * proj_geom['DetectorCount'], 2)))) + filtSize = nexpow / 2 + 1 + filt_proj_geom = create_proj_geom( + 'parallel', 1.0, filtSize, proj_geom['ProjectionAngles']) + filt_id = data2d.create('-sino', filt_proj_geom, filterData) + else: + filt_id = filterData + cfg['FilterSinogramId'] = filt_id + cfg['options']['UseMinConstraint'] = use_minc + cfg['options']['MinConstraintValue'] = minc + cfg['options']['UseMaxConstraint'] = use_maxc + cfg['options']['MaxConstraintValue'] = maxc + cfg['options']['ProjectionOrder'] = 'random' + alg_id = algorithm.create(cfg) + algorithm.run(alg_id, iterations) + + algorithm.delete(alg_id) + + if isinstance(sinogram, np.ndarray): + data2d.delete(sino_id) + if use_mask == 'yes' and isinstance(mask, np.ndarray): + data2d.delete(mask_id) + if not filterData == None: + if isinstance(filterData, np.ndarray): + data2d.delete(filt_id) + if returnData: + return recon_id, data2d.get(recon_id) + else: + return recon_id + + +def create_projector(proj_type, proj_geom, vol_geom): + """Create a 2D projector. + +:param proj_type: Projector type, such as ``'line'``, ``'linear'``, ... +:type proj_type: :class:`string` +:param proj_geom: Projection geometry. +:type proj_geom: :class:`dict` +:param vol_geom: Volume geometry. +:type vol_geom: :class:`dict` +:returns: :class:`int` -- The ID of the projector. + +""" + if proj_type == 'blob': + raise Exception('Blob type not yet implemented') + cfg = astra_dict(proj_type) + cfg['ProjectionGeometry'] = proj_geom + cfg['VolumeGeometry'] = vol_geom + return projector.create(cfg) diff --git a/astra/data2d.py b/astra/data2d.py new file mode 100644 index 0000000..f768f02 --- /dev/null +++ b/astra/data2d.py @@ -0,0 +1,109 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +import data2d_c as d + +def clear(): + """Clear all 2D data objects.""" + return d.clear() + +def delete(ids): + """Delete a 2D object. + + :param ids: ID or list of ID's to delete. + :type ids: :class:`int` or :class:`list` + + """ + return d.delete(ids) + +def create(datatype, geometry, data=None): + """Create a 2D object. + + :param datatype: Data object type, '-vol' or '-sino'. + :type datatype: :class:`string` + :param geometry: Volume or projection geometry. + :type geometry: :class:`dict` + :param data: Data to fill the constructed object with, either a scalar or array. + :type data: :class:`float` or :class:`numpy.ndarray` + :returns: :class:`int` -- the ID of the constructed object. + + """ + return d.create(datatype,geometry,data) + +def store(i, data): + """Fill existing 2D object with data. + + :param i: ID of object to fill. + :type i: :class:`int` + :param data: Data to fill the object with, either a scalar or array. + :type data: :class:`float` or :class:`numpy.ndarray` + + """ + return d.store(i, data) + +def get_geometry(i): + """Get the geometry of a 2D object. + + :param i: ID of object. + :type i: :class:`int` + :returns: :class:`dict` -- The geometry of object with ID ``i``. + + """ + return d.get_geometry(i) + +def change_geometry(i, geom): + """Change the geometry of a 2D object. + + :param i: ID of object. + :type i: :class:`int` + :param geom: new geometry. + :type geom: :class:`dict` + + """ + return d.change_geometry(i, geom) + +def get(i): + """Get a 2D object. + + :param i: ID of object to get. + :type i: :class:`int` + :returns: :class:`numpy.ndarray` -- The object data. + + """ + return d.get(i) + +def get_single(i): + """Get a 2D object in single precision. + + :param i: ID of object to get. + :type i: :class:`int` + :returns: :class:`numpy.ndarray` -- The object data. + + """ + return d.get_single(i) + +def info(): + """Print info on 2D objects in memory.""" + return d.info() diff --git a/astra/data2d_c.pyx b/astra/data2d_c.pyx new file mode 100644 index 0000000..0ce13c5 --- /dev/null +++ b/astra/data2d_c.pyx @@ -0,0 +1,224 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +cimport PyData2DManager +from PyData2DManager cimport CData2DManager + +cimport PyXMLDocument +from PyXMLDocument cimport XMLDocument + +import numpy as np + +from PyIncludes cimport * + +cimport utils + +cdef CData2DManager * man2d = PyData2DManager.getSingletonPtr() + + +def clear(): + man2d.clear() + + +def delete(ids): + try: + for i in ids: + man2d.remove(i) + except TypeError: + man2d.remove(ids) + + +def create(datatype, geometry, data=None): + cdef XMLDocument * xml + cdef Config cfg + cdef CVolumeGeometry2D * pGeometry + cdef CProjectionGeometry2D * ppGeometry + cdef CFloat32Data2D * pDataObject2D + if datatype == '-vol': + xml = utils.dict2XML('VolumeGeometry', geometry) + cfg.self = xml.getRootNode() + pGeometry = new CVolumeGeometry2D() + if not pGeometry.initialize(cfg): + del xml + del pGeometry + raise Exception('Geometry class not initialized.') + pDataObject2D = new CFloat32VolumeData2D(pGeometry) + del xml + del pGeometry + elif datatype == '-sino': + xml = utils.dict2XML('ProjectionGeometry', geometry) + cfg.self = xml.getRootNode() + tpe = str(cfg.self.getAttribute('type')) + if (tpe == 'sparse_matrix'): + ppGeometry = new CSparseMatrixProjectionGeometry2D() + elif (tpe == 'fanflat'): + ppGeometry = new CFanFlatProjectionGeometry2D() + elif (tpe == 'fanflat_vec'): + ppGeometry = new CFanFlatVecProjectionGeometry2D() + else: + ppGeometry = new CParallelProjectionGeometry2D() + if not ppGeometry.initialize(cfg): + del xml + del ppGeometry + raise Exception('Geometry class not initialized.') + pDataObject2D = new CFloat32ProjectionData2D(ppGeometry) + del ppGeometry + del xml + else: + raise Exception("Invalid datatype. Please specify '-vol' or '-sino'.") + + if not pDataObject2D.isInitialized(): + del pDataObject2D + raise Exception("Couldn't initialize data object.") + + fillDataObject(pDataObject2D, data) + + return man2d.store(pDataObject2D) + +cdef fillDataObject(CFloat32Data2D * obj, data): + if data == None: + fillDataObjectScalar(obj, 0) + else: + if isinstance(data, np.ndarray): + fillDataObjectArray(obj, data) + else: + fillDataObjectScalar(obj, data) + +cdef fillDataObjectScalar(CFloat32Data2D * obj, s): + cdef int i + for i in range(obj.getSize()): + obj.getData()[i] = s + +cdef fillDataObjectArray(CFloat32Data2D * obj, data): + cdef int i, row, col + if (not data.shape[0] == obj.getHeight()) or (not data.shape[1] == obj.getWidth()): + raise Exception( + "The dimensions of the data do not match those specified in the geometry.") + for col in range(data.shape[1]): + for row in range(data.shape[0]): + obj.getData2D()[row][col] = data[row][col] + +cdef CFloat32Data2D * getObject(i) except NULL: + cdef CFloat32Data2D * pDataObject = man2d.get(i) + if pDataObject == NULL: + raise Exception("Data object not found") + if not pDataObject.isInitialized(): + raise Exception("Data object not initialized properly.") + return pDataObject + + +def store(i, data): + cdef CFloat32Data2D * pDataObject = getObject(i) + fillDataObject(pDataObject, data) + + +def get_geometry(i): + cdef CFloat32Data2D * pDataObject = getObject(i) + cdef CFloat32ProjectionData2D * pDataObject2 + cdef CFloat32VolumeData2D * pDataObject3 + if pDataObject.getType() == PROJECTION: + pDataObject2 = pDataObject + geom = utils.createProjectionGeometryStruct(pDataObject2.getGeometry()) + elif pDataObject.getType() == VOLUME: + pDataObject3 = pDataObject + geom = utils.createVolumeGeometryStruct(pDataObject3.getGeometry()) + else: + raise Exception("Not a known data object") + return geom + + +def change_geometry(i, geom): + cdef XMLDocument * xml + cdef Config cfg + cdef CVolumeGeometry2D * pGeometry + cdef CProjectionGeometry2D * ppGeometry + cdef CFloat32Data2D * pDataObject = getObject(i) + cdef CFloat32ProjectionData2D * pDataObject2 + cdef CFloat32VolumeData2D * pDataObject3 + if pDataObject.getType() == PROJECTION: + pDataObject2 = pDataObject + xml = utils.dict2XML('ProjectionGeometry', geom) + cfg.self = xml.getRootNode() + tpe = str(cfg.self.getAttribute('type')) + if (tpe == 'sparse_matrix'): + ppGeometry = new CSparseMatrixProjectionGeometry2D() + elif (tpe == 'fanflat'): + ppGeometry = new CFanFlatProjectionGeometry2D() + elif (tpe == 'fanflat_vec'): + ppGeometry = new CFanFlatVecProjectionGeometry2D() + else: + ppGeometry = new CParallelProjectionGeometry2D() + if not ppGeometry.initialize(cfg): + del xml + del ppGeometry + raise Exception('Geometry class not initialized.') + if (ppGeometry.getDetectorCount() != pDataObject2.getDetectorCount() or ppGeometry.getProjectionAngleCount() != pDataObject2.getAngleCount()): + del ppGeometry + del xml + raise Exception( + "The dimensions of the data do not match those specified in the geometry.") + pDataObject2.changeGeometry(ppGeometry) + del ppGeometry + del xml + elif pDataObject.getType() == VOLUME: + pDataObject3 = pDataObject + xml = utils.dict2XML('VolumeGeometry', geom) + cfg.self = xml.getRootNode() + pGeometry = new CVolumeGeometry2D() + if not pGeometry.initialize(cfg): + del xml + del pGeometry + raise Exception('Geometry class not initialized.') + if (pGeometry.getGridColCount() != pDataObject3.getWidth() or pGeometry.getGridRowCount() != pDataObject3.getHeight()): + del xml + del pGeometry + raise Exception( + 'The dimensions of the data do not match those specified in the geometry.') + pDataObject3.changeGeometry(pGeometry) + del xml + del pGeometry + else: + raise Exception("Not a known data object") + + +def get(i): + cdef row, col + cdef CFloat32Data2D * pDataObject = getObject(i) + outArr = np.empty((pDataObject.getHeight(), pDataObject.getWidth())) + for row in range(outArr.shape[0]): + for col in range(outArr.shape[1]): + outArr[row][col] = pDataObject.getData2D()[row][col] + return outArr + + +def get_single(i): + raise Exception("Not yet implemented") + + +def info(): + print man2d.info() diff --git a/astra/data3d.py b/astra/data3d.py new file mode 100644 index 0000000..5545a74 --- /dev/null +++ b/astra/data3d.py @@ -0,0 +1,98 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +import data3d_c as d + +def create(datatype,geometry,data=None): + """Create a 3D object. + + :param datatype: Data object type, '-vol' or '-sino'. + :type datatype: :class:`string` + :param geometry: Volume or projection geometry. + :type geometry: :class:`dict` + :param data: Data to fill the constructed object with, either a scalar or array. + :type data: :class:`float` or :class:`numpy.ndarray` + :returns: :class:`int` -- the ID of the constructed object. + + """ + return d.create(datatype,geometry,data) + +def get(i): + """Get a 3D object. + + :param i: ID of object to get. + :type i: :class:`int` + :returns: :class:`numpy.ndarray` -- The object data. + + """ + return d.get(i) + +def get_single(i): + """Get a 3D object in single precision. + + :param i: ID of object to get. + :type i: :class:`int` + :returns: :class:`numpy.ndarray` -- The object data. + + """ + return g.get_single(i) + +def store(i,data): + """Fill existing 3D object with data. + + :param i: ID of object to fill. + :type i: :class:`int` + :param data: Data to fill the object with, either a scalar or array. + :type data: :class:`float` or :class:`numpy.ndarray` + + """ + return d.store(i,data) + +def dimensions(i): + """Get dimensions of a 3D object. + + :param i: ID of object. + :type i: :class:`int` + :returns: :class:`tuple` -- dimensions of object with ID ``i``. + + """ + return d.dimensions(i) + +def delete(ids): + """Delete a 2D object. + + :param ids: ID or list of ID's to delete. + :type ids: :class:`int` or :class:`list` + + """ + return d.delete(ids) + +def clear(): + """Clear all 3D data objects.""" + return d.clear() + +def info(): + """Print info on 3D objects in memory.""" + return d.info() diff --git a/astra/data3d_c.pyx b/astra/data3d_c.pyx new file mode 100644 index 0000000..aae0791 --- /dev/null +++ b/astra/data3d_c.pyx @@ -0,0 +1,172 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +cimport PyData3DManager +from PyData3DManager cimport CData3DManager + +from PyIncludes cimport * +import numpy as np + +cimport PyXMLDocument +from PyXMLDocument cimport XMLDocument + +cimport utils + +cdef CData3DManager * man3d = PyData3DManager.getSingletonPtr() + +cdef extern from *: + CFloat32Data3DMemory * dynamic_cast_mem "dynamic_cast" (CFloat32Data3D * ) except NULL + +def create(datatype,geometry,data=None): + cdef XMLDocument * xml + cdef Config cfg + cdef CVolumeGeometry3D * pGeometry + cdef CProjectionGeometry3D * ppGeometry + cdef CFloat32Data3DMemory * pDataObject3D + cdef CConeProjectionGeometry3D* pppGeometry + if datatype == '-vol': + xml = utils.dict2XML('VolumeGeometry', geometry) + cfg.self = xml.getRootNode() + pGeometry = new CVolumeGeometry3D() + if not pGeometry.initialize(cfg): + del xml + del pGeometry + raise Exception('Geometry class not initialized.') + pDataObject3D = new CFloat32VolumeData3DMemory(pGeometry) + del xml + del pGeometry + elif datatype == '-sino' or datatype == '-proj3d': + xml = utils.dict2XML('ProjectionGeometry', geometry) + cfg.self = xml.getRootNode() + tpe = str(cfg.self.getAttribute('type')) + if (tpe == "parallel3d"): + ppGeometry = new CParallelProjectionGeometry3D(); + elif (tpe == "parallel3d_vec"): + ppGeometry = new CParallelVecProjectionGeometry3D(); + elif (tpe == "cone"): + ppGeometry = new CConeProjectionGeometry3D(); + elif (tpe == "cone_vec"): + ppGeometry = new CConeVecProjectionGeometry3D(); + else: + raise Exception("Invalid geometry type.") + + if not ppGeometry.initialize(cfg): + del xml + del ppGeometry + raise Exception('Geometry class not initialized.') + pDataObject3D = new CFloat32ProjectionData3DMemory(ppGeometry) + del ppGeometry + del xml + elif datatype == "-sinocone": + xml = utils.dict2XML('ProjectionGeometry', geometry) + cfg.self = xml.getRootNode() + pppGeometry = new CConeProjectionGeometry3D() + if not pppGeometry.initialize(cfg): + del xml + del pppGeometry + raise Exception('Geometry class not initialized.') + pDataObject3D = new CFloat32ProjectionData3DMemory(pppGeometry) + else: + raise Exception("Invalid datatype. Please specify '-vol' or '-proj3d'.") + + if not pDataObject3D.isInitialized(): + del pDataObject3D + raise Exception("Couldn't initialize data object.") + + fillDataObject(pDataObject3D, data) + + pDataObject3D.updateStatistics() + + return man3d.store(pDataObject3D) + + +cdef fillDataObject(CFloat32Data3DMemory * obj, data): + if data == None: + fillDataObjectScalar(obj, 0) + else: + if isinstance(data, np.ndarray): + fillDataObjectArray(obj, data) + else: + fillDataObjectScalar(obj, data) + +cdef fillDataObjectScalar(CFloat32Data3DMemory * obj, s): + cdef int i + for i in range(obj.getSize()): + obj.getData()[i] = s + +cdef fillDataObjectArray(CFloat32Data3DMemory * obj, data): + cdef int i, row, col,slc + if (not data.shape[0] == obj.getWidth()) or (not data.shape[1] == obj.getHeight()) or (not data.shape[2] == obj.getDepth()): + raise Exception( + "The dimensions of the data do not match those specified in the geometry.") + for row in range(data.shape[0]): + for col in range(data.shape[1]): + for slc in range(data.shape[2]): + obj.getData3D()[slc][col][row] = data[row][col][slc] + +cdef CFloat32Data3D * getObject(i) except NULL: + cdef CFloat32Data3D * pDataObject = man3d.get(i) + if pDataObject == NULL: + raise Exception("Data object not found") + if not pDataObject.isInitialized(): + raise Exception("Data object not initialized properly.") + return pDataObject + +def get(i): + cdef row, col,slc + cdef CFloat32Data3DMemory * pDataObject = dynamic_cast_mem(getObject(i)) + outArr = np.empty((pDataObject.getDepth(),pDataObject.getHeight(), pDataObject.getWidth())) + for slc in range(outArr.shape[0]): + for col in range(outArr.shape[2]): + for row in range(outArr.shape[1]): + outArr[slc][row][col] = pDataObject.getData3D()[slc][row][col] + return outArr + +def get_single(i): + raise Exception("Not yet implemented") + +def store(i,data): + cdef CFloat32Data3D * pDataObject = getObject(i) + fillDataObject(dynamic_cast_mem(pDataObject), data) + +def dimensions(i): + cdef CFloat32Data3D * pDataObject = getObject(i) + return (pDataObject.getWidth(),pDataObject.getHeight(),pDataObject.getDepth()) + +def delete(ids): + try: + for i in ids: + man3d.remove(i) + except TypeError: + man3d.remove(ids) + +def clear(): + man3d.clear() + +def info(): + print man3d.info() diff --git a/astra/extrautils.pyx b/astra/extrautils.pyx new file mode 100644 index 0000000..09a0d61 --- /dev/null +++ b/astra/extrautils.pyx @@ -0,0 +1,44 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +def clipCircle(img): + cdef int i,j + cdef double x2,y2,mid,bnd + cdef long sz,sz2 + sz = img.shape[0] + sz2 = sz*sz + bnd = sz2/4. + mid = (sz-1.)/2. + nDel=0 + for i in range(sz): + for j in range(sz): + x2 = (i-mid)*(i-mid) + y2 = (j-mid)*(j-mid) + if x2+y2>bnd: + img[i,j]=0 + nDel=nDel+1 + return nDel + + diff --git a/astra/functions.py b/astra/functions.py new file mode 100644 index 0000000..dfcd0e4 --- /dev/null +++ b/astra/functions.py @@ -0,0 +1,109 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +"""Additional functions for PyAstraToolbox. + +.. moduleauthor:: Daniel M. Pelt + + +""" + +import creators as ac +import numpy as np +import scipy.weave + +import data2d +import data3d +import projector +import algorithm + + + +def clear(): + """Clears all used memory of the ASTRA Toolbox. + + .. note:: + This is irreversible. + + """ + data2d.clear() + data3d.clear() + projector.clear() + algorithm.clear() + + +def data_op(op, data, scalar, gpu_core, mask=None): + """Perform data operation on data. + + :param op: Operation to perform. + :param data: Data to perform operation on. + :param scalar: Scalar argument to data operation. + :param gpu_core: GPU core to perform operation on. + :param mask: Optional mask. + + """ + + cfg = ac.astra_dict('DataOperation_CUDA') + cfg['Operation'] = op + cfg['Scalar'] = scalar + cfg['DataId'] = data + if not mask == None: + cfg['MaskId'] = mask + cfg['option']['GPUindex'] = gpu_core + alg_id = at.algorithm('create', cfg) + at.algorithm('run', alg_id) + at.algorithm('delete', alg_id) + + +def add_noise_to_sino(sinogram_in, I0): + """Adds Poisson noise to a sinogram. + + :param sinogram_in: Sinogram to add noise to. + :type sinogram_in: :class:`numpy.ndarray` + :param I0: Background intensity. Lower values lead to higher noise. + :type I0: :class:`float` + :returns: :class:`numpy.ndarray` -- the sinogram with added noise. + + """ + if isinstance(sinogram_in, np.ndarray): + sinogramRaw = sinogram_in + else: + sinogramRaw = at.data2d('get', sinogram_in) + max_sinogramRaw = sinogramRaw.max() + sinogramRawScaled = sinogramRaw / max_sinogramRaw + # to detector count + sinogramCT = I0 * np.exp(-sinogramRawScaled) + # add poison noise + sinogramCT_C = np.zeros_like(sinogramCT) + for i in xrange(sinogramCT_C.shape[0]): + for j in xrange(sinogramCT_C.shape[1]): + sinogramCT_C[i, j] = np.random.poisson(sinogramCT[i, j]) + # to density + sinogramCT_D = sinogramCT_C / I0 + sinogram_out = -max_sinogramRaw * np.log(sinogramCT_D) + + if not isinstance(sinogram_in, np.ndarray): + at.data2d('store', sinogram_in, sinogram_out) + return sinogram_out diff --git a/astra/matlab.py b/astra/matlab.py new file mode 100644 index 0000000..9291d82 --- /dev/null +++ b/astra/matlab.py @@ -0,0 +1,112 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +"""This module implements a MATLAB-like interface to the ASTRA Toolbox. + +Note that all functions are called with a :class:`string` as the first +argument, specifying the operation to perform. This un-pythonic way +is used to make transitioning from MATLAB code to Python code easier, as +the MATLAB interface uses the same type of method calling. + +After an initial ``import astra``, these functions can be accessed in the +``astra.m`` module. + +""" + +import astra_c +import data2d_c +import data3d_c +import projector_c +import algorithm_c +import matrix_c +import numpy as np + + +def astra(command, *args): + """MATLAB-like interface to the :mod:`astra.astra` module + + For example: + + ``astra.m.astra('use_cuda')`` -- Check if CUDA is enabled. + + """ + return getattr(astra_c, command)(*args) + + +def data2d(command, *args): + """MATLAB-like interface to the :mod:`astra.data2d` module + + For example: + + ``astra.m.data2d('create',type,geometry,data)`` -- Create a 2D object. + + """ + return getattr(data2d_c, command)(*args) + + +def data3d(command, *args): + """MATLAB-like interface to the :mod:`astra.data3d` module + + For example: + + ``astra.m.data3d('get',i)`` -- Get 3D object data. + + """ + return getattr(data3d_c, command)(*args) + + +def projector(command, *args): + """MATLAB-like interface to the :mod:`astra.projector` module + + For example: + + ``astra.m.projector('volume_geometry',i)`` -- Get volume geometry. + + """ + return getattr(projector_c, command)(*args) + + +def matrix(command, *args): + """MATLAB-like interface to the :mod:`astra.matrix` module + + For example: + + ``astra.m.matrix('delete',i)`` -- Delete a matrix. + + """ + return getattr(matrix_c, command)(*args) + + +def algorithm(command, *args): + """MATLAB-like interface to the :mod:`astra.algorithm` module + + For example: + + ``astra.m.algorithm('run',i,1000)`` -- Run an algorithm with 1000 iterations. + + """ + if command == 'iterate': + command = 'run' + return getattr(algorithm_c, command)(*args) diff --git a/astra/matrix.py b/astra/matrix.py new file mode 100644 index 0000000..5beb62d --- /dev/null +++ b/astra/matrix.py @@ -0,0 +1,86 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +import matrix_c as m + +def delete(ids): + """Delete a matrix object. + + :param ids: ID or list of ID's to delete. + :type ids: :class:`int` or :class:`list` + + """ + return m.delete(ids) + +def clear(): + """Clear all matrix objects.""" + return m.clear() + +def create(data): + """Create matrix object with data. + + :param data: Data to fill the created object with. + :type data: :class:`scipy.sparse.csr_matrix` + :returns: :class:`int` -- the ID of the constructed object. + + """ + return m.create(data) + + +def store(i,data): + """Fill existing matrix object with data. + + :param i: ID of object to fill. + :type i: :class:`int` + :param data: Data to fill the object with. + :type data: :class:`scipy.sparse.csr_matrix` + + """ + return m.store(i,data) + +def get_size(i): + """Get matrix dimensions. + + :param i: ID of object. + :type i: :class:`int` + :returns: :class:`tuple` -- matrix dimensions. + """ + return m.get_size(i) + +def get(i): + """Get a matrix object. + + :param i: ID of object to get. + :type i: :class:`int` + :returns: :class:`scipy.sparse.csr_matrix` -- The object data. + + """ + return m.get(i) + +def info(): + """Print info on matrix objects in memory.""" + return m.info() + + diff --git a/astra/matrix_c.pyx b/astra/matrix_c.pyx new file mode 100644 index 0000000..264cb48 --- /dev/null +++ b/astra/matrix_c.pyx @@ -0,0 +1,115 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +import numpy as np +import scipy.sparse as ss + +cimport PyMatrixManager +from PyMatrixManager cimport CMatrixManager + +from PyIncludes cimport * + +cdef CMatrixManager * manM = PyMatrixManager.getSingletonPtr() + +from libcpp cimport bool + +def delete(ids): + try: + for i in ids: + manM.remove(i) + except TypeError: + manM.remove(ids) + +def clear(): + manM.clear() + +cdef int csr_matrix_to_astra(data,CSparseMatrix *mat) except -1: + if isinstance(data,ss.csr_matrix): + csrD = data + else: + csrD = data.tocsr() + if not mat.isInitialized(): + raise Exception("Couldn't initialize data object.") + if csrD.nnz > mat.m_lSize or csrD.shape[0] > mat.m_iHeight: + raise Exception("Matrix too large to store in this object.") + for i in xrange(len(csrD.indptr)): + mat.m_plRowStarts[i] = csrD.indptr[i] + for i in xrange(csrD.nnz): + mat.m_piColIndices[i] = csrD.indices[i] + mat.m_pfValues[i] = csrD.data[i] + +cdef astra_to_csr_matrix(CSparseMatrix *mat): + indptr = np.zeros(mat.m_iHeight+1,dtype=np.int) + indices = np.zeros(mat.m_plRowStarts[mat.m_iHeight],dtype=np.int) + data = np.zeros(mat.m_plRowStarts[mat.m_iHeight]) + for i in xrange(mat.m_iHeight+1): + indptr[i] = mat.m_plRowStarts[i] + for i in xrange(mat.m_plRowStarts[mat.m_iHeight]): + indices[i] = mat.m_piColIndices[i] + data[i] = mat.m_pfValues[i] + return ss.csr_matrix((data,indices,indptr),shape=(mat.m_iHeight,mat.m_iWidth)) + +def create(data): + cdef CSparseMatrix* pMatrix + pMatrix = new CSparseMatrix(data.shape[0], data.shape[1], data.nnz) + if not pMatrix.isInitialized(): + del pMatrix + raise Exception("Couldn't initialize data object.") + try: + csr_matrix_to_astra(data,pMatrix) + except: + del pMatrix + raise Exception("Failed to create data object.") + + return manM.store(pMatrix) + +cdef CSparseMatrix * getObject(i) except NULL: + cdef CSparseMatrix * pDataObject = manM.get(i) + if pDataObject == NULL: + raise Exception("Data object not found") + if not pDataObject.isInitialized(): + raise Exception("Data object not initialized properly.") + return pDataObject + + +def store(i,data): + cdef CSparseMatrix * pDataObject = getObject(i) + csr_matrix_to_astra(data,pDataObject) + +def get_size(i): + cdef CSparseMatrix * pDataObject = getObject(i) + return (pDataObject.m_iHeight,pDataObject.m_iWidth) + +def get(i): + cdef CSparseMatrix * pDataObject = getObject(i) + return astra_to_csr_matrix(pDataObject) + +def info(): + print manM.info() + + diff --git a/astra/projector.py b/astra/projector.py new file mode 100644 index 0000000..a222097 --- /dev/null +++ b/astra/projector.py @@ -0,0 +1,100 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +import projector_c as p + +def create(config): + """Create projector object. + + :param config: Projector options. + :type config: :class:`dict` + :returns: :class:`int` -- the ID of the constructed object. + + """ + return p.create(config) + + +def delete(ids): + """Delete a projector object. + + :param ids: ID or list of ID's to delete. + :type ids: :class:`int` or :class:`list` + + """ + return p.delete(ids) + + +def clear(): + """Clear all projector objects.""" + return p.clear() + + +def info(): + """Print info on projector objects in memory.""" + return p.info() + +def projection_geometry(i): + """Get projection geometry of a projector. + + :param i: ID of projector. + :type i: :class:`int` + :returns: :class:`dict` -- projection geometry + + """ + return p.projection_geometry(i) + + +def volume_geometry(i): + """Get volume geometry of a projector. + + :param i: ID of projector. + :type i: :class:`int` + :returns: :class:`dict` -- volume geometry + + """ + return p.volume_geometry(i) + + +def weights_single_ray(i, projection_index, detector_index): + return p.weights_single_ray(i, projection_index, detector_index) + + +def weights_projection(i, projection_index): + return p.weights_projection(i, projection_index) + + +def splat(i, row, col): + return p.splat(i, row, col) + + +def matrix(i): + """Get sparse matrix of a projector. + + :param i: ID of projector. + :type i: :class:`int` + :returns: :class:`int` -- ID of sparse matrix. + + """ + return p.matrix(i) diff --git a/astra/projector_c.pyx b/astra/projector_c.pyx new file mode 100644 index 0000000..87fedd1 --- /dev/null +++ b/astra/projector_c.pyx @@ -0,0 +1,117 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +from PyIncludes cimport * + +cimport utils + +cimport PyProjector2DFactory +from PyProjector2DFactory cimport CProjector2DFactory + +cimport PyProjector2DManager +from PyProjector2DManager cimport CProjector2DManager + +cimport PyXMLDocument +from PyXMLDocument cimport XMLDocument + +cimport PyMatrixManager +from PyMatrixManager cimport CMatrixManager + +cdef CProjector2DManager * manProj = PyProjector2DManager.getSingletonPtr() +cdef CMatrixManager * manM = PyMatrixManager.getSingletonPtr() + + +def create(config): + cdef XMLDocument * xml = utils.dict2XML('Projector2D', config) + cdef Config cfg + cdef CProjector2D * proj + cfg.self = xml.getRootNode() + proj = PyProjector2DFactory.getSingletonPtr().create(cfg) + if proj == NULL: + del xml + raise Exception("Error creating projector.") + del xml + return manProj.store(proj) + + +def delete(ids): + try: + for i in ids: + manProj.remove(i) + except TypeError: + manProj.remove(ids) + + +def clear(): + manProj.clear() + + +def info(): + print manProj.info() + +cdef CProjector2D * getObject(i) except NULL: + cdef CProjector2D * proj = manProj.get(i) + if proj == NULL: + raise Exception("Projector not initialized.") + if not proj.isInitialized(): + raise Exception("Projector not initialized.") + return proj + + +def projection_geometry(i): + cdef CProjector2D * proj = getObject(i) + return utils.createProjectionGeometryStruct(proj.getProjectionGeometry()) + + +def volume_geometry(i): + cdef CProjector2D * proj = getObject(i) + return utils.createVolumeGeometryStruct(proj.getVolumeGeometry()) + + +def weights_single_ray(i, projection_index, detector_index): + raise Exception("Not yet implemented") + + +def weights_projection(i, projection_index): + raise Exception("Not yet implemented") + + +def splat(i, row, col): + raise Exception("Not yet implemented") + + +def matrix(i): + cdef CProjector2D * proj = getObject(i) + cdef CSparseMatrix * mat = proj.getMatrix() + if mat == NULL: + del mat + raise Exception("Data object not found") + if not mat.isInitialized(): + del mat + raise Exception("Data object not initialized properly.") + return manM.store(mat) diff --git a/astra/utils.pxd b/astra/utils.pxd new file mode 100644 index 0000000..b1986f2 --- /dev/null +++ b/astra/utils.pxd @@ -0,0 +1,37 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +from libcpp.string cimport string + +cimport PyXMLDocument +from PyXMLDocument cimport XMLDocument +from PyXMLDocument cimport XMLNode + +from PyIncludes cimport * + +cdef XMLDocument *dict2XML(string rootname, dc) +cdef XML2dict(XMLDocument *) +cdef createVolumeGeometryStruct(CVolumeGeometry2D* geom) +cdef createProjectionGeometryStruct(CProjectionGeometry2D* geom) diff --git a/astra/utils.pyx b/astra/utils.pyx new file mode 100644 index 0000000..5a51ca3 --- /dev/null +++ b/astra/utils.pyx @@ -0,0 +1,228 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +# distutils: language = c++ +# distutils: libraries = astra + +from libcpp.string cimport string +from libcpp.list cimport list +from libcpp.vector cimport vector + +cimport PyXMLDocument +from PyXMLDocument cimport XMLDocument +from PyXMLDocument cimport XMLNode +from cython.operator cimport dereference as deref + +from PyIncludes cimport * + +import numpy as np + +cdef XMLDocument * dict2XML(string rootname, dc): + cdef XMLDocument * doc = PyXMLDocument.createDocument(rootname) + cdef XMLNode * node = doc.getRootNode() + try: + readDict(node, dc) + except: + print 'Error reading XML' + del doc + doc = NULL + finally: + del node + return doc + +cdef void readDict(XMLNode * root, dc): + cdef XMLNode * listbase + cdef XMLNode * itm + cdef int i + cdef int j + for item in dc: + val = dc[item] + if isinstance(val, np.ndarray): + if val.size == 0: + break + listbase = root.addChildNode(item) + listbase.addAttribute(< string > 'listsize', < float32 > val.size) + index = 0 + if val.ndim == 2: + for i in range(val.shape[0]): + for j in range(val.shape[1]): + itm = listbase.addChildNode('ListItem') + itm.addAttribute(< string > 'index', < float32 > index) + itm.addAttribute( < string > 'value', < float32 > val[i, j]) + index += 1 + del itm + elif val.ndim == 1: + for i in range(val.shape[0]): + itm = listbase.addChildNode('ListItem') + itm.addAttribute(< string > 'index', < float32 > index) + itm.addAttribute(< string > 'value', < float32 > val[i]) + index += 1 + del itm + else: + raise Exception("Only 1 or 2 dimensions are allowed") + del listbase + elif isinstance(val, dict): + if item == 'option' or item == 'options' or item == 'Option' or item == 'Options': + readOptions(root, val) + else: + itm = root.addChildNode(item) + readDict(itm, val) + del itm + else: + if item == 'type': + root.addAttribute(< string > 'type', < string > str(val)) + else: + itm = root.addChildNode(item, str(val)) + del itm + +cdef void readOptions(XMLNode * node, dc): + cdef XMLNode * listbase + cdef XMLNode * itm + cdef int i + cdef int j + for item in dc: + val = dc[item] + if node.hasOption(item): + raise Exception('Duplicate Option: %s' % item) + if isinstance(val, np.ndarray): + if val.size == 0: + break + listbase = node.addChildNode('Option') + listbase.addAttribute(< string > 'key', < string > val) + listbase.addAttribute(< string > 'listsize', < float32 > val.size) + index = 0 + if val.ndim == 2: + for i in range(val.shape[0]): + for j in range(val.shape[1]): + itm = listbase.addChildNode('ListItem') + itm.addAttribute(< string > 'index', < float32 > index) + itm.addAttribute( < string > 'value', < float32 > val[i, j]) + index += 1 + del itm + elif val.ndim == 1: + for i in range(val.shape[0]): + itm = listbase.addChildNode('ListItem') + itm.addAttribute(< string > 'index', < float32 > index) + itm.addAttribute(< string > 'value', < float32 > val[i]) + index += 1 + del itm + else: + raise Exception("Only 1 or 2 dimensions are allowed") + del listbase + else: + node.addOption(item, str(val)) + +cdef vectorToNumpy(vector[float32] inp): + cdef int i + cdef int sz = inp.size() + ret = np.empty(sz) + for i in range(sz): + ret[i] = inp[i] + return ret + +cdef XMLNode2dict(XMLNode * node): + cdef XMLNode * subnode + cdef list[XMLNode * ] nodes + cdef list[XMLNode * ].iterator it + dct = {} + if node.hasAttribute('type'): + dct['type'] = node.getAttribute('type') + nodes = node.getNodes() + it = nodes.begin() + while it != nodes.end(): + subnode = deref(it) + if subnode.hasAttribute('listsize'): + dct[subnode.getName( + )] = vectorToNumpy(subnode.getContentNumericalArray()) + else: + dct[subnode.getName()] = subnode.getContent() + del subnode + return dct + +cdef XML2dict(XMLDocument * xml): + cdef XMLNode * node = xml.getRootNode() + dct = XMLNode2dict(node) + del node; + return dct; + +cdef createProjectionGeometryStruct(CProjectionGeometry2D * geom): + cdef int i + cdef CFanFlatVecProjectionGeometry2D * fanvecGeom + # cdef SFanProjection* p + dct = {} + dct['DetectorCount'] = geom.getDetectorCount() + if not geom.isOfType(< string > 'fanflat_vec'): + dct['DetectorWidth'] = geom.getDetectorWidth() + angles = np.empty(geom.getProjectionAngleCount()) + for i in range(geom.getProjectionAngleCount()): + angles[i] = geom.getProjectionAngle(i) + dct['ProjectionAngles'] = angles + else: + raise Exception("Not yet implemented") + # fanvecGeom = geom + # vecs = np.empty(fanvecGeom.getProjectionAngleCount()*6) + # iDetCount = pVecGeom.getDetectorCount() + # for i in range(fanvecGeom.getProjectionAngleCount()): + # p = &fanvecGeom.getProjectionVectors()[i]; + # out[6*i + 0] = p.fSrcX + # out[6*i + 1] = p.fSrcY + # out[6*i + 2] = p.fDetSX + 0.5f*iDetCount*p.fDetUX + # out[6*i + 3] = p.fDetSY + 0.5f*iDetCount*p.fDetUY + # out[6*i + 4] = p.fDetUX + # out[6*i + 5] = p.fDetUY + # dct['Vectors'] = vecs + if (geom.isOfType(< string > 'parallel')): + dct["type"] = "parallel" + elif (geom.isOfType(< string > 'fanflat')): + raise Exception("Not yet implemented") + # astra::CFanFlatProjectionGeometry2D* pFanFlatGeom = dynamic_cast(_pProjGeom) + # mGeometryInfo["DistanceOriginSource"] = mxCreateDoubleScalar(pFanFlatGeom->getOriginSourceDistance()) + # mGeometryInfo["DistanceOriginDetector"] = + # mxCreateDoubleScalar(pFanFlatGeom->getOriginDetectorDistance()) + dct["type"] = "fanflat" + elif (geom.isOfType(< string > 'sparse_matrix')): + raise Exception("Not yet implemented") + # astra::CSparseMatrixProjectionGeometry2D* pSparseMatrixGeom = + # dynamic_cast(_pProjGeom); + dct["type"] = "sparse_matrix" + # dct["MatrixID"] = + # mxCreateDoubleScalar(CMatrixManager::getSingleton().getIndex(pSparseMatrixGeom->getMatrix())) + elif(geom.isOfType(< string > 'fanflat_vec')): + dct["type"] = "fanflat_vec" + return dct + +cdef createVolumeGeometryStruct(CVolumeGeometry2D * geom): + mGeometryInfo = {} + mGeometryInfo["GridColCount"] = geom.getGridColCount() + mGeometryInfo["GridRowCount"] = geom.getGridRowCount() + + mGeometryOptions = {} + mGeometryOptions["WindowMinX"] = geom.getWindowMinX() + mGeometryOptions["WindowMaxX"] = geom.getWindowMaxX() + mGeometryOptions["WindowMinY"] = geom.getWindowMinY() + mGeometryOptions["WindowMaxY"] = geom.getWindowMaxY() + + mGeometryInfo["option"] = mGeometryOptions + return mGeometryInfo diff --git a/builder.py b/builder.py new file mode 100644 index 0000000..617b2b1 --- /dev/null +++ b/builder.py @@ -0,0 +1,81 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- +import sys + +if sys.version_info[0]>2: + raise Exception("Only Python version 2 is supported.") + +from distutils.version import StrictVersion +from distutils.core import setup +from distutils.extension import Extension + +use_cython=False +try: + from Cython.Distutils import build_ext + from Cython.Build import cythonize + import Cython + if StrictVersion(Cython.__version__)>=StrictVersion('0.13'): + use_cython = True +except ImportError: + use_cython = False + +cmdclass = { } +ext_modules = [ ] + +if use_cython: + ext_modules = cythonize("astra/*.pyx") + cmdclass = { 'build_ext': build_ext } +else: + ext_modules += [ + Extension("astra.algorithm_c", [ "astra/algorithm_c.cpp" ],libraries = ['astra']), + Extension("astra.astra_c", [ "astra/astra_c.cpp" ],libraries = ['astra']), + Extension("astra.data2d_c", [ "astra/data2d_c.cpp" ],libraries = ['astra']), + Extension("astra.data3d_c", [ "astra/data3d_c.cpp" ],libraries = ['astra']), + Extension("astra.matrix_c", [ "astra/matrix_c.cpp" ],libraries = ['astra']), + Extension("astra.projector_c", [ "astra/projector_c.cpp" ],libraries = ['astra']), + Extension("astra.utils", [ "astra/utils.cpp" ],libraries = ['astra']), + Extension("astra.extrautils", [ "astra/extrautils.c" ],libraries = ['astra']), + ] + + + + + +setup (name = 'PyASTRAToolbox', + version = '1.0', + description = 'Python interface to the ASTRA-Toolbox', + author='D.M. Pelt', + author_email='D.M.Pelt@cwi.nl', + url='http://dmpelt.github.io/pyastratoolbox/', + #ext_package='astra', + #ext_modules = cythonize(Extension("astra/*.pyx",extra_compile_args=extra_compile_args,extra_linker_args=extra_compile_args)), + license='GPLv3', + ext_modules = ext_modules, + cmdclass = cmdclass, + #ext_modules = [Extension("astra","astra/astra.pyx")], + packages=['astra'], + requires=['numpy'], + ) diff --git a/doc b/doc new file mode 120000 index 0000000..3705b55 --- /dev/null +++ b/doc @@ -0,0 +1 @@ +docSRC/_build/html \ No newline at end of file diff --git a/docSRC/ASTRAProjector.rst b/docSRC/ASTRAProjector.rst new file mode 100644 index 0000000..1c267e3 --- /dev/null +++ b/docSRC/ASTRAProjector.rst @@ -0,0 +1,8 @@ +Helper class: the :mod:`ASTRAProjector` module +============================================== + +.. automodule:: astra.ASTRAProjector + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/Makefile b/docSRC/Makefile new file mode 100644 index 0000000..a005bab --- /dev/null +++ b/docSRC/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docSRC/algorithm.rst b/docSRC/algorithm.rst new file mode 100644 index 0000000..83752bd --- /dev/null +++ b/docSRC/algorithm.rst @@ -0,0 +1,8 @@ +Algorithms: the :mod:`algorithm` module +======================================= + +.. automodule:: astra.algorithm + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/conf.py b/docSRC/conf.py new file mode 100644 index 0000000..389f8ae --- /dev/null +++ b/docSRC/conf.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# +# .. documentation build configuration file, created by +# sphinx-quickstart on Wed Mar 13 16:36:32 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode','sphinx.ext.mathjax','sphinx.ext.intersphinx'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'PyASTRAToolbox' +copyright = u'2013, Centrum Wiskunde & Informatica, Amsterdam' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'doc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', '.tex', u'.. Documentation', + u'Author', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', '', u'.. Documentation', + [u'Author'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', '', u'.. Documentation', + u'Author', '', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'..' +epub_author = u'Author' +epub_publisher = u'Author' +epub_copyright = u'2013, Author' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +#epub_exclude_files = [] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + +intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None), 'numpy':('http://docs.scipy.org/doc/numpy/',None)} diff --git a/docSRC/creators.rst b/docSRC/creators.rst new file mode 100644 index 0000000..d6249c3 --- /dev/null +++ b/docSRC/creators.rst @@ -0,0 +1,8 @@ +Creation of objects: the :mod:`creators` module +=============================================== + +.. automodule:: astra.creators + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/data2d.rst b/docSRC/data2d.rst new file mode 100644 index 0000000..342cbec --- /dev/null +++ b/docSRC/data2d.rst @@ -0,0 +1,8 @@ +2D data objects: the :mod:`data2d` module +========================================= + +.. automodule:: astra.data2d + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/data3d.rst b/docSRC/data3d.rst new file mode 100644 index 0000000..5b7de23 --- /dev/null +++ b/docSRC/data3d.rst @@ -0,0 +1,8 @@ +3D data objects: the :mod:`data3d` module +========================================= + +.. automodule:: astra.data3d + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/functions.rst b/docSRC/functions.rst new file mode 100644 index 0000000..749eb27 --- /dev/null +++ b/docSRC/functions.rst @@ -0,0 +1,8 @@ +Additional functions: the :mod:`functions` module +================================================= + +.. automodule:: astra.functions + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/index.rst b/docSRC/index.rst new file mode 100644 index 0000000..0170e9a --- /dev/null +++ b/docSRC/index.rst @@ -0,0 +1,33 @@ +.. .. documentation master file, created by + sphinx-quickstart on Wed Mar 13 16:36:32 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to PyASTRAToolbox's documentation! +========================================== + +Contents: + +.. toctree:: + :maxdepth: 4 + + data2d + data3d + projector + algorithm + matrix + creators + functions + ASTRAProjector + matlab +.. astra +.. builder + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docSRC/make.bat b/docSRC/make.bat new file mode 100644 index 0000000..d70c604 --- /dev/null +++ b/docSRC/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/docSRC/matlab.rst b/docSRC/matlab.rst new file mode 100644 index 0000000..fb7033e --- /dev/null +++ b/docSRC/matlab.rst @@ -0,0 +1,8 @@ +MATLAB compatibility interface: the :mod:`matlab` module +======================================================== + +.. automodule:: astra.matlab + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/matrix.rst b/docSRC/matrix.rst new file mode 100644 index 0000000..6f11d8a --- /dev/null +++ b/docSRC/matrix.rst @@ -0,0 +1,8 @@ +Sparse matrices: the :mod:`matrix` module +========================================= + +.. automodule:: astra.matrix + :members: + :undoc-members: + :show-inheritance: + diff --git a/docSRC/projector.rst b/docSRC/projector.rst new file mode 100644 index 0000000..b0854e8 --- /dev/null +++ b/docSRC/projector.rst @@ -0,0 +1,8 @@ +Projector object: the :mod:`projector` module +============================================= + +.. automodule:: astra.projector + :members: + :undoc-members: + :show-inheritance: + diff --git a/examples/phantom.mat b/examples/phantom.mat new file mode 100644 index 0000000..c465bbe Binary files /dev/null and b/examples/phantom.mat differ diff --git a/examples/s001_sinogram_par2d.py b/examples/s001_sinogram_par2d.py new file mode 100644 index 0000000..009d9b3 --- /dev/null +++ b/examples/s001_sinogram_par2d.py @@ -0,0 +1,60 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +# Create a basic 256x256 square volume geometry +vol_geom = astra.create_vol_geom(256, 256) + +# Create a parallel beam geometry with 180 angles between 0 and pi, and +# 384 detector pixels of width 1. +# For more details on available geometries, see the online help of the +# function astra_create_proj_geom . +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + +# Load a 256x256 phantom image +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] + +# Create a sinogram using the GPU. +# Note that the first time the GPU is accessed, there may be a delay +# of up to 10 seconds for initialization. +proj_id = astra.create_projector('line',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(P) +pylab.figure(2) +pylab.imshow(sinogram) +pylab.show() + + +# Free memory +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/examples/s002_data2d.py b/examples/s002_data2d.py new file mode 100644 index 0000000..35fb91f --- /dev/null +++ b/examples/s002_data2d.py @@ -0,0 +1,77 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(256, 256) + +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + + +# Create volumes + +# initialized to zero +v0 = astra.data2d.create('-vol', vol_geom) + +# initialized to 3.0 +v1 = astra.data2d.create('-vol', vol_geom, 3.0) + +# initialized to a matrix. A may be a single, double or logical (0/1) array. +import scipy.io +A = scipy.io.loadmat('phantom.mat')['phantom256'] +v2 = astra.data2d.create('-vol', vol_geom, A) + + +# Projection data +s0 = astra.data2d.create('-sino', proj_geom) +# Initialization to a scalar or a matrix also works, exactly as with a volume. + + +# Update data + +# set to zero +astra.data2d.store(v0, 0) + +# set to a matrix +astra.data2d.store(v2, A) + + + +# Retrieve data + +R = astra.data2d.get(v2) +import pylab +pylab.gray() +pylab.imshow(R) +pylab.show() + + +# Free memory +astra.data2d.delete(v0) +astra.data2d.delete(v1) +astra.data2d.delete(v2) +astra.data2d.delete(s0) diff --git a/examples/s003_gpu_reconstruction.py b/examples/s003_gpu_reconstruction.py new file mode 100644 index 0000000..4f6ec1f --- /dev/null +++ b/examples/s003_gpu_reconstruction.py @@ -0,0 +1,75 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + +# As before, create a sinogram from a phantom +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] +proj_id = astra.create_projector('line',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(P) +pylab.figure(2) +pylab.imshow(sinogram) + +# Create a data object for the reconstruction +rec_id = astra.data2d.create('-vol', vol_geom) + +# Set up the parameters for a reconstruction algorithm using the GPU +cfg = astra.astra_dict('SIRT_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id + +# Available algorithms: +# SIRT_CUDA, SART_CUDA, EM_CUDA, FBP_CUDA (see the FBP sample) + + +# Create the algorithm object from the configuration structure +alg_id = astra.algorithm.create(cfg) + +# Run 150 iterations of the algorithm +astra.algorithm.run(alg_id, 150) + +# Get the result +rec = astra.data2d.get(rec_id) +pylab.figure(3) +pylab.imshow(rec) +pylab.show() + +# Clean up. Note that GPU memory is tied up in the algorithm object, +# and main RAM in the data objects. +astra.algorithm.delete(alg_id) +astra.data2d.delete(rec_id) +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/examples/s004_cpu_reconstruction.py b/examples/s004_cpu_reconstruction.py new file mode 100644 index 0000000..8385cf8 --- /dev/null +++ b/examples/s004_cpu_reconstruction.py @@ -0,0 +1,81 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + +# For CPU-based algorithms, a "projector" object specifies the projection +# model used. In this case, we use the "strip" model. +proj_id = astra.create_projector('strip', proj_geom, vol_geom) + +# Create a sinogram from a phantom +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] +sinogram_id, sinogram = astra.create_sino(P, proj_id) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(P) +pylab.figure(2) +pylab.imshow(sinogram) + +# Create a data object for the reconstruction +rec_id = astra.data2d.create('-vol', vol_geom) + +# Set up the parameters for a reconstruction algorithm using the CPU +# The main difference with the configuration of a GPU algorithm is the +# extra ProjectorId setting. +cfg = astra.astra_dict('SIRT') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id +cfg['ProjectorId'] = proj_id + +# Available algorithms: +# ART, SART, SIRT, CGLS, FBP + + +# Create the algorithm object from the configuration structure +alg_id = astra.algorithm.create(cfg) + +# Run 20 iterations of the algorithm +# This will have a runtime in the order of 10 seconds. +astra.algorithm.run(alg_id, 20) + +# Get the result +rec = astra.data2d.get(rec_id) +pylab.figure(3) +pylab.imshow(rec) +pylab.show() + +# Clean up. +astra.algorithm.delete(alg_id) +astra.data2d.delete(rec_id) +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/examples/s005_3d_geometry.py b/examples/s005_3d_geometry.py new file mode 100644 index 0000000..5ed6061 --- /dev/null +++ b/examples/s005_3d_geometry.py @@ -0,0 +1,113 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(64, 64, 64) + + +# There are two main 3d projection geometry types: cone beam and parallel beam. +# Each has a regular variant, and a 'vec' variant. +# The 'vec' variants are completely free in the placement of source/detector, +# while the regular variants assume circular trajectories around the z-axis. + + +# ------------- +# Parallel beam +# ------------- + + +# Circular + +# Parameters: width of detector column, height of detector row, #rows, #columns +angles = np.linspace(0, 2*np.pi, 48,False) +proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0, 32, 64, angles) + + +# Free + +# We generate the same geometry as the circular one above. +vectors = np.zeros((len(angles), 12)) +for i in xrange(len(angles)): + # ray direction + vectors[i,0] = np.sin(angles[i]) + vectors[i,1] = -np.cos(angles[i]) + vectors[i,2] = 0 + + # center of detector + vectors[i,3:6] = 0 + + # vector from detector pixel (0,0) to (0,1) + vectors[i,6] = np.cos(angles[i]) + vectors[i,7] = np.sin(angles[i]) + vectors[i,8] = 0; + + # vector from detector pixel (0,0) to (1,0) + vectors[i,9] = 0 + vectors[i,10] = 0 + vectors[i,11] = 1 + +# Parameters: #rows, #columns, vectors +proj_geom = astra.create_proj_geom('parallel3d_vec', 32, 64, vectors) + +# ---------- +# Cone beam +# ---------- + + +# Circular + +# Parameters: width of detector column, height of detector row, #rows, #columns, +# angles, distance source-origin, distance origin-detector +angles = np.linspace(0, 2*np.pi, 48,False) +proj_geom = astra.create_proj_geom('cone', 1.0, 1.0, 32, 64, angles, 1000, 0) + +# Free + +vectors = np.zeros((len(angles), 12)) +for i in xrange(len(angles)): + # source + vectors[i,0] = np.sin(angles[i]) * 1000 + vectors[i,1] = -np.cos(angles[i]) * 1000 + vectors[i,2] = 0 + + # center of detector + vectors[i,3:6] = 0 + + # vector from detector pixel (0,0) to (0,1) + vectors[i,6] = np.cos(angles[i]) + vectors[i,7] = np.sin(angles[i]) + vectors[i,8] = 0 + + # vector from detector pixel (0,0) to (1,0) + vectors[i,9] = 0 + vectors[i,10] = 0 + vectors[i,11] = 1 + +# Parameters: #rows, #columns, vectors +proj_geom = astra.create_proj_geom('cone_vec', 32, 64, vectors) + diff --git a/examples/s006_3d_data.py b/examples/s006_3d_data.py new file mode 100644 index 0000000..8794b12 --- /dev/null +++ b/examples/s006_3d_data.py @@ -0,0 +1,76 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +# Create a 3D volume geometry. +# Parameter order: rows, colums, slices (y, x, z) +vol_geom = astra.create_vol_geom(64, 48, 32) + + +# Create volumes + +# initialized to zero +v0 = astra.data3d.create('-vol', vol_geom) + +# initialized to 3.0 +v1 = astra.data3d.create('-vol', vol_geom, 3.0) + +# initialized to a matrix. A may be a single or double array. +# Coordinate order: column, row, slice (x, y, z) +A = np.zeros((48, 64, 32)) +v2 = astra.data3d.create('-vol', vol_geom, A) + + +# Projection data + +# 2 projection directions, along x and y axis resp. +V = np.array([[ 1,0,0, 0,0,0, 0,1,0, 0,0,1], + [0,1,0, 0,0,0, -1,0,0, 0,0,1]],dtype=np.float) +# 32 rows (v), 64 columns (u) +proj_geom = astra.create_proj_geom('parallel3d_vec', 32, 64, V) + +s0 = astra.data3d.create('-proj3d', proj_geom) + +# Initialization to a scalar or zero works exactly as with a volume. + +# Initialized to a matrix: +# Coordinate order: column (u), angle, row (v) +A = np.zeros((64, 2, 32)) +s1 = astra.data3d.create('-proj3d', proj_geom, A) + + +# Retrieve data: +R = astra.data3d.get(v1) + + +# Delete all created data objects +astra.data3d.delete(v0) +astra.data3d.delete(v1) +astra.data3d.delete(v2) +astra.data3d.delete(s0) +astra.data3d.delete(s1) diff --git a/examples/s007_3d_reconstruction.py b/examples/s007_3d_reconstruction.py new file mode 100644 index 0000000..40e9556 --- /dev/null +++ b/examples/s007_3d_reconstruction.py @@ -0,0 +1,77 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(128, 128, 128) + +angles = np.linspace(0, np.pi, 180,False) +proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0, 128, 192, angles) + +# Create a simple hollow cube phantom +cube = np.zeros((128,128,128)) +cube[17:113,17:113,17:113] = 1 +cube[33:97,33:97,33:97] = 0 + +# Create projection data from this +proj_id, proj_data = astra.create_sino3d_gpu(cube, proj_geom, vol_geom) + +# Display a single projection image +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(proj_data[:,20,:]) + +# Create a data object for the reconstruction +rec_id = astra.data3d.create('-vol', vol_geom) + +# Set up the parameters for a reconstruction algorithm using the GPU +cfg = astra.astra_dict('SIRT3D_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = proj_id + + +# Create the algorithm object from the configuration structure +alg_id = astra.algorithm.create(cfg) + +# Run 150 iterations of the algorithm +# Note that this requires about 750MB of GPU memory, and has a runtime +# in the order of 10 seconds. +astra.algorithm.run(alg_id, 150) + +# Get the result +rec = astra.data3d.get(rec_id) +pylab.figure(2) +pylab.imshow(rec[:,:,65]) +pylab.show() + + +# Clean up. Note that GPU memory is tied up in the algorithm object, +# and main RAM in the data objects. +astra.algorithm.delete(alg_id) +astra.data3d.delete(rec_id) +astra.data3d.delete(proj_id) diff --git a/examples/s008_gpu_selection.py b/examples/s008_gpu_selection.py new file mode 100644 index 0000000..c42e53b --- /dev/null +++ b/examples/s008_gpu_selection.py @@ -0,0 +1,61 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] + +proj_id = astra.create_projector('line',proj_geom,vol_geom) + +# Create a sinogram from a phantom, using GPU #1. (The default is #0) +sinogram_id, sinogram = astra.create_sino(P, proj_id, useCUDA=True, gpuIndex=1) + + +# Set up the parameters for a reconstruction algorithm using the GPU +rec_id = astra.data2d.create('-vol', vol_geom) +cfg = astra.astra_dict('SIRT_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id + +# Use GPU #1 for the reconstruction. (The default is #0.) +cfg['option'] = {} +cfg['option']['GPUindex'] = 1 + +# Run 150 iterations of the algorithm +alg_id = astra.algorithm.create(cfg) +astra.algorithm.run(alg_id, 150) +rec = astra.data2d.get(rec_id) + + +# Clean up. +astra.algorithm.delete(alg_id) +astra.data2d.delete(rec_id) +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/examples/s009_projection_matrix.py b/examples/s009_projection_matrix.py new file mode 100644 index 0000000..2ff0280 --- /dev/null +++ b/examples/s009_projection_matrix.py @@ -0,0 +1,65 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + +# For CPU-based algorithms, a "projector" object specifies the projection +# model used. In this case, we use the "line" model. +proj_id = astra.create_projector('line', proj_geom, vol_geom) + +# Generate the projection matrix for this projection model. +# This creates a matrix W where entry w_{i,j} corresponds to the +# contribution of volume element j to detector element i. +matrix_id = astra.projector.matrix(proj_id) + +# Get the projection matrix as a Matlab sparse matrix. +W = astra.matrix.get(matrix_id) + + +# Manually use this projection matrix to do a projection: +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] +s = W.dot(P.flatten()) +s = np.reshape(s, (len(proj_geom['ProjectionAngles']),proj_geom['DetectorCount'])) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(s) +pylab.show() + +# Each row of the projection matrix corresponds to a detector element. +# Detector t for angle p is for row 1 + t + p*proj_geom.DetectorCount. +# Each column corresponds to a volume pixel. +# Pixel (x,y) corresponds to column 1 + x + y*vol_geom.GridColCount. + + +astra.projector.delete(proj_id) +astra.matrix.delete(matrix_id) diff --git a/examples/s010_supersampling.py b/examples/s010_supersampling.py new file mode 100644 index 0000000..1a337bc --- /dev/null +++ b/examples/s010_supersampling.py @@ -0,0 +1,85 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 3.0, 128, np.linspace(0,np.pi,180,False)) +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] + +# Because the astra.create_sino method does not have support for +# all possible algorithm options, we manually create a sinogram +phantom_id = astra.data2d.create('-vol', vol_geom, P) +sinogram_id = astra.data2d.create('-sino', proj_geom) +cfg = astra.astra_dict('FP_CUDA') +cfg['VolumeDataId'] = phantom_id +cfg['ProjectionDataId'] = sinogram_id + +# Set up 3 rays per detector element +cfg['option'] = {} +cfg['option']['DetectorSuperSampling'] = 3 + +alg_id = astra.algorithm.create(cfg) +astra.algorithm.run(alg_id) +astra.algorithm.delete(alg_id) +astra.data2d.delete(phantom_id) + +sinogram3 = astra.data2d.get(sinogram_id) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(P) +pylab.figure(2) +pylab.imshow(sinogram3) + +# Create a reconstruction, also using supersampling +rec_id = astra.data2d.create('-vol', vol_geom) +cfg = astra.astra_dict('SIRT_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id +# Set up 3 rays per detector element +cfg['option'] = {} +cfg['option']['DetectorSuperSampling'] = 3 + +# There is also an option for supersampling during the backprojection step. +# This should be used if your detector pixels are smaller than the voxels. + +# Set up 2 rays per image pixel dimension, for 4 rays total per image pixel. +# cfg['option']['PixelSuperSampling'] = 2 + + +alg_id = astra.algorithm.create(cfg) +astra.algorithm.run(alg_id, 150) +astra.algorithm.delete(alg_id) + +rec = astra.data2d.get(rec_id) +pylab.figure(3) +pylab.imshow(rec) +pylab.show() + diff --git a/examples/s011_object_info.py b/examples/s011_object_info.py new file mode 100644 index 0000000..02f387a --- /dev/null +++ b/examples/s011_object_info.py @@ -0,0 +1,54 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra + +# Create two volume geometries +vol_geom1 = astra.create_vol_geom(256, 256) +vol_geom2 = astra.create_vol_geom(512, 256) + +# Create volumes +v0 = astra.data2d.create('-vol', vol_geom1) +v1 = astra.data2d.create('-vol', vol_geom2) +v2 = astra.data2d.create('-vol', vol_geom2) + +# Show the currently allocated volumes +astra.data2d.info() + + +astra.data2d.delete(v2) +astra.data2d.info() + +astra.data2d.clear() +astra.data2d.info() + + + +# The same clear and info command also work for other object types: +astra.algorithm.info() +astra.data3d.info() +astra.projector.info() +astra.matrix.info() diff --git a/examples/s012_masks.py b/examples/s012_masks.py new file mode 100644 index 0000000..441d11b --- /dev/null +++ b/examples/s012_masks.py @@ -0,0 +1,92 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + + +import astra +import numpy as np + +# In this example we will create a reconstruction in a circular region, +# instead of the usual rectangle. + +# This is done by placing a circular mask on the square reconstruction volume: + +c = np.linspace(-127.5,127.5,256) +x, y = np.meshgrid(c,c) +mask = np.array((x**2 + y**2 < 127.5**2),dtype=np.float) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(mask) + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,50,False)) + +# As before, create a sinogram from a phantom +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] +proj_id = astra.create_projector('line',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) + +pylab.figure(2) +pylab.imshow(P) +pylab.figure(3) +pylab.imshow(sinogram) + +# Create a data object for the reconstruction +rec_id = astra.data2d.create('-vol', vol_geom) + +# Create a data object for the mask +mask_id = astra.data2d.create('-vol', vol_geom, mask) + +# Set up the parameters for a reconstruction algorithm using the GPU +cfg = astra.astra_dict('SIRT_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id +cfg['option'] = {} +cfg['option']['ReconstructionMaskId'] = mask_id + +# Create the algorithm object from the configuration structure +alg_id = astra.algorithm.create(cfg) + +# Run 150 iterations of the algorithm +astra.algorithm.run(alg_id, 150) + +# Get the result +rec = astra.data2d.get(rec_id) + +pylab.figure(4) +pylab.imshow(rec) + +pylab.show() + +# Clean up. Note that GPU memory is tied up in the algorithm object, +# and main RAM in the data objects. +astra.algorithm.delete(alg_id) +astra.data2d.delete(mask_id) +astra.data2d.delete(rec_id) +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/examples/s013_constraints.py b/examples/s013_constraints.py new file mode 100644 index 0000000..009360e --- /dev/null +++ b/examples/s013_constraints.py @@ -0,0 +1,77 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +# In this example we will create a reconstruction constrained to +# greyvalues between 0 and 1 + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,50,False)) + +# As before, create a sinogram from a phantom +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] +proj_id = astra.create_projector('line',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(P) +pylab.figure(2) +pylab.imshow(sinogram) + +# Create a data object for the reconstruction +rec_id = astra.data2d.create('-vol', vol_geom) + +# Set up the parameters for a reconstruction algorithm using the GPU +cfg = astra.astra_dict('SIRT_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id +cfg['option']={} +cfg['option']['MinConstraint'] = 0 +cfg['option']['MaxConstraint'] = 1 + +# Create the algorithm object from the configuration structure +alg_id = astra.algorithm.create(cfg) + +# Run 150 iterations of the algorithm +astra.algorithm.run(alg_id, 150) + +# Get the result +rec = astra.data2d.get(rec_id) +pylab.figure(3) +pylab.imshow(rec) +pylab.show() + +# Clean up. Note that GPU memory is tied up in the algorithm object, +# and main RAM in the data objects. +astra.algorithm.delete(alg_id) +astra.data2d.delete(rec_id) +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/examples/s014_FBP.py b/examples/s014_FBP.py new file mode 100644 index 0000000..ef4afc2 --- /dev/null +++ b/examples/s014_FBP.py @@ -0,0 +1,76 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + +# As before, create a sinogram from a phantom +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] +proj_id = astra.create_projector('line',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(P) +pylab.figure(2) +pylab.imshow(sinogram) + +# Create a data object for the reconstruction +rec_id = astra.data2d.create('-vol', vol_geom) + +# create configuration +cfg = astra.astra_dict('FBP_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id +cfg['FilterType'] = 'Ram-Lak' + +# possible values for FilterType: +# none, ram-lak, shepp-logan, cosine, hamming, hann, tukey, lanczos, +# triangular, gaussian, barlett-hann, blackman, nuttall, blackman-harris, +# blackman-nuttall, flat-top, kaiser, parzen + + +# Create and run the algorithm object from the configuration structure +alg_id = astra.algorithm.create(cfg) +astra.algorithm.run(alg_id) + +# Get the result +rec = astra.data2d.get(rec_id) +pylab.figure(3) +pylab.imshow(rec) +pylab.show() + +# Clean up. Note that GPU memory is tied up in the algorithm object, +# and main RAM in the data objects. +astra.algorithm.delete(alg_id) +astra.data2d.delete(rec_id) +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/examples/s015_fp_bp.py b/examples/s015_fp_bp.py new file mode 100644 index 0000000..10c238d --- /dev/null +++ b/examples/s015_fp_bp.py @@ -0,0 +1,86 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + + +# This example demonstrates using the FP and BP primitives with Matlab's lsqr +# solver. Calls to FP (astra_create_sino_cuda) and +# BP (astra_create_backprojection_cuda) are wrapped in a function astra_wrap, +# and a handle to this function is passed to lsqr. + +# Because in this case the inputs/outputs of FP and BP have to be vectors +# instead of images (matrices), the calls require reshaping to and from vectors. + +import astra +import numpy as np + +# FP/BP wrapper class +class astra_wrap(object): + def __init__(self,proj_geom,vol_geom): + self.proj_id = astra.create_projector('line',proj_geom,vol_geom) + self.shape = (proj_geom['DetectorCount']*len(proj_geom['ProjectionAngles']),vol_geom['GridColCount']*vol_geom['GridRowCount']) + self.dtype = np.float + + def matvec(self,v): + sid, s = astra.create_sino(np.reshape(v,(vol_geom['GridRowCount'],vol_geom['GridColCount'])),self.proj_id,useCUDA=True) + astra.data2d.delete(sid) + return s.flatten() + + def rmatvec(self,v): + bid, b = astra.create_backprojection(np.reshape(v,(len(proj_geom['ProjectionAngles']),proj_geom['DetectorCount'],)),self.proj_id,useCUDA=True) + astra.data2d.delete(bid) + return b.flatten() + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + +# Create a 256x256 phantom image +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] + +# Create a sinogram using the GPU. +proj_id = astra.create_projector('line',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) + +# Reshape the sinogram into a vector +b = sinogram.flatten() + +# Call lsqr with ASTRA FP and BP +import scipy.sparse.linalg +wrapper = astra_wrap(proj_geom,vol_geom) +result = scipy.sparse.linalg.lsqr(wrapper,b,atol=1e-4,btol=1e-4,iter_lim=25) + +# Reshape the result into an image +Y = np.reshape(result[0],(vol_geom['GridRowCount'], vol_geom['GridColCount'])); + +import pylab +pylab.gray() +pylab.imshow(Y) +pylab.show() + +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) +astra.projector.delete(wrapper.proj_id) + diff --git a/examples/s016_plots.py b/examples/s016_plots.py new file mode 100644 index 0000000..8ded525 --- /dev/null +++ b/examples/s016_plots.py @@ -0,0 +1,85 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +import astra +import numpy as np + + +vol_geom = astra.create_vol_geom(256, 256) +proj_geom = astra.create_proj_geom('parallel', 1.0, 384, np.linspace(0,np.pi,180,False)) + +# As before, create a sinogram from a phantom +import scipy.io +P = scipy.io.loadmat('phantom.mat')['phantom256'] +proj_id = astra.create_projector('line',proj_geom,vol_geom) +sinogram_id, sinogram = astra.create_sino(P, proj_id,useCUDA=True) + +import pylab +pylab.gray() +pylab.figure(1) +pylab.imshow(P) +pylab.figure(2) +pylab.imshow(sinogram) + +# Create a data object for the reconstruction +rec_id = astra.data2d.create('-vol', vol_geom) + +# Set up the parameters for a reconstruction algorithm using the GPU +cfg = astra.astra_dict('SIRT_CUDA') +cfg['ReconstructionDataId'] = rec_id +cfg['ProjectionDataId'] = sinogram_id + +# Create the algorithm object from the configuration structure +alg_id = astra.algorithm.create(cfg) + +# Run 1500 iterations of the algorithm one at a time, keeping track of errors +nIters = 1500 +phantom_error = np.zeros(nIters) +residual_error = np.zeros(nIters) +for i in xrange(nIters): + # Run a single iteration + astra.algorithm.run(alg_id, 1) + residual_error[i] = astra.algorithm.get_res_norm(alg_id) + rec = astra.data2d.get(rec_id) + phantom_error[i] = np.sqrt(((rec - P)**2).sum()) + +# Get the result +rec = astra.data2d.get(rec_id) +pylab.figure(3) +pylab.imshow(rec) + +pylab.figure(4) +pylab.plot(residual_error) +pylab.figure(5) +pylab.plot(phantom_error) + +pylab.show() + +# Clean up. +astra.algorithm.delete(alg_id) +astra.data2d.delete(rec_id) +astra.data2d.delete(sinogram_id) +astra.projector.delete(proj_id) diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..fd58c1a --- /dev/null +++ b/install.sh @@ -0,0 +1,95 @@ +#! /bin/bash + +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#----------------------------------------------------------------------- + +function printHelp { + echo "install.sh: Installs Python interface to the ASTRA-toolbox" + echo + echo "Usage: ./install.sh [-i astra_include_path] [-l astra_library_path] [-p python_executable_path] [-c cuda_path]" + echo + echo -e "\t-i astra_include_path:\t\tspecify path to astra header files (without trailing astra/) (Optional)" + echo -e "\t-l astra_library_path:\t\tspecify parent path of astra library file (Optional)" + echo -e "\t-p python_executable_path:\tspecify path to python executable (Optional)" + echo -e "\t-c cuda_path:\t\t\tpath to CUDA (Optional)" + echo -e "\t-h:\t\t\t\tprint this help (Optional)" + exit 1 +} + + +CINFLAGS="" +LINFLAGS="" +PEX=python +while getopts ":i:l:p:c:" opt; do + case $opt in + h) + printHelp + ;; + i) + CINFLAGS="${CINFLAGS} -I${OPTARG}" + ;; + l) + LINFLAGS="${LINFLAGS} -L${OPTARG}" + ;; + c) + LINFLAGS="${LINFLAGS} -DASTRA_CUDA -L${OPTARG}/lib" + CINFLAGS="${CINFLAGS} -DASTRA_CUDA -I${OPTARG}/include" + ;; + p) + PEX=${OPTARG} + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + printHelp + ;; + esac +done + +if [ -d build ] +then + echo "Previous build found!" + echo "Remove it before rebuilding (recommended)?" + pushd build > /dev/null + BUILDPATH=`pwd` + popd > /dev/null + read -p "Remove $BUILDPATH (y/n/q)?" choice + case "$choice" in + q|Q ) + exit 1 + ;; + y|Y ) + rm -r build + ;; + n|N ) + ;; + * ) + echo "Invalid choice, quitting..." + exit 1 + ;; + esac +fi + +CPPFLAGS=${CINFLAGS} LDFLAGS=${LINFLAGS} $PEX builder.py install diff --git a/license-header.txt b/license-header.txt new file mode 100644 index 0000000..e356190 --- /dev/null +++ b/license-header.txt @@ -0,0 +1,25 @@ +#----------------------------------------------------------------------- +#Copyright 2013 Centrum Wiskunde & Informatica, Amsterdam +# +#Author: Daniel M. Pelt +#Contact: D.M.Pelt@cwi.nl +#Website: http://dmpelt.github.io/pyastratoolbox/ +# +# +#This file is part of the Python interface to the +#All Scale Tomographic Reconstruction Antwerp Toolbox ("ASTRA Toolbox"). +# +#The Python interface to the ASTRA Toolbox 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. +# +#The Python interface to the ASTRA Toolbox 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 the Python interface to the ASTRA Toolbox. If not, see . +# +#-----------------------------------------------------------------------