From 306d4dce90ce402fba3f8f7a354fd9a48ec50675 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 30 May 2022 10:11:38 +0200 Subject: [PATCH 01/53] Change license to GPL --- LICENSE | 695 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- setup.cfg | 4 +- 2 files changed, 676 insertions(+), 23 deletions(-) diff --git a/LICENSE b/LICENSE index a0b058a8e..f288702d2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,674 @@ -MIT License - -Copyright (c) 2018 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + 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/setup.cfg b/setup.cfg index a77b1e909..c053e526e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,12 +5,12 @@ description = A Quantum compUting PULse parametrization and SEquencing framework long_description = file: README.md long_description_content_type = text/markdown author = Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University -license = MIT +license = GPLv3+ license_files = LICENSE keywords = quantum, physics, control pulse, qubit classifiers = Programming Language :: Python :: 3 - License :: OSI Approved :: MIT License + OSI Approved :: GNU General Public License v3 or later (GPLv3+) Operating System :: OS Independent Topic :: Scientific/Engineering Intended Audience :: Science/Research From 2282171dec31e43a3006158b5f53dc0a0b754610 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 27 May 2024 15:25:30 +0200 Subject: [PATCH 02/53] Add SPDX license headers and move license file --- LICENSE | 674 ------------------ LICENSES/GPL-3.0-or-later.txt | 232 ++++++ qctoolkit/__init__.py | 4 + qupulse/__init__.py | 4 + qupulse/__init__.pyi | 3 + qupulse/_program/__init__.py | 4 + qupulse/_program/_loop.py | 4 + qupulse/_program/tabor.py | 4 + qupulse/_program/transformation.py | 4 + qupulse/_program/volatile.py | 4 + qupulse/_program/waveforms.py | 4 + qupulse/comparable.py | 4 + qupulse/examples/VolatileParameters.py | 4 + qupulse/expressions/__init__.py | 4 + qupulse/expressions/protocol.py | 4 + qupulse/expressions/sympy.py | 4 + qupulse/expressions/wrapper.py | 4 + qupulse/hardware/__init__.py | 4 + qupulse/hardware/awgs/__init__.py | 4 + qupulse/hardware/awgs/base.py | 4 + qupulse/hardware/awgs/dummy.py | 4 + qupulse/hardware/awgs/tabor.py | 4 + qupulse/hardware/awgs/tektronix.py | 4 + qupulse/hardware/awgs/zihdawg.py | 4 + qupulse/hardware/dacs/__init__.py | 4 + qupulse/hardware/dacs/alazar.py | 4 + qupulse/hardware/dacs/alazar2.py | 4 + qupulse/hardware/dacs/dac_base.py | 4 + qupulse/hardware/dacs/dummy.py | 4 + qupulse/hardware/feature_awg/base.py | 4 + qupulse/hardware/feature_awg/base_features.py | 4 + .../feature_awg/channel_tuple_wrapper.py | 4 + qupulse/hardware/feature_awg/features.py | 4 + qupulse/hardware/feature_awg/tabor.py | 4 + qupulse/hardware/setup.py | 4 + qupulse/hardware/util.py | 4 + qupulse/parameter_scope.py | 4 + qupulse/plotting.py | 4 + qupulse/program/__init__.py | 4 + qupulse/program/linspace.py | 4 + qupulse/program/loop.py | 4 + qupulse/program/transformation.py | 4 + qupulse/program/volatile.py | 4 + qupulse/program/waveforms.py | 4 + qupulse/pulses/__init__.py | 4 + qupulse/pulses/abstract_pulse_template.py | 4 + qupulse/pulses/arithmetic_pulse_template.py | 3 + qupulse/pulses/constant_pulse_template.py | 4 + qupulse/pulses/function_pulse_template.py | 4 + qupulse/pulses/interpolation.py | 4 + qupulse/pulses/loop_pulse_template.py | 4 + qupulse/pulses/mapping_pulse_template.py | 4 + qupulse/pulses/measurement.py | 4 + .../pulses/multi_channel_pulse_template.py | 4 + qupulse/pulses/parameters.py | 4 + qupulse/pulses/plotting.py | 4 + qupulse/pulses/point_pulse_template.py | 4 + qupulse/pulses/pulse_template.py | 4 + .../pulse_template_parameter_mapping.py | 4 + qupulse/pulses/range.py | 4 + qupulse/pulses/repetition_pulse_template.py | 4 + qupulse/pulses/sequence_pulse_template.py | 4 + qupulse/pulses/table_pulse_template.py | 4 + .../pulses/time_reversal_pulse_template.py | 4 + qupulse/serialization.py | 4 + qupulse/utils/__init__.py | 4 + qupulse/utils/numeric.py | 4 + qupulse/utils/performance.py | 4 + qupulse/utils/sympy.py | 4 + qupulse/utils/tree.py | 4 + qupulse/utils/types.py | 4 + setup.cfg | 4 +- 72 files changed, 508 insertions(+), 676 deletions(-) delete mode 100644 LICENSE create mode 100644 LICENSES/GPL-3.0-or-later.txt diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702d2..000000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - 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/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt new file mode 100644 index 000000000..f6cdd22a6 --- /dev/null +++ b/LICENSES/GPL-3.0-or-later.txt @@ -0,0 +1,232 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 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/qctoolkit/__init__.py b/qctoolkit/__init__.py index b9a2ab843..208c2083f 100644 --- a/qctoolkit/__init__.py +++ b/qctoolkit/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This is a (hopefully temporary) alias package to not break existing code. If you know a better way please change""" import sys import re diff --git a/qupulse/__init__.py b/qupulse/__init__.py index 5bf9d2ffe..92a430692 100644 --- a/qupulse/__init__.py +++ b/qupulse/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """A Quantum compUting PULse parametrization and SEquencing framework.""" import lazy_loader as lazy diff --git a/qupulse/__init__.pyi b/qupulse/__init__.pyi index 8c311a9e3..f0e1cf5ff 100644 --- a/qupulse/__init__.pyi +++ b/qupulse/__init__.pyi @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later from . import pulses from . import hardware diff --git a/qupulse/_program/__init__.py b/qupulse/_program/__init__.py index 93773ebb1..5f2427b92 100644 --- a/qupulse/_program/__init__.py +++ b/qupulse/_program/__init__.py @@ -1 +1,5 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This is a private package meaning there are no stability guarantees.""" diff --git a/qupulse/_program/_loop.py b/qupulse/_program/_loop.py index b5ad53deb..3eec640cc 100644 --- a/qupulse/_program/_loop.py +++ b/qupulse/_program/_loop.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """Backwards compatibility link to qupulse.program.loop""" from qupulse.program.loop import * diff --git a/qupulse/_program/tabor.py b/qupulse/_program/tabor.py index 235cc945c..5b690b4d4 100644 --- a/qupulse/_program/tabor.py +++ b/qupulse/_program/tabor.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import dataclasses import sys from typing import NamedTuple, Optional, List, Generator, Tuple, Sequence, Mapping, Union, Dict, FrozenSet, cast,\ diff --git a/qupulse/_program/transformation.py b/qupulse/_program/transformation.py index c6a0d0def..977b01c5f 100644 --- a/qupulse/_program/transformation.py +++ b/qupulse/_program/transformation.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from qupulse.program.transformation import * import qupulse.program.transformation diff --git a/qupulse/_program/volatile.py b/qupulse/_program/volatile.py index ddfe2aa16..e50970865 100644 --- a/qupulse/_program/volatile.py +++ b/qupulse/_program/volatile.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from qupulse.program.volatile import * import qupulse.program.volatile diff --git a/qupulse/_program/waveforms.py b/qupulse/_program/waveforms.py index 5038c3988..964236438 100644 --- a/qupulse/_program/waveforms.py +++ b/qupulse/_program/waveforms.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """Backwards compatibility link to qupulse.program.waveforms""" from qupulse.program.waveforms import * diff --git a/qupulse/comparable.py b/qupulse/comparable.py index 2582faa8b..c6d929364 100644 --- a/qupulse/comparable.py +++ b/qupulse/comparable.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines the abstract Comparable class.""" from abc import abstractmethod from typing import Hashable, Any diff --git a/qupulse/examples/VolatileParameters.py b/qupulse/examples/VolatileParameters.py index 53dcc3dab..ec8228a6c 100644 --- a/qupulse/examples/VolatileParameters.py +++ b/qupulse/examples/VolatileParameters.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from qupulse.hardware.setup import HardwareSetup, PlaybackChannel, MarkerChannel from qupulse.pulses import PointPT, RepetitionPT, TablePT diff --git a/qupulse/expressions/__init__.py b/qupulse/expressions/__init__.py index 52aa5f325..398edb394 100644 --- a/qupulse/expressions/__init__.py +++ b/qupulse/expressions/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This subpackage contains qupulse's expression logic. The submodule :py:mod:`.expressions.protocol` defines the :py:class:`typing.Protocol` that expression functionality providers must implement. This allows to substitute the powerful and expressive but slow default implementation with a faster less expressive backend. diff --git a/qupulse/expressions/protocol.py b/qupulse/expressions/protocol.py index 667337c3d..917291e81 100644 --- a/qupulse/expressions/protocol.py +++ b/qupulse/expressions/protocol.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module contains the interface / protocol descriptions of ``Expression``, ``ExpressionScalar`` and ``ExpressionVector``.""" diff --git a/qupulse/expressions/sympy.py b/qupulse/expressions/sympy.py index 150a1b6a5..30d230d5d 100644 --- a/qupulse/expressions/sympy.py +++ b/qupulse/expressions/sympy.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """ This module defines the class Expression to represent mathematical expression as well as corresponding exception classes. diff --git a/qupulse/expressions/wrapper.py b/qupulse/expressions/wrapper.py index 1052c1174..984e6479a 100644 --- a/qupulse/expressions/wrapper.py +++ b/qupulse/expressions/wrapper.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module contains the function :py:``make_wrappers`` to define wrapper classes for expression protocol implementations which only implements methods of the protocol. It is used for finding code that relies on expression implementation details.""" diff --git a/qupulse/hardware/__init__.py b/qupulse/hardware/__init__.py index a545e01d8..0d5cf722b 100644 --- a/qupulse/hardware/__init__.py +++ b/qupulse/hardware/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """Contains drivers for AWG control and digitizer configuration as well as a unifying interface to all instruments: :class:`~qupulse.hardware.setup.HardwareSetup`""" diff --git a/qupulse/hardware/awgs/__init__.py b/qupulse/hardware/awgs/__init__.py index e76d4d9b8..ab11be2d9 100644 --- a/qupulse/hardware/awgs/__init__.py +++ b/qupulse/hardware/awgs/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import lazy_loader as lazy diff --git a/qupulse/hardware/awgs/base.py b/qupulse/hardware/awgs/base.py index 108230179..9ed5e5756 100644 --- a/qupulse/hardware/awgs/base.py +++ b/qupulse/hardware/awgs/base.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines the common interface for arbitrary waveform generators. Classes: diff --git a/qupulse/hardware/awgs/dummy.py b/qupulse/hardware/awgs/dummy.py index 249497483..fd010d0fc 100644 --- a/qupulse/hardware/awgs/dummy.py +++ b/qupulse/hardware/awgs/dummy.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Tuple, Set from .base import AWG, ProgramOverwriteException diff --git a/qupulse/hardware/awgs/tabor.py b/qupulse/hardware/awgs/tabor.py index 90e03866e..b500f3645 100644 --- a/qupulse/hardware/awgs/tabor.py +++ b/qupulse/hardware/awgs/tabor.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import fractions import functools import warnings diff --git a/qupulse/hardware/awgs/tektronix.py b/qupulse/hardware/awgs/tektronix.py index eaaa7a360..26cfb8d17 100644 --- a/qupulse/hardware/awgs/tektronix.py +++ b/qupulse/hardware/awgs/tektronix.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Tuple, Callable, Optional, Sequence, Union, Dict, Mapping, Set from types import MappingProxyType import numpy as np diff --git a/qupulse/hardware/awgs/zihdawg.py b/qupulse/hardware/awgs/zihdawg.py index 519051c38..2b66c8c79 100644 --- a/qupulse/hardware/awgs/zihdawg.py +++ b/qupulse/hardware/awgs/zihdawg.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import sys import argparse import logging diff --git a/qupulse/hardware/dacs/__init__.py b/qupulse/hardware/dacs/__init__.py index b2e3277cb..f40cf97d7 100644 --- a/qupulse/hardware/dacs/__init__.py +++ b/qupulse/hardware/dacs/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import lazy_loader as lazy __getattr__, __dir__, __all__ = lazy.attach( diff --git a/qupulse/hardware/dacs/alazar.py b/qupulse/hardware/dacs/alazar.py index c694c4be6..0a4c08158 100644 --- a/qupulse/hardware/dacs/alazar.py +++ b/qupulse/hardware/dacs/alazar.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import dataclasses from typing import Dict, Any, Optional, Tuple, List, Iterable, Callable, Sequence from collections import defaultdict diff --git a/qupulse/hardware/dacs/alazar2.py b/qupulse/hardware/dacs/alazar2.py index 15a881cf8..4cd7db2f7 100644 --- a/qupulse/hardware/dacs/alazar2.py +++ b/qupulse/hardware/dacs/alazar2.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import dataclasses from typing import Union, Iterable, Dict, Tuple, Mapping, Optional from types import MappingProxyType diff --git a/qupulse/hardware/dacs/dac_base.py b/qupulse/hardware/dacs/dac_base.py index cab2e7b7f..14be68934 100644 --- a/qupulse/hardware/dacs/dac_base.py +++ b/qupulse/hardware/dacs/dac_base.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from abc import ABCMeta, abstractmethod from typing import Dict, Tuple, Iterable, TYPE_CHECKING diff --git a/qupulse/hardware/dacs/dummy.py b/qupulse/hardware/dacs/dummy.py index ba0cf6f51..3a8fc3a7a 100644 --- a/qupulse/hardware/dacs/dummy.py +++ b/qupulse/hardware/dacs/dummy.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Tuple, Set, Dict from collections import deque diff --git a/qupulse/hardware/feature_awg/base.py b/qupulse/hardware/feature_awg/base.py index 0ea254b96..868e84b2b 100644 --- a/qupulse/hardware/feature_awg/base.py +++ b/qupulse/hardware/feature_awg/base.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from abc import ABC, abstractmethod from typing import Optional, Collection import weakref diff --git a/qupulse/hardware/feature_awg/base_features.py b/qupulse/hardware/feature_awg/base_features.py index 7461bf046..a95d140eb 100644 --- a/qupulse/hardware/feature_awg/base_features.py +++ b/qupulse/hardware/feature_awg/base_features.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from types import MappingProxyType from typing import Callable, Generic, Mapping, Optional, Type, TypeVar from abc import ABC diff --git a/qupulse/hardware/feature_awg/channel_tuple_wrapper.py b/qupulse/hardware/feature_awg/channel_tuple_wrapper.py index a840ce9c9..40ce75e9c 100644 --- a/qupulse/hardware/feature_awg/channel_tuple_wrapper.py +++ b/qupulse/hardware/feature_awg/channel_tuple_wrapper.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Tuple, Optional, Callable, Set from qupulse import ChannelID diff --git a/qupulse/hardware/feature_awg/features.py b/qupulse/hardware/feature_awg/features.py index 29439f70a..bdd070096 100644 --- a/qupulse/hardware/feature_awg/features.py +++ b/qupulse/hardware/feature_awg/features.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from abc import ABC, abstractmethod from typing import Callable, Optional, Set, Tuple, Dict, Union, Any, Mapping from numbers import Real diff --git a/qupulse/hardware/feature_awg/tabor.py b/qupulse/hardware/feature_awg/tabor.py index 554939719..4cbd0bf18 100644 --- a/qupulse/hardware/feature_awg/tabor.py +++ b/qupulse/hardware/feature_awg/tabor.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import functools import logging import numbers diff --git a/qupulse/hardware/setup.py b/qupulse/hardware/setup.py index d034e3b26..01e2e240b 100644 --- a/qupulse/hardware/setup.py +++ b/qupulse/hardware/setup.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import NamedTuple, Set, Callable, Dict, Tuple, Union, Iterable, Any, Mapping from collections import defaultdict import warnings diff --git a/qupulse/hardware/util.py b/qupulse/hardware/util.py index 2d656d529..5134b6043 100644 --- a/qupulse/hardware/util.py +++ b/qupulse/hardware/util.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Collection, Sequence, Tuple, Union, Optional import itertools diff --git a/qupulse/parameter_scope.py b/qupulse/parameter_scope.py index a59f94a0b..ca2959ddf 100644 --- a/qupulse/parameter_scope.py +++ b/qupulse/parameter_scope.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """Contains various implementations of the parameter lookup interface :class:`.Scope`""" from abc import abstractmethod diff --git a/qupulse/plotting.py b/qupulse/plotting.py index 600087ed9..5b7d42827 100644 --- a/qupulse/plotting.py +++ b/qupulse/plotting.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines plotting functionality for instantiated PulseTemplates using matplotlib. Classes: diff --git a/qupulse/program/__init__.py b/qupulse/program/__init__.py index 611a96fcd..644cf9bd2 100644 --- a/qupulse/program/__init__.py +++ b/qupulse/program/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import contextlib from abc import ABC, abstractmethod from dataclasses import dataclass diff --git a/qupulse/program/linspace.py b/qupulse/program/linspace.py index 4fe387856..81081ecde 100644 --- a/qupulse/program/linspace.py +++ b/qupulse/program/linspace.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import abc import contextlib import dataclasses diff --git a/qupulse/program/loop.py b/qupulse/program/loop.py index 0f0356531..5f127fbef 100644 --- a/qupulse/program/loop.py +++ b/qupulse/program/loop.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import reprlib import warnings from collections import defaultdict diff --git a/qupulse/program/transformation.py b/qupulse/program/transformation.py index 784e8e193..21a7eb382 100644 --- a/qupulse/program/transformation.py +++ b/qupulse/program/transformation.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Any, Mapping, Set, Tuple, Sequence, AbstractSet, Union, TYPE_CHECKING, Hashable from abc import abstractmethod from numbers import Real diff --git a/qupulse/program/volatile.py b/qupulse/program/volatile.py index afd4692ff..ab0925ae1 100644 --- a/qupulse/program/volatile.py +++ b/qupulse/program/volatile.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import NamedTuple, Mapping import warnings import numbers diff --git a/qupulse/program/waveforms.py b/qupulse/program/waveforms.py index 5080a92e8..dc777a231 100644 --- a/qupulse/program/waveforms.py +++ b/qupulse/program/waveforms.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module contains all waveform classes Classes: diff --git a/qupulse/pulses/__init__.py b/qupulse/pulses/__init__.py index 4a8e1016f..3ed818c57 100644 --- a/qupulse/pulses/__init__.py +++ b/qupulse/pulses/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This is the central package for defining pulses. All :class:`~qupulse.pulses.pulse_template.PulseTemplate` subclasses that are final and ready to be used are imported here with their recommended abbreviation as an alias. diff --git a/qupulse/pulses/abstract_pulse_template.py b/qupulse/pulses/abstract_pulse_template.py index 05e75307c..272534035 100644 --- a/qupulse/pulses/abstract_pulse_template.py +++ b/qupulse/pulses/abstract_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Set, Optional, Dict, Any, cast from functools import partial, partialmethod import warnings diff --git a/qupulse/pulses/arithmetic_pulse_template.py b/qupulse/pulses/arithmetic_pulse_template.py index eedfce20b..19b9b45d2 100644 --- a/qupulse/pulses/arithmetic_pulse_template.py +++ b/qupulse/pulses/arithmetic_pulse_template.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later from typing import Any, Dict, List, Set, Optional, Union, Mapping, FrozenSet, cast, Callable from numbers import Real diff --git a/qupulse/pulses/constant_pulse_template.py b/qupulse/pulses/constant_pulse_template.py index 192ee82b1..839548f2a 100644 --- a/qupulse/pulses/constant_pulse_template.py +++ b/qupulse/pulses/constant_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines the ConstantPulseTemplate, a pulse tempalte representating a pulse with constant values on all channels Classes: diff --git a/qupulse/pulses/function_pulse_template.py b/qupulse/pulses/function_pulse_template.py index 24d98fbe2..b943ef5a9 100644 --- a/qupulse/pulses/function_pulse_template.py +++ b/qupulse/pulses/function_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines the FunctionPulseTemplate, one of the elementary pulse templates and its waveform representation. diff --git a/qupulse/pulses/interpolation.py b/qupulse/pulses/interpolation.py index 40eac69e9..e5c81f8c1 100644 --- a/qupulse/pulses/interpolation.py +++ b/qupulse/pulses/interpolation.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines strategies for interpolation between points in a pulse table or similar. Classes: diff --git a/qupulse/pulses/loop_pulse_template.py b/qupulse/pulses/loop_pulse_template.py index 0f458c687..cd7aefaaa 100644 --- a/qupulse/pulses/loop_pulse_template.py +++ b/qupulse/pulses/loop_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines LoopPulseTemplate, a higher-order hierarchical pulse template that loops another PulseTemplate based on a condition.""" import dataclasses diff --git a/qupulse/pulses/mapping_pulse_template.py b/qupulse/pulses/mapping_pulse_template.py index 07e7d1024..af5119b66 100644 --- a/qupulse/pulses/mapping_pulse_template.py +++ b/qupulse/pulses/mapping_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Optional, Set, Dict, Union, List, Any, Tuple, Mapping import itertools import numbers diff --git a/qupulse/pulses/measurement.py b/qupulse/pulses/measurement.py index 2a12575f9..e44b7d0e9 100644 --- a/qupulse/pulses/measurement.py +++ b/qupulse/pulses/measurement.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Optional, List, Tuple, Union, Dict, Set, Mapping, AbstractSet from numbers import Real import itertools diff --git a/qupulse/pulses/multi_channel_pulse_template.py b/qupulse/pulses/multi_channel_pulse_template.py index 6b76bb49f..a7e11914d 100644 --- a/qupulse/pulses/multi_channel_pulse_template.py +++ b/qupulse/pulses/multi_channel_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines MultiChannelPulseTemplate, which allows the combination of several AtomicPulseTemplates into a single template spanning several channels. diff --git a/qupulse/pulses/parameters.py b/qupulse/pulses/parameters.py index da381b053..d78bf4632 100644 --- a/qupulse/pulses/parameters.py +++ b/qupulse/pulses/parameters.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines parameter constriants. """ diff --git a/qupulse/pulses/plotting.py b/qupulse/pulses/plotting.py index 8d98f3112..907629fe4 100644 --- a/qupulse/pulses/plotting.py +++ b/qupulse/pulses/plotting.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """Deprecated plotting location. Was moved to :py:`qupulse.plotting`. No deprecation warning because we will keep it around forever.""" diff --git a/qupulse/pulses/point_pulse_template.py b/qupulse/pulses/point_pulse_template.py index 0075a98dc..77ebada8f 100644 --- a/qupulse/pulses/point_pulse_template.py +++ b/qupulse/pulses/point_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Optional, List, Union, Set, Dict, Sequence, Any, Tuple from numbers import Real import itertools diff --git a/qupulse/pulses/pulse_template.py b/qupulse/pulses/pulse_template.py index 97dd5cda4..68d4adac9 100644 --- a/qupulse/pulses/pulse_template.py +++ b/qupulse/pulses/pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines the abstract PulseTemplate class which is the basis of any pulse model in the qupulse. diff --git a/qupulse/pulses/pulse_template_parameter_mapping.py b/qupulse/pulses/pulse_template_parameter_mapping.py index 5daf2695a..3043670a3 100644 --- a/qupulse/pulses/pulse_template_parameter_mapping.py +++ b/qupulse/pulses/pulse_template_parameter_mapping.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """..deprecated:: 0.1 """ diff --git a/qupulse/pulses/range.py b/qupulse/pulses/range.py index 34f7e8a8e..c39ad39e6 100644 --- a/qupulse/pulses/range.py +++ b/qupulse/pulses/range.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Tuple, Any, AbstractSet, Mapping, Union, Iterator from numbers import Number from dataclasses import dataclass diff --git a/qupulse/pulses/repetition_pulse_template.py b/qupulse/pulses/repetition_pulse_template.py index ead19c6d9..a88485ed0 100644 --- a/qupulse/pulses/repetition_pulse_template.py +++ b/qupulse/pulses/repetition_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines RepetitionPulseTemplate, a higher-order hierarchical pulse template that represents the n-times repetition of another PulseTemplate.""" diff --git a/qupulse/pulses/sequence_pulse_template.py b/qupulse/pulses/sequence_pulse_template.py index 5107bb104..19e80ed04 100644 --- a/qupulse/pulses/sequence_pulse_template.py +++ b/qupulse/pulses/sequence_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines SequencePulseTemplate, a higher-order hierarchical pulse template that combines several other PulseTemplate objects for sequential execution.""" diff --git a/qupulse/pulses/table_pulse_template.py b/qupulse/pulses/table_pulse_template.py index f8b631add..cb9287b01 100644 --- a/qupulse/pulses/table_pulse_template.py +++ b/qupulse/pulses/table_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module defines the TablePulseTemplate, one of the elementary pulse templates and its waveform representation. diff --git a/qupulse/pulses/time_reversal_pulse_template.py b/qupulse/pulses/time_reversal_pulse_template.py index 35a1884be..5dc9fcabd 100644 --- a/qupulse/pulses/time_reversal_pulse_template.py +++ b/qupulse/pulses/time_reversal_pulse_template.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Optional, Set, Dict, Union from qupulse import ChannelID diff --git a/qupulse/serialization.py b/qupulse/serialization.py index 389748666..3cadee40f 100644 --- a/qupulse/serialization.py +++ b/qupulse/serialization.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """ This module provides serialization and storage functionality. Classes: diff --git a/qupulse/utils/__init__.py b/qupulse/utils/__init__.py index 326072f4b..84a05d8be 100644 --- a/qupulse/utils/__init__.py +++ b/qupulse/utils/__init__.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This package contains utility functions and classes as well as custom sympy extensions(hacks).""" from typing import Union, Iterable, Any, Tuple, Mapping, Iterator, TypeVar, Sequence, AbstractSet, Optional, Callable diff --git a/qupulse/utils/numeric.py b/qupulse/utils/numeric.py index 5a263a39a..4fdeed43b 100644 --- a/qupulse/utils/numeric.py +++ b/qupulse/utils/numeric.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Tuple, Type from numbers import Rational from math import gcd diff --git a/qupulse/utils/performance.py b/qupulse/utils/performance.py index ebdb3b0a8..8d0c6141e 100644 --- a/qupulse/utils/performance.py +++ b/qupulse/utils/performance.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import warnings from typing import Tuple import numpy as np diff --git a/qupulse/utils/sympy.py b/qupulse/utils/sympy.py index 7a04d53f6..aa2056143 100644 --- a/qupulse/utils/sympy.py +++ b/qupulse/utils/sympy.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + from typing import Union, Dict, Tuple, Any, Sequence, Optional, Callable from numbers import Number from types import CodeType diff --git a/qupulse/utils/tree.py b/qupulse/utils/tree.py index 2585a5f57..f320f9534 100644 --- a/qupulse/utils/tree.py +++ b/qupulse/utils/tree.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + """This module contains a tree implementation.""" from typing import Iterable, Union, List, Generator, Tuple, TypeVar, Optional, Sequence diff --git a/qupulse/utils/types.py b/qupulse/utils/types.py index 7ec9d8c7c..ca51d1965 100644 --- a/qupulse/utils/types.py +++ b/qupulse/utils/types.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2014-2024 Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University +# +# SPDX-License-Identifier: GPL-3.0-or-later + import typing import abc import inspect diff --git a/setup.cfg b/setup.cfg index c053e526e..2c4b13050 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,8 +5,8 @@ description = A Quantum compUting PULse parametrization and SEquencing framework long_description = file: README.md long_description_content_type = text/markdown author = Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University -license = GPLv3+ -license_files = LICENSE +license = GPL-3.0-or-later +license_files = LICENSE/GPL-3.0-or-later.txt keywords = quantum, physics, control pulse, qubit classifiers = Programming Language :: Python :: 3 From 4ebd314eaf8e9a1da658e5c5349c574239969149 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 27 May 2024 15:38:23 +0200 Subject: [PATCH 03/53] Add section about licensing in README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d47d1e09f..4dfe22973 100644 --- a/README.md +++ b/README.md @@ -63,3 +63,6 @@ The repository primarily consists of the folders `qupulse` (toolkit core code) a Contents of `tests` mirror the structure of `qupulse`. For every `` somewhere in `qupulse` there should exist a `Tests.py` in the corresponding subdirectory of `tests`. +## License + +The current version of qupulse is available under the `GPL-3.0-or-later` license. Versions up to and including 0.10 were licensed under the MIT license. If you require different licensing terms, please contact us to discuss your needs. From ea88576ea5993d9dae3b9b410e6dd96f86cd0f1c Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 3 Jun 2024 14:14:34 +0200 Subject: [PATCH 04/53] Move pytest config to pyproject and use default path --- pyproject.toml | 18 ++++++++++++++++++ setup.cfg | 11 ----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 994c5e81e..cd673d74b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,3 +8,21 @@ package_dir = "./qupulse" filename = "RELEASE_NOTES.rst" name = "qupulse" issue_format = "`#{issue} `_" + +[tool.pytest.ini_options] +minversion = "6.0" +python_files = [ + "*_tests.py", + "*_bug.py" +] +filterwarnings = [ + # syntax is action:message_regex:category:module_regex:lineno + # we fail on all with a whitelist because a dependency might mess-up passing the correct stacklevel + "error::SyntaxWarning", + "error::DeprecationWarning", + # pytest uses readline which uses collections.abc + # "ignore:Using or importing the ABCs from 'collections' instead of from 'collections\.abc\' is deprecated:DeprecationWarning:.*readline.*" +] + + + diff --git a/setup.cfg b/setup.cfg index a77b1e909..fceb89d5a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -70,17 +70,6 @@ qupulse = qctoolkit = *.pyi -[tool:pytest] -testpaths = tests tests/pulses tests/hardware tests/backward_compatibility -python_files=*_tests.py *_bug.py -filterwarnings = -# syntax is action:message_regex:category:module_regex:lineno -# we fail on all with a whitelist because a dependency might mess-up passing the correct stacklevel - error::SyntaxWarning - error::DeprecationWarning -# pytest uses readline which uses collections.abc - ignore:Using or importing the ABCs from \'collections\' instead of from \'collections\.abc\' is deprecated:DeprecationWarning:.*readline.* - [build_sphinx] project = 'qupulse' version = 0.9 From 2342c57736bec846cf3c7f55184b8ecc0af8b077 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 13:49:00 +0200 Subject: [PATCH 05/53] Only trigger import hacking on manual request --- tests/utils/time_type_tests.py | 381 +++++++++++++++++---------------- 1 file changed, 193 insertions(+), 188 deletions(-) diff --git a/tests/utils/time_type_tests.py b/tests/utils/time_type_tests.py index 93e118325..cdb9ccffd 100644 --- a/tests/utils/time_type_tests.py +++ b/tests/utils/time_type_tests.py @@ -5,6 +5,8 @@ import importlib import fractions import random +import os + from unittest import mock try: @@ -18,6 +20,9 @@ import qupulse.utils.types as qutypes +MOCK_GMPY2_AS_MISSING = bool(os.getenv("QUPULSE_TESTS_MOCK_GMPY2_AS_MISSING")) + + @contextlib.contextmanager def mock_missing_module(module_name: str): exit_stack = contextlib.ExitStack() @@ -43,21 +48,191 @@ def mock_import(name, *args, **kwargs): yield -class TestTimeType(unittest.TestCase): - """The fallback test is here for convenience while developing. The fallback is also tested by the CI explicitly""" +@unittest.skipIf(gmpy2 and not MOCK_GMPY2_AS_MISSING, "Not explicitly included. " + "Define QUPULSE_TESTS_MOCK_GMPY2_AS_MISSING to include.") +class TestTimeTypeDevFallback(unittest.TestCase): + @classmethod + def setUpClass(cls): + with mock_missing_module('gmpy2'): + cls.fallback_qutypes = importlib.reload(qutypes) + + def test_fraction_fallback(self): + self.assertIs(fractions.Fraction, self.fallback_qutypes.TimeType._InternalType) - _fallback_qutypes = None + def test_fraction_time_from_fraction_fallback(self): + assert_from_fraction_works(self, self.fallback_qutypes.TimeType) - @property - def fallback_qutypes(self): - if not self._fallback_qutypes: - if gmpy2: - with mock_missing_module('gmpy2'): - self._fallback_qutypes = importlib.reload(qutypes) + def test_fraction_time_from_float_exact_fallback(self): + assert_from_float_exact_works(self, self.fallback_qutypes.TimeType) - else: - self._fallback_qutypes = qutypes - return self._fallback_qutypes + def test_fraction_time_from_float_with_precision_fallback(self): + assert_fraction_time_from_float_with_precision_works(self, self.fallback_qutypes.TimeType) + + def test_from_float_no_extra_args_fallback(self): + assert_from_float_no_extra_args_works(self, self.fallback_qutypes.TimeType) + + def test_try_from_any_fallback(self): + assert_try_from_any_works(self, self.fallback_qutypes.TimeType) + + def test_comparisons_work_fallback(self): + assert_comparisons_work(self, self.fallback_qutypes.TimeType) + + +def assert_from_fraction_works(test: unittest.TestCase, time_type): + t = time_type.from_fraction(43, 12) + test.assertIsInstance(t, time_type) + test.assertEqual(t, fractions.Fraction(43, 12)) + + +def assert_from_float_exact_works(test: unittest.TestCase, time_type): + test.assertEqual(time_type.from_float(123 / 931, 0), + fractions.Fraction(123 / 931)) + + +def assert_fraction_time_from_float_with_precision_works(test: unittest.TestCase, time_type): + test.assertEqual(time_type.from_float(1000000 / 1000001, 1e-5), + fractions.Fraction(1)) + test.assertEqual(time_type.from_float(2.50000000000008, absolute_error=1e-10), + time_type.from_fraction(5, 2)) + test.assertEqual(time_type.from_float(9926.666666667, absolute_error=1e-9), + time_type.from_fraction(29780, 3)) + + +def assert_from_float_no_extra_args_works(test: unittest.TestCase, time_type): + # test that float(from_float(x)) == x + base_floats = [4/5, 1, 1000, 0, np.pi, 1.23456789**99, 1e-100, 2**53] + n_steps = 10**2 + + def float_generator(): + for f in base_floats: + for _ in range(n_steps): + yield f + f = np.nextafter(f, float('inf')) + + for f in base_floats: + for _ in range(n_steps): + yield f + f = np.nextafter(f, float('-inf')) + + for x in float_generator(): + t = time_type.from_float(x) + t2x = float(t) + test.assertEqual(x, t2x) + test.assertGreater(t, np.nextafter(x, float('-inf'))) + test.assertLess(t, np.nextafter(x, float('inf'))) + + +def assert_try_from_any_works(test: unittest.TestCase, time_type): + try_from_any = time_type._try_from_any + + # these duck types are here because isinstance(, numbers.) is version dependent + class DuckTypeWrapper: + def __init__(self, value): + self.value = value + + def __repr__(self): + return f'{type(self)}({self.value})' + + class DuckInt(DuckTypeWrapper): + def __int__(self): + return int(self.value) + + class DuckFloat(DuckTypeWrapper): + def __float__(self): + return float(self.value) + + class DuckIntFloat(DuckFloat): + def __int__(self): + return int(self.value) + + class DuckRational: + def __init__(self, numerator, denominator): + self.numerator = numerator + self.denominator = denominator + + def __repr__(self): + return f'{type(self)}({self.numerator}, {self.denominator})' + + for_array_tests = [] + + signed_int_types = [int, sympy.Integer, np.int8, np.int16, np.int32, np.int64, DuckInt, DuckIntFloat] + if gmpy2: + signed_int_types.append(gmpy2.mpz) + + for s_t in signed_int_types: + for val in (1, 17, -17): + any_val = s_t(val) + expected_val = time_type.from_fraction(int(val), 1) + test.assertEqual(expected_val, try_from_any(any_val)) + for_array_tests.append((expected_val, any_val)) + + unsigned_int_types = [np.uint8, np.uint16, np.uint32, np.uint] + for u_t in unsigned_int_types: + for val in (1, 17): + any_val = u_t(val) + expected_val = time_type.from_fraction(int(val), 1) + test.assertEqual(expected_val, try_from_any(any_val)) + for_array_tests.append((expected_val, any_val)) + + rational_types = [fractions.Fraction, sympy.Rational, time_type.from_fraction, DuckRational] + if gmpy2: + rational_types.append(gmpy2.mpq) + for r_t in rational_types: + for num, den in ((1, 3), (-3, 8), (17, 5)): + any_val = r_t(num, den) + expected_val = time_type.from_fraction(num, den) + test.assertEqual(expected_val, try_from_any(any_val)) + for_array_tests.append((expected_val, any_val)) + + float_types = [float, sympy.Float, DuckFloat, DuckIntFloat] + if gmpy2: + float_types.append(gmpy2.mpfr) + for f_t in float_types: + for val in (3.4, -3., 1.): + any_val = f_t(val) + expected_val = time_type.from_float(val) + test.assertEqual(expected_val, try_from_any(any_val)) + for_array_tests.append((expected_val, any_val)) + + arr = np.array(for_array_tests, dtype='O') + any_arr = arr[:, 1] + expected_arr = arr[:, 0] + np.testing.assert_equal(expected_arr, try_from_any(any_arr)) + + +def assert_comparisons_work(test: unittest.TestCase, time_type): + tt = time_type.from_float(1.1) + + test.assertLess(tt, 4) + test.assertLess(tt, 4.) + test.assertLess(tt, time_type.from_float(4.)) + test.assertLess(tt, float('inf')) + + test.assertLessEqual(tt, 4) + test.assertLessEqual(tt, 4.) + test.assertLessEqual(tt, time_type.from_float(4.)) + test.assertLessEqual(tt, float('inf')) + + test.assertGreater(tt, 1) + test.assertGreater(tt, 1.) + test.assertGreater(tt, time_type.from_float(1.)) + test.assertGreater(tt, float('-inf')) + + test.assertGreaterEqual(tt, 1) + test.assertGreaterEqual(tt, 1.) + test.assertGreaterEqual(tt, time_type.from_float(1.)) + test.assertGreaterEqual(tt, float('-inf')) + + test.assertFalse(tt == float('nan')) + test.assertFalse(tt <= float('nan')) + test.assertFalse(tt >= float('nan')) + test.assertFalse(tt < float('nan')) + test.assertFalse(tt > float('nan')) + + +class TestTimeType(unittest.TestCase): + """The fallback test is here for convenience while developing and only triggered if the environment variable is set. + The fallback is also tested by the CI explicitly""" def test_non_finite_float(self): with self.assertRaisesRegex(ValueError, 'Cannot represent'): @@ -67,76 +242,17 @@ def test_non_finite_float(self): with self.assertRaisesRegex(ValueError, 'Cannot represent'): qutypes.TimeType.from_float(float('nan')) - def test_fraction_fallback(self): - self.assertIs(fractions.Fraction, self.fallback_qutypes.TimeType._InternalType) - - def assert_from_fraction_works(self, time_type): - t = time_type.from_fraction(43, 12) - self.assertIsInstance(t, time_type) - self.assertEqual(t, fractions.Fraction(43, 12)) - def test_fraction_time_from_fraction(self): - self.assert_from_fraction_works(qutypes.TimeType) - - @unittest.skipIf(gmpy2 is None, "fallback already tested") - def test_fraction_time_from_fraction_fallback(self): - self.assert_from_fraction_works(self.fallback_qutypes.TimeType) - - def assert_from_float_exact_works(self, time_type): - self.assertEqual(time_type.from_float(123 / 931, 0), - fractions.Fraction(123 / 931)) + assert_from_fraction_works(self, qutypes.TimeType) def test_fraction_time_from_float_exact(self): - self.assert_from_float_exact_works(qutypes.TimeType) - - @unittest.skipIf(gmpy2 is None, "fallback already tested") - def test_fraction_time_from_float_exact_fallback(self): - self.assert_from_float_exact_works(self.fallback_qutypes.TimeType) - - def assert_fraction_time_from_float_with_precision_works(self, time_type): - self.assertEqual(time_type.from_float(1000000 / 1000001, 1e-5), - fractions.Fraction(1)) - self.assertEqual(time_type.from_float(2.50000000000008, absolute_error=1e-10), - time_type.from_fraction(5, 2)) - self.assertEqual(time_type.from_float(9926.666666667, absolute_error=1e-9), - time_type.from_fraction(29780, 3)) + assert_from_float_exact_works(self, qutypes.TimeType) def test_fraction_time_from_float_with_precision(self): - self.assert_fraction_time_from_float_with_precision_works(qutypes.TimeType) - - @unittest.skipIf(gmpy2 is None, "fallback already tested") - def test_fraction_time_from_float_with_precision_fallback(self): - self.assert_fraction_time_from_float_with_precision_works(self.fallback_qutypes.TimeType) - - def assert_from_float_no_extra_args_works(self, time_type): - # test that float(from_float(x)) == x - base_floats = [4/5, 1, 1000, 0, np.pi, 1.23456789**99, 1e-100, 2**53] - n_steps = 10**2 - - def float_generator(): - for f in base_floats: - for _ in range(n_steps): - yield f - f = np.nextafter(f, float('inf')) - - for f in base_floats: - for _ in range(n_steps): - yield f - f = np.nextafter(f, float('-inf')) - - for x in float_generator(): - t = time_type.from_float(x) - t2x = float(t) - self.assertEqual(x, t2x) - self.assertGreater(t, np.nextafter(x, float('-inf'))) - self.assertLess(t, np.nextafter(x, float('inf'))) + assert_fraction_time_from_float_with_precision_works(self, qutypes.TimeType) def test_from_float_no_extra_args(self): - self.assert_from_float_exact_works(qutypes.TimeType) - - @unittest.skipIf(gmpy2 is None, "fallback already tested") - def test_from_float_no_extra_args_fallback(self): - self.assert_from_float_exact_works(self.fallback_qutypes.TimeType) + assert_from_float_exact_works(self, qutypes.TimeType) def test_from_float_exceptions(self): with self.assertRaisesRegex(ValueError, '> 0'): @@ -145,122 +261,11 @@ def test_from_float_exceptions(self): with self.assertRaisesRegex(ValueError, '<= 1'): qutypes.time_from_float(.8, 2) - def assert_try_from_any_works(self, time_type): - try_from_any = time_type._try_from_any - - # these duck types are here because isinstance(, numbers.) is version dependent - class DuckTypeWrapper: - def __init__(self, value): - self.value = value - - def __repr__(self): - return f'{type(self)}({self.value})' - - class DuckInt(DuckTypeWrapper): - def __int__(self): - return int(self.value) - - class DuckFloat(DuckTypeWrapper): - def __float__(self): - return float(self.value) - - class DuckIntFloat(DuckFloat): - def __int__(self): - return int(self.value) - - class DuckRational: - def __init__(self, numerator, denominator): - self.numerator = numerator - self.denominator = denominator - - def __repr__(self): - return f'{type(self)}({self.numerator}, {self.denominator})' - - for_array_tests = [] - - signed_int_types = [int, sympy.Integer, np.int8, np.int16, np.int32, np.int64, DuckInt, DuckIntFloat] - if gmpy2: - signed_int_types.append(gmpy2.mpz) - - for s_t in signed_int_types: - for val in (1, 17, -17): - any_val = s_t(val) - expected_val = time_type.from_fraction(int(val), 1) - self.assertEqual(expected_val, try_from_any(any_val)) - for_array_tests.append((expected_val, any_val)) - - unsigned_int_types = [np.uint8, np.uint16, np.uint32, np.uint] - for u_t in unsigned_int_types: - for val in (1, 17): - any_val = u_t(val) - expected_val = time_type.from_fraction(int(val), 1) - self.assertEqual(expected_val, try_from_any(any_val)) - for_array_tests.append((expected_val, any_val)) - - rational_types = [fractions.Fraction, sympy.Rational, time_type.from_fraction, DuckRational] - if gmpy2: - rational_types.append(gmpy2.mpq) - for r_t in rational_types: - for num, den in ((1, 3), (-3, 8), (17, 5)): - any_val = r_t(num, den) - expected_val = time_type.from_fraction(num, den) - self.assertEqual(expected_val, try_from_any(any_val)) - for_array_tests.append((expected_val, any_val)) - - float_types = [float, sympy.Float, DuckFloat, DuckIntFloat] - if gmpy2: - float_types.append(gmpy2.mpfr) - for f_t in float_types: - for val in (3.4, -3., 1.): - any_val = f_t(val) - expected_val = time_type.from_float(val) - self.assertEqual(expected_val, try_from_any(any_val)) - for_array_tests.append((expected_val, any_val)) - - arr = np.array(for_array_tests, dtype='O') - any_arr = arr[:, 1] - expected_arr = arr[:, 0] - np.testing.assert_equal(expected_arr, try_from_any(any_arr)) - def test_try_from_any(self): - self.assert_try_from_any_works(qutypes.TimeType) - self.assert_try_from_any_works(self.fallback_qutypes.TimeType) - - def assert_comparisons_work(self, time_type): - tt = time_type.from_float(1.1) - - self.assertLess(tt, 4) - self.assertLess(tt, 4.) - self.assertLess(tt, time_type.from_float(4.)) - self.assertLess(tt, float('inf')) - - self.assertLessEqual(tt, 4) - self.assertLessEqual(tt, 4.) - self.assertLessEqual(tt, time_type.from_float(4.)) - self.assertLessEqual(tt, float('inf')) - - self.assertGreater(tt, 1) - self.assertGreater(tt, 1.) - self.assertGreater(tt, time_type.from_float(1.)) - self.assertGreater(tt, float('-inf')) - - self.assertGreaterEqual(tt, 1) - self.assertGreaterEqual(tt, 1.) - self.assertGreaterEqual(tt, time_type.from_float(1.)) - self.assertGreaterEqual(tt, float('-inf')) - - self.assertFalse(tt == float('nan')) - self.assertFalse(tt <= float('nan')) - self.assertFalse(tt >= float('nan')) - self.assertFalse(tt < float('nan')) - self.assertFalse(tt > float('nan')) + assert_try_from_any_works(self, qutypes.TimeType) def test_comparisons_work(self): - self.assert_comparisons_work(qutypes.TimeType) - - @unittest.skipIf(gmpy2 is None, "fallback already tested") - def test_comparisons_work_fallback(self): - self.assert_comparisons_work(self.fallback_qutypes.TimeType) + assert_comparisons_work(self, qutypes.TimeType) def get_some_floats(seed=42, n=1000): From 4f4721dd5ee9131ef3b72f4868c6a2cb35d4dff3 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 3 Jun 2024 13:57:13 +0200 Subject: [PATCH 06/53] Make Waveform comparison __slots__based --- qupulse/program/waveforms.py | 56 +++++++----------------------------- 1 file changed, 11 insertions(+), 45 deletions(-) diff --git a/qupulse/program/waveforms.py b/qupulse/program/waveforms.py index 94c395532..8765ee5d4 100644 --- a/qupulse/program/waveforms.py +++ b/qupulse/program/waveforms.py @@ -52,7 +52,7 @@ def _to_time_type(duration: Real) -> TimeType: return time_from_float(float(duration), absolute_error=PULSE_TO_WAVEFORM_ERROR) -class Waveform(Comparable, metaclass=ABCMeta): +class Waveform(metaclass=ABCMeta): """Represents an instantiated PulseTemplate which can be sampled to retrieve arrays of voltage values for the hardware.""" @@ -143,6 +143,16 @@ def get_sampled(self, output_array[:] = constant_value return output_array + def __hash__(self): + return hash(tuple(getattr(self, slot) for slot in self.__slots__)) + + def __eq__(self, other): + slots = self.__slots__ + if slots is getattr(other, '__slots__', None): + return all(getattr(self, slot) == getattr(other, slot) for slot in slots) + # The other class might be more lenient + return NotImplemented + @property @abstractmethod def defined_channels(self) -> AbstractSet[ChannelID]: @@ -350,10 +360,6 @@ def from_table(cls, channel: ChannelID, table: Sequence[EntryInInit]) -> Union[' else: return TableWaveform(channel, tuple(table)) - @property - def compare_key(self) -> Any: - return self._channel_id, self._table - def unsafe_sample(self, channel: ChannelID, sample_times: np.ndarray, @@ -434,10 +440,6 @@ def defined_channels(self) -> AbstractSet[ChannelID]: return {self._channel} - @property - def compare_key(self) -> Tuple[Any, ...]: - return self._duration, self._amplitude, self._channel - def unsafe_sample(self, channel: ChannelID, sample_times: np.ndarray, @@ -506,10 +508,6 @@ def constant_value_dict(self) -> Optional[Mapping[ChannelID, float]]: def defined_channels(self) -> AbstractSet[ChannelID]: return {self._channel_id} - @property - def compare_key(self) -> Any: - return self._channel_id, self._expression, self._duration - @property def duration(self) -> TimeType: return self._duration @@ -636,10 +634,6 @@ def unsafe_sample(self, time = end return output_array - @property - def compare_key(self) -> Tuple[Waveform]: - return self._sequenced_waveforms - @property def duration(self) -> TimeType: return self._duration @@ -784,11 +778,6 @@ def __getitem__(self, key: ChannelID) -> Waveform: def defined_channels(self) -> AbstractSet[ChannelID]: return self._defined_channels - @property - def compare_key(self) -> Any: - # sort with channels - return self._sub_waveforms - def unsafe_sample(self, channel: ChannelID, sample_times: np.ndarray, @@ -853,10 +842,6 @@ def unsafe_sample(self, time = end return output_array - @property - def compare_key(self) -> Tuple[Any, int]: - return self._body.compare_key, self._repetition_count - def unsafe_get_subset_for_channels(self, channels: AbstractSet[ChannelID]) -> Waveform: return RepetitionWaveform.from_repetition_count( body=self._body.unsafe_get_subset_for_channels(channels), @@ -928,10 +913,6 @@ def transformation(self) -> Transformation: def defined_channels(self) -> AbstractSet[ChannelID]: return self.transformation.get_output_channels(self.inner_waveform.defined_channels) - @property - def compare_key(self) -> Tuple[Waveform, Transformation]: - return self.inner_waveform, self.transformation - def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> 'SubsetWaveform': return SubsetWaveform(self, channel_subset=channels) @@ -977,10 +958,6 @@ def inner_waveform(self) -> Waveform: def defined_channels(self) -> FrozenSet[ChannelID]: return self._channel_subset - @property - def compare_key(self) -> Tuple[frozenset, Waveform]: - return self.defined_channels, self.inner_waveform - def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> Waveform: return self.inner_waveform.get_subset_for_channels(channels) @@ -1128,10 +1105,6 @@ def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> Waveform: # TODO: optimization possible return SubsetWaveform(self, channels) - @property - def compare_key(self) -> Tuple[str, Waveform, Waveform]: - return self._arithmetic_operator, self._lhs, self._rhs - class FunctorWaveform(Waveform): # TODO: Use Protocol to enforce that it accepts second argument has the keyword out @@ -1188,9 +1161,6 @@ def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> Waveform: self._inner_waveform.unsafe_get_subset_for_channels(channels), {ch: self._functor[ch] for ch in channels}) - @property - def compare_key(self) -> Tuple[Waveform, FrozenSet]: - return self._inner_waveform, frozenset(self._functor.items()) class ReversedWaveform(Waveform): @@ -1229,9 +1199,5 @@ def defined_channels(self) -> AbstractSet[ChannelID]: def unsafe_get_subset_for_channels(self, channels: AbstractSet[ChannelID]) -> 'Waveform': return ReversedWaveform.from_to_reverse(self._inner.unsafe_get_subset_for_channels(channels)) - @property - def compare_key(self) -> Hashable: - return self._inner.compare_key - def reversed(self) -> 'Waveform': return self._inner From 839e1143f1b1a71c291ca08ac15bb4ed08c11e3b Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 14:19:35 +0200 Subject: [PATCH 07/53] Re-introduce compare_key with deprecation warning --- qupulse/program/waveforms.py | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/qupulse/program/waveforms.py b/qupulse/program/waveforms.py index 8765ee5d4..437cbfe70 100644 --- a/qupulse/program/waveforms.py +++ b/qupulse/program/waveforms.py @@ -360,6 +360,12 @@ def from_table(cls, channel: ChannelID, table: Sequence[EntryInInit]) -> Union[' else: return TableWaveform(channel, tuple(table)) + @property + def compare_key(self) -> Any: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._channel_id, self._table + def unsafe_sample(self, channel: ChannelID, sample_times: np.ndarray, @@ -440,6 +446,12 @@ def defined_channels(self) -> AbstractSet[ChannelID]: return {self._channel} + @property + def compare_key(self) -> Tuple[Any, ...]: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._duration, self._amplitude, self._channel + def unsafe_sample(self, channel: ChannelID, sample_times: np.ndarray, @@ -508,6 +520,12 @@ def constant_value_dict(self) -> Optional[Mapping[ChannelID, float]]: def defined_channels(self) -> AbstractSet[ChannelID]: return {self._channel_id} + @property + def compare_key(self) -> Any: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._channel_id, self._expression, self._duration + @property def duration(self) -> TimeType: return self._duration @@ -634,6 +652,12 @@ def unsafe_sample(self, time = end return output_array + @property + def compare_key(self) -> Tuple[Waveform]: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._sequenced_waveforms + @property def duration(self) -> TimeType: return self._duration @@ -778,6 +802,12 @@ def __getitem__(self, key: ChannelID) -> Waveform: def defined_channels(self) -> AbstractSet[ChannelID]: return self._defined_channels + @property + def compare_key(self) -> Any: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._sub_waveforms + def unsafe_sample(self, channel: ChannelID, sample_times: np.ndarray, @@ -842,6 +872,12 @@ def unsafe_sample(self, time = end return output_array + @property + def compare_key(self) -> Tuple[Any, int]: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._body.compare_key, self._repetition_count + def unsafe_get_subset_for_channels(self, channels: AbstractSet[ChannelID]) -> Waveform: return RepetitionWaveform.from_repetition_count( body=self._body.unsafe_get_subset_for_channels(channels), @@ -913,6 +949,12 @@ def transformation(self) -> Transformation: def defined_channels(self) -> AbstractSet[ChannelID]: return self.transformation.get_output_channels(self.inner_waveform.defined_channels) + @property + def compare_key(self) -> Tuple[Waveform, Transformation]: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self.inner_waveform, self.transformation + def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> 'SubsetWaveform': return SubsetWaveform(self, channel_subset=channels) @@ -958,6 +1000,12 @@ def inner_waveform(self) -> Waveform: def defined_channels(self) -> FrozenSet[ChannelID]: return self._channel_subset + @property + def compare_key(self) -> Tuple[frozenset, Waveform]: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self.defined_channels, self.inner_waveform + def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> Waveform: return self.inner_waveform.get_subset_for_channels(channels) @@ -1105,6 +1153,12 @@ def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> Waveform: # TODO: optimization possible return SubsetWaveform(self, channels) + @property + def compare_key(self) -> Tuple[str, Waveform, Waveform]: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._arithmetic_operator, self._lhs, self._rhs + class FunctorWaveform(Waveform): # TODO: Use Protocol to enforce that it accepts second argument has the keyword out @@ -1161,6 +1215,11 @@ def unsafe_get_subset_for_channels(self, channels: Set[ChannelID]) -> Waveform: self._inner_waveform.unsafe_get_subset_for_channels(channels), {ch: self._functor[ch] for ch in channels}) + @property + def compare_key(self) -> Tuple[Waveform, FrozenSet]: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._inner_waveform, frozenset(self._functor.items()) class ReversedWaveform(Waveform): @@ -1199,5 +1258,11 @@ def defined_channels(self) -> AbstractSet[ChannelID]: def unsafe_get_subset_for_channels(self, channels: AbstractSet[ChannelID]) -> 'Waveform': return ReversedWaveform.from_to_reverse(self._inner.unsafe_get_subset_for_channels(channels)) + @property + def compare_key(self) -> Hashable: + warnings.warn("Waveform.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + return self._inner.compare_key + def reversed(self) -> 'Waveform': return self._inner From 3d1ebbb3ed62653d3933f33ce80784d2aa72b1d6 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 14:49:00 +0200 Subject: [PATCH 08/53] Include duration in Waveform comparison --- qupulse/program/waveforms.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/qupulse/program/waveforms.py b/qupulse/program/waveforms.py index 437cbfe70..a492169a3 100644 --- a/qupulse/program/waveforms.py +++ b/qupulse/program/waveforms.py @@ -144,12 +144,14 @@ def get_sampled(self, return output_array def __hash__(self): - return hash(tuple(getattr(self, slot) for slot in self.__slots__)) + if self.__class__.__base__ is not Waveform: + raise NotImplementedError("Waveforms __hash__ and __eq__ implementation requires direct inheritance") + return hash(tuple(getattr(self, slot) for slot in self.__slots__)) ^ hash(self._duration) def __eq__(self, other): slots = self.__slots__ if slots is getattr(other, '__slots__', None): - return all(getattr(self, slot) == getattr(other, slot) for slot in slots) + return self._duration == other._duration and all(getattr(self, slot) == getattr(other, slot) for slot in slots) # The other class might be more lenient return NotImplemented From 3a1042da7d5b51b26ed6452551c586cf38fb8c88 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 14:49:34 +0200 Subject: [PATCH 09/53] Exclude cached attributes from TransformingWaveform comparison --- qupulse/program/waveforms.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/qupulse/program/waveforms.py b/qupulse/program/waveforms.py index a492169a3..ac077bb1f 100644 --- a/qupulse/program/waveforms.py +++ b/qupulse/program/waveforms.py @@ -911,6 +911,14 @@ def __init__(self, inner_waveform: Waveform, transformation: Transformation): self._cached_data = None self._cached_times = lambda: None + def __hash__(self): + return hash((self._inner_waveform, self._transformation)) + + def __eq__(self, other): + if getattr(other, '__slots__', None) is self.__slots__: + return self._inner_waveform == other._inner_waveform and self._transformation == other._transformation + return NotImplemented + @classmethod def from_transformation(cls, inner_waveform: Waveform, transformation: Transformation) -> Waveform: constant_values = inner_waveform.constant_value_dict() From 2c686e695adf77f8ee2af0cf5684c8a043bb4bea Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 14:50:29 +0200 Subject: [PATCH 10/53] Update tests to reflect compare_key deprecation --- tests/_program/waveforms_tests.py | 55 +++++++++++++++++++----------- tests/pulses/sequencing_dummies.py | 7 +++- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/tests/_program/waveforms_tests.py b/tests/_program/waveforms_tests.py index c62fceb3a..ece22dce1 100644 --- a/tests/_program/waveforms_tests.py +++ b/tests/_program/waveforms_tests.py @@ -207,7 +207,10 @@ def test_init_several_channels(self) -> None: dwf_c_valid = DummyWaveform(duration=2.2, defined_channels={'C'}) waveform_flat = MultiChannelWaveform.from_parallel((waveform, dwf_c_valid)) - self.assertEqual(len(waveform_flat.compare_key), 3) + self.assertEqual( + MultiChannelWaveform([dwf_a, dwf_b, dwf_c_valid]), + waveform_flat + ) def test_unsafe_sample(self) -> None: sample_times = numpy.linspace(98.5, 103.5, num=11) @@ -330,10 +333,17 @@ def test_defined_channels(self): body_wf = DummyWaveform(defined_channels={'a'}) self.assertIs(RepetitionWaveform(body_wf, 2).defined_channels, body_wf.defined_channels) - def test_compare_key(self): - body_wf = DummyWaveform(defined_channels={'a'}) - wf = RepetitionWaveform(body_wf, 2) - self.assertEqual(wf.compare_key, (body_wf.compare_key, 2)) + def test_equality(self): + body_wf_1 = DummyWaveform(defined_channels={'a'}) + wf_1 = RepetitionWaveform(body_wf_1, 2) + body_wf_2 = DummyWaveform(defined_channels={'a'}) + wf_2 = RepetitionWaveform(body_wf_2, 2) + wf_3 = RepetitionWaveform(body_wf_1, 3) + wf_1_equal = RepetitionWaveform(body_wf_1, 2) + self.assertEqual(wf_1_equal, wf_1) + self.assertNotEqual(wf_1, wf_2) + self.assertNotEqual(wf_1, wf_3) + self.assertEqual({wf_1, wf_2, wf_3}, {wf_1, wf_2, wf_3, wf_1_equal}) def test_unsafe_get_subset_for_channels(self): body_wf = DummyWaveform(defined_channels={'a', 'b'}) @@ -395,12 +405,11 @@ def test_init(self): swf1 = SequenceWaveform((dwf_ab, dwf_ab)) self.assertEqual(swf1.duration, 2*dwf_ab.duration) - self.assertEqual(len(swf1.compare_key), 2) + self.assertEqual(swf1.sequenced_waveforms, (dwf_ab, dwf_ab)) swf2 = SequenceWaveform((swf1, dwf_ab)) self.assertEqual(swf2.duration, 3 * dwf_ab.duration) - - self.assertEqual(len(swf2.compare_key), 2) + self.assertEqual(swf2.sequenced_waveforms, (swf1, dwf_ab)) def test_from_sequence(self): dwf = DummyWaveform(duration=1.1, defined_channels={'A'}) @@ -478,12 +487,12 @@ def test_unsafe_get_subset_for_channels(self): sub_wf = wf.unsafe_get_subset_for_channels(subset) self.assertIsInstance(sub_wf, SequenceWaveform) - self.assertEqual(len(sub_wf.compare_key), 2) - self.assertEqual(sub_wf.compare_key[0].defined_channels, subset) - self.assertEqual(sub_wf.compare_key[1].defined_channels, subset) + self.assertEqual(len(sub_wf.sequenced_waveforms), 2) + self.assertEqual(sub_wf.sequenced_waveforms[0].defined_channels, subset) + self.assertEqual(sub_wf.sequenced_waveforms[1].defined_channels, subset) - self.assertEqual(sub_wf.compare_key[0].duration, TimeType.from_float(2.2)) - self.assertEqual(sub_wf.compare_key[1].duration, TimeType.from_float(3.3)) + self.assertEqual(sub_wf.sequenced_waveforms[0].duration, TimeType.from_float(2.2)) + self.assertEqual(sub_wf.sequenced_waveforms[1].duration, TimeType.from_float(3.3)) def test_repr(self): cwf_2_a = ConstantWaveform(duration=1.1, amplitude=2.2, channel='A') @@ -714,7 +723,8 @@ def test_simple_properties(self): self.assertIs(trafo_wf.inner_waveform, inner_wf) self.assertIs(trafo_wf.transformation, trafo) - self.assertEqual(trafo_wf.compare_key, (inner_wf, trafo)) + with self.assertWarns(DeprecationWarning): + self.assertEqual(trafo_wf.compare_key, (inner_wf, trafo)) self.assertIs(trafo_wf.duration, inner_wf.duration) self.assertIs(trafo_wf.defined_channels, output_channels) trafo.get_output_channels.assert_called_once_with(inner_wf.defined_channels) @@ -804,7 +814,8 @@ def test_simple_properties(self): subset_wf = SubsetWaveform(inner_wf, {'a', 'c'}) self.assertIs(subset_wf.inner_waveform, inner_wf) - self.assertEqual(subset_wf.compare_key, (frozenset(['a', 'c']), inner_wf)) + with self.assertWarns(DeprecationWarning): + self.assertEqual(subset_wf.compare_key, (frozenset(['a', 'c']), inner_wf)) self.assertIs(subset_wf.duration, inner_wf.duration) self.assertEqual(subset_wf.defined_channels, {'a', 'c'}) @@ -891,8 +902,8 @@ def test_simple_properties(self): self.assertIs(rhs, arith.rhs) self.assertEqual('-', arith.arithmetic_operator) self.assertEqual(lhs.duration, arith.duration) - - self.assertEqual(('-', lhs, rhs), arith.compare_key) + with self.assertWarns(DeprecationWarning): + self.assertEqual(('-', lhs, rhs), arith.compare_key) def test_unsafe_get_subset_for_channels(self): lhs = DummyWaveform(duration=1.5, defined_channels={'a', 'b', 'c'}) @@ -944,10 +955,12 @@ def test_equality(self) -> None: wf1b = FunctionWaveform(ExpressionScalar('2*t'), 3, channel='A') wf3 = FunctionWaveform(ExpressionScalar('2*t+2'), 3, channel='A') wf4 = FunctionWaveform(ExpressionScalar('2*t'), 4, channel='A') + wf5 = FunctionWaveform(ExpressionScalar('2*t'), 3, channel='B') self.assertEqual(wf1a, wf1a) self.assertEqual(wf1a, wf1b) self.assertNotEqual(wf1a, wf3) self.assertNotEqual(wf1a, wf4) + self.assertNotEqual(wf1a, wf5) def test_defined_channels(self) -> None: wf = FunctionWaveform(ExpressionScalar('t'), 4, channel='A') @@ -1056,7 +1069,7 @@ def test_unsafe_get_subset_for_channels(self): wf.unsafe_get_subset_for_channels({'A'})) inner_subset.assert_called_once_with({'A'}) - def test_compare_key(self): + def test_comparison(self): inner_wf_1 = DummyWaveform(defined_channels={'A', 'B'}) inner_wf_2 = DummyWaveform(defined_channels={'A', 'B'}) functors_1 = dict(A=np.positive, B=np.negative) @@ -1067,7 +1080,8 @@ def test_compare_key(self): wf21 = FunctorWaveform(inner_wf_2, functors_1) wf22 = FunctorWaveform(inner_wf_2, functors_2) - self.assertEqual((inner_wf_1, frozenset(functors_1.items())), wf11.compare_key) + with self.assertWarns(DeprecationWarning): + self.assertEqual((inner_wf_1, frozenset(functors_1.items())), wf11.compare_key) self.assertEqual(wf11, wf11) self.assertEqual(wf11, FunctorWaveform(inner_wf_1, functors_1)) @@ -1083,7 +1097,8 @@ def test_simple_properties(self): self.assertEqual(dummy_wf.duration, reversed_wf.duration) self.assertEqual(dummy_wf.defined_channels, reversed_wf.defined_channels) - self.assertEqual(dummy_wf.compare_key, reversed_wf.compare_key) + with self.assertWarns(DeprecationWarning): + self.assertEqual(dummy_wf.compare_key, reversed_wf.compare_key) self.assertNotEqual(reversed_wf, dummy_wf) def test_reversed_sample(self): diff --git a/tests/pulses/sequencing_dummies.py b/tests/pulses/sequencing_dummies.py index 21c3c7e62..c70cd8d85 100644 --- a/tests/pulses/sequencing_dummies.py +++ b/tests/pulses/sequencing_dummies.py @@ -34,7 +34,6 @@ def normalize_measurement_windows(mw): class DummyWaveform(Waveform): - def __init__(self, duration: Union[float, TimeType]=0, sample_output: Union[numpy.ndarray, dict]=None, defined_channels=None) -> None: super().__init__(duration=duration if isinstance(duration, TimeType) else TimeType.from_float(duration)) self.sample_output = sample_output @@ -46,6 +45,12 @@ def __init__(self, duration: Union[float, TimeType]=0, sample_output: Union[nump self.defined_channels_ = defined_channels self.sample_calls = [] + def __hash__(self): + return hash(self.compare_key) + + def __eq__(self, other): + return isinstance(other, DummyWaveform) and self.compare_key == other.compare_key + @property def compare_key(self) -> Any: if self.sample_output is not None: From 216da480a6ab9752f7dfcb5e2b2af4d1b6740c27 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 15:15:33 +0200 Subject: [PATCH 11/53] Missing waveform related test --- tests/pulses/sequence_pulse_template_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pulses/sequence_pulse_template_tests.py b/tests/pulses/sequence_pulse_template_tests.py index d2a7f5544..ff14a0ed5 100644 --- a/tests/pulses/sequence_pulse_template_tests.py +++ b/tests/pulses/sequence_pulse_template_tests.py @@ -76,7 +76,7 @@ def test_build_waveform(self): self.assertIs(pt.build_waveform_calls[0][0], parameters) self.assertIsInstance(wf, SequenceWaveform) - for wfa, wfb in zip(wf.compare_key, wfs): + for wfa, wfb in zip(wf.sequenced_waveforms, wfs): self.assertIs(wfa, wfb) def test_identifier(self) -> None: From 9f38a39eae00350947e260eced75f714d4e7801f Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 15:16:07 +0200 Subject: [PATCH 12/53] Depreacte Comparable and cleanup some imports --- qupulse/comparable.py | 4 ++ qupulse/hardware/awgs/base.py | 12 +++- qupulse/program/transformation.py | 72 +++++++++++++++++-- qupulse/program/waveforms.py | 7 +- tests/_program/transformation_tests.py | 12 ++-- tests/comparable_tests.py | 5 +- .../pulses/arithmetic_pulse_template_tests.py | 11 ++- 7 files changed, 103 insertions(+), 20 deletions(-) diff --git a/qupulse/comparable.py b/qupulse/comparable.py index 2582faa8b..ce57c5aaa 100644 --- a/qupulse/comparable.py +++ b/qupulse/comparable.py @@ -1,6 +1,7 @@ """This module defines the abstract Comparable class.""" from abc import abstractmethod from typing import Hashable, Any +import warnings from qupulse.utils.types import DocStringABCMeta @@ -8,6 +9,9 @@ __all__ = ["Comparable"] +warnings.warn("qupulse.comparable is deprecated since 0.11 and will be removed in 0.12", DeprecationWarning) + + class Comparable(metaclass=DocStringABCMeta): """An object that can be queried for equality with other Comparable objects. diff --git a/qupulse/hardware/awgs/base.py b/qupulse/hardware/awgs/base.py index 5b1bb7c74..21b8a1cea 100644 --- a/qupulse/hardware/awgs/base.py +++ b/qupulse/hardware/awgs/base.py @@ -12,7 +12,7 @@ from typing import Set, Tuple, Callable, Optional, Mapping, Sequence, List, Union, NamedTuple from collections import OrderedDict from enum import Enum -# from itertools import chain +import warnings from qupulse.hardware.util import get_sample_times, not_none_indices from qupulse.utils.types import ChannelID @@ -20,7 +20,6 @@ Increment, Set as LSPSet, LoopLabel, LoopJmp, Wait, Play from qupulse.program.loop import Loop from qupulse.program.waveforms import Waveform -from qupulse.comparable import Comparable from qupulse.utils.types import TimeType import numpy @@ -39,7 +38,7 @@ class AWGAmplitudeOffsetHandling: _valid = [IGNORE_OFFSET, CONSIDER_OFFSET] -class AWG(Comparable): +class AWG: """An arbitrary waveform generator abstraction class. It represents a set of channels that have to have(hardware enforced) the same: @@ -142,6 +141,13 @@ def sample_rate(self) -> float: def compare_key(self) -> int: """Comparison and hashing is based on the id of the AWG so different devices with the same properties are ot equal""" + warnings.warn("AWG.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) + + def __eq__(self, other): + return self is other + + def __hash__(self): return id(self) @abstractmethod diff --git a/qupulse/program/transformation.py b/qupulse/program/transformation.py index 1d3c86879..c51c5fbb0 100644 --- a/qupulse/program/transformation.py +++ b/qupulse/program/transformation.py @@ -1,12 +1,12 @@ from typing import Any, Mapping, Set, Tuple, Sequence, AbstractSet, Union, TYPE_CHECKING, Hashable from abc import abstractmethod from numbers import Real +import warnings import numpy as np from qupulse import ChannelID -from qupulse.comparable import Comparable -from qupulse.utils.types import SingletonABCMeta, frozendict +from qupulse.utils.types import SingletonABCMeta, frozendict, DocStringABCMeta from qupulse.expressions import ExpressionScalar @@ -18,7 +18,9 @@ 'chain_transformations'] -class Transformation(Comparable): +class Transformation(metaclass=DocStringABCMeta): + __slots__ = () + _identity_singleton = None """Transforms numeric time-voltage values for multiple channels to other time-voltage values. The number and names of input and output channels might differ.""" @@ -58,6 +60,8 @@ def get_constant_output_channels(self, input_channels: AbstractSet[ChannelID]) - class IdentityTransformation(Transformation, metaclass=SingletonABCMeta): + __slots__ = () + def __call__(self, time: Union[np.ndarray, float], data: Mapping[ChannelID, Union[np.ndarray, float]]) -> Mapping[ChannelID, Union[np.ndarray, float]]: return data @@ -66,9 +70,17 @@ def get_output_channels(self, input_channels: AbstractSet[ChannelID]) -> Abstrac return input_channels @property - def compare_key(self) -> None: + def compare_key(self) -> type(None): + warnings.warn("Transformation.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) return None + def __hash__(self): + return 0x1234991 + + def __eq__(self, other): + return isinstance(other, IdentityTransformation) + def get_input_channels(self, output_channels: AbstractSet[ChannelID]) -> AbstractSet[ChannelID]: return output_channels @@ -87,6 +99,8 @@ def get_constant_output_channels(self, input_channels: AbstractSet[ChannelID]) - class ChainedTransformation(Transformation): + __slots__ = ('_transformations',) + def __init__(self, *transformations: Transformation): self._transformations = transformations @@ -112,8 +126,16 @@ def __call__(self, time: Union[np.ndarray, float], @property def compare_key(self) -> Tuple[Transformation, ...]: + warnings.warn("Transformation.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) return self._transformations + def __hash__(self): + return hash(self._transformations) + + def __eq__(self, other): + return self._transformations == getattr(other, '_transformations', None) + def chain(self, next_transformation) -> Transformation: return chain_transformations(*self.transformations, next_transformation) @@ -197,8 +219,20 @@ def get_input_channels(self, output_channels: AbstractSet[ChannelID]) -> Abstrac else: return forwarded | self._input_channels_set + def __hash__(self): + return hash((self._input_channels, self._output_channels, self._matrix.tobytes())) + + def __eq__(self, other): + if isinstance(other, type(self)): + return (self._input_channels == other._input_channels and + self._output_channels == other._output_channels and + np.array_equal(self._matrix, other._matrix)) + return False + @property def compare_key(self) -> Tuple[Tuple[ChannelID], Tuple[ChannelID], bytes]: + warnings.warn("Transformation.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) return self._input_channels, self._output_channels, self._matrix.tobytes() def __repr__(self): @@ -218,6 +252,8 @@ def get_constant_output_channels(self, input_channels: AbstractSet[ChannelID]) - class OffsetTransformation(Transformation): + __slots__ = ('_offsets',) + def __init__(self, offsets: Mapping[ChannelID, _TrafoValue]): """Adds an offset to each channel specified in offsets. @@ -241,8 +277,16 @@ def get_input_channels(self, output_channels: AbstractSet[ChannelID]) -> Abstrac def get_output_channels(self, input_channels: AbstractSet[ChannelID]) -> AbstractSet[ChannelID]: return input_channels + def __eq__(self, other): + return isinstance(other, OffsetTransformation) and self._offsets == other._offsets + + def __hash__(self): + return hash(self._offsets) + @property def compare_key(self) -> Hashable: + warnings.warn("Transformation.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) return self._offsets def __repr__(self): @@ -257,6 +301,8 @@ def get_constant_output_channels(self, input_channels: AbstractSet[ChannelID]) - class ScalingTransformation(Transformation): + __slots__ = ('_factors',) + def __init__(self, factors: Mapping[ChannelID, _TrafoValue]): self._factors = frozendict(factors) assert _are_valid_transformation_expressions(self._factors), f"Not valid transformation expressions: {self._factors}" @@ -273,8 +319,16 @@ def get_input_channels(self, output_channels: AbstractSet[ChannelID]) -> Abstrac def get_output_channels(self, input_channels: AbstractSet[ChannelID]) -> AbstractSet[ChannelID]: return input_channels + def __eq__(self, other): + return isinstance(other, ScalingTransformation) and self._factors == other._factors + + def __hash__(self): + return hash(self._factors) + @property def compare_key(self) -> Hashable: + warnings.warn("Transformation.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) return self._factors def __repr__(self): @@ -312,6 +366,8 @@ def linear_transformation_from_pandas(transformation: PandasDataFrameType) -> Li class ParallelChannelTransformation(Transformation): + __slots__ = ('_channels', ) + def __init__(self, channels: Mapping[ChannelID, _TrafoValue]): """Set channel values to given values regardless their former existence. The values can be time dependent expressions. @@ -333,8 +389,16 @@ def _instantiated_values(self, time): return {channel: value.evaluate_in_scope(scope) if hasattr(value, 'evaluate_in_scope') else array_or_float(value) for channel, value in self._channels.items()} + def __hash__(self): + return hash(self._channels) + + def __eq__(self, other): + return isinstance(other, ParallelChannelTransformation) and self._channels == other._channels + @property def compare_key(self) -> Hashable: + warnings.warn("Transformation.compare_key is deprecated since 0.11 and will be removed in 0.12", + DeprecationWarning, stacklevel=2) return self._channels def get_input_channels(self, output_channels: AbstractSet[ChannelID]) -> AbstractSet[ChannelID]: diff --git a/qupulse/program/waveforms.py b/qupulse/program/waveforms.py index ac077bb1f..15a33273e 100644 --- a/qupulse/program/waveforms.py +++ b/qupulse/program/waveforms.py @@ -17,18 +17,15 @@ import numpy as np from qupulse import ChannelID -from qupulse.program.transformation import Transformation -from qupulse.utils import checked_int_cast, isclose -from qupulse.utils.types import TimeType, time_from_float from qupulse.utils.performance import is_monotonic -from qupulse.comparable import Comparable from qupulse.expressions import ExpressionScalar from qupulse.pulses.interpolation import InterpolationStrategy from qupulse.utils import checked_int_cast, isclose -from qupulse.utils.types import TimeType, time_from_float, FrozenDict +from qupulse.utils.types import TimeType, time_from_float from qupulse.program.transformation import Transformation from qupulse.utils import pairwise + class ConstantFunctionPulseTemplateWarning(UserWarning): """ This warning indicates a constant waveform is constructed from a FunctionPulseTemplate """ pass diff --git a/tests/_program/transformation_tests.py b/tests/_program/transformation_tests.py index f9422f1f4..2d8e31918 100644 --- a/tests/_program/transformation_tests.py +++ b/tests/_program/transformation_tests.py @@ -64,10 +64,12 @@ def test_compare_key_and_init(self): matrix_2 = np.array([[1, 1, 1], [1, 0, -1]]) trafo_2 = LinearTransformation(matrix_2, in_chs_2, out_chs_2) - self.assertEqual(trafo.compare_key, trafo_2.compare_key) + with self.assertWarns(DeprecationWarning): + self.assertEqual(trafo.compare_key, trafo_2.compare_key) self.assertEqual(trafo, trafo_2) self.assertEqual(hash(trafo), hash(trafo_2)) - self.assertEqual(trafo.compare_key, (in_chs, out_chs, matrix.tobytes())) + with self.assertWarns(DeprecationWarning): + self.assertEqual(trafo.compare_key, (in_chs, out_chs, matrix.tobytes())) def test_from_pandas(self): try: @@ -175,7 +177,8 @@ def test_constant_propagation(self): class IdentityTransformationTests(unittest.TestCase): def test_compare_key(self): - self.assertIsNone(IdentityTransformation().compare_key) + with self.assertWarns(DeprecationWarning): + self.assertIsNone(IdentityTransformation().compare_key) def test_singleton(self): self.assertIs(IdentityTransformation(), IdentityTransformation()) @@ -216,7 +219,8 @@ def test_init_and_properties(self): chained = ChainedTransformation(*trafos) self.assertEqual(chained.transformations, trafos) - self.assertIs(chained.transformations, chained.compare_key) + with self.assertWarns(DeprecationWarning): + self.assertIs(chained.transformations, chained.compare_key) def test_get_output_channels(self): trafos = TransformationStub(), TransformationStub(), TransformationStub() diff --git a/tests/comparable_tests.py b/tests/comparable_tests.py index 0394c7b3a..5a0c489f3 100644 --- a/tests/comparable_tests.py +++ b/tests/comparable_tests.py @@ -1,7 +1,10 @@ import unittest from typing import Any +import warnings -from qupulse.comparable import Comparable +with warnings.catch_warnings(): + warnings.simplefilter(action='ignore', category=DeprecationWarning) + from qupulse.comparable import Comparable class DummyComparable(Comparable): diff --git a/tests/pulses/arithmetic_pulse_template_tests.py b/tests/pulses/arithmetic_pulse_template_tests.py index 66ff074c8..7f833d7ad 100644 --- a/tests/pulses/arithmetic_pulse_template_tests.py +++ b/tests/pulses/arithmetic_pulse_template_tests.py @@ -435,9 +435,11 @@ def test_internal_create_program(self): to_single_waveform = {'something_else'} program_builder = mock.Mock() - expected_transformation = mock.Mock(spec=IdentityTransformation()) + with self.assertWarns(DeprecationWarning): + expected_transformation = mock.Mock(spec=IdentityTransformation()) - inner_trafo = mock.Mock(spec=IdentityTransformation()) + with self.assertWarns(DeprecationWarning): + inner_trafo = mock.Mock(spec=IdentityTransformation()) inner_trafo.chain.return_value = expected_transformation with mock.patch.object(rhs, '_create_program') as inner_create_program: @@ -593,7 +595,10 @@ def test_build_waveform(self): channel_mapping = dict(a='u', b='v') inner_wf = DummyWaveform(duration=6, defined_channels={'a'}) - trafo = mock.Mock(spec=IdentityTransformation()) + with self.assertWarns(DeprecationWarning): + # mock will inspect alsod eprecated attributes + # TODO: remove assert as soon as attribute is removed + trafo = mock.Mock(spec=IdentityTransformation()) arith = ArithmeticPulseTemplate(pt, '-', 6) From f78b832e9047166bb09c3200534321dcbfa6d155 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 15:33:16 +0200 Subject: [PATCH 13/53] Fix missing return value in AWG.compare_key --- qupulse/hardware/awgs/base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qupulse/hardware/awgs/base.py b/qupulse/hardware/awgs/base.py index 21b8a1cea..43209c4db 100644 --- a/qupulse/hardware/awgs/base.py +++ b/qupulse/hardware/awgs/base.py @@ -143,6 +143,7 @@ def compare_key(self) -> int: are ot equal""" warnings.warn("AWG.compare_key is deprecated since 0.11 and will be removed in 0.12", DeprecationWarning, stacklevel=2) + return id(self) def __eq__(self, other): return self is other From fc0e5e762f50a6f7ab5b912199f1f58c01db9e4c Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 4 Jun 2024 15:50:00 +0200 Subject: [PATCH 14/53] Unify transformation comparison implementations --- qupulse/program/transformation.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/qupulse/program/transformation.py b/qupulse/program/transformation.py index c51c5fbb0..22a28e495 100644 --- a/qupulse/program/transformation.py +++ b/qupulse/program/transformation.py @@ -79,7 +79,7 @@ def __hash__(self): return 0x1234991 def __eq__(self, other): - return isinstance(other, IdentityTransformation) + return self is other def get_input_channels(self, output_channels: AbstractSet[ChannelID]) -> AbstractSet[ChannelID]: return output_channels @@ -134,7 +134,9 @@ def __hash__(self): return hash(self._transformations) def __eq__(self, other): - return self._transformations == getattr(other, '_transformations', None) + if isinstance(other, ChainedTransformation): + return self._transformations == other._transformations + return NotImplemented def chain(self, next_transformation) -> Transformation: return chain_transformations(*self.transformations, next_transformation) @@ -223,11 +225,11 @@ def __hash__(self): return hash((self._input_channels, self._output_channels, self._matrix.tobytes())) def __eq__(self, other): - if isinstance(other, type(self)): + if isinstance(other, LinearTransformation): return (self._input_channels == other._input_channels and self._output_channels == other._output_channels and np.array_equal(self._matrix, other._matrix)) - return False + return NotImplemented @property def compare_key(self) -> Tuple[Tuple[ChannelID], Tuple[ChannelID], bytes]: @@ -278,7 +280,9 @@ def get_output_channels(self, input_channels: AbstractSet[ChannelID]) -> Abstrac return input_channels def __eq__(self, other): - return isinstance(other, OffsetTransformation) and self._offsets == other._offsets + if isinstance(other, OffsetTransformation): + return self._offsets == other._offsets + return NotImplemented def __hash__(self): return hash(self._offsets) @@ -320,7 +324,9 @@ def get_output_channels(self, input_channels: AbstractSet[ChannelID]) -> Abstrac return input_channels def __eq__(self, other): - return isinstance(other, ScalingTransformation) and self._factors == other._factors + if isinstance(other, ScalingTransformation): + return self._factors == other._factors + return NotImplemented def __hash__(self): return hash(self._factors) @@ -393,7 +399,9 @@ def __hash__(self): return hash(self._channels) def __eq__(self, other): - return isinstance(other, ParallelChannelTransformation) and self._channels == other._channels + if isinstance(other, ParallelChannelTransformation): + return self._channels == other._channels + return NotImplemented @property def compare_key(self) -> Hashable: From b346ad79a5326627c0a0429d0c1c3ff12b9c2fdb Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Tue, 7 May 2024 17:38:47 +0200 Subject: [PATCH 15/53] Add zenodo metadata --- .zenodo.json | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 .zenodo.json diff --git a/.zenodo.json b/.zenodo.json new file mode 100644 index 000000000..69d6c7d28 --- /dev/null +++ b/.zenodo.json @@ -0,0 +1,74 @@ +{ + "creators": [ + { + "orcid": "0000-0002-9399-1055", + "affiliation": "RWTH Aachen University", + "name": "Humpohl, Simon" + }, + { + "orcid": "0000-0001-8678-961X", + "affiliation": "RWTH Aachen University", + "name": "Prediger, Lukas" + }, + { + "orcid": "0000-0002-8227-4018", + "affiliation": "RWTH Aachen University", + "name": "Cerfontaine, Pascal" + }, + { + "affiliation": "Forschungszentrum Jülich", + "name": "Papajewski, Benjamin" + }, + { + "orcid": "0000-0001-9927-3102", + "affiliation": "RWTH Aachen University", + "name": "Bethke, Patrick" + }, + { + "orcid": "0000-0003-2057-9913", + "affiliation": "Forschungszentrum Jülich", + "name": "Lankes, Lukas" + }, + { + "orcid": "0009-0006-9702-2979", + "affiliation": "Forschungszentrum Jülich", + "name": "Willmes, Alexander" + }, + { + "orcid": "0009-0000-3779-4711", + "affiliation": "Forschungszentrum Jülich", + "name": "Kammerloher, Eugen" + } + ], + + "contributors": [ + { + "orcid": "0000-0001-7018-1124", + "affiliation": "Netherlands Organisation for Applied Scientific Research TNO", + "name": "Eendebak, Pieter Thijs" + }, + { + "name": "Kreutz, Maike", + "affiliation": "RWTH Aachen University" + }, + { + "name": "Xue, Ran", + "affiliation": "RWTH Aachen University", + "orcid": "0000-0002-2009-6279" + } + ], + + "related_identifiers": [ + { + "identifier": "2128/24264", + "relation": "isDocumentedBy", + "resource_type": "publication-thesis" + } + ], + + "license": "GPL-3.0-or-later", + + "title": "qupulse: A Quantum compUting PULse parametrization and SEquencing framework", + + "keywords": ["quantum computing", "control pulse"] +} From f9ed9ffc4ad9e525cd20ccc3064ce488c8617135 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 10 Jun 2024 15:24:48 +0200 Subject: [PATCH 16/53] Do not execute hardware dependent notebook when building docs --- doc/source/examples/04ZurichInstrumentsSetup.ipynb | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/examples/04ZurichInstrumentsSetup.ipynb b/doc/source/examples/04ZurichInstrumentsSetup.ipynb index 851c806bc..21a77fe44 100644 --- a/doc/source/examples/04ZurichInstrumentsSetup.ipynb +++ b/doc/source/examples/04ZurichInstrumentsSetup.ipynb @@ -462,6 +462,7 @@ } ], "metadata": { + "nbsphinx": { "execute": "never" }, "kernelspec": { "display_name": "Python 3", "language": "python", From 787f2bc8d108775b7edf5a8d3a3d69fd3aa4bf41 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 10 Jun 2024 15:31:10 +0200 Subject: [PATCH 17/53] Include LoopBuilder explicitly in public interface --- qupulse/program/loop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qupulse/program/loop.py b/qupulse/program/loop.py index 5f127fbef..0e5dccc3e 100644 --- a/qupulse/program/loop.py +++ b/qupulse/program/loop.py @@ -25,7 +25,7 @@ from qupulse.utils.tree import Node from qupulse.utils.types import TimeType, MeasurementWindow -__all__ = ['Loop', 'make_compatible', 'MakeCompatibleWarning', 'to_waveform'] +__all__ = ['Loop', 'make_compatible', 'MakeCompatibleWarning', 'to_waveform', 'LoopBuilder'] DurationStructure = Tuple[int, Union[TimeType, 'DurationStructure']] From 3be8559ec3356cc166999e3d5a3689fc98f10971 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 10 Jun 2024 16:02:46 +0200 Subject: [PATCH 18/53] Fix several docstrings and improve program concept documentation --- doc/source/concepts/program.rst | 31 +++++++++++-------------------- qupulse/program/__init__.py | 9 ++++++--- qupulse/pulses/plotting.py | 2 +- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/doc/source/concepts/program.rst b/doc/source/concepts/program.rst index 82208ac15..f607f2e99 100644 --- a/doc/source/concepts/program.rst +++ b/doc/source/concepts/program.rst @@ -3,26 +3,17 @@ Instantiated Pulse: Program --------------------------- -In qupulse an instantiated pulse template is called a program as it is something that an arbitrary waveform generator -(AWG) can execute/playback. -It is created by the ``create_program`` method of the pulse template which returns a hardware -independent representation which is of type ``Loop`` by default. The method takes a ``program_builder`` keyword argument -which is passed through the pulse template tree and thereby implements the visitor pattern. If the argument is not -passed ``default_program_builder()`` is used instead which is ``LoopBuilder`` by default. - -The ``Loop`` default program is the root node of a tree ``Loop``s of arbitrary depth. -Each node consists of a repetition count and either a waveform or a sequence of nodes which are repeated that many times. -Iterations like the ```ForLoopPT`` cannot be represented natively but are unrolled into a sequence of items. -The repetition count is currently the only property of a program that can be defined as volatile. This means that the AWG driver tries to upload the program in a way, where the repetition count can quickly be changed. This is implemented via the ```VolatileRepetitionCount`` class. - -There is no description of the details of the program object here to avoid duplicated and outdated documentation. -The documentation is in the docstrings of the source code. -The program can be thought of as compact representation of a mapping :math:`\{t | 0 \le t \le t_{\texttt{duration}}} \rightarrow \mathbb{R}^n` from the time while the program lasts :math:´t´ to an n-dimensional voltage space :math:´\mathbb{R}^n´. +In qupulse an instantiated pulse template is called a program as it is something that an arbitrary waveform generator (AWG) can execute/playback. +It can be thought of as compact representation of a mapping :math:`\{t | 0 \le t \le t_{\texttt{duration}}\} \rightarrow \mathbb{R}^n` from the time while the program lasts :math:`t` to an n-dimensional voltage space :math:`\mathbb{R}^n`. The dimensions are named by the channel names. -The ``Loop`` class and its constituents ``Waveform`` and ``VolatileRepetitionCount`` are defined in the ``qupulse.program`` subpackage and it's submodules. -The private subpackage ``qupulse._program`` contains AWG driver internals that can change with any release, for example a -transpiler to Zurich Instruments sequencing C in ``qupulse._program.seqc``. +Programs are created by the :meth:`~.PulseTemplate.create_program` method of `PulseTemplate` which returns a hardware independent and un-parameterized representation. +The method takes a ``program_builder`` keyword argument that is propagated through the pulse template tree and thereby implements the visitor pattern. +If the argument is not passed :py:func:`~qupulse.program.default_program_builder()` is used instead which is :class:`.LoopBuilder` by default, i.e. the program created by default is of type :class:`.Loop`. The available program builders, programs and their constituents like :class:`.Waveform` and :class:`.VolatileRepetitionCount` are defined in th :mod:`qupulse.program` subpackage and it's submodules. There is a private ``qupulse._program`` subpackage that was used for more rapid iteration development and is slowly phased out. It still contains the hardware specific program representation for the tabor electronics AWG driver. Zurich instrument specific code has been factored into the separate package ``qupulse-hdawg``. Please refer to the reference and the docstrings for exact interfaces and implementation details. + +The :class:`.Loop` default program is the root node of a tree of loop objects of arbitrary depth. +Each node consists of a repetition count and either a waveform or a sequence of nodes which are repeated that many times. +Iterations like the :class:`.ForLoopPT` cannot be represented natively but are unrolled into a sequence of items. +The repetition count is currently the only property of a program that can be defined as volatile. This means that the AWG driver tries to upload the program in a way, where the repetition count can quickly be changed. This is implemented via the ``VolatileRepetitionCount`` class. -Another program format that is currently under development is ``LinSpaceProgram`` which efficiently encodes linearly -spaced sweeps in voltage space. However, the status of this is preliminary and not yet documented here. +A much more capable program format is :class:`.LinSpaceNode` which efficiently encodes linearly spaced sweeps in voltage space by utilizing increment commands. It is build via :class:`.LinSpaceBuilder`. Increment commands are available in the HDAWG command table. diff --git a/qupulse/program/__init__.py b/qupulse/program/__init__.py index 644cf9bd2..cd578dd5c 100644 --- a/qupulse/program/__init__.py +++ b/qupulse/program/__init__.py @@ -109,7 +109,8 @@ def evaluate_in_scope_(self, *args, **kwargs): @runtime_checkable class Program(Protocol): - """This protocol is used to inspect and or manipulate programs""" + """This protocol is used to inspect and or manipulate programs. As you can see the functionality is very limited + because most of a program class' capability are specific to the implementation.""" @property def duration(self) -> TimeType: @@ -117,11 +118,12 @@ def duration(self) -> TimeType: class ProgramBuilder(Protocol): - """This protocol is used by PulseTemplate to build the program via the visitor pattern. + """This protocol is used by :py:meth:`.PulseTemplate.create_program` to build a program via the visitor pattern. There is a default implementation which is the loop class. - Other hardware backends can use this protocol to implement easy translation of pulse templates.""" + Other hardware backends can use this protocol to implement easy translation of pulse templates into a hardware + compatible format.""" def inner_scope(self, scope: Scope) -> Scope: """This function is necessary to inject program builder specific parameter implementations into the build @@ -167,6 +169,7 @@ def to_program(self) -> Optional[Program]: def default_program_builder() -> ProgramBuilder: + """This function returns an instance of the default program builder class `LoopBuilder`""" from qupulse.program.loop import LoopBuilder return LoopBuilder() diff --git a/qupulse/pulses/plotting.py b/qupulse/pulses/plotting.py index 907629fe4..b6f29a4cd 100644 --- a/qupulse/pulses/plotting.py +++ b/qupulse/pulses/plotting.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -"""Deprecated plotting location. Was moved to :py:`qupulse.plotting`. +"""Deprecated plotting location. Was moved to :py:mod:`qupulse.plotting`. No deprecation warning because we will keep it around forever.""" from qupulse.plotting import * From bd99d286727fed9f2054f9b58b57c3144e0c4129 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 10 Jun 2024 16:51:45 +0200 Subject: [PATCH 19/53] Fix license classifier --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index d40206f1d..fd4cef6be 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ license_files = LICENSE/GPL-3.0-or-later.txt keywords = quantum, physics, control pulse, qubit classifiers = Programming Language :: Python :: 3 - OSI Approved :: GNU General Public License v3 or later (GPLv3+) + License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) Operating System :: OS Independent Topic :: Scientific/Engineering Intended Audience :: Science/Research From f154f1b24afb2b9be0d6dd19b6e2f42246fb2b9c Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 17 Jun 2024 12:53:16 +0200 Subject: [PATCH 20/53] Make gmpy2 a hard dependency --- .github/workflows/pythontest.yaml | 6 -- qupulse/hardware/awgs/tabor.py | 6 +- qupulse/utils/types.py | 24 ++----- setup.cfg | 4 +- tests/utils/time_type_tests.py | 105 +++++------------------------- 5 files changed, 28 insertions(+), 117 deletions(-) diff --git a/.github/workflows/pythontest.yaml b/.github/workflows/pythontest.yaml index 64a7c27cd..e4300f978 100644 --- a/.github/workflows/pythontest.yaml +++ b/.github/workflows/pythontest.yaml @@ -23,17 +23,11 @@ jobs: fail-fast: false matrix: python-version: ["3.8", "3.9", "3.10"] - time-type: ["fractions", "gmpy2"] env: INSTALL_EXTRAS: tests,plotting,zurich-instruments,tektronix,tabor-instruments steps: - - name: Add gmpy extra feature - if: ${{ matrix.time-type }} == 'gmpy2' - run: | - echo "INSTALL_EXTRAS=${{ env.INSTALL_EXTRAS }},Faster-fractions" >> $GITHUB_ENV - - name: Checkout repository uses: actions/checkout@v2 diff --git a/qupulse/hardware/awgs/tabor.py b/qupulse/hardware/awgs/tabor.py index b500f3645..7711773d5 100644 --- a/qupulse/hardware/awgs/tabor.py +++ b/qupulse/hardware/awgs/tabor.py @@ -2,9 +2,7 @@ # # SPDX-License-Identifier: GPL-3.0-or-later -import fractions import functools -import warnings import weakref import logging import numbers @@ -14,7 +12,7 @@ import tabor_control.device import numpy as np -from qupulse.utils.types import ChannelID +from qupulse.utils.types import ChannelID, TimeType from qupulse.program.loop import Loop, make_compatible from qupulse.hardware.util import voltage_to_uint16, traced from qupulse.hardware.awgs.base import AWG, AWGAmplitudeOffsetHandling @@ -470,7 +468,7 @@ def upload(self, name: str, make_compatible(program, minimal_waveform_length=192, waveform_quantum=16, - sample_rate=fractions.Fraction(sample_rate, 10**9)) + sample_rate=TimeType.from_fraction(sample_rate, 10**9)) if name in self._known_programs: if force: diff --git a/qupulse/utils/types.py b/qupulse/utils/types.py index ca51d1965..83dce2a0f 100644 --- a/qupulse/utils/types.py +++ b/qupulse/utils/types.py @@ -14,6 +14,7 @@ import numpy import sympy +import gmpy2 try: from frozendict import frozendict @@ -30,16 +31,6 @@ MeasurementWindow = typing.Tuple[str, numbers.Real, numbers.Real] ChannelID = typing.Union[str, int] -try: - import gmpy2 - qupulse_numeric.FractionType = gmpy2.mpq - -except ImportError: - gmpy2 = None - - warnings.warn('gmpy2 not found. Using fractions.Fraction as fallback. Install gmpy2 for better performance.' - 'time_from_float might produce slightly different results') - def _with_other_as_time_type(fn): """This is decorator to convert the other argument and the result into a :class:`TimeType`""" @@ -57,17 +48,16 @@ def wrapper(self, other) -> 'TimeType': class TimeType: - """This type represents a rational number with arbitrary precision. - - Internally it uses :func:`gmpy2.mpq` (if available) or :class:`fractions.Fraction` - """ __slots__ = ('_value',) - _InternalType = fractions.Fraction if gmpy2 is None else type(gmpy2.mpq()) - _to_internal = fractions.Fraction if gmpy2 is None else gmpy2.mpq + _InternalType = type(gmpy2.mpq()) + _to_internal = gmpy2.mpq def __init__(self, value: typing.Union[numbers.Rational, int] = 0., denominator: typing.Optional[int] = None): - """ + """This type represents a rational number with arbitrary precision. + + Internally it uses :func:`gmpy2.mpq` which is considered an implementation detail. + Args: value: interpreted as Rational if denominator is None. interpreted as numerator otherwise denominator: Denominator of the Fraction if not None diff --git a/setup.cfg b/setup.cfg index fd4cef6be..0d4a6d23d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,6 +29,7 @@ install_requires = typing-extensions;python_version<'3.8' frozendict lazy_loader + gmpy2 test_suite = tests [options.extras_require] @@ -46,7 +47,6 @@ tabor-instruments = zurich-instruments = qupulse-hdawg-legacy;python_version<'3.9' qupulse-hdawg;python_version>='3.9' -Faster-fractions = gmpy2 tektronix = tek_awg>=0.2.1 autologging = autologging # sadly not open source for external legal reasons @@ -55,7 +55,7 @@ autologging = autologging faster-sampling = numba # Everything besides awg drivers default = - qupulse[tests,docs,plotting,Faster-fractions,autologging,faster-sampling] + qupulse[tests,docs,plotting,autologging,faster-sampling] pandas [options.packages.find] diff --git a/tests/utils/time_type_tests.py b/tests/utils/time_type_tests.py index cdb9ccffd..b069cacf4 100644 --- a/tests/utils/time_type_tests.py +++ b/tests/utils/time_type_tests.py @@ -1,81 +1,12 @@ -import sys import unittest -import builtins -import contextlib -import importlib import fractions import random -import os - -from unittest import mock - -try: - import gmpy2 -except ImportError: - gmpy2 = None import numpy as np import sympy +import gmpy2 -import qupulse.utils.types as qutypes - - -MOCK_GMPY2_AS_MISSING = bool(os.getenv("QUPULSE_TESTS_MOCK_GMPY2_AS_MISSING")) - - -@contextlib.contextmanager -def mock_missing_module(module_name: str): - exit_stack = contextlib.ExitStack() - - if module_name in sys.modules: - # temporarily remove gmpy2 from the imported modules - - temp_modules = sys.modules.copy() - del temp_modules[module_name] - exit_stack.enter_context(mock.patch.dict(sys.modules, temp_modules)) - - original_import = builtins.__import__ - - def mock_import(name, *args, **kwargs): - if name == module_name: - raise ImportError(name) - else: - return original_import(name, *args, **kwargs) - - exit_stack.enter_context(mock.patch('builtins.__import__', mock_import)) - - with exit_stack: - yield - - -@unittest.skipIf(gmpy2 and not MOCK_GMPY2_AS_MISSING, "Not explicitly included. " - "Define QUPULSE_TESTS_MOCK_GMPY2_AS_MISSING to include.") -class TestTimeTypeDevFallback(unittest.TestCase): - @classmethod - def setUpClass(cls): - with mock_missing_module('gmpy2'): - cls.fallback_qutypes = importlib.reload(qutypes) - - def test_fraction_fallback(self): - self.assertIs(fractions.Fraction, self.fallback_qutypes.TimeType._InternalType) - - def test_fraction_time_from_fraction_fallback(self): - assert_from_fraction_works(self, self.fallback_qutypes.TimeType) - - def test_fraction_time_from_float_exact_fallback(self): - assert_from_float_exact_works(self, self.fallback_qutypes.TimeType) - - def test_fraction_time_from_float_with_precision_fallback(self): - assert_fraction_time_from_float_with_precision_works(self, self.fallback_qutypes.TimeType) - - def test_from_float_no_extra_args_fallback(self): - assert_from_float_no_extra_args_works(self, self.fallback_qutypes.TimeType) - - def test_try_from_any_fallback(self): - assert_try_from_any_works(self, self.fallback_qutypes.TimeType) - - def test_comparisons_work_fallback(self): - assert_comparisons_work(self, self.fallback_qutypes.TimeType) +from qupulse.utils.types import TimeType, time_from_float def assert_from_fraction_works(test: unittest.TestCase, time_type): @@ -155,9 +86,7 @@ def __repr__(self): for_array_tests = [] - signed_int_types = [int, sympy.Integer, np.int8, np.int16, np.int32, np.int64, DuckInt, DuckIntFloat] - if gmpy2: - signed_int_types.append(gmpy2.mpz) + signed_int_types = [int, sympy.Integer, np.int8, np.int16, np.int32, np.int64, DuckInt, DuckIntFloat, gmpy2.mpz] for s_t in signed_int_types: for val in (1, 17, -17): @@ -231,41 +160,41 @@ def assert_comparisons_work(test: unittest.TestCase, time_type): class TestTimeType(unittest.TestCase): - """The fallback test is here for convenience while developing and only triggered if the environment variable is set. - The fallback is also tested by the CI explicitly""" + """Tests the TimeType class. The layout of this test is in this way for historic reasons, i.e. to allow testing + different internal representations for the time type. Right now only gmpy.mpq is implemented and tested.""" def test_non_finite_float(self): with self.assertRaisesRegex(ValueError, 'Cannot represent'): - qutypes.TimeType.from_float(float('inf')) + TimeType.from_float(float('inf')) with self.assertRaisesRegex(ValueError, 'Cannot represent'): - qutypes.TimeType.from_float(float('-inf')) + TimeType.from_float(float('-inf')) with self.assertRaisesRegex(ValueError, 'Cannot represent'): - qutypes.TimeType.from_float(float('nan')) + TimeType.from_float(float('nan')) def test_fraction_time_from_fraction(self): - assert_from_fraction_works(self, qutypes.TimeType) + assert_from_fraction_works(self, TimeType) def test_fraction_time_from_float_exact(self): - assert_from_float_exact_works(self, qutypes.TimeType) + assert_from_float_exact_works(self, TimeType) def test_fraction_time_from_float_with_precision(self): - assert_fraction_time_from_float_with_precision_works(self, qutypes.TimeType) + assert_fraction_time_from_float_with_precision_works(self, TimeType) def test_from_float_no_extra_args(self): - assert_from_float_exact_works(self, qutypes.TimeType) + assert_from_float_exact_works(self, TimeType) def test_from_float_exceptions(self): with self.assertRaisesRegex(ValueError, '> 0'): - qutypes.time_from_float(.8, -1) + time_from_float(.8, -1) with self.assertRaisesRegex(ValueError, '<= 1'): - qutypes.time_from_float(.8, 2) + time_from_float(.8, 2) def test_try_from_any(self): - assert_try_from_any_works(self, qutypes.TimeType) + assert_try_from_any_works(self, TimeType) def test_comparisons_work(self): - assert_comparisons_work(self, qutypes.TimeType) + assert_comparisons_work(self, TimeType) def get_some_floats(seed=42, n=1000): @@ -274,7 +203,7 @@ def get_some_floats(seed=42, n=1000): def get_from_float(fs): - return [qutypes.time_from_float(f) for f in fs] + return [time_from_float(f) for f in fs] def do_additions(xs, ys): From 850786e0a360443dad0b96bde4fa58fec083bc3a Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 17 Jun 2024 12:54:14 +0200 Subject: [PATCH 21/53] Delete .travis.yml Remove completetely outdated CI configuration --- .travis.yml | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index df66b4e0b..000000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -language: python -python: - - 3.7 - - 3.8 -env: - - INSTALL_EXTRAS=[plotting,zurich-instruments,tektronix,tabor-instruments] - - INSTALL_EXTRAS=[plotting,zurich-instruments,tektronix,tabor-instruments,Faster-fractions,faster-sampling] - -#use container based infrastructure -sudo: false - -#these directories are persistent -cache: pip - -# install dependencies for gmpy2 -addons: - apt: - update: true - - sources: - # newer compiler for zhinst - - ubuntu-toolchain-r-test - - packages: - - libgmp-dev - - libmpfr-dev - - libmpc-dev - -before_install: - - eval "CC=gcc-8 && GXX=g++-8" - - pip install coverage coveralls -install: - - pip install .$INSTALL_EXTRAS -script: - - "coverage run --source=qupulse --rcfile=coverage.ini setup.py test" -after_success: - - coveralls - -notifications: - email: false From 3968eb57a27d9e7d7283b86c01a3ff22652617ec Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 17 Jun 2024 13:03:00 +0200 Subject: [PATCH 22/53] Add news fragment --- changes.d/845.removal | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes.d/845.removal diff --git a/changes.d/845.removal b/changes.d/845.removal new file mode 100644 index 000000000..b47bfa1fb --- /dev/null +++ b/changes.d/845.removal @@ -0,0 +1 @@ +Fallback for a missing `gmpy2` via `fractions` was removed. \ No newline at end of file From 5cb794ead18c7b70f7e6af31f1a82ce6006677c3 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 17 Jun 2024 13:29:13 +0200 Subject: [PATCH 23/53] Migrate to hatch # Conflicts: # setup.cfg # Conflicts: # setup.cfg --- pyproject.toml | 82 +++++++++++++++++++++++++++++++++++++++++++++++++- setup.cfg | 79 ------------------------------------------------ setup.py | 5 --- 3 files changed, 81 insertions(+), 85 deletions(-) delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/pyproject.toml b/pyproject.toml index cd673d74b..ff43e4937 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,85 @@ [build-system] -requires = ["setuptools", "wheel"] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "qupulse" +dynamic = ["version"] +description = "A Quantum compUting PULse parametrization and SEquencing framework" +readme = "README.md" +license = "GPL-3.0-or-later" +requires-python = ">=3.8" +authors = [ + { name = "Quantum Technology Group and Chair of Software Engineering" }, + { name = "RWTH Aachen University" }, +] +keywords = [ + "control", + "physics", + "pulse", + "quantum", + "qubit", +] +classifiers = [ + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Topic :: Scientific/Engineering", +] +dependencies = [ + "frozendict", + "lazy_loader", + "numpy", + "sympy>=1.1.1", + "gmpy2", +] + +[project.optional-dependencies] +autologging = [ + "autologging", +] +default = [ + "pandas", + "qupulse[tests,docs,plotting,autologging,faster-sampling]", +] +docs = [ + "ipykernel", + "nbsphinx", + "pyvisa", + "sphinx>=4", +] +faster-sampling = [ + "numba", +] +plotting = [ + "matplotlib", +] +tabor-instruments = [ + "tabor_control>=0.1.1", +] +tektronix = [ + "tek_awg>=0.2.1", +] +tests = [ + "pytest", + "pytest_benchmark", +] +zurich-instruments = [ + "qupulse-hdawg-legacy;python_version<'3.9'", + "qupulse-hdawg;python_version>='3.9'", +] + +[project.urls] +Homepage = "https://github.com/qutech/qupulse" + +[tool.hatch.version] +path = "qupulse/__init__.py" + +[tool.hatch.build.targets.sdist] +include = [ + "/qupulse", +] [tool.towncrier] directory = "changes.d" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 0d4a6d23d..000000000 --- a/setup.cfg +++ /dev/null @@ -1,79 +0,0 @@ -[metadata] -name = qupulse -version = attr: qupulse.__version__ -description = A Quantum compUting PULse parametrization and SEquencing framework -long_description = file: README.md -long_description_content_type = text/markdown -author = Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University -license = GPL-3.0-or-later -license_files = LICENSE/GPL-3.0-or-later.txt -keywords = quantum, physics, control pulse, qubit -classifiers = - Programming Language :: Python :: 3 - License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) - Operating System :: OS Independent - Topic :: Scientific/Engineering - Intended Audience :: Science/Research -url = https://github.com/qutech/qupulse - -[options] -packages = find: -package_dir = - qupulse=qupulse - qctoolkit=qctoolkit -python_requires = >=3.8 -install_requires = - sympy>=1.1.1 - numpy - cached_property;python_version<'3.8' - typing-extensions;python_version<'3.8' - frozendict - lazy_loader - gmpy2 -test_suite = tests - -[options.extras_require] -tests = - pytest - pytest_benchmark -docs = - sphinx>=4 - nbsphinx - ipykernel - pyvisa -plotting = matplotlib -tabor-instruments = - tabor_control>=0.1.1 -zurich-instruments = - qupulse-hdawg-legacy;python_version<'3.9' - qupulse-hdawg;python_version>='3.9' -tektronix = tek_awg>=0.2.1 -autologging = autologging -# sadly not open source for external legal reasons -# commented out because pypi does not allow direct dependencies -# atsaverage = atsaverage @ git+ssh://git@git.rwth-aachen.de/qutech/cpp-atsaverage.git@master#egg=atsaverage&subdirectory=python_source -faster-sampling = numba -# Everything besides awg drivers -default = - qupulse[tests,docs,plotting,autologging,faster-sampling] - pandas - -[options.packages.find] -include = - qupulse - qupulse.* - qctoolkit - -[options.package_data] -qupulse = - *.pyi -qctoolkit = - *.pyi - -[build_sphinx] -project = 'qupulse' -version = 0.9 -release = 0.9 -source-dir = ./doc/source -build-dir = ./doc/build -fresh-env = 1 diff --git a/setup.py b/setup.py deleted file mode 100644 index 5ff9a65c8..000000000 --- a/setup.py +++ /dev/null @@ -1,5 +0,0 @@ -from setuptools import setup - -if __name__ == '__main__': - # reads from setup.cfg - setup() From a1f834d53414b460effa64a57cf7edd9c8587105 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 10 Jun 2024 18:05:20 +0200 Subject: [PATCH 24/53] Switch to hatch as unified documentation build interface --- doc/Makefile | 20 -------------------- doc/README.md | 4 ++-- doc/make.bat | 35 ----------------------------------- doc/requirements.txt | 3 --- pyproject.toml | 31 +++++++++++++++++++++++++++++-- 5 files changed, 31 insertions(+), 62 deletions(-) delete mode 100644 doc/Makefile delete mode 100644 doc/make.bat delete mode 100644 doc/requirements.txt diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index d0c3cbf10..000000000 --- a/doc/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/doc/README.md b/doc/README.md index 4aab70678..014783155 100644 --- a/doc/README.md +++ b/doc/README.md @@ -8,6 +8,6 @@ You may either build the documentation yourself or read it on [readthedocs](http In the subdirectory *examples* you can find various [Jupyter notebook](http://jupyter.org/) files providing some step-by-step examples of how qupulse can be used. These can be explored in an interactive fashion by running the *Jupyter notebook* application inside the folder. However, a static version will also be included in the documentation created with *sphinx*. ## Building the Documentation -To build the documentation, you will need [sphinx](http://www.sphinx-doc.org/en/stable/) and [nbsphinx](https://nbsphinx.readthedocs.org/) which, in turn, requires [pandoc](http://pandoc.org/). +To build the documentation, you will need [sphinx](http://www.sphinx-doc.org/en/stable/) and [nbsphinx](https://nbsphinx.readthedocs.org/) which, in turn, requires [pandoc](http://pandoc.org/) which must be installed separately. -The documentation is built by invoking `make ` inside the */doc* directory, where `` is an output format supported by *sphinx*, e.g., `html`. The output will then be found in `/doc/build/`. +You can use hatch to build the documentation locally via `hatch run docs:build ` or a bit more concise `hatch run docs:html`. The output will then be found in `/doc/build/`. diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100644 index 9534b0181..000000000 --- a/doc/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/doc/requirements.txt b/doc/requirements.txt deleted file mode 100644 index 575c546ab..000000000 --- a/doc/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -sphinx==4.4.0 -nbsphinx==0.8.8 -ipykernel==6.9.1 diff --git a/pyproject.toml b/pyproject.toml index ff43e4937..5b4d1f00c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,8 +10,7 @@ readme = "README.md" license = "GPL-3.0-or-later" requires-python = ">=3.8" authors = [ - { name = "Quantum Technology Group and Chair of Software Engineering" }, - { name = "RWTH Aachen University" }, + { name = "Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University" }, ] keywords = [ "control", @@ -81,6 +80,34 @@ include = [ "/qupulse", ] +[tool.hatch.envs.docs] +dependencies = [ + "sphinx", + "nbsphinx", + "sphinx-rtd-theme" +] +[tool.hatch.envs.docs.scripts] +# This is a hack to achieve cross-platform version extraction until https://github.com/pypa/hatch/issues/1006 +build = """ + python -c "import subprocess, os; \ + result = subprocess.run(['hatch', 'version'], capture_output=True, text=True); \ + version = result.stdout.strip(); \ + subprocess.run(['sphinx-build', '-b', '{args:0}', 'doc/source', 'doc/build', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" +""" +latex = """ + python -c "import subprocess, os; \ + result = subprocess.run(['hatch', 'version'], capture_output=True, text=True); \ + version = result.stdout.strip(); \ + subprocess.run(['sphinx-build', '-b', 'latex', 'doc/source', 'doc/build', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" +""" +html = """ + python -c "import subprocess, os; \ + result = subprocess.run(['hatch', 'version'], capture_output=True, text=True); \ + version = result.stdout.strip(); \ + subprocess.run(['sphinx-build', '-b', 'html', 'doc/source', 'doc/build', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" +""" + + [tool.towncrier] directory = "changes.d" package = "qupulse" From 2e583593d0b915db3ef093c4ea3fd93d1381e87d Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 10 Jun 2024 18:25:41 +0200 Subject: [PATCH 25/53] Make build path even more confused --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 5b4d1f00c..14128685a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,19 +92,19 @@ build = """ python -c "import subprocess, os; \ result = subprocess.run(['hatch', 'version'], capture_output=True, text=True); \ version = result.stdout.strip(); \ - subprocess.run(['sphinx-build', '-b', '{args:0}', 'doc/source', 'doc/build', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" + subprocess.run(['sphinx-build', '-b', '{args:0}', 'doc/source', 'doc/build/{args:0}', '-d', 'doc/build/.doctrees', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" """ latex = """ python -c "import subprocess, os; \ result = subprocess.run(['hatch', 'version'], capture_output=True, text=True); \ version = result.stdout.strip(); \ - subprocess.run(['sphinx-build', '-b', 'latex', 'doc/source', 'doc/build', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" + subprocess.run(['sphinx-build', '-b', 'latex', 'doc/source', 'doc/build/latex', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" """ html = """ python -c "import subprocess, os; \ result = subprocess.run(['hatch', 'version'], capture_output=True, text=True); \ version = result.stdout.strip(); \ - subprocess.run(['sphinx-build', '-b', 'html', 'doc/source', 'doc/build', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" + subprocess.run(['sphinx-build', '-b', 'html', 'doc/source', 'doc/build/html', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" """ From b9d726ba19a843ef66c2d5ad16379fd9cbeb5bae Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 10 Jun 2024 18:26:08 +0200 Subject: [PATCH 26/53] Use default requirements to build docs --- readthedocs.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/readthedocs.yml b/readthedocs.yml index 903c17d30..3c8203900 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -3,13 +3,14 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.9" + python: "3.11" python: install: - - requirements: doc/requirements.txt - - method: setuptools + - method: pip path: . + extra_requirements: + - default sphinx: builder: html From 147676db4336eff714cf028f93bbe4f73e61a999 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 17 Jun 2024 13:26:19 +0200 Subject: [PATCH 27/53] Add towncrier integration and update README accordingly --- README.md | 11 ++++++++++- pyproject.toml | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4dfe22973..ac8825e34 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Alternatively, the current development version of qupulse can be installed by ex ```sh python -m pip install -e git+https://github.com/qutech/qupulse.git#egg=qupulse[default] ``` -which will clone the github repository to `./src/qupulse` and do an editable/development install. +which will clone the github repository to `./src/qupulse` and do an editable/development install. ### Requirements and dependencies qupulse requires at least Python 3.8 and is tested on 3.8, 3.9 and 3.10. It relies on some external Python packages as dependencies. @@ -63,6 +63,15 @@ The repository primarily consists of the folders `qupulse` (toolkit core code) a Contents of `tests` mirror the structure of `qupulse`. For every `` somewhere in `qupulse` there should exist a `Tests.py` in the corresponding subdirectory of `tests`. +## Development + +`qupulse` uses `hatch` as development tool which provides a convenient interface for most development tasks. The following should work. + + - `hatch build`: Build wheel and source tarball + - `hatch version X.X.X`: Set version + - `hatch run docs:html`: Build documentation (requires pandoc) + - `hatch run changelog:draft` and `hatch run changelog:release` to preview or update the changelog. + ## License The current version of qupulse is available under the `GPL-3.0-or-later` license. Versions up to and including 0.10 were licensed under the MIT license. If you require different licensing terms, please contact us to discuss your needs. diff --git a/pyproject.toml b/pyproject.toml index 14128685a..b0d59c055 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -107,6 +107,15 @@ html = """ subprocess.run(['sphinx-build', '-b', 'html', 'doc/source', 'doc/build/html', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" """ +[tool.hatch.envs.changelog] +detached = true +dependencies = [ + "towncrier", +] + +[tool.hatch.envs.changelog.scripts] +draft = "towncrier build --version main --draft" +release = "towncrier build --yes --version {args}" [tool.towncrier] directory = "changes.d" From cc4e7b8efbf5b770f92e971c7a8ed58c9aa88fec Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 17 Jun 2024 13:27:45 +0200 Subject: [PATCH 28/53] Update python setup --- .github/workflows/pythontest.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/pythontest.yaml b/.github/workflows/pythontest.yaml index e4300f978..b67a02074 100644 --- a/.github/workflows/pythontest.yaml +++ b/.github/workflows/pythontest.yaml @@ -32,12 +32,10 @@ jobs: uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - # supported since 2.3 cache: pip - cache-dependency-path: setup.cfg - name: Install dependencies run: | From c74c87100f49a3e4a0083c1fca65f4f065e4a457 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 12:39:59 +0200 Subject: [PATCH 29/53] Properly include ZHINST example --- doc/source/examples/examples.rst | 1 + doc/source/learners_guide.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/examples/examples.rst b/doc/source/examples/examples.rst index c543712d4..3226464d5 100644 --- a/doc/source/examples/examples.rst +++ b/doc/source/examples/examples.rst @@ -45,6 +45,7 @@ All examples are provided as static text in this documentation and, additionally :name: hardware_examples 02CreatePrograms + 04ZurichInstrumentsSetup The ``/doc/source/examples`` directory also contains some outdated examples for features and functionality that has been changed. These examples start with an underscore i.e. ``_*.ipynb`` and are currently left only for reference purposes. If you are just learning how to get around in qupulse please ignore them. \ No newline at end of file diff --git a/doc/source/learners_guide.rst b/doc/source/learners_guide.rst index ee728dd2a..f21b329d0 100644 --- a/doc/source/learners_guide.rst +++ b/doc/source/learners_guide.rst @@ -97,4 +97,4 @@ Read :ref:`program` and :ref:`hardware`. Setup an experiment ^^^^^^^^^^^^^^^^^^^ -This section is under construction. There is currently an outdated example :ref:`/examples/_HardwareSetup.ipynb` +This process is not fully documented yet. qupulse gives you tools for very flexible setup configurations. However, there is an example setup with Zurich Instruments devices in :ref:`/examples/04ZurichInstrumentsSetup.ipynb`. From a229bf235b260c2216bf629dc94e4b55e19778a2 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 12:44:20 +0200 Subject: [PATCH 30/53] Specify expression path --- doc/source/concepts/pulsetemplates.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/concepts/pulsetemplates.rst b/doc/source/concepts/pulsetemplates.rst index 9c1463917..85b7853ad 100644 --- a/doc/source/concepts/pulsetemplates.rst +++ b/doc/source/concepts/pulsetemplates.rst @@ -8,7 +8,7 @@ qupulse represents pulses as abstract pulse templates. A pulse template can be u There are multiple types of different pulse template classes, briefly explained in the following. :class:`.TablePulseTemplate`, :class:`.PointPulseTemplate` and :class:`.FunctionPulseTemplate` are used to define the atomic building blocks of pulses in the following ways: :class:`.TablePulseTemplate` and :class:`.PointPulseTemplate` allow the user to specify pairs of time and voltage values and choose an interpolation strategy between neighbouring points. Both templates support multiple channels but :class:`.TablePulseTemplate` allows for different time values for different channels meaning that the channels can change their voltages at different times. :class:`.PointPulseTemplate` restricts this to switches at the same time by interpreting the voltage as a vector and provides a more convenient interface for this case. -:class:`.FunctionPulseTemplate` accepts any mathematical function that maps time to voltage values. Internally it uses :class:`.Expression` for function evaluation. +:class:`.FunctionPulseTemplate` accepts any mathematical function that maps time to voltage values. Internally it uses :class:`qupulse.expressions.Expression` for function evaluation. All other pulse template classes are then used to construct arbitrarily complex pulse templates by combining existing ones into new structures [#tree]_: :class:`.SequencePulseTemplate` enables the user to specify a sequence of existing pulse templates (subtemplates) and modify parameter values using a mapping function. From a707b906e4a7ee71f2fe9fd196265a9fd62bb226 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 12:44:57 +0200 Subject: [PATCH 31/53] Include zhinst as dependency for documentation --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index b0d59c055..c79768ccb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,6 +82,7 @@ include = [ [tool.hatch.envs.docs] dependencies = [ + "qupulse[default,zurich-instruments]", "sphinx", "nbsphinx", "sphinx-rtd-theme" From 168f0a6c39cef037e5930745ba8abb2d9fef0a1e Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 12:45:53 +0200 Subject: [PATCH 32/53] Include docs:clean command --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index c79768ccb..fd747e3eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -107,6 +107,9 @@ html = """ version = result.stdout.strip(); \ subprocess.run(['sphinx-build', '-b', 'html', 'doc/source', 'doc/build/html', '-D', 'version=%s' % version, '-D', 'release=%s' % version])" """ +clean= """ +python -c "import shutil; shutil.rmtree('doc/build')" +""" [tool.hatch.envs.changelog] detached = true From 3294b649e7fae86ab28ad891c80e5a61c0b2b358 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 12:49:13 +0200 Subject: [PATCH 33/53] Remove outdated sentence in documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac8825e34..358bb1c93 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ which will clone the github repository to `./src/qupulse` and do an editable/dev qupulse requires at least Python 3.8 and is tested on 3.8, 3.9 and 3.10. It relies on some external Python packages as dependencies. We intentionally did not restrict versions of dependencies in the install scripts to not unnecessarily prevent usage of newer releases of dependencies that might be compatible. However, if qupulse does encounter problems with a particular dependency version please file an issue. -The backend for TaborAWGs requires packages that can be found [here](https://git.rwth-aachen.de/qutech/python-TaborDriver). As a shortcut you can install it from the python interpreter via `qupulse.hardware.awgs.install_requirements('tabor')`. +The backend for TaborAWGs requires packages that can be found [here](https://git.rwth-aachen.de/qutech/python-TaborDriver). The data acquisition backend for AlazarTech cards needs a package that unfortunately is not open source (yet). If you need it or have questions contact . From 5a724a95cd263709192abe20e256dd718c2584c8 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 14:55:33 +0200 Subject: [PATCH 34/53] Remove "unexpected indentation" --- doc/source/concepts/awgs.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/source/concepts/awgs.rst b/doc/source/concepts/awgs.rst index 0b3497652..accd604d3 100644 --- a/doc/source/concepts/awgs.rst +++ b/doc/source/concepts/awgs.rst @@ -8,9 +8,10 @@ This section is supposed to help you understand how qupulse sees AWGs and by ext When a program is uploaded to an arbitrary waveform generator (AWG) it needs to brought in a form that the hardware understands. Most AWGs consist of three significant parts: - * The actual digital to analog converter (DAC) that outputs samples at a (semi-) fixed rate [1]_ - * A sequencer which tells the DAC what to do - * Waveform memory which contains sampled waveforms in a format that the DAC understands + +* The actual digital to analog converter (DAC) that outputs samples at a (semi-) fixed rate [1]_, +* a sequencer which tells the DAC what to do, +* waveform memory which contains sampled waveforms in a format that the DAC understands. The sequencer feeds the data from the waveform memory to the DAC in the correct order. Uploading a qupulse pulse to an AWG requires to sample the program, upload waveforms to the memory From c00dd7b69f229ac661f4f9e840a8b8d66f32d638 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 15:05:02 +0200 Subject: [PATCH 35/53] Push minimal supported python version --- .github/workflows/pythontest.yaml | 2 +- README.md | 2 +- changes.d/835.removal | 1 + pyproject.toml | 5 ++--- 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 changes.d/835.removal diff --git a/.github/workflows/pythontest.yaml b/.github/workflows/pythontest.yaml index b67a02074..38cadd540 100644 --- a/.github/workflows/pythontest.yaml +++ b/.github/workflows/pythontest.yaml @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.10", "3.11", "3.12"] env: INSTALL_EXTRAS: tests,plotting,zurich-instruments,tektronix,tabor-instruments diff --git a/README.md b/README.md index 358bb1c93..1ad4ccb7b 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ python -m pip install -e git+https://github.com/qutech/qupulse.git#egg=qupulse[d which will clone the github repository to `./src/qupulse` and do an editable/development install. ### Requirements and dependencies -qupulse requires at least Python 3.8 and is tested on 3.8, 3.9 and 3.10. It relies on some external Python packages as dependencies. +qupulse requires at least Python 3.10 and is tested on 3.10, 3.11 and 3.12. It relies on some external Python packages as dependencies. We intentionally did not restrict versions of dependencies in the install scripts to not unnecessarily prevent usage of newer releases of dependencies that might be compatible. However, if qupulse does encounter problems with a particular dependency version please file an issue. The backend for TaborAWGs requires packages that can be found [here](https://git.rwth-aachen.de/qutech/python-TaborDriver). diff --git a/changes.d/835.removal b/changes.d/835.removal new file mode 100644 index 000000000..cc2f7a5f0 --- /dev/null +++ b/changes.d/835.removal @@ -0,0 +1 @@ +Remove python 3.8 and 3.9 support. Version 3.10 is now the minimal supported version. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index fd747e3eb..f0697b235 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ dynamic = ["version"] description = "A Quantum compUting PULse parametrization and SEquencing framework" readme = "README.md" license = "GPL-3.0-or-later" -requires-python = ">=3.8" +requires-python = ">=3.10" authors = [ { name = "Quantum Technology Group and Chair of Software Engineering, RWTH Aachen University" }, ] @@ -65,8 +65,7 @@ tests = [ "pytest_benchmark", ] zurich-instruments = [ - "qupulse-hdawg-legacy;python_version<'3.9'", - "qupulse-hdawg;python_version>='3.9'", + "qupulse-hdawg", ] [project.urls] From 21cd24bc4fb7adb18fd5055dafab614b14d4498b Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 15:25:12 +0200 Subject: [PATCH 36/53] Allow gmpy2 release candidate installation for python 3.12 --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f0697b235..32f04eb74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,9 @@ dependencies = [ "lazy_loader", "numpy", "sympy>=1.1.1", - "gmpy2", + # This is required because there is no 3.12 compatible gmpy2 stable release as of 2024.06.20 + "gmpy2;python_version<'3.12'", + "gmpy2>=2.2.0rc1;python_version>='3.12'" ] [project.optional-dependencies] From e50211606ec97854bc4496786d92d92f9e18a664 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 15:32:28 +0200 Subject: [PATCH 37/53] Do not used removed assertEquals alias --- tests/serialization_tests.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/serialization_tests.py b/tests/serialization_tests.py index 1ebd93b8e..537e642c2 100644 --- a/tests/serialization_tests.py +++ b/tests/serialization_tests.py @@ -1527,8 +1527,8 @@ def test_convert_stored_pulse_in_storage_dest_not_empty_id_overlap(self) -> None with self.assertRaises(ValueError): convert_stored_pulse_in_storage('hugos_parent', source_backend, destination_backend) - self.assertEquals('already_existing_data', destination_backend['hugo']) - self.assertEquals(1, len(destination_backend.stored_items)) + self.assertEqual('already_existing_data', destination_backend['hugo']) + self.assertEqual(1, len(destination_backend.stored_items)) def test_convert_stored_pulse_in_storage_dest_not_empty_no_id_overlap(self) -> None: with warnings.catch_warnings(): @@ -1548,7 +1548,7 @@ def test_convert_stored_pulse_in_storage_dest_not_empty_no_id_overlap(self) -> N destination_backend.put('ilse', 'already_existing_data') convert_stored_pulse_in_storage('hugos_parent', source_backend, destination_backend) - self.assertEquals('already_existing_data', destination_backend['ilse']) + self.assertEqual('already_existing_data', destination_backend['ilse']) pulse_storage = PulseStorage(destination_backend) deserialized = pulse_storage['hugos_parent'] self.assertEqual(serializable, deserialized) @@ -1607,8 +1607,8 @@ def test_convert_stored_pulses_dest_not_empty_id_overlap(self) -> None: with self.assertRaises(ValueError): convert_pulses_in_storage(source_backend, destination_backend) - self.assertEquals('already_existing_data', destination_backend['hugo']) - self.assertEquals(1, len(destination_backend.stored_items)) + self.assertEqual('already_existing_data', destination_backend['hugo']) + self.assertEqual(1, len(destination_backend.stored_items)) def test_convert_stored_pulses_dest_not_empty_no_id_overlap(self) -> None: with warnings.catch_warnings(): From bce97bc46f815bdf2da224150a04a186e4409bfb Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Thu, 20 Jun 2024 16:06:30 +0200 Subject: [PATCH 38/53] Remove dead custom frozendict implementations --- changes.d/853.misc | 1 + qupulse/utils/types.py | 128 +------------------------------------ tests/utils/types_tests.py | 102 +---------------------------- 3 files changed, 5 insertions(+), 226 deletions(-) create mode 100644 changes.d/853.misc diff --git a/changes.d/853.misc b/changes.d/853.misc new file mode 100644 index 000000000..cf8b7ff32 --- /dev/null +++ b/changes.d/853.misc @@ -0,0 +1 @@ +Remove private and unused frozendict fallback implementations `_FrozenDictByInheritance` and `_FrozenDictByWrapping`. \ No newline at end of file diff --git a/qupulse/utils/types.py b/qupulse/utils/types.py index 83dce2a0f..915fe8832 100644 --- a/qupulse/utils/types.py +++ b/qupulse/utils/types.py @@ -15,18 +15,12 @@ import numpy import sympy import gmpy2 - -try: - from frozendict import frozendict -except ImportError: - warnings.warn("The frozendict package is not installed. We currently also ship a fallback frozendict which " - "will be removed in a future release.", category=DeprecationWarning) - frozendict = None +from frozendict import frozendict import qupulse.utils.numeric as qupulse_numeric __all__ = ["MeasurementWindow", "ChannelID", "HashableNumpyArray", "TimeType", "time_from_float", "DocStringABCMeta", - "SingletonABCMeta", "SequenceProxy", "frozendict"] + "SingletonABCMeta", "SequenceProxy"] MeasurementWindow = typing.Tuple[str, numbers.Real, numbers.Real] ChannelID = typing.Union[str, int] @@ -399,121 +393,7 @@ def has_type_interface(obj: typing.Any, type_obj: typing.Type) -> bool: _T_co_hash = typing.TypeVar('_T_co_hash', bound=typing.Hashable, covariant=True) # Any type covariant containers. FrozenMapping = typing.Mapping[_KT_hash, _T_co_hash] - - -class _FrozenDictByInheritance(dict): - """This is non mutable, hashable dict. It violates the Liskov substitution principle but is faster than wrapping. - It is not used by default and may be removed in the future. - """ - def __setitem__(self, key, value): - raise TypeError('FrozenDict is immutable') - - def __delitem__(self, key): - raise TypeError('FrozenDict is immutable') - - def update(self, *args, **kwargs): - raise TypeError('FrozenDict is immutable') - - def setdefault(self, *args, **kwargs): - raise TypeError('FrozenDict is immutable') - - def clear(self): - raise TypeError('FrozenDict is immutable') - - def pop(self, *args, **kwargs): - raise TypeError('FrozenDict is immutable') - - def popitem(self, *args, **kwargs): - raise TypeError('FrozenDict is immutable') - - def copy(self): - return self - - def to_dict(self) -> typing.Dict[_KT_hash, _T_co_hash]: - return super().copy() - - def __hash__(self): - # faster than functools.reduce(operator.xor, map(hash, self.items())) but takes more memory - # TODO: investigate caching - return hash(frozenset(self.items())) - - -class _FrozenDictByWrapping(FrozenMapping): - """Immutable dict like type. - - There are the following possibilities in pure python: - - subclass dict (violates the Liskov substitution principle) - - wrap dict (slow construction and method indirection) - - abuse MappingProxyType (hard to add hash and make mutation difficult) - - - - Wrapper around builtin dict without the mutating methods. - - Hot path methods in __slots__ are the bound methods of the dict object. The other methods are wrappers. - - Why not subclass dict and overwrite mutating methods: - roughly the same speed for __slot__ methods (a bit slower than native dict) - dict subclass always implements MutableMapping which makes type annotations useless - caching the hash value is slightly slower for the subclass - - Only downside: This wrapper class needs to implement __init__ and copy the __slot__ methods which is an overhead of - ~10 i.e. 250ns for empty subclass init vs. 4µs for empty wrapper init - """ - # made concessions in code style due to performance - _HOT_PATH_METHODS = ('keys', 'items', 'values', 'get', '__getitem__') - _PRIVATE_ATTRIBUTES = ('_hash', '_dict') - __slots__ = _HOT_PATH_METHODS + _PRIVATE_ATTRIBUTES - - def __new__(cls, *args, **kwds): - """Overwriting __new__ saves a factor of two for initialization. This is the relevant line from - Generic.__new__""" - return object.__new__(cls) - - def __init__(self, *args, **kwargs): - inner_dict = dict(*args, **kwargs) - self._dict = inner_dict # type: typing.Dict[_KT_hash, _T_co_hash] - self._hash = None - - self.__getitem__ = inner_dict.__getitem__ - self.keys = inner_dict.keys - self.items = inner_dict.items - self.values = inner_dict.values - self.get = inner_dict.get - - def __contains__(self, item: _KT_hash) -> bool: - return item in self._dict - - def __iter__(self) -> typing.Iterator[_KT_hash]: - return iter(self._dict) - - def __len__(self) -> int: - return len(self._dict) - - def __repr__(self): - return '%s(%r)' % (self.__class__.__name__, self._dict) - - def __hash__(self) -> int: - # use the local variable h to minimize getattr calls to minimum and reduce caching overhead - h = self._hash - if h is None: - self._hash = h = functools.reduce(operator.xor, map(hash, self.items()), 0xABCD0) - return h - - def __eq__(self, other: typing.Mapping): - return other == self._dict - - def copy(self): - return self - - def to_dict(self) -> typing.Dict[_KT_hash, _T_co_hash]: - return self._dict.copy() - - -if frozendict is None: - FrozenDict = _FrozenDictByWrapping -else: - FrozenDict = frozendict +FrozenDict = frozendict class SequenceProxy(collections.abc.Sequence): @@ -550,5 +430,3 @@ def __eq__(self, other): and all(x == y for x, y in zip(self, other))) else: return NotImplemented - - diff --git a/tests/utils/types_tests.py b/tests/utils/types_tests.py index e2271d2fe..5a2a53ef1 100644 --- a/tests/utils/types_tests.py +++ b/tests/utils/types_tests.py @@ -1,10 +1,8 @@ import unittest -import inspect import numpy as np -from qupulse.utils.types import (HashableNumpyArray, SequenceProxy, _FrozenDictByWrapping, - _FrozenDictByInheritance) +from qupulse.utils.types import (HashableNumpyArray, SequenceProxy,) class HashableNumpyArrayTest(unittest.TestCase): @@ -36,101 +34,3 @@ def test_sequence_proxy(self): with self.assertRaises(TypeError): p[1] = 7 - - -class FrozenDictTests(unittest.TestCase): - FrozenDictType = _FrozenDictByWrapping - - """This class can test general non mutable mappings""" - def setUp(self) -> None: - self.d = {'a': 1, 'b': 2} - self.f = self.FrozenDictType(self.d) - self.prev_state = dict(self.f) - - def tearDown(self) -> None: - self.assertEqual(self.prev_state, dict(self.f)) - - def test_init(self): - d = {'a': 1, 'b': 2} - - f1 = self.FrozenDictType(d) - f2 = self.FrozenDictType(**d) - f3 = self.FrozenDictType(d.items()) - - self.assertEqual(d, f1) - self.assertEqual(d, f2) - self.assertEqual(d, f3) - - self.assertEqual(d.keys(), f1.keys()) - self.assertEqual(d.keys(), f2.keys()) - self.assertEqual(d.keys(), f3.keys()) - - self.assertEqual(set(d.items()), set(f1.items())) - self.assertEqual(set(d.items()), set(f2.items())) - self.assertEqual(set(d.items()), set(f3.items())) - - def test_mapping(self): - d = {'a': 1, 'b': 2} - f = self.FrozenDictType(d) - - self.assertEqual(len(d), len(f)) - self.assertIn('a', f) - self.assertIn('b', f) - self.assertNotIn('c', f) - - self.assertEqual(1, f['a']) - self.assertEqual(2, f['b']) - - with self.assertRaisesRegex(KeyError, 'c'): - _ = f['c'] - - with self.assertRaises(TypeError): - f['a'] = 9 - - with self.assertRaises(TypeError): - del f['a'] - - def test_copy(self): - d = {'a': 1, 'b': 2} - f = self.FrozenDictType(d) - self.assertIs(f, f.copy()) - - def test_eq_and_hash(self): - d = {'a': 1, 'b': 2} - - f1 = self.FrozenDictType(d) - f2 = self.FrozenDictType({'a': 1, 'b': 2}) - f3 = self.FrozenDictType({'a': 1, 'c': 3}) - - self.assertEqual(f1, f2) - self.assertEqual(hash(f1), hash(f2)) - - self.assertNotEqual(f1, f3) - - -class FrozenDictByInheritanceTests(FrozenDictTests): - FrozenDictType = _FrozenDictByInheritance - - def test_update(self): - with self.assertRaisesRegex(TypeError, 'immutable'): - self.f.update(d=5) - - def test_setdefault(self): - with self.assertRaisesRegex(TypeError, 'immutable'): - self.f.setdefault('c', 3) - with self.assertRaisesRegex(TypeError, 'immutable'): - self.f.setdefault('a', 2) - - def test_clear(self): - with self.assertRaisesRegex(TypeError, 'immutable'): - self.f.clear() - - def test_pop(self): - with self.assertRaisesRegex(TypeError, 'immutable'): - self.f.pop() - with self.assertRaisesRegex(TypeError, 'immutable'): - self.f.pop('a') - - def test_popitem(self): - with self.assertRaisesRegex(TypeError, 'immutable'): - self.f.popitem() From ed91fb1d0bcebfcfd5f257af7d302f5597abadee Mon Sep 17 00:00:00 2001 From: Nomos11 <82180697+Nomos11@users.noreply.github.com> Date: Thu, 20 Jun 2024 21:58:58 +0200 Subject: [PATCH 39/53] fix jump back in linspace --- qupulse/program/linspace.py | 2 +- tests/program/linspace_tests.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/qupulse/program/linspace.py b/qupulse/program/linspace.py index 43d01113e..c15202088 100644 --- a/qupulse/program/linspace.py +++ b/qupulse/program/linspace.py @@ -341,7 +341,7 @@ def _add_iteration_node(self, node: LinSpaceIter): self.add_node(node.body) if node.length > 1: - self.iterations[-1] = node.length + self.iterations[-1] = node.length - 1 label, jmp = self.new_loop(node.length - 1) self.commands.append(label) self.add_node(node.body) diff --git a/tests/program/linspace_tests.py b/tests/program/linspace_tests.py index 03a5b2971..60acd136c 100644 --- a/tests/program/linspace_tests.py +++ b/tests/program/linspace_tests.py @@ -74,7 +74,7 @@ def setUp(self): LoopLabel(1, 99), - Increment(0, -2.0, key_0), + Increment(0, -1.99, key_0), Increment(1, 0.02, key_1), Wait(TimeType(10 ** 6)), @@ -131,8 +131,8 @@ def setUp(self): LoopLabel(1, 99), - Increment(0, 1e-3 + -200 * 1e-2, key_0), - Increment(1, 0.02 + -200 * -3e-3, key_1), + Increment(0, 1e-3 + -199 * 1e-2, key_0), + Increment(1, 0.02 + -199 * -3e-3, key_1), Wait(TimeType(10 ** 6)), LoopLabel(2, 199), @@ -223,7 +223,7 @@ def setUp(self): Set(0, -0.4), Set(1, -0.3), Wait(TimeType(10 ** 5)), - Increment(0, -2.0, key_0), + Increment(0, -1.99, key_0), Increment(1, 0.02, key_1), Wait(TimeType(10 ** 6)), Set(0, 0.05), From 06da4f7dbe85c917d94ec24dde29393d92f7116b Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 21 Jun 2024 10:23:47 +0200 Subject: [PATCH 40/53] Add numpy to test matrix --- .github/workflows/pythontest.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pythontest.yaml b/.github/workflows/pythontest.yaml index 38cadd540..f64dfb63f 100644 --- a/.github/workflows/pythontest.yaml +++ b/.github/workflows/pythontest.yaml @@ -23,6 +23,7 @@ jobs: fail-fast: false matrix: python-version: ["3.10", "3.11", "3.12"] + numpy-version: [">=1.24,<2.0", ">=2.0"] env: INSTALL_EXTRAS: tests,plotting,zurich-instruments,tektronix,tabor-instruments @@ -42,6 +43,9 @@ jobs: python -m pip install --upgrade pip python -m pip install coverage coveralls + - name: Install numpy ${{ matrix.numpy-version }} + run: python -m pip install "numpy${{ matrix.numpy-version }}" + - name: Install package run: | python -m pip install .[${{ env.INSTALL_EXTRAS }}] From ed23e610c67c6c401d9faf3ff0cbbc5fd49ad433 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 21 Jun 2024 10:28:13 +0200 Subject: [PATCH 41/53] Execute tests on workflow changes --- .github/workflows/pythontest.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pythontest.yaml b/.github/workflows/pythontest.yaml index f64dfb63f..5b1c9c3f6 100644 --- a/.github/workflows/pythontest.yaml +++ b/.github/workflows/pythontest.yaml @@ -15,6 +15,7 @@ on: - 'tests/**' - 'setup.*' - 'pyproject.toml' + - '.github/workflows/*' jobs: test: From d70643bae7b21ce9a1b34958eb6cde3ebb901842 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 21 Jun 2024 12:15:41 +0200 Subject: [PATCH 42/53] Add linspace VM --- qupulse/program/linspace.py | 69 +++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/qupulse/program/linspace.py b/qupulse/program/linspace.py index 43d01113e..ec1f790ac 100644 --- a/qupulse/program/linspace.py +++ b/qupulse/program/linspace.py @@ -412,3 +412,72 @@ def to_increment_commands(linspace_nodes: Sequence[LinSpaceNode]) -> List[Comman state.add_node(linspace_nodes) return state.commands + +class LinSpaceVM: + def __init__(self, channels: int): + self.current_values = [np.nan] * channels + self.time = TimeType(0) + self.registers = tuple({} for _ in range(channels)) + + self.history: List[Tuple[TimeType, Tuple[float, ...]]] = [] + + self.commands = None + self.label_targets = None + self.label_counts = None + self.current_command = None + + def change_state(self, cmd: Union[Set, Increment, Wait, Play]): + if isinstance(cmd, Play): + raise NotImplementedError("TODO: Implement arbitrary waveform simulation") + elif isinstance(cmd, Wait): + self.history.append( + (self.time, self.current_values.copy()) + ) + self.time += cmd.duration + elif isinstance(cmd, Set): + self.current_values[cmd.channel] = cmd.value + self.registers[cmd.channel][cmd.key] = cmd.value + elif isinstance(cmd, Increment): + value = self.registers[cmd.channel][cmd.dependency_key] + value += cmd.value + self.registers[cmd.channel][cmd.dependency_key] = value + self.current_values[cmd.channel] = value + else: + raise NotImplementedError(cmd) + + def set_commands(self, commands: Sequence[Command]): + self.commands = [] + self.label_targets = {} + self.label_counts = {} + self.current_command = None + + for cmd in commands: + self.commands.append(cmd) + if isinstance(cmd, LoopLabel): + # a loop label signifies a reset count followed by the actual label that targets the following command + assert cmd.idx not in self.label_targets + self.label_targets[cmd.idx] = len(self.commands) + + self.current_command = 0 + + def step(self): + cmd = self.commands[self.current_command] + if isinstance(cmd, LoopJmp): + if self.label_counts[cmd.idx] > 0: + self.label_counts[cmd.idx] -= 1 + self.current_command = self.label_targets[cmd.idx] + else: + # ignore jump + self.current_command += 1 + elif isinstance(cmd, LoopLabel): + self.label_counts[cmd.idx] = cmd.count + self.current_command += 1 + else: + self.change_state(cmd) + self.current_command += 1 + + def run(self): + while self.current_command < len(self.commands): + self.step() + + From 025ba8a0d14c48d556f8488379f931c040bf9301 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 21 Jun 2024 12:15:59 +0200 Subject: [PATCH 43/53] Add test that fails due to known bug --- tests/program/linspace_tests.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/program/linspace_tests.py b/tests/program/linspace_tests.py index 03a5b2971..4c2dc59ed 100644 --- a/tests/program/linspace_tests.py +++ b/tests/program/linspace_tests.py @@ -32,6 +32,10 @@ def setUp(self): LoopJmp(0) ] + self.output = [ + (TimeType(10**6 * idx), [sum([-1.0] + [0.01] * idx)]) for idx in range(200) + ] + def test_program(self): program_builder = LinSpaceBuilder(('a',)) program = self.pulse_template.create_program(program_builder=program_builder) @@ -41,6 +45,12 @@ def test_commands(self): commands = to_increment_commands([self.program]) self.assertEqual(self.commands, commands) + def test_output(self): + vm = LinSpaceVM(1) + vm.set_commands(commands=self.commands) + vm.run() + self.assertEqual(self.output, vm.history) + class PlainCSDTest(TestCase): def setUp(self): From 6aa2e03a718073ac90afe7f92f7a649d2b7b4f17 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 21 Jun 2024 13:04:51 +0200 Subject: [PATCH 44/53] Fix VM loop count handling --- qupulse/program/linspace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qupulse/program/linspace.py b/qupulse/program/linspace.py index 3ddc5a713..600a6f82b 100644 --- a/qupulse/program/linspace.py +++ b/qupulse/program/linspace.py @@ -470,7 +470,7 @@ def step(self): # ignore jump self.current_command += 1 elif isinstance(cmd, LoopLabel): - self.label_counts[cmd.idx] = cmd.count + self.label_counts[cmd.idx] = cmd.count - 1 self.current_command += 1 else: self.change_state(cmd) From e598e8c054e3587926d68659960a377a909601dc Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 21 Jun 2024 13:05:42 +0200 Subject: [PATCH 45/53] Add working VM tests --- tests/program/linspace_tests.py | 58 +++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/tests/program/linspace_tests.py b/tests/program/linspace_tests.py index a68f62ecc..604f82378 100644 --- a/tests/program/linspace_tests.py +++ b/tests/program/linspace_tests.py @@ -6,6 +6,16 @@ from qupulse.program.linspace import * from qupulse.program.transformation import * + +def assert_vm_output_almost_equal(test: TestCase, expected, actual): + test.assertEqual(len(expected), len(actual)) + for idx, ((t_e, vals_e), (t_a, vals_a)) in enumerate(zip(expected, actual)): + test.assertEqual(t_e, t_a, f"Differing times in {idx} element") + test.assertEqual(len(vals_e), len(vals_a), f"Differing channel count in {idx} element") + for ch, (val_e, val_a) in enumerate(zip(vals_e, vals_a)): + test.assertAlmostEqual(val_e, val_a, msg=f"Differing values in {idx} element channel {ch}") + + class SingleRampTest(TestCase): def setUp(self): hold = ConstantPT(10 ** 6, {'a': '-1. + idx * 0.01'}) @@ -50,6 +60,7 @@ def test_output(self): vm.set_commands(commands=self.commands) vm.run() self.assertEqual(self.output, vm.history) + assert_vm_output_almost_equal(self, self.output, vm.history) class PlainCSDTest(TestCase): @@ -96,6 +107,16 @@ def setUp(self): LoopJmp(1), ] + a_values = [sum([-1.] + [0.01] * i) for i in range(200)] + b_values = [sum([-.5] + [0.02] * j) for j in range(100)] + + self.output = [ + ( + TimeType(10 ** 6 * (i + 200 * j)), + [a_values[i], b_values[j]] + ) for j in range(100) for i in range(200) + ] + def test_program(self): program_builder = LinSpaceBuilder(('a', 'b')) program = self.pulse_template.create_program(program_builder=program_builder) @@ -105,13 +126,20 @@ def test_increment_commands(self): commands = to_increment_commands([self.program]) self.assertEqual(self.commands, commands) + def test_output(self): + vm = LinSpaceVM(2) + vm.set_commands(self.commands) + vm.run() + assert_vm_output_almost_equal(self, self.output, vm.history) + class TiltedCSDTest(TestCase): def setUp(self): + repetition_count = 3 hold = ConstantPT(10**6, {'a': '-1. + idx_a * 0.01 + idx_b * 1e-3', 'b': '-.5 + idx_b * 0.02 - 3e-3 * idx_a'}) scan_a = hold.with_iteration('idx_a', 200) self.pulse_template = scan_a.with_iteration('idx_b', 100) - self.repeated_pt = self.pulse_template.with_repetition(42) + self.repeated_pt = self.pulse_template.with_repetition(repetition_count) self.program = LinSpaceIter(length=100, body=(LinSpaceIter( length=200, @@ -123,7 +151,7 @@ def setUp(self): duration_factors=None ),) ),)) - self.repeated_program = LinSpaceRepeat(body=(self.program,), count=42) + self.repeated_program = LinSpaceRepeat(body=(self.program,), count=repetition_count) key_0 = DepKey.from_voltages((1e-3, 0.01,), DEFAULT_INCREMENT_RESOLUTION) key_1 = DepKey.from_voltages((0.02, -3e-3), DEFAULT_INCREMENT_RESOLUTION) @@ -157,7 +185,19 @@ def setUp(self): for cmd in inner_commands: if hasattr(cmd, 'idx'): cmd.idx += 1 - self.repeated_commands = [LoopLabel(0, 42)] + inner_commands + [LoopJmp(0)] + self.repeated_commands = [LoopLabel(0, repetition_count)] + inner_commands + [LoopJmp(0)] + + self.output = [ + ( + TimeType(10 ** 6 * (i + 200 * j)), + [-1. + i * 0.01 + j * 1e-3, -.5 + j * 0.02 - 3e-3 * i] + ) for j in range(100) for i in range(200) + ] + self.repeated_output = [ + (t + TimeType(10**6) * (n * 100 * 200), vals) + for n in range(repetition_count) + for t, vals in self.output + ] def test_program(self): program_builder = LinSpaceBuilder(('a', 'b')) @@ -177,6 +217,18 @@ def test_repeated_increment_commands(self): commands = to_increment_commands([self.repeated_program]) self.assertEqual(self.repeated_commands, commands) + def test_output(self): + vm = LinSpaceVM(2) + vm.set_commands(self.commands) + vm.run() + assert_vm_output_almost_equal(self, self.output, vm.history) + + def test_repeated_output(self): + vm = LinSpaceVM(2) + vm.set_commands(self.repeated_commands) + vm.run() + assert_vm_output_almost_equal(self, self.repeated_output, vm.history) + class SingletLoadProcessing(TestCase): def setUp(self): From e2801ffa3c316b2949e07a7078726954b5d59747 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Fri, 21 Jun 2024 13:11:09 +0200 Subject: [PATCH 46/53] Add singlet reload test --- tests/program/linspace_tests.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/tests/program/linspace_tests.py b/tests/program/linspace_tests.py index 604f82378..23d050ac2 100644 --- a/tests/program/linspace_tests.py +++ b/tests/program/linspace_tests.py @@ -8,6 +8,7 @@ def assert_vm_output_almost_equal(test: TestCase, expected, actual): + """Compare two vm outputs with default TestCase.assertAlmostEqual accuracy""" test.assertEqual(len(expected), len(actual)) for idx, ((t_e, vals_e), (t_a, vals_a)) in enumerate(zip(expected, actual)): test.assertEqual(t_e, t_a, f"Differing times in {idx} element") @@ -59,7 +60,6 @@ def test_output(self): vm = LinSpaceVM(1) vm.set_commands(commands=self.commands) vm.run() - self.assertEqual(self.output, vm.history) assert_vm_output_almost_equal(self, self.output, vm.history) @@ -309,6 +309,23 @@ def setUp(self): LoopJmp(1), ] + self.output = [] + time = TimeType(0) + for idx_b in range(100): + for idx_a in range(200): + self.output.append( + (time, [-.4, -.3]) + ) + time += 10 ** 5 + self.output.append( + (time, [-1. + idx_a * 0.01, -.5 + idx_b * 0.02]) + ) + time += 10 ** 6 + self.output.append( + (time, [0.05, 0.06]) + ) + time += 10 ** 5 + def test_singlet_scan_program(self): program_builder = LinSpaceBuilder(('a', 'b')) program = self.pulse_template.create_program(program_builder=program_builder) @@ -318,6 +335,12 @@ def test_singlet_scan_commands(self): commands = to_increment_commands([self.program]) self.assertEqual(self.commands, commands) + def test_singlet_scan_output(self): + vm = LinSpaceVM(2) + vm.set_commands(self.commands) + vm.run() + assert_vm_output_almost_equal(self, self.output, vm.history) + class TransformedRampTest(TestCase): def setUp(self): From 62c61f512e8b02add33535788652697cf437150a Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 1 Jul 2024 17:57:25 +0200 Subject: [PATCH 47/53] Improve arithmetic atomic pt warning level --- qupulse/pulses/arithmetic_pulse_template.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qupulse/pulses/arithmetic_pulse_template.py b/qupulse/pulses/arithmetic_pulse_template.py index 19b9b45d2..727b6456c 100644 --- a/qupulse/pulses/arithmetic_pulse_template.py +++ b/qupulse/pulses/arithmetic_pulse_template.py @@ -70,11 +70,13 @@ def __init__(self, "If they evaluate to different values on instantiation this will result in an error. " "(%r != %r) for ALL inputs " "(it may be unequal only for fringe cases)" % (lhs.duration, rhs.duration), + stacklevel=2, category=UnequalDurationWarningInArithmeticPT) if not silent_atomic and not (lhs._is_atomic() and rhs._is_atomic()): warnings.warn("ArithmeticAtomicPulseTemplate treats all operands as if they are atomic. " "You can silence this warning by passing `silent_atomic=True` or by ignoring this category.", + stacklevel=2, category=ImplicitAtomicityInArithmeticPT) self._lhs = lhs From 418e0cd2ab5fa9d8b1839a55d9c890796cd3d92a Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 1 Jul 2024 17:57:56 +0200 Subject: [PATCH 48/53] Add clean notebook command --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 32f04eb74..89edff880 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -111,6 +111,7 @@ html = """ clean= """ python -c "import shutil; shutil.rmtree('doc/build')" """ +clean-notebooks = "jupyter nbconvert --ClearOutputPreprocessor.enabled=True --ClearMetadataPreprocessor.enabled=True --to=notebook --inplace --log-level=ERROR doc/source/examples/*.ipynb" [tool.hatch.envs.changelog] detached = true From 3e4cee6e367c5e71681430e76dcbe0d8823da7e5 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 1 Jul 2024 18:13:20 +0200 Subject: [PATCH 49/53] Add failing test --- .../time_reversal_pulse_template_tests.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/pulses/time_reversal_pulse_template_tests.py b/tests/pulses/time_reversal_pulse_template_tests.py index 0ded84236..ad012e5f8 100644 --- a/tests/pulses/time_reversal_pulse_template_tests.py +++ b/tests/pulses/time_reversal_pulse_template_tests.py @@ -1,5 +1,9 @@ import unittest +import numpy as np + +from qupulse.pulses import ConstantPT, FunctionPT +from qupulse.plotting import render from qupulse.pulses.time_reversal_pulse_template import TimeReversalPulseTemplate from qupulse.utils.types import TimeType from qupulse.expressions import ExpressionScalar @@ -25,6 +29,19 @@ def test_simple_properties(self): self.assertEqual(reversed_pt.identifier, 'reverse') + def test_time_reversal_program(self): + inner = ConstantPT(4, {'a': 3}) @ FunctionPT('sin(t)', 5, channel='a') + manual_reverse = FunctionPT('sin(5 - t)', 5, channel='a') @ ConstantPT(4, {'a': 3}) + time_reversed = TimeReversalPulseTemplate(inner) + + program = time_reversed.create_program() + manual_program = manual_reverse.create_program() + + t, data, _ = render(program, 9 / 10) + _, manual_data, _ = render(manual_program, 9 / 10) + + np.testing.assert_allclose(data['a'], manual_data['a']) + class TimeReversalPulseTemplateSerializationTests(unittest.TestCase, SerializableTests): @property From 2fd223e8c12fc90b9b3f60a9039dc42ac5192019 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 1 Jul 2024 18:24:56 +0200 Subject: [PATCH 50/53] Add time_reversed to LoopBuilder --- qupulse/program/__init__.py | 3 +++ qupulse/program/loop.py | 10 ++++++++++ qupulse/program/waveforms.py | 2 +- qupulse/pulses/time_reversal_pulse_template.py | 11 ++++------- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/qupulse/program/__init__.py b/qupulse/program/__init__.py index cd578dd5c..63dc4f60e 100644 --- a/qupulse/program/__init__.py +++ b/qupulse/program/__init__.py @@ -164,6 +164,9 @@ def with_iteration(self, index_name: str, rng: range, measurements: Optional[Sequence[MeasurementWindow]] = None) -> Iterable['ProgramBuilder']: pass + def time_reversed(self) -> ContextManager['ProgramBuilder']: + pass + def to_program(self) -> Optional[Program]: """Further addition of new elements might fail after finalizing the program.""" diff --git a/qupulse/program/loop.py b/qupulse/program/loop.py index 0e5dccc3e..9e59f9d32 100644 --- a/qupulse/program/loop.py +++ b/qupulse/program/loop.py @@ -817,6 +817,16 @@ def with_iteration(self, index_name: str, rng: range, top_frame.iterating = (index_name, value) yield self + @contextmanager + def time_reversed(self) -> ContextManager['LoopBuilder']: + inner_builder = LoopBuilder() + yield inner_builder + inner_program = inner_builder.to_program() + + if inner_program: + inner_program.reverse_inplace() + self._try_append(inner_program, None) + @contextmanager def with_sequence(self, measurements: Optional[Sequence[MeasurementWindow]] = None) -> ContextManager['ProgramBuilder']: top_frame = StackFrame(LoopGuard(self._top, measurements), None) diff --git a/qupulse/program/waveforms.py b/qupulse/program/waveforms.py index 08b544115..1e35bc1b1 100644 --- a/qupulse/program/waveforms.py +++ b/qupulse/program/waveforms.py @@ -1257,7 +1257,7 @@ def unsafe_sample(self, channel: ChannelID, sample_times: np.ndarray, else: inner_output_array = output_array[::-1] inner_output_array = self._inner.unsafe_sample(channel, inner_sample_times, output_array=inner_output_array) - if inner_output_array.base not in (output_array, output_array.base): + if id(inner_output_array.base) not in (id(output_array), id(output_array.base)): # TODO: is there a guarantee by numpy we never end up here? output_array[:] = inner_output_array[::-1] return output_array diff --git a/qupulse/pulses/time_reversal_pulse_template.py b/qupulse/pulses/time_reversal_pulse_template.py index 5dc9fcabd..47bec2322 100644 --- a/qupulse/pulses/time_reversal_pulse_template.py +++ b/qupulse/pulses/time_reversal_pulse_template.py @@ -5,7 +5,7 @@ from typing import Optional, Set, Dict, Union from qupulse import ChannelID -from qupulse.program.loop import Loop +from qupulse.program import ProgramBuilder from qupulse.program.waveforms import Waveform from qupulse.serialization import PulseRegistryType from qupulse.expressions import ExpressionScalar @@ -50,12 +50,9 @@ def defined_channels(self) -> Set['ChannelID']: def integral(self) -> Dict[ChannelID, ExpressionScalar]: return self._inner.integral - def _internal_create_program(self, *, parent_loop: Loop, **kwargs) -> None: - inner_loop = Loop() - self._inner._internal_create_program(parent_loop=inner_loop, **kwargs) - inner_loop.reverse_inplace() - - parent_loop.append_child(inner_loop) + def _internal_create_program(self, *, program_builder: ProgramBuilder, **kwargs) -> None: + with program_builder.time_reversed() as reversed_builder: + self._inner._internal_create_program(program_builder=reversed_builder, **kwargs) def build_waveform(self, *args, **kwargs) -> Optional[Waveform]: From 54a7921e1377c1e2e738ef34db25a67d6d153d34 Mon Sep 17 00:00:00 2001 From: Simon Humpohl Date: Mon, 1 Jul 2024 21:46:01 +0200 Subject: [PATCH 51/53] Clean execution state of nearly all notebooks --- .../examples/00AbstractPulseTemplate.ipynb | 24 +- .../examples/00AdvancedTablePulse.ipynb | 2387 +--------- .../00ArithmeticWithPulseTemplates.ipynb | 193 +- doc/source/examples/00ComposedPulses.ipynb | 3953 +--------------- .../examples/00ConstantPulseTemplate.ipynb | 22 +- doc/source/examples/00FunctionPulse.ipynb | 1602 +------ doc/source/examples/00MappingTemplate.ipynb | 818 +--- .../examples/00MultiChannelTemplates.ipynb | 2433 +--------- doc/source/examples/00PointPulse.ipynb | 803 +--- ...RetrospectiveConstantChannelAddition.ipynb | 808 +--- doc/source/examples/00SimpleTablePulse.ipynb | 2377 +--------- doc/source/examples/00TimeReversal.ipynb | 111 +- doc/source/examples/01Measurements.ipynb | 20 +- .../examples/01ParameterConstraints.ipynb | 811 +--- doc/source/examples/01PulseStorage.ipynb | 27 +- doc/source/examples/02CreatePrograms.ipynb | 58 +- .../03DynamicNuclearPolarisation.ipynb | 52 +- .../03FreeInductionDecayExample.ipynb | 1638 +------ .../examples/03GateConfigurationExample.ipynb | 3957 +---------------- doc/source/examples/03SnakeChargeScan.ipynb | 80 +- .../examples/04ZurichInstrumentsSetup.ipynb | 225 +- 21 files changed, 399 insertions(+), 22000 deletions(-) diff --git a/doc/source/examples/00AbstractPulseTemplate.ipynb b/doc/source/examples/00AbstractPulseTemplate.ipynb index 050e81f91..7c2899b9e 100644 --- a/doc/source/examples/00AbstractPulseTemplate.ipynb +++ b/doc/source/examples/00AbstractPulseTemplate.ipynb @@ -14,9 +14,7 @@ { "cell_type": "code", "execution_count": 1, - "metadata": { - "scrolled": true - }, + "metadata": {}, "outputs": [], "source": [ "from qupulse.pulses import AbstractPT, FunctionPT, AtomicMultiChannelPT, PointPT\n", @@ -46,7 +44,7 @@ "output_type": "stream", "text": [ "The integral has been declared so we can get it\n", - "{'Y': Expression('a*b + sin(t_manip)'), 'X': Expression('t_init - cos(t_manip) + 2')}\n", + "{'X': ExpressionScalar('t_init/2 - cos(t_manip) + 2'), 'Y': ExpressionScalar('a*b + t_init/2 + sin(t_manip)')}\n", "\n", "We get an error that for the pulse \"readout\" the property \"duration\" was not specified:\n", "NotSpecifiedError('readout', 'duration')\n" @@ -84,7 +82,7 @@ "text": [ "With wrong integral value:\n", "RuntimeError('Cannot link to target. Wrong value of property \"integral\"')\n", - "the linking worked. The new experiment has now a defined duration of Expression('t_init + t_manip + t_read') .\n" + "the linking worked. The new experiment has now a defined duration of ExpressionScalar('t_init + t_manip + t_read') .\n" ] } ], @@ -107,22 +105,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.2" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/00AdvancedTablePulse.ipynb b/doc/source/examples/00AdvancedTablePulse.ipynb index de87a5d57..1ea295c7b 100644 --- a/doc/source/examples/00AdvancedTablePulse.ipynb +++ b/doc/source/examples/00AdvancedTablePulse.ipynb @@ -18,797 +18,13 @@ { "cell_type": "code", "execution_count": 1, - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], + "image/png": "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0KBBqlfP+XpFfn6+fagoNDRULVq00FNPPaUpU6a4Nd4L2QxXJo1bTH5+vmJjY5WXl6eYmBizwwEAuOinn37SgQMH1KpVK4WFhZkdDtzoYv+2rnx+M/QDAAAsi0QFAABYFokKAACwLJppAX9lGFJpYcXz4AjplzUcAMCXkKgA/sgwpLcGSkc2V2wnXyndvZJkBYDPYegH8EelheeSFEk6skkqOFGRwACADyFRAQLF/BTprUEkKwB8CokK4O8S0s89p7ICwMeQqAD+LmOlNHn/uW0qK4DHHTx4UDabTdu3bzc7FKf06dNHEyZMMDsMh0hUAH9ns0mR8RUNtZWorACohaKiIsXFxSk+Pl7FxcVeeU8SFSAQ2GwVs36orACog+XLl6tDhw5KS0vTBx984JX3JFEBAgWVFcCtysvLNW/ePKWkpCg0NFTNmzfXrFmzqhzz7bff6vrrr1dERIQ6d+6sjRs32l87efKkRowYoWbNmikiIkLp6elaunRpla/v06ePxo8fr0cffVRxcXFKSEjQE088UeUYm82mN954Q7feeqsiIiKUmpqqDz/8sMoxu3bt0uDBgxUVFaWmTZtq1KhROnHihMvf85tvvqmRI0dq5MiRLt0pui5IVIBAQmUFvsAwpJICcx4u/B5MnTpVf/zjHzV9+nTt3r1b7777rpo2bVrlmMcff1yTJ0/W9u3b1bZtW40YMUI///yzpIqb9nXr1k0fffSRdu3apfvvv1+jRo3SF198UeUcixcvVmRkpDZv3qx58+bpqaee0urVq6sc8+STT2rYsGHasWOHbrjhBt155506deqUJOn06dPq27evunTpoq1bt2rlypU6duyYhg0b5tI/S3Z2tjZu3Khhw4Zp2LBhWrdunQ4dOuTSOWqDuycD/qikQJqdVPH8saNSSGTV1w2jIjk5suncvsn7KyouLAoHL3J4h93zf369zdHviwNnzpxR48aNtXDhQt17773VXj948KBatWqlN954Q/fcc48kaffu3erQoYP27NmjtLQ0h+e96aablJaWpvnz50uqqKiUlZVp3bp19mN69uypvn376o9//KOkiorKtGnT9PTTT0uSCgoKFBUVpY8//liDBg3SM888o3Xr1mnVqlX2c3z33XdKTk7W3r171bZtW/Xp00dXXHGFFixYUOP3/Pjjj2v37t1asWKFJGno0KG64oor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", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -1668,9 +99,7 @@ { "cell_type": "code", "execution_count": 3, - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -1681,791 +110,9 @@ }, { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAGwCAYAAABFFQqPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3fUlEQVR4nO3dfVxUZf7/8feAOIDAKCkCird4f0OY2qKWN5mmLq27rbqWgqlttmip3RjV2tpusrqaXys3t9LMXVtNTWu7M/IG0kXTkk2zNBXFXNDUBAEXFc7vjx7MLxJwBmcYhvN6Ph7zeDBnrnPmc3EaeXeu6zpjMQzDEAAAgAn5eLoAAAAATyEIAQAA0yIIAQAA0yIIAQAA0yIIAQAA0yIIAQAA0yIIAQAA06rn6QJqWmlpqf773/8qODhYFovF0+UAAAAHGIahCxcuKDIyUj4+rruOY7og9N///ldRUVGeLgMAAFTDiRMn1Lx5c5cdz3RBKDg4WNIPv8iQkBAPVwMAAByRn5+vqKgo+99xVzFdECobDgsJCSEIAQDgZVw9rYXJ0gAAwLQIQgAAwLQIQgAAwLRMN0fIUSUlJbp8+bKny4AL+Pn5ydfX19NlAABqIYLQTxiGodzcXJ0/f97TpcCFGjZsqPDwcO4dBQAohyD0E2UhKCwsTIGBgfzh9HKGYaioqEinT5+WJEVERHi4IgBAbUIQ+pGSkhJ7CLrhhhs8XQ5cJCAgQJJ0+vRphYWFMUwGALBjsvSPlM0JCgwM9HAlcLWyc8q8LwDAjxGEKsBwWN3DOQUAVIQgBAAATIsgBAAATIsgZALHjh2TxWJRZmamp0txyIABAzR9+nRPlwEAMAGCELzWxYsXFRoaqsaNG6u4uNjT5QAAvBBBCF5r/fr16tKlizp27KiNGzd6uhwAgBciCF2DYRgqunTFIw/DMByus7S0VPPnz1d0dLSsVqtatGihZ599tlybo0ePauDAgQoMDFRMTIwyMjLsr509e1Zjx45Vs2bNFBgYqG7duumf//xnuf0HDBigBx98UI899phCQ0MVHh6uP/zhD+XaWCwWvfrqq/rlL3+pwMBAtWvXTu+88065Nvv379ewYcMUFBSkpk2bavz48Tpz5ozDfS2zbNkyjRs3TuPGjdOyZcuc3h8AAG6oeA0XL5eo8+xNHnnvA88MVWB9x05RcnKyXnnlFS1atEj9+vVTTk6Ovv7663JtnnzySS1YsEDt2rXTk08+qbFjx+rw4cOqV6+e/ve//+mmm27SrFmzFBISovfee0/jx49X27Zt1bt3b/sxXn/9dc2cOVO7du1SRkaGJkyYoL59++r222+3t5kzZ47mz5+vv/zlL3rhhRd0zz336Pjx4woNDdX58+c1aNAgTZ48WYsWLdLFixc1a9YsjR49Wlu2bHH4d3PkyBFlZGTorbfekmEYmjFjho4fP66WLVs6fAwAALgiVAdcuHBBixcv1vz585WYmKi2bduqX79+mjx5crl2jzzyiEaMGKH27dtrzpw5On78uA4fPixJatasmR555BHdeOONatOmjaZNm6Y77rhDb775ZrljdO/eXU8//bTatWunhIQE9ezZU5s3by7XZsKECRo7dqyio6M1d+5cFRQU6NNPP5Ukvfjii4qNjdXcuXPVsWNHxcbGavny5dq6dasOHTrkcJ+XL1+uYcOGqVGjRgoNDdXQoUP12muvVefXBwAwMa4IXUOAn68OPDPUY+/tiK+++krFxcW67bbbqmzXvXt3+89l37l1+vRpdezYUSUlJZo7d67efPNNnTx5UpcuXVJxcfFVd9n+8THKjlP2PV4VtWnQoIFCQkLsbf7zn/9o69atCgoKuqq+I0eOqH379tfsb0lJiV5//XUtXrzYvm3cuHF65JFHNHv2bPn4kO8BAI4hCF2DxWJxeHjKU8q+S+ta/Pz87D+X3Wm5tLRUkvSXv/xFixcv1v/93/+pW7duatCggaZPn65Lly5Veoyy45Qdw5E2BQUFio+P17x5866qz9EvRN20aZNOnjypMWPGlNteUlKizZs3lxumAwCgKrX7Lzwc0q5dOwUEBGjz5s1XDYc5aseOHfrFL36hcePGSfohIB06dEidO3d2Zanq0aOH1q9fr1atWqlever957ds2TL95je/0ZNPPllu+7PPPqtly5YRhAAADmMMoQ7w9/fXrFmz9Nhjj2nlypU6cuSIdu7c6dRKqnbt2ik1NVX//ve/9dVXX+n+++/XqVOnXF5rUlKSzp07p7Fjx2r37t06cuSINm3apHvvvVclJSXX3P+7777Tv/71LyUmJqpr167lHgkJCdq4caPOnTvn8roBAHUTQaiO+P3vf6+HH35Ys2fPVqdOnTRmzJir5u5U5amnnlKPHj00dOhQDRgwQOHh4Ro5cqTL64yMjNSOHTtUUlKiIUOGqFu3bpo+fboaNmzo0NyelStXqkGDBhXOh7rtttsUEBCgf/zjHy6vGwBQN1kMZ25WUwfk5+fLZrMpLy9PISEh5V773//+p6ysLLVu3Vr+/v4eqhDuwLkFAO9W1d/v68EVIQAAYFoeDUIpKSnq1auXgoODFRYWppEjR+rgwYMO77969WpZLBa3DOEAAIC6z6NBKC0tTUlJSdq5c6dSU1N1+fJlDRkyRIWFhdfc99ixY3rkkUd0yy231EClAACgLvLo8vkPP/yw3PMVK1YoLCxMn332mW699dZK9yspKdE999yjOXPm6JNPPtH58+ddWpfJpk2ZgtnOqWEYunj52qvwAHivAD9f+z3hUH216j5CeXl5kqTQ0NAq2z3zzDMKCwvTpEmT9Mknn1TZtri4WMXFxfbn+fn5lbYtuxFgUVGRwzcphHcoKiqSdPXNHusiwzD066UZ+uz4954uBYAbOfN9lKhcrfkNlpaWavr06erbt6+6du1aabvt27dr2bJlyszMdOi4KSkpmjNnjkNtfX191bBhQ/uy88DAQNK2lzMMQ0VFRTp9+rQaNmwoX1/HvrbEm128XEIIAgAH1ZoglJSUpP3792v79u2Vtrlw4YLGjx+vV155RY0bN3bouMnJyZo5c6b9eX5+vqKioiptHx4eLklO3YMHtV/Dhg3t59ZM9jw1WIH16374A8zI0e+jRNVqRRCaOnWq3n33XaWnp6t58+aVtjty5IiOHTum+Ph4+7ay77CqV6+eDh48qLZt25bbx2q1ymq1OlyLxWJRRESEwsLCdPnyZSd7gtrIz8/PFFeCKhJY35dL5wBQBY/+C2kYhqZNm6YNGzZo27Ztat26dZXtO3bsqH379pXb9tRTT+nChQtavHhxlVd6nOXr62vaP54AAJiFR4NQUlKS3njjDb399tsKDg5Wbm6uJMlms9knKyckJKhZs2ZKSUmRv7//VfOHGjZsKElVzisCAACoiEeD0EsvvSRJGjBgQLntr732miZMmCBJys7Odug7qAAAAJzl8aGxa9m2bVuVr69YscI1xQAAANPhUgsAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtghAAADAtjwahlJQU9erVS8HBwQoLC9PIkSN18ODBKvd55ZVXdMstt6hRo0Zq1KiRBg8erE8//bSGKgYAAHWJR4NQWlqakpKStHPnTqWmpury5csaMmSICgsLK91n27ZtGjt2rLZu3aqMjAxFRUVpyJAhOnnyZA1WDgAA6gKLYRiGp4so89133yksLExpaWm69dZbHdqnpKREjRo10osvvqiEhIRrts/Pz5fNZlNeXp5CQkKut2Sg1im6dEWdZ2+SJB14ZqgC69fzcEUAcP3c9fe7Vv0LmZeXJ0kKDQ11eJ+ioiJdvny50n2Ki4tVXFxsf56fn399RQIAgDqj1kyWLi0t1fTp09W3b1917drV4f1mzZqlyMhIDR48uMLXU1JSZLPZ7I+oqChXlQwAALxcrQlCSUlJ2r9/v1avXu3wPn/+85+1evVqbdiwQf7+/hW2SU5OVl5env1x4sQJV5UMAAC8XK0YGps6dareffddpaenq3nz5g7ts2DBAv35z3/Wxx9/rO7du1fazmq1ymq1uqpUAABQh3g0CBmGoWnTpmnDhg3atm2bWrdu7dB+8+fP17PPPqtNmzapZ8+ebq4SAADUVR4NQklJSXrjjTf09ttvKzg4WLm5uZIkm82mgIAASVJCQoKaNWumlJQUSdK8efM0e/ZsvfHGG2rVqpV9n6CgIAUFBXmmIwAAwCt5dI7QSy+9pLy8PA0YMEARERH2x5o1a+xtsrOzlZOTU26fS5cu6de//nW5fRYsWOCJLgAAAC/m8aGxa9m2bVu558eOHXNPMQAAwHRqzaoxAACAmkYQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQAgAApkUQ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ALiB00Fo2bJlCg0N1U033SSr1Sqr1aqePXsqNDRUy5YtkyQFBQVp4cKFLi8WAADAlZyeIxQeHq7U1FR9/fXXOnTokCSpQ4cO6tChg73NwIEDXVchAACAm1T7hoodO3ZUx44dXVkLAABAjapWEPr222/1zjvvKDs7W5cuXSr32nPPPeeSwgAAANzN6SC0efNm3XnnnWrTpo2+/vprde3aVceOHZNhGOrRo4c7agQAAHALpydLJycn65FHHtG+ffvk7++v9evX68SJE+rfv79GjRrljhoBAADcwukg9NVXXykhIUGSVK9ePV28eFFBQUF65plnNG/ePKeOlZ6ervj4eEVGRspisWjjxo3X3Ke4uFhPPvmkWrZsKavVqlatWmn58uXOdgMAAMD5obEGDRrY5wVFREToyJEj6tKliyTpzJkzTh2rsLBQMTExmjhxon71q185tM/o0aN16tQpLVu2TNHR0crJyVFpaalznQAAAFA1gtDPfvYzbd++XZ06ddLw4cP18MMPa9++fXrrrbf0s5/9zKljDRs2TMOGDXO4/Ycffqi0tDQdPXpUoaGhkqRWrVo59Z4AAABlnB4ae+6553TzzTdLkubMmaPbbrtNa9asUatWrew3VHSXd955Rz179tT8+fPVrFkztW/fXo888oguXrxY6T7FxcXKz88v9wAAAJCqcUWoTZs29p8bNGigpUuXurSgqhw9elTbt2+Xv7+/NmzYoDNnzuh3v/udzp49q9dee63CfVJSUjRnzpwaqxEAAHgPp68ItWnTRmfPnr1q+/nz58uFJHcoLS2VxWLRqlWr1Lt3bw0fPlzPPfecXn/99UqvCiUnJysvL8/+OHHihFtrBAAA3sPpK0LHjh1TSUnJVduLi4t18uRJlxRVmYiICDVr1kw2m82+rVOnTjIMQ99++63atWt31T5l34cGAADwUw4HoXfeecf+86ZNm8qFkZKSEm3evNntE5f79u2rtWvXqqCgQEFBQZKkQ4cOycfHR82bN3frewMAgLrH4SA0cuRISZLFYlFiYmK51/z8/NSqVSunv3G+oKBAhw8ftj/PyspSZmamQkND1aJFCyUnJ+vkyZNauXKlJOnuu+/WH//4R917772aM2eOzpw5o0cffVQTJ05UQECAU+8NAADgcBAqu1dP69attXv3bjVu3Pi633zPnj3lvql+5syZkqTE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", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -851,11 +81,9 @@ }, { "data": { - "text/html": [ - "" - ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAGwCAYAAABFFQqPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA+lElEQVR4nO3dfVhUdf7/8dcMCCgCSYhAoWKa5k2GYUVSWpHmXev+WjW3JCvbNNTMbtn8arSlq5v1LXPX3Vaz+9RKc7XN9S4NQ4uSTbM0lcQMvEEFARcUzu8PvzMLAjKDcz/Px3XNdcnhnJk3R5x5eT6f8/6YDMMwBAAA4IfM7i4AAADAXQhCAADAbxGEAACA3yIIAQAAv0UQAgAAfosgBAAA/BZBCAAA+K1AdxfgatXV1frll18UFhYmk8nk7nIAAIANDMPQyZMnFRcXJ7PZcddx/C4I/fLLL4qPj3d3GQAAoAkOHDigSy+91GHP53dBKCwsTNLZExkeHu7magAAgC1KSkoUHx9v/Rx3FL8LQpbhsPDwcIIQAABextHTWpgsDQAA/BZBCAAA+C2CEAAA8Ft+N0cIAOA7qqurVVlZ6e4y4CBBQUEOvTXeFgQhAIBXqqysVF5enqqrq91dChzEbDYrISFBQUFBLntNghAAwOsYhqGCggIFBAQoPj7e5VcR4HiWhscFBQVq27aty5oeE4QAAF7nzJkzKi8vV1xcnFq0aOHucuAgrVu31i+//KIzZ86oWbNmLnlNIjQAwOtUVVVJkkuHUOB8lr9Py9+vKxCEAABeizUjfYs7/j4JQgAAwG8RhAAAgN8iCAEA4AF++uknmUwm5ebmursUm/Tr10+TJ092dxkXjCAEAACc5tSpU4qMjFRUVJQqKircXU4dBCEAAOA0H374obp166YuXbpo+fLl7i6nDoIQAMDrGYah8sozbnkYhmFzndXV1Zo9e7Y6duyo4OBgtW3bVs8//3ytffbt26ebbrpJLVq0UM+ePZWdnW39XlFRkUaNGqVLLrlELVq0UI8ePfTee+/VOr5fv36aNGmSnnjiCUVGRiomJkbPPPNMrX1MJpP+/ve/69e//rVatGihTp06acWKFbX22bFjhwYOHKiWLVuqTZs2Gj16tI4ePWrzz2qxYMEC3X333br77ru1YMECu493NhoqAgC83qnTVeo6bbVbXnvnswPUIsi2j9OMjAy99tpreumll5SSkqKCggL98MMPtfZ5+umn9cILL6hTp056+umnNWrUKO3Zs0eBgYH6z3/+o6uvvlpPPvmkwsPDtWrVKo0ePVqXXXaZrrnmGutzvPHGG5oyZYq2bt2q7OxsjRkzRn369NGtt95q3SczM1OzZ8/Wn/70J82dO1d33XWX9u/fr8jISJ04cUI333yzxo4dq5deekmnTp3Sk08+qREjRmj9+vU2n5u9e/cqOztbH330kQzD0COPPKL9+/erXbt2Nj+Hs3FFCAAAFzh58qRefvllzZ49W/fcc48uu+wypaSkaOzYsbX2e+yxxzR48GBdfvnlyszM1P79+7Vnzx5J0iWXXKLHHntMV111lTp06KCJEyfqtttu05IlS2o9x5VXXqnp06erU6dOSktLU1JSktatW1drnzFjxmjUqFHq2LGjZsyYodLSUn355ZeSpFdffVWJiYmaMWOGunTposTERC1cuFAbNmzQ7t27bf6ZFy5cqIEDB6pVq1aKjIzUgAED9Prrrzfl9DkNV4QAAF6vebMA7Xx2gNte2xbff/+9KioqdMstt5x3vyuvvNL659jYWEnS4cOH1aVLF1VVVWnGjBlasmSJDh48qMrKSlVUVNRZZqTmc1ie5/Dhww3uExoaqvDwcOs+//73v7Vhwwa1bNmyTn179+7V5Zdf3ujPW1VVpTfeeEMvv/yyddvdd9+txx57TNOmTfOY9eEIQgAAr2cymWwennKX5s2b27RfzTW2LJ2Wq6urJUl/+tOf9PLLL+t///d/1aNHD4WGhmry5MmqrKxs8Dksz2N5Dlv2KS0t1dChQzVr1qw69VnCWWNWr16tgwcPauTIkbW2V1VVad26dbWG6dzJs39rAADwEZ06dVLz5s21bt26OsNhttq8ebN+9atf6e6775Z0NiDt3r1bXbt2dWSp6tWrlz788EO1b99egYFNiwoLFizQnXfeqaeffrrW9ueff14LFizwmCDkGdelAADwcSEhIXryySf1xBNP6M0339TevXu1ZcsWu+6k6tSpk9asWaMvvvhC33//vR588EEdOnTI4bWmp6fr2LFjGjVqlL766ivt3btXq1ev1r333mvTgqhHjhzRP/7xD91zzz3q3r17rUdaWpqWL1+uY8eOObzupiAIAQDgIv/zP/+jRx99VNOmTdMVV1yhkSNH1pm7cz5T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nDihm2++WYmJicrJydGnn36qQ4cOacSIEQ2+xrfffqvi4mIlJSXV+d6cOXOUlJSkbdu26aGHHtL48eOtV7JeeeUVrVixQkuWLNGuXbv0zjvvqH379rWOv+aaa/T555877oQAcAmCEACP0LNnT02dOlWdOnVSRkaGQkJCFBUVpQceeECdOnXStGnTVFRUpG+//VbS2Xk5iYmJmjFjhrp06aLExEQtXLhQGzZs0O7du+t9jf379ysgIEDR0dF1vjdo0CA99NBD6tixo5588klFRUVpw4YNkqT8/Hx16tRJKSkpateunVJSUjRq1Khax8fFxWn//v0OPisAnI0gBMAjXHnlldY/BwQE6OKLL1aPHj2s29q0aSNJOnz4sKSzk543bNhgnXPUsmVLdenSRZK0d+/eel/j1KlTCg4OrndCd83XtwznWV5rzJgxys3NVefOnTVp0iT961//qnN88+bNrVerAHiPQHcXAACS1KxZs1pfm0ymWtss4aW6ulqSVFpaqqFDh2rWrFl1nis2Nrbe14iKilJ5ebkqKysVFBTU6OtbXqtXr17Ky8vTP//5T61du1YjRoxQamqqPvjgA+v+x44dU+vWrW39cQF4CIIQAK/Uq1cvffjhh2rfvr0CA217K7vqqqskSTt37rT+2Vbh4eEaOXKkRo4cqd/85je67bbbdOzYMUVGRko6O3E7MTHRrucE4H4MjQHwSunp6Tp27JhGjRqlr776Snv37tXq1at17733qqqqqt5jWrdurV69eikrK8uu13rxxRf13nvv6YcfftDu3bu1dOlSxcTE1OqD9Pnnn6t///4X8iMBcAOCEACvFBcXp82bN6uqqkr9+/dXjx49NHnyZF100UUymxt+axs7dqzeeecdu14rLCxMs2fPVlJSknr37q2ffvpJn3zyifV1srOzVVxcrN/85jcX9DMBcD0aKgLwK6dOnVLnzp21ePFiJScnO+Q5R44cqZ49e+r3v/+9Q54PgOtwRQiAX2nevLnefPPN8zZetEdlZaV69OihRx55xCHPB8C1uCIEAAD8FleEAACA3yIIAQAAv0UQAgAAfosgBAAA/BZBCAAA+C2CEAAA8FsEIQAA4LcIQgAAwG8RhAAAgN/6/87odjf0xUZaAAAAAElFTkSuQmCC", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -863,1583 +91,9 @@ }, { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -2447,7 +101,6 @@ } ], "source": [ - "%matplotlib notebook\n", "from qupulse.pulses.plotting import plot\n", "\n", "parameters = dict(t=3,\n", @@ -2478,797 +131,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "repetition parameters: {'v_1', 'n_rep', 'v_0', 't'}\n", + "repetition parameters: {'t', 'v_0', 'v_1', 'n_rep'}\n", "repetition measurements: {'M'}\n" ] }, { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], + "image/png": "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oDo8TnReeOEFvfzyyxo7dqxr39VXX62uXbvqscceI9EBAAB1hsdNV9nZ2br44ovP2X/xxRcrOzvbK0EBAAB4g8eJTvv27fXee++ds3/u3LkVLqoJAABgFo+brqZOnarRo0dr2bJlrj46K1as0KJFiypMgAAAAMzido3O5s2bJUnXXnutvv32WzVv3lwLFy7UwoUL1bx5c61evVq/+93vfBYoAACAp9yu0enRo4f69Omj2267TX/84x/1n//8x5dxAQAA1JjbNTpLly5V165ddf/99ysqKkrjx4/XN99848vYAAAAasTtROfSSy/VG2+8oezsbL3wwgvKzMzU5Zdfrg4dOuipp57S/v37fRknAACAxzweddW4cWPdfPPNWrp0qbZt26brrrtOL730ktq0aaOrr77aFzECAABUS43Wumrfvr0efvhhPfLIIwoNDdWnn37qrbgAAABqzOPh5U7Lli3TG2+8ofnz58vPz0+jRo3Srbfe6s3YAAAAasSjROfnn39WWlqa0tLStH37dl188cV6/vnnNWrUKDVu3NhXMQIAAFSL24lOUlKSvvrqKzVv3lxjx47VLbfcoo4dO/oyNgAAgBpxO9Fp2LCh3n//ff2///f/1KBBA1/GBAAA4BVuJzofffSRL+MAAADwuhqNugIAAKjLSHQAAIBtkegAAADbItEBAAC2RaIDAABsi0QHAADYFokOAACwLRIdAABgWyQ6AADAtkh0AACAbZHoAAAA2yLRAQAAtmVqorNs2TKNGDFC0dHRcjgcWrhwodvnrlixQv7+/rrooot8Fh8AALA2UxOdgoICJSQk6KWXXvLovGPHjmns2LEaPHiwjyIDAAB24G/mmyclJSkpKcnj8+68805df/31atCggUe1QAAAoH6xXB+dN998Uzt37tSjjz7q1vFFRUXKzc0t9/CGUsPwynVQd1HG5jtxssTsEOBjxylj+JilEp2ffvpJf/nLX/Sf//xH/v7uVUalpqYqLCzM9YiJifFKLF/+cECSdb8MD+UXSZJKLBp/bfjv5v2SrFvGdrA+65gkysDONu87/eOTzyL4imUSnZKSEl1//fWaOnWqOnTo4PZ5KSkpysnJcT327NnjlXh+zD79x/lLXrFXrlfb1u0+Kknis6VymYcKJEmHC6xZxnYS3NDUVnb4iFHmA6hJUEMTI4GdWebTIy8vT2vXrtWGDRs0YcIESVJpaakMw5C/v7++/PJLDRo06JzzAgMDFRgY6LO4urcK89m1fWnNrqNmh2AZCa2tWcZWl3vipGu7d2wzEyOBrxwp8yMiIaapeYHA1iyT6DRp0kSbNm0qt+9f//qXvv76a73//vuKi4szJa5+7cJNed+a+n5fjiSpVdNgkyOp+/rFXWB2CPXSd3uOubabh/juxwrMU/YHV1gwNTrwDVMTnfz8fG3fvt31PDMzUxkZGQoPD1ebNm2UkpKiffv2afbs2fLz81O3bt3KnR8REaGgoKBz9vvagdwTru1uFq3R2XmmWSYhxprx+1rW4ULXdsfIUBMjqb+odbS/dbuPmB0C6gFTE521a9fqiiuucD2fPHmyJGncuHFKS0tTdna2srKyzAqvUmvLfACHBFqmUqxCvdtas0bK19bsOvsBHNSwgYmR1F8//OydEZKou7bsz5MkBTSwTHdRWJCp39IDBw4s1xnt19LS0s57/mOPPabHHnvMu0G54fufc2r9Pb2ppPTsv3lim6bmBVKHfc+XrOmcHf57taV/jl05y7hPHGUM3yGNrgbniKXmIQEmR1I9+44ed213iW5iYiR117qs02VMHybz7Dt2+v9pN/6P2tah/NOdkbtF04QO3yHRqYYNZ+b2iI+wZt+NDXvONr0F+tMsUxFnR9gOLUPMDQTqatF+cHCfVfs6whpIdKqhuKRUktQ5ypq/NFdn0gHQXV35pWmKsjMi94ujH5kdFRSdcm33pYzhQyQ6NdDXou3K3+09Jklq2ojhnFXhA9gc2w7kubZjmjUyMRL4yuZ9Z/s6tmwSZGIksDsSHQ+VncSsl0VHLG07kC9J6krfhwo5l8eQpIvorG2Kb3eerXX083OYGAl8hZpl1BYSHQ+VncTsgsbW7IxcfOp005tVEzVfc3Y2l5iW3iybLT6yEVVjZCNqC4mOhzbuPfsBbMVfmmWH8/dhWv0Kla1Shzm2nplfpX0EncHtauuZ5slurahZhm+R6Hho45n+LYH+1vynK7tAJR1tK+ZMZpmS3jzOieQuYv0j23IumpvQuqm5gcD2rPltbSLnrMidLDrialOZ2opwiza9+ZpzVmSWfjCfVUc2wn384IKvkeh4yFkj0tGi86usoQNglQqLTw9t7kyiY4pTZ6ZvkGhetauiU2enD7Dq6FVYB4lONVl1WnpnR9sAiza91aZesXTWNsPeMjN3d2hJsmlHO38pcG3HXtDYxEhQH/Bt5wHnaCVJ6ht3gYmRVJ9zfpJO1FZUqOwkZtQmmKPssGMWVLWnb3cedm37s6AnfIz/YR5wjgSRpNbNrLkG0tHC0/MA9WzDl3hFyvZhighlEjMzbCgzhQPsqezoVcDXSHQ8sD7r7PwqDS3+K6QPzTIVyijzJdvAgtMH2MHW/afnV2kRGmhyJPAV59DymHBr/mCEtVj727qW/WDxCa7Krh/UozUjHSrinMTMQY5jGmetWi9qHW3L+XfWm0lLUQtIdDyw+syw43iLTmJWdiZSqza9+draM2XM8hjmOVlyelJLhpbbX+co+grC90h0POCc4KqDRTvyOr/EJclBlUWFsnNOSGK0j1nKztydyDpjtlRSeraMrTp6FdZColMNCRZt9lmz62jVB0GSlMiMvKY4Umbm7gTKwJb2555wbXeJsuZnKayFRKca+ll0aPmP2aebrtq1YN6KipSdqK5fO2uWsdWVTcZZgsOeVmeeHVoeHMD0AfA9Eh03ZR0udG1bdWmAfcdOT8R2EWvLVGgHk5iZbt1uZu62u/W7j5kdAuoZEh03rdlln0nM+sQx0qEiZcuYmaPN4VzMM8Di0zegclvOTB/QJMjf5EhQX/Bp4qbvLT60vGyzDCtCV8zZtAfzOMugD+sf2daP2aeT2b784EItIdFx07ozkwW2amrNYdk7D51tlmFEUcWc64DRh8k8h/JPd0buxorWtpV/ZpmVLpQxagmJjpu+OzNjbgeLrlq+fvfZTp7M+FsxZ7NJRxJB03VrxZeg3fWgjFFLSHQ81NWiv0JW76KTp7v4kjVH2QVVadawp5wza+1JzKGD2kOi4yGrfgBvOrOIXssmrB9UlX4WLWOr21xmQdWWTVhQ1Y7WZZ39wdWscYCJkaA+IdFxw6H8Itf2RRadrfWng/mSpO6tmpobSB3185mh95LUheUfTLE6k1pHu1udyaSlqH0kOm5YV6Z/S5Mga09i1juW6uKKlB1a3iiAYa9msPrIRlTNObQcqE0kOm4oW6VuRaVl1pbpTbt4hfiSNd/WA6c7g3drRY2aXW05M7SczyHUJhIdN2w807/FqlPSZ5ddW4ZmmQplnBlVRx8m8zgXzU1g5m7bcq5zxTpmqE0kOm5wNmtYdemHjWe+xCWaZSrjbJ7sGEkiaDarjmyE+6i1Q20i0XFDYXGJJKmzRROdb+nkWaWSM817naOsWcZWV3SqxLXdl1mRbel48dky7hPLyEbUHhIdD/Sy6B/nhjOzOoeytkyV+rS1Zhlb3U4WVLW9H8t0RG7drJGJkaC+MTXRWbZsmUaMGKHo6Gg5HA4tXLjwvMd/8MEH+u1vf6sWLVqoSZMm6t+/v7744gufxlh2ErM+Fh2xtO3A6aHlnWmWqdCxwmLXNqPSzPHtzsOubX8W9LSlb3dSswxzmPqJUlBQoISEBL300ktuHb9s2TL99re/1WeffaZ169bpiiuu0IgRI7RhwwafxbipzIiriFBrTmJ2/OTpKuNefIlXaEPWMdd200ZMYmYGZ4d/2JfVR6/Cukxty0hKSlJSUpLbx//zn/8s93zatGn68MMP9fHHHysxMdHL0Z2WUaYjrxXXiDKMs0PLrVoj5Wvf7T1mdgj1nnNoeUy4NRfNRdWcZRwfYc31AmFdlu60UVpaqry8PIWHV96voqioSEVFZ2c2zs31bL4U5/wqDuvlOJKknONn15ZhReiKOcu4cUADkyOpv5xl0Js+Ura1/czs7Kxxhdpm6cbwZ555Rvn5+Ro1alSlx6SmpiosLMz1iImJ8eg91p4ZWt7VovPPbN53NrFrEcocMRVxTh/QOcqaZWwnjHqzP+byQm2zbKLzzjvvaOrUqXrvvfcUERFR6XEpKSnKyclxPfbs2ePR+2TnnJ7gqkNLa34Al13awGHVaikfO3ZmRWWrzpNkdSVlZu7m1749nSwpdW1Txqhtlmy6mjNnjm677TbNmzdPQ4YMOe+xgYGBCgyseU1GokVn8nROhOdvwf5FtS2xDR/AZthfdubuKJpX7Wj34ULXtlV/NMK6LFej8+677+rmm2/Wu+++q+HDh/v0vU6V+RXSr90FPn0vX3EuohfPh0uFTpw8O4lZvzj6h5hhdebZoeXB9JOypbIr0zdk+gDUMlNrdPLz87V9+3bX88zMTGVkZCg8PFxt2rRRSkqK9u3bp9mzZ0s63Vw1btw4zZw5U/369dP+/fslScHBwQoL8/4vwR02mMTsUP7pOWIS2zQ1N5A6quxinlFh1pw+wOrW7z5mdgjwMeekpYAZTE2t165dq8TERNfQ8MmTJysxMVFTpkyRJGVnZysrK8t1/KuvvqpTp04pOTlZUVFRrse9997rk/jK9m8J8Lf2r5C+Fp3V2dfW7z77AcxEdeZw1jo2YeZu23IOLY9gQARMYOony8CBA8vN8/JraWlp5Z4vWbLEtwH9yo/Zng1Fr2uKT51temO14IqVnZYe5vgx+/SXYF+aDm3rhzM1p30oY5iAn7Dn4ezI266FNZuttpT5Em8bztoyFXGWMUPLzZN/ZpmVLszzZFunzoysYy4vmIFE5zy27D/9S7OjRTvyrivTLOPHqKsKOUeDdGzJbK1m69GKL0E7Ki0zfUBCDGWM2kei44ZuFv0ALtvHCOfXvXVTs0Ool3IKz87czfwq9nQo/+zM9D34O4MJSHTcYNVhx85ZkdvQbFWhshPVWbWMrW5d1tlkvFljFlS1ozW7ztYshwTS4Ry1j0SnEj8fO+7atuqU5VlHTjfL9GhtzRopX9t9+Oz0Ae1ZaNAUqzMZdmx31CzDbCQ6lSj7x9kowNq/QhjNUrGyZRzUkInqzLCFUW+25yzjYP7GYBISnUqUnUjOiso2y/RkaYMKWb2M7WDLmaHlvemfY1vOQR29YyljmINEpxIZe45Jklo2seYEV2WbZVissmLfnSlj+jCZx7nOFfM82Zdz0Vya0GEWEp1KOIdmd4y0Zv+cDVnHXNusLVOx7/bmSJI6kQiarlsra/6dwX3dLTp6FdbHN2AlnE0/naOs+SVIB0D3MVmgOY4Xn11QtQ9LlNhS3omz0wf0pHkSJiHRqUKfttb8AHY2vTUPsWbTW21iaLk5yi6/0boZzYd29N2eHNd2RCiL5sIcJDoVOFZY7Nq2age6nw7mS5K6WnRovK8dzDvh2u5O3wFTfLuTWke7W5152OwQABKdipTt39K0kTUnMXM2vTGapWJry0xiFhrU0MRI6q/N+3KqPgiWxshG1AUkOhX4bu8xs0OokbIrwvem70OFNu7lS9ZsWw+cHnYcz2SNtuUsYzoiw0wkOhVw/gppHGDNCa4O5p1dW6Yro1kq9P3PpxOdcJYdMM32M82rrHFlX3uPnp5hnjKGmUh0KuAcsWTV0TibytRWNKFZpkLOMu5i0TK2E6susQL3UcYwE4lOBZwTXFl1or3VDC2v0omTpZKYQ8csp0pLXdv82renopNny5jpA2AmEp3zSLTo0gnOyQ5ZKbhqfMmaY/fhQtd2h5Ykm3bkHPkpSW2ZfRwmItH5lRMnz05iZtX5VbadWVsmviWdPCuSf+KUa5vO2uZYnXm21pGZu+3p2zJDy/38HCZGgvqOT5hfKTscMirMmhNc5RWd/iLvZdEaKV8rO+KqeQidkc2wYc/Rqg+CpZWdLBAwE4nOr6zfffYD2N/ivzT7WLRGytfWZ50tY4eDX5pm2HPk9GiciFBm7rarfcdOlzGL5sJs1v4m94Gy09JbkbM2R2LuisoUnlljqQHV6aYjGbc/OiLDbCQ6v+LsyGvVoeV5ZfqfWLXprbb0YOkH03WLpgzsjpXpYTYSnV9xjgbpaIOOvDTLnF9HRvuYLiGGRMfurDp6FfZBolOJ7q2bmh1CjZDjVC0hpqnZIdR7PSz+d4aqMVcVzEaiU4ZzIUzJukPLnVg/qGpWL2M7YK4n+wtqaM2ldGAfJDpl7D5c4Npub/FEIYFfylWKYTQIANgeiU4Za8osnWD1XyGMZqkaE9WZK9jif2OoWtNGrLUH8/FJX0bZyQKtrmebpmaHAJxX71g6qdodQ8tRF5DolPHdnmOS7DHBVVxzaze9+Rp9mMzH8H77S6CMUQeQ6JTx3ZmlAewwSoDJ8M6vk0XnSbITJrS0J+PsmA7Lj16FPZDoVMCqkwXCfV2jKWMzlF1QtScrx9vS0YJi1/ZFTOGAOoBEpwJWH3bcqmmw2SHUSWV/aVq9jK1qf+4J13ZEKDN321HZZWjCgumMDPOZmugsW7ZMI0aMUHR0tBwOhxYuXFjlOUuWLFHPnj0VGBio9u3bKy0tzSuxHMw7+wHc3eLtyky5XjHnIoOS1CmSfyMAqA9MTXQKCgqUkJCgl156ya3jMzMzNXz4cF1xxRXKyMjQpEmTdNttt+mLL76ocSxrd51d0To0yNq/QhjpULHVmWenDwgOYGgzANQHpk5LmpSUpKSkJLePf+WVVxQXF6cZM2ZIkjp37qzly5frueee07Bhw2oUyzc//VKj881WWqZdphd9Hyp0qszM1wB8q7YGRJSUlOjkyZO18l7wvYYNG6pBA+/+ELXU/OsrV67UkCFDyu0bNmyYJk2aVOk5RUVFKioqcj3Pza14rpwvvz8gSbqgcUDNAzVB7omzf+h0pq5YSKC/8sv0H4B5epOM294l7Zv7/D3y8/O1d+9eGQY/YuzC4XCodevWCgnx3hQglkp09u/fr5YtW5bb17JlS+Xm5ur48eMKDj63E25qaqqmTp1a5bVHJERr/rq9mvb77l6Ltzb1iQ1Xl6gmim3eyPKzOvvKM9cl6G8fbtaTFi1jO7h3cLzeX7dXM0YlmB0KfCT5igu1cMPPPv8sLSkp0d69e9WoUSO1aNFCDlYytjzDMPTLL79o7969io+P91rNjsOoI6mww+HQggULNHLkyEqP6dChg26++WalpKS49n322WcaPny4CgsLK0x0KqrRiYmJUU5Ojpo0oeYDAKzoxIkTyszMVGxsbIWf/bCm48ePa9euXYqLi1NQUPmRmbm5uQoLC/P4+9tSNTqRkZE6cOBAuX0HDhxQkyZNKv2PHhgYqMDAwNoIDwBQy6jJsRdflKel5tHp37+/Fi1aVG5fenq6+vfvb1JEAACgLjM10cnPz1dGRoYyMjIknR4+npGRoaysLElSSkqKxo4d6zr+zjvv1M6dO/XnP/9ZW7Zs0b/+9S+99957uu+++8wIHwAA1HGmJjpr165VYmKiEhMTJUmTJ09WYmKipkyZIknKzs52JT2SFBcXp08//VTp6elKSEjQjBkz9Prrr9d4aDkAAGbbtWuXHA6H68d/XTdw4MDzjnquK0ztozNw4MDzDgusaNbjgQMHasOGDT6MCgAAeMvx48fVqlUr+fn5ad++fbXeb9ZSfXQAAIC1zJ8/X127dlWnTp3cWurJ20h0AACWZxiGCotPmfLwZJaW0tJSTZ8+Xe3bt1dgYKDatGmjJ554otwxO3fu1BVXXKFGjRopISFBK1eudL12+PBhjRkzRq1atVKjRo3UvXt3vfvuu+XOHzhwoO655x79+c9/Vnh4uCIjI/XYY4+VO8bhcOj111/X7373OzVq1Ejx8fH66KOPyh2zefNmJSUlKSQkRC1bttRNN92kQ4cOuX2vTrNmzdKNN96oG2+8UbNmzfL4/Jqy1PByAAAqcvxkibpMqfm6h9Xxw+PD1CjAva/TlJQUvfbaa3ruued0ySWXKDs7W1u2bCl3zF//+lc988wzio+P11//+leNGTNG27dvl7+/v06cOKFevXrpoYceUpMmTfTpp5/qpptu0oUXXqi+ffu6rvHWW29p8uTJ+vbbb7Vy5UqNHz9eAwYM0G9/+1vXMVOnTtX06dP19NNP64UXXtANN9yg3bt3Kzw8XMeOHdOgQYN022236bnnntPx48f10EMPadSoUfr666/d/rfZsWOHVq5cqQ8++ECGYei+++7T7t271bZtW7evUVPU6AAAUAvy8vI0c+ZMTZ8+XePGjdOFF16oSy65RLfddlu54x544AENHz5cHTp00NSpU7V7925t375dktSqVSs98MADuuiii9SuXTtNnDhRV155pd57771y1+jRo4ceffRRxcfHa+zYserdu/c507OMHz9eY8aMUfv27TVt2jTl5+dr9erVkqQXX3xRiYmJmjZtmjp16qTExES98cYbWrx4sbZt2+b2Pb/xxhtKSkpSs2bNFB4ermHDhunNN9+szj9ftVGjAwCwvOCGDfTD4+aMwA12c9mdH3/8UUVFRRo8ePB5j+vRo4drOyoqSpJ08OBBderUSSUlJZo2bZree+897du3T8XFxSoqKlKjRo0qvYbzOgcPHqz0mMaNG6tJkyauY7777jstXry4wjWnduzYoQ4dOlR5vyUlJXrrrbc0c+ZM174bb7xRDzzwgKZMmSI/v9qpayHRAQBYnsPhcLv5yCzuLlXRsGFD17ZzpuDS0lJJ0tNPP62ZM2fqn//8p7p3767GjRtr0qRJKi4urvQazus4r+HOMfn5+RoxYoSeeuqpc+JzJl9V+eKLL7Rv3z6NHj263P6SkhItWrSoXDOaL9Xt/xUAANhEfHy8goODtWjRonOaq9y1YsUKXXPNNbrxxhslnU6Atm3bpi5dungzVPXs2VPz589XbGys/P2rlyrMmjVLf/zjH/XXv/613P4nnnhCs2bNqrVEhz46AADUgqCgID300EP685//rNmzZ2vHjh1atWqVRyOR4uPjlZ6erv/973/68ccfdccdd5yzBqQ3JCcn68iRIxozZozWrFmjHTt26IsvvtDNN9+skpKSKs//5Zdf9PHHH2vcuHHq1q1bucfYsWO1cOFCHTlyxOtxV4REBwCAWvK3v/1N999/v6ZMmaLOnTtr9OjR5/SdOZ9HHnlEPXv21LBhwzRw4EBFRkZq5MiRXo8zOjpaK1asUElJiYYOHaru3btr0qRJatq0qVt9a2bPnq3GjRtX2B9p8ODBCg4O1n/+8x+vx10Rh+HJBAA2UN1l3gEAdceJEyeUmZmpuLg4BQUFmR0OvOR85Vrd729qdAAAgG2R6AAAANsi0QEAALZFogMAAGyLRAcAYFn1bDyN7fmiPEl0AACW06DB6WUXfj0jMKzNWZ7O8vUGZkYGAFiOv7+/GjVqpF9++UUNGzastXWT4DulpaX65Zdf1KhRo2rPxlwREh0AgOU4HA5FRUUpMzNTu3fvNjsceImfn5/atGnjWuPLG0h0AACWFBAQoPj4eJqvbCQgIMDrtXMkOgAAy/Lz82NmZJwXjZoAAMC2SHQAAIBtkegAAADbqnd9dJyTEeXm5pocCQAAcJfze9vTSQXrXaKTl5cnSYqJiTE5EgAA4Km8vDyFhYW5fbzDqGfzZ5eWlurnn39WaGhouXH6ubm5iomJ0Z49e9SkSRMTI6w99e2e69v9SvXvnuvb/Ur1757r2/1K9e+eK7tfwzCUl5en6Ohoj4ag17saHT8/P7Vu3brS15s0aVIv/iOVVd/uub7dr1T/7rm+3a9U/+65vt2vVP/uuaL79aQmx4nOyAAAwLZIdAAAgG2R6JwRGBioRx99VIGBgWaHUmvq2z3Xt/uV6t8917f7lerfPde3+5Xq3z17+37rXWdkAABQf1CjAwAAbItEBwAA2BaJDgAAsC0SHQAAYFskOme89NJLio2NVVBQkPr166fVq1ebHZLPPPbYY3I4HOUenTp1Mjssr1m2bJlGjBih6OhoORwOLVy4sNzrhmFoypQpioqKUnBwsIYMGaKffvrJnGC9pKp7Hj9+/DllfuWVV5oTrBekpqaqT58+Cg0NVUREhEaOHKmtW7eWO+bEiRNKTk7WBRdcoJCQEF177bU6cOCASRHXjDv3O3DgwHPK+M477zQp4pp7+eWX1aNHD9ekcf3799d///tf1+t2Kl+p6vu1W/n+2pNPPimHw6FJkya59nmrjEl0JM2dO1eTJ0/Wo48+qvXr1yshIUHDhg3TwYMHzQ7NZ7p27ars7GzXY/ny5WaH5DUFBQVKSEjQSy+9VOHr06dP1/PPP69XXnlF3377rRo3bqxhw4bpxIkTtRyp91R1z5J05ZVXlivzd999txYj9K6lS5cqOTlZq1atUnp6uk6ePKmhQ4eqoKDAdcx9992njz/+WPPmzdPSpUv1888/6/e//72JUVefO/crSbfffnu5Mp4+fbpJEddc69at9eSTT2rdunVau3atBg0apGuuuUbff/+9JHuVr1T1/Ur2Kt+y1qxZo//7v/9Tjx49yu33WhkbMPr27WskJye7npeUlBjR0dFGamqqiVH5zqOPPmokJCSYHUatkGQsWLDA9by0tNSIjIw0nn76ade+Y8eOGYGBgca7775rQoTe9+t7NgzDGDdunHHNNdeYEk9tOHjwoCHJWLp0qWEYp8u0YcOGxrx581zH/Pjjj4YkY+XKlWaF6TW/vl/DMIzLL7/cuPfee80LqhY0a9bMeP31121fvk7O+zUM+5ZvXl6eER8fb6Snp5e7R2+Wcb2v0SkuLta6des0ZMgQ1z4/Pz8NGTJEK1euNDEy3/rpp58UHR2tdu3a6YYbblBWVpbZIdWKzMxM7d+/v1x5h4WFqV+/frYub0lasmSJIiIi1LFjR9111106fPiw2SF5TU5OjiQpPDxckrRu3TqdPHmyXDl36tRJbdq0sUU5//p+nd5++201b95c3bp1U0pKigoLC80Iz+tKSko0Z84cFRQUqH///rYv31/fr5Mdyzc5OVnDhw8vV5aSd/+G692inr926NAhlZSUqGXLluX2t2zZUlu2bDEpKt/q16+f0tLS1LFjR2VnZ2vq1Km69NJLtXnzZoWGhpodnk/t379fkiosb+drdnTllVfq97//veLi4rRjxw49/PDDSkpK0sqVK9WgQQOzw6uR0tJSTZo0SQMGDFC3bt0knS7ngIAANW3atNyxdijniu5Xkq6//nq1bdtW0dHR2rhxox566CFt3bpVH3zwgYnR1symTZvUv39/nThxQiEhIVqwYIG6dOmijIwMW5ZvZfcr2bN858yZo/Xr12vNmjXnvObNv+F6n+jUR0lJSa7tHj16qF+/fmrbtq3ee+893XrrrSZGBl/54x//6Nru3r27evTooQsvvFBLlizR4MGDTYys5pKTk7V582Zb9TM7n8ru909/+pNru3v37oqKitLgwYO1Y8cOXXjhhbUdpld07NhRGRkZysnJ0fvvv69x48Zp6dKlZoflM5Xdb5cuXWxXvnv27NG9996r9PR0BQUF+fS96n3TVfPmzdWgQYNzenIfOHBAkZGRJkVVu5o2baoOHTpo+/btZofic84yrc/lLUnt2rVT8+bNLV/mEyZM0CeffKLFixerdevWrv2RkZEqLi7WsWPHyh1v9XKu7H4r0q9fP0mydBkHBASoffv26tWrl1JTU5WQkKCZM2fatnwru9+KWL18161bp4MHD6pnz57y9/eXv7+/li5dqueff17+/v5q2bKl18q43ic6AQEB6tWrlxYtWuTaV1paqkWLFpVrG7Wz/Px87dixQ1FRUWaH4nNxcXGKjIwsV965ubn69ttv6015S9LevXt1+PBhy5a5YRiaMGGCFixYoK+//lpxcXHlXu/Vq5caNmxYrpy3bt2qrKwsS5ZzVfdbkYyMDEmybBlXpLS0VEVFRbYr38o477ciVi/fwYMHa9OmTcrIyHA9evfurRtuuMG17bUy9l7faeuaM2eOERgYaKSlpRk//PCD8ac//clo2rSpsX//frND84n777/fWLJkiZGZmWmsWLHCGDJkiNG8eXPj4MGDZofmFXl5ecaGDRuMDRs2GJKMZ5991tiwYYOxe/duwzAM48knnzSaNm1qfPjhh8bGjRuNa665xoiLizOOHz9ucuTVd757zsvLMx544AFj5cqVRmZmpvHVV18ZPXv2NOLj440TJ06YHXq13HXXXUZYWJixZMkSIzs72/UoLCx0HXPnnXcabdq0Mb7++mtj7dq1Rv/+/Y3+/fubGHX1VXW/27dvNx5//HFj7dq1RmZmpvHhhx8a7dq1My677DKTI6++v/zlL8bSpUuNzMxMY+PGjcZf/vIXw+FwGF9++aVhGPYqX8M4//3asXwr8uuRZd4qYxKdM1544QWjTZs2RkBAgNG3b19j1apVZofkM6NHjzaioqKMgIAAo1WrVsbo0aON7du3mx2W1yxevNiQdM5j3LhxhmGcHmL+t7/9zWjZsqURGBhoDB482Ni6dau5QdfQ+e65sLDQGDp0qNGiRQujYcOGRtu2bY3bb7/d0ol8RfcqyXjzzTddxxw/fty4++67jWbNmhmNGjUyfve73xnZ2dnmBV0DVd1vVlaWcdlllxnh4eFGYGCg0b59e+PBBx80cnJyzA28Bm655Rajbdu2RkBAgNGiRQtj8ODBriTHMOxVvoZx/vu1Y/lW5NeJjrfK2GEYhlHNmicAAIA6rd730QEAAPZFogMAAGyLRAcAANgWiQ4AALAtEh0AAGBbJDoAAMC2SHQAAIBtkegAAADbItEBUOvGjx+vkSNHmvb+N910k6ZNm+aVaxUXFys2NlZr1671yvUAeBczIwPwKofDcd7XH330Ud13330yDENNmzatnaDK+O677zRo0CDt3r1bISEhXrnmiy++qAULFpRbgBBA3UCiA8Cr9u/f79qeO3eupkyZoq1bt7r2hYSEeC3BqI7bbrtN/v7+euWVV7x2zaNHjyoyMlLr169X165dvXZdADVH0xUAr4qMjHQ9wsLC5HA4yu0LCQk5p+lq4MCBmjhxoiZNmqRmzZqpZcuWeu2111RQUKCbb75ZoaGhat++vf773/+We6/NmzcrKSlJISEhatmypW666SYdOnSo0thKSkr0/vvva8SIEeX2x8bGatq0abrlllsUGhqqNm3a6NVXX3W9XlxcrAkTJigqKkpBQUFq27atUlNTXa83a9ZMAwYM0Jw5c2r4rwfA20h0ANQJb731lpo3b67Vq1dr4sSJuuuuu3Tdddfp4osv1vr16zV06FDddNNNKiwslCQdO3ZMgwYNUmJiotauXavPP/9cBw4c0KhRoyp9j40bNyonJ0e9e/c+57UZM2aod+/e2rBhg+6++27dddddrpqo559/Xh999JHee+89bd26VW+//bZiY2PLnd+3b19988033vsHAeAVJDoA6oSEhAQ98sgjio+PV0pKioKCgtS8eXPdfvvtio+P15QpU3T48GFt3LhR0ul+MYmJiZo2bZo6deqkxMREvfHGG1q8eLG2bdtW4Xvs3r1bDRo0UERExDmvXXXVVbr77rvVvn17PfTQQ2revLkWL14sScrKylJ8fLwuueQStW3bVpdcconGjBlT7vzo6Gjt3r3by/8qAGqKRAdAndCjRw/XdoMGDXTBBReoe/furn0tW7aUJB08eFDS6U7FixcvdvX5CQkJUadOnSRJO3bsqPA9jh8/rsDAwAo7TJd9f2dzm/O9xo8fr4yMDHXs2FH33HOPvvzyy3PODw4OdtU2Aag7/M0OAAAkqWHDhuWeOxyOcvucyUlpaakkKT8/XyNGjNBTTz11zrWioqIqfI/mzZursLBQxcXFCggIqPL9ne/Vs2dPZWZm6r///a+++uorjRo1SkOGDNH777/vOv7IkSNq0aKFu7cLoJaQ6ACwpJ49e2r+/PmKjY2Vv797H2UXXXSRJOmHH35wbburSZMmGj16tEaPHq0//OEPuvLKK3XkyBGFh4dLOt0xOjEx0aNrAvA9mq4AWFJycrKOHDmiMWPGaM2aNdqxY4e++OIL3XzzzSopKanwnBYtWqhnz55avny5R+/17LPP6t1339WWLVu0bds2zZs3T5GRkeXmAfrmm280dOjQmtwSAB8g0QFgSdHR0VqxYoVKSko0dOhQde/eXZMmTVLTpk3l51f5R9ttt92mt99+26P3Cg0N1fTp09W7d2/16dNHu3bt0meffeZ6n5UrVyonJ0d/+MMfanRPALyPCQMB1CvHjx9Xx44dNXfuXPXv398r1xw9erQSEhL08MMPe+V6ALyHGh0A9UpwcLBmz5593okFPVFcXKzu3bvrvvvu88r1AHgXNToAAMC2qNEBAAC2RaIDAABsi0QHAADYFokOAACwLRIdAABgWyQ6AADAtkh0AACAbZHoAAAA2yLRAQAAtvX/ATmezirBcyO9AAAAAElFTkSuQmCC", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -4142,22 +231,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/00ConstantPulseTemplate.ipynb b/doc/source/examples/00ConstantPulseTemplate.ipynb index 41b71020a..0dafbe501 100644 --- a/doc/source/examples/00ConstantPulseTemplate.ipynb +++ b/doc/source/examples/00ConstantPulseTemplate.ipynb @@ -46,8 +46,10 @@ "outputs": [ { "data": { - "text/plain": "
", - "image/png": "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SzFSUVGRFR8fb6WlpVm33HKL9fjjj3u7JKOMHTvWuvHGG71dhvF69eplDR061Kntr3/9qzVw4EAvVWQmSdbHH3/seG+3262oqCjrpZdecrT98ccfVkREhPXWW29VeT3M3FygkpISpaenKykpyak9KSlJW7du9VJVl4aCggJJUp06dbxciZlGjBihXr16qWvXrt4uxUirVq1S+/btdc8996hBgwa65pprtGDBAm+XZZwbb7xR69at0+7duyVJ//u//6vNmzerZ8+eXq7MbFlZWTpy5IjTsTEgIEC33HJLtRwbL7kHZ3ra0aNHVVZWpsjISKf2yMhIHTlyxEtVmc+yLI0ePVo33nij2rRp4+1yjPPBBx/o22+/1fbt271dirH279+vefPmafTo0Ro/fry2bdumkSNHKiAgQIMHD/Z2ecYYO3asCgoK1KpVK/n6+qqsrEwvvviiBgwY4O3SjHbm+FfRsfHgwYNVvn/CjYfYbDan95ZllWuD5zz66KP67rvvtHnzZm+XYpycnBw9/vjjWrt2rQIDA71djrHsdrvat2+vqVOnSpKuueYa/fjjj5o3bx7hxoNSU1P1H//xH1q+fLmuvPJKZWZmKiUlRTExMRoyZIi3yzOet46NhJsLVK9ePfn6+pabpcnPzy+XWOEZjz32mFatWqWNGzeqUaNG3i7HOOnp6crPz1diYqKjraysTBs3btScOXNUXFwsX19fL1ZohujoaF1xxRVOba1bt9aKFSu8VJGZnnzyST399NO69957JUlt27bVwYMHNW3aNMJNFYqKipJ0egYnOjra0V5dx0bW3Fwgf39/JSYmKi0tzak9LS1NHTp08FJVZrIsS48++qhWrlypzz//XHFxcd4uyUi33nqrvv/+e2VmZjpe7du31/3336/MzEyCjYd07Nix3K0Mdu/erSZNmnipIjOdPHlSPj7OhzpfX18uBa9icXFxioqKcjo2lpSUaMOGDdVybGTmxgNGjx6tQYMGqX379rrhhhs0f/58ZWdnKzk52dulGWXEiBFavny5/uu//kthYWGO2bKIiAgFBQV5uTpzhIWFlVvHFBISorp167K+yYNGjRqlDh06aOrUqerXr5+2bdum+fPna/78+d4uzSi9e/fWiy++qMaNG+vKK69URkaGZs6cqaFDh3q7tIve77//rr179zreZ2VlKTMzU3Xq1FHjxo2VkpKiqVOnKj4+XvHx8Zo6daqCg4N13333VX1xVX491iXizTfftJo0aWL5+/tbCQkJXJ5cBSRV+HrnnXe8XZrxuBS8anz66adWmzZtrICAAKtVq1bW/PnzvV2ScQoLC63HH3/caty4sRUYGGg1a9bMmjBhglVcXOzt0i5669evr/D/k4cMGWJZ1unLwZ977jkrKirKCggIsG6++Wbr+++/r5babJZlWVUfoQAAAKoHa24AAIBRCDcAAMAohBsAAGAUwg0AADAK4QYAABiFcAMAAIxCuAEAAEYh3AAAAKMQbgBUu0mTJunqq6/22v6fffZZPfTQQx4b7y9/+YtWrlzpsfEAXBjuUAzAo2w22zk/HzJkiOPp4nXr1q2mqv7Pzz//rPj4eH333Xdq2rSpR8ZctWqVxowZo59++qncQxoBVD/CDQCPOvNAU0lKTU3VxIkTnZ5+HRQUpIiICG+UJkmaOnWqNmzYoDVr1nhszLKyMsXExGjJkiXq0aOHx8YFUDn8JwYAj4qKinK8IiIiZLPZyrX9+2mpBx54QH379tXUqVMVGRmp2rVra/LkySotLdWTTz6pOnXqqFGjRlq8eLHTvnJzc9W/f39ddtllqlu3rvr06aMDBw6cs74PPvhAd9xxh1Nbp06dNHLkSD311FOqU6eOoqKiNGnSJKc+kyZNUuPGjRUQEKCYmBiNHDnS8Zmvr6969uyp999/v1K/GQDPItwAqBE+//xzHT58WBs3btTMmTM1adIk3X777brsssv09ddfKzk5WcnJycrJyZEknTx5Up07d1ZoaKg2btyozZs3KzQ0VLfddptKSkoq3Mevv/6qH374Qe3bty/32bvvvquQkBB9/fXXmjFjhqZMmaK0tDRJ0kcffaRZs2bp7bff1p49e/TJJ5+obdu2Tttfe+212rRpk4d/FQCVQbgBUCPUqVNHr7/+ulq2bKmhQ4eqZcuWOnnypMaPH6/4+HiNGzdO/v7+2rJli6TTMzA+Pj5auHCh2rZtq9atW+udd95Rdna2vvjiiwr3cfDgQVmWpZiYmHKftWvXTs8995zi4+M1ePBgtW/fXuvWrZMkZWdnKyoqSl27dlXjxo117bXX6sEHH3TavmHDhsrOzpbdbvfsDwPAbYQbADXClVde6bQYNzIy0ml2xNfXV3Xr1lV+fr4kKT09XXv37lVYWJhCQ0MVGhqqOnXq6I8//tC+ffsq3MepU6ckSYGBgeU+a9eundP76Ohox77uuecenTp1Ss2aNdODDz6ojz/+WKWlpU79g4KCZLfbVVxcXIlvD8CT/LxdAABIUq1atZze22y2CtvOzIzY7XYlJiZq2bJl5caqX79+hfuoV6+epNOnp/69z7n2FRsbq127diktLU3//Oc/9cgjj+jll1/Whg0bHNsdP35cwcHBCgoKcvUrA6gihBsAF6WEhASlpqaqQYMGCg8Pd2mbyy+/XOHh4dqxY4datGjh1v6CgoJ0xx136I477tCIESPUqlUrff/990pISJAk/fDDD45/A/AuTksBuCjdf//9qlevnvr06aNNmzYpKytLGzZs0OOPP65Dhw5VuI2Pj4+6du2qzZs3u7WvJUuWaNGiRfrhhx+0f/9+vffeewoKClKTJk0cfTZt2qSkpKQL+k4APINwA+CiFBwcrI0bN6px48b661//qtatW2vo0KE6derUOWdyHnroIX3wwQduLfytXbu2FixYoI4dO6pdu3Zat26dPv30U8dNCHNzc7V161b97W9/u+DvBeDCcRM/AJcUy7J0/fXXKyUlRQMGDPDImE8++aQKCgo0f/58j4wH4MIwcwPgkmKz2TR//vxyVztdiAYNGuj555/32HgALgwzNwAAwCjM3AAAAKMQbgAAgFEINwAAwCiEGwAAYBTCDQAAMArhBgAAGIVwAwAAjEK4AQAARiHcAAAAo/w/CSwDtMUQAowAAAAASUVORK5CYII=\n" + "image/png": "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8vA43Gzbtq3Eez8/P9WrV08zZsy47pVUAAAAFc3jcLNu3bqKqAMAAMAruIkfAAAwitfCzZgxYzgtBQAAfM5rD848evSojhw54q3hAAC4LofDoYsXL/q6DHhJYGCgVx7C7bVw8/rrr3trKAAArsmyLOXm5urMmTO+LgVe5Ofnp8TERAUGBt7QOF4LNwAAVJYrwSYqKkohISGy2Wy+Lgk3yOl06tixYzp+/LgaNGhwQ79pucJNYWGhPv30Ux0+fFjFxcUlPhsxYkS5iwEA4HocDocr2NStW9fX5cCL6tWrp2PHjunSpUuqUaNGuccp131u7rzzTp0/f16FhYWqU6eOTp06pZCQEEVFRRFuAAAV6socm5CQEB9XAm+7cjrK4XDcULjxeNbOyJEjlZGRoR9//FHBwcH68ssv9f3336tdu3Z6+eWXy10IAACe4FSUebz1m3ocbnJycvTHP/5Rfn5+8vf3V1FRkeLj4zVt2jSNGTPGK0UBAACUl8fhpkaNGq7LtKKionT48GFJUkREBJeCAwBQTocOHZLNZlNOTo6vS3HLbbfdpszMTF+XUSaPw01KSoo2b94sSeratavGjx+vN998U5mZmWrZsqXXCwQAANXPkiVLZLPZXK/Q0FC1a9dO77zzToWv2+NwM3nyZMXGxkqSJk2apNq1a+uxxx7TyZMnNX/+fK8XCAAAqqfw8HAdP35cx48f17Zt25Senq4+ffpoz549Fbpej8NNamqqunXrJunyaanVq1eroKBAW7ZsUXJystcLBADAFE6nU9OmTVPjxo1lt9vVoEEDTZo0qUSfAwcOqFu3bgoJCVFycrI2btzo+uyHH35Qv379VL9+fYWEhKhVq1Z66623Six/2223acSIEXr66adVp04dxcTE6LnnnivRx2azaeHChbrnnnsUEhKipKQkrVq1qkSfHTt2qFevXgoNDVV0dLQGDBigU6dOefR9bTabYmJiFBMTo6SkJL344ovy8/PT9u3bPRrHUzw4EwBQ7VmWpfPFl3zysizL7TpHjx6tl156SePGjdPOnTu1dOlSRUdHl+jz7LPP6qmnnlJOTo6aNGmifv366dKlS5Kkn376Se3atdP777+vHTt26NFHH9WAAQO0adOmEmO8/vrrqlmzpr766itNmzZNzz//vNauXVuiz8SJE9WnTx9t375dd955px544AGdPn1aknTmzBl1795dKSkp+vrrr7V69Wrl5eWpT58+5fl5JF2+vPvK0wzatm1b7nHc4dZ9bu644w4999xz+tWvfnXNfmfPntVrr72m0NBQDRs2zCsFAgBwPRcuOtR8/BqfrHvn8+kKCbz+7vTs2bN69dVXNWfOHA0aNEiSdPPNN6tLly4l+j311FO66667JF0OIC1atNC+ffvUrFkz1a9fX0899ZSr7xNPPKE1a9ZoxYoVat++vau9devWmjBhgiQpKSlJc+bMUXZ2tm6//XZXnwcffFD9+vWTdHnKyezZs7Vp0ybdcccdmjNnjlJSUjR58mRX/8WLFys+Pl579+5VkyZN3No2+fn5Cg0NlSRduHBBNWrU0Pz583XzzTe7tXx5uRVu7r//ft17772KiIhQRkaGUlNTFRcXp6CgIP3444/auXOn1q9frw8++EB33XWXpk+fXqFFAwBQ3ezatUtFRUXq0aPHNfu1bt3a9feVOa4nTpxQs2bN5HA4NHnyZK1YsUJHjx5VcXGxioqKSt3Q8OdjXBnnxIkTV+1Ts2ZNhYeHu/p88803WrdunSuY/Nz+/fvdDjdhYWHaunWrJOn8+fP6+OOPNXToUNWtW1cZGRlujVEeboWbhx9+WP3799df/vIXLV++XPPnz1d+fr6ky+fTmjdvrvT0dG3evFm33HJLhRULAEBZgmv4a+fz6T5bt1v9goPd6vfzO/Neuamd0+mUJE2fPl2vvvqqZs2apVatWqlmzZrKzMws9Sikf727r81mc43hTp9z584pIyNDU6dOLVXflcDlDj8/PzVu3Nj1vnXr1vroo480depU34cbSbLb7erfv7/69+8v6fKhpgsXLqhu3bo3dItkAABulM1mc+vUkC8lJSUpODhY2dnZGjJkSLnG2LBhg37729+69sVOp1N79+5V8+bNvVmq2rZtq5UrVyohIUEBAd7drv7+/rpw4YJXx/xX5Z5QHBERoZiYGIINAABuCAoK0qhRo/T000/rjTfe0P79+/Xll19q0aJFbo+RlJSktWvX6osvvtCuXbv0hz/8QXl5eV6vddiwYTp9+rT69eunzZs3a//+/VqzZo0GDx4sh8Ph9jiWZSk3N1e5ubk6ePCg5s+frzVr1ui3v/2t12v+uaodcwEAMMi4ceMUEBCg8ePH69ixY4qNjdXQoUPdXn7s2LE6cOCA0tPTFRISokcffVS9e/d2TRXxlri4OG3YsEGjRo1Sz549VVRUpIYNG+qOO+5wPaXAHQUFBa7TWHa7XQ0bNtTzzz+vUaNGebXef2WzPLmGzQAFBQWKiIhQfn6+wsPDfV0OAMBDP/30kw4ePKjExEQFBQX5uhx40bV+W0/239znBgAAGIVwAwAAjFKucHPmzBktXLhQo0ePdt3NcOvWrTp69KhXiwMAAPCUxxOKt2/frrS0NEVEROjQoUN65JFHVKdOHb3zzjs6fPiw3njjjYqoEwAAwC0eH7nJysrSgw8+qO+++67EZJ8777xTn332mVeLAwAA8JTH4Wbz5s36wx/+UKq9fv36ys3N9biAuXPnKiEhQUFBQerQoUOph3/9qzNnzmjYsGGKjY2V3W5XkyZN9MEHH3i8XgAAYCaPT0vZ7XYVFBSUat+7d6/q1avn0VjLly9XVlaW5s2bpw4dOmjWrFlKT0/Xnj17FBUVVap/cXGxbr/9dkVFRentt99W/fr19f3336tWrVqefg0AAGAoj4/c3H333Xr++ed18eJFSZdveX348GGNGjVK9957r0djzZw5U4888ogGDx6s5s2ba968eQoJCdHixYvL7L948WKdPn1a7733njp37qyEhAR17dpVycnJnn4NAABgKI/DzYwZM3Tu3DlFRUXpwoUL6tq1qxo3bqywsDBNmjTJ7XGKi4u1ZcsWpaWl/bMYPz+lpaVp48aNZS6zatUqdezYUcOGDVN0dLRatmypyZMnX/NW0EVFRSooKCjxAgAA5vL4tFRERITWrl2r9evXa/v27Tp37pzatm1bIqS449SpU3I4HIqOji7RHh0drd27d5e5zIEDB/T3v/9dDzzwgD744APt27dPjz/+uC5evKgJEyaUucyUKVM0ceJEj2oDAKCyHTp0SImJidq2bZvatGnj63Ku67bbblObNm00a9YsX5dSSrmfLdWlSxd16dLFm7Vcl9PpVFRUlObPny9/f3+1a9dOR48e1fTp068abkaPHq2srCzX+4KCAsXHx1dWyQAA/KJduHBB9evXl5+fn44ePSq73V7h6/Q43MyePbvMdpvNpqCgIDVu3Fj/7//9P/n7+19znMjISPn7+5d6mmleXp5iYmLKXCY2NlY1atQoMfYtt9yi3NxcFRcXKzAwsNQydru9UjYkAAAobeXKlWrRooUsy9J7772nvn37Vvg6PZ5z88orr2jMmDHKzMzUxIkTNXHiRGVmZmr06NEaN26cevTooaZNm+rIkSPXHCcwMFDt2rVTdna2q83pdCo7O1sdO3Ysc5nOnTtr3759cjqdrra9e/cqNja2zGADAEBV4nQ6NW3aNDVu3Fh2u10NGjQoNV/1wIED6tatm0JCQpScnFxiHuoPP/ygfv36qX79+goJCVGrVq301ltvlVj+tttu04gRI/T000+rTp06iomJ0XPPPVeij81m08KFC3XPPfcoJCRESUlJWrVqVYk+O3bsUK9evRQaGqro6GgNGDBAp06d8vg7L1q0SP3791f//v21aNEij5cvF8tDS5cutW677TZr3759rrbvvvvO6t69u7Vs2TLryJEjVufOna177733umMtW7bMstvt1pIlS6ydO3dajz76qFWrVi0rNzfXsizLGjBggPXMM8+4+h8+fNgKCwuzhg8fbu3Zs8f629/+ZkVFRVkvvvii2/Xn5+dbkqz8/HwPvjUAoKq4cOGCtXPnTuvChQv/bHQ6LavonG9eTqfbtT/99NNW7dq1rSVLllj79u2zPv/8c2vBggWWZVnWwYMHLUlWs2bNrL/97W/Wnj17rPvuu89q2LChdfHiRcuyLOsf//iHNX36dGvbtm3W/v37rdmzZ1v+/v7WV1995VpH165drfDwcOu5556z9u7da73++uuWzWazPvroI1cfSdZNN91kLV261Pruu++sESNGWKGhodYPP/xgWZZl/fjjj1a9evWs0aNHW7t27bK2bt1q3X777Va3bt1KrOfJJ5+85vfdt2+fZbfbrdOnT1s//PCDFRQUZB06dMiz3/b/eLL/tv3fl3TbzTffrJUrV5aa7LRt2zbde++9OnDggL744gvde++9On78+HXHmzNnjqZPn67c3Fy1adNGs2fPVocOHSRdTp8JCQlasmSJq//GjRs1cuRI5eTkqH79+nr44Yc1atSo654Gu8KTR6YDAKqen376SQcPHlRiYuI/75RfXChNjvNNQWOOSYE1r9vt7NmzqlevnubMmaMhQ4aU+vzKhOKFCxfq4YcfliTt3LlTLVq00K5du9SsWbMyx/3Nb36jZs2a6eWXX5Z0ed/pcDj0+eefu/q0b99e3bt310svvSTp8pGbsWPH6oUXXpAkFRYWKjQ0VB9++KHuuOMOvfjii/r888+1Zs0a1xj/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8EHl5OSoadOmGjFihD766KNSywcHB7uOKgHwrQBfFwAAklSjRo0S7202W4m2K4HE6XRKks6dO6eMjAxNnTq11FixsbFlriMyMlLnz59XcXGxAgMDr7v+K+tq27atDh48qA8//FAff/yx+vTpo7S0NL399tuu/qdPn1a9evXc/boAKhDhBkC11LZtW61cuVIJCQkKCHDvn7I2bdpIknbu3On6213h4eHq27ev+vbtq/vuu0933HGHTp8+rTp16ki6PLk5JSXFozEBVAxOSwGoloYNG6bTp0+rX79+2rx5s/bv3681a9Zo8ODBcjgcZS5Tr149tW3bVuvXr/doXTNnztRbb72l3bt3a+/evfrLX/6imJiYEvfp+fzzz9WzZ88b+UoAvIRwA6BaiouL04YNG+RwONSzZ0+1atVKmZmZqlWrlvz8rv5P25AhQ/Tmm296tK6wsDBNmzZNqampuvXWW3Xo0CF98MEHrvVs3LhR+fn5uu+++27oOwHwDm7iB+AX5cKFC2ratKmWL1+ujh07emXMvn37Kjk5WWPGjPHKeABuDEduAPyiBAcH64033rjmzf48UVxcrFatWmnkyJFeGQ/AjePIDQAAMApHbgAAgFEINwAAwCiEGwAAYBTCDQAAMArhBgAAGIVwAwAAjEK4AQAARiHcAAAAoxBuAACAUf4/vUa+J2Znxp4AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] }, "metadata": {}, "output_type": "display_data" @@ -61,22 +63,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.6" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/00FunctionPulse.ipynb b/doc/source/examples/00FunctionPulse.ipynb index 2d0d53edb..1bb33ff91 100644 --- a/doc/source/examples/00FunctionPulse.ipynb +++ b/doc/source/examples/00FunctionPulse.ipynb @@ -18,791 +18,9 @@ "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\Simon\\Documents\\git\\qupulse\\qupulse\\plotting.py:186: UserWarning: Sample count 6288/5 is not an integer. Will be rounded (this changes the sample rate).\n", + " times, voltages, measurements = render(program,\n" + ] }, { "data": { - "text/html": [ - "" - ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAksAAAGwCAYAAAC5ACFFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAACRS0lEQVR4nO3dd3xT9foH8E/SvQfdrFJWQcqGslSEXuYVuS70hyKIoCh6Ab0iXkFFBcGN1yuK4roO3FsEKkORDWXIXmV1UEo3XUl+fyTn5KTNOElOVvt5v159cZqcnHMS2ubJ9/t8n0el0+l0ICIiIiKz1J6+ACIiIiJvxmCJiIiIyAoGS0RERERWMFgiIiIisoLBEhEREZEVDJaIiIiIrGCwRERERGSFv6cvoCnQarW4cOECIiIioFKpPH05REREJINOp0N5eTlSUlKgVlseP2KwpIALFy6gdevWnr4MIiIicsDZs2fRqlUri/czWFJAREQEAP2LHRkZ6eGrISIiIjnKysrQunVr8X3cEgZLChCm3iIjIxksERER+RhbKTRM8CYiIiKygsESERERkRUMloiIiIisYM4SERG5lUajQV1dnacvg5qBgIAA+Pn5OX0cBktEROQWOp0O+fn5KCkp8fSlUDMSHR2NpKQkp+ogMlgiIiK3EAKlhIQEhIaGsogvuZROp0NVVRUKCwsBAMnJyQ4fi8ESERG5nEajEQOlFi1aePpyqJkICQkBABQWFiIhIcHhKTkmeBMRkcsJOUqhoaEevhJqboSfOWfy5BgsERGR23DqjdxNiZ85BktEREREVjBYIiIiIrKCwRIREZGDTp8+DZVKhZycHE9fiixDhw7FrFmz7HrMU089hZ49e9r1mMOHD2PAgAEIDg62+7HWOHL9SmCwRERERIp68sknERYWhiNHjiA7O9tl50lNTcWrr77qsuMLWDqAiIiIFHXixAmMHTsWbdu29fSlKIIjS0RE5BE6nQ5VtfUe+dLpdLKvU6vVYunSpejQoQOCgoLQpk0bPPfccyb7nDx5Etdddx1CQ0PRo0cPbNmyRbzv0qVLuP3229GyZUuEhoYiIyMDn376qcnjhw4dioceegiPPvooYmNjkZSUhKeeespkH5VKhXfeeQf/+Mc/EBoaio4dO+L777832efAgQMYPXo0wsPDkZiYiDvvvBNFRUWynysAPP/880hMTERERASmTp2K6urqRvu888476NKlC4KDg5Geno7//ve/Jte5a9cuLFy4ECqVSnwec+fORadOnRAaGoq0tDTMnz/fZDn/5MmTMX78eJPzzJo1C0OHDjV7nUOHDkVubi5mz54NlUrl0pWWHFkiIiKPuFKnQdcFv3rk3AcXjkRooLy3wHnz5mHFihV45ZVXMGTIEOTl5eHw4cMm+/z73//Giy++iI4dO+Lf//43br/9dhw/fhz+/v6orq5Gnz59MHfuXERGRuKnn37CnXfeifbt26N///7iMT744APMmTMH27Ztw5YtWzB58mQMHjwYf/vb38R9nn76aSxduhQvvPACXn/9dUycOBG5ubmIjY1FSUkJhg0bhnvuuQevvPIKrly5grlz5+LWW2/Fb7/9Juu5fv7553jqqafwxhtvYMiQIfjoo4+wbNkypKWlift8/PHHWLBgAf7zn/+gV69e2LNnD6ZNm4awsDDcddddyMvLQ1ZWFkaNGoVHHnkE4eHhAICIiAi8//77SElJwf79+zFt2jRERETg0UcflXVtDX399dfo0aMHpk+fjmnTpjl0DLl8amRp06ZNuP7665GSkgKVSoVvv/3W5mM2bNiA3r17IygoCB06dMD777/faJ833ngDqampCA4ORmZmJrZv3678xRMRkc8pLy/Ha6+9hqVLl+Kuu+5C+/btMWTIENxzzz0m+z3yyCMYO3YsOnXqhKeffhq5ubk4fvw4AKBly5Z45JFH0LNnT6SlpeHBBx/EqFGj8Pnnn5sco3v37njyySfRsWNHTJo0CX379m2U7zN58mTcfvvt6NChAxYtWoSKigrxPUsIXhYtWoT09HT06tULK1euxPr163H06FFZz/fVV1/F1KlTMXXqVHTu3BnPPvssunbtarLPk08+iZdeegk33ngj2rVrhxtvvBGzZ8/GW2+9BQBISkqCv78/wsPDkZSUJAZLTzzxBAYNGoTU1FRcf/31eOSRRxq9BvaIjY2Fn58fIiIikJSUhKSkJIePZYtPjSxVVlaiR48euPvuu3HjjTfa3P/UqVMYO3Ys7rvvPnz88cfIzs7GPffcg+TkZIwcORIAsGrVKsyZMwfLly9HZmYmXn31VYwcORJHjhxBQkKCq58SEVGzFRLgh4MLR3rs3HIcOnQINTU1GD58uNX9unfvLm4LPcgKCwuRnp4OjUaDRYsW4fPPP8f58+dRW1uLmpqaRtXMpccQjiP0NTO3T1hYGCIjI8V99u7di/Xr14vBidSJEyfQqVMnWc/3vvvuM7lt4MCBWL9+PQD9+/CJEycwdepUk9Gc+vp6REVFWT32qlWrsGzZMpw4cQIVFRWor69HZGSkzWvyBj4VLI0ePRqjR4+Wvf/y5cvRrl07vPTSSwCALl264I8//sArr7wiBksvv/wypk2bhilTpoiP+emnn7By5Uo89thjyj8JIiICoM9tkTsV5ilCbzFbAgICxG0hd0ar1QIAXnjhBbz22mt49dVXkZGRgbCwMMyaNQu1tbUWjyEcRziGnH0qKipw/fXXY8mSJY2uz5kmslIVFRUAgBUrViAzM9PkPmt917Zs2YKJEyfi6aefxsiRIxEVFYXPPvtMfH8GALVa3SiXzJkWJUry7p9SJ23ZsgVZWVkmt40cOVKs0VBbW4tdu3Zh3rx54v1qtRpZWVkmyXkN1dTUoKamRvy+rKxM2QsnIiKv0LFjR4SEhIgzE47YvHkzbrjhBtxxxx0A9EHU0aNHG01vOat379746quvkJqaCn9/x97eu3Tpgm3btmHSpEnibVu3bhW3ExMTkZKSgpMnT2LixImyj/vnn3+ibdu2+Pe//y3elpuba7JPfHw8Dhw4YHJbTk5OowBRKjAwEBqNRvZ1OMqncpbslZ+fj8TERJPbEhMTUVZWhitXrqCoqAgajcbsPvn5+RaPu3jxYkRFRYlfrVu3dsn1ExGRZwUHB2Pu3Ll49NFH8eGHH+LEiRPYunUr3n33XdnH6NixI9auXYs///wThw4dwr333ouCggLFr/WBBx5AcXExbr/9duzYsQMnTpzAr7/+iilTpsgOKP75z39i5cqVeO+993D06FE8+eST+Ouvv0z2efrpp7F48WIsW7YMR48exf79+/Hee+/h5Zdftnjcjh074syZM/jss89w4sQJLFu2DN98843JPsOGDcPOnTvx4Ycf4tixY3jyyScbBU8NpaamYtOmTTh//rzdq/7s0aSDJVeZN28eSktLxa+zZ896+pKIiMhF5s+fj4cffhgLFixAly5dMGHChEa5RNY88cQT6N27N0aOHImhQ4ciKSmp0RJ5JaSkpGDz5s3QaDQYMWIEMjIyMGvWLERHR0Otlvd2P2HCBMyfPx+PPvoo+vTpg9zcXMyYMcNkn3vuuQfvvPMO3nvvPWRkZODaa6/F+++/j3bt2lk87rhx4zB79mzMnDkTPXv2xJ9//on58+eb7DNy5Ejx3P369UN5ebnJCJc5CxcuxOnTp9G+fXvEx8fLeo6OUOnsKTbhRVQqFb755hurP3DXXHMNevfubVLd87333sOsWbNQWlqK2tpahIaG4ssvvzQ5zl133YWSkhJ89913sq6lrKwMUVFRKC0t9ZlkNSIid6qursapU6fQrl07BAcHe/pyqBmx9rMn9/27SY8sDRw4sNGyy7Vr12LgwIEA9HOdffr0MdlHq9UiOztb3IeIiIiaN58KlioqKpCTkyM2LDx16hRycnJw5swZAPrpMemQ3X333YeTJ0/i0UcfxeHDh/Hf//4Xn3/+OWbPni3uM2fOHKxYsQIffPABDh06hBkzZqCyslJcHUdERETNm0+thtu5cyeuu+468fs5c+YA0E+bvf/++8jLyxMDJwBo164dfvrpJ8yePRuvvfYaWrVqhXfeeUcsGwDo52cvXryIBQsWID8/Hz179sTq1asbJX0TERFR8+SzOUvexB05S9V1GtRrdQgP8qn4logIgDFvJDU1VXbtIiIlXLlyBadPn2bOUlNXWlWH9Pmr0e3JX/HJtjO2H0BE5GWEWjlVVVUevhJqboSfOWv1mmzhMIUPeGvTCXF70c+H8H+ZbTx4NURE9vPz80N0dLS45D40NNSlXeKJdDodqqqqUFhYiOjoaKsVxm1hsOQDduZeFrcraupRr9HC34+DgkTkW4RGp/bUKCJyVnR0tNNNdhks+YB950pMvtcyy4yIfJBKpUJycjISEhK8pucXNW0BAQFOjSgJGCz5gOiQQOTXVYvfbz9VjCEd4zx4RUREjvPz81PkDYzIXTiX4+XqNFrkl1Wb3HbuMhMkiYiI3IXBkpfLOVsibl+VwlYqRERE7sZgycvVabTidnKUvj7EtznnPXU5REREzQ6DJR/RKTEcZVfqAQAaZngTERG5DYMlL7f5eJG4fdegVABgbRIiIiI3YrDk5fJK9MndZ4uvgDESERGR+zFY8nJqtT5CeuC69uJt208Ve+pyiIiImh0GSz7C30+NqBBjX5uL5TUevBoiIqLmg8GSl9NJcrkHpLUQt2vqNR64GiIiouaHwZKX+2r3OXHbT61CkD//y4iIiNyJ77xeTkjqbh0T6tkLISIiaqYYLHk5YQFcv9QYk9tr67WNdyYiIiLFMVjyMTWGIGn1X/kevhIiIqLmgcGSj4kI8gcAaDSs4k1EROQODJa8XMPOJn/vkeKZCyEiImqmGCx5sb1nS4zfsHo3ERGRRzBY8mKnL1WK2/HhQR68EiIiouaLwZIPGNIhrlHz3Ko6FqUkIiJyBwZLPkaj1a+Ge2vjCQ9fCRERUfPAYMnHdEgIBwC0bRHm4SshIiJqHhgs+ZjebWJs70RERESKYbDkxfJLqz19CURERM0egyUv9tP+PABARU29h6+EiIio+WKw5MWiQwMBAL3aRHvk/Ltyi3G8sNwj5yYiIvIW/p6+ALIto2VUo9tOFVWa2VM5L605gtd/Ow4A+Pr+QcyVIiKiZosjSz5GrTbWW7pQcsVl5xECJQD4Yuc5l52HiIjI2zFY8jHdUoyjTPll7kkA/3T7Gbech4iIyBv5XLD0xhtvIDU1FcHBwcjMzMT27dst7jt06FCoVKpGX2PHjhX3mTx5cqP7R40a5Y6n4pBAfzVax4a49Bx/XSg1+T4mNMCl5yMiIvJmPpWztGrVKsyZMwfLly9HZmYmXn31VYwcORJHjhxBQkJCo/2//vpr1NbWit9funQJPXr0wC233GKy36hRo/Dee++J3wcFNe8+bMcKKky+v1xVh4qaeoQH+dSPCxERkSJ8amTp5ZdfxrRp0zBlyhR07doVy5cvR2hoKFauXGl2/9jYWCQlJYlfa9euRWhoaKNgKSgoyGS/mBjrycw1NTUoKysz+XKFTUcvuuS4thRX6gPM7q2MU367ci975FqIiIg8zWeCpdraWuzatQtZWVnibWq1GllZWdiyZYusY7z77ru47bbbEBZm2ipkw4YNSEhIQOfOnTFjxgxcunTJ6nEWL16MqKgo8at169b2PyEbLlcaR8SSo1w77dbQV7v1Cd2BfmokRQYDALQ6nVuvgYiIyFv4TLBUVFQEjUaDxMREk9sTExORn59v8/Hbt2/HgQMHcM8995jcPmrUKHz44YfIzs7GkiVLsHHjRowePRoajcbisebNm4fS0lLx6+zZs449KSs0kuBkQFqs4se3JjZMX9+pc1IE4iP0U5J7z5a49RqIiIi8RbNJQnn33XeRkZGB/v37m9x+2223idsZGRno3r072rdvjw0bNmD48OFmjxUUFOTWvCaVSmX2dunokyv0TY3BmoMFAICDF1wz1UhEROTtfGZkKS4uDn5+figoKDC5vaCgAElJSVYfW1lZic8++wxTp061eZ60tDTExcXh+PHjNvf1lLIr+vYnqw/YHlFzxO/HisTt2/vppxiDAvxcci4iIiJv5zPBUmBgIPr06YPs7GzxNq1Wi+zsbAwcONDqY7/44gvU1NTgjjvusHmec+fO4dKlS0hOTnb6ml2la3IkACDYBQHMpYoacbtVTChiDFNyREREzZXPBEsAMGfOHKxYsQIffPABDh06hBkzZqCyshJTpkwBAEyaNAnz5s1r9Lh3330X48ePR4sWLUxur6iowL/+9S9s3boVp0+fRnZ2Nm644QZ06NABI0eOdMtzckT/dq7LYdJK8rj7pRrP88PeCy47JxERkTfzqZylCRMm4OLFi1iwYAHy8/PRs2dPrF69Wkz6PnPmDNRq0/jvyJEj+OOPP7BmzZpGx/Pz88O+ffvwwQcfoKSkBCkpKRgxYgSeeeaZZl9rSRATahxZqtdo4e/nU/E1ERGR03wqWAKAmTNnYubMmWbv27BhQ6PbOnfuDJ2FZe8hISH49ddflbw8xXhqpX6tRmvy/dDO8eI2iwcQEVFzxGECL5V9qMD2Ti6w5i/TpHEVzK/EIyIiai4YLHmp8up6j5y3zjCyFOTPHw0iIiKAwZLXu7FXS4+cd2z3xqsBWZiSiIiaIwZLPuyjrbkuP0dkiDGt7eTFSpefj4iIyNswWPJBQjuS0EDl6yxV15kmeKtUKgxPT1D8PERERL6CwZIPuq6zPnhxRer125tOAgA0Wq59IyIiAhgsUQOtYkIAAG1iQz18JURERN6BwRKZNSCtRaPbNhwt9MCVEBEReRaDJbKpuKoWAJBfWu3hKyEiInI/Bkte6n/bXL/STa6JmW0BAAEubnWyK7cY9360Eyv/OOXS8xAREdnD59qdNBchAfqVbho39z05UlBu8VpcqU6jxU1vbgEA/PpXAcZkJCMpKtjl5yUiIrKFI0te7uY+rdx2rsKyarEnnZ/avW1Otp68ZPL9j/suuPX8REREljBY8mGVtRpcqdUodryLFTXidq820YodV47950tNvn/nd07FERGRd2Cw5IOiQgLE7T9PFCl+/ISIIAT5N55623aqWPFzCT7aYpqjJX2OREREnsRgyQdFhQaIjW7rNK7PaWoRHihuF5a7ZkVcRLA+fS7FkKd0pKAcWhbGJCIiL8BgyUd1axnltnP1T40Vt10VnB0tqAAAzBjaXrztWGGFS85FRERkDwZLZJNarUKgv+t+VC6UXBG305MjxW22XCEiIm/AYIlEZ4urPHLe4spacbtn62gkRAQBAHadueyR6yEiIpJisESiLSf0y/cLy2ts7OkaSZHBCPBTi+c/dbHSI9dBREQkxWDJC9VptDic37g4pKsJFbpHd0ty63nX/JUPANBBP+129+B2AAA3l3oiIiIyi8GSFzpx0ZjY3DY2zO3nb9vC8jlzzpQofr6KGn2tqEsV+um4AH99lJTHXnREROQFGCx5IWmHkzYtQj13IRK19VoAwMmLrluhNu2aNABAvWHF3U/781x2LiIiIrkYLHmxeEOiszUbjxa64UqACX1bAwBULpgaq9NoTb7v305fqqBFWKC53YmIiNyKwZKPyjdMUV0sr7WxpzLULvxJ+Wirvnq31jCk1i7O/VOPREREljBY8lHTrtYnQfsp+D9Y4KFVcDGh+tYm7ePCTW6/VOmeQJCIiMgaBks+KsAFRSJ/2HsBAFDfYFrMXXq3jQYASGf6XJkjRUREJAeDJRLFGnKE+kram3hCWrxxhOmMhwplEhERCRgsUSPt4y3nDG06WqToueo1WlyuqjO5zU+tQreWkRYeQURE5F4MlkiWqlp9LSSlR3q2ny4WtyOCAxQ9thy19VqcvFgBnY596IiIyDx/T18A+YbxPVviu5wLCA30U/S4NXXG/KjEyOBG9+e7sDBlSVUtei5cCwBIiw/Dbw8Pddm5iIjId3FkyQutPmBo/+FFgx3hwa6Nq7u3ijL5vvSKfmpuzcECl53z5bVHxe2TFyvFcxIREUn5XLD0xhtvIDU1FcHBwcjMzMT27dst7vv+++9DpVKZfAUHm45e6HQ6LFiwAMnJyQgJCUFWVhaOHTvm6qdhVVVtPQDgclXzXTrft60+yTw8yHVB2odbck2+33T0osvORUREvsungqVVq1Zhzpw5ePLJJ7F792706NEDI0eORGGh5SrWkZGRyMvLE79yc03fIJcuXYply5Zh+fLl2LZtG8LCwjBy5EhUV3u+L9k9hlpK1hzMK1PkXDqdDsUeqGtkKSDs1jLK7O2u9M7vJ91+TiIi8n4+FSy9/PLLmDZtGqZMmYKuXbti+fLlCA0NxcqVKy0+RqVSISkpSfxKTEwU79PpdHj11VfxxBNP4IYbbkD37t3x4Ycf4sKFC/j222/d8Iwc52foO3K2+IrYt80Zf10wBl3+Sla6tOG7HH1tp8qaeredEwBOFVWK221i9f33IkPcn2BORETez2eCpdraWuzatQtZWVnibWq1GllZWdiyZYvFx1VUVKBt27Zo3bo1brjhBvz111/ifadOnUJ+fr7JMaOiopCZmWn1mDU1NSgrKzP5crehnRPE7Ya91RxxscJYvTvVjc17Iwy5UJ0SI8ze76qpyFNFxmKXM4d1AAD8fqwIGq0XJYoREZFX8JlgqaioCBqNxmRkCAASExORn59v9jGdO3fGypUr8d133+F///sftFotBg0ahHPnzgGA+Dh7jgkAixcvRlRUlPjVunVrZ56aQ6JDXTMK0q1lJFRWuuWeLKpUJDhrSGieKxCW8v9+rMgly/p3nL4MAOjRKgp928aIt5c04zwxIiIyz2eCJUcMHDgQkyZNQs+ePXHttdfi66+/Rnx8PN566y2njjtv3jyUlpaKX2fPnlXoir1XkmRZ/yGF8qSsyWzXQtx2xWDP8UL9yFJeabVJxfBaD7V6ISIi7+UzwVJcXBz8/PxQUGC6lLygoABJSUmyjhEQEIBevXrh+PHjACA+zt5jBgUFITIy0uSrqWsda5yac8dMVevYEJceP9DQW+/OAW1Nbl/zl+tKFRARkW/ymWApMDAQffr0QXZ2tnibVqtFdnY2Bg4cKOsYGo0G+/fvR3JyMgCgXbt2SEpKMjlmWVkZtm3bJvuYzUmrGOUDmB/35Sl+TDl+MpxXyJkSgiclkuWJiKhp8ZlgCQDmzJmDFStW4IMPPsChQ4cwY8YMVFZWYsqUKQCASZMmYd68eeL+CxcuxJo1a3Dy5Ens3r0bd9xxB3Jzc3HPPfcA0K+UmzVrFp599ll8//332L9/PyZNmoSUlBSMHz/eE0+xWamXTHmFBbqvmLw05yrG0Dx4bIY+gK6sde+qPCIi8n4+1e5kwoQJuHjxIhYsWID8/Hz07NkTq1evFhO0z5w5A7XaGP9dvnwZ06ZNQ35+PmJiYtCnTx/8+eef6Nq1q7jPo48+isrKSkyfPh0lJSUYMmQIVq9e3ah4JSlPOps3vEuCxf3qNFr4qZVrsyLNFxdWFQoB1Mo/TmFWVifFzkVERL7Pp4IlAJg5cyZmzpxp9r4NGzaYfP/KK6/glVdesXo8lUqFhQsXYuHChUpdotO+NdQecqdtJ4tt7+RCDWs7BUi+X3+4EKMNIz9K0EnCNGHhn5Dk3TLGfWUTiIjIN/jUNFxzUV2rAeDe3nBnivVFGi+UeL5yOQCESdqclCtcsPKPY0XittoQLfVLjbG0OxERNXMMlryQkGw8rkeKrP2VSEr2N0xfTh1iu8VKmZsazg5Ltzw154yL5cYCnA17zx3KK3NJXSciIvJdDJa8WICVtiNqSeHI7MOWe+PZKyTAcm6Q0JLkJ4VWsHm6WnZWF2Mx0pjQQHFb2grFFQrKqpFf6h0jeEREZBuDJR8ljD4BwBU3reAS8nqCApT5sdl49KK47a+2XDVcaVfqNI1uuyrFWCurxoXlA1b+cQqZi7IxYHE2Xvz1iMvOQ0REymGw5MNGd5NXjFMpgzvEKXo8aWuRsCDLaw2Ubq/y/p+nAQD1WuNxVSoV4iOCFD1PQzqdDgt/PCh+/5/1x116PiIiUgaDJfK44RZyk+oN03Tv/nFK0fMlRujLQqREmy+yeanCNf3h8ssaT70dznd/E2YiIrIPgyXyWnGGgpEJLhrxGdJgpOxypT5IWnfINS1PNkmmHQXf7DnvknMREZFyGCyR17rORavhLOndRl8+IMDPNflTn2zXN1xOiw9DsCHvq9hFo1hERKQcBksEAPh+r/sLYXqCTqfD9tPmC3D2ahPt0nMHGJLYW0aH4MFhHQEAX+w659JzEhGR83yugjcpT7qEPzRQubYithzKK3fbuQTSvCFLOUuuoNPpsDP3MgBgYmYbVBkKj/q5cRUgERE5hiNLZFKEMatropU99X45kK/Iebed0o/wlLqpyCVgGhj2bB1tdp8VvyubUA4AeZK6SomRwRjUPk68nmozpQyIiMh7MFjyMlW19bhU6bk8lgC17R+JSxU1NveRIzJYP7A58irrJRC2uqBvXbCZWlExhoTyFmGBje5zVsMgLUQygve7pP0KERF5HwZLXmaXYaoGgMvr/thrTIY+qAkNVHb21tJ0WESw8TzFbgggr+usTyhXuWBmbNMx/Uq44AA1VCoVokICxPvMFckkIiLvwWDJywgDEJHB/oi1McIhzJ65YtrInGB/9+UzAaZL+2vqlQkojhVUKHIcexWV64O96jpjIcxB7VsAADYcUa5dDRERKY/BkpdqHRtqcx+h7UiLcOWnjbyBv58agVb64zki52wJANOgpaEaK/c5a2JmG3FbaOhbWKbMtCYREbkGgyUf9vfuKZ6+BJ8jrD67oafl1668ph55pVcUPe+K3082um3K4HYAAH8X1XWSqtNoTRL5iYhIPpYOII85fanSY+c214uubQvjaN7RggokRylXWiA2LBAVNfUICTBOZQrNkDccaVzZW0l3vrtNTCLf9vhwJEYGu/R8RERNDUeWyCMqaupRYJh+UnimzWHBAX64KiXSJccWksZHZySLt0mTvMurXVM+4WhBuclqu1uWb3HJeYiImjIveZsiT/rrgvubuUprKw1q0KPNnLIr9Yqc98RF9yd463Q65F6qanT7tZ3ixe06jWumyN7bbJr8f6a4SrFkeSKi5oLBEuFIvrGSdmSI7ZnZipp6k7pBzgjyVyMyOMDi/bUafbK1Us1t1x7UH8edhSCPSlbghQUZp+H83VC9+/Od+nYqMaHG1zjnTInLz0tE1JQwWCLRsPQEqKwUGZIWUtx+SvlCkeZI84iUkGCoXTXExmjWTgv94xxRUWMcReucGOHy8wk0Wp0Y1D46Kl28fcNR1+ZIERE1NQyWSDZpYrCrcmwaGpjWwiXHbWOhNMOFEv0quJMXlU8+b9si1CQYVUtGls4UN56mc9b+86Xi9pAOceifGgsA+JLNe4mI7MJgiezSu020py/BpSYPUn45v7VAaLyVEgbO+uuCMVhqHRuKzkn6US0/V5QoJyJqwhgseZmKamUSmckx0pwipfxx7BIA68UntS6ogbTHkJskFPa8qU8rAEB+WTXqNa4rvElE1NQwWPIyX+/WT5HY0y9sjw8m7BaVu79qtVarw2kzq9JcTWjaO+KqxEb3CXny/91wQvHzFhpe41v76YOkOEml973nSs0+hoiIGmOw5GXCDc1jLeXUSAVIporc0WhWSUIhxpp6eSMcSqy+O5hnLJEQY6PvXp0LRl7S4sIb3Sa0qklRsACmYJMhkbtFmD6pvVWM8WeK5QOIiOSzO1iqqanBpk2b8NFHH+Gtt97C119/jVOn3NPItTm5umO8zX0GSJKfpXWLfIGQ29ytpfUikML01H9+O+70OWslAVD7+MaBi9TP+/MVaw9iLWfpus4JipzDHGFEa2B7489JqmF14aodZ112XkC/AGDn6WJcqWVQRkS+T3a7k82bN+O1117DDz/8gLq6OkRFRSEkJATFxcWoqalBWloapk+fjvvuuw8REeaXR5OyggP8EBHsj3IfznPKaBll9f54w1L/VrHKjbxYG7W7KsV4PTqdsfK2M4QK2ho39marrtOIzYJbxRhfuwBD/lKwv/K5WYLTRZUY+uIG8fv9T41AhJVaWkRE3k7WyNK4ceMwYcIEpKamYs2aNSgvL8elS5dw7tw5VFVV4dixY3jiiSeQnZ2NTp06Ye3ata6+blLQB1tOA4BXNlq9RsYIm5LSk5QP9IV+cIPaWy6DcDCvTNGpsc3HjS1OIoKMgcr4Xi0BADtzXVcna9x//jD5fs7ne112LiIid5A1sjR27Fh89dVXCAgw/+kwLS0NaWlpuOuuu3Dw4EHk5eUpepHkWhGGPClrBSkb+jbnPEZcleSqS2qSWkY3Hh3rmGicDjxVVIn0JGV600lzwaJCG//ennBBHSlAn0Rf1mCkc+3BAuh0Ort+voiIvImskaV7773XYqDUUNeuXTF8+HCnLoo848beLW3uI7wRKtXuxJ08sQLPluSoEIQFKj8lJrSwEQpRCoal63OkAhSsIyW1TVLZ/dUJPcVtVxTdJCJyF59bDffGG28gNTUVwcHByMzMxPbt2y3uu2LFClx99dWIiYlBTEwMsrKyGu0/efJkqFQqk69Ro0a5+mn4rMmDUgEAKvjeKMEaQ1+4kir3rRwsq66zWQYixAXBktCO5lKlaYAYbRhlqtPoXBLw/m9brrj99+7J4raQt0VE5IsUC5buuusuDBs2TKnDmbVq1SrMmTMHTz75JHbv3o0ePXpg5MiRKCwsNLv/hg0bcPvtt2P9+vXYsmULWrdujREjRuD8+fMm+40aNQp5eXni16effurS50HAnrMlbj+nsDqsZ5sYi/tIZ4p25l52+pxbT1wSt6PNTIdJlV1RLlE/LEg/tTq6W7LJ7UKBSgDYIrk2pZQZVmW2jw+Dv58aXZP104pvbVK+jhQRkbsoFiy1bNkSbdu2VepwZr388suYNm0apkyZgq5du2L58uUIDQ3FypUrze7/8ccf4/7770fPnj2Rnp6Od955B1qtFtnZ2Sb7BQUFISkpSfyKibH8ZkrKyDEES3KXlivZq81ay5aoEGNAk3vJ+XMKpQ8SIoIsrggTpjZXH8h3+nyCogr9iJJ0JRwAtAgPErcvKzzCptHqxBGkaVenATAmzNdrfG/alohIoFiwtGjRIrz33ntKHa6R2tpa7Nq1C1lZWeJtarUaWVlZ2LJli6xjVFVVoa6uDrGxpnkcGzZsQEJCAjp37owZM2bg0iXrn7hrampQVlZm8kX2iTYEJbaSxKVTVCcvVrj0mgB9kvvQzsqvwGvbwnK5AqHmk1J5RHUarRiMmsupdlVz4ooa48hY77b6DxxjMvQjW3ml1ShzU/NlIiKl+UzOUlFRETQaDRITTVtGJCYmIj9f3ifyuXPnIiUlxSTgGjVqFD788ENkZ2djyZIl2LhxI0aPHg2NxvKIx+LFixEVFSV+tW7d2rEnRWIdJUu6Seoe+XI9KWuu7hin6PGkOVKD2jc+tg76UZ7/bc1tdJ8z9ktaqLSLCwMA9E8zfjAprnBdrphOp8OWE5fw0dZcVNY0zZ8TIvIc2UUpBXfffbfV+y1NiXna888/j88++wwbNmxAcHCwePttt90mbmdkZKB79+5o3749NmzYYHFV37x58zBnzhzx+7KyMsUCpt8Om8+/sqXajl5yvkStVqFldAjOl1xx+lieKCO19qBj/59KSYwMbnSbkNcdqnBi+dGCcnHb31CiPTI4AOFB/qioqcf6I4WYEtdO0XMKRr/2Ow4bVgDO//YATiwaAz+17y1CICLvZPfI0uXLl02+CgsL8dtvv+Hrr79GSUmJCy5RLy4uDn5+figoKDC5vaCgAElJ1qdyXnzxRTz//PNYs2YNunfvbnXftLQ0xMXF4fhxy+01goKCEBkZafKlBK1WJ46eyJ2SEXJ+ft7P2la2fLztjNvPKay8KyizXbbgx33K/B+WVlmf7rqlTytFztPQ1pP66eu/d082qakkTM9ddlH/wksVNWKgJFiWfcwl5yKi5snuYOmbb74x+frxxx9x8uRJTJgwAQMGDHDFNQIAAgMD0adPH5PkbCFZe+DAgRYft3TpUjzzzDNYvXo1+vbta/M8586dw6VLl5CcnGxzX6VJBz6Gd2ncod6cFuHWG8LKsfWk/dWcL1Z4X80iW4SRlOSoxqMt5nymQP80tWF0Y/o1aRb3EZbwK5XTs+GIcTTL2ujKBkOjXaWcLNInxFc0mAabNFC/8OMXBRPYpd7c0Hil3WsMlohIQYrkLKnVasyZMwevvPKKEoezaM6cOVixYgU++OADHDp0CDNmzEBlZSWmTJkCAJg0aRLmzZsn7r9kyRLMnz8fK1euRGpqKvLz85Gfn4+KCn2icEVFBf71r39h69atOH36NLKzs3HDDTegQ4cOGDlypEufiy2hAfKmSEY5WUW7sLxa3I4Lt54/JLUr9zLqJY1pfcnANOs5QnWG5yVdZu8sa0HLDT1TAABBCvVrE4KvltEhZs8bGqiffdfpgKpa5fJ7hNIM43uaFjetNVQTL3FRs+ev9+hLgYQF+mHJTRni7a4aySKi5kexd4MTJ06gvt61iZUTJkzAiy++iAULFqBnz57IycnB6tWrxaTvM2fOmLRaefPNN1FbW4ubb74ZycnJ4teLL74IAPDz88O+ffswbtw4dOrUCVOnTkWfPn3w+++/IyhIfuDgy6RLujPbxVrZU0/awb7WiWDJVW+cSpjQrw0AZZroyhHo75p1Fj0tlEiQrvarqVMm4K2u0+DAef2qUGn5BQD4Ry/bleEdVVlTj2JDUDRnRGf8vXuKeN+vf7lmJIuImh+7E7ylic2AfhVKXl4efvrpJ9x1112KXZglM2fOxMyZM83et2HDBpPvT58+bfVYISEh+PXXXxW6Mt8W6K+W1btL7hSWNUUVNeIbnD3xSF5pNXr42MLDtQcLbO+ksI02pteCZY5a2uPcZWM7k64ppjl8QYbzXSyvwaWKGpNaT846mGcs2/GPXi0RFuSPhIggFJbX4Pu9F3Bb/zaKnYuImi+7g6U9e/aYfK9WqxEfH4+XXnrJ5ko5IgA4K+kTdpWkNIAlQoHFDUcKMaqb7zTvlRbcjLRQkFKqqKIGNfUap6fj8kr1U6tlMkbvCstrEBPmfN6bIDLYv9EKvI4JxmbBJy5WKhosrTGMHvmpVYg1PI/BHeLwzZ7z+NMFFcobqqiph79a5ZIAlIi8h93B0vr1611xHdQMtY4NkdUX7eqO8Vh3qABBTk5XVcmsFq6Ueq1xistaoctYSbCy6/RlDOrgXN0l4XW6pa/5YTjpaN4fx4vQ2VBl2xm/7NcHLeZGJ8OC/JEWH4aTFyvFiuZKyT6kT2ZPlzyHv3VNxDeGPKbqOo3LApn2j/8s5ofd2rcVlt7cwyXnISLP85milNR8dU12/s1cWjBRLfOnXsmRCWsJ3gkRxpGYegWb24YHmQ8S1GoVerSyPaJnjypDna9SC6NZQlCxSoEVhlLCqsx+qcZ8u2s7GQNTJdvkSH28LdekEfHnO8+ZjJgSUdOiWLD0+OOPcxqOvJa0qGXL6BAre5omKBe7aUVVl2RlanUBwF5JYGhJqqHCtlKEAaO7B5svOulnGHFydnRQSiOpS3Z9D2OpjxDJSNKuM843Qzbn398caHTb/R/vdsm5iMjzFPvLdf78eZsJ1USe1rdtjM1E9iGSaTBh2buvuCAJCsODbOdJSWsyOWP5Rn2tIx3Mj4zd2Fu/Iq5SwanQPZJASJonpVYb+/v9uPeCYucTSJPZnxnfDWmGwHP/+VLoPFEmnohcTrFg6YMPPsBvv/2m1OGIPMZPrVKkqe0fx4rEbbllCM5ddq6tizQvq6+hma05woiMkAzurCRDsGKpVpcwY/WDgsGLdNSvVYxpo2KhJEKNC4LdtzedFLcn9G2NZbf3Er8XGhgTUdPCnKUm4oqbk5cB4xsgmSetcm5rhZtQQFGpkZ7o0ACxerg5Nxtanig5LQaY5gtJZRhypJSsKfXV7nMAgNQWoY3uu2uQvmq4K4KXnw3J7NGhAQj0V6NbS2P+1+c7zyl+PimdToeKmnqOYBG5md2r4QCgsrISGzduxJkzZ1Bba5rT8dBDDylyYc2RdPWUXBrDH813/jiFJ/7e1e7Hbz9lX6sTtWSIZMORQpMigHIVOdh93lc/tY/NsN065+qOcfhi1zmEBTn0K2k3JZvo1tRrkF9mfYSqc6IhSV/B93jhtUoyU/srOtS4wrCgrNpsQ2FHCaUsHhzWUbytc2IEjhSU49PtZ7D4xgxLD3XK2eIqXL3UuBr5rTv7YKSTFfyJSB6H6iyNGTMGVVVVqKysRGxsLIqKihAaGoqEhAQGS07YeMRYTNBf5jRQ+3h9DRtbScuWCCt45ObmSJdhl9ho2GqJUBtH7uOFFWJyEpctqfPy1ixKLN8HgNUH9BXstTKH/f66UGZ7JxtyzpSI2/ER1mso1Wq0OFtchdaxjUeD7PX1bn15gGHpCY3u6y9ZHVddp9yoq3TF298k/Rtv7tMKz/18CIB+9EdOgVd7SQMlALj3o104/Mwo1ngicgO7x8Rnz56N66+/HpcvX0ZISAi2bt2K3Nxc9OnTR2wjQo6RLruOkFHEEAB6t7GclyKH8Dd9goWaPOY4249O+OPes3W0rP2Hd9G/GUY4Mery0dZcAECdzCBCmOXYftr+JsOeJOQslVVbbz0ULnktpQnLjpAuobc0giMNovaeK3HqfNaOLVCrVeLomZJtT6QjscnRxucqHeFRIgBtaI+FVX1P/3BQ8XMRUWN2B0s5OTl4+OGHoVar4efnh5qaGrRu3RpLly7F448/7oprbHaus1LA0FXc1QdNqpfMQC82zPmKz9GGcgDRIfKCUGE0y5naOX+dt/9Ns9xGkCPXlMGpVu+XBtnOFusUYiVxqs2MAD81+qU6F9hbMqSD+d8X4XlV1Cg3svTuH6cAAP3bxSJA0mi5daxxZNfeqW05Zq3KEbdPLR4jbn+6/Yzi5yKixuwOlgICAqA2VPVLSEjAmTP6X9aoqCicPatswTkipcnN8bjFkADtDGFUqrzGdgAkVLZed6jALcm7arUKLRRqcyK8YdvKuRMKcyox8iINSCzlsd85QJ/k/ccx673y7CH8zzRsX6NSqcRE8/UKJekLauu1yL2kD9rHdk+GSqXC+1P6ifcfdMFIllR1ncYjC0iIvInd8xq9evXCjh070LFjR1x77bVYsGABioqK8NFHH6Fbt26uuEYit1NipC3SMIo1omuijT2BPlaW+dvjd0m5Armcjc2EaVXpSIs5lwyJ/btznS8Ueb7EOOJnqdeckKt0+pIylbWr6zQ4ZGjcO65n44UNV3eMx+lLuQ79H1jz5wnj8f49pgsA01WHH2/LxXP/cE1S+R3vbMMfx43nXz3raqQnKVdAlchX2D2ytGjRIiQn61f3PPfcc4iJicGMGTNw8eJFvP3224pfIJGvSzazWquhdnHhNveR43SRvr2HnIR9YSXlj/uUqX00vldLq/df30MfYCix4u9CiX713dUdLffRG9s92XA+ZRKgpY2JB6a1aHR/d0kLGSWLmX65y1iOIMWwkEOlUon98L7LUb7wJqAP0qSBEgCMevV3kxw1oubC7mCpb9++uO666wDop+FWr16NsrIy7Nq1Cz16sJEkkSeFB+sDETnlCoSplVonVwpuPCpvmksoXFlT7/yUzi+GVX+VVqY4hbY1Z4uvoKrW+VwwIXBQqcwnlWdJVseVVzu2UtScrSf1PQr/1mCEcmJmGwBARU29Is+vof9bsU3cvmNAG3H7texjip+LyNuxKCX5DDm5P5Y4+mH4spt6wyktUkYi+6SBbRU5l1B3yE/m3OXm45dQ72SAFmOoo9RXUiKgoTaS8gRK5EkVluufp6Vpy1DJCNb6I8rkSVXV1ot1yRquQh0jCYh3nla2B97hfOPr9eCwDnh2vHGab5kbgqWSqlqUVPnm7x41TbKCpVGjRmHr1q029ysvL8eSJUvwxhtvOH1h5P0crV9j71JuaQLvXxfsr7Wk0+mw7lCBfltmVURhGuXjbY6tNtLpdNjrYBHNyw7Wr/IU4f8ny0ZuVh/JarhKJ1eoCXlBXa00IG4RHqRYEjsArNqhX8Bys4Xk/yB/P7Ekg7PlGASH8srF7WsaVEdvER4kVmBfrWB5BABY9PNhcfufw/XFN/87sbd42/HC8kaPUUJNvQapj/2EngvXoufCtUh97Cero4dE7iIrWLrllltw0003oWvXrpg7dy6++OILbN68Gbt27cK6deuwbNky3HrrrUhOTsbu3btx/fXXu/q6SSGOJPcKq55WGpZR20vaBkQO6QiBkKtiD+nS+KtSoqzsaSS0sGgZ42ixT2OPN1uFGgHTitobjzq2mqqypt6hXm9CcUdn2coNaqtAIUoAKJNMcYXYqEQeYZiWVKInnbCaz9qoWK820QCAb/co85p+s0efrxQR7G/250jIk1K6hMAmw9Rql+RI+BsS96UrSZ/63jX1nTo/sbrRbVc9+atLzkVkD1nB0tSpU3Hy5Ek8/vjjOHjwIKZPn46rr74a/fr1w8iRI7FixQq0adMGO3bswKpVq9CmTRvbByWv8Pr64wDsC5qEauHm2kzIERaofwMbkyFvGb9KpRLfhJyVLrNStrTflyPqJMvoM2QcKzjAD+0M3esdnaHaJ6lwniKjorswNelMdfPSqjqHpjgrncixkY5oWupFJxAKvdZpnE9KPl5YAQC41UoBV6HQqlJta3bllgAwTjs2dE1H/fNXstrEyYsV4vZjo9PFbT+18fewYeK3EqSr/gBjoAsoF3wSOUp2zlJQUBDuuOMO/PDDD7h8+TIuX76MCxcuoLq6Gvv378eLL76ILl26uPJayYrzJVdQ4cBwdSvDyElsuPzpisEdLK9AskdIM2jTEBnsL7v1RRsnR16EKca48EDEyph+Gt9Tv3rN1pJ/azZJahhFBFnPk5K+DtmGaVFH1NRpDceDzVYfdw9up3+Mk0nlpwyrDAHrgZAwcvnXhTJF2qwIpQpGW/hgMaa7MW8p91Kl2X3stXKzccR4SIPf9UdHGoOn8yVXoCRpQvmJRWOwd8EI8XtpUU6llVfXocfTazDhrS246c0/8dbGEy47F/kuh/9KRkVFISkpCQEB8ioik2uYJLGed7x32nWdG/fXIt9kaRSiIT9L1RztICwjT4kKtjkl5qdWISZU//fCmZGetQcN+WcyDiGMejk71SjNm5GWCGiod9tocbuwzL7p5oakAd6IruaDJenvv1LFKbMP6aeBEyODGv2MDEgzJtT/vC9PkfMBQKGkEfOkgW3hp1ZBrVZhgaQ5+H4nekNaUl2nQcZTa1B6pQ7bThVjV+5lLP7lMF749bDtB1OzwtVwXuR/hmRie95GYsICxSXZ1DTIbYKrlIvlzr2pA0D7BHl1oq7u6HwrH2HaMDjA9p+vrin6BHAhEdpRQgCRFBlsdaQwISJYzD87WVRhcT85pFXKLY06BvipxST3TxTIW6rXaMW8txnXtm90v0qlEqfH3thw3OnzCZ7/xRicSKf+Jg9KNd7+9T7FzicY/tJGs7e/sf4ECsrsz/+zh1arw+XKWtat8hEMlrxIqGFKwd5fnlCFiu5RY0Keir0cmRIRWp6862Di/OoDdq4ylPz2ny5ybArH0dYe3+U4PtIjrFQcm9G4inZDQrBU42SRSCH3KV/GG6iwoMDZSuXS1ZTWFgm0MEyhn7/s/LTYiYvGn4O/WWgNdKOh+GhJVZ1irXm+NuQkxYQGIDTQOM2pVqvQv51+NEvpBsW5lypNphJPPz8W6+ZcK34/cHG2oueT6vvsWqQ9/jN6PbMW7R//GTe9+afLzkXKYLDkhawlkJL9ih2olRQuyUs5cdH+gGmbYVSgzI7GuMIn9rgIx5a7C2/SRTJXG3ZMMCa7n3PwjVaYapI7OiVMZ9U6MQ233JBTopXxRi0dA3JmmkrIHbp/aOPRloaEhQuXnKzRtftMCQDjggpLRhiCmpNFlU6PUkhXYloasb61n/HvkyO/Gw3llRp/9p4Z37hllnQqbleuck2K71q5Xdw+8PRIAECHhHBcZQiwtTrnGmlb0mvhGrF2lmBX7mXc+N/Nip+LlMNgiXyKI605pBWm/WXm6Qh/MAHrVaItCTAM2zQsJGiN3Ca/lgjPbPo1tt/QAX0OkdzVgZb4++nPepdkusSaiYZK0E7klKNVjH5KKiXa9vSz9A3/lIOjZwCwxVBFu15GMCIE2p/tcK6xuLDiTGgTY8m1kqlNZ5PKP9qaC0DfzsVSTpu0ttX3CrRa+WKnsZ2Lud8X6e+itP6TM6rrNGLPwI4J4SYfjr64b6C4fe9HuxQ5n2D1gTyTOmp/zL1O3N59pgSbXbDKENDPVnR/6lf0f24dbvjPH0h97CeXN2Buahz6k1VSUoJ33nkH8+bNQ3GxPtLfvXs3zp/n8k6yrrZe69CqPaEJq7ASyh7CVEGHhHCxZowtKpXK5id6ORwtr+Br5OYECfk+jvw/NjSove1VmdJpHGdEGxLTh9ooVQAAvdroi2868/NTr9GK042pLayvkpRO0Tk6LSoQ6oN1thJEq1QqMZASgkhnvP6bviJ4aKCf2d9PlUol9uLblXtZkam//24wrnj74O7+JveFBvqLZTwO5pU5XW1eoNXqcN//dovfH35mFFrFhJqs+pv4zjZzD3VKTb0G7R//GWXV9Sgsr8FeQ6L8mGW/210guDmzO1jat28fOnXqhCVLluDFF19ESUkJAODrr7/GvHnzlL4+8mLSYo9ySf+4httRi2ba1fol4DJX4ZvVKVGZZrXeypm3kKMFjlVkFipp2+tYYYVDI3bVdRocsfdaDS/M/wyjJvaqrKlHiWE0IEHGYgoh0DhTXOXwSI+0X9/wLtYro0tXIZ686PjomTSheVQ366OcU4fofx93ONlmRaPViSsjpwxOtbjfIyM7idu5l5yfGpO2bDFXk+zNO4zVyp0dIRRISzIsvjFDLHsRFRqAJ8Yay+68v9mxnEVLGhb6lI4M3vvRLsWqzTe0dPVhQzX2Nej33DqkPvYT/nTRyJk72B0szZkzB5MnT8axY8cQHGz8wzFmzBhs2rRJ0Ysj73Y4v9zuBp7SN48W4bYrWzdHm4879mld6E4vt6ULYOx3tuO0/bkg0t5diTJXZHaXFOi84ECdHmmOTFp8mKzHCK+HrQrjlkhfmzgZ9chaSd58HWnPAwC/HTaOEMn5UCHUQ/rGieKNuyQJ6f2t9NwDTEuNONM0OOes8Zy39bNczLhPW0nJggPOlSyQ/tw+Pe4qs/ukJxkDivnfHXDqfIJnfzokbt/e3/S53nN1mrj91A/KVUd/e5NpzajTz4/Fz/+8Gu/e1Ve8bciS9Yol6guGvbRBHL0rqaoTcxr/751teGXtUUXP5S52B0s7duzAvffe2+j2li1bIj+fQ3q+pt6BRNvebY09vhytJdNHcoymSFqsUS5p81tHmogKUyOpLeQFEQAwzpAP40iBUGn+zqD2LWQ9pkV4kKyCmbaEBfohOUreNJfQy83R9wMhkTw6NADRMmpYJUQGi6+no9ONJVXyW7oAQIah9tMlO1sJSR3ON47YqW3k9nWV5BHtdGLVn7T3YmsbRVkTI/Ufrt74zbmSBW9Kik7e0td8nz8AuPcafQCj0zmfC7ZNMqL+0i09zO7z/I3GZsXrDjpetFWg0epMcryOPzda3B7eJREjJL0cHV2Ba86T3x0wGeF8dnw3TJAsWnot+5hPTv/ZHSwFBQWhrKxxYtjRo0cRH+98DRVyn9IrdTjjwGqPuPAgu6bQfJ0jK36Epfi1duQ7XC2pluzMUve+dgSiSuRlAZBdpVxKTrJ0Q0JwHh5s/89f9uFChz5BCwUtW8fIr7AuFN/8cvc5G3ua987vJwEAw9PlFYvtZWizUlZdb9I7zx5vGFof3WolgBBEhQSIwcvHDk5vAsbXVs4UuRD0VtZqnMojemuj/rUNC/QzKVPQ0PRrjKM9q5ycinvw0z3i9o29W5rdZ4JkleH0j3Y6dT7AtOr5h3f3b5QP9tadfcTtZ386pEi9p+OF5fhgi/Hn4fAzo3DHgLZYcnN3rJtzjXj7vR/tcmpE0hPsDpbGjRuHhQsXoq5O/0RVKhXOnDmDuXPn4qabblL8Asl1pKuDrCV0+jpHq0ULNVi2n7L/k7MQTP49I9nGnkb+fmrZq/WU5sgrdNnBpfF1hkDwOwdWUgnTUw2XXlvTNdk49WdPKYeG7MmxigjWB0u22rFYkhChn9aMCpHXIUHagqi0yrE3ISGQlDul2iJMHywdynMs300auE6wMgUnkE7T7XJwNOuKJM9yzojOVveVpgksXe34KrzKmnpxuvuGnikWP1ioVCrcYVgtqtU5N0pYp9GaNI++xszCBJVKZZLcvvCHvxw+nyDrZWMqzsZ/DTX5+e+QEIH/TjTmgmU8tcbp87mT3cHSSy+9hIqKCiQkJODKlSu49tpr0aFDB0REROC5555zxTWSTI6MEgH60QW5f5R90dub9J8k7f3kJHwCdKb6s/Cm6Q6OjJoI+TyO5Lo4uvIqwInXM9DwWLnTfgCQnuzcBwEh32LSwLayHzPW0LPNkREJjVaH7YY8qb91tZ7cLQgL8kegYeTgFwdyei6UXBFbwwyTOZp1e3/9SMj5kisOjUpIA56/d7f9oUI6TffTfsfylqSvjZwRtPsMVcwrazUmgZY93v/ztLgtrRllzrzRxkRvZ3KXpHlBX80YZHE/aSPqD7bkOtU9QDqVN6Fva7Q1kw4wJiMZCZLVm6udzD9zJ7v/akVFRWHt2rX44YcfsGzZMsycORM///wzNm7ciLAw+bkSjnrjjTeQmpqK4OBgZGZmYvv27Vb3/+KLL5Ceno7g4GBkZGTg559/Nrlfp9NhwYIFSE5ORkhICLKysnDs2DELR/NOwh9zV3QC9za/2FmlGjAu37dWBdmcFJk5Md4g91IlHPk7Z09+kyUdZLY6EQgVoB0htDrpJkkUt4e9U6parU4sMGrPyxvoREAoTXy357UVpnwra+x/U5fmmAjNgG0ZKknydmQU5POdxkBS7miWUHPpwy2OTf29us74t13OB5n7rjVOxTkShALAC78eEbdtLWoJC/IXpzelI0P20Ol0JqURbOWHfjptgLj9soPJ11qtDs/8aAzultzc3eK+fz42TNy+73+73d7eyVEO/0YPGTIE999/Px599FFkZWUpeU0WrVq1CnPmzMGTTz6J3bt3o0ePHhg5ciQKC81/wv3zzz9x++23Y+rUqdizZw/Gjx+P8ePH48AB4+qGpUuXYtmyZVi+fDm2bduGsLAwjBw5EtXVru0LpCTh06cjSbq+QppbUOtgPs+1nXynWXCOpNWFvfvbk0DdW4FEe2uNZa2RroSSS3iTlFO9WyCd2swxVMWWS5pXNdCO0ayxhulXR0ZcLkoCj46J8kfF/i9TP4Uj1C2yx9d79LlVSZHBsgM9aYCz4aj9CxoOGqqi26ojJXVTb+NoUJ2deUs6nU4cfR/f03arHAAmCf1LVx+xsqd5heXG95F/j+liZU+jl27pKW5L+wPKJR3xfWdSXyt76kl/rv+z/rhDI9SPfLlX3H5vSj+r+/r7qbHkJmMy+7+/VWa1oavZHSwtW7bM7Nfrr7+OFStWYP369dBonFs5YMnLL7+MadOmYcqUKejatSuWL1+O0NBQrFy50uz+r732GkaNGoV//etf6NKlC5555hn07t0b//nPfwDof3leffVVPPHEE7jhhhvQvXt3fPjhh7hw4QK+/fZblzwHS8qq6xwu8NY+3nfqBxU62JwyS1Jrxp43Sk/Q6XS4UOrY8xTenB1tI5HZLlZ24U1nnSpybNpXGAHZnVti92OFxOn2cfJ/5lUqlfiBwt48dOkbsrl6PJZIV5PZWz5gwxH7Aw8AiDeMWthznYIjhpVw9oy+BvqrkWYo3ihd1SZHnUaLA+f1wdJUybJ5W8ZKput22BlI7Dtn/H+410yTYEuElVz5ZdV2J5ZLp8PuGCBvGndwB2PwMvWDHXadDwDuft+YHD68i7wPiNJcInvrStXWa8VEfcC0rIQl0hy1T7efsbtQ8Y/7LuCVtUdN+ie6mt1/VV955RU8/vjjmDVrFp5++mk8/fTTmDVrFubNm4f58+dj+PDh6Ny5M86eVaaQl6C2tha7du0yGcVSq9XIysrCli1bzD5my5YtjUa9Ro4cKe5/6tQp5Ofnm+wTFRWFzMxMi8cEgJqaGpSVlZl8OUuaPOpoPRhf8PN+/TSavSshhLYavkCa8BocYN+vmPDJWQXHnq8zr5O9oyBrD+r/L+3N5RCKLMaEOZ7P1atNtF37C3ln9k7jSj+lB6jl/1+mSCq321tEUfjd6GFY4SbXNZ30Sd7nLl8RG//KJTSplfvmKmhlyCOydxpO2nNNTlV0gXQ0y97l7tK8vC6Swoy23H+dMbBad8i+PL1Pt+vfB+PCg2SVgAD0wb3Q4qa8ut6uhQXSBt7Trm4ne5XqGMlClHlf75d9PgC4/2NjVfJv7recH9XQL/+8Wtwe+Yr8Go1arQ4zP9mD17KPYd+5EtmPc5bdwdKiRYvQr18/HDt2DJcuXcKlS5dw9OhRZGZm4rXXXsOZM2eQlJSE2bNnK3qhRUVF0Gg0SEw0TXhMTEy0WN8pPz/f6v7Cv/YcEwAWL16MqKgo8at1a+cb34YG+mPK4FQ8NjodQzo03RIMkSH66bRerX2nzpI0QVMO6RuVvfk87l4MFyAZhbK3NlScYSRjUAfbbUdMH+dYnaXqOo1JXy17lBtWwZXbuRquQrK/3Dc7QP+GJxR2PHDevpElYaqxk50/Ox0kjZGPF8ofmZROa8sZFZD6P0OS97nLV+x6U98kmbazdyQsw5Cvln3YvsBF+D3uaOfrKk1UFsoryCHNPXvyeuuJ3Q1Ji2Xac86HJCUKHrax2q8haRXxTTKnVavrNFh3yFgTSmj1I0eX5Ehx1fD5kiuyuwj8U1ISwVZtLiXZHSw98cQTeOWVV9C+vTHa7tChA1588UXMmzcPrVq1wtKlS7F5c9PtoDxv3jyUlpaKX0qMokWFBODJ66/Cfde2dyo51N0cnTrMcDDPxZ2EN0dHa0p1SAh3qP6QI37Y61jyqXQVpKOlANo5mCReUFZjV/6ZtJK2vYUtJxryeQLsHHnbY8hxyrJzxAUAiir1oy177fz02zpGHzxIG8jKERUSgFaGx260I4fozxPGhSH2vvkMTDMGyvY0Kl5uqHXUOTHCYsNeS+4ekipu19TLG9WUjmTfaceqRoFQwHH/+VLZOT0LJavZ7G2SLf35liZrW1NbrxX7vrWODbG7bIXQwgYAJq20vnBKMPk9434/PTTErvMBwOa5xmTvETJGl84WV5kkvg+1M7h3ht3vynl5eaivb/wJor6+XhyNSUlJQXm5Y7U3LImLi4Ofnx8KCkwrmxYUFCApyfwPYlJSktX9hX/tOSagL8wZGRlp8tXcCHPMeQ60rHAnnU5nd7K0YLShP5YnSh8V2JnbJbxpFFfaP/JirgaLHI6WqoiTrAjafUZ+kreQzxXor7a7VY4wgrbvnPw3OwD4K0//5lPiwIjWDT30q/787Zi+q6ipx2nDtJ0jHyiE0YwiO6bFnAlCo0KNwXa2HVNU+Yaf7552TjUCwIiuxr/NcvO7vpXU9BKq1tvjvqHGwQG5f09WG6pUt4sLc+gD8KJ/GJOg5dSVenWdMT/qw7sz7T6fSqXCA5IpR2kQbU5JVS22njT+7MhdRSkVFRpgUqTzpTWWk+h1Oh2uXrpe/P73R6+z+3zOsPt/8LrrrsO9996LPXuMw3179uzBjBkzMGyYPkrcv38/2rVrZ+kQDgkMDESfPn2QnZ0t3qbVapGdnY2BAweafczAgQNN9geAtWvXivu3a9cOSUlJJvuUlZVh27ZtFo9JencKyYpuGjlx1HlJMOfo9I87CZW7v9plX+VnteH/Qfrp0JWKKmrERsr2BpPSvBN78qSEUajOdqwQE7SQ/N/bE+QJqzDHyVw9JZVgWAK+8ehF2c/ziKTlSJodSeyCh4Z3BAB8YkfCtfDmLyRr20uYal61Q945pb+TN8uoddRQmGSkV+4UlfB6+KtVslrWNNRLEtQ9/4vtApXSgEoa9NhDWtH7XhsVvRuWC2jn4P/l7Cxjw+L/W7HN6r4DFhvfN50JXKTtX17/7bjJz4fU2GV/iNujrkpy6xQc4ECw9O677yI2NhZ9+vRBUFAQgoKC0LdvX8TGxuLdd98FAISHh+Oll15S/GLnzJmDFStW4IMPPsChQ4cwY8YMVFZWYsqUKQCASZMmYd68eeL+//znP7F69Wq89NJLOHz4MJ566ins3LkTM2fOBKCPpGfNmoVnn30W33//Pfbv349JkyYhJSUF48ePV/z6vc2WE45NoQGejZHsWQ0nrd7tyKdYRzizWk9IXE6Kkld3piFn/lvW/CW/H5W0J6Aj5QfSHagY/+l2/RuevUvGAWOeiz2P1+l04tLtOAeaPkuT0CtlNpw+aVgFmRQZjBgHeugJtYPsKaQqNG6+oadj9a/6GPJUimRO466V9AXrY0eOi5RQTFG6ws2aQ4YyBbf2cyy/VKVSifWKtp0qtjk6+cS3xiRpe0pOSPmpVeLKuKKKWqttbL6UfLiSrmyzl7+fWgy4AeBNC1OAu3Ivo9rQ9zAuPNCpwEWlUuHnh4zJ3oOf/61RL75X1x0VS00AwJt3OP4cHWV3sJSUlIS1a9fi4MGD+OKLL/DFF1/g4MGDWLNmjZgofd1112HEiBGKX+yECRPw4osvYsGCBejZsydycnKwevVq8bxnzpxBXp4xd2PQoEH45JNP8Pbbb6NHjx748ssv8e2336Jbt27iPo8++igefPBBTJ8+Hf369UNFRQVWr16N4GDH3qx8iTBkbymS9ybSvAZHllZHBPu7LX9IWHrrSI0dabdzdxFWMtm7ggoAEiKCHG7pAdhX6E8IBKJD7V9Fp1KpxLIDeTLLOkj3E3KB7CH9dC+3BYlQALPYgUbKgDG3pqZeKysHTZqU3dXOHCnBrf30o0O19VpZ08fSxGxbDXstmSGZFjt32fpIoTTBXshdc4Q0Adpa8+B6SVmEfqnOLWR57bZe4vZdVvKI/vXlPnFbSB9w1CxJsLRk9eFGy/q1Wh1uevNP8ftNCkyHdU2JNKmhlT5/tbhI4e+v/25STDRnwd/c9rdcyuFM4vT0dIwbNw7jxo1D5872Zd07Y+bMmcjNzUVNTQ22bduGzEzj3OyGDRvw/vvvm+x/yy234MiRI6ipqcGBAwcwZswYk/tVKhUWLlyI/Px8VFdXY926dejUqROaA+Hv1P1D5dcc8RTpG/JlB99IHGVvU9sQQ7kAe5OJnWFPQm9Ddw/WT93Zm2jrDKFXVpUD1abtTZYVCCvp5K70kY4Qdm8Vbff5/CR/0OUWbRQ+wDiSVwOY5hxtk1GHSLpq7uqO9q1qFEhzVeSMVv9p2Efog+aIzHax4va3Nlr1LJVU0O5qR8mAhqQj0/d+tMvifsIIKAAsvtGxKThBXHiQ+OFgz5kSsyVXpOd7YmwXpwMJtVqFT6YZ31e7Pfmr+MFPp9Mh7XFjF4xHRnSy2ozYHi/d2sNkBDfr5Y1IfewnMfAEgDWzr3FoGlUJDgVL586dw3//+1889thjmDNnjskXeY7cT8wNubN5a76D1wgAI6+S1ydLaTX1WpufXs0Z70RbD3tIRxAcGQFxpDbTGkONJUcnHO8VOrrbcWpH2z8IhGBAbtFOIfHZ3lpZAn8/tfj/IXfVnxBIpDg4DRsW5I+0eP2I1pq/bNeU2iNJsA90sJhpcICfmMD8+zHrScHFlbXiG+/wdMd/n1UqFSIMuUvSUQdzhOC4R6sopwIJlUol9rArrqy1WCtu/nfGhrTScg6O+u6BweL2gEWmObh1Gq1JXaR77Cjwac2g9nHizxEAtH/8Z7z7xym0m2faLmzmsI4NH+qUnU9kWfygsO3x4ejkQL6iUuz+7cjOzkbnzp3x5ptv4qWXXsL69evx3nvvYeXKlcjJyXHBJZItwh8fZ0YX3KFeY1za6uV54QCAVjHGefjDDnZWd9SxwgrZ1YKlIyCZaY7lRwBAbrH8pd9C/SF7Vl2ZI3fVnzTPKCHCsUCio+GNa73M+jxni/WjPEJuhiOEVjDLN8pb/i0YbGftKinh74G1HBfBu5v1hR2zuiQ4PCUG6BNuAeCr3dYXJkgDuP6S0SFHTDEsZqjX6izWeJImzM+T2W7EGmn9o39/07hNx35JDtXcUelOnw/Q13mKCNYHhpW1Gnyzx/gad/z3L+L2m07kKpmTPedak++lvd8A4MQi01kapSy7vRdOLhqDdXOuxZrZ12DXE1k4/fxY2f0DXcXuYGnevHl45JFHsH//fgQHB+Orr77C2bNnce211+KWW25xxTWSDQMMb5COfjJ0l1rJG97g9o6/GbhLoL/a7irKzpKODB3Od0+AJqykO1t8xe5q3Pde49gUrpDOJSQX22OIg4GEEHDJzdETkkxv7+940VlhWkzOSNHxQuP/tyMtSwTTDaN26w4V2kxELjGUmpDTVNaaoZ2N5Ses1T4SKqhHhQSYrGpzxORBqeL2R1vNN9Zd9PMhcTvTyeAMMG2E+/3eC40+0Fz/H+OKrWlXK7cyddvjw8Xt2av24qnv/0LqYz+Z7DNaUoVbCSqVCqcWjxGT6YW/TelJETi5aIxLp+3VahU6JISjU2KE3WVCXMXud9dDhw5h0qRJAAB/f39cuXIF4eHhWLhwIZYsWaL4BZJtrWMd/8PqKe76lLDuoGGFl4PzRY78OXCmdZ10VYm7WuBJc1XsbUPjKGGFkNwRRkebJ0sJUyhhMnMs3tqkL5zoSKK+YFi6vmje3nOlNrurS/OHnAmWpFMV1npulVTVotxwvyOlEaSkxQH/sDIVJ4x+S3s9Okqan2VuOb9OpxPP1z4+TLGk4C/uM5aVufNdY9L1b4eNq0nH9UhRtEdjaKA//jfVmEfUsKvA8edGK3YuKZVKhQ/u7o/Tz4/FH3OH4fTzY7F61jVOjUL6Krv/N8PCwlBbq8+RSE5OxokTxuHloiLr89XU9Ky0sz+TuwlTEeV2Nmp0xheGZbyOBjvJduarOJqrJogODbS7VtI7Tv6/t7QzGDDp0ebv2B9qYSQjv6xaVvmANobA1ZlG1a0lU7mnL1mf5vxhn35lYL/UGKc+tUvLJEgLTjYkHbl0dtRFGrgIQWZDeaWS+kp97K+vZM4jI4yLcYobrP5bLekD+Mz4blBKv1Tja7Xl5CVsPl6Ey5W1Jg1sX5TUDlLKkI5x+PzexvX/Dj8zym3Ns5szu1/hAQMG4I8/9EONY8aMwcMPP4znnnsOd999NwYMGKD4BZJ3ElanSdtluIsjQYh0yN7VhIR5R4v82ctWpV1XEJbhhzvZ9Fmnk5dbI1015+jqG+lKG6GNieXr0ontO/o4UEdK0FEyylNUYX0VZ40hN+qSg21nBNKVoztPW17iLs3dUmJFkzA9ut1CHaLlkpo9zrymUndLirA+IGnoCgAzJN8PdCKXz5zNjxnbdEx8Zxt6PbNW/P7VCT1d1rKqf7tYnH5+rMmXM6U7SD67/0dffvllcbn+008/jeHDh2PVqlVITU0Vi1JS0yd0qXZnorbw9/ed381/cnUla9MZljhSrFGqWmbfK5VhsrB/qvM5GcdkNmAVpjRGOLiMP0wSZMlZyq+DsILK8V5Q0kKftpLnjxYYX4fwYGWWRmcftl70U2hIqkQVdmH677scyysI39t8GoDztYAE0tpHQnK81AeGBsFtW4QqFkyEBvqLI7FbTl4Sp5G3S8omTB6UqnhdnpbRIVh2e69Gtw9PT3DbKlhyL7t/YtPS0tC9e3cA+im55cuXY9++ffjqq6/Qtq39DQqJ5BI+Qbkz4U9I8v3SzvYjSpzzuxzr9WMaaulA2QCBkE5jb9NXR4UG+ovtZ+RMia34XT/t50x1dMDYKsXWylFpxW1H2qtICfV5rJXNkK7msnca1hyhPcf5kisWk7yFBRf9FAiyAdOpvGW/mS7nl66adHRRgCWfTTfOaGQ8tQa19Vrc+tYW8TZpMUkljeuRgl1PZOHFW3rglQk9sHb2NXh3cj+XnIs8z6Fg6dKlxitYSkpKkJamTI0Hco+vbRRz8zZjFF7tIYeQcB0ZoszoghxCm4sAN+YhjDW8tmoZn8DLq+sa5Yc4oouhQKBWRu52C8NrEurkCiqhXtbFcuslDzYbkpRbx4Y4PSpxlaEytrVRHmk+zyAFVooO62IcgTPXC0+6pN7RNicN+fupxVy0hh8uXllrbPIqbZyqhLYtwkyqund6wricfs7fOrk0n6dFeBBu7tMK/+jVymTKlZoeu3+KTp8+DY2m8fRATU0Nzp/3rTff5k7IkWiOKxvkcrSqsTPsbVcgTN84IyRQft7Dbkm+T6KDNY8A4yjRu3Yki4/p5lzAfP91HQDYrspeUK4fBTI3nWSvATLyZf6UVL5WIkiWVtU2F6R9vvOsuN0p0fEE9oYel9QyEqbCdDodPjY0slWp4JIcmx3/zmp0W5C/aZ8zImfI/pj2/fffi9u//voroqKMv4wajQbZ2dlITU1V9OLItYL81ajVaMUl1a62O7fELeeRcnehzrzSK6h3Yqm5Iy4apjgcyatqaL+kj5YlwrROUmQwohzo0yYQlvC3CLfevkCr1clq3SGHMEj00/48vGFlPyG5+6FhHZw+Z4cEYzBy4mKF2dV1QkDTPzVWsfo1/moV6rU6/G9rbqOgQRj5iQhStmeiNNC/9a0tOP38WDE3ClC+cKIgwE+NU4vH4POdZ1Gr0SElKhjDFShPQCSQHSyNHz8egD6x86677jK5LyAgAKmpqXjppZcUvThyD3+1e6Z7TkmWTjvaQsJeuZf0UxDWCuUpSZpY6kjDV0cE+es/qd/ixHLsKkOOzg47gpK4COd6NI3OSMKag7ZHxfIkVb6lgYcjehh6vNmKR4RimUrEvdKcpxOF5oMl4eczSMHfi//LbIMPt+SisLwGOp1ODIq0Wp3YNPnB4c4Hg1Jqtb4lyI+GMgiPfbVPbCwNON7XTw6VSoUJ/RzvN0dkjezfTK1WC61WizZt2qCwsFD8XqvVoqamBkeOHMHf//53V14r2VArsz2Gp43uluS2rtHhhhyXsRnOFd2zV6820WIQ4yjpJ3I57JlKa+hvhm71cgK8TUeVLVXw+7Eim5WmBZ2TnMsL6WiYctLqYLVaeZjhtRyiwDSsWq0Sqx+bmxKrqdeIzULvHKDcIplJA43H2plrLCGw8ZhxtHVsd+V/L16d0FPclgZK703u55Fu8URKsPtjzKlTpxAX5/2tKpqrQ3lltndSkK2qxC45pwMroiKcXP79837bTUmlQpzIy4g3rPZzZw0reyqqC/k85y87l8/TRlKt3FrCeK5hSkyJ5ebSekIbj5rvEZdfWo1KQyCVEqVMdXwhWNpysvHimDOXjAnY3SQFJZ0lbeIq7ev1yOd7xW17i4PK4e+nxs8PXW1y29juybjOibIPRJ4m6x1k2bJlsg/40EMPOXwx5Bhpku3xwgpxlZE7XCitRklVLaJDnZuSsceeMyWorde6rPCblLQycU29xunRIjmu7hRveycDjVanaIAsrS9kiZ9hdOC+a51bAt6nrXGpubWYe4ehsKISLU/Cg/zhp1ZBo9XhSp35kaWcsyXidkKkMmUqhqUnYOvJYrNB4Q979aNNAX4qp9qcmNO7TTR2nynBvnOlqNdoUVWnEYteujJXsWtKJE4/PxaF5dWICQ1068pOIleQFSy98sorsg6mUqkYLHmAWq3CgLRYbD2pTBKsHO3jjdWpjxZUON1BXI5uLY1BYH5pNdq0CLWytzKulQQu7urVZg+l+olJ38wulFyRdSwllmSrVPrXtaSqFvER5gMT4TRK9BMD9PWA/jxxCSv/OI1/9Gqc57X/fAkAoHurKMVWbo3omoRFP+v7l50vuWIyovOdIVgKdkEg/uz4DIxZ9jsA4LGv9+OvC8bA+ulxVyl+voYSnFgtSeRNZAVLp055d/8vcr+I4AC0bREqJlC7Q6uYUAQHqFFd577cLHtzLH79y77pOmdJpySd6WEmFE4E9FNi1oKl7/darhdkL+HyfztcaLFOjZAsHO9kQrlACIBiwswfb78hf6ikSrmmwtLX84e9F0xG5YTfIWeb2ZrTNcX4AaNh7SNv6eZO5Auc+mio0+lkJ2ZS0+PngWRNe89ZWO5ck1l7lVfrV5VJKxY7qvRKnbhqyRZLozJyBfipkSQjb0kjmS9r7UTFcIGc1W1CSQSlgmRh+mnT0Ytm/34JKwJv6q1Ms1dAn2+VbkhO/1ZSDFYoUQAAt/Rtrdj5pNY/MrTRbbueaFyXiIgscyhY+vDDD5GRkYGQkBCEhISge/fu+Oijj5S+NiKnXCi5gjqN/s3QXXGdUCPnnqsdr2YvDXx25bpvalUgt8yCElOvwlJ+a21WAg3zcM6URpCSjsA1bFpbU68Rc5mcaR9jjlCZ+3B+udji5b3NxlH7DAWTu6XaxYXhl39ejWlXt8PUIe3w+6PXcVSJyE4ONdKdMWMGxowZg88//xyff/45Ro0ahfvuu092bhN5Xm29FuUKFDG0x0dbTrv1fGclbR7Sk5xPetfYsfJPTtsQSyKDA8ScFlsDt78fU67ophAkWWvLoTShvpOlgqXVdRqcNIy+BCiU0N9DMuXYcBpZGBkEnGvaa86Uwani9h/H9eUXPjQ0l40JDVCsGKU5XZIj8e+xXTH/713FFj5EJJ/df31ef/11vPnmm1iyZAnGjRuHcePGYenSpfjvf/9r16o58qytkiXMSnVVt0VYtu1sM1R7tY8Pc3jlnHTab8MR91UDj7NR1VpQWKaf7rPV60wOoVSBtSKlO04bR7pUcP7NfcRViSbnbuiwpIdZGxe8yUufDwBkS1rHKP17IQ1Spry3w2QKbt4Y1zR7JSJl2P0OkpeXh0GDBjW6fdCgQcjLy1Pkosj1qiXLpuPcNCQvxB1K5oK4mrTQo9z8IXcSXtPp1zjfxFpOo2JpU1ZnWp0IhNVSRwrKzeYPCbeFBvrZVQvKlus661c5fiHpkQYA2Yf0tZeCA9QuWe4+QZKXdN2LG8Ttf/RStrksESnL7r8GHTp0wOeff97o9lWrVqFjRzYt9DW92kR7+hLsIrydZh92vnmsXCO6yluyrtPpFB99Wn/EfOHEhpScwGk42mLOMIWmqKSBurQMgkBIho5RuI5XmKGyu3TaDTBOy/VuE6Po+QRPmVmuf1PvVqxDROTl7B5nfvrppzFhwgRs2rQJgwcPBgBs3rwZ2dnZZoMoavrq3NhmpcpQWVnJZd1KuSy5po5O9jC7UKpfxXepwnJlawDIK1VutZ+Qk2Wtme5eScFGJUjbl5hr1yMEx9UWCkg66vb+bfDjvjwUlteIRVWr6zQ4UqCf9rtZoWTyhkIC/bDs9l546NM94m1Lb+7uknMRkXJkf5w5cOAAAOCmm27Ctm3bEBcXh2+//Rbffvst4uLisH37dvzjH/9w2YWSPO7MBhLe3BrWb3ElJXtnuZKzK5uEOjxqG0m/Qg0iYdWfM7Jk9Ifbd04fSF2ush7E2SPBsPrvt0ONR9FWH9DXrZqo8P+7NMn7zxP6/D3huQHGlWuuMK5HCk4/P1b8cmViNxEpQ/bIUvfu3dGvXz/cc889uO222/C///3PlddFdhIWar2/+RTG9XBP01ihSW2wgp3SlbRJwZViAKBxY2K6v8w30LjwQBRV1KJfqvPTRjEycpDCgvQ5XH9XsAFroSE5vcRMTthFBepVmSP87AL6Zq9jMpKxStL0NSmKlaeJyEj2u9zGjRtx1VVX4eGHH0ZycjImT56M33//3ZXXRnYIMqz2cmePNlf2llKCsFLsrJMNX4XVe29vOuH0Ndl9bpnlCtKcqN7dUElVHS5baGwrTAsmOFkEU2rGUP0o2sajpsGtvuitfntMRpJi5xOMNKzE22Q471e79SOkrqp3RES+S3awdPXVV2PlypXIy8vD66+/jlOnTuHaa69Fp06dsGTJEuTnu7fNA5m63k2jSc6Q+8avFKHW0YPXdXDqOEIAmujGPlfCKrBfDuS7rUp+cpSxCGOOmdykK7UaHDMkYTtTR6ohIVcq91Klye3SabGwQOXLW0zMNE7tLVl9WNyeOqSd4uciIt9m9/xJWFgYpkyZgo0bN+Lo0aO45ZZb8MYbb6BNmzYYN26cK66RmoCaeg32nrOcOOxKtvJ+bMnqIm/ll5IFIq+SjG6YS3wGgLLqOhTZSAC3R1iQv9X2IyVXjOcakKZc4+RR3fSjRnUa0/ZJ0uT1VgpX0waAqzsa85Le3GAcNfSFDx5E5F5OJZt06NABjz/+OJ544glERETgp59+Uuq6qInJKzG+8WW0cn6a42hBue2d3ExaGNLZAC09yXxTWamcMyXitpy+bnKEGupKnW4wyiMV6KdWtF1GrGTqWLoS76OtpwHok7HtbWgsh0qlwiMjOpncNmVwKhOuiagRh8e2N23ahJUrV+Krr76CWq3GrbfeiqlTpyp5beRCxy82rmnjDmGBfibTPfYSlpDLrT/kCeNd0D3eHGEMJiUqWJECkYAxJ2nT0YuYMth0Omr7Kdf0qWvbwljZ+lhBBbob+sUJ5SGCXFiDaOawjqiq1eB4YQVaxYRiwfVdXXYuIvJddv0VunDhAhYtWoROnTph6NChOH78OJYtW4YLFy5gxYoVGDBggKuuE8XFxZg4cSIiIyMRHR2NqVOnoqLC8ht+cXExHnzwQXTu3BkhISFo06YNHnroIZSWmk4FqVSqRl+fffaZy56Ht9hiWC5dbCGR11WczXW51lB5OV7BBGO5lKxpZI8rtdZrDMWEKZfULxSbDAtq/DnqnCFR3tK0oKNUKhXS4sIAAD/u0/elq9do8deFMgDADb1cG3w+Oiodb0/qy0CJiCySPbI0evRorFu3DnFxcZg0aRLuvvtudO7c2ZXXZmLixInIy8vD2rVrUVdXhylTpmD69On45JNPzO5/4cIFXLhwAS+++CK6du2K3Nxc3Hfffbhw4QK+/PJLk33fe+89jBo1Svw+OjralU/FKwhLp0depfwqI1dKiZY/KrWqQSsLRwlTQOdLrqCipt5k2bmrSCs6/3a4EDeaaRFzwkzFa2e1j9cHLTtPX7a4j7Rlh1K6JEfiZFEl1hsqoBdKpjSHdHBdzSMiIjlk/9UPCAjAl19+ib///e/w8/Oz/QAFHTp0CKtXr8aOHTvQt29fAPqGvmPGjMGLL76IlJTGnzy7deuGr776Svy+ffv2eO6553DHHXegvr4e/v7Gpx4dHY2kJN8KGpSiRAfyT7efxeIbvbcKcUiAcz+vA9JaiNuXK2stBktKTlMFB/ghLNAPlbUa1NSbH8nZYmiGrEQTXYGQr5NfVg2NVmeSv/Pf9ccVO09D16Un4Kf9QoFNrViMErAvQCYicgXZ03Dff/89brjhBrcHSgCwZcsWREdHi4ESAGRlZUGtVmPbtm2yj1NaWorIyEiTQAkAHnjgAcTFxaF///5YuXKlzaXaNTU1KCsrM/lqjkINy7m9NSE2wE9/XcJqK0dFhQSIic/WCK0yKmrqbewpz0AbVaSFaxrt5POTuk7S803ToNRDoqFQY0Sw8iNrI64y9t/beOQiXss+BgBoGR3CvmlE5HE+8VcoPz8fCQmmy7f9/f0RGxsru75TUVERnnnmGUyfPt3k9oULF+Lzzz/H2rVrcdNNN+H+++/H66+/bvVYixcvRlRUlPjVurXy0xK+YKThTdpbgyWBCxZSmSXUAlJ66XmpmcrWUkqMDgoigo2J4g2DvpMX9Svk/iazsbA9IiXnvefDneJzlgZRRESe4tFg6bHHHjObYC39Onz4sO0D2VBWVoaxY8eia9eueOqpp0zumz9/PgYPHoxevXph7ty5ePTRR/HCCy9YPd68efNQWloqfp09q0xujBL+PFHktnPZE4NoFS6sWFPnvua99opRqIp6Tb0+sfuz7WfM3v/rX8oXghUqwQPA+sPGFYdni6vEbX8XjfTcYGYV4UwnC4oSESnB9ZmqVjz88MOYPHmy1X3S0tKQlJSEwkLTpeL19fUoLi62mWtUXl6OUaNGISIiAt988w0CAqwvsc7MzMQzzzyDmpoaBAWZX3EVFBRk8T5PEd7kquu0uFKrQYiMaSN3Ehu+apUJcgrLa1BcWYtYBVeCyXGxokbRkRxrOiSE4/djRUgwUzlcq9Wh2hAwSgMcZwUH+In95uokq96kqyZ7KFAny5xnxnfDdzkXxO/DAv0UredEROQojwZL8fHxiI+Pt7nfwIEDUVJSgl27dqFPnz4AgN9++w1arRaZmZkWH1dWVoaRI0ciKCgI33//PYKDbRfuy8nJQUxMjNcFQ7YMk+Sa1NR7X7BUb3jjdTZW6pRoLNZ48mIFYsOUqyRtTZVh+f6Gw4Xo3cZ809rjCq9O658ai/c2n7a5X5bC02I9WkUj+3AhVm4+hdv6twEA/HFcP2LZMjrEZSNLkcEB+GRaJt7ffBoBfmq8dGsPl5yHiMheHg2W5OrSpQtGjRqFadOmYfny5airq8PMmTNx2223iSvhzp8/j+HDh+PDDz9E//79UVZWhhEjRqCqqgr/+9//TBKx4+Pj4efnhx9++AEFBQUYMGAAgoODsXbtWixatAiPPPKIJ5+uQ0Jd0DvLFW7r71x+V3iQP9rFheFUkeUK0wBQWFaNOo1yU389WkVh77lSi5W5L5bXiPWH/BXO4dpz1vIyfgAI9lc2MBYSqqVNmQvK9DWmzpc415TYlkHt4zDIRmI7EZG7+cY7LICPP/4YM2fOxPDhw6FWq3HTTTdh2bJl4v11dXU4cuQIqqr0uRW7d+8WV8p16GCa93Dq1CmkpqYiICAAb7zxBmbPng2dTocOHTrg5ZdfxrRp09z3xMgltkmW8SuRQ9StZZTV3naXKo3L93u3NT/yZK9Aw/RanUaH0qo6kyrdeWWuK5A5rmcKVv+Vj+2niqHV6qBWq/C5oWYVc4iIqDnymWApNjbWYgFKAEhNTTVZ8j906FCbJQBGjRplUoyyOfnlgPLJwd6oe6soBDtZZ8keceGBip1POsJSVm0aLAkV2AHz1badkWYoTAnog7KWkjpHXMZPRM0R//I1Q0J/NQCIUyBBurZea7Mlh6eEKTw9WVGtTA0lOUIC/SwW1BQ+CPRuEy2OQCklPSlS3N55uhhFFTViMvnfeyQrei4iIl/AYKkZkg64XdPJdoK9JeGS4oRCAnBTVW/If3p38ymz9yu0yM+ikw1ytIoMDW+jQpRpoGvJpqNF2GBoQQIAyVG2F0kQETU1DJaaOWcKNkYGByDQMC1Ta6Elhyu5os6QJenJ+lV4bSyUDfgu5zwAKJpUDgBXDKOAu3JNk7y/3aM/X5WLRvT+0aslAOCr3efw0dZcAEBqi1CfWUhARKQkBkvklF5tomXt94OhzpISCg3JzRU1lgMFS/3UHNW9VbSs/ZQuZj4mw1AlvUFU2yJcP32a0dI1NY+kzWv3ni0BAFzlonMREXk7BkvkFpWG1hnSQoeOuu/a9jb3+WjLaQBAvavnxxq4pa+yrW+E5fv7zpWY3J5Xqg8Yu7eOVvR8grHdG+cmPTSso0vORUTk7RgskVsIScg39m7llvMJlb3jFK4AnXupyvZOCqo2TLPtlEzDXanViHWmGo44KSU4wA/925kW/OycFGFhbyKipo3BUhO09WSx7Z08xN1Lz6WVzZ0hbRYs7ZMm2H7aNa+50LQ2RlI2QNpYd1D7Fi45LwCsmj4AT4+7Co+M6IQjzzbPEhtERIAP1Vki66Rv5q6ustwcdUsxLqcvLK9u1B/uwHl9wUqlE90TIvUjY6cvVYkFIqtq9VOaAX4qxLiwN55KpcJdg1JddnwiIl/BkaUmZFyPxl3bmzJ3BoX+fmqktrDcQDcqRB+0jLhK2T5t0pYjB/P07Xp+/asAgPIr74iIyDwGS6SItQfdt4xfYygUtenoRRt7ul+swiM97ePDxW1hhZ/W8Pzjwl03qkREREYMlpqh348ZgwwVnEsQvlih74lWIsmjcbUBafo8nSALlat1Oh3WH3FdIHUkv6LRbZeral12PqG20/eGWk5vbzoJALiuszL5WEREZB2DpWaosNzY9DUk0Lk+ZtOuTgNgfVWWTqfDucvKTZm1igmxen9JlTFwk7bucJYw7bf7jGmByLPFVdBoXTclVmEouyCMqMVH6POYQp38vyMiInkYLDVjIxXIr5GzdF3ItQGAMDe/wXdNUS5YEmooNezFdkrSikQ6baaUSQPbAgD+t/UMqmrrcbxQP7I1OoN92oiI3IHBErlcpaTSdocE5YMJd0mMsN4XrUtypEtKI0j7sR3KKxe3XRGYERFRYwyWyG3S4sOgUrCIotItTeTaevKSW893dUdjs+P53x4AAEQG+4vTcURE5FoMlsinnZZMgbmaDvqcoZMXTc+5audZ/f061+QtSUeWhClNaUkBIiJyLQZLTZDWhcnG3iApsnHwIJXToI+aUrK66HO8QgJM864CDVNvSvS9M0elUqFrsmnu1fRr0lxyLiIiaozBUhMi1N95c+MJt5/7j+NFbjuXv58a/VNjLd5/otC4tF+tYOu0qJAAq/ff3r+Ncidr4M07ept8/38uPBcREZliu5MmRGgamxJtPRFZSUEB+ni7pl6LK7Uap0sRyGYlCBLyosb1SFE0R0pwpU6Dsuo6RAbrgydp3SpXadsiDH8+NgyH8sqQmdYCaiWjQCIisoojS03I0M7xtndS/JzGwoiW+qKdvNi4iKM7KB0nSfuwbTmhT/LW6XQoqtAXpPRzcQCTEh2C4V0SER7EzzhERO7EYKkZ+uDP0wAAJfKR5RRGFFaPFZbV2NjTfvVuzM8KD/IXk63N5YUJOU1ERNS0MFhqhiINuTdqF0xRmRNsSIgek5Gk2DGFitlC4CflypGs1jH61iNCNW9pzBTGER8ioiaJwVIz9o/eLd16PqHHmRIigvWBSUxo46Tr7EOFAEyLYSqlrFrfSmXNwQIApontrp6GIyIiz2CwRD5pdDfLo1QtwvW5Rdd0ilP8vP3b6VfhCcndFyV99mytliMiIt/EYImarLYtwhQ/ZhdDvaN1h/QjSwfOlwIAru3k/uR6IiJyDwZLpBhhiqopk44eVdXWY8+ZywCAkqpaT10SERG5GIMlcoo0SXz9kUKz+1TXKZ87JFh3qLBRm5G/LjSu6q2U6xqUSsgrrQYAjO2e7LJzEhGRZzFYaoIOnC9zWZ+yhvzUKqQYltNrLCzj/zbnAgDTlWPOahNrnGIrr6kXtwvLq8XtABckXPv7GY/5w748FBpyllrFKJe8TkRE3oXBUhOSKOmZdtKNDWb7WGk9AgCB/vofs24tI63uZ9c528aI29K4sKTKOBXY18Z1OSLAz/gr883uc+L2kI7KJ5MTEZF3YLDUhHSRNFu1NMoDAAVl1Rbvc6X0JOWCJVtahAWKQZrSrjEkc+8+UyLeJqyOIyKipofBUhPTQtKSw5zy6jqcu6wvqOiuopRNzcirTCt1C9OQRETUNDFYamaKK42rtoSaQb5OWJEGACcvun76cVyPFJPv7x7SzuXnJCIiz/GZYKm4uBgTJ05EZGQkoqOjMXXqVFRUWG9rMXToUKhUKpOv++67z2SfM2fOYOzYsQgNDUVCQgL+9a9/ob6+3sIRm47wIH/FiyjWacw30nWFAEmi9WlJftaO08UAgEuVrlvKHxEcgFlZHREVEoD0pAjcPZjBEhFRU+YzzawmTpyIvLw8rF27FnV1dZgyZQqmT5+OTz75xOrjpk2bhoULF4rfh4YaVy1pNBqMHTsWSUlJ+PPPP5GXl4dJkyYhICAAixYtctlzaWqEprJvbTyJ6de0b3R/bb3yQZRKpcLfuyfjx315JrcLq9X+7uKl/LOyOmFWVieXnoOIiLyDTwRLhw4dwurVq7Fjxw707dsXAPD6669jzJgxePHFF5GSkmLxsaGhoUhKMt8aY82aNTh48CDWrVuHxMRE9OzZE8888wzmzp2Lp556CoGB5vN/ampqUFNjbHNRVua6uj6+IMmQs5MSHdLovr8ulIrb7kyRSmYeERERKcQnpuG2bNmC6OhoMVACgKysLKjVamzbts3qYz/++GPExcWhW7dumDdvHqqqqkyOm5GRgcREY8LuyJEjUVZWhr/++sviMRcvXoyoqCjxq3Xr1k48O99nbdn8KckUWVKkawKYXw7ki9tbTlxyyTmIiKj58omRpfz8fCQkJJjc5u/vj9jYWOTn51t4FPB///d/aNu2LVJSUrBv3z7MnTsXR44cwddffy0eVxooARC/t3bcefPmYc6cOeL3ZWVlzT5gsmVAWixUCg8tlVXXm/wLAEfyywEAdRr3FOUkIqKmz6PB0mOPPYYlS5ZY3efQoUMOH3/69OnidkZGBpKTkzF8+HCcOHEC7ds3zq2RKygoCEFBQQ4/3h0OnC9Fp8QIT1+GS03MbINNRy+aJHtHhgTgYnkNRl5lfuqViIjIXh4Nlh5++GFMnjzZ6j5paWlISkpCYaFp37H6+noUFxdbzEcyJzMzEwBw/PhxtG/fHklJSdi+fbvJPgUF+m7y9hzXmwirwA7lNf08KiFIMpdArvRKPyIiar48GizFx8cjPj7e5n4DBw5ESUkJdu3ahT59+gAAfvvtN2i1WjEAkiMnJwcAkJycLB73ueeeQ2FhoTjNt3btWkRGRqJr1652Phvv8H+ZbfDJtjNQW+iLtu9cqdnblbD/vOuObc3h/HJcqdWgpl6Di+U1th9ARERkB59I8O7SpQtGjRqFadOmYfv27di8eTNmzpyJ2267TVwJd/78eaSnp4sjRSdOnMAzzzyDXbt24fTp0/j+++8xadIkXHPNNejevTsAYMSIEejatSvuvPNO7N27F7/++iueeOIJPPDAA14/zWZJaICf1fuPFuhzeipqlKslFSRpK9Kwlcru3BLFztNQRstocft8yRUcOG8cTWsd23hlHhERkSN8IlgC9Kva0tPTMXz4cIwZMwZDhgzB22+/Ld5fV1eHI0eOiKvdAgMDsW7dOowYMQLp6el4+OGHcdNNN+GHH34QH+Pn54cff/wRfn5+GDhwIO644w5MmjTJpC5TUyMkWd/WT7mE9H6ShrVlV+pM7hOmA4sqlC8SGR8RhOjQxtNtaXFhiGCvNiIiUohPrIYDgNjYWKsFKFNTU6GTtJ9v3bo1Nm7caPO4bdu2xc8//6zINfqSAD/l4uQAPzViQgNwuaqu0X0hgfqRrpt6t1LsfOZsO3UJxwv1Fd1d1UCXiIiaJ76rkFvYavDrqBJDgHbu8hVcNiS355VWW3sIERGRXRgskU+bPCgVAHC8sEJMML9/qONlIYiIiBrymWk48g3uLgVZr9WXDcg+VABDizqo3dlXhYiImjyOLDVRO09fduv56g2Ryg97L5jc/tvhQnO7K2ZIB33pCa0kSrsu3XY5CiIiIrkYLDUxdRr9SMt+S/WUdK4Z+xHOWy+JWsqrjQnf8RGuKcWQntS4SnlSFMsGEBGRchgsNTF/66qvPG5uST0AvL7+OABAp/CE2cTMto1u00oKa1trtuuM1LiwRreFB3F2mYiIlMNgqYmJtbHqrFVMiGE/9xbddGUW0TWdjNNu069Jc+GZiIioOeJH8Gbqus5NJ69nxaQ++PWvAgT5q/G3LomevhwiImpiOLJEivplf564Xadt3ODWFYL8/TCuRwpGXpVksSceERGRoxgskSLqDQne0ire6w4WiNsqLucnIiIfxWCJFDGuZ0sAQHCA8UeqqlYjbvtxxIeIiHwUgyVShDRIamhcjxQ3XgkREZGyGCw1UYXlNSirbtzYloiIiOzDYKmJaRljLMi476xpYcrqOg3OFl9x6fkLympQVVsPAPjzRJFLz0VEROQODJaamKiQALGWUkMHzhuDp5YW9nFUUmSwuJ1ztgQAcLKoEoBpJW8iIiJfw2CpCbJUwVqo2R0Z7I+EiGCz+ziqRXgQokL0VcOFjiqhgX4AgPG9Wip6LiIiIndisNQMxYW7pnq3dHRJKjLEfOsVIiIiX8BgiRR3OL8cAHDgfJmHr4SIiMh5DJZIMfll1QCA3Wcu42xxlXh7FEeWiIjIhzFYIsXc2NtQmNLfD9V1xoKUvVpHe+iKiIiInMdgqQn7SdKnDQDqNK7t1SbkLJVeqRWTyWPDAtnqhIiIfJr5ZVPk0y5V1gKAyegOAHyx8xwAoNZFQZPWECGtO1SI9KRIAMaecURERL6KI0tN0LSr2wEAGo7nCC1JhCX9SuubGqM/rwqoN0ROdRqdtYcQERF5PQZLzdD13V3Tqy21RRgAfZ2lDUcKAQATM9u45FxERETuwmCJFCNtpiuUD3B1nhQREZGrMVgixUQENy4RMLJbkgeuhIiISDkMlkhRV6VEmnwvTM0RERH5KgZLTdjXe86bfH+0oMLl57y9v2mOUkq0sg17iYiI3I3BUhMUG2a+99uu3MsAjEv8XeHmPq0Q6Kf/sXr+xgzXnYiIiMhNWGepCRraOd7s7UH+atTUa3FNpziXnTs4wA9HnxvtsuMTERG5G0eWmqEEQ6VtIiIiss1ngqXi4mJMnDgRkZGRiI6OxtSpU1FRYTkH5/Tp01CpVGa/vvjiC3E/c/d/9tln7nhKRERE5AN8Zhpu4sSJyMvLw9q1a1FXV4cpU6Zg+vTp+OSTT8zu37p1a+TlmfZGe/vtt/HCCy9g9GjTaaL33nsPo0aNEr+Pjo5W/PqJiIjIN/lEsHTo0CGsXr0aO3bsQN++fQEAr7/+OsaMGYMXX3wRKSmNK1L7+fkhKcm0xs8333yDW2+9FeHh4Sa3R0dHN9q3qaip1yDI38+wzQKRRERE9vKJabgtW7YgOjpaDJQAICsrC2q1Gtu2bZN1jF27diEnJwdTp05tdN8DDzyAuLg49O/fHytXroROZ325WE1NDcrKyky+vEmQv/G/dcORiwCAPWcui7f5qRp2jSMiIiJLfGJkKT8/HwkJCSa3+fv7IzY2Fvn5+bKO8e6776JLly4YNGiQye0LFy7EsGHDEBoaijVr1uD+++9HRUUFHnroIYvHWrx4MZ5++mn7n4ibSCtpV9bUAwAulFSLtyVGmi8tQERERI15dGTpscces5iELXwdPnzY6fNcuXIFn3zyidlRpfnz52Pw4MHo1asX5s6di0cffRQvvPCC1ePNmzcPpaWl4tfZs2edvkalXd3RfHmA/u1ioeLIEhERkWweHVl6+OGHMXnyZKv7pKWlISkpCYWFhSa319fXo7i4WFau0ZdffomqqipMmjTJ5r6ZmZl45plnUFNTg6Ag8yMwQUFBFu8jIiKipsWjwVJ8fDzi480XUJQaOHAgSkpKsGvXLvTp0wcA8Ntvv0Gr1SIzM9Pm4999912MGzdO1rlycnIQExPDYIiIiIgA+EiCd5cuXTBq1ChMmzYN27dvx+bNmzFz5kzcdttt4kq48+fPIz09Hdu3bzd57PHjx7Fp0ybcc889jY77ww8/4J133sGBAwdw/PhxvPnmm1i0aBEefPBBtzwvd/h0+xkAwE/7L3j4SoiIiHyTTyR4A8DHH3+MmTNnYvjw4VCr1bjpppuwbNky8f66ujocOXIEVVVVJo9buXIlWrVqhREjRjQ6ZkBAAN544w3Mnj0bOp0OHTp0wMsvv4xp06a5/Pm4Wp1GXyYgOEBfNqC6Tv99cWWtx66JiIjIF6l0ttbJk01lZWWIiopCaWkpIiMjPX05AIBv95zHrFU5uLpjHD6amol7PtiBdYcK8fyNGbitfxtPXx4REZHHyX3/9olpOFIOF8IRERHZh8FSE7crV1+M8sB57yqcSURE5CsYLDVRQhXvqloNiitrkV+mL0rpr+Z/ORERkT34ztlEXdPJWCZBmtQ9tLPt8glERERkxGCpiQoL8ofaTH5SZEhA4xuJiIjIIgZLzcD+8yWevgQiIiKfxWCpCdMaikI8/4uxv54fl8MRERHZhcFSE9anbQwAQAV9gNS9VRTU5ubmiIiIyCIGS01YaoswABBXwrWJDfXk5RAREfkkBktNmEarNfm+XsNi7URERPZisNSE3dq3tcn3E/q1trAnERERWcJgqQnrnBRh8n23llEeuhIiIiLfxWCpCWsRHoS7B7dDSIAfJg9KRXxEkKcviYiIyOeodDodE1mcJLdrMREREXkPue/fHFkiIiIisoLBEhEREZEVDJaIiIiIrGCwRERERGQFgyUiIiIiKxgsEREREVnBYImIiIjICgZLRERERFYwWCIiIiKygsESERERkRUMloiIiIisYLBEREREZAWDJSIiIiIrGCwRERERWcFgiYiIiMgKBktEREREVjBYIiIiIrKCwRIRERGRFT4TLD333HMYNGgQQkNDER0dLesxOp0OCxYsQHJyMkJCQpCVlYVjx46Z7FNcXIyJEyciMjIS0dHRmDp1KioqKlzwDIiIiMgX+UywVFtbi1tuuQUzZsyQ/ZilS5di2bJlWL58ObZt24awsDCMHDkS1dXV4j4TJ07EX3/9hbVr1+LHH3/Epk2bMH36dFc8BSIiIvJBKp1Op/P0Rdjj/fffx6xZs1BSUmJ1P51Oh5SUFDz88MN45JFHAAClpaVITEzE+++/j9tuuw2HDh1C165dsWPHDvTt2xcAsHr1aowZMwbnzp1DSkqK2WPX1NSgpqZG/L6srAytW7dGaWkpIiMjlXmiRERE5FJlZWWIioqy+f7tMyNL9jp16hTy8/ORlZUl3hYVFYXMzExs2bIFALBlyxZER0eLgRIAZGVlQa1WY9u2bRaPvXjxYkRFRYlfrVu3dt0TISIiIo9qssFSfn4+ACAxMdHk9sTERPG+/Px8JCQkmNzv7++P2NhYcR9z5s2bh9LSUvHr7NmzCl89EREReQuPBkuPPfYYVCqV1a/Dhw978hLNCgoKQmRkpMkXERERNU3+njz5ww8/jMmTJ1vdJy0tzaFjJyUlAQAKCgqQnJws3l5QUICePXuK+xQWFpo8rr6+HsXFxeLjiYiIqHnzaLAUHx+P+Ph4lxy7Xbt2SEpKQnZ2thgclZWVYdu2beKKuoEDB6KkpAS7du1Cnz59AAC//fYbtFotMjMzXXJdRERE5Ft8JmfpzJkzyMnJwZkzZ6DRaJCTk4OcnByTmkjp6en45ptvAAAqlQqzZs3Cs88+i++//x779+/HpEmTkJKSgvHjxwMAunTpglGjRmHatGnYvn07Nm/ejJkzZ+K2226zuBKOiIiImhePjizZY8GCBfjggw/E73v16gUAWL9+PYYOHQoAOHLkCEpLS8V9Hn30UVRWVmL69OkoKSnBkCFDsHr1agQHB4v7fPzxx5g5cyaGDx8OtVqNm266CcuWLXPPkyIiIiKv53N1lrxRaWkpoqOjcfbsWSZ7ExER+QihTmJJSQmioqIs7uczI0verLy8HABYb4mIiMgHlZeXWw2WOLKkAK1WiwsXLiAiIgIqlcrh4wgRLkeoLONrZBtfI9v4GtnG10gevk62efNrpNPpUF5ejpSUFKjVltO4ObKkALVajVatWil2PNZuso2vkW18jWzja2QbXyN5+DrZ5q2vkbURJYHPrIYjIiIi8gQGS0RERERWMFjyIkFBQXjyyScRFBTk6UvxWnyNbONrZBtfI9v4GsnD18m2pvAaMcGbiIiIyAqOLBERERFZwWCJiIiIyAoGS0RERERWMFgiIiIisoLBkpd44403kJqaiuDgYGRmZmL79u2eviSvsnjxYvTr1w8RERFISEjA+PHjceTIEU9fltd6/vnnoVKpMGvWLE9fitc5f/487rjjDrRo0QIhISHIyMjAzp07PX1ZXkOj0WD+/Plo164dQkJC0L59ezzzzDNozmuBNm3ahOuvvx4pKSlQqVT49ttvTe7X6XRYsGABkpOTERISgqysLBw7dswzF+sh1l6juro6zJ07FxkZGQgLC0NKSgomTZqECxcueO6C7cRgyQusWrUKc+bMwZNPPondu3ejR48eGDlyJAoLCz19aV5j48aNeOCBB7B161asXbsWdXV1GDFiBCorKz19aV5nx44deOutt9C9e3dPX4rXuXz5MgYPHoyAgAD88ssvOHjwIF566SXExMR4+tK8xpIlS/Dmm2/iP//5Dw4dOoQlS5Zg6dKleP311z19aR5TWVmJHj164I033jB7/9KlS7Fs2TIsX74c27ZtQ1hYGEaOHInq6mo3X6nnWHuNqqqqsHv3bsyfPx+7d+/G119/jSNHjmDcuHEeuFIH6cjj+vfvr3vggQfE7zUajS4lJUW3ePFiD16VdyssLNQB0G3cuNHTl+JVysvLdR07dtStXbtWd+211+r++c9/evqSvMrcuXN1Q4YM8fRleLWxY8fq7r77bpPbbrzxRt3EiRM9dEXeBYDum2++Eb/XarW6pKQk3QsvvCDeVlJSogsKCtJ9+umnHrhCz2v4Gpmzfft2HQBdbm6uey7KSRxZ8rDa2lrs2rULWVlZ4m1qtRpZWVnYsmWLB6/Mu5WWlgIAYmNjPXwl3uWBBx7A2LFjTX6eyOj7779H3759ccsttyAhIQG9evXCihUrPH1ZXmXQoEHIzs7G0aNHAQB79+7FH3/8gdGjR3v4yrzTqVOnkJ+fb/I7FxUVhczMTP4Nt6K0tBQqlQrR0dGevhRZ2EjXw4qKiqDRaJCYmGhye2JiIg4fPuyhq/JuWq0Ws2bNwuDBg9GtWzdPX47X+Oyzz7B7927s2LHD05fitU6ePIk333wTc+bMweOPP44dO3bgoYceQmBgIO666y5PX55XeOyxx1BWVob09HT4+flBo9Hgueeew8SJEz19aV4pPz8fAMz+DRfuI1PV1dWYO3cubr/9dq9srGsOgyXyOQ888AAOHDiAP/74w9OX4jXOnj2Lf/7zn1i7di2Cg4M9fTleS6vVom/fvli0aBEAoFevXjhw4ACWL1/OYMng888/x8cff4xPPvkEV111FXJycjBr1iykpKTwNSKn1dXV4dZbb4VOp8Obb77p6cuRjdNwHhYXFwc/Pz8UFBSY3F5QUICkpCQPXZX3mjlzJn788UesX78erVq18vTleI1du3ahsLAQvXv3hr+/P/z9/bFx40YsW7YM/v7+0Gg0nr5Er5CcnIyuXbua3NalSxecOXPGQ1fkff71r3/hsccew2233YaMjAzceeedmD17NhYvXuzpS/NKwt9p/g23TQiUcnNzsXbtWp8ZVQIYLHlcYGAg+vTpg+zsbPE2rVaL7OxsDBw40INX5l10Oh1mzpyJb775Br/99hvatWvn6UvyKsOHD8f+/fuRk5MjfvXt2xcTJ05ETk4O/Pz8PH2JXmHw4MGNSk4cPXoUbdu29dAVeZ+qqiqo1aZvDX5+ftBqtR66Iu/Wrl07JCUlmfwNLysrw7Zt2/g3XEIIlI4dO4Z169ahRYsWnr4ku3AazgvMmTMHd911F/r27Yv+/fvj1VdfRWVlJaZMmeLpS/MaDzzwAD755BN89913iIiIEHMBoqKiEBIS4uGr87yIiIhG+VthYWFo0aIF87okZs+ejUGDBmHRokW49dZbsX37drz99tt4++23PX1pXuP666/Hc889hzZt2uCqq67Cnj178PLLL+Puu+/29KV5TEVFBY4fPy5+f+rUKeTk5CA2NhZt2rTBrFmz8Oyzz6Jjx45o164d5s+fj5SUFIwfP95zF+1m1l6j5ORk3Hzzzdi9ezd+/PFHaDQa8W94bGwsAgMDPXXZ8nl6OR7pvf7667o2bdroAgMDdf3799dt3brV05fkVQCY/Xrvvfc8fWlei6UDzPvhhx903bp10wUFBenS09N1b7/9tqcvyauUlZXp/vnPf+ratGmjCw4O1qWlpen+/e9/62pqajx9aR6zfv16s39/7rrrLp1Opy8fMH/+fF1iYqIuKChIN3z4cN2RI0c8e9FuZu01OnXqlMW/4evXr/f0pcui0umacVlWIiIiIhuYs0RERERkBYMlIiIiIisYLBERERFZwWCJiIiIyAoGS0RERERWMFgiIiIisoLBEhEREZEVDJaIiIiIrGCwREQ+b/LkyR5tLXHnnXdi0aJFihyrtrYWqamp2LlzpyLHIyLnsYI3EXk1lUpl9f4nn3wSs2fPhk6nQ3R0tHsuSmLv3r0YNmwYcnNzER4ersgx//Of/+Cbb74xac5KRJ7DYImIvJrQcBMAVq1ahQULFuDIkSPibeHh4YoFKY6455574O/vj+XLlyt2zMuXLyMpKQm7d+/GVVddpdhxicgxnIYjIq+WlJQkfkVFRUGlUpncFh4e3mgabujQoXjwwQcxa9YsxMTEIDExEStWrEBlZSWmTJmCiIgIdOjQAb/88ovJuQ4cOIDRo0cjPDwciYmJuPPOO1FUVGTx2jQaDb788ktcf/31JrenpqZi0aJFuPvuuxEREYE2bdrg7bffFu+vra3FzJkzkZycjODgYLRt2xaLFy8W74+JicHgwYPx2WefOfnqEZESGCwRUZP0wQcfIC4uDtu3b8eDDz6IGTNm4JZbbsGgQYOwe/dujBgxAnfeeSeqqqoAACUlJRg2bBh69eqFnTt3YvXq1SgoKMCtt95q8Rz79u1DaWkp+vbt2+i+l156CX379sWePXtw//33Y8aMGeKI2LJly/D999/j888/x5EjR/Dxxx8jNTXV5PH9+/fH77//rtwLQkQOY7BERE1Sjx498MQTT6Bjx46YN28egoODERcXh2nTpqFjx45YsGABLl26hH379gHQ5wn16tULixYtQnp6Onr16oWVK1di/fr1OHr0qNlz5Obmws/PDwkJCY3uGzNmDO6//3506NABc+fORVxcHNavXw8AOHPmDDp27IghQ4agbdu2GDJkCG6//XaTx6ekpCA3N1fhV4WIHMFgiYiapO7du4vbfn5+aNGiBTIyMsTbEhMTAQCFhYUA9Ina69evF3OgwsPDkZ6eDgA4ceKE2XNcuXIFQUFBZpPQpecXpg6Fc02ePBk5OTno3LkzHnroIaxZs6bR40NCQsRRLyLyLH9PXwARkSsEBASYfK9SqUxuEwIcrVYLAKioqMD111+PJUuWNDpWcnKy2XPExcWhqqoKtbW1CAwMtHl+4Vy9e/fGqVOn8Msvv2DdunW49dZbkZWVhS+//FLcv7i4GPHx8XKfLhG5EIMlIiLoA5ivvvoKqamp8PeX96exZ8+eAICDBw+K23JFRkZiwoQJmDBhAm6++WaMGjUKxcXFiI2NBaBPNu/Vq5ddxyQi1+A0HBERgAceeADFxcW4/fbbsWPHDpw4cQK//vorpkyZAo1GY/Yx8fHx6N27N/744w+7zvXyyy/j008/xeHDh3H06FF88cUXSEpKMqkT9fvvv2PEiBHOPCUiUgiDJSIi6BOqN2/eDI1GgxEjRiAjIwOzZs1CdHQ01GrLfyrvuecefPzxx3adKyIiAkuXLkXfvn3Rr18/nD59Gj///LN4ni1btqC0tBQ333yzU8+JiJTBopRERE64cuUKOnfujFWrVmHgwIGKHHPChAno0aMHHn/8cUWOR0TO4cgSEZETQkJC8OGHH1otXmmP2tpaZGRkYPbs2Yocj4icx5ElIiIiIis4skRERERkBYMlIiIiIisYLBERERFZwWCJiIiIyAoGS0RERERWMFgiIiIisoLBEhEREZEVDJaIiIiIrGCwRERERGTF/wNpIUkcU+qg/gAAAABJRU5ErkJggg==", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -1637,22 +77,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/00MappingTemplate.ipynb b/doc/source/examples/00MappingTemplate.ipynb index d5dc11078..b9fb1f9d1 100644 --- a/doc/source/examples/00MappingTemplate.ipynb +++ b/doc/source/examples/00MappingTemplate.ipynb @@ -59,7 +59,6 @@ "output_type": "stream", "text": [ "we expect an exception here:\n", - "MissingMappingException : The template needs a mapping function for parameter(s) {'omega', 'a'}\n", "\n", "no exception with allow_partial_parameter_mapping=True\n", "2*pi/omega\n", @@ -139,8 +138,8 @@ "remapped_sine channels: {'sin_channel'}\n", "remapped_sine measurements: {'M_sin'}\n", "\n", - "{'sin_channel', 'cos_channel'}\n", - "{'M_cos', 'M_sin'}\n" + "{'cos_channel', 'sin_channel'}\n", + "{'M_sin', 'M_cos'}\n" ] } ], @@ -177,792 +176,18 @@ "metadata": {}, "outputs": [ { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "The number of channels in table_template is 2.\n" + ] }, { "data": { - "text/html": [ - "" - ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjUAAAHHCAYAAABHp6kXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABekUlEQVR4nO3dd1gUVxsF8LMgLB1EBURRRFEEURGisQU7NhJjrIkGSxJN7CUajYoliiUa62fsLRq7xmisiL1hwWgsIKIYewURBd2d748NC8sCUnZ32OH8nocnd+8MM+8O4J7cuTMjEwRBABEREZGRMxG7ACIiIiJdYKghIiIiSWCoISIiIklgqCEiIiJJYKghIiIiSWCoISIiIklgqCEiIiJJYKghIiIiSWCoISIiIklgqCEqZNzd3dG2bVuxy9AZd3d39OjRw2D7ys2xO3ToEGQyGQ4dOqT/ogopmUyG8ePHi10GkU4x1BDlQWRkJPr37w8fHx9YW1ujXLly6NSpE6Kjo8UuzeidOHEC48ePx4sXL8QuJV/++uuvIhESrly5gvHjx+PWrVtil0KkhaGGKA+mTZuGLVu2oGnTppgzZw6++eYbHDlyBLVq1cLly5fFLs+onThxAhMmTDDqUDNhwgSxy9C7K1euYMKECQw1VCgVE7sAImMydOhQrFu3Dubm5uq+zp07w9fXF1OnTsVvv/0mYnVEREUbR2qI8qBevXoagQYAPD094ePjg6tXr+ZqG7/99htq164NKysrFC9eHB999BH27duntd6xY8dQu3ZtWFhYwMPDA6tXr9ZY/uzZMwwfPhy+vr6wsbGBnZ0dWrVqhYsXL2qslzZ/ZOPGjZg8eTLKli0LCwsLNG3aFDdu3NBYt1GjRqhWrRquXLmCxo0bw8rKCmXKlMH06dO16ktJSUFoaCgqVaoEuVwONzc3jBgxAikpKbk6DhmNHz8e33//PQCgQoUKkMlkkMlk6tGAFStWoEmTJnBycoJcLoe3tzcWLlyY7fb27duHmjVrwsLCAt7e3ti6dWuu6jh9+jRatmwJe3t7WFlZITAwEMePH3/v9/Xo0QMLFiwAAHXtMplMvVypVGL27Nnw8fGBhYUFnJ2d0adPHzx//lxjO2lzgg4dOoSAgABYWlrC19dXPfdn69at8PX1hYWFBfz9/XHhwgWtOmxsbHDz5k0EBQXB2toarq6umDhxIgRByPE93L59G9999x2qVKkCS0tLlChRAh07dtQYkVm5ciU6duwIAGjcuLH6fWacm7R79240bNgQ1tbWsLW1RZs2bfDPP/+89xgS6QJDDVEBCYKAhw8fomTJku9dd8KECejevTvMzMwwceJETJgwAW5ubjh48KDGejdu3ECHDh3QvHlzzJw5E8WLF0ePHj00Phxu3ryJ7du3o23btpg1axa+//57XLp0CYGBgbh3757WvqdOnYpt27Zh+PDhGDVqFE6dOoUvvvhCa73nz5+jZcuWqFGjBmbOnAkvLy+MHDkSu3fvVq+jVCrx8ccf4+eff0ZwcDDmzZuHdu3a4ZdffkHnzp3zcvgAAO3bt0fXrl0BAL/88gvWrFmDNWvWoFSpUgCAhQsXonz58hg9ejRmzpwJNzc3fPfdd+ogkVFMTAw6d+6MVq1aISwsDMWKFUPHjh2xf//+HGs4ePAgPvroIyQmJiI0NBRTpkzBixcv0KRJE5w5cybH7+3Tpw+aN28OAOra16xZo7H8+++/R/369TFnzhz07NkTa9euRVBQEN6+fauxrRs3buDzzz9HcHAwwsLC8Pz5cwQHB2Pt2rUYMmQIunXrhgkTJiA2NhadOnWCUqnU+H6FQoGWLVvC2dkZ06dPh7+/P0JDQxEaGprje4iMjMSJEyfQpUsXzJ07F3379kV4eDgaNWqE5ORkAMBHH32EgQMHAgBGjx6tfp9Vq1ZVv/c2bdrAxsYG06ZNw9ixY3HlyhU0aNCAp6vIMAQiKpA1a9YIAIRly5bluF5MTIxgYmIifPrpp4JCodBYplQq1e3y5csLAIQjR46o+x49eiTI5XJh2LBh6r43b95obScuLk6Qy+XCxIkT1X0RERECAKFq1apCSkqKun/OnDkCAOHSpUvqvsDAQAGAsHr1anVfSkqK4OLiInz22Wca79nExEQ4evSoxv5//fVXAYBw/PhxjfcTEhKS47ERBEGYMWOGAECIi4vTWpacnKzVFxQUJHh4eGj0pR27LVu2qPsSEhKE0qVLC35+fuq+tGMSEREhCILq+Ht6egpBQUEaP4vk5GShQoUKQvPmzd9bf79+/YSs/kk9evSoAEBYu3atRv+ePXu0+tPqP3HihLpv7969AgDB0tJSuH37trp/0aJFGu9BEAQhJCREACAMGDBA3adUKoU2bdoI5ubmwuPHj9X9AITQ0FCN95rZyZMntX4fNm3apLVfQRCEly9fCg4ODsLXX3+t0f/gwQPB3t5eq59IHzhSQ1QA165dQ79+/VC3bl2EhITkuO727duhVCoxbtw4mJho/ullPFUBAN7e3mjYsKH6dalSpVClShXcvHlT3SeXy9XbUSgUePr0KWxsbFClShWcP39ea/89e/bUOHWWtv2M2wQAGxsbdOvWTf3a3NwctWvX1lhv06ZNqFq1Kry8vPDkyRP1V5MmTQAAEREROR6LvLK0tFS3ExIS8OTJEwQGBuLmzZtISEjQWNfV1RWffvqp+rWdnR2+/PJLXLhwAQ8ePMhy+1FRUYiJicHnn3+Op0+fqt/Pq1ev0LRpUxw5ckRrRCS3Nm3aBHt7ezRv3lzjWPn7+8PGxkbrWHl7e6Nu3brq13Xq1AEANGnSBOXKldPqz/zzA4D+/fur2zKZDP3790dqaioOHDiQbZ0Zj/Hbt2/x9OlTVKpUCQ4ODln+PmW2f/9+vHjxAl27dtV4n6ampqhTp47OfyeIssKJwkT59ODBA7Rp0wb29vbYvHkzTE1NAag+dF+/fq1ez9zcHI6OjoiNjYWJiQm8vb3fu+2MH15pihcvrjEHQ6lUYs6cOfjf//6HuLg4KBQK9bISJUq8d5vFixcHAK15HWXLltUKWcWLF8fff/+tfh0TE4OrV6+qTw9l9ujRoyz7FQoFHj9+rNHn6OioNU8ps+PHjyM0NBQnT55UnwpJk5CQAHt7e/XrSpUqadVfuXJlAMCtW7fg4uKitf2YmBgAyDGYJiQkwNraGs+ePdPoL1WqlPpnn5WYmBgkJCTAyckpy+WZj1Xmn1Pae3Nzc8uyP/PPz8TEBB4eHhp9Gd9/dl6/fo2wsDCsWLECd+/e1ZiDkzk4ZiXtGKYF28zs7Ozeuw2igmKoIcqHhIQEtGrVCi9evMDRo0fh6uqqXjZo0CCsWrVK/TowMDDPN3nL7kMy4wfNlClTMHbsWPTq1QuTJk2Co6MjTExMMHjw4CxHFXKzzdyup1Qq4evri1mzZmW5buYP4DR37txBhQoVNPoiIiLQqFGjLNcHgNjYWDRt2hReXl6YNWsW3NzcYG5ujr/++gu//PJLvkdQMkrbxowZM1CzZs0s17GxscHx48fRuHFjjf64uDi4u7vnuG0nJyesXbs2y+WZg2F2xz+3P7/8GjBgAFasWIHBgwejbt26sLe3h0wmQ5cuXXJ1jNPWWbNmTZbBsVgxftyQ/vG3jCiP3rx5g+DgYERHR+PAgQNaIy8jRozQOH2TNiJSsWJFKJVKXLlyJdsPzrzYvHkzGjdujGXLlmn0v3jxIleTlguiYsWKuHjxIpo2bao1KpITFxcXrQm7NWrUAKB9Ci7Nn3/+iZSUFOzYsUNjFCO70xk3btyAIAga20u7OWJ24aNixYoAVKMJzZo1y7b+GjVqaNWf9gGeXf0VK1bEgQMHUL9+fY1TPPqiVCpx8+ZN9egM8P73D6h+n0JCQjBz5kx135s3b7TuG5TT+wQAJyenHI8hkT5xTg1RHigUCnTu3BknT57Epk2bNOY+pPH29kazZs3UX/7+/gCAdu3awcTEBBMnTtT6P9/8/N+2qamp1vdt2rQJd+/ezfO28qpTp064e/culixZorXs9evXePXqVZbfZ2FhoXFsmjVrpg591tbWAKD1IZo2QpH5dMiKFSuy3Me9e/ewbds29evExESsXr0aNWvWzHIEAQD8/f1RsWJF/Pzzz0hKStJannbKrHjx4lr1W1hY5Fh/p06doFAoMGnSJK3tvnv3Ti83G5w/f766LQgC5s+fDzMzMzRt2jTb78nq92nevHkapzWB7N9nUFAQ7OzsMGXKFK0rugBonXYk0geO1BDlwbBhw7Bjxw4EBwfj2bNnWjfbyzhCk1mlSpXw448/YtKkSWjYsCHat28PuVyOyMhIuLq6IiwsLE+1tG3bFhMnTkTPnj1Rr149XLp0CWvXrtWaT6EP3bt3x8aNG9G3b19ERESgfv36UCgUuHbtGjZu3Ii9e/ciICAgT9tMC38//vgjunTpAjMzMwQHB6NFixYwNzdHcHAw+vTpg6SkJCxZsgROTk64f/++1nYqV66M3r17IzIyEs7Ozli+fDkePnyYbQgCVPNQli5dilatWsHHxwc9e/ZEmTJlcPfuXURERMDOzg5//vlnruofOHAggoKCYGpqii5duiAwMBB9+vRBWFgYoqKi0KJFC5iZmSEmJgabNm3CnDlz0KFDhzwdq5xYWFhgz549CAkJQZ06dbB7927s2rULo0ePznYOFKD6fVqzZg3s7e3h7e2NkydP4sCBA1rzs2rWrAlTU1NMmzYNCQkJkMvl6nsILVy4EN27d0etWrXQpUsXlCpVCvHx8di1axfq16+vEbaI9EKkq66IjFLaJc/ZfeXG8uXLBT8/P0EulwvFixcXAgMDhf3796uXly9fXmjTpk2W+w4MDFS/fvPmjTBs2DChdOnSgqWlpVC/fn3h5MmTWuulXb68adMmje3FxcUJAIQVK1Zo7MPHx0dr3yEhIUL58uU1+lJTU4Vp06YJPj4+6vfi7+8vTJgwQUhISNB4P7m5pFsQBGHSpElCmTJlBBMTE43Lu3fs2CFUr15dsLCwENzd3YVp06YJy5cv17oEPO3Y7d27V6hevbogl8sFLy8vrfee+ZLuNBcuXBDat28vlChRQpDL5UL58uWFTp06CeHh4e+t/d27d8KAAQOEUqVKCTKZTOv3YfHixYK/v79gaWkp2NraCr6+vsKIESOEe/fuadWfGQChX79+Gn1pP78ZM2ao+0JCQgRra2shNjZWaNGihWBlZSU4OzsLoaGhWpf/I9Ml3c+fPxd69uwplCxZUrCxsRGCgoKEa9euZfnzW7JkieDh4SGYmppqHceIiAghKChIsLe3FywsLISKFSsKPXr0EM6ePfveY0hUUDJB0NEsMyIiElWPHj2wefPmLE+hERUFnFNDREREksBQQ0RERJLAUENERESSwDk1REREJAkcqSEiIiJJYKghIiIiSShSN99TKpW4d+8ebG1t83RrdyIiIhKPIAh4+fIlXF1dYWKS/XhMkQo19+7dy/ZBe0RERFS43blzB2XLls12eZEKNba2tgBUB8XOzk7kaoiIiCg3EhMT4ebmpv4cz06RCjVpp5zs7OwYaoiIiIzM+6aOcKIwERERSQJDDREREUkCQw0RERFJAkMNERERSQJDDREREUkCQw0RERFJAkMNERERSQJDDREREUkCQw0RERFJAkMNERERSQJDDREREUkCQw0RERFJAkMNERERSQJDDREREUkCQw0RERFJAkMNERERSQJDDREREUkCQw0RERFJAkMNERERSQJDDREREUkCQw0RERFJAkMNERERSQJDDREREUkCQw0RERFJgtGGmqlTp0Imk2Hw4MFil0JERESFgFGGmsjISCxatAjVq1cXuxQiIiIqJIqJXUBeJSUl4YsvvsCSJUvw008/iV2OUXv8MgUp7xRil0FERsbFzgLFTI3y/4lJ4owu1PTr1w9t2rRBs2bN3htqUlJSkJKSon6dmJio7/KMxqoTtxC64x+xyyAiI1SjrD3+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", "text/plain": [ - "" + "
" ] }, "metadata": {}, "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The number of channels in table_template is 2.\n" - ] } ], "source": [ "from qupulse.pulses import TablePT\n", + "from qupulse.plotting import plot\n", "\n", "table_template = TablePT(identifier='2-channel-table-template',\n", " entries={'first_channel' : [(0, 0),\n", @@ -832,9 +51,6 @@ " (9, 'bar', 'linear')]}\n", " )\n", "\n", - "# plot it\n", - "%matplotlib notebook\n", - "from qupulse.pulses.plotting import plot\n", "parameters = dict(\n", " foo=7,\n", " bar=-1.3\n", @@ -860,804 +76,22 @@ "metadata": {}, "outputs": [ { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "The number of channels in sequence_template is 2.\n" + ] }, { "data": { - "text/html": [ - "" - ], + "image/png": "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", "text/plain": [ - "" + "
" ] }, "metadata": {}, "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The number of channels in sequence_template is 2.\n" - ] } ], "source": [ @@ -2590,22 +221,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/00PointPulse.ipynb b/doc/source/examples/00PointPulse.ipynb index 2eff02f84..e99cbc0a9 100644 --- a/doc/source/examples/00PointPulse.ipynb +++ b/doc/source/examples/00PointPulse.ipynb @@ -49,791 +49,9 @@ "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], + "image/png": "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", "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -890,8 +108,6 @@ } ], "source": [ - "%matplotlib notebook\n", - "\n", "import json\n", "from qupulse.pulses.plotting import plot\n", "\n", @@ -903,22 +119,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.2" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/00SimpleTablePulse.ipynb b/doc/source/examples/00SimpleTablePulse.ipynb index 3da941c64..6c7c313c5 100644 --- a/doc/source/examples/00SimpleTablePulse.ipynb +++ b/doc/source/examples/00SimpleTablePulse.ipynb @@ -65,791 +65,9 @@ "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGwCAYAAABVdURTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA5f0lEQVR4nO3de1xUdeL/8TcgVwW8clHxCok3EMULamlqmvm12G+Z63dLNG3T1Uqpr34xV6vdlcrMtFzNyrXLmlqmtVYqkpdUzCulmZlXvADeQVBBYX5/9HO2WcFmcOAMh9fz8ZjHg/nMOWfeMxW8O+czn3GzWCwWAQAAmIS70QEAAACciXIDAABMhXIDAABMhXIDAABMhXIDAABMhXIDAABMhXIDAABMpZrRASpacXGxTp06JX9/f7m5uRkdBwAA2MFisejSpUuqX7++3N1vfW6mypWbU6dOKSwszOgYAACgDI4fP66GDRvecpsqV278/f0l/fLmBAQEGJwGAADYIzc3V2FhYda/47dS5crNjUtRAQEBlBsAACoZe6aUMKEYAACYCuUGAACYCuUGAACYSpWbcwMAMJeioiJdu3bN6BhwAi8vr9/8mLc9KDcAgErJYrEoKytLFy9eNDoKnMTd3V1NmzaVl5fXbR2HcgMAqJRuFJugoCD5+fmxMGsld2OR3czMTDVq1Oi2/nlSbgAAlU5RUZG12NSpU8foOHCSevXq6dSpU7p+/bo8PT3LfBwmFAMAKp0bc2z8/PwMTgJnunE5qqio6LaOQ7kBAFRaXIoyF2f986TcAAAAU6HcAAAAU6HcAADgIo4ePSo3Nzelp6cbHcUuPXv21Lhx44yOcRPKDQAAKDfr169X+/bt5e3trfDwcC1cuLDcn5NyAwAAysWRI0c0YMAA3X333UpPT9e4ceM0cuRIrV69ulyfl3IDADAFi8Wiy4XXDblZLBa7cxYXF+uVV15ReHi4vL291ahRI/3tb3+z2ebw4cO6++675efnp+joaKWlpVkfO3funIYMGaIGDRrIz89Pbdu21UcffWSzf8+ePfXUU09pwoQJql27tkJCQvT888/bbOPm5qZ33nlHv/vd7+Tn56eIiAh9/vnnNtvs3btX/fv3V40aNRQcHKxHH31UZ8+etfu1zps3T02bNtWMGTPUsmVLjR07Vg899JBmzpxp9zHKgkX8AACmcOVakVpNKd8zAqXZ92I/+XnZ9yc1KSlJb7/9tmbOnKnu3bsrMzNT+/fvt9nmueee06uvvqqIiAg999xzGjJkiA4ePKhq1arp6tWr6tChgyZOnKiAgAB98cUXevTRR9W8eXN16tTJeoz33ntPiYmJ+vbbb5WWlqZhw4apW7duuueee6zbvPDCC3rllVc0ffp0vfHGG/rDH/6gY8eOqXbt2rp48aJ69eqlkSNHaubMmbpy5YomTpyohx9+WF9//bVdrzUtLU19+vSxGevXr1+5z9Oh3AAAUEEuXbqkWbNm6c0331RCQoIkqXnz5urevbvNds8++6wGDBgg6ZcC0rp1ax08eFCRkZFq0KCBnn32Weu2Tz75pFavXq2lS5falJuoqChNnTpVkhQREaE333xTqampNuVm2LBhGjJkiCRp2rRpmj17trZt26Z7771Xb775pmJiYjRt2jTr9gsWLFBYWJgOHDigO+644zdfb1ZWloKDg23GgoODlZubqytXrsjX19eu981RlBsAgCn4enpo34v9DHtue/z4448qKChQ7969b7ldVFSU9efQ0FBJ0unTpxUZGamioiJNmzZNS5cu1cmTJ1VYWKiCgoKbVmv+9TFuHOf06dOlblO9enUFBARYt/nuu++0bt061ahR46Z8hw4dsqvcGIVyAwAwBTc3N7svDRnF3jMVv/5epRur9hYXF0uSpk+frlmzZun1119X27ZtVb16dY0bN06FhYWlHuPGcW4cw55t8vLyNHDgQL388ss35btRuH5LSEiIsrOzbcays7MVEBBQbmdtJMoNAAAVJiIiQr6+vkpNTdXIkSPLdIzNmzfrgQce0COPPCLpl9Jz4MABtWrVyplR1b59ey1btkxNmjRRtWplqwtxcXH68ssvbcZSUlIUFxfnjIil4tNSAABUEB8fH02cOFETJkzQ+++/r0OHDmnr1q1699137T5GRESEUlJStGXLFv3444964oknbjo74gxjxozR+fPnNWTIEG3fvl2HDh3S6tWrNXz4cLu/2HLUqFE6fPiwJkyYoP379+vvf/+7li5dqvHjxzs9769x5gYAgAr05z//WdWqVdOUKVN06tQphYaGatSoUXbvP3nyZB0+fFj9+vWTn5+f/vjHPyo+Pl45OTlOzVm/fn1t3rxZEydOVN++fVVQUKDGjRvr3nvvlbu7fedGmjZtqi++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AwIAADjC4TM3sbGx1p+DgoK0atUqpwYCAAC4HSziBwAATMWucnPvvfdq69atv7ndpUuX9PLLL2vOnDm3HQwAAKAs7LosNWjQID344IMKDAzUwIEDFRsbq/r168vHx0cXLlzQvn37tGnTJn355ZcaMGCApk+fXt65AQAASmRXuRkxYoQeeeQRffzxx1qyZInmz5+vnJwcSZKbm5tatWqlfv36afv27WrZsmW5BgYAALgVuycUe3t765FHHtEjjzwiScrJydGVK1dUp04deXp6lltAAAAAR5TpizOlXxbtCwwMdGYWAACA28anpQAAgKlQbgAAgKlQbgAAgKkYWm42btyogQMHqn79+nJzc9OKFStuuf369evl5uZ20y0rK6tiAgMAAJdXpnJz8eJFvfPOO0pKStL58+clSbt27dLJkycdOk5+fr6io6MdXvTvp59+UmZmpvUWFBTk0P4AAMC8HP601Pfff68+ffooMDBQR48e1eOPP67atWvr008/VUZGht5//327j9W/f3/179/f0QgKCgpSzZo1Hd4PAACYn8NnbhITEzVs2DD9/PPP8vHxsY7fd9992rhxo1PDlaZdu3YKDQ3VPffco82bN99y24KCAuXm5trcAACAeTlcbrZv364nnnjipvEGDRqU+9yX0NBQzZs3T8uWLdOyZcsUFhamnj17ateuXaXuk5ycbF2TJzAwUGFhYeWaEQAAGMvhy1Le3t4lnv04cOCA6tWr55RQpWnRooVatGhhvd+1a1cdOnRIM2fO1AcffFDiPklJSUpMTLTez83NpeAAAGBiDp+5uf/++/Xiiy/q2rVrkn75bqmMjAxNnDhRDz74oNMD/pZOnTrp4MGDpT7u7e2tgIAAmxsAADAvh8vNjBkzlJeXp6CgIF25ckU9evRQeHi4/P399be//a08Mt5Senq6QkNDK/x5AQCAa3L4slRgYKBSUlK0adMmff/998rLy1P79u3Vp08fh588Ly/P5qzLkSNHlJ6ertq1a6tRo0ZKSkrSyZMnrZ/Aev3119W0aVO1bt1aV69e1TvvvKOvv/5aa9ascfi5AQCAOZX5izO7d++u7t2739aT79ixQ3fffbf1/o25MQkJCVq4cKEyMzOVkZFhfbywsFDPPPOMTp48KT8/P0VFRWnt2rU2xwAAAFWbw+Vm9uzZJY67ubnJx8dH4eHhuuuuu+Th4fGbx+rZs6csFkupjy9cuNDm/oQJEzRhwgSH8gIAgKrF4XIzc+ZMnTlzRpcvX1atWrUkSRcuXJCfn59q1Kih06dPq1mzZlq3bh2fSgIAABXO4QnF06ZNU8eOHfXzzz/r3LlzOnfunA4cOKDOnTtr1qxZysjIUEhIiMaPH18eeQEAAG7J4TM3kydP1rJly9S8eXPrWHh4uF599VU9+OCDOnz4sF555RVDPhYOAADg8JmbzMxMXb9+/abx69evW1corl+/vi5dunT76QAAABzkcLm5++679cQTT2j37t3Wsd27d2v06NHq1auXJGnPnj1q2rSp81ICAADYyeFy8+6776p27drq0KGDvL295e3trdjYWNWuXVvvvvuuJKlGjRqaMWOG08MCAAD8Fofn3ISEhCglJUX79+/XgQMHJN38nU+sOwMAAIxS5kX8IiMjFRkZ6cwsAAAAt61M5ebEiRP6/PPPlZGRocLCQpvHXnvtNacEAwAAKAuHy01qaqruv/9+NWvWTPv371ebNm109OhRWSwWtW/fvjwyAgAA2M3hCcVJSUl69tlntWfPHvn4+GjZsmU6fvy4evTooUGDBpVHRgAAALs5XG5+/PFHDR06VJJUrVo1XblyRTVq1NCLL76ol19+2ekBAQAAHOFwualevbp1nk1oaKgOHTpkfezs2bPOSwYAAFAGDs+56dKlizZt2qSWLVvqvvvu0zPPPKM9e/bo008/VZcuXcojIwAAgN0cLjevvfaa8vLyJEkvvPCC8vLytGTJEkVERPBJKQAAYDiHy02zZs2sP1evXl3z5s1zaiAAAIDb4fCcm2bNmuncuXM3jV+8eNGm+AAAABjB4XJz9OhRFRUV3TReUFCgkydPOiUUAABAWdl9Werzzz+3/rx69WoFBgZa7xcVFSk1NVVNmjRxajgAAABH2V1u4uPjJUlubm5KSEiweczT01NNmjThm8ABAIDh7C43xcXFkqSmTZtq+/btqlu3brmFAgAAKCuHPy115MiR8sgBAADgFHaVm9mzZ9t9wKeeeqrMYQAAAG6XXeVm5syZdh3Mzc2NcgMAAAxlV7nhUhQAAKgsHF7n5tcsFossFouzsgAAANy2MpWb999/X23btpWvr698fX0VFRWlDz74wNnZAAAAHFamL87885//rLFjx6pbt26SpE2bNmnUqFE6e/asxo8f7/SQAAAA9nK43LzxxhuaO3euhg4dah27//771bp1az3//POUGwAAYCiHL0tlZmaqa9euN4137dpVmZmZTgkFAABQVg6Xm/DwcC1duvSm8SVLligiIsIpoQAAAMrK4ctSL7zwggYPHqyNGzda59xs3rxZqampJZYeAACAimT3mZu9e/dKkh588EF9++23qlu3rlasWKEVK1aobt262rZtm373u9+VW1AAAAB72H3mJioqSh07dtTIkSP1+9//Xh9++GF55gIAACgTu8/cbNiwQa1bt9Yzzzyj0NBQDRs2TN988015ZgMAAHCY3eXmzjvv1IIFC5SZmak33nhDR44cUY8ePXTHHXfo5ZdfVlZWVnnmBAAAsIvDn5aqXr26hg8frg0bNujAgQMaNGiQ5syZo0aNGun+++8vj4wAAAB2u63vlgoPD9ekSZM0efJk+fv764svvnBWLgAAgDJx+KPgN2zcuFELFizQsmXL5O7urocfflgjRoxwZjYAAACHOVRuTp06pYULF2rhwoU6ePCgunbtqtmzZ+vhhx9W9erVyysjAACA3ey+LNW/f381btxYb7zxhn73u9/pxx9/1KZNmzR8+PAyF5uNGzdq4MCBql+/vtzc3LRixYrf3Gf9+vVq3769vL29FR4eroULF5bpuQEAgDnZXW48PT31ySef6MSJE3r55ZfVokWL237y/Px8RUdHa86cOXZtf+TIEQ0YMEB333230tPTNW7cOI0cOVKrV6++7SwAAMAc7L4s9fnnnzv9yfv376/+/fvbvf28efPUtGlTzZgxQ5LUsmVLbdq0STNnzlS/fv2cng8AAFQ+t/VpqYqWlpamPn362Iz169dPaWlppe5TUFCg3NxcmxsAADCvSlVusrKyFBwcbDMWHBys3NxcXblypcR9kpOTFRgYaL2FhYVVRFQAAGCQSlVuyiIpKUk5OTnW2/Hjx42OBAAAylGZ17kxQkhIiLKzs23GsrOzFRAQIF9f3xL38fb2lre3d0XEAwAALqBSnbmJi4tTamqqzVhKSori4uIMSgQAAFyNoeUmLy9P6enpSk9Pl/TLR73T09OVkZEh6ZdLSkOHDrVuP2rUKB0+fFgTJkzQ/v379fe//11Lly7V+PHjjYgPAABckKHlZseOHYqJiVFMTIwkKTExUTExMZoyZYokKTMz01p0JKlp06b64osvlJKS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2rXTqlWrrJOGMzIy5O7+7xNMXbt21aJFizR58mRNmjRJERERWrFihdq0aWPUSwAAAC7E8HVuKporrXMDAADs48jf78r3+S4AAIBboNwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTodwAAABTqWZ0gIpmsVgkSbm5uQYnAQAA9rrxd/vG3/FbqXLl5tKlS5KksLAwg5MAAABHXbp0SYGBgbfcxs1iTwUykeLiYp06dUr+/v5yc3MzOo5yc3MVFham48ePKyAgwOg4LoX3pmS8L6XjvSkd703peG9K50rvjcVi0aVLl1S/fn25u996Vk2VO3Pj7u6uhg0bGh3jJgEBAYb/i+OqeG9KxvtSOt6b0vHelI73pnSu8t781hmbG5hQDAAATIVyAwAATIVyYzBvb29NnTpV3t7eRkdxObw3JeN9KR3vTel4b0rHe1O6yvreVLkJxQAAwNw4cwMAAEyFcgMAAEyFcgMAAEyFcgMAAEyFcmOgOXPmqEmTJvLx8VHnzp21bds2oyO5hI0bN2rgwIGqX7++3NzctGLFCqMjuYTk5GR17NhR/v7+CgoKUnx8vH766SejY7mEuXPnKioqyrrQWFxcnL766iujY7mcl156SW5ubho3bpzRUVzC888/Lzc3N5tbZGSk0bFcwsmTJ/XII4+oTp068vX1Vdu2bbVjxw6jY9mNcmOQJUuWKDExUVOnTtWuXbsUHR2tfv366fTp00ZHM1x+fr6io6M1Z84co6O4lA0bNmjMmDHaunWrUlJSdO3aNfXt21f5+flGRzNcw4YN9dJLL2nnzp3asWOHevXqpQceeEA//PCD0dFcxvbt2/XWW28pKirK6CgupXXr1srMzLTeNm3aZHQkw124cEHdunWTp6envvrqK+3bt08zZsxQrVq1jI5mPwsM0alTJ8uYMWOs94uKiiz169e3JCcnG5jK9UiyLF++3OgYLun06dMWSZYNGzYYHcUl1apVy/LOO+8YHcMlXLp0yRIREWFJSUmx9OjRw/L0008bHcklTJ061RIdHW10DJczceJES/fu3Y2OcVs4c2OAwsJC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", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -1741,791 +176,9 @@ "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], + "image/png": "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", "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -808,9 +26,8 @@ } ], "source": [ - "%matplotlib notebook\n", "from qupulse.pulses import TablePT\n", - "from qupulse.pulses.plotting import plot\n", + "from qupulse.plotting import plot\n", "\n", "table_pulse = TablePT({'A': [(0, 'v_a'),\n", " ('t_ramp', 'v_b', 'linear')]})\n", @@ -833,7 +50,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'v_a', 'max_rate', 't_ramp', 'v_b'}\n", + "{'v_b', 'max_rate', 'v_a', 't_ramp'}\n", "Abs(v_a - v_b)/t_ramp < max_rate\n", "t_ramp > 1\n" ] @@ -864,7 +81,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "ParameterNotProvidedException: No value was provided for parameter ''max_rate''.\n" + "ParameterNotProvidedException: No value was provided for parameter 'max_rate'.\n" ] } ], @@ -892,7 +109,7 @@ "output_type": "stream", "text": [ "ParameterConstraintViolation: The constraint 'Abs(v_a - v_b)/t_ramp < max_rate' is not fulfilled.\n", - "Parameters: {'v_a': -1, 'max_rate': 0.1, 't_ramp': 10, 'v_b': 1}\n" + "Parameters: DictScope(values=frozendict.frozendict({'t_ramp': 10, 'v_a': -1, 'v_b': 1, 'max_rate': 0.1}))\n" ] } ], @@ -905,22 +122,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/01PulseStorage.ipynb b/doc/source/examples/01PulseStorage.ipynb index 437778796..b0889b321 100644 --- a/doc/source/examples/01PulseStorage.ipynb +++ b/doc/source/examples/01PulseStorage.ipynb @@ -113,21 +113,18 @@ }, { "data": { - "image/png": "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VYXPLVmyhPfff5/Zs2dz/PHHM3LkSOrUqcOLL75Io0aNWLFiBfvuuy/HH388APPmzeOZZ57hoYce4ic/+QnPP/88Z5xxBgDbtm1jypQpjB8/nuuvv56JEyfyyCOP0LhxYz7++GM2b97MAQccwJFHHlliw/eLL77InDlzmDFjBkuXLqVnz56cc845bN26lUsuuYRx48bRokULnn32Wa699loeffRRLrzwQho0aMBvf/tbAB599FGaNm3Kxo0b2XvvvTn55JNp1qxZmftx5MiR3HPPPdx+++3k5eUlvP+TQUVFRLLG22+/zciRI2nevDkATZs2LXzuhBNOoFq1avTs2ZOlS5cCwdHCNddcw6RJk6hWrRrfffdd4XMdO3akf//+AAwaNIiFCxcWbuukk07a5fEJEybw+eefFx4FrVmzhnnz5tG1a9dis06aNInTTjuN6tWr06ZNGw499FAA5syZwxdffMERRxwBBEdArVu3LnYbd911Fy+++CIA3377LfPmzUuoqEQp0qJiZo8CxwLL3H2Xli4L/gS4Ezga2ACMcvdP0ptSRIpT2hFFqrh7iUcGtWvX3mk9gKeffprly5czbdo0atasSYcOHQr7aMSvX7169Z1OEcWeq169Otu2bSvc5t13382wYcN2et/4YlRUcVndnV69ejF58uTSPirvvvsuEydOZPLkydSrV4+hQ4cWZo/fbqaNbhB1m8pjwFGlPD8c6BLeLgDuT0MmEclQhx12GM899xwrV64E2On0V3HWrFlDy5YtqVmzJu+88w6LFlV8dPdhw4Zx//33s3XrVgDmzp3L+vXrS1z/4IMPZsyYMWzfvp0lS5bwzjvvANCtWzeWL19eWFS2bt3KzJkzi83epEkT6tWrx+zZs/nwww8Ln2vVqhWzZs2ioKCg8EimqIYNG7J27doKf96KivRIxd0nmVmHUlYZATzhwZ8dH5rZbmbW2t2XpCWgZDR3Z9HKDSz9cRP1atWgfu3q7NmsPtWrqXNeVdWrVy+uvfZahgwZQvXq1RkwYACPPfZYieuffvrpHHfcceTl5dG/f3+6d+9e4fc+77zzWLhwIQMHDsTdadGiBS+99FKJ65944om8/fbb9OnTh65duzJkyBAAatWqxdixY7n00ktZs2YN27Zt4/LLL6dXr52P/I466igeeOAB+vbtS7du3dh3330Ln7vllls4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\n", + "image/png": "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", "text/plain": [ - "
" + "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], "source": [ - "%matplotlib inline\n", "import math\n", - "from qupulse.pulses.plotting import plot as plot\n", + "from qupulse.plotting import plot\n", "\n", "sine = file_pulse_storage['my_other_pulse']\n", "\n", @@ -389,22 +386,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/02CreatePrograms.ipynb b/doc/source/examples/02CreatePrograms.ipynb index 251769ad5..6e65cbb27 100644 --- a/doc/source/examples/02CreatePrograms.ipynb +++ b/doc/source/examples/02CreatePrograms.ipynb @@ -21,21 +21,19 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjUAAAGwCAYAAABRgJRuAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAABAa0lEQVR4nO3dd3wUdeL/8fembXogJBACoYSEThAIKMWjKfVQPAUOlWKHAznaiUGleAcBrBS/2EDACoogioKISBPpCIjIEWlHr0lIwoYk+/uDH3vmSCCBzc7u5PV8PPbxyM5ndvbtIss7M5+ZsdjtdrsAAAA8nJfRAQAAAJyBUgMAAEyBUgMAAEyBUgMAAEyBUgMAAEyBUgMAAEyBUgMAAEzBx+gArpSXl6djx44pJCREFovF6DgAAKAI7Ha70tPTFR0dLS+vwvfHlKpSc+zYMcXExBgdAwAA3IQjR46ocuXKhY6XqlITEhIi6cqHEhoaamiWzMxM/bh+u6zWCPn5+RmaBZ4jOztbNtsZtWjZSIGBgUbHgYfIzMzUL5u2qWJIuPytVqPjwANcstl0PP2c6jVr7BbfNWlpaYqJiXH8O16YUlVqrh5yCg0NNbzU+Pj4KCgoSCEh5RQQYPz/MPAMWVmZSk/PUmhoqFt80cAzXP2+iSwXocCAAKPjwANkZmUpLc/mdt81N5o6wkRhAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCpQaAABgCh5TambOnKmEhASFhoYqNDRUzZs31zfffGN0LAAA4CY8ptRUrlxZkyZN0tatW7Vlyxa1a9dO9957r3755RejowEAADfgY3SAourWrVu+5xMmTNDMmTP1008/qV69egalAgA3l2OTLp40OgXgEh5Tav4oNzdXn376qTIyMtS8efNC17PZbLLZbI7naWlprogHAMay26UdH0pfDJIkBUqKrtZXivy7sbmAEuZRpWbXrl1q3ry5Ll26pODgYC1atEh169YtdP3k5GSNHz/ehQkBwEBHNkvzHypwz0xQ+r+VZ0AkwJU8Zk6NJNWqVUs7duzQxo0bNXDgQPXr10979uwpdP2kpCSlpqY6HkeOHHFhWgBwgYunpPe6SuPCpFl3cagJpZpH7anx8/NTXFycJKlJkybavHmzpk6dqrfeeqvA9a1Wq6xWqysjAkDJy7FJK1+UNswoeLxiQ6nHHCk8Vto8S1o63KXxAKN4VKn5X3l5efnmzACAadnt0s8fS4sHFjzuFyz1nCfVaCdZLK7NBrgJjyk1SUlJ6ty5s6pUqaL09HR99NFH+uGHH7R8+XKjowFAyTm0QVrQR8o4XfB4x2Sp2ZOSt8d8nQMlxmP+Fpw6dUp9+/bV8ePHFRYWpoSEBC1fvlx333230dEAwLkuHJa+GCwdWF3weON+0t0vSgFlXBoLcHceU2pmzZpldAQAKDnZGdK3L0hbCvmui24k3T9LKlfDtbkAD+IxpQYATCcv70qJ+XpkwePeftJDn0qxbVwaC/BUlBoAcLWD66SPH5RsqQWPd0yWbh8geXnUVTcAw1FqAMAVLhyRPu0vHd1S8PhtD0ldXpb8Al0aCzATSg0AlBTbRem7sdLmdwsej7lD+svbUtmqrs0FmBSlBgCcKS9P2jZH+mpYweOB5aReH0hVW7g0FlAaUGoAwBkOrL1y36VLhcyT+fPrV07FZp4MUGIoNQBws879Li0aIB3ZWPD47QOkdi9I1mDX5gJKKUoNABSHLV36+hnp548KHq/SXPrLO1KZGNfmAkCpAYAbysuVNrwhrXih4HH/MKn3fKlqc9fmApAPpQYACrN/pfRRLynvcsHjXV+VmjzCPBnATVBqAOCPzqZIC/pJJ3cVPN70CanDPyXfANfmAnBDlBoAyDovLX9e2vFBweOxbaV7Z0hhlV2bC0CxUGoAlE65OdKmt6TlowseD4mWes6VYpq5NheAm0apAVB62O1Sykrpk4elnKyC17nvLSmhl2SxuDYbgFtGqQFgfmf2S589Ip3YWfB4y6FS29GSj9WlsQA4F6UGgDldSpWWDJH2LC54vHrrK9eTCang0lgASg6lBoB55OZI61+Tvv9XwePBUVLvj6RKTVybC4BLUGoAeDa7XfrtG+mT3oWv032m1LA382QAk6PUAPBMJ/dIn/aTzuwreLzFEKntc5Kvv2tzATAMpQaA58g4Iy17Vtr1acHjtbpcucpvaEXX5gLgFig1ANxbjk1aP01aVcg8mbLVpAfekyo1dmksAO6HUgPA/djt0q9LpE/7S/a8gtfpMUeq2515MgAcKDUA3MepX6UFfQufJ9N6lPSnf0jevq7NBcAjUGoAGOtSqvT5k9K+ZQWPx3eU/vKWFFDWtbkAeBxKDQDXy70srZ4srXmp4PGy1aS/fiRVqOfSWAA8G6UGgGvY7dIvi67crqAgFi/p/llSvfuYJwPgplBqAJSsY9ulBf2kC4cKHm89SrpzBPddAnDLKDUAnC/9hLR0hLT3q4LH6/1F6jxFCo50bS4ApkapAeAcl7OuzJNZ91rB45G1pQdmM08GQImh1AC4eXa7tHOBtOjJwtf568dS7S6uywSg1KLUACi+Y9ul+X2k1CMFj7d7Xmo5TPLmKwaA6/CNA6BoMs9ducLvgdUFj9e558rdsK3BLo0FAFdRagAULidb+v6f0o/TCh4vX1fq+b4UEefaXABQAEoNgPxuNE/GJ+DKfZdqduR6MgDcCqUGwBVHNksL+kjpxwsev2u81HwQ910C4LYoNUBpduGI9OXfpZSVBY/f9rDU4Z9SYLhrcwHATaDUAKVNdoa08kVp45sFj0clXLldQWRN1+YCgFtEqQFKg7w8afu8K3tlCmLxkh76VIq7y7W5AMCJKDWAmR3+SfrkQSnzbMHjd//zyjwZL2/X5gKAEkCpAcwm7fiV68kc+ang8YRe0p9fk/yCXBoLAEqax5Sa5ORkff7559q7d68CAgLUokULTZ48WbVq1TI6GmC8y1nSd+MKnydTqcmV+y6VrebKVADgUh5TalavXq1BgwapadOmysnJ0ejRo9WhQwft2bNHQUH8xolSyG6Xtr8vLXm64HH/MlLPeVJsa5fGAgCjeEypWbZsWb7nc+bMUfny5bV161b96U9/MigV4Hpl03YrYHpfKet8wSt0eVlKfJR5MgBKHY8pNf8rNTVVkhQeXvj1M2w2m2w2m+N5WlpaiecCSow9V7evbC7vvEvXjjV9XGo/RvIPc30uAHATHllq8vLyNHToULVs2VL169cvdL3k5GSNHz/ehcmAkuObdSJ/oancVPrLO1J4deNCAYAb8chSM2jQIO3evVvr1q277npJSUkaPny443laWppiYmJKOh5Q4jKfOa7AwECjYwCAW/G4UjN48GB99dVXWrNmjSpXrnzdda1Wq6xWq4uSAa6R6+VndAQAcEseU2rsdruefvppLVq0SD/88IOqV2eXOwAA+C+PKTWDBg3SRx99pC+++EIhISE6ceKEJCksLEwBAQEGpwMAAEbzMjpAUc2cOVOpqalq06aNKlas6HjMnz/f6GgAAMANeMyeGrvdbnQEAADgxjxmTw0AAMD1UGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApUGoAAIApeFSpWbNmjbp166bo6GhZLBYtXrzY6EgAAMBNeFSpycjIUMOGDfXGG28YHQUAALgZH6MDFEfnzp3VuXNno2MAAAA35FGlprhsNptsNpvjeVpamoFpAABASfKow0/FlZycrLCwMMcjJibG6EgAAKCEmLrUJCUlKTU11fE4cuSI0ZEAAEAJMfXhJ6vVKqvVanQMAADgAqbeUwMAAEoPj9pTc/HiRe3fv9/x/MCBA9qxY4fCw8NVpUoVA5MBAACjeVSp2bJli9q2bet4Pnz4cElSv379NGfOHINSAQAAd+BRpaZNmzay2+1GxwA8Tm5uri5fvmx0DDiBr6+vvL29jY4BuKVilxqbzaaNGzfq0KFDyszMVGRkpBo1aqTq1auXRD4At8But+vEiRO6cOGC0VHgRGXKlFFUVJQsFovRUQC3UuRSs379ek2dOlVffvmlLl++rLCwMAUEBOjcuXOy2WyKjY3Vk08+qQEDBigkJKQkMwMooquFpnz58goMDOQfQQ9nt9uVmZmpU6dOSZIqVqxocCLAvRSp1Nxzzz3atm2bHnzwQX377bdKTExUQECAY/z333/X2rVr9fHHH+vVV1/VvHnzdPfdd5dYaAA3lpub6yg05cqVMzoOnOTqd++pU6dUvnx5DkUBf1CkUtO1a1ctXLhQvr6+BY7HxsYqNjZW/fr10549e3T8+HGnhgRQfFfn0AQGBhqcBM529c/08uXLlBrgD4pUap566qkib7Bu3bqqW7fuTQcC4FwccjIf/kyBgnHxPQAAYApOKzX9+vVTu3btnLU5ACjQwYMHZbFYtGPHDqOjFEmbNm00dOhQo2MApYLTSk2lSpVUtWpVZ20OAEqFOXPmyGKxOB7BwcFq0qSJPv/8c6OjAR7HaRffmzhxorM2BQClSmhoqH777TdJUnp6ut577z317NlTv/zyi2rVqmVwOsBzMKcGgNvJy8vTlClTFBcXJ6vVqipVqmjChAn51vn999/Vtm1bBQYGqmHDhtqwYYNj7OzZs+rdu7cqVaqkwMBANWjQQB9//HG+17dp00ZDhgzRM888o/DwcEVFRWncuHH51rFYLHr33Xd13333KTAwUPHx8VqyZEm+dXbv3q3OnTsrODhYFSpUUJ8+fXTmzJli/fdaLBZFRUUpKipK8fHx+te//iUvLy/t3LmzWNsBSrti76l59NFHrzs+e/bsmw4DoGTZ7XZlXc415L0DfL2LfNZOUlKS3nnnHb322mtq1aqVjh8/rr179+Zb57nnntPLL7+s+Ph4Pffcc+rdu7f2798vHx8fXbp0SU2aNNGoUaMUGhqqpUuXqk+fPqpRo4aaNWvm2MbcuXM1fPhwbdy4URs2bFD//v3VsmXLfNfZGj9+vKZMmaKXXnpJ06dP10MPPaRDhw4pPDxcFy5cULt27fT444/rtddeU1ZWlkaNGqWePXvq+++/v6nPKTc3V/PmzZMkNW7c+Ka2AZRWxS4158+fz/f88uXL2r17t+MvNwD3lXU5V3XHLDfkvfe82FGBfjf+yklPT9fUqVM1Y8YM9evXT5JUo0YNtWrVKt96I0eOVNeuXSVdKR716tXT/v37Vbt2bVWqVEkjR450rPv0009r+fLlWrBgQb5Sk5CQoLFjx0qS4uPjNWPGDK1cuTJfqenfv7969+4t6cph9mnTpmnTpk3q1KmTZsyYoUaNGuU7/D579mzFxMRo3759qlmzZpE+m9TUVAUHB0uSsrKy5Ovrq7fffls1atQo0usBXFHsUrNo0aJrluXl5WngwIH8BQRwy3799VfZbDa1b9/+uuslJCQ4fr56u4BTp06pdu3ays3N1cSJE7VgwQIdPXpU2dnZstls11yI8I/buLqdq7cgKGidoKAghYaGOtb5+eeftWrVKkch+aOUlJQil5qQkBBt27ZNkpSZmanvvvtOAwYMULly5dStW7cibQOAkyYKe3l5afjw4WrTpo2eeeYZZ2wSQAkI8PXWnhc7GvbeRVrvD7dguZ4/XuH86mGtvLw8SdJLL72kqVOn6vXXX1eDBg0UFBSkoUOHKjs7u9BtXN3O1W0UZZ2LFy+qW7dumjx58jX5inNfJi8vL8XFxTmeJyQk6Ntvv9XkyZMpNUAxOO3sp5SUFOXk5DhrcwBKgMViKdIhICPFx8crICBAK1eu1OOPP35T21i/fr3uvfdePfzww5KulJ19+/Y5/WrnjRs31sKFC1WtWjX5+Dj3c/X29lZWVpZTtwmYXbH/Fg4fPjzfc7vdruPHj2vp0qWO498AcLP8/f01atQoPfPMM/Lz81PLli11+vRp/fLLL3rssceKtI34+Hh99tln+vHHH1W2bFm9+uqrOnnypNNLzaBBg/TOO++od+/ejrOo9u/fr08++UTvvvtuke/LZLfbdeLECUlX5tSsWLFCy5cv15gxY5yaFzC7Ypea7du353vu5eWlyMhIvfLKKzc8MwoAiuKFF16Qj4+PxowZo2PHjqlixYoaMGBAkV///PPP6/fff1fHjh0VGBioJ598Ut27d1dqaqpTc0ZHR2v9+vUaNWqUOnToIJvNpqpVq6pTp07y8ir6FTPS0tIch6usVquqVq2qF198UaNGjXJqXsDsLHa73W50CFdJS0tTWFiYUlNTFRoaamiWzMxMrV2zRSEhlRUQwF2UcWO+mUdV/7t2yvXyk23koRveffvSpUs6cOCAqlevLn9/fxelhCsU68928yxp6XCdLddcea1nKLCIc5ZQumVmZSnl9FElNG96w+8aVyjqv99cfA8AAJiC00rN6NGjOfwEAAAM47Tp+kePHtWRI0ectTkAAIBicVqpmTt3rrM2BQAAUGzMqQEAAKZwU3tqMjIytHr1ah0+fPiaK3QOGTLEKcEAAACK46auU9OlSxdlZmYqIyND4eHhOnPmjAIDA1W+fHlKDQAAMESxDz8NGzZM3bp10/nz5xUQEKCffvpJhw4dUpMmTfTyyy+XREYAAIAbKnap2bFjh0aMGCEvLy95e3vLZrMpJiZGU6ZM0ejRo0siIwAAwA0Vu9T4+vo6Lv9dvnx5HT58WJIUFhbGKd0AStzBgwdlsVi0Y8cOo6MUSZs2bTR06FCjYwClQrHn1DRq1EibN29WfHy8WrdurTFjxujMmTN6//33Vb9+/ZLICACml5WVpUqVKsnLy0tHjx6V1Wo1OhLgcYq9p2bixImOG69NmDBBZcuW1cCBA3X69Gm9/fbbTg8IAKXBwoULVa9ePdWuXVuLFy82Og7gkYpdahITE9W2bVtJVw4/LVu2TGlpadq6dasaNmzo9IAASp+8vDxNmTJFcXFxslqtqlKliiZMmJBvnd9//11t27ZVYGCgGjZsqA0bNjjGzp49q969e6tSpUoKDAxUgwYN9PHHH+d7fZs2bTRkyBA988wzCg8PV1RUlMaNG5dvHYvFonfffVf33XefAgMDFR8fryVLluRbZ/fu3ercubOCg4NVoUIF9enTR2fOnCn2f/OsWbP08MMP6+GHH9asWbOK/XoAXHwPKF3sdik7w5iH3V7kmElJSZo0aZJeeOEF7dmzRx999JEqVKiQb53nnntOI0eO1I4dO1SzZk317t1bOTk5kq7cxbpJkyZaunSpdu/erSeffFJ9+vTRpk2b8m1j7ty5CgoK0saNGzVlyhS9+OKLWrFiRb51xo8fr549e2rnzp3q0qWLHnroIZ07d06SdOHCBbVr106NGjXSli1btGzZMp08eVI9e/Ys1h9LSkqKNmzYoJ49e6pnz55au3atDh06VKxtACjinJpOnTpp3LhxuuOOO667Xnp6uv7v//5PwcHBGjRokFMCAnCiy5nSxGhj3nv0Mckv6Iarpaena+rUqZoxY4b69esnSapRo4ZatWqVb72RI0eqa9eukq4Uj3r16mn//v2qXbu2KlWqpJEjRzrWffrpp7V8+XItWLBAzZo1cyxPSEjQ2LFjJUnx8fGaMWOGVq5cqbvvvtuxTv/+/dW7d29JVw6/T5s2TZs2bVKnTp00Y8YMNWrUSBMnTnSsP3v2bMXExGjfvn2qWbNmkT6a2bNnq3PnzipbtqwkqWPHjnrvvfeu2XME4PqKVGp69Oih+++/X2FhYerWrZsSExMVHR0tf39/nT9/Xnv27NG6dev09ddfq2vXrnrppZdKOjcAk/r1119ls9nUvn37666XkJDg+PnqPL9Tp06pdu3ays3N1cSJE7VgwQIdPXpU2dnZstlsCgwMLHQbV7dz6tSpQtcJCgpSaGioY52ff/5Zq1atUnBw8DX5UlJSilRqcnNzNXfuXE2dOtWx7OGHH9bIkSM1ZswYx9mmAG6sSKXmscce08MPP6xPP/1U8+fP19tvv63U1FRJV445161bVx07dtTmzZtVp06dEg0M4Bb4Bl7ZY2LUexdBQEBA0Tbn6+v42WKxSLoyF0eSXnrpJU2dOlWvv/66GjRooKCgIA0dOvSa27r8cRtXt3N1G0VZ5+LFi+rWrZsmT558Tb6rRetGli9frqNHj6pXr175lufm5l6z1wjA9RX5lG6r1eqYxCZJqampysrKUrly5a75Sw/ATVksRToEZKT4+HgFBARo5cqVevzxx29qG+vXr9e9997r+L7Ky8vTvn37VLduXWdGVePGjbVw4UJVq1ZNPj43dSs9zZo1S3/961/13HPP5Vs+YcIEzZo1i1IDFMNN79cMCwtTVFQUhQaAU/n7+2vUqFF65plnNG/ePKWkpOinn34q1hlB8fHxWrFihX788Uf9+uuveuqpp3Ty5EmnZx00aJDOnTun3r17a/PmzUpJSdHy5cv1yCOPKDc394avP336tL788kv169dP9evXz/fo27evFi9e7JiUDODGOFgLwO288MILGjFihMaMGaM6deqoV69e18x1uZ7nn39ejRs3VseOHdWmTRtFRUWpe/fuTs8ZHR2t9evXKzc3Vx06dFCDBg00dOhQlSlTpkhzYebNm6egoKAC5w+1b99eAQEB+uCDD5yeGzAri91ejPMsPVxaWprCwsKUmpqq0NBQQ7NkZmZq7ZotCgmprICAos01QOnmm3lU9b9rp1wvP9lGHrpm0uv/unTpkg4cOKDq1avL39/fRSnhCsX6s908S1o6XGfLNVde6xkKLOKcJZRumVlZSjl9VAnNm97wu8YVivrvN3tqAACAKXhcqXnjjTdUrVo1+fv76/bbb7/mYloAAKB0uqlSc+HCBb377rtKSkpyTGLbtm2bjh496tRw/2v+/PkaPny4xo4dq23btqlhw4bq2LFjsY61AwAAcyr2OYg7d+7UXXfdpbCwMB08eFBPPPGEwsPD9fnnn+vw4cOaN29eSeSUJL366qt64okn9Mgjj0iS3nzzTS1dulSzZ8/Ws88+W2LvWxLOnjisrLQTslzO02Xuxosi8Lc5/+wdlB65ly/p7JnD8vfj+wY3dinbposXTisz/YJbzKkpqmKXmuHDh6t///6aMmWKQkJCHMu7dOmiBx980Knh/ig7O1tbt25VUlKSY5mXl5fuuuuufDey+yObzSabzeZ4npaWVmL5iiv3/fvV3f4f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NDTfAwAAmJOhc2pGjBih/v37X3ed2NhY14QBAAAezdBSExkZqcjISCMjAAAAk/CYs58OHz6sc+fO6fDhw8rNzdWOHTskXbn/VHBwsLHhAACA4Tym1IwZM0Zz5851PG/UqJEkadWqVWrTpo1BqQAAgLvwmLOf5syZI7vdfs2DQgMAACQPKjUAAADXQ6kBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACmQKkBAACm4BGl5uDBg3rsscdUvXp1BQQEqEaNGho7dqyys7ONjgYAANyEj9EBimLv3r3Ky8vTW2+9pbi4OO3evVtPPPGEMjIy9PLLLxsdDwAAuAGPKDWdOnVSp06dHM9jY2P122+/aebMmZQalDqX8yRbTq4CjQ4CAG7GI0pNQVJTUxUeHn7ddWw2m2w2m+N5WlpaSccCSoyXxeL4udHENZKk13vdpntvi5blD2MAUFp5xJya/7V//35Nnz5dTz311HXXS05OVlhYmOMRExPjooSA85UL8FVc2YB8y4bO36HqSV+rRfJKbT983qBkAOAeDC01zz77rCwWy3Ufe/fuzfeao0ePqlOnTurRo4eeeOKJ624/KSlJqampjseRI0dK8j8HKFEWi0UvtqqmV1sGq3vDqHxjx1Iv6b7/+1HVnl2qPrM26kTqJYNSAoBxDD38NGLECPXv3/+668TGxjp+PnbsmNq2basWLVro7bffvuH2rVarrFbrrcYE3EqQr0UT762j13s30YEzGRr4wVbtPZHuGF/77zO6I3mlJKlv86oa3aWO/H29jYoLAC5jaKmJjIxUZGRkkdY9evSo2rZtqyZNmui9996Tl5dHHjkDnKp6RJCWDf2TJGnVb6f01Lytys7Nc4zP23BI8zYckiRNvK+B/to0Rl5ezL8BYE4eMVH46NGjatOmjapWraqXX35Zp0+fdoxF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", "text/plain": [ - "
" + "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], "source": [ - "%matplotlib inline\n", - "from qupulse.pulses.plotting import plot\n", + "from qupulse.plotting import plot\n", "from qupulse.pulses import TablePT\n", + "\n", "template = TablePT(entries={'A': [(0, 0),\n", " ('ta', 'va', 'hold'),\n", " ('tb', 'vb', 'linear'),\n", @@ -73,8 +71,8 @@ "output_type": "stream", "text": [ "LOOP 1 times:\n", - " ->EXEC 1 times\n", - "Defined on {'B', 'A'}\n", + " ->EXEC MultiChannelWaveform((TableWaveform(channel='A', waveform_table=(TableWaveformEntry(t=0.0, v=0, interp=), TableWaveformEntry(t=2, v=2, interp=), TableWaveformEntry(t=4, v=3, interp=), TableWaveformEntry(t=6, v=0, interp=))), TableWaveform(channel='B', waveform_table=(TableWaveformEntry(t=0.0, v=0, interp=), TableWaveformEntry(t=2, v=-2, interp=), TableWaveformEntry(t=4, v=-3, interp=), TableWaveformEntry(t=6, v=0, interp=))))) 1 times\n", + "Defined on frozenset({'B', 'A'})\n", "{'m': (array([0.]), array([2.])), 'n': (array([4.]), array([2.]))}\n" ] } @@ -109,7 +107,7 @@ "output_type": "stream", "text": [ "LOOP 1 times:\n", - " ->EXEC 1 times\n", + " ->EXEC TableWaveform(channel='Y', waveform_table=(TableWaveformEntry(t=0.0, v=0, interp=), TableWaveformEntry(t=2, v=-2, interp=), TableWaveformEntry(t=4, v=-3, interp=), TableWaveformEntry(t=6, v=0, interp=))) 1 times\n", "Defined on {'Y'}\n", "{'foo': (array([0.]), array([2.]))}\n" ] @@ -136,9 +134,7 @@ { "cell_type": "code", "execution_count": 4, - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -146,21 +142,27 @@ "text": [ "LOOP 1 times:\n", " ->LOOP 4 times:\n", - " ->EXEC 1 times\n", - " ->EXEC 1 times\n", + " ->EXEC MultiChannelWaveform((TableWaveform(channel='A', waveform_table=(TableWaveformEntry(t=0.0, v=0, interp=), TableWaveformEntry(t=2, v=2, interp=), TableWaveformEntry(t=4, v=3, interp=), TableWaveformEntry(t=6, v=0, interp=))), TableWaveform(channel='B', waveform_table=(TableWaveformEntry(t=0.0, v=0, interp=), TableWaveformEntry(t=2, v=-2, interp=), TableWaveformEntry(t=4, v=-3, interp=), TableWaveformEntry(t=6, v=0, interp=))))) 1 times\n", + " ->EXEC MultiChannelWaveform((FunctionWaveform(duration=TimeType(6283, 1000), expression=ExpressionScalar('sin(t)'), channel='A'), FunctionWaveform(duration=TimeType(6283, 1000), expression=ExpressionScalar('2*sin(t)'), channel='B'))) 1 times\n", "{'m': (array([ 0., 6., 12., 18.]), array([2., 2., 2., 2.])), 'n': (array([ 4., 10., 16., 22.]), array([2., 2., 2., 2.]))}\n" ] }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\Simon\\Documents\\git\\qupulse\\qupulse\\plotting.py:186: UserWarning: Sample count 30293/10 is not an integer. Will be rounded (this changes the sample rate).\n", + " times, voltages, measurements = render(program,\n" + ] + }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ - "
" + "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], @@ -198,22 +200,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/03DynamicNuclearPolarisation.ipynb b/doc/source/examples/03DynamicNuclearPolarisation.ipynb index 5f02c1219..f2abaed8f 100644 --- a/doc/source/examples/03DynamicNuclearPolarisation.ipynb +++ b/doc/source/examples/03DynamicNuclearPolarisation.ipynb @@ -44,7 +44,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -89,20 +89,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "LOOP 1 times:\n", - " ->EXEC 3 times\n", - " ->EXEC 3 times\n", - " ->EXEC 3 times\n" - ] - } - ], + "outputs": [], "source": [ "hardware_setup.register_program('dnp', dnp_prog)\n", "hardware_setup.arm_program('dnp')\n", @@ -123,7 +112,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -139,20 +128,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "LOOP 1 times:\n", - " ->EXEC 3 times\n", - " ->EXEC 1 times\n", - " ->EXEC 5 times\n" - ] - } - ], + "outputs": [], "source": [ "used_awg.run_current_program()\n", "\n", @@ -168,22 +146,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.4" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/03FreeInductionDecayExample.ipynb b/doc/source/examples/03FreeInductionDecayExample.ipynb index eb5ab7458..365eff2aa 100644 --- a/doc/source/examples/03FreeInductionDecayExample.ipynb +++ b/doc/source/examples/03FreeInductionDecayExample.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -86,17 +86,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'max_ramp_speed', 't_meas_start', 'ST_jump', 't_ST_read', 'eps_J', 't_init', 'ST_plus', 'N_repetitions', 't_step', 't_start', 'op', 't_meas_duration', 'S_init', 't_meas_wait', 'N_fid_steps', 't_op', 'meas', 't_ST_prep'}\n" - ] - } - ], + "outputs": [], "source": [ "print(experiment.parameter_names)" ] @@ -112,802 +104,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "example_values['N_fid_steps'] = 1\n", "example_values['N_repetitions'] = 1\n", @@ -1763,17 +169,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Successfully saved pulse and example parameters\n" - ] - } - ], + "outputs": [], "source": [ "import json\n", "from qupulse.serialization import FilesystemBackend, PulseStorage\n", @@ -1794,22 +192,8 @@ } ], "metadata": { - "kernelspec": { - "display_name": "Python [default]", - "language": "python", - "name": "python3" - }, "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.0" + "name": "python" } }, "nbformat": 4, diff --git a/doc/source/examples/03GateConfigurationExample.ipynb b/doc/source/examples/03GateConfigurationExample.ipynb index 95e2fe12a..f20bf30d7 100644 --- a/doc/source/examples/03GateConfigurationExample.ipynb +++ b/doc/source/examples/03GateConfigurationExample.ipynb @@ -16,13 +16,13 @@ "An example for a real use case of qupulse is the search for and evaluation of parameters for pulses that represent quantum gate operations on a toy example. To see an example closer to reality but less verbose in explanations, please see [Free Induction Decay - A Real Use Case](03FreeInductionDecayExample.ipynb).\n", "\n", "## Description of the Experiment\n", - "The experiment will typically involve a set of gate pulses $G_j, 0 \\leq j \\lt N_{Gates}$.\n", + "The experiment will typically involve a set of gate pulses $G_j, 0 \\leq j < N_{Gates}$.\n", "\n", - "The template for a gate pulse $G_j$ is a sequence of $\\epsilon_i, 0 \\leq i \\lt N_{G_j}$ voltage levels held for time $\\Delta t = 1$ ns as illustrated in the figure below (with $N_{G_j} = 7$).\n", + "The template for a gate pulse $G_j$ is a sequence of $\\epsilon_i, 0 \\leq i < N_{G_j}$ voltage levels held for time $\\Delta t = 1$ ns as illustrated in the figure below (with $N_{G_j} = 7$).\n", "\n", "![Template of a gate pulse](img/gate_pulse_scheme.png)\n", "\n", - "The experiment defines a number of sequences $S_k, 0 \\leq k \\lt N_{Sequences}$ of the $G_j$ as $$S_k = (G_{m_k(1)}, G_{m_k(2)}, \\dots, G_{m_k(N_{S_k})})$$ where $N_{S_k}$ is the length of sequence $k$ and $m_k(i): \\{0, \\dots, N_{S_k} - 1\\} \\rightarrow \\{0, \\dots, N_{Gates} - 1\\}$ is a function that maps an index $i$ to the $m_k(i)$-th gate of sequence $S_k$ and thus fully describes the sequence. (These sequences express the sequential application of the gates to the qubit. In terms of quantum mathematics they may rather be expressed as multiplication of the matrices describing the unitary transformations applied by the gates: $S_k = \\prod_{i=N_{S_k} - 1}^{0} G_{m_k(i)} = G_{(N_{S_k} - 1)} \\cdot \\dots \\cdot G_{1} \\cdot G_{0}$.)\n", + "The experiment defines a number of sequences $S_k, 0 \\leq k < N_{Sequences}$ of the $G_j$ as $$S_k = (G_{m_k(1)}, G_{m_k(2)}, \\dots, G_{m_k(N_{S_k})})$$ where $N_{S_k}$ is the length of sequence $k$ and $m_k(i): \\{0, \\dots, N_{S_k} - 1\\} \\rightarrow \\{0, \\dots, N_{Gates} - 1\\}$ is a function that maps an index $i$ to the $m_k(i)$-th gate of sequence $S_k$ and thus fully describes the sequence. (These sequences express the sequential application of the gates to the qubit. In terms of quantum mathematics they may rather be expressed as multiplication of the matrices describing the unitary transformations applied by the gates: $S_k = \\prod_{i=N_{S_k} - 1}^{0} G_{m_k(i)} = G_{(N_{S_k} - 1)} \\cdot \\dots \\cdot G_{1} \\cdot G_{0}$.)\n", "\n", "Measuring and analysing the effects of these sequences on the qubit's state to derive parameters $\\epsilon_i$ for gate pulses that achieve certain state transformations is the goal of the experiment.\n", "\n", @@ -126,797 +126,13 @@ { "cell_type": "code", "execution_count": 4, - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], + "image/png": "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", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -1704,803 +150,9 @@ }, { "data": { - "text/html": [ - "" - ], + "image/png": "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", "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " event.shiftKey = false;\n", - " // Send a \"J\" for go to next cell\n", - " event.which = 74;\n", - " event.keyCode = 74;\n", - " manager.command_mode();\n", - " manager.handle_keydown(event);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], + "image/png": "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1dChQ7Vq1SqrS/J6f/7zn2Wz2Zp89ezZ0/n+oUOHNGXKFLVv316RkZG6/PLLtW/fPgsr9i5LlizRJZdcotTUVNlsNn344YdN3jcMQw888IBSUlIUFhamUaNGafv27U22KS4u1tVXX63o6GjFxsbqhhtuUEVFhYnfhXc41VxOmjTpmJ/VsWPHNtmGuWwwe/ZsnXHGGYqKilJiYqIuu+wybd26tck2rvzZzs7O1rhx4xQeHq7ExET94Q9/UF1dnZnfildwZT7PO++8Y34+J0+e3GQb5rP12kyomTt3rqZPn64HH3xQa9asUf/+/TVmzBgVFBRYXZrX6927t/Ly8pxfS5cudb43bdo0/fe//9W7776rxYsXa+/evfr1r39tYbXe5eDBg+rfv7+ef/75474/Z84cPfPMM3rxxRe1cuVKRUREaMyYMTp06JBzm6uvvlo//vij5s+fr08++URLlizRzTffbNa34DVONZeSNHbs2CY/q2+//XaT95nLBosXL9aUKVO0YsUKzZ8/X7W1tRo9erQOHjzo3OZUf7br6+s1btw41dTU6Ntvv9Ubb7yh119/XQ888IAV35KlXJlPSbrpppua/HzOmTPH+R7z6SZGGzFkyBBjypQpzuf19fVGamqqMXv2bAur8n4PPvig0b9//+O+V1JSYgQHBxvvvvuu87XNmzcbkozly5ebVKHvkGR88MEHzucOh8NITk42HnvsMedrJSUlht1uN95++23DMAxj06ZNhiRj9erVzm0+//xzw2azGbm5uabV7m2OnkvDMIyJEycav/zlL0/4GebyxAoKCgxJxuLFiw3DcO3P9meffWYEBAQY+fn5zm1eeOEFIzo62qiurjb3G/AyR8+nYRjGueeea/z+978/4WeYT/doE0dqampq9P3332vUqFHO1wICAjRq1CgtX77cwsp8w/bt25WamqouXbro6quvVnZ2tiTp+++/V21tbZN57dmzpzp16sS8uiArK0v5+flN5i8mJkZDhw51zt/y5csVGxurwYMHO7cZNWqUAgICtHLlStNr9naLFi1SYmKievTooVtvvVVFRUXO95jLEystLZX0801/XfmzvXz5cvXt21dJSUnObcaMGaOysjL9+OOPJlbvfY6ez0ZvvfWW4uPj1adPH82cOVOVlZXO95hP92gTN7QsLCxUfX19kx8WSUpKStKWLVssqso3DB06VK+//rp69OihvLw8PfTQQzr77LO1ceNG5efnKyQkRLGxsU0+k5SUpPz8fGsK9iGNc3S8n8vG9/Lz85WYmNjk/aCgIMXFxTHHRxk7dqx+/etfKyMjQzt37tR9992niy66SMuXL1dgYCBzeQIOh0NTp07VWWedpT59+kiSS3+28/Pzj/uz2/heW3W8+ZSk3/72t+rcubNSU1O1fv16zZgxQ1u3btX7778vifl0lzYRatByF110kfNxv379NHToUHXu3Fnz5s1TWFiYhZUBTf3mN79xPu7bt6/69eunrl27atGiRbrgggssrMy7TZkyRRs3bmyyVg4td6L5PHLtVt++fZWSkqILLrhAO3fuVNeuXc0u02+1idNP8fHxCgwMPGbl/r59+5ScnGxRVb4pNjZW3bt3144dO5ScnKyamhqVlJQ02YZ5dU3jHJ3s5zI5OfmYxex1dXUqLi5mjk+hS5cuio+P144dOyQxl8dz++2365NPPtHChQvVsWNH5+uu/NlOTk4+7s9u43tt0Ynm83iGDh0qSU1+PpnP1msToSYkJESDBg3SggULnK85HA4tWLBAw4YNs7Ay31NRUaGdO3cqJSVFgwYNUnBwcJN53bp1q7Kzs5lXF2RkZCg5ObnJ/JWVlWnlypXO+Rs2bJhKSkr0/fffO7f5+uuv5XA4nH8p4vh++uknFRUVKSUlRRJzeSTDMHT77bfrgw8+0Ndff62MjIwm77vyZ3vYsGHasGFDk6A4f/58RUdHq1evXuZ8I17iVPN5POvWrZOkJj+fzKcbWL1S2SzvvPOOYbfbjddff93YtGmTcfPNNxuxsbFNVprjWHfddZexaNEiIysry1i2bJkxatQoIz4+3igoKDAMwzAmT55sdOrUyfj666+N7777zhg2bJgxbNgwi6v2HuXl5cbatWuNtWvXGpKMJ5980li7dq2xZ88ewzAM4y9/+YsRGxtrfPTRR8b69euNX/7yl0ZGRoZRVVXl3MfYsWONAQMGGCtXrjSWLl1qZGZmGhMmTLDqW7LMyeayvLzcuPvuu43ly5cbWVlZxldffWUMHDjQyMzMNA4dOuTcB3PZ4NZbbzViYmKMRYsWGXl5ec6vyspK5zan+rNdV1dn9OnTxxg9erSxbt0644svvjASEhKMmTNnWvEtWepU87ljxw7j4YcfNr777jsjKyvL+Oijj4wuXboY55xzjnMfzKd7tJlQYxiG8eyzzxqdOnUyQkJCjCFDhhgrVqywuiSvN378eCMlJcUICQkxOnToYIwfP97YsWOH8/2qqirjtttuM9q1a2eEh4cbv/rVr4y8vDwLK/YuCxcuNCQd8zVx4kTDMBou6/7Tn/5kJCUlGXa73bjggguMrVu3NtlHUVGRMWHCBCMyMtKIjo42rrvuOqO8vNyC78ZaJ5vLyspKY/To0UZCQoIRHBxsdO7c2bjpppuO+UcLc9ngePMoyfjHP/7h3MaVP9u7d+82LrroIiMsLMyIj4837rrrLqO2ttbk78Z6p5rP7Oxs45xzzjHi4uIMu91udOvWzfjDH/5glJaWNtkP89l6NsMwDPOOCwEAAHhGm1hTAwAA/B+hBgAA+AVCDQAA8AuEGgAA4BcINQAAwC8QagAAgF8g1AAAAL9AqAEAAH6BUAPANJMmTdJll11m2fjXXnutZs2a5ZZ91dTUKD09Xd99951b9geg9egoDMAtbDbbSd9/8MEHNW3aNBmGodjYWHOKOsIPP/yg888/X3v27FFkZKRb9vncc8/pgw8+aHLjRwDWIdQAcIv8/Hzn47lz5+qBBx7Q1q1bna9FRka6LUy0xI033qigoCC9+OKLbtvngQMHlJycrDVr1qh3795u2y+AluH0EwC3SE5Odn7FxMTIZrM1eS0yMvKY00/nnXee7rjjDk2dOlXt2rVTUlKS/v73v+vgwYO67rrrFBUVpW7duunzzz9vMtbGjRt10UUXKTIyUklJSbr22mtVWFh4wtrq6+v1n//8R5dcckmT19PT0zVr1ixdf/31ioqKUqdOnfTyyy8736+pqdHtt9+ulJQUhYaGqnPnzpo9e7bz/Xbt2umss87SO++808rZA+AOhBoAlnrjjTcUHx+vVatW6Y477tCtt96qK6+8UsOHD9eaNWs0evRoXXvttaqsrJQklZSU6Pzzz9eAAQP03Xff6YsvvtC+fft01VVXnXCM9evXq7S0VIMHDz7mvSeeeEKDBw/W2rVrddttt+nWW291HmF65pln9PHHH2vevHnaunWr3nrrLaWnpzf5/JAhQ/TNN9+4b0IAtBihBoCl+vfvr/vvv1+ZmZmaOXOmQkNDFR8fr5tuukmZmZl64IEHVFRUpPXr10tqWMcyYMAAzZo1Sz179tSAAQP02muvaeHChdq2bdtxx9izZ48CAwOVmJh4zHsXX3yxbrvtNnXr1k0zZsxQfHy8Fi5cKEnKzs5WZmamRowYoc6dO2vEiBGaMGFCk8+npqZqz549bp4VAC1BqAFgqX79+jkfBwYGqn379urbt6/ztaSkJElSQUGBpIYFvwsXLnSu0YmMjFTPnj0lSTt37jzuGFVVVbLb7cddzHzk+I2nzBrHmjRpktatW6cePXrozjvv1P/+979jPh8WFuY8igTAWkFWFwCgbQsODm7y3GazNXmtMYg4HA5JUkVFhS655BI9+uijx+wrJSXluGPEx8ersrJSNTU1CgkJOeX4jWMNHDhQWVlZ+vzzz/XVV1/pqquu0qhRo/Sf//zHuX1xcbESEhJc/XYBeBChBoBPGThwoN577z2lp6crKMi1v8JOP/10SdKmTZucj10VHR2t8ePHa/z48briiis0duxYFRcXKy4uTlLDouUBAwY0a58APIPTTwB8ypQpU1RcXKwJEyZo9erV2rlzp7788ktdd911qq+vP+5nEhISNHDgQC1durRZYz355JN6++23tWXLFm3btk3vvvuukpOTm/TZ+eabbzR69OjWfEsA3IRQA8CnpKamatmyZaqvr9fo0aPVt29fTZ06VbGxsQoIOPFfaTfeeKPeeuutZo0VFRWlOXPmaPDgwTrjjDO0e/duffbZZ85xli9frtLSUl1xxRWt+p4AuAfN9wC0CVVVVerRo4fmzp2rYcOGuWWf48ePV//+/XXfffe5ZX8AWocjNQDahLCwML355psnbdLXHDU1Nerbt6+mTZvmlv0BaD2O1AAAAL/AkRoAAOAXCDUAAMAvEGoAAIBfINQAAAC/QKgBAAB+gVADAAD8AqEGAAD4BUINAADwC4QaAADgF/4/COPD/2jZQ5UAAAAASUVORK5CYII=", "text/plain": [ - "" + "
" ] }, "metadata": {}, @@ -3424,791 +293,9 @@ "outputs": [ { "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " fig.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('