pax_global_header00006660000000000000000000000064130263472310014513gustar00rootroot0000000000000052 comment=5b11f7e5277c122a266895314be98e564712a60e fityk-1.3.1/000077500000000000000000000000001302634723100126435ustar00rootroot00000000000000fityk-1.3.1/.gitignore000066400000000000000000000007711302634723100146400ustar00rootroot00000000000000*~ *.bak *.pyc *.o cscope.out tags Makefile.in Makefile configure config.h.in aclocal.m4 autom4te.cache build-aux m4/libtool.m4 m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/lt~obsolete.m4 doc/html/ doc/latex/ doc/web/ doc/doctrees/ samples/tmp_* fityk/swig/Fityk.pm fityk/swig/fityk.py fityk/swig/fityk_*.cpp fityk/swig/luarun.h fityk/swig/java/ doc/screenshots/*.png ! doc/screenshots/fityk076.png fityk/cmpfit/test* fityk/cmpfit/*.patch *-build/ *-build-*/ fityk-?.?.?-setup.exe fityk-?.?.?.tar.bz2 fityk-1.3.1/.travis.yml000066400000000000000000000016211302634723100147540ustar00rootroot00000000000000language: cpp compiler: - gcc # - clang before_install: - curl http://download.opensuse.org/repositories/home:/wojdyr/xUbuntu_12.04/Release.key | sudo apt-key add - - echo 'deb http://download.opensuse.org/repositories/home:/wojdyr/xUbuntu_12.04/ /' | sudo tee -a /etc/apt/sources.list.d/obs.list - sudo add-apt-repository ppa:teward/swig3.0 -y - sudo apt-get update -qq - sudo apt-get install -y libboost-dev liblua5.1-0-dev lua5.1 - sudo apt-get install -y --force-yes swig3.0 - sudo apt-get install -y --force-yes libxy-dev wxgtk-for-fityk-devel before_script: - curl -o tests/catch.hpp https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp - autoreconf -i script: ./configure LUA=/usr/bin/lua5.1 LUA_INCLUDE=-I/usr/include/lua5.1 LUA_LIB=-llua5.1 SWIG=swig3.0 && make -j2 check branches: only: - master notifications: email: - wojdyr@gmail.com fityk-1.3.1/CMakeLists.txt000066400000000000000000000217241302634723100154110ustar00rootroot00000000000000# Use autotools-based build system instead if you can. # For now CMake limited to building libfityk and cfityk. # But it can automatically download and build Lua, xylib and zlib! # You still need to have Boost libraries (headers only). # If they can't be found automatically, use -D BOOST_ROOT=C:\Path\to\boost cmake_minimum_required(VERSION 2.8) project(fityk C CXX) option(DOWNLOAD_LUA "Fetch Lua from its website" ON) option(DOWNLOAD_XYLIB "Fetch xylib from git" ON) option(DOWNLOAD_ZLIB "Fetch zlib from its website" ON) option(BUILD_SHARED_LIBS "Build as a shared library" ON) # on Windows default CMAKE_INSTALL_PREFIX is Program Files/Fityk # so it overwrites files from Fityk installer if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND WIN32) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/inst" CACHE PATH "install prefix" FORCE) endif() # TODO: ${THIRDPARTY_INSTALL} is used during 'make' so should be user-writable, # OTOH libraries are needed at runtime set(THIRDPARTY_INSTALL "${CMAKE_INSTALL_PREFIX}") if(NOT DEFINED LIB_INSTALL_DIR) set(LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib) endif() include(ExternalProject) if (POLICY CMP0042) cmake_policy(SET CMP0042 OLD) endif() if (MSVC) # C4244: '=' : conversion from 'double' to 'float', possible loss of data add_definitions( /wd4244 ) # same as _CRT_SECURE_NO_WARNINGS add_definitions( /wd4996 ) # warning C4275: non dll-interface class 'std::runtime_error' used as base # for dll-interface class ... add_definitions( /wd4275 ) # warning C4251: class (e.g. std::vector<...>) needs to have dll-interface # to be used by clients of class ... add_definitions( /wd4251 ) endif() # if we build static library we likely prefer 3rd-party libraries also static if(NOT BUILD_SHARED_LIBS) set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} ${CMAKE_FIND_LIBRARY_SUFFIXES}) endif() include_directories(${CMAKE_SOURCE_DIR}) include_directories(${CMAKE_SOURCE_DIR}/fityk) # only for fityk_lua.cpp include_directories(${CMAKE_BINARY_DIR}) if (BUILD_SHARED_LIBS AND WIN32) add_definitions(-DLUA_BUILD_AS_DLL) add_definitions(-DLIBFITYK_DLL) # add_definitions(-DXYLIB_DLL=1) endif() find_package(Boost REQUIRED) message(STATUS "Boost headers in: ${Boost_INCLUDE_DIR}") include_directories(${Boost_INCLUDE_DIR}) set(thirdparty_dir ${CMAKE_SOURCE_DIR}/3rdparty) if (DOWNLOAD_LUA) ExternalProject_Add(lua52-fetch URL "http://www.lua.org/ftp/lua-5.2.4.tar.gz" URL_MD5 913fdb32207046b273fdb17aad70be13 DOWNLOAD_DIR ${thirdparty_dir} SOURCE_DIR ${thirdparty_dir}/lua52 PREFIX lua52 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "") set(lua_filenames lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c) foreach(lua_f ${lua_filenames}) set(lua_src ${lua_src} ${thirdparty_dir}/lua52/src/${lua_f}) endforeach() set_source_files_properties(${lua_src} PROPERTIES GENERATED TRUE) #add_definitions(-DLUA_ANSI=1) add_library(lua ${lua_src}) set(LUA_LIBRARIES lua) set(LUA_INCLUDE_DIR "${thirdparty_dir}/lua52/src") set(BUILT_LUA lua) add_dependencies(lua lua52-fetch) else() find_package(Lua REQUIRED) endif() include_directories(${LUA_INCLUDE_DIR}) find_package(SWIG REQUIRED) #include(${SWIG_USE_FILE}) if (BUILD_SHARED_LIBS) set(LIB_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) if (WIN32) set(LIB_SUFFIX ${CMAKE_IMPORT_LIBRARY_SUFFIX}) else() set(LIB_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) endif() else() set(LIB_PREFIX ${CMAKE_STATIC_LIBRARY_PREFIX}) set(LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX}) endif() if (DOWNLOAD_ZLIB) ExternalProject_Add(zlib URL "http://zlib.net/zlib-1.2.8.tar.gz" URL_MD5 44d667c142d7cda120332623eab69f40 DOWNLOAD_DIR ${thirdparty_dir} SOURCE_DIR ${thirdparty_dir}/zlib BINARY_DIR ${CMAKE_BINARY_DIR}/zlib PREFIX zlib CMAKE_ARGS -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} -DCMAKE_INSTALL_PREFIX:PATH=${THIRDPARTY_INSTALL} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DSKIP_INSTALL_FILES=ON) set(ZLIB_INCLUDE_DIR "${THIRDPARTY_INSTALL}/include") if (NOT WIN32) set(ZLIB_NAME libz) elseif (BUILD_SHARED_LIBS) set(ZLIB_NAME zlib$<$:d>) else() # static windows set(ZLIB_NAME zlibstatic$<$:d>) endif() set(ZLIB_LIBRARIES "${THIRDPARTY_INSTALL}/lib/${ZLIB_NAME}${LIB_SUFFIX}") message(STATUS "Using local zlib: ${ZLIB_LIBRARIES}") else() find_package(ZLIB REQUIRED) endif() include_directories("${ZLIB_INCLUDE_DIR}") if (DOWNLOAD_XYLIB) ExternalProject_Add(xylib GIT_REPOSITORY https://github.com/wojdyr/xylib DOWNLOAD_DIR ${thirdparty_dir} SOURCE_DIR ${thirdparty_dir}/xylib BINARY_DIR ${CMAKE_BINARY_DIR}/xylib PREFIX xylib CMAKE_ARGS "-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS}" "-DCMAKE_INSTALL_PREFIX:PATH=${THIRDPARTY_INSTALL}" "-DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR}" "-DZLIB_LIBRARIES=${ZLIB_LIBRARIES}" -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DGUI=OFF "-DBoost_INCLUDE_DIR=${Boost_INCLUDE_DIR}") set(XY_LIBRARY "${THIRDPARTY_INSTALL}/lib/${LIB_PREFIX}xy${LIB_SUFFIX}") set(XY_INCLUDE_DIR "${THIRDPARTY_INSTALL}/include") else() set(XY_LIBRARY xy) endif() include_directories("${XY_INCLUDE_DIR}") # show warnings by default include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-Wextra HAS_WEXTRA_FLAG) if (HAS_WEXTRA_FLAG) set(EXTRA_CXX_FLAGS "-Wall -Wextra" CACHE STRING "") endif() set(EXTRA_CXX_FLAGS ${EXTRA_CXX_FLAGS} CACHE STRING "Flags for compiler" FORCE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXX_FLAGS}") set(lua_runtime swig/luarun.h) set(lua_cxx swig/fityk_lua.cpp) add_custom_command(OUTPUT ${lua_runtime} COMMAND ${CMAKE_COMMAND} -E make_directory swig COMMAND ${SWIG_EXECUTABLE} ARGS -lua -external-runtime ${lua_runtime}) add_custom_command(OUTPUT ${lua_cxx} COMMAND ${CMAKE_COMMAND} -E make_directory swig COMMAND ${SWIG_EXECUTABLE} ARGS -c++ -lua -I${CMAKE_SOURCE_DIR}/fityk -o ${lua_cxx} ${CMAKE_SOURCE_DIR}/fityk/swig/fityk.i DEPENDS fityk/fityk.h) set_source_files_properties(fityk/swig/fityk.i PROPERTIES CPLUSPLUS ON) #set_source_files_properties(fityk/swig/fityk.i PROPERTIES SWIG_FLAGS "-includeall") add_library(fityk fityk/ast.cpp fityk/fityk.cpp fityk/mgr.cpp fityk/udf.cpp fityk/bfunc.cpp fityk/func.cpp fityk/model.cpp fityk/ui_api.cpp fityk/CMPfit.cpp fityk/GAfit.cpp fityk/NLfit.cpp fityk/ui.cpp fityk/common.cpp fityk/guess.cpp fityk/NMfit.cpp fityk/var.cpp fityk/cparser.cpp fityk/info.cpp fityk/numfuncs.cpp fityk/view.cpp fityk/data.cpp fityk/lexer.cpp fityk/runner.cpp fityk/vm.cpp fityk/eparser.cpp fityk/LMfit.cpp fityk/settings.cpp fityk/voigt.cpp fityk/f_fcjasym.cpp fityk/logic.cpp fityk/tplate.cpp fityk/fit.cpp fityk/luabridge.cpp fityk/transform.cpp fityk/cmpfit/mpfit.c ${lua_runtime} ${lua_cxx}) if (DOWNLOAD_XYLIB) add_dependencies(fityk xylib) endif() if (DOWNLOAD_ZLIB) add_dependencies(fityk zlib) endif() if (DOWNLOAD_ZLIB AND DOWNLOAD_XYLIB) add_dependencies(xylib zlib) endif() target_link_libraries(fityk ${XY_LIBRARY} ${LUA_LIBRARIES} ${ZLIB_LIBRARIES}) set_target_properties(fityk PROPERTIES SOVERSION 4 VERSION 4.0.0) # ignoring libreadline for now add_executable(cfityk cli/gnuplot.cpp cli/main.cpp) target_link_libraries(cfityk fityk) #add_definitions(-DVERSION="1.3.0") set_target_properties (fityk cfityk PROPERTIES COMPILE_DEFINITIONS VERSION="1.3.0") #swig_add_module(fityk python fityk/swig/fityk.i fityk/ui_api.h) #swig_link_libraries(fityk fityk ${PYTHON_LIBRARIES}) install(TARGETS cfityk DESTINATION bin) install(TARGETS fityk ${BUILT_LUA} RUNTIME DESTINATION bin ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" LIBRARY DESTINATION "${LIB_INSTALL_DIR}") enable_testing() if (NOT EXISTS "${CMAKE_SOURCE_DIR}/tests/catch.hpp") message(STATUS "Downloading catch.hpp...") file(DOWNLOAD https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp "${CMAKE_SOURCE_DIR}/tests/catch.hpp" SHOW_PROGRESS STATUS download_status) list(GET download_status 0 status_code) if (NOT ${status_code} EQUAL 0) message(FATAL_ERROR "Downloading catch.hpp FAILED: ${download_status}") endif() endif() add_library(catch STATIC tests/catch.cpp) foreach(t gradient guess psvoigt num lua) add_executable(test_${t} tests/${t}.cpp) target_link_libraries(test_${t} fityk catch) add_test(NAME ${t} COMMAND $) endforeach() fityk-1.3.1/COPYING000066400000000000000000000432541302634723100137060ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) 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 this service 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 make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. 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. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the 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 a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 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. 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 convey 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 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision 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, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This 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. fityk-1.3.1/INSTALL000066400000000000000000000453211302634723100137010ustar00rootroot00000000000000 Prerequisites ============= * C++ compiler (e.g. GCC) * Boost libraries >= 1.35 (headers only) * Lua >= 5.1 * zlib library * xylib library - http://xylib.sf.net * wxWidgets (wxGTK or wxMSW) >= 3.0 (for the GUI) * readline library >= 4.2 or compatible (optional, for the CLI) * gnuplot program (optional, can be used with the CLI) Installation ============ $ ./configure (optionally followed by options, see: Configuration Options) $ make # make install Uninstallation ============== either do "make uninstall" or manually find and remove all files, e.g.: find /usr/local/ -name \*fityk\* -exec rm -r \{} \; wxWidgets ========= If you compile wxWidgets only to build fityk, you may use the following configure flags to disable unused features and make the compilation faster. --disable-compat28 \ --without-regex --without-expat --without-opengl \ --without-libjpeg --without-libtiff \ --disable-threads --disable-html --disable-htmlhelp --enable-stc \ --disable-xlocale --disable-protocols --disable-protocol --disable-fs_inet \ --disable-sockets --disable-ipc --disable-apple_ieee --disable-backtrace \ --disable-dialupman --disable-tarstream --disable-sound \ --disable-mediactrl --disable-url --disable-aui --disable-xrc \ --disable-docview --disable-logdialog --disable-animatectrl \ --disable-calendar --disable-datepick --disable-tipwindow --disable-splash \ --disable-tipdlg --disable-wizarddlg --disable-miniframe --disable-joystick \ --disable-gif --disable-pcx --disable-tga --disable-iff --disable-pnm \ --disable-mdi --disable-richtext --disable-rearrangectrl --disable-fswatcher \ --disable-ribbon --disable-propgrid --disable-arcstream \ --disable-dataviewctrl --disable-detect_sm --disable-treelist \ --disable-baseevtloop and optionally: --disable-shared --enable-optimise --disable-debug_flag --disable-debugreport To install the latest version from Git ====================================== Install automake, autoconf, libtool and SWIG. Before the ./configure step, run: $ autoreconf -iv Optionally, build the fityk manual (html version): cd doc && make html This requires Sphinx >= 1.0 (http://sphinx.pocoo.org/), LaTeX and dvipng. If built, the manual is installed ("make install") along with the program. To compile tests (make check) download https://raw.githubusercontent.com/philsquared/Catch/master/single_include/catch.hpp and put it into tests/ Configuration Options ===================== ./configure --help shows all the options. Variables LUA, LUA_INCLUDE and LUA_LIB are useful when Lua is in non-default location or if it is suffixed (say, liblua5.2.so instead of liblua.so). To build python bindings, use --enable-python option. To build perl bindings, install perl-ExtUtils-Embed and do "make perl" in fityk/ subdirectory. swig/Fityk.pm and swig/perl/Fityk.so can be installed manually. Try test: samples/hello.pl. For debugging you may use: ./configure CXXFLAGS="-g -O0 -fno-inline -W -Wall" \ --enable-static --disable-shared Tests ===== make check - runs unit tests in C++ make check-python - runs tests that require Python bindings make check-cfityk - runs cfityk script that tests command parser ########################################################################### # The instructions below are from GNU automake. # ########################################################################### Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. fityk-1.3.1/Makefile.am000066400000000000000000000073321302634723100147040ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = README.md fityk.iss fityk.url \ doc/fityk-manual.rst doc/intro.rst doc/getstarted.rst \ doc/data.rst doc/model.rst doc/fit.rst \ doc/script.rst doc/ref.rst \ doc/Makefile doc/conf.py doc/fityk_ext.py \ doc/img doc/fitheme doc/html SUBDIRS = fityk if GUI_DIR SUBDIRS += wxgui endif if CLI_DIR bin_PROGRAMS = cli/cfityk endif # for Linux desktop icon32dir = $(datadir)/icons/hicolor/32x32/apps iconscdir = $(datadir)/icons/hicolor/scalable/apps desktopdir = $(datadir)/applications mimepkgdir = $(datadir)/mime/packages dist_icon32_DATA = fityk.png dist_iconsc_DATA = fityk.svg dist_desktop_DATA = fityk.desktop dist_mimepkg_DATA = fityk.xml # --- cli/ --- cli_cfityk_SOURCES = cli/gnuplot.cpp cli/main.cpp cli/gnuplot.h cli_cfityk_LDADD = fityk/libfityk.la $(READLINE_LIBS) # --- tests/ --- TESTS = tests/gradient tests/guess tests/psvoigt tests/num tests/lua check_LIBRARIES = tests/libcatch.a tests_libcatch_a_SOURCES = tests/catch.cpp tests/catch.hpp tests_gradient_SOURCES = tests/gradient.cpp tests_gradient_LDADD = fityk/libfityk.la tests/libcatch.a tests_gradient_LDFLAGS = -no-install tests_guess_SOURCES = tests/guess.cpp tests_guess_LDADD = fityk/libfityk.la tests/libcatch.a tests_guess_LDFLAGS = -no-install tests_psvoigt_SOURCES = tests/psvoigt.cpp tests_psvoigt_LDADD = fityk/libfityk.la tests/libcatch.a tests_psvoigt_LDFLAGS = -no-install tests_num_SOURCES = tests/num.cpp tests_num_LDADD = fityk/libfityk.la tests/libcatch.a tests_num_LDFLAGS = -no-install tests_lua_SOURCES = tests/lua.cpp tests_lua_LDADD = fityk/libfityk.la tests/libcatch.a tests_lua_LDFLAGS = -no-install check_PROGRAMS = $(TESTS) if ! OS_WIN32 check_PROGRAMS += tests/mpfit_deriv tests_mpfit_deriv_SOURCES = tests/mpfit_deriv.cpp tests_mpfit_deriv_LDADD = fityk/libfityk.la tests_mpfit_deriv_LDFLAGS = -no-install endif dist_noinst_SCRIPTS = tests/test_syntax.fit \ tests/test_nist.py tests/test_guess.py tests/test_model.py \ tests/test_tranform.py tests/test_data_load.py tests/test_info.py # --- samples/ --- samplesdir = $(pkgdatadir)/samples dist_samples_DATA = samples/nacl01.fit samples/nacl01.dat \ samples/SiC_Zn.fit samples/SiC_Zn.dat \ samples/enso.fit samples/enso.dat \ samples/read-shockley.fit \ samples/hello.c samples/hello.cc \ samples/hello.py samples/hello.lua samples/hello.pl \ samples/hello.rb samples/hello.java \ samples/cfityk.py \ samples/README check_PROGRAMS += samples/hello samples/helloc samples_hello_SOURCES = samples/hello.cc samples_hello_CPPFLAGS = -I$(srcdir) samples_hello_LDADD = fityk/libfityk.la samples_helloc_SOURCES = samples/hello.c samples_helloc_CPPFLAGS = -I$(srcdir) samples_helloc_LDADD = fityk/libfityk.la # workaround to link helloc with C++ linker nodist_EXTRA_samples_helloc_SOURCES = dummy.cxx check-cfityk: cli/cfityk -q -c "= F:get_info('version')..'\n'..F:get_info('compiler')" cli/cfityk -n -q $(srcdir)/samples/enso.fit cli/cfityk -n -q $(srcdir)/samples/read-shockley.fit cli/cfityk -n -q $(srcdir)/samples/nacl01.fit cli/cfityk -n -q $(srcdir)/samples/SiC_Zn.fit cli/cfityk -n -q $(srcdir)/samples/hello.lua rm -f tmp_save.fit cli/cfityk -n -q $(srcdir)/tests/test_syntax.fit check-python: PYTHONPATH=fityk/swig/.libs:$(srcdir)/fityk/swig/ \ python -m unittest discover -s $(srcdir)/tests/ check-scripts: check-cfityk check-python # --- doc/ --- dist_man_MANS = doc/fityk.1 install-data-hook: @$(NORMAL_INSTALL) $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)/html" cp -fR $(srcdir)/doc/html/* "$(DESTDIR)$(pkgdatadir)/html" && \ chmod -R u+w "$(DESTDIR)$(pkgdatadir)/html" ||: uninstall-local: @$(NORMAL_UNINSTALL) cd "$(DESTDIR)$(pkgdatadir)" && rm -rf html fityk-1.3.1/NEWS000066400000000000000000000603451302634723100133520ustar00rootroot00000000000000User-visible changes in version 1.3.1 (2016-12-21): * GUI: more options in the peak-top menu * GUI: Tools > XPS KE <-> BE * added utilities F.findx(), F.extremum(), centile(N, expr), %peak.IB * bug fixes, as always User-visible changes in version 1.3.0 (2015-05-25): * support filenames with non-ascii characters * simple-variable ~NUM can be followed by domain, e.g.: %f=Linear(~3[2:5], ~8) and also default parameters can have domain (...shape=~0.5 [0:1],...), Voigt and PseudoVoigt have now shape with default domain [0:1] * if variable has a domain (example: $a = ~1.2 [-3:4]) then "$a = ~3" keeps domain of $a (also "a={$a}; $a=~{a}" preserves domain) "$a = ~3 [:]" unsets domain "$a = copy($x) - copy $x with domain * new boolean box_constraints option decides if domains are used as box constraints in fitting methods that support it (default: on) * GUI: added auto-completion to Lua script editor * xyConvert is now part of xylib (removed flag --disable-xyconvert) * command "reset" does not reset Lua VM (to allow "reset" from Lua scripts) * Lua: add Python-style formatting (e.g."%d pigs" % 3) using __mod for strings User-visible changes in version 1.2.9 (2014-04-13): * fitting: - a few optimization methods from the NLopt library have been added - MPFIT and NLopt methods support box constraints - simplifications that made using external libraries easier: - removed stopping criterium based on iterations. The max. number of WSSR evaluations can be used instead. - removed fit continuation (fit +N) * new function Sigmoid and new category of functions (S-shaped/step/sigmoidal) * GUI: added menu Session > Recent Scripts * GUI: added checkbox to Functions > Export Peak Parameters * GUI: added "decimal comma" option to Data > Load dialogs. User-visible changes in version 1.2.1 (2012-11-05): * added commands '=' and 'exec=' - shorthands 'lua return' and 'lua F:execute' * API: default dataset in a few functions changed from @0 to the currently used * GUI: new dialog GUI > Configure > Default Directories * a few tweaks and fixes related to printing, and other bug fixes User-visible changes in version 1.2.0 (2012-05-24): * added fitting method "mpfit" -- wrapper around MINPACK-1 based MPFIT library (http://www.physics.wisc.edu/~craigm/idl/cmpfit.html) * changed public API of libfityk; now cfityk uses only public API * added C API and Ruby and Java bindings to libfityk * enhanced Python API and added Python equivalent of cfityk (samples/cfityk.py) * CLI: cfityk can be built with libedit (but it works better with readline) * in scripts, backslash (\) at the end of line means line continuation * bug fixes, as usually User-visible changes in version 1.1.1 (2011-09-28): * option exit_on_warning=0/1 was replaced with on_error=stop/exit; new option on_error=nothing allows to ignore errors in script. * current working directory can be changed using new option `cwd' * GUI: a new dialog for Model > Export Formula * minor bug fixes User-visible changes in version 1.1.0 (2011-07-18): * embedded Lua (lightweight programming language) * syntax changes and enhancements in dataset transformations (@n = ...); example: "@0 = @0 - 0.23 * @1" removes (background) @1 with y's scaled by factor 0.23 from dataset @0; if @0 and @1 have different x's, linear interpolation is used. * added calculation of Polyline derivatives, what enables weighted least squares approximation by broken lines * gzipped fit files can be read directly (extension .fit.gz or .fityk.gz) * new option max_fitting_time -- stopping criterium based on elapsed time * GUI: mouse wheel and mouse extra buttons can be used to zoom in/out * Mac GUI: added Session > New Window that opens new window (open -n Fityk.app) * GUI: added optional, configurable description in the corner of the main plot * GUI: Session > Copy to Clipboard works differently and on all platforms now * GUI: enhanced file dialogs: Data > Quick Load and Session > Save as Image * fixed all reported bugs User-visible changes in version 1.0.2 (2011-06-08): * changed Data > Load File dialog * fixed a few minor problems and a major one (GUI not working on OSX 10.5) User-visible changes in version 1.0.1 (2011-03-30): * corrected calculation of Exponentially Modified Gaussian * added calculation of confidence intervals * GUI: anti-aliasing (can be switched off in menu GUI > Anti-aliasing) * added (experimental) option guess_uses_weights that changes peak "guessing" * as usually, a few bug fixes and minor changes in the GUI User-visible changes in version 1.0.0 (2011-03-18): * fixed bugs: several bugs in the powder diffraction add-on, problem with negative simple-variables, crash when the status bar has an extra value set * GUI: several changes necessary to make the program working on OSX (>= 10.4) * GUI: new configuration dialogs for plots * GUI: all configs including the default one are now stored in .fityk/configs/ * samples are always installed, removed configure option --with-samples, added menu Help > Examples in the GUI * requires wxWidgets >= 2.9.1 User-visible changes in version 0.9.8 (2011-06-08): * several bug fixes ported from version 1.0.2 (unlike 1.x, this version can be built with wxWidgets 2.8) User-visible changes in version 0.9.7 (2011-02-08): * bug fixes: UDFs (user-defined functions) did not work in ver. 0.9.5-6, a few fixes in the powder diffraction add-on and in other places * data operations: added aggregate functions argmin, argmax and count * GUI: redesigned the Data > Export dialog User-visible changes in version 0.9.6 (2011-01-26): * fixed three bugs, one of them was sometimes crashing the program at startup User-visible changes in version 0.9.5 (2011-01-24): * libfityk: the parser has been completely rewritten and the syntax was slightly changed: - major changes in the `info' command; two new commands, `print' and `debug', partially took over some functionality of the old `info' - "commands" replaced by "set"/"exec" - "dump" replaced by "info state" - values of the fitting_method setting changed to lower case - "set @0.title = ..." replaced with "@0: title = ..." - settings: removed formula_export_style, guess_at_center_pm and can_cancel_guess, changed autoplot and verbosity, added logfile, log_full, fit_replot, info_numeric_format renamed to numeric_format, data_default_sigma to default_sigma, cut_function_level to function_cutoff, variable_domain_percent to domain_percent - in "define ... where param=expr" expr is substituted in brackets now - added syntax: delete file 'filename' - "guess": changed argument order - F.param = $variable -> F[*].param = $variable See the wiki for details (there is a tool that upgrades fityk scripts). * new website address (fityk.nieto.pl) and new code repository (GitHub) * GUI: simplified two dialogs: Edit Script and Definition Manager * error in script stops the script User-visible changes in version 0.9.4 (2010-10-09): * removed syntax `delete[range]', use `delete(condition)' instead * syntax `y[x=15]' replaced with `y[index(15)]' * removed data range syntax, e.g. X[3...10]=15. It can be replaced with X = n >= 3 and n < 10 ? 15 : x * removed syntax "order=" * removed syntax "commands < file[m:n]", only the whole file can be executed * modulo syntax changed from a%b to mod(a,b) * syntax: '-' replaced with '_' in settings and 'info fit_history' * syntax: 'fit history clear' replaced with 'fit clear_history' * added Perl bindings (manual compilation: cd swig/ && make perl) * GUI: remember recently subtracted baselines (GUI > Baseline Mode > Recent) * bug fixes User-visible changes in version 0.9.3 (2010-06-24): * changed implementation of gamma and related functions (using boost.math now) * syntax: so-called parametrized-functions spline[] and interpolate[] are replaced by so-called variadic functions Spline() and Polyline(). The GUI in the Baseline Mode handles a separate baseline for each dataset now. * abandoned syntax like 5 Auto-Freeze option that automatically locks/unlocks parameters of a peak when a data range containing the center of this peak is disactivated/activated * GUI: added option GUI > Zoom All Shows Y=0 * required Boost version (only in the compilation time) is now >= 1.36 User-visible changes in version 0.9.2 (2010-05-07): * To compile fityk, Boost (only headers) and xylib must be installed first. Fityk tarball does not contain a copy of boost and xylib now. * user-defined functions: split functions can be defined in this way: SplitG(h, c, w1, w2) = x < c ? Gaussian(h, c, w1) : Gaussian(h, c, w2) * added info-numeric-format option * a couple of bug fixes User-visible changes in version 0.9.1 (2010-03-25): * added cfityk to Windows installer * Unix only: fitting can be interrupted by the INT signal * changed output of "info errors", see the manual for details * GUI: "plot in @n" changes selected datasets (useful in scripts) * many bugs fixed User-visible changes in version 0.9.0 (2010-01-05): * GUI: Data > Editor dialog was replaced with two dialogs: Data > Table and Data > Edit Transformations * added Lua bindings (configure option --enable-lua) * a syntax to execute output from external program: command ! program [args...] * xyConvert (which requires wx 2.9) is built by default. Added flag --disable-xyconvert, which must be used with wx 2.8. * parsing of info command was rewritten, but functionality is almost the same * bug fixes User-visible changes in version 0.8.9 (2009-08-20): * manual was converted from DocBook to reStructuredText * GUI: On Linux fitting was very slow, this was fixed. A new option `refresh-period` was added to control refreshing during fitting. * define supports variable substitution with "define ... where ...", e.g. define Foo(alpha) = alpha * eta * (eta / tanh(eta) - ln (2*sinh(eta))) \ where eta = 2*pi/alpha * sin(theta/2), theta=x*pi/180 * added access to symmetric errors from scripts (e.g. $variable.error or %func.height.error) * category "Education" was added to fityk.desktop User-visible changes in version 0.8.8 (2009-06-21): * added two flags to the configure script: --with-xylib and --with-samples (xylib from the fityk tarball is not used by default now) User-visible changes in version 0.8.7 (2009-06-10): * fityk license was changed from GPLv2 to GPLv2+ (2 or at your option any later) * all config files are stored in a single directory: Unix: ~/.fityk Windows: C:\Documents and Settings\username\Application Data\fityk Mac: ~/Library/Application Support/fityk This changes the path to the default and alt. configs on Windows and Mac. * now works also with GCC 4.4 and Boost 1.35 * minimum wxWidgets version increased to 2.8.0 * added functions LogNormal and LogNormalA (Mirko Scholz) * abs() can be used in user-defined functions * added syntax for loading data from all columns in file: file.csv:1:2..:: * bug fixes, most notably bugs with saving/loading session User-visible changes in version 0.8.6 (2008-04-15): * bug fixes (drawing baseline, "zoom all" with log scale) * GUI: parameters (at the bottom of the sidebar) can be changed with Page-Up and Page-Down keys or with mouse wheel. Shift, Ctrl, Alt keys modify speed. * GUI: two buttons added to the "functions" pane in the sidebar. They make HWHM and shape equal for all functions (works only with a few function types) User-visible changes in version 0.8.5 (2008-03-17): * minor changes in syntax: info @0 -> info data in @0 info @0.title -> info title in @0 info @0.filename -> info filename in @0 @0.title = abc -> set @0.title = abc @+ -> @+ = 0 @0.revert -> @0 < . data is exported with "info" now: info @n ( expr1, ... ) > filename where: columns have to be given, @* can be used, F() and Z() can be used without "@n." prefix, *F() can not be used. * xylib: RIET7/LHPM/CSRIET/ILL_D1A5/PSI_DMC .dat filetypes added * non-Windows platforms: using HTML manual (in default browser) instead of HTB * GUI: command line history is stored in ~/.fityk/history * --disable-3rdparty configure flag prevents building with xylib from 3rdparty/ * GUI: added Session -> Save as Image * !foo: executes a command foo by calling system() (from stdlib.h) * bug fixes (there are some bug fixes in every release) * xyConvert tool (can be built only with wxWidgets >= 2.9) User-visible changes in version 0.8.4 (2008-02-15): * xylib: pdCIF format was added User-visible changes in version 0.8.3 (2008-01-25): * data import is done using (modified) xylib library. VAMAS and a few other new file formats are supported. * added hyperbolic functions * command "@n.revert" reloads data points from file * GUI: menu item "Apply to all datasets" was removed. Now all data-related menu items and buttons are applied to datasets selected at the sidebar * GUI: new dataset is opened in a new slot now (it was replacing an active dataset before) User-visible changes in version 0.8.2 (2007-08-21): * multiple fixes for MacOSX, added macosx/ directory (Ken McIvor) * reading multiple y columns from data file: "@+ < foo.xy:0,5/6/7" (or :0,5-7) * "Tip of the day" removed (tips.txt deleted). * added SVG icon (fityk.svg) and MIME type info (fityk.xml) * removed files AUTHORS and ChangeLog * the API is now a Fityk class * GUI: setting baseline as convex hull of data points (experimental) * XPS Shirley background removing * minor improvements and bug fixes (e.g. "reset" was not working in 0.8.1) User-visible changes in version 0.8.1 (2007-04-23): * extended version info can be shown by "info+ version" * displaying Gaussian-FWHM and Lorentzian-FWHM of Voigt function * GUI, MS Windows: configuration is now stored in files, not in registry * GUI: support for any numbers of config files. * changes in command-line parameters * "_EXECUTED_SCRIPT_DIR_/" in scripts is replaced with the script directory * GUI: logarithmic x scale and reversed y scale * bug fixes User-visible changes in version 0.8.0 (2007-03-19): * libfityk (fityk library) if introduced. About half of the fityk source code goes into the library; the rest is GUI and CLI. The library has minimal public well-documented C++ API. * experimental(!) python bindings to the library are prepared using SWIG * bug fixes, of course User-visible changes in version 0.7.8 (2007-03-02): * syntax changed for dataset sum (was: @+ < @0 + @1; is: @+ = @0 + @1) * introduced dataset operations sum_same_x and avg_same_x, eg. "@+ = sum_same_x @0 + @1" (in GUI: Data > Merge points) * command "info version" * changed options to "set verbosity" * GUI: error bars for data * voigt(x,y) function for data transformations and variable definitions * new option in settings "epsilon" used for floating point comparision. * GUI: script debugger dialog was finished; "Edit init file" was added to menu * option data-default-sigma with possible values: one, sqrt. * plot command: dataset can be specified using "in @n" or "in @*", default view may not contain y=0, if it's far enough from data points * corrected calculation of covariance matrix (new C_ij = old C_ij / 2) * several bug fixes (most of them reported by Wolfgang Christen) User-visible changes in version 0.7.7 (2007-01-08): * fixed GCC 4.1 compilation problem * GUI: plot buffering (as a bitmap); disabling menu, toolbar, etc. when fitting * new option guess-at-center-pm (float), used by "guess Type center=$variable" * ascii data loading: column number of 0 generates a number increasing with each point * parameters history ("fit undo", "fit redo", and related commands) * syntax changes: "%a[hwhm]" replaced with "%a.hwhm" "@n.F[hwhm]" replaced with "@n.F.hwhm" "%f -> F" replaced with "F += %f" "%f -> N" replaced with "F -= %f" the dataset can be specified in data expression: {y[0] in @1} @0.F[3] means 4th function in @0.F (the same with Z) User-visible changes in version 0.7.6 (2006-09-15): * changes to the manual sent by Michael Richardson * erf and erfc functions can be used in data transformations and UDFs * command "dump" works now * changed syntax for exporing function parameters and formulae (info peaks in @0 > filename; info formula in @0 > filename) * guess command supports now not only "peaks", but also "linear" functions * GUI: improved peak dragging, full-screen mode (F11), configurable status bar, minor tics on plot axes, function parameters can be locked (frozen) using buttons at sidebar, improved "Data->Load File (custom)" dialog * a bunch of other improvements, bugs fixes and optimizations User-visible changes in version 0.7.5 (2006-07-31): * GUI: Definition Manager dialog * user defined functions (UDF) * GUI: gradient dialog for changing color of many datasets at once * GUI: new Fit->Run dialog * So-called domain of simple-variables can be specified ($a = ~3.5 [3 +- 2]), it is used only for randomization of the variable by some fitting methods. * "info" can be redirected to file using "info ... > filename" syntax to truncate the file and "info ... >> file" to appends to the file * variables with names starting with "_" are auto-deleted when not used * parameters of Lev-Mar methods can be changed (it was disabled in 0.7.0) * GUI: pressing Shift in data range mode allows (dis)activate data in rectangle * r-squared shown in "info fit" output (Emmanuel Lamprecht) * a few bug fixes User-visible changes in version 0.7.4 (2006-05-31): * improved data and sum export * GUI: optional grid in main plot (see axes configuration dialog) * defined function types can be undefined using "undefine Function" syntax * with option=value[, option2=value2 ...] command ... sets value of options for this command only * GUI: if cut-function-level is set, function limits are shown when cursor is over peak top * aggregate functions in data expressions: min, max, sum, avg, stddev, darea eg. min(y if 20 "Copy to Clipboard" copies plots to clipboard * added fityk.desktop file for Linux desktop integration (Niklas Volbers) * GUI: "directories" tab in settings dialog User-visible changes in version 0.7.1 (2006-02-23): * new functions: EMG (exponentially modified gauss) and Doniach-Sunjic * GUI: fixes and improvements in printing * GUI: new aux. plot type: cumulative chi2 * minor bug fixes User-visible changes in version 0.7.0 (2006-02-08): * program can be compiled with unicode-enabled wxWidgets * GUI: more configurable axes (eg. a reversed x axis option) and peak labels (eg. horizontal/vertical labels) User-visible changes in version 0.7.0pre1 (2006-01-23): * ########################################################################### # completely changed syntax # ########################################################################### * GUI: dataset/function/variable lists at right-hand panel * new built-in functions: split-Gaussian (a.k.a Bifurcated Gaussian) and others * there where many other changes not listed here. More then half of the code was either written from scratch or refactored. * some features available in previous version are temporarily disabled, most notably: powder diffraction part - c.xxx commands parameters history User-visible changes in version 0.5.1 (2005-07-21): * new toolbar icons * data tranformations: treat "3 < x < 4" like "3 < x and x < 4" * GUI data viewer - "Fit Zoom" button User-visible changes in version 0.5.0 (2005-06-09): * d.load -- possibility of loading of only selected points from file was removed (it can be done with d.tranform after loading) new option: adding data points from file to currently loaded data * d.transform -- new quite powerful command for transforming data, Commands d.deviation, d.range, d.background, d.calibrate, d.set were removed. Handling of background (and calibration) is now a little different. * added Data Editor dialog and Data->Fast DT menu. User-visible changes in version 0.4.4 (2005-03-04): * fixed Pseudo-Voigt formula in manual (program was not changed) (David Hovis) * peak labels (above each peak) that can display peak area, position etc. * fonts used for scale labels can be changed * data viewer (it is first step in implementing data editor) * input field: up/down arrow keys work as in bash (wxComboBox was replaced by wxTextCtrl) * optionally drawing sum and peaks as smooth curves (computed at every pixel) * info about wxWidgets version in About box and --version switch for fityk-GUI. User-visible changes in version 0.4.3: * wxWidgets 2.5 compatible * data files (in addition to scripts) can be specified as command line arguments to fityk-GUI. Scripts should either have .fit or .fityk extensions or start with "# Fityk" string. * crosshair cursor (GUI->Crosshair cursor) * "Data->Load File" dialog (simple) allows to open many files * unix man page (Carlo Segre) User-visible changes in version 0.4.2: * "File" menu name was replaced with "Session", and "Manipulate" with "FindPeak" * "s.info ^number" prints more informations. * fixed problem with locales, that have decimal point different than dot. Now LC_NUMERIC variable is ignored. (Vincent Favre-Nicolin) * new configure flags: --enable-debug and --enable-optimization * ambiguous 'log(2)' in "export as function" was replaced by numeric value (in gnuplot log means natural log, in Excel log=log10). * program version is written in scripts (session dumps and log files) and in configuration files User-visible changes in version 0.4.1: * two independent auxiliary plots (by default one is visible) * implemented s.guess command that adjusts existing peak - also in peak pop-up menu (based on patch sent by Jonathan Hunt) * config file can store info, what windows are visible (see GUI->Show) User-visible changes in version 0.4.0: * multiple datasets in one plot * multiple plots - all can be fitted simultaneously * New menu items - GUI->Show->..., GUI->Scroll... User-visible changes in version 0.3.4: * enhanced peak dragging * commands from ${HOME}/.fityk/init are executed on start-up * added Data->Recent files->... to menu * minor fixes User-visible changes in version 0.3.3: * Major changes in graphical interface (mouse usage, toolbar etc.) * Added support for Siemens .raw data file format (Stefan Krumm) User-visible changes in version 0.3.2: * Voigt function * File->Re-Include menu item * File->Print Setup menu item * Zoom All menu item added to main plot popup menu * Zooming with left mouse button in normal mode * Auto-scaling auxiliary plot when changing type of the plot * Exporting peak parameters (Sum->Export or s.export) * Sum/Data Export: optionally appending to a file, instead of overwritting * Minor changes and bug fixes User-visible changes in version 0.3.1: * Saving GUI configuration to file (Unix) or registry (Windows) * s.export ---> XFIT format * d.load ---> CPI format * Minor bug fixes * Minor changes in documentation (XSLT stylesheet for generating command and option indices) * fityk.spec for creating RPMs * Windows installer (produced with InnoSetup) * Using HtmlHelp (*.chm) manual format in Windows version fityk-1.3.1/README.md000066400000000000000000000013541302634723100141250ustar00rootroot00000000000000 Website: http://fityk.nieto.pl Wiki: https://github.com/wojdyr/fityk/wiki Code: https://github.com/wojdyr/fityk Manual: http://fityk.readthedocs.org/en/latest/ Discussions: http://groups.google.com/group/fityk-users/ Building from Source: Read the INSTALL file [![Build Status](https://travis-ci.org/wojdyr/fityk.svg?branch=master)](https://travis-ci.org/wojdyr/fityk) [![MSVC Build Status](https://ci.appveyor.com/api/projects/status/q2vmyiya4vril835?svg=true)](https://ci.appveyor.com/project/wojdyr/fityk) Citing in academic papers: [J. Appl. Cryst. 43, 1126 (2010)](http://dx.doi.org/10.1107/S0021889810030499) ([reprint](http://wojdyr.github.io/fityk-JAC-10-reprint.pdf)) Contact: wojdyr@gmail.com fityk-1.3.1/TODO000066400000000000000000000075531302634723100133450ustar00rootroot00000000000000 * getting NaN as one of X values leads to hard to diagnose problems, need to filter it out at some stage and warn the user * handle correlated parameters: use pseudo-inverse for covariance matrix * API: add all_datasets(): for n, title in F:all_datasets() do ... (or a public class Dataset?) * API: access to confidence intervals * GUI: Tools > Macros * document how to get Gaussian/Lorentzian width from Voigt * info cov/errors - do not specify dataset * samples: add CeO2 from http://mysite.du.edu/~balzar/s-s_rr.htm * XRPD - db of popular materials? but which are the most popular? * GUI: plot histogram of residuals: http://www.itl.nist.gov/div898/handbook/eda/section3/normprpl.htm * Use more exact Voigt approximation from Faddeeva Package (by SGJ) or libcerf * FFT data transformation using FFTW library, fft[-inv]-xx, where xx is re, im, amp, e.g. @n = fft-re(@3) * convolution and deconvolution of two datasets or a dataset with Gaussian: convolve(@0, @1); convolve(@0, 2.3); deconvolve(@0,3.4) OR conv(@0, gauss(2.3)) * GUI: draw points (handles) for dragging peak width at half height * CLI/GUI: use sigaction() instead of signal() to handle SIGINT print a message from interrupt_handler() * refactor sidebar; use wxDataViewCtrl for the lists at the sidebar, rewrite ListWithColors::populate(), add sorting by clicking on column header (use case: sort functions by centers) * syntax enhancements: $min = @*.min(y if a) print all: F[*](x) # print all components as columns * finish the powder diffraction add-on (Pawley fitting) * add functions cot and coth * allow all the functions from data transformation in variable/UDF definition * GUI: there is ugly vertical line (a part of the fitted curve) in points where the value is undefined (e.g. in ReadShockley function for x=0). * GUI: when dataset is changed and the active function (i.e. the function in the bottom of the sidebar) is not in the new active dataset, the active function should also be changed (to the function that was active last time this dataset was active) * (?) GUI: possibility to plot horizontal/vertical lines on the main plot (for example to show theoretical peak positions in XRD or to mark simulation restarts in data from MD. Syntax: plot line x=42.2 label="foo" * GUI: a simple (for the user) way to interrupt fitting. Requires two threads. * confidence bands * data smoothing (Savitzky-Golay and/or other methods) * splines: fitting, guessing, handling knots in the GUI * user defined functions: - calculating limits, width, area, etc. for UDF - ?? use LLVM for faster calculation of user-defined functions * info dpeak [range]: show parameters of selected data range assuming that this range contains a peak: area, center, FWHM, max, peak-area, backgr-area (like in the Xview program) * more sophisticated algorithms for peak detection - compare methods from origin pkfind, peakfit, fitzpeak and other programs - research papers: http://dx.doi.org/10.1016/j.chroma.2004.11.073 http://dx.doi.org/10.1002/cem.1005 http://www.ncbi.nlm.nih.gov/pmc/articles/PMC2631518/ * "anonymous" function types: %f = ~1/(1+exp(11*(~0.663-x))) -> Anon1(a0,a1) * fitting - external libraries to be considered/tested: - ceres-solver (or http://dlib.net/optimization.html) - libgencurvefit (Differential Evolution), - PaGMO library that collects many optimisation methods. - GSL: https://www.sourceware.org/ml/gsl-discuss/2014-q1/msg00025.html * fitting: in addition to the least squares fit, add so-called robust fit (it is called robust fit in the Numerical Recipes book), i.e. optimize assuming the error distribution is other then Gaussian, eg. Lorenzian...; there is also a literature about so called 'maximum-likelihood method' in which the exact Poisson error distribution is handled. fityk-1.3.1/autogen.sh000077500000000000000000000002761302634723100146510ustar00rootroot00000000000000#!/bin/sh set -x # choose one: (cd doc && make) # build docs #mkdir -p doc/html/placeholder # do not build docs autoreconf --install --verbose \ && ./configure "$@" fityk-1.3.1/cli/000077500000000000000000000000001302634723100134125ustar00rootroot00000000000000fityk-1.3.1/cli/gnuplot.cpp000066400000000000000000000074621302634723100156170ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // CLI-only file #include "gnuplot.h" #include #include #include #include #include #include #include #ifndef _WIN32 #include #endif #include "fityk/fityk.h" #include "fityk/common.h" // is_finite() #define GNUPLOT_PATH "gnuplot" using namespace std; using fityk::Point; using fityk::is_finite; GnuPlot::GnuPlot() : failed_(false), gnuplot_pipe_(NULL) { } GnuPlot::~GnuPlot() { if (gnuplot_pipe_) fclose(gnuplot_pipe_); } void GnuPlot::fork_and_make_pipe() { #ifndef _WIN32 signal(SIGPIPE, SIG_IGN); int fd[2]; int ret = pipe(fd); if (ret == -1) { perror("pipe"); exit(1); } pid_t childpid = fork(); if (childpid == -1) { perror("fork"); exit(1); } if (childpid == 0) { // Child process closes up output side of pipe close(fd[1]); // and input side is stdin dup2(fd[0], 0); if (fd[0] > 2) close(fd[0]); //putenv("PAGER="); execlp(GNUPLOT_PATH, GNUPLOT_PATH, /*"-",*/ NULL); // if we are here, sth went wrong fprintf(stderr, "** Calling `" GNUPLOT_PATH "' failed. Plotting disabled. **\n"); abort(); // exit() messed with open files. } else { // Parent process closes up input side of pipe close(fd[0]); gnuplot_pipe_ = fdopen(fd[1], "w"); //fdopen() - POSIX, not ANSI } #endif //!_WIN32 } bool GnuPlot::test_gnuplot_pipe() { #ifdef _WIN32 return false; #else //!_WIN32 errno = 0; fprintf(gnuplot_pipe_, " "); //pipe test fflush(gnuplot_pipe_); if (errno != 0) // errno == EPIPE if the pipe doesn't work failed_ = true; return errno == 0; #endif //_WIN32 } void GnuPlot::plot() { // plot only the active dataset and model int dm_number = ftk->get_default_dataset(); const vector& points = ftk->get_data(dm_number); double left_x = ftk->get_view_boundary('L'); double right_x = ftk->get_view_boundary('R'); vector::const_iterator begin = lower_bound(points.begin(), points.end(), Point(left_x,0)); vector::const_iterator end = upper_bound(points.begin(), points.end(), Point(right_x,0)); bool has_points = (begin != end); if (gnuplot_pipe_ == NULL && has_points) fork_and_make_pipe(); if (gnuplot_pipe_ == NULL || failed_ || !test_gnuplot_pipe()) return; // send "plot ..." through the pipe to gnuplot string plot_string = "plot " + ftk->get_info("view") + " \'-\' title \"data\", '-' title \"sum\" with line\n"; fprintf(gnuplot_pipe_, "%s", plot_string.c_str()); if (fflush(gnuplot_pipe_) != 0) fprintf(stderr, "Flushing pipe program-to-gnuplot failed.\n"); // data if (has_points) { for (vector::const_iterator i = begin; i != end; ++i) if (i->is_active && is_finite(i->x) && is_finite(i->y)) fprintf(gnuplot_pipe_, "%f %f\n", double(i->x), double(i->y)); } else // if there are no points, we send empty dataset to reset the plot fprintf(gnuplot_pipe_, "0.0 0.0\n"); fprintf(gnuplot_pipe_, "e\n");//gnuplot needs 'e' at the end of data // model if (has_points) { for (vector::const_iterator i = begin; i != end; ++i) if (i->is_active && is_finite(i->x)) { double y = ftk->get_model_value(i->x, dm_number); if (is_finite(y)) fprintf(gnuplot_pipe_, "%f %f\n", double(i->x), y); } } else fprintf(gnuplot_pipe_, "0.0 0.0\n"); fprintf(gnuplot_pipe_, "e\n"); fflush(gnuplot_pipe_); } fityk-1.3.1/cli/gnuplot.h000066400000000000000000000007351302634723100152600ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_GNUPLOT_H_ #define FITYK_GNUPLOT_H_ #include namespace fityk { class Fityk; } extern fityk::Fityk* ftk; // defined in cli/main.cpp class GnuPlot { public: GnuPlot(); ~GnuPlot(); void plot(); private: bool failed_; FILE *gnuplot_pipe_; void fork_and_make_pipe(); bool test_gnuplot_pipe(); }; #endif fityk-1.3.1/cli/main.cpp000066400000000000000000000223711302634723100150470ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // Command-line user interface. // In this file: main loop,callbacks for UiApi (CLI-specific) // and readline support (command expansion). #include #include //#include #include #include #include #ifdef _WIN32 # include // _getcwd() # ifdef _MSC_VER # include # define access _access # define X_OK 0 # define R_OK 4 # endif #else # include # include #endif #include "fityk/fityk.h" #include "fityk/ui_api.h" #include "gnuplot.h" #if HAVE_CONFIG_H # include // VERSION, HAVE_LIBREADLINE, etc #endif #if HAVE_LIBREADLINE # if defined(HAVE_READLINE_READLINE_H) # include # elif defined(HAVE_READLINE_H) # include # endif # if defined(HAVE_READLINE_HISTORY_H) # include # elif defined(HAVE_HISTORY_H) # include # elif defined(HAVE_READLINE_HISTORY) extern "C" { extern void add_history(const char*); } # endif #endif // HAVE_LIBREADLINE using namespace std; using namespace fityk; Fityk* ftk = 0; //------ implementation of CLI specific methods for UiApi callbacks ------ static void cli_draw_plot (UiApi::RepaintMode /*mode*/, const char* filename) { static GnuPlot my_gnuplot; if (filename) { fprintf(stderr, "Saving plot to file is not implemented.\n"); return; } my_gnuplot.plot(); } //----------------------------------------------------------------- namespace { const char* prompt = "=-> "; /// returns absolute path to config directory string get_config_dir() { static bool first_run = true; static string dir; if (!first_run) return dir; char t[200]; char *home_dir = getenv("HOME"); if (home_dir == NULL) { #ifdef _WIN32 home_dir = _getcwd(t, 200); #else home_dir = getcwd(t, 200); #endif } if (home_dir != NULL) { // '/' is assumed as path separator dir = string(home_dir) + "/" + config_dirname() + "/"; if (access(dir.c_str(), X_OK) != 0) dir = ""; } first_run = false; return dir; } #if HAVE_LIBREADLINE void read_and_execute_input() { char *line = readline(prompt); if (!line) throw ExitRequestedException(); if (*line) add_history(line); string s = line; free(line); while (!s.empty() && *(s.end()-1) == '\\') { s.resize(s.size()-1); char *cont = readline("... "); s += cont; free(cont); } ftk->get_ui_api()->exec_and_log(s); } int f_start = -1; int f_end = -1; char *completion_generator(const char *text, int state) { static size_t list_index = 0; static vector entries; if (!state) { entries = complete_fityk_line(ftk, rl_line_buffer, f_start, f_end, text); list_index = 0; } else list_index++; rl_attempted_completion_over = 1; // special value - request for filename completion if (entries.size() == 1 && entries[0].empty()) return rl_filename_completion_function(text, state); if (list_index < entries.size()) return strdup(entries[list_index].c_str()); else return NULL; } char **my_completion (const char *text, int start, int end) { f_start = start; f_end = end; return rl_completion_matches(text, completion_generator); } #if defined(HAVE_READLINE_HISTORY_H) || defined(HAVE_HISTORY_H) /// Reads history (for readline) in ctor and saves it to file in dtor. /// Proper use: single instance created at the beginning of the program /// and destroyed at the end. class RlHistoryManager { public: RlHistoryManager(); ~RlHistoryManager(); private: string hist_file; }; /// read history file RlHistoryManager::RlHistoryManager() { string fityk_dir = get_config_dir(); if (!fityk_dir.empty()) { hist_file = fityk_dir + "history"; read_history (hist_file.c_str()); } } /// save history to file RlHistoryManager::~RlHistoryManager() { //saving command history to file if (!hist_file.empty()) { int hist_file_size = -1; char *hfs = getenv ("HISTFILESIZE"); if (hfs) hist_file_size = atoi (hfs); if (hist_file_size <= 0) hist_file_size = 500; write_history (hist_file.c_str()); history_truncate_file (hist_file.c_str(), hist_file_size); } } #else typedef int RlHistoryManager; #endif void main_loop() { //initialize readline char name[] = "fit"; rl_readline_name = name; char word_break_characters[] = " \t\n\"\\'`@$><=;|&{(:"; // default+":" rl_basic_word_break_characters = word_break_characters; rl_attempted_completion_function = my_completion; RlHistoryManager hm; // reads and saves readline history (RAII) // the main loop -- reading input and executing commands for (;;) read_and_execute_input(); } #else //HAVE_LIBREADLINE // the simplest version of user interface -- when readline is not available void main_loop() { string s; char line_buffer[1024]; for (;;) { printf("%s", prompt); fflush(stdout); if (!fgets(line_buffer, sizeof(line_buffer), stdin)) break; s = line_buffer; while (!s.empty() && *(s.end()-1) == '\\') { s.resize(s.size()-1); printf("... "); fflush(stdout); if (!fgets(line_buffer, sizeof(line_buffer), stdin)) break; s += line_buffer; } ftk->get_ui_api()->exec_and_log(s); } } #endif //HAVE_LIBREADLINE void interrupt_handler (int /*signum*/) { fityk::user_interrupt = 1; // set flag to stop computations } } // anonymous namespace int main (int argc, char **argv) { #ifndef _WIN32 // setting Ctrl-C handler if (signal (SIGINT, interrupt_handler) == SIG_IGN) signal (SIGINT, SIG_IGN); #endif //_WIN32 // process command-line arguments bool exec_init_file = true; bool enable_plot = true; bool quit = false; string script_string; for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { printf( "Usage: cfityk [-h] [-V] [-c ] [script or data file...]\n" " -h, --help show this help message\n" " -V, --version output version information and exit\n" " -c, --cmd= script passed in as string\n" " -I, --no-init don't process $HOME/.fityk/init file\n" " -n, --no-plot disable plotting (gnuplot)\n" " -q, --quit don't enter interactive shell\n"); return 0; } else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) { printf("fityk version " VERSION "\n"); return 0; } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--cmd")) { argv[i] = 0; ++i; if (i < argc) { script_string = argv[i]; argv[i] = 0; } else { fprintf(stderr, "Option %s requires parameter\n", argv[i]); return 1; } } else if (!strncmp(argv[i], "-c", 2)) { script_string = string(argv[i] + 2); argv[i] = 0; } else if (!strncmp(argv[i], "--cmd=", 6)) { script_string = string(argv[i] + 6); argv[i] = 0; } else if (!strcmp(argv[i], "-I") || !strcmp(argv[i], "--no-init")) { argv[i] = 0; exec_init_file = false; } else if (!strcmp(argv[i], "-n") || !strcmp(argv[i], "--no-plot")) { argv[i] = 0; enable_plot = false; } else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--quit")) { argv[i] = 0; quit = true; } else if (strlen(argv[i]) > 1 && argv[i][0] == '-') { fprintf(stderr, "Unknown option %s\n", argv[i]); return 1; } } ftk = new Fityk; // set callbacks if (enable_plot) ftk->get_ui_api()->connect_draw_plot(cli_draw_plot); if (exec_init_file) { // file with initial commands is executed first (if exists) string init_file = get_config_dir() + startup_commands_filename(); if (access(init_file.c_str(), R_OK) == 0) { fprintf(stderr, " -- init file: %s --\n", init_file.c_str()); ftk->get_ui_api()->exec_fityk_script(init_file); fprintf(stderr, " -- end of init file --\n"); } } try { //then string given with -c is executed if (!script_string.empty()) ftk->get_ui_api()->exec_and_log(script_string); //the rest of parameters/arguments are scripts and/or data files for (int i = 1; i < argc; ++i) { if (argv[i]) ftk->process_cmd_line_arg(argv[i]); } // there are two versions of main_loop(), w/ and w/o libreadline if (!quit) main_loop(); } catch(ExitRequestedException) { fprintf(stderr, "\nbye...\n"); } catch (runtime_error const& e) { fprintf(stderr, "Error: %s\n", e.what()); return 1; } return 0; } fityk-1.3.1/configure.ac000066400000000000000000000156231302634723100151400ustar00rootroot00000000000000# Process this file with autoconf to produce a configure script. AC_INIT([fityk],[1.3.1]) LIBRARY_VERSION_FLAG="-version-info 4:0:0" AC_CONFIG_SRCDIR([fityk/voigt.h]) AC_CONFIG_AUX_DIR(build-aux) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADER([config.h]) AM_INIT_AUTOMAKE([1.11 foreign subdir-objects silent-rules -Wall]) AC_PROG_CC AC_PROG_CXX AM_PROG_CC_C_O m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) LT_INIT([disable-static win32-dll]) AC_ARG_ENABLE(GUI, AS_HELP_STRING([--disable-GUI], [do not build the GUI])) AC_ARG_ENABLE(CLI, AS_HELP_STRING([--disable-CLI], [do not build the CLI])) AC_ARG_ENABLE(powdifpat, AS_HELP_STRING([--enable-powdifpat], [build (not working) powdifpat program])) AC_ARG_ENABLE(python, AS_HELP_STRING([--enable-python], [build Python bindings to libfityk])) #AC_ARG_ENABLE(perl, AS_HELP_STRING([--enable-perl], # [build Perl bindings to libfityk])) AC_ARG_ENABLE(nlopt, AS_HELP_STRING([--enable-nlopt], [use NLopt library])) # this option is handled in m4/readline.m4 AC_ARG_WITH(readline, AS_HELP_STRING([--without-readline], [do not use the GNU readline library for cfityk])) AC_ARG_WITH(options, AS_HELP_STRING([--with-options=OPTIONS], [options appended to CC, CXX and LD (e.g. -isysroot)]), [UNIV_OPTION=$withval]) AM_OPTIONS_WXCONFIG AC_MSG_CHECKING([for MinGW compiler]) case "$host_os" in mingw*) windows=yes ;; *) windows=no ;; esac AC_MSG_RESULT([$windows]) AM_CONDITIONAL(OS_WIN32, test "$windows" = "yes") if test "$windows" = "yes"; then AC_CHECK_TOOL(RC, windres) if test "x$RC" = "x"; then AC_MSG_ERROR([Required resource tool 'windres' not found on PATH.]) fi fi if test "x$with_options" != "x"; then CC="$CC $with_options" CXX="$CXX $with_options" LD="$LD $with_options" fi AC_LANG_PUSH([C++]) # AC_PROG_CXX doesn't fail if compiler is not found, test it explicitely AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])], [], [AC_MSG_ERROR([C++ compiler not found.])]) AC_CHECK_HEADER(sstream, [], [AC_MSG_ERROR( [You don't have a header. It is a part of standard C++ library. Either you have too old compiler, or standard C++ library can't be found.])]) AC_CHECK_HEADER([boost/math/special_functions/gamma.hpp], [], [AC_MSG_ERROR( [Boost::Math headers not found. Make sure you have Boost installed.])]) AC_CHECK_HEADER([boost/array.hpp], [], [AC_MSG_ERROR( [Boost::Array headers not found. Make sure you have Boost installed.])]) AC_CHECK_HEADER([boost/scoped_ptr.hpp], [], [AC_MSG_ERROR( [Boost Smart Pointers not found. Make sure you have Boost installed.])]) AC_LANG_POP([C++]) AC_CHECK_HEADER([zlib.h], [], [AC_MSG_ERROR( [zlib.h header not found. Install zlib library (with development files).])]) AC_CHECK_FUNCS([popen getline]) AC_SEARCH_LIBS([cos], [m], [], [ AC_MSG_ERROR([unable to find the dlopen() function])]) AC_CHECK_FUNC(erf, [], [AC_MSG_ERROR([erf function not found (?). Please inform program developer(s) about this problem.])]) AC_CHECK_FUNC(erfc, [], [AC_MSG_ERROR([erfc function not found (?). Please inform program developer(s) about this problem.])]) AC_CHECK_FUNCS([finite isnan]) # see m4/ax_cxx_have_isfinite.m4 AX_CXX_HAVE_ISFINITE AC_CHECK_HEADER([xylib/xylib.h], [], [AC_MSG_ERROR( [xylib headers were not found. You may need to install xylib first.])]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([@%:@include ], [ #if XYLIB_VERSION < 10000 # error "xylib >= 1.0 is required" #endif ])], [], [AC_MSG_ERROR([xylib >= 1.0 is not installed])]) AS_IF([test x"$LUA52_FROM_SOURCE" != xyes], [ AX_PROG_LUA(5.1, 5.4) AX_LUA_HEADERS AX_LUA_LIBS ]) # Checks for version specific libraries and headers. AS_IF([test "x$enable_GUI" != "xno"], [ AM_PATH_WXCONFIG([3.0.0], [wxWin=1], [wxWin=0], [adv,core,base,stc]) if test "$wxWin" != 1; then AC_MSG_ERROR([ wxWidgets must be installed on your system but wx-config script could not be found. Please check that wx-config is in path, the directory where wxWidgets libraries are installed (returned by 'wx-config --libs' command) is in LD_LIBRARY_PATH or equivalent variable and wxWidgets version is 3.0 or above. ]) fi ]) AS_IF([test "x$enable_CLI" != "xno"], [ if test "x$with_readline" != "xno" ; then ORIG_LIBS="$LIBS" AX_LIB_READLINE LIBS=$ORIG_LIBS READLINE_LIBS="$ax_cv_lib_readline" # readline < 4.2 doesn't have rl_completion_matches() function # some libreadline-compatibile libraries (like libedit) may also # not have it. We don't support them. AC_CHECK_DECLS([rl_completion_matches], [], [AC_MSG_ERROR([ Readline library that has rl_completion_matches() not found. Either install libreadline >= 4.2 or compatible library, or configure fityk with option --without-readline])], [ #include #if defined(HAVE_READLINE_READLINE_H) #include #elif defined(HAVE_READLINE_H) #include #endif ]) fi AC_CHECK_PROG(gnuplot_in_path, gnuplot, yes) if test "x$gnuplot_in_path" != "xyes" ; then AC_MSG_RESULT([gnuplot not found (it is not necessary)]) fi AC_CHECK_HEADER(unistd.h, [], [AC_MSG_ERROR( [unistd.h header not found (required for cfityk.])]) ]) if test "x$enable_python" = "xyes"; then AM_PATH_PYTHON(2.3) AX_PYTHON_DEVEL fi if test "x$enable_nlopt" = "xyes"; then AC_CHECK_LIB(nlopt, nlopt_version, , AC_MSG_ERROR([nlopt library not found.])) AC_CHECK_HEADER(nlopt.h, , AC_MSG_ERROR([nlopt.h header not found.])) fi AM_CONDITIONAL([POWDIFPAT], [test x$enable_powdifpat = xyes]) AM_CONDITIONAL([GUI_DIR], [test "x$enable_GUI" != xno]) AM_CONDITIONAL([CLI_DIR], [test "x$enable_CLI" != xno]) AM_CONDITIONAL([PYTHON_ENABLED], [test "x$enable_python" = xyes]) #AM_CONDITIONAL([PERL_ENABLED], [test "x$enable_perl" = xyes]) AM_CONDITIONAL([NLOPT_ENABLED], [test "x$enable_nlopt" = xyes]) AM_CONDITIONAL([COMPILE_LUA_SRC], [test "x$LUA52_FROM_SOURCE" = xyes]) #if test "x$enable_perl" = "xyes"; then # AC_CHECK_PROG(PERL, perl, "yes") #fi # 2.0.12 is required here b/c 2.0.11 has a critical bug in Lua generator AS_IF([test -z "$SWIG"], [AX_PKG_SWIG(2.0.12, [], [SWIG=swig_not_found])], [AC_MSG_NOTICE([Using SWIG=$SWIG without checking])]) AC_ARG_VAR([SWIG], [the SWIG program]) AC_SUBST(LIBRARY_VERSION_FLAG) AC_SUBST(LUA_INCLUDE) AC_SUBST(LUA_LIB) AC_SUBST(READLINE_LIBS) AC_DEFINE_UNQUOTED(CONFIGURE_BUILD, "$ac_cv_build", [ac_cv_build]) AC_DEFINE_UNQUOTED(CONFIGURE_ARGS, "$ac_configure_args", [ac_configure_args]) AC_OUTPUT([Makefile fityk.iss fityk/Makefile wxgui/Makefile]) fityk-1.3.1/doc/000077500000000000000000000000001302634723100134105ustar00rootroot00000000000000fityk-1.3.1/doc/Makefile000066400000000000000000000011751302634723100150540ustar00rootroot00000000000000 # this is normal Makefile, _not_ generated by autotools SPHINX = sphinx-build -a -d ./doctrees/ html: *.rst fitheme/* fitheme/static/* conf.py $(SPHINX) -b html . html rm -f html/objects.inv html/.buildinfo fityk-banner.pdf: fityk-banner.svg inkscape --export-text-to-path --export-pdf=$@ $< pdf: rm -rf doctrees/ $(SPHINX) -b latex . latex cd latex/ && make all-pdf website: rm -rf web BUILD_WEBSITE=1 $(SPHINX) -b html -Awebsite=1 . web cp screenshots/fityk-1.0.1-osx-so.png web/_images/ rm -f web/objects.inv web/.buildinfo sed -i 's/— Fityk ..... manual//' web/index.html web/screens.html .PHONY: pdf website fityk-1.3.1/doc/conf.py000066400000000000000000000063411302634723100147130ustar00rootroot00000000000000# -*- coding: utf-8 -*- needs_sphinx = '1.5' import sys, os sys.path.append(os.path.abspath('.')) extensions = ["sphinx.ext.imgmath", "sphinx.ext.extlinks", "fityk_ext"] exclude_patterns = ['html', 'latex'] if not os.getenv('BUILD_WEBSITE'): exclude_patterns += ['index.rst', 'screens.rst'] if os.getenv('READTHEDOCS'): # RTD works better with index.html html_additional_pages = { 'index': '_build/html/fityk-manual.html' } html_theme_path = ['.'] source_suffix = '.rst' source_encoding = 'utf-8' master_doc = 'fityk-manual' project = 'Fityk' version = '1.3.1' release = version default_role = None suppress_warnings = ["ref.option"] #highlight_language = "none" highlight_language = "fityk" pygments_style = "trac" #html_theme = "sphinxdoc" html_theme = 'fitheme' html_theme_options = { 'github_blob': 'wojdyr/fityk/blob/master/doc', 'logo': 'fityk-logo.png', 'logo_caption': 'curve fitting,  data analysis', 'website': 'http://fityk.nieto.pl/', 'wiki': 'https://github.com/wojdyr/fityk/wiki', } if os.getenv('BUILD_WEBSITE'): html_theme_options['analytics_id'] = 'UA-20519098-2' html_sidebars = { 'index': [], 'screens': [], '**': ['side.html'] } html_title = 'Fityk %s manual' % version html_short_title = 'Manual' html_favicon = 'fityk.ico' html_static_path = ['fityk-logo.png', 'img/mouse16.png'] html_last_updated_fmt = '%Y-%m-%d' html_use_smartypants = True html_use_modindex = False html_use_index = False #html_add_permalinks = False #html_compact_lists = True html_show_copyright = False html_copy_source = False # we link directly to GitHub latex_documents = [ ('fityk-manual', 'fityk-manual.tex', 'Fityk manual', '', 'manual', True), ] latex_logo = 'fityk-banner.pdf' latex_elements = { 'papersize': 'a4paper', # 'letterpaper' 'pointsize': '10pt,oneside,openany', #'classoptions': ',oneside,openany', 'inputenc': r""" \usepackage{ucs} \usepackage[utf8x]{inputenc}""", 'utf8extra': '', # put notes into boxes 'preamble': r""" \usepackage{fancybox} \usepackage{ifthen} \definecolor{gray03}{gray}{0.3} \let\origbeginnotice\notice \let\origendnotice\endnotice \renewenvironment{notice}[2]{% \def\noticetype{#1} \def\inTheGui{\equal{#2}{In the GUI}} \def\inCLI{\equal{#2}{CLI}} \ifthenelse{\equal{#1}{note}}{% \setlength{\fboxrule}{1pt} \setlength{\fboxsep}{6pt} \setlength{\mylen}{\linewidth} \addtolength{\mylen}{-2\fboxsep} \addtolength{\mylen}{-4\fboxrule} %\setlength{\shadowsize}{3pt} \Sbox \minipage{\mylen} \ifthenelse{\inTheGui}{\color{gray03}}{} \ifthenelse{\inCLI}{}{\par\sphinxstylestrong{#2}} }{% \origbeginnotice{#1}{#2}% } }{% \ifthenelse{\equal{\noticetype}{note}}{% \endminipage \endSbox \ifthenelse{\inTheGui}{\ovalbox{\TheSbox}}{\fbox{\TheSbox}} }{% \origendnotice% } } """, 'printindex' : '' } #latex_show_pagerefs = True latex_show_urls = 'footnote' latex_keep_old_macro_names = False # determine vertical alignment of the math PNGs imgmath_use_preview = True dl_dir = 'http://fityk.nieto.pl/subscribers/' dl_prefix = 'fityk-%s' % version extlinks = { 'wiki': ('https://github.com/wojdyr/fityk/wiki/%s', ''), 'subscribers_download': (dl_dir + dl_prefix + '%s', dl_prefix), } fityk-1.3.1/doc/data.rst000066400000000000000000000523211302634723100150560ustar00rootroot00000000000000.. _data: Data ==== .. _dataload: Loading Data ------------ Data files are read using the `xylib library `_. .. admonition:: In the GUI click |load-data-icon|. If it just works for your files, you may go straight to :ref:`activepoints`. .. |load-data-icon| image:: img/load_data_icon.png :alt: Load Data :class: icon Points are loaded from files using the command:: dataslot < filename[:xcol:ycol:scol:block] [filetype options...] where - *dataslot* should be replaced with ``@0``, unless many datasets are to be used simultaneously (for details see: :ref:`multidata`), - *xcol*, *ycol*, *scol* (supported only in text file) are columns corresponding to x, y and std. dev. of y. Column 0 means index of the point: 0 for the first point, 1 for the second, etc. - *block* - selects one or more blocks of data from a multi-block file such as VAMAS - *filetype* usually can be omitted, because in most of the cases the filetype can be detected; the list of supported filetypes is at the end of this section - *options* depend on a filetype and usually are omitted If the filename contains blank characters, a semicolon or comma, it should be put inside single quotation marks (together with colon-separated indices, if any). Multiple y columns and/or blocks can be specified, see the examples below:: @0 < foo.vms @0 < foo.fii text first_line_header @0 < foo.dat:1:4:: # x,y - 1st and 4th columns @0 < foo.dat:1:3,4:: # load two dataset (with y in columns 3,4) @0 < foo.dat:1:3..5:: # load three dataset (with y in columns 3,4,5) @0 < foo.dat:1:4..6,2:: # load four dataset (y: 4,5,6,2) @0 < foo.dat:1:2..:: # load 2nd and all the next columns as y @0 < foo.dat:1:2:3: # read std. dev. of y from 3rd column @0 < foo.dat:0:1:: # x - 0,1,2,..., y - first column @0 < 'foo.dat:0:1::' # the same @0 < foo.raw::::0,1 # load two first blocks of data (as one dataset) Information about loaded data can be obtained with:: info data Supported Filetypes ~~~~~~~~~~~~~~~~~~~ text ASCII text, multicolumn numeric data. The details are given in the next section. dbws format used by DBWS (program for Rietveld analysis) and DMPLOT. cpi Sietronics Sieray CPI format uxd Siemens/Bruker UXD format (powder diffraction data) bruker_raw Simens-Bruker RAW format (version 1,2,3) rigaku_dat Rigaku dat format (powder diffraction data) vamas VAMAS ISO-14976 (only experiment modes: "SEM" or "MAPSV" or "MAPSVDP" and only "REGULAR" scan mode are supported) philips_udf Philips UDF (powder diffraction data) philips_rd Philips RD raw scan format V3 (powder diffraction data) spe Princeton Instruments WinSpec SPE format (only 1-D data is supported) pdcif CIF for powder diffraction The full list is available at: http://xylib.sourceforge.net/. Reading Text Files ~~~~~~~~~~~~~~~~~~ The *xylib* library can read TSV or CSV formats (tab or comma separated values). In fact, the values can be separated by any whitespace character or by one of ,;: punctations, or by any combination of these. Empty lines and comments that start with hash (#) are skipped. Since there is a lot of files in the world that contain numeric data mixed with text, unless the :option:`strict` option is given any text that can not be interpreted as a number is regarded a start of comment (the rest of the line is ignored). Note that the file is parsed regardless of blocks and columns specified by the user. The data read from the file are first stored in a table with *m* columns and *n* rows. If some of the lines have 3 numbers in it, and some have 5 numbers, we can either discard the lines that have 3 numbers or we can discard the numbers in 4th and 5th column. Usually the latter is done, but there are exceptions. The shorter lines are ignored * if it is the last line in the file (probably the program was terminated while writing the file), * if it contains only one number, but the prior lines had more numbers (this may be a comment that starts with a number) * if all the (not ignored) prior lines and the next line are longer These rule were introduced to read free-format log files with textual comments inserted between lines with numeric data. For now, xylib does not handle well nan's and inf's in the data. Data blocks and columns may have names. These names are used to set a title of the dataset (see :ref:`multidata` for details). If the option :option:`first_line_header` is given and the number of words in the first line is equal to the number of data columns, each word is used as a name of corresponding column. If the number of words is different, the first line is used as a name of the block. If the :option:`last_line_header` option is given, the line preceding the first data line is used to set either column names or the block name. If the file starts with the "``LAMMPS (``" string, the :option:`last_line_header` option is set automatically. This is very helpful when plotting data from LAMMPS log files. .. _activepoints: Active and Inactive Points -------------------------- We often have the situation that only a part of the data from a file is of interest. In Fityk, each point is either *active* or *inactive*. Inactive points are excluded from fitting and all calculations. (Since active points do not need to be in one region, we do not use the *region of interest* term here, but such region can be easy selected). A data :ref:`transformation `:: A = boolean-condition can be used to change the state of points. .. admonition:: In the GUI data points can be activated and disactivated with mouse in the data-range mode (toolbar: |mode-range-icon|). .. |mode-range-icon| image:: img/mode_range_icon.png :alt: Data-Range Mode :class: icon .. _weights: Standard Deviation (or Weight) ------------------------------ When fitting data, we assume that only the *y* coordinate is subject to statistical errors in measurement. This is a common assumption. To see how the *y*'s standard deviation, *σ*, influences fitting (optimization), look at the weighted sum of squared residuals formula in :ref:`nonlinear`. We can also think about weights of points -- every point has a weight assigned, that is equal :math:`w_i=1/\sigma_i^2`. Standard deviation of points can be :ref:`read from file ` together with the *x* and *y* coordinates. Otherwise, it is set either to max(*y*:sup:`1/2`, 1) or to 1, depending on the :option:`default_sigma` option. Setting std. dev. as a square root of the value is common and has theoretical ground when *y* is the number of independent events. You can always change the standard deviation, e.g. make it equal for every point with the command: ``S=1``. See :ref:`transform` for details. .. note:: It is often the case that user is not sure what standard deviation should be assumed, but it is her responsibility to pick something. .. _transform: Data Point Transformations -------------------------- Every data point has four properties: *x* coordinate, *y* coordinate, standard deviation of *y* and active/inactive flag. These properties can be changed using symbols ``X``, ``Y``, ``S`` and ``A``, respectively. It is possible to either change a single point or apply a transformation to all points. For example: * ``Y[3]=1.2`` assigns the *y* coordinate of the 4th point (0 is first), * ``Y = -y`` changes the sign of the *y* coordinate for all points. On the left side of the equality sign you can have one of symbols ``X``, ``Y``, ``S``, ``A``, possibly with the index in brackets. The symbols on the left side are case insensitive. The right hand side is a mathematical expression that can have special variables: * lower case letters ``x``, ``y``, ``s``, ``a`` represent properties of data points before transformation, * upper case ``X``, ``Y``, ``S``, ``A`` stand for the same properties after transformation, * ``M`` stands for the number of points. * ``n`` stands for the index of currently transformed point, e.g., ``Y=y[M-n-1]`` means that *n*-th point (*n*\ =0, 1, ... M-1) is assigned *y* value of the *n*-th point from the end. Before the transformation a new array of points is created as a copy of the old array. Operations are applied sequentially from the first point to the last one, so while ``Y[n+1]`` and ``y[n+1]`` have always the same value, ``Y[n-1]`` and ``y[n-1]`` may differ. For example, the two commands:: Y = y[n] + y[n-1] Y = y[n] + Y[n-1] differ. The first one adds to each point the value of the previous point. The second one adds the value of the previous point *after* transformation, so effectively it adds the sum of all previous points. The index ``[n]`` could be omitted (``Y = y + y[n-1]``). The value of undefined points, like ``y[-1]`` and ``Y[-1]``, is explained later in this section. Expressions can contain: - real numbers in normal or scientific format (e.g. ``1.23e5``), - constants ``pi``, ``true`` (1), ``false`` (0) - binary operators: ``+``, ``-``, ``*``, ``/``, ``^``, - boolean operators: ``and``, ``or``, ``not``, - comparisions: ``>``, ``>=``, ``<``, ``<=``, ``==``, ``!=``. - one argument functions: * ``sqrt`` * ``exp`` * ``log10`` * ``ln`` * ``sin`` * ``cos`` * ``tan`` * ``sinh`` * ``cosh`` * ``tanh`` * ``atan`` * ``asin`` * ``acos`` * ``erf`` * ``erfc`` * ``gamma`` * ``lgamma`` (=ln(\|\ ``gamma()``\ \|)) * ``abs`` * ``round`` (rounds to the nearest integer) - two argument functions: * ``mod`` (modulo) * ``min2`` * ``max2`` (``max2(3,5)`` gives 5), * ``randuniform(a, b)`` (random number from interval (a, b)), * ``randnormal(mu, sigma)`` (random number from normal distribution), * ``voigt(a, b)`` = :math:`\frac{b}{\pi} \int_{-\infty}^{+\infty} \frac{\exp(-t^2)}{b^2+(a-t)^2} dt` - ternary ``?:`` operator: ``condition ? expression1 : expression2``, which returns *expression1* if condition is true and *expression2* otherwise. A few examples. * The *x* scale of diffraction pattern can be changed from 2\ *θ* to *Q*:: X = 4*pi * sin(x/2*pi/180) / 1.54051 # Cu 2θ -> Q * Negative *y* values can be zeroed:: Y = max2(y, 0) * All standard deviations can be set to 1:: S = 1 * It is possible to select active range of data:: A = x > 40 and x < 60 # select range (40, 60) All operations are performed on **real numbers**. Two numbers that differ less than *ε* (the value of *ε* is set by the :ref:`option epsilon `) are considered equal. Points can be created or deleted by changing the value of ``M``. For example, the following commands:: M=500; x=n/100; y=sin(x) create 500 points and generate a sinusoid. Points are kept sorted according to their *x* coordinate. The sorting is performed after each transformation. .. note:: Changing the *x* coordinate may change the order and indices of points. Indices, like all other values, are computed in the real number domain. If the index is not integer (it is compared using *ε* to the rounded value): * ``x``, ``y``, ``s``, ``a`` are interpolated linearly. For example, ``y[2.5]`` is equal to ``(y[2]+[3])/2``. If the index is less than 0 or larger than M-1, the value for the first or the last point, respectively, is returned. * For ``X``, ``Y``, ``S``, ``A`` the index is rounded to integer. If the index is less than 0 or larger than M-1, 0 is returned. Transformations separated by commas (``,``) form a sequance of transformations. During the sequance, the vectors ``x``, ``y``, ``s`` and ``a`` that contain old values are not changed. This makes possible to swap the axes:: X=y, Y=x The special ``index(arg)`` function returns the index of point that has *x* equal *arg*, or, if there is no such point, the linear interpolation of two neighbouring indices. This enables equilibrating the step of data (with interpolation of *y* and *σ*):: X = x[0] + n * (x[M-1]-x[0]) / (M-1), Y = y[index(X)], S = s[index(X)] It is possible to delete points for which given condition is true, using expression ``delete(condition)``:: delete(not a) # delete inactive points # reduce twice the number of points, averaging x and adding y x = (x[n]+x[n+1])/2 y = y[n]+y[n+1] delete(mod(n,2) == 1) If you have more than one dataset, you may need to specify to which dataset the transformation applies. See :ref:`multidata` for details. The value of a data expression can be shown using the ``print`` command. The precision of printed numbers is governed by the :ref:`numeric_format ` option. :: print M # the number of points print y[index(20)] # value of y for x=20 Aggregate Functions ------------------- Aggregate functions have syntax:: aggregate(expression [if condition]) and return a single value, calculated from values of all points for which the given condition is true. If the condition is omitted, all points in the dataset are taken into account. The following aggregate functions are recognized: * ``min()`` --- the smallest value, * ``max()`` --- the largest value, * ``argmin()`` --- (stands for the argument of the minimum) the x value of the point for which the expression in brackets has the smallest value, * ``argmax()`` --- the x value of the point for which the expression in brackets has the largest value, * ``sum()`` --- the sum, * ``count()`` --- the number of points for which the expression is true, * ``avg()`` --- the arithmetic mean, * ``stddev()`` --- the standard deviation, * ``centile(N, )`` --- percentile * ``darea()`` --- a function used to normalize the area (see the example below). It returns the sum of *expression*\ \*(*x*\ [*n*\ +1]-*x*\ [*n*-1])/2. In particular, ``darea(y)`` returns the interpolated area under data points. Examples:: p avg(y) # print the average y value p centile(50, y) # print the median y value p max(y) # the largest y value p argmax(y) # the position of data maximum p max(y if x > 40 and x < 60) # the largest y value for x in (40, 60) p max(y if a) # the largest y value in the active range p min(x if y > 0.1)] # x of the first point with y > 0.1 p count(y>100) # the number of points that have y above 100 p count(y>avg(y)) # aggregate functions can be nested p y[min(n if y > 100)] # the first (from the left) value of y above 100 # take the first 2000 points, average them and subtract as background Y = y - avg(y if n<2000) Y = y / darea(y) # normalize data area # make active only the points on the left from the first # point with y > 0.1 a = x < min(x if y > 0.1)] .. _funcindt: Functions and Variables in Data Transformation ---------------------------------------------- You may postpone reading this section and read about the :ref:`model` first. Variables ($foo) and functions (%bar) can be used in data expressions:: Y = y / $foo # divides all y's by $foo Y = y - %f(x) # subtracts function %f from data Y = y - @0.F(x) # subtracts all functions in F # print the abscissa value of the maximum of the model # (only the values in points are considered, # so it's not exactly the model's maximum) print argmax(F(x)) # print the maximum of the sum of two functions print max(%_1(x) + %_2(x)) # Fit constant x-correction (i.e. fit the instrumental zero error), ... Z = Constant(~0) fit X = x + Z(x) # ... correct the data Z = 0 # ... and remove the correction from the model. .. admonition:: In the GUI in the *Baseline Mode* (|mode-bg-icon|), functions ``Spline`` and ``Polyline`` are used to subtract manually selected background. Clicking |strip-bg-icon| results in a command like this:: %bg0 = Spline(14.2979,62.1253, 39.5695,35.0676, 148.553,49.9493) Y = y - %bg0(x) Clicking the same button again undoes the subtraction:: Y = y + %bg0(x) The function edited in the *Baseline Mode* is always named ``%bgX``, where *X* is the index of the dataset. .. |mode-bg-icon| image:: img/mode_bg_icon.png :alt: Baseline Mode :class: icon .. |strip-bg-icon| image:: img/strip_bg_icon.png :alt: Strip Background :class: icon Values of the function parameters (e.g. ``%fun.a0``) and pseudo-parameters ``Center``, ``Height``, ``FWHM``, ``IB`` and ``Area`` (e.g. ``%fun.Area``) can also be used. IB stands for Integral Breadth -- width of rectangle with the same area and height as the peak, in other words Area/Height. Not all functions have pseudo-parameters. It is also possible to calculate some properties of %functions: - ``%f.numarea(x1, x2, n)`` gives area integrated numerically from *x1* to *x2* using trapezoidal rule with *n* equal steps. - ``%f.findx(x1, x2, y)`` finds *x* in interval (*x1*, *x2*) such that %f(*x*)=\ *y* using bisection method combined with Newton-Raphson method. It is a requirement that %f(*x1*) < *y* < %f(*x2*). - ``%f.extremum(x1, x2)`` finds *x* in interval (*x1*, *x2*) such that %f'(*x*)=0 using bisection method. It is a requirement that %f'(*x1*) and %f'(*x2*) have different signs. A few examples:: print %fun.findx(-10, 10, 0) # find the zero of %fun in [-10, 10] print F.findx(-10, 10, 0) # find the zero of the model in [-10, 10] print %fun.numarea(0, 100, 10000) # shows area of function %fun print %_1(%_1.extremum(40, 50)) # shows extremum value # calculate FWHM numerically, value 50 can be tuned $c = {%f.Center} p %f.findx($c, $c+50, %f.Height/2) - %f.findx($c, $c-50, %f.Height/2) p %f.FWHM # should give almost the same. .. _multidata: Working with Multiple Datasets ------------------------------ Let us call a set of data that usually comes from one file -- a :dfn:`dataset`. It is possible to work simultaneously with multiple datasets. Datasets have numbers and are referenced by ``@`` with the number, (e.g. ``@3``). The user can specify which dataset the command should be applied to:: @0: M=500 # change the number of points in the first dataset @1 @2: M=500 # the same command applied to two datasets @*: M=500 # and the same applied to all datasets If the dataset is not specified, the command applies to the default dataset, which is initially @0. The ``use`` command changes the default dataset:: use @2 # set @2 as default To load dataset from file, use one of the commands:: @n < filename:xcol:ycol:scol:block filetype options... @+ < filename:xcol:ycol:scol:block filetype options... The first one uses existing data slot and the second one creates a new slot. Using ``@+`` increases the number of datasets, and the command ``delete @n`` decreases it. The dataset can be duplicated (``@+ = @n``) or transformed, more on this in :ref:`the next section `. Each dataset has a separate :ref:`model `, that can be fitted to the data. This is explained in the next chapter. Each dataset also has a title (it does not have to be unique, however). When loading file, a title is automatically created: * if there is a name associated with the column *ycol*, the title is based on it; * otherwise, if there is a name associated with the data block read from file, the title is set to this name; * otherwise, the title is based on the filename Titles can be changed using the command:: @n: title = 'new-title' To print the title of the dataset, type ``@n: info title``. .. _datasettr: Dataset Transformations ----------------------- There are a few transformations defined for a whole dataset or for two datasets. The syntax is ``@n = ...`` or ``@+ = ...``. The the right hand side expression supports the following operations: ``-@n`` negation of all *y* values, ``d * @n`` (e.g. ``0.4*@0``) *y* values are multiplied by *d*, ``@n + @m`` returns ``@n`` with added *y* values from interpolated ``@m``, ``@n - @m`` returns ``@n`` with subtracted *y* values from interpolated ``@m``, ``@n and @m`` returns points from both datasets (re-sorted), and functions: ``sum_same_x(@n)`` Merges points which have distance in *x* is smaller than :ref:`epsilon `. *x* of the merged point is the average, and *y* and *σ* are sums of components. ``avg_same_x(@n)`` The same as ``sum_same_x``, but *y* and *σ* are set as the average of components. ``shirley_bg(@n)`` Calculates Shirley background (useful in X-ray photoelectron spectroscopy). Examples:: @+ = @0 # duplicate the dataset @+ = @0 and @1 # create a new dataset from @0 and @1 @0 = @0 - shirley_bg(@0) # remove Shirley background @0 = @0 - @1 # subtract @1 from @0 @0 = @0 - 0.28*@1 # subtract scaled dataset @1 from @0 .. _dexport: Exporting Data -------------- Command:: print all: expression, ... > file.tsv can export data to an ASCII TSV (tab separated values) file. .. admonition:: In the GUI :menuselection:`Data --> Export` To export data in a 3-column (x, y and standard deviation) format, use:: print all: x, y, s > file.tsv Any expressions can be printed out:: p all: n+1, x, y, F(x), y-F(x), %foo(x), sin(pi*x)+y^2 > file.tsv It is possible to select which points are to be printed by replacing ``all`` with ``if`` followed by a condition:: print if a: x, y # only active points are printed print if x > 30 and x < 40: x, y # only points in (30,40) The option :ref:`numeric_format ` controls the format and precision of all numbers. fityk-1.3.1/doc/fit.rst000066400000000000000000000404171302634723100147320ustar00rootroot00000000000000.. _fit: Curve Fitting ============= .. _nonlinear: Nonlinear Optimization ---------------------- This is the core. We have a set of observations (data points) to which we want to fit a *model* that depends on adjustable parameters. Let me quote `Numerical Recipes `_, chapter 15.0, page 656): The basic approach in all cases is usually the same: You choose or design a figure-of-merit function (merit function, for short) that measures the agreement between the data and the model with a particular choice of parameters. The merit function is conventionally arranged so that small values represent close agreement. The parameters of the model are then adjusted to achieve a minimum in the merit function, yielding best-fit parameters. The adjustment process is thus a problem in minimization in many dimensions. \[...] however, there exist special, more efficient, methods that are specific to modeling, and we will discuss these in this chapter. There are important issues that go beyond the mere finding of best-fit parameters. Data are generally not exact. They are subject to measurement errors (called noise in the context of signal-processing). Thus, typical data never exactly fit the model that is being used, even when that model is correct. We need the means to assess whether or not the model is appropriate, that is, we need to test the goodness-of-fit against some useful statistical standard. We usually also need to know the accuracy with which parameters are determined by the data set. In other words, we need to know the likely errors of the best-fit parameters. Finally, it is not uncommon in fitting data to discover that the merit function is not unimodal, with a single minimum. In some cases, we may be interested in global rather than local questions. Not, "how good is this fit?" but rather, "how sure am I that there is not a very much better fit in some corner of parameter space?" Our function of merit is the weighted sum of squared residuals (WSSR), also called chi-square: .. math:: \chi^{2}(\mathbf{a}) =\sum_{i=1}^{N} \left[\frac{y_i-y(x_i;\mathbf{a})}{\sigma_i}\right]^{2} =\sum_{i=1}^{N} w_{i}\left[y_{i}-y(x_{i};\mathbf{a})\right]^{2} Weights are based on standard deviations, :math:`w_i=1/\sigma_i^2`. You can learn why squares of residuals are minimized e.g. from chapter 15.1 of *Numerical Recipes*. The most popular method for curve-fitting is Levenberg-Marquardt. Fityk can also use a few general-purpose optimization methods. These methods are slower, some of them are orders of magnitude slower. Sometimes alternative methods find global minimum when the L-M algorithm is stuck in a local minimum, but in majority of cases the default L-M method is superior. Uncertainty of Parameters ------------------------- (It is easier for me to find a quote than to express it myself). From the book J. Wolberg, *Data Analysis Using the Method of Least Squares: Extracting the Most Information from Experiments*, Springer, 2006, p.50: (...) we turn to the task of determining the uncertainties associated with the :math:`a_k`'s. The usual measures of uncertainty are standard deviation (i.e., *σ*) or variance (i.e., *σ*:sup:`2`) so we seek an expression that allows us to estimate the :math:`\sigma_{a_k}`'s. It can be shown (...) that the following expression gives us an unbiased estimate of :math:`\sigma_{a_k}`: .. math:: \sigma_{a_k}^{2}=\frac{S}{n-p}C_{kk}^{-1} Note that :math:`\sigma_{a_k}` is a square root of the value above. In this formula *n-p*, the number of (active) data points minus the number of independent parameters, is equal to the number of degrees of freedom. *S* is another symbol for :math:`\chi^2`. Terms of the *C* matrix are given as (p. 47 in the same book): .. math:: C_{jk}=\sum_{i=1}^n w_i \frac{\partial f}{\partial a_j} \frac{\partial f}{\partial a_k} :math:`\sigma_{a_k}` above is often called a *standard error*. Having standard errors, it is easy to calculate *confidence intervals*. But all these values should be used with care. Now another book will be cited: H. Motulsky and A. Christopoulos, *Fitting Models to Biological Data Using Linear and Nonlinear Regression: A Practical Guide to Curve Fitting*, Oxford University Press, 2004. This book can be `downloaded for free`__ as a manual to GraphPad Prism 4. __ http://www.graphpad.com/manuals/prism4/RegressionBook.pdf The standard errors reported by most nonlinear regression programs (...) are "approximate" or "asymptotic". Accordingly, the confidence intervals computed using these errors should also be considered approximate. It would be a mistake to assume that the "95% confidence intervals" reported by nonlinear regression have exactly a 95% chance of enclosing the true parameter values. The chance that the true value of the parameter is within the reported confidence interval may not be exactly 95%. Even so, the asymptotic confidence intervals will give you a good sense of how precisely you have determined the value of the parameter. The calculations only work if nonlinear regression has converged on a sensible fit. If the regression converged on a false minimum, then the sum-of-squares as well as the parameter values will be wrong, so the reported standard error and confidence intervals won’t be helpful. .. _bound_constraints: Bound Constraints ----------------- *Simple-variables* can have a :ref:`domain `. Fitting method ``mpfit`` (Lev-Mar implementation) and the methods from the NLOpt library use domains to constrain the parameters -- they never let the parameters go outside of the domain during fitting. In the literature, bound constraints are also called box constraints or, more generally, inequality constraints. Now a quotation discouraging the use of constraints. Peter Gans, *Data Fitting in the Chemical Sciences by the Method of Least Squares*, John Wiley & Sons, 1992, chapter 5.2.2: Before looking at ways of dealing with inequality constraints we must ask a fundamental question: are they necessary? In the physical sciences and in least-squares minimizations in particular, inequality constraints are not always justified. The most common inequality constraint is that some number that relates to a physical quantity should be positive, *p*:sub:`j` > 0. If an unconstrained minimalization leads to a negative value, what are we to conclude? There are three possibilities; (a) the refinement has converged to a false minimum; (b) the model is wrong; (c) the parameter is not well defined by the data and is not significantly different from zero. In each of these three cases a remedy is at hand that does not involve constrained minimization: (a) start the refinement from good first estimates of the parameters; (b) change the model; (c) improve the quality of the data by further experimental work. If none of these remedies cure the problem of non-negativity constraints, then something is seriously wrong with the patient, and constrained minimization will probably not help. Setting the domain is described in the section :ref:`domain`. For a convenience, the :option:`box_constraints` option can globally disable (and re-enable) the constraints. .. _fitting_cmd: Fitting Related Commands ------------------------ To fit model to data, use command:: fit [max-eval] [@n ...] Specifying *max-eval* is equivalent to setting the :option:`max_wssr_evaluations` option, for example ``fit 200`` is a shorthand for ``with max_wssr_evaluations=200 fit``. Like with all commands, the generic dataset specification (``@n: fit``) can be used, but in special cases the datasets can be given at the end of the command. The difference is that ``fit @*`` fits all datasets simultaneously, while ``@*: fit`` fits all datasets one by one, separately. The fitting method can be set using the set command:: set fitting_method = method where method is one of: ``levenberg_marquardt``, ``mpfit``, ``nelder_mead_simplex``, ``genetic_algorithms``, ``nlopt_nm``, ``nlopt_lbfgs``, ``nlopt_var2``, ``nlopt_praxis``, ``nlopt_bobyqa``, ``nlopt_sbplx``. All non-linear fitting methods are iterative and evaluate the model many times, with different parameter sets, until one of the stopping criteria is met. There are three common criteria: - the maximum number of evaluations of the objective function (WSSR), (option :option:`max_wssr_evaluations`, 0=unlimited). Sometimes evaluations of WSSR and its derivatives is counted as 2. - limit on processor time, in seconds (option :option:`max_fitting_time`, 0=unlimited). - (Unix only) receiving the ``INT`` signal which can be sent by pressing Ctrl-C in the terminal. and method-specific criteria, which generally stop when no further progress is expected. Setting ``set fit_replot = 1`` updates the plot periodically during fitting, to visualize the progress. ``info fit`` shows measures of goodness-of-fit, including :math:`\chi^2`, reduced :math:`\chi^2` and R-squared: .. math:: R^2 \equiv 1 - {{\sum_i (y_i - f_i)^2} \over {\sum_i (y_i-\bar{y})^2}} Parameter uncertainties and related values can be shown using: * ``info errors`` -- values of :math:`\sigma_{a_k}`. * ``info confidence 95`` -- confidence limits for confidence level 95% (any level can be choosen) * ``info cov`` -- the *C*:sup:`--1` matrix. * ``print $variable.error`` -- standard error of specified simple-variable, ``print %func.height.error`` also works. .. admonition:: In the GUI select :menuselection:`Fit --> Info` from the menu to see uncertainties, confidence intervals and and the covariance matrix. .. note:: In Fityk 0.9.0 and earlier ``info errors`` reported values of :math:`\sqrt{C_{kk}^{-1}}`, which makes sense if the standard deviations of *y*'s are set accurately. This formula is derived in *Numerical Recipes*. Finally, the user can *undo* and *redo* fitting: * ``fit undo`` -- restore previous parameter values, * ``fit redo`` -- move forward in the parameter history, * ``info fit_history`` -- show number of items in the fitting history, * ``fit history n`` -- load the *n*-th set of parameters from history * ``fit clear_history`` -- clear the history Parameters are saved before and after fitting. Only changes to parameter values can be undone, other operations (like adding or removing variables) cannot. .. _levmar: Levenberg-Marquardt ------------------- This is a standard nonlinear least-squares routine, and involves computing the first derivatives of functions. For a description of the algorithm see *Numerical Recipes*, chapter 15.5 or Siegmund Brandt, *Data Analysis*, chapter 10.15. Essentially, it combines an inverse-Hessian method with a steepest descent method by introducing a |lambda| factor. When |lambda| is equal to 0, the method is equivalent to the inverse-Hessian method. When |lambda| increases, the shift vector is rotated toward the direction of steepest descent and the length of the shift vector decreases. (The shift vector is a vector that is added to the parameter vector.) If a better fit is found on iteration, |lambda| is decreased. Two implementation of this method are available: one from the MPFIT_ library, based on the old good MINPACK_ code (default method since ver. 1.3.0), and a custom implementation (default method in earlier fityk versions). To switch between the two implementation use command:: set fitting_method = mpfit # switch to MPFIT set fitting_method = levenberg_marquardt # switch to fityk implem. of L-M .. _MPFIT: http://www.physics.wisc.edu/~craigm/idl/cmpfit.html .. _MINPACK: http://en.wikipedia.org/wiki/MINPACK The following stopping criteria are available for *mpfit*: - the relative change of WSSR is smaller than the value of the :option:`ftol_rel` option (default: 10^-10), - the relative change of parameters is smaller than the value of the :option:`xtol_rel` option (default: 10^-10), and for *levenberg_marquardt*: - the relative change of WSSR is smaller than the value of the :option:`lm_stop_rel_change` option twice in row, - |lambda| is greater than the value of the :option:`lm_max_lambda` option (default: 10^15), which normally means WSSR is not changing due to limited numerical precision. .. |lambda| replace:: *λ* .. _nelder: Nelder-Mead Downhill Simplex ---------------------------- To quote chapter 4.8.3, p. 86 of Peter Gans, *Data Fitting in the Chemical Sciences by the Method of Least Squares*: A simplex is a geometrical entity that has n+1 vertices corresponding to variations in n parameters. For two parameters the simplex is a triangle, for three parameters the simplex is a tetrahedron and so forth. The value of the objective function is calculated at each of the vertices. An iteration consists of the following process. Locate the vertex with the highest value of the objective function and replace this vertex by one lying on the line between it and the centroid of the other vertices. Four possible replacements can be considered, which I call contraction, short reflection, reflection and expansion.[...] It starts with an arbitrary simplex. Neither the shape nor position of this are critically important, except insofar as it may determine which one of a set of multiple minima will be reached. The simplex than expands and contracts as required in order to locate a valley if one exists. Then the size and shape of the simplex is adjusted so that progress may be made towards the minimum. Note particularly that if a pair of parameters are highly correlated, *both* will be simultaneously adjusted in about the correct proportion, as the shape of the simplex is adapted to the local contours.[...] Unfortunately it does not provide estimates of the parameter errors, etc. It is therefore to be recommended as a method for obtaining initial parameter estimates that can be used in the standard least squares method. This method is also described in previously mentioned *Numerical Recipes* (chapter 10.4) and *Data Analysis* (chapter 10.8). There are a few options for tuning this method. One of these is a stopping criterium :option:`nm_convergence`. If the value of the expression 2(*M*\ −\ *m*)/(*M*\ +\ *m*), where *M* and *m* are the values of the worst and best vertices respectively (values of objective functions of vertices, to be precise!), is smaller then the value of :option:`nm_convergence` option, fitting is stopped. In other words, fitting is stopped if all vertices are almost at the same level. The remaining options are related to initialization of the simplex. Before starting iterations, we have to choose a set of points in space of the parameters, called vertices. Unless the option :option:`nm_move_all` is set, one of these points will be the current point -- values that parameters have at this moment. All but this one are drawn as follows: each parameter of each vertex is drawn separately. It is drawn from a distribution that has its center in the center of the :ref:`domain ` of the parameter, and a width proportional to both width of the domain and value of the :option:`nm_move_factor` parameter. Distribution shape can be set using the option :option:`nm_distribution` as one of: ``uniform``, ``gaussian``, ``lorentzian`` and ``bound``. The last one causes the value of the parameter to be either the greatest or smallest value in the domain of the parameter -- one of the two bounds of the domain (assuming that :option:`nm_move_factor` is equal 1). NLopt ----- A few methods from the NLopt_ library are available: - ``nlopt_nm`` -- Nelder-Mead method, similar to the one described above, - ``nlopt_lbfgs`` -- low-storage BFGS, - ``nlopt_var2`` -- shifted limited-memory variable-metric, - ``nlopt_praxis`` -- PRAXIS (PRincipal AXIS), - ``nlopt_bobyqa`` -- BOBYQA, - ``nlopt_sbplx`` -- Sbplx (based on Subplex), .. _NLopt: http://ab-initio.mit.edu/wiki/index.php/NLopt All NLopt methods have the same stopping criteria (in addition to the common criteria): - an optimization step changes the WSSR value by less than the value of the :option:`ftol_rel` option (default: 10^-10) multiplied by the WSSR, - an optimization step changes every parameter by less than the value of the :option:`xtol_rel` option (default: 10^-10) multiplied by the absolute value of the parameter. fityk-1.3.1/doc/fitheme/000077500000000000000000000000001302634723100150315ustar00rootroot00000000000000fityk-1.3.1/doc/fitheme/layout.html000066400000000000000000000031551302634723100172400ustar00rootroot00000000000000{%- extends "basic/layout.html" %} {%- block extrahead %} {{ super() }} {% endblock %} {% block relbar1 %}{% endblock %} {%- block rootrellink %}{% endblock %} {% block relbar2 %} {%- if next %} {%- endif %} {% endblock %} {%- block footer %} {%- if theme_analytics_id %} {%- endif %} {%- endblock %} fityk-1.3.1/doc/fitheme/side.html000066400000000000000000000015521302634723100166460ustar00rootroot00000000000000{%- if theme_logo %} {%- endif %}

Manual

{{ toctree() }} {%- if theme_wiki %} {%- endif %} {%- if pagename != "search" and builder != "singlehtml" %} {%- endif %} fityk-1.3.1/doc/fitheme/static/000077500000000000000000000000001302634723100163205ustar00rootroot00000000000000fityk-1.3.1/doc/fitheme/static/fitheme.css000066400000000000000000000402201302634723100204510ustar00rootroot00000000000000/* based on Sphinx basic.css and alabaster.css */ div.clearer { clear: both; } /* -- sidebar --------------------------------------------------------------- */ div.sphinxsidebar form { margin-top: 10px; } img { border: 0; max-width: 100%; } /* -- search page ----------------------------------------------------------- */ ul.search { margin: 10px 0 0 20px; padding: 0; } ul.search li { padding: 5px 0 5px 20px; background-image: url(file.png); background-repeat: no-repeat; background-position: 0 7px; } ul.search li a { font-weight: bold; } ul.search li div.context { color: #888; margin: 2px 0 0 30px; text-align:left; } ul.keywordmatches li.goodmatch a { font-weight: bold; } /* -- general body styles --------------------------------------------------- */ a.headerlink { visibility: hidden; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink, caption:hover > a.headerlink, p.caption:hover > a.headerlink, div.code-block-caption:hover > a.headerlink { visibility: visible; } div.body p.caption { text-align: inherit; } div.body td { text-align: left; } .field-list ul { padding-left: 1em; } .first { margin-top: 0 !important; } p.rubric { margin-top: 30px; font-weight: bold; } img.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } img.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } img.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } .align-left { text-align: left; } .align-center { text-align: center; } .align-right { text-align: right; } /* -- sidebars -------------------------------------------------------------- */ div.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px 7px 0 7px; background-color: #ffe; width: 40%; float: right; } p.sidebar-title { font-weight: bold; } /* -- topics ---------------------------------------------------------------- */ div.topic { border: 1px solid #ccc; padding: 7px 7px 0 7px; margin: 10px 0 10px 0; } p.topic-title { font-size: 1.1em; font-weight: bold; margin-top: 10px; } /* -- tables ---------------------------------------------------------------- */ table.docutils { border: 0; border-collapse: collapse; } table caption span.caption-number { font-style: italic; } table caption span.caption-text { } table.docutils td, table.docutils th { padding: 1px 8px 1px 5px; border-top: 0; border-left: 0; border-right: 0; border-bottom: 1px solid #aaa; } table.field-list td, table.field-list th { border: 0 !important; } table.footnote td, table.footnote th { border: 0 !important; } th { text-align: left; padding-right: 5px; } table.citation { border-left: solid 1px gray; margin-left: 1px; } table.citation td { border-bottom: none; } /* -- figures --------------------------------------------------------------- */ div.figure { margin: 0.5em; padding: 0.5em; } div.figure p.caption { padding: 0.3em; } div.figure p.caption span.caption-number { font-style: italic; } div.figure p.caption span.caption-text { } /* -- other body styles ----------------------------------------------------- */ ol.arabic { list-style: decimal; } ol.loweralpha { list-style: lower-alpha; } ol.upperalpha { list-style: upper-alpha; } ol.lowerroman { list-style: lower-roman; } ol.upperroman { list-style: upper-roman; } dl { margin-bottom: 15px; } dd p { margin-top: 0px; } dd ul, dd table { margin-bottom: 10px; } dd { margin-top: 3px; margin-bottom: 10px; margin-left: 30px; } dt:target, .highlighted { background-color: #fbe54e; } dl.glossary dt { font-weight: bold; font-size: 1.1em; } .field-list ul { margin: 0; padding-left: 1em; } .field-list p { margin: 0; } .optional { font-size: 1.3em; } .sig-paren { font-size: larger; } .versionmodified { font-style: italic; } .system-message { background-color: #fda; padding: 5px; border: 3px solid red; } .footnote:target { background-color: #ffa; } .line-block { display: block; margin-top: 1em; margin-bottom: 1em; } .line-block .line-block { margin-top: 0; margin-bottom: 0; margin-left: 1.5em; } .guilabel, .menuselection { font-family: Helvetica,Arial,sans-serif; font-size: 90%; } .accelerator { text-decoration: underline; } .classifier { font-style: oblique; } abbr, acronym { border-bottom: dotted 1px; cursor: help; } /* -- code displays --------------------------------------------------------- */ pre { overflow: auto; overflow-y: hidden; /* fixes display issues on Chrome browsers */ } td.linenos pre { padding: 5px 0px; border: 0; background-color: transparent; color: #aaa; } table.highlighttable { margin-left: 0.5em; } table.highlighttable td { padding: 0 0.5em 0 0.5em; } div.code-block-caption { padding: 2px 5px; font-size: small; } div.code-block-caption code { background-color: transparent; } div.code-block-caption + div > div.highlight > pre { margin-top: 0; } div.code-block-caption span.caption-number { padding: 0.1em 0.3em; font-style: italic; } div.code-block-caption span.caption-text { } div.literal-block-wrapper { padding: 1em 1em 0; } div.literal-block-wrapper div.highlight { margin: 0; } code.descname { background-color: transparent; font-weight: bold; font-size: 1.2em; } code.descclassname { background-color: transparent; } code.xref, a code { background-color: transparent; font-weight: bold; } h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { background-color: transparent; } .viewcode-link { float: right; } .viewcode-back { float: right; font-family: sans-serif; } div.viewcode-block:target { margin: -1px -10px; padding: 0 10px; } /* -- math display ---------------------------------------------------------- */ img.math { vertical-align: middle; } div.body div.math p { text-align: center; } span.eqno { float: right; } /* -- printout stylesheet --------------------------------------------------- */ /************ end of basic.css ***********/ /* -- page layout ----------------------------------------------------------- */ body { font-family: Georgia,serif; font-size: 16px; background-color: white; color: #000; margin: 0; padding: 0; } div.document { width: 940px; margin: 30px auto 0 auto; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 220px; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #303338; padding: 0 30px 0 30px; } div.footer { width: 940px; margin: 20px auto 30px auto; font-size: 14px; color: #888; text-align: right; } div.footer a { color: #888; } div.related { width: 940px; margin: 15px auto 0; padding-left: 220px; text-align: center; } div.sphinxsidebar { float: left; margin-left: -100%; width: 220px; font-size: 14px; line-height: 1.5; } div.sphinxsidebar a { color: #555; text-decoration: none; border-bottom: 1px dotted #999; } div.sphinxsidebar a:hover { border-bottom: 1px solid #999; } div.sphinxsidebarwrapper { padding: 18px 10px; } div.sphinxsidebarwrapper p.logo { padding: 0; margin: 0; font-style: italic; } div.sphinxsidebarwrapper h1.logo { margin-top: -10px; text-align: center; margin-bottom: 5px; text-align: left; } div.sphinxsidebarwrapper h1.logo-name { margin-top: 0px; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: 'Garamond', 'Georgia', serif; color: #555; font-size: 24px; font-weight: normal; margin: 0 0 5px 0; padding: 0; } div.sphinxsidebar h3 { margin-top: 15px; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #555; } div.sphinxsidebar p.logo a, div.sphinxsidebar p.logo a:hover, div.sphinxsidebar h3 a, div.sphinxsidebar h3 a:hover { border: none; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { list-style: none; margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar ul ul { list-style: square; margin: 0 0 0 20px; } div.sphinxsidebar ul li.toctree-l1 > a { font-size: 120%; } div.sphinxsidebar ul li.toctree-l2 > a { font-size: 110%; } input, textarea { color: #000; background-color: #fff; } div.sphinxsidebar input { border: 1px solid #CCC; font-family: sans-serif; } div.sphinxsidebar hr { border: none; height: 1px; color: #999; background: #999; text-align: left; margin-left: 0; width: 50%; } #searchbox { margin-top: 25px; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6, span.h1 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } div.body h1, span.h1 { margin-top: 0; padding-top: 0; font-size: 220%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: #DDD; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #EAEAEA; } div.body p, div.body dd, div.body li, div.body blockquote { line-height: 1.4em; } div.admonition { margin: 10px 0px; padding: 10px 20px; background-color: #fcfce0; border: 1px solid #ff9; } div.admonition dt { font-weight: bold; } div.admonition dl { margin-bottom: 0; } div.body p.centered { text-align: center; margin-top: 25px; } div.admonition tt.xref, div.admonition a tt { border-bottom: 1px solid #fafafa; } dd div.admonition { margin-left: -60px; padding-left: 60px; } div.admonition p.admonition-title { font-weight: bold; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-top: 5px; margin-bottom: 0; } div.highlight { background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.seealso { background-color: #EEE; border: 1px solid #CCC; } div.topic { background-color: #eee; } p.admonition-title { display: inline; } /*p.admonition-title:after { content: ":"; }*/ pre, tt, code, div.admonition-cli p.last { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } tt.descname, tt.descclassname, code.descname, code.descclassname { font-size: 0.95em; } tt.descname, code.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #EEE; background: #FDFDFD; font-size: 0.9em; } table.footnote + table.footnote { margin-top: -15px; border-top: none; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td.label { width: 0px; padding: 0.3em 0 0.3em 0.5em; } table.footnote td { padding: 0.3em 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } blockquote { margin: 0 0 0 30px; padding: 0; } ul, ol { margin: 10px 0 10px 30px; padding: 0; } pre { background: #f0f0f0; padding: 7px 30px; margin: 15px 0px; line-height: 1.3em; } dl dl pre { margin-left: -90px; padding-left: 90px; } tt, code { background-color: #ecf0f3; color: #222; } a.reference { text-decoration: none; border-bottom: 1px dotted #004B6B; } a.reference:hover { border-bottom: 1px solid #6D4100; } a.footnote-reference { text-decoration: none; font-size: 0.7em; vertical-align: top; border-bottom: 1px dotted #004B6B; } a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } a:hover tt, a:hover code { background: #EEE; } /* public domain icon from wikipedia */ div.sphinxsidebar a.external { background-position: right center; background-repeat: no-repeat; background-image: linear-gradient(transparent, transparent), url("data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2210%22%3E%3Cg%20transform%3D%22translate%28-826.429%20-698.791%29%22%3E%3Crect%20width%3D%225.982%22%20height%3D%225.982%22%20x%3D%22826.929%22%20y%3D%22702.309%22%20fill%3D%22%23fff%22%20stroke%3D%22%2306c%22%2F%3E%3Cg%3E%3Cpath%20d%3D%22M831.194%20698.791h5.234v5.391l-1.571%201.545-1.31-1.31-2.725%202.725-2.689-2.689%202.808-2.808-1.311-1.311z%22%20fill%3D%22%2306f%22%2F%3E%3Cpath%20d%3D%22M835.424%20699.795l.022%204.885-1.817-1.817-2.881%202.881-1.228-1.228%202.881-2.881-1.851-1.851z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"); padding-right: 13px; } /* div.sphinxsidebar a.current { font-weight: bold; } */ /* for math symbols in the text use Century Schoolbook * that is more like LaTeX Computer Modern font. .math { font-family: "Century Schoolbook", "New Century Schoolbook", times, serif; } */ img.icon { vertical-align: text-bottom; } div#download img { margin-bottom: -1px; } div.admonition-in-the-gui p.admonition-title { padding-left: 36px; background: url('mouse16.png') no-repeat 10px 0; } div.admonition-cli { display: inline-block; border-width: 0; padding: 2px 3px; //background-color: transparent; background-color: #999; border-radius: 6px 6px 6px 6px; margin-top: 0; } div.admonition-cli p.admonition-title { vertical-align: middle; color: #f0f0f0; background-color: transparent; padding: 1px 8px 1px 10px; font-size: 0.8em; display: inline; } div.admonition-cli p.last { vertical-align: middle; background: #f0f0f0; color: #222; display: inline; padding: 3px 8px 2px 10px; border-radius: 5px 5px 5px 5px; } span.cli-title { display: inline-block; border-radius: 5px; background-color: #999; color: #f0f0f0; font-size: 0.8em; font-weight: bold; padding: 1px 5px; } .quote { font-size: 0.9em; } .quote-author, div.body span.quote-author a { color: #888; } div.screenshot { clear: right; float: right; margin-left: 1em; } div.screenshot p.caption { text-align: center; font-size: 0.9em; } .smallfont { font-size: 0.9em; } div.subscr, div.subscr span.pre { background-color: #EEEEEE; } div.subscr ul.simple { padding-top: 0; padding-bottom: 0; margin-top: 0; } div.subscr { padding: 0px 12px; border: 1px solid #CCC; border-width: 1px 0; } .FlattrButton { text-align: center; float: right; } #contents { text-align: center; display: none; } #expand_features a { text-decoration: none; } #expand_features span.h1 { color: #303338; } img.banner { margin-top: 10px; margin-bottom: 10px; } @media print { div.document, div.documentwrapper, div.bodywrapper { margin: 0 !important; width: 100%; } div.sphinxsidebar, div.related, div.footer, #top-link { display: none; } } @media screen and (max-width: 870px) { div.sphinxsidebar { display: none; } div.documentwrapper { margin: 0; } ul { margin-left: 0; } } @media screen and (max-width: 875px) { body { margin: 0; padding: 20px 10px; } div.documentwrapper { float: none; background: white; } div.sphinxsidebar { display: block; float: none; width: 100%; margin: 0; } div.sphinxsidebar p.logo { display: none; } div.document { width: 100%; margin: 0; } div.related { width: 100%; margin: 0; padding: 10px 0 20px 0; } div.related ul, div.related ul li { margin: 0; padding: 0; } div.footer { display: none; } div.bodywrapper { margin: 0; } div.body { min-height: 0; padding: 0; } .rtd_doc_footer { display: none; } .document { width: auto; } .footer { width: auto; } pre { padding: 7px 5px; } div.admonition { padding: 10px 5px; border-width: 1px 0; } div.screenshot { margin-left: 0; } } fityk-1.3.1/doc/fitheme/theme.conf000066400000000000000000000002001302634723100167720ustar00rootroot00000000000000[theme] inherit = basic stylesheet = fitheme.css [options] github_blob = analytics_id = logo = website = wiki = logo_caption = fityk-1.3.1/doc/fityk-banner.pdf000066400000000000000000000543011302634723100164770ustar00rootroot00000000000000%PDF-1.4 %µí®û 3 0 obj << /Length 4 0 R /Filter /FlateDecode >> stream xœm½I’4)&¶SäZ‹”3Ã1tY˜ukQµt3ñ ñ¸ý>ûíþÓ€ôâoÀ5ýÎgÅŸÖò[÷ÊüâÁoü®a¯ÉúwÅߟÿëÿ÷ ÿãÃ’ð‚\s«{(àü›çú){-OýÉÏo_*¿O-}Jú}Æüùx ¯ß:ÏŸ¤¼· µøÓ<¸R¿øcð{~×½&ÿéŸã³þû û³jýM{ÛÊü­¹ï¡€ûoíí§æß¶½Ôß9övíå§ÐÔNKû˜ž¶âOÒ‹¿ïwì¬þtÀš5^ü1øßÇZ“ÿôïŠñYÿýœÖÔPÞhPpZ†" ö›º¸·{ù=€¾ü£Ö÷&ûñ>~ÿÔ^ü=pZëO÷û‰>zñÇà7~7{MþÓ?+æiýçðYõwåü“ú^‘ÐðÞLù-yþ¤½y\héÀ°j#¾@âO:Þú=ðü}Ê:¹¸Œx­ Ï÷ü¨{AúÓ¿Ëå7ýçö7åDÞ³3´‰y5¼´¦Ÿö›žýïñ[ë2ðýIT"ð“ÊïÜóýWøÂo@i_Nñg{@!~§¡ï~а—â¿|/_òwÙøŽõ[êÏÞ0 ãwà=ûµïÅ%¼¦ýŽ™ ì­Þ«ËñhÿlÞèâ¿Ä÷}Jé·ïê¯ö—åý#~£¡oüÜ's%ñ‡wü†÷’ñ sŸ%ÙÄ3¸º©Œ½°°J26Úâúæ“Ææägœ?5¤÷~¼?»×ó§{Ùí¾XÐÆ¯ø]?Ö’ü—ïåò{þ®_ì­Žr‡ÖÂ6›™cŪ7Y©ÞoÚô·Z×Þ›•ÍÀü§Å¬•ùO½h¿øcð{~×½&ýéß›½ýù†ýYÏÏ#™Û7>°ˆœñhƒ +Ã}ïåàSðÍ µÒ âɆó)ë糡T Z9—ï)D-Î}rÊ„§åw Òzmã 2„€Ûo| ™ÝH™h‰Øü†±NKûž…<à’ Šô;uƒÙ@œ>CŽàÛ=›,@uå€6!·Å­õÀ†ÒþÁýª¾ÿצ¶¥ýÎBÕ`Óðf"Æ6o¨vñî¼÷eƒ…½âÜœ¸àÚ2nC©S2tÿ5–&Ü/{:ß’–8ÁâOdá8„sK¥ŒÇl¨éi|-4-C{{ñ-ÏŠýá8¨ •-C¼eàßÕû»¹ý^Džç¿€…ûýû,*{ }—~à am ¨}` 2ï½½{`4ýìÞ¹ ­JÖ† ì›·K1ª‰‹Ø§»÷g³VȆJ£Øs>WŠæ®ª€r¶äÔ\äschÁk‰Ï=\â(dì$ œJNî‡US÷ß T7T‹0}ãô† žlÔðù$ ¨MûC°8Å$ľí±œÜâŸPÃD=î›ÿ „ËÐÆ€õ«‘ÖNèii¿e:‘siªä¾@ }ÜýÿÃ7?Üâ áoŒœ:ü ±®e×4÷À…!ÞeÊØUH@« 5ŠjÈùõxc㦳 Ͷîä-N¡Þõ'ޏM"0´ÜÏÞÄ9MBÚÓ49·A®Õ Lp€ "@p#s+8)ŸA GÌR~fíßPý{}‚À%P<îÄæý3ü8C‹ÿû¼e.(ÐæÂ{ã>ÍÚt¨$M| ð–æ€ =⟑‡ â\Å'‹mèÙt¶!Š·j{¤mœ3Ù›Ž`l97áÒÇàÆÌlù<ÞT8(zñþ€6©s.\º„¾Á¾Ï/š|8É% ÎÁÝx¸5T¬o# P8qw7¢g² p˜ð±X8¥ó<¤Q×-r6aX21|Ÿ ¶à³9n£6¾€(Ň³9N®äÝ›”ÚàŠ6“sÁ:Áç÷JpÊ@‰¢W%¸k5µPß¾¡ågâ ›¾¸Ø®Ÿ"Á±ÉyòW•üMî@üêþ€Í@È{E.Ã,ú0Ý}Ôpˆq=>ûsE=,ò¦•hi´:ÈÛ%á¶ÝNîÝmVmÛ†!ë`KjòÈ’ç›n7ɹOØ,_ZI=àÞˆµf— •:N·‘ƒs¤ Èœ s¡$„‰aþ²Ê–ÚŸk6_„ª\˜”‰ž. ŠÄç:ôýùŸÔlD5è¸&Ú=¢Ö¨ž p‹ø»&â7ü„^°‰# ½±©k²a`Þª,Ý¿hýÛßâÍrzp ØÍ•SÝÎy¶&÷—o&þÇúбëG;L7ž6Êí"B$Ÿ‹xûgÐDï "67rúѤ9¢_¼*wªÅ€¬iPs° €´!C¿x V8q.°О4¬³/óà!áþ¹¡!f#cSyå\Ø¡{®¨rÃkËÈ ùLá Ù4 C{îþ£Òãé|¤j-nË…ÈW/H#rÿ%xËfS}r 8(O9¾­×Ðþáú3¤Ø,Ajz0 7 o°ArMaË>˜°ææïÆâ0 ^ udë(†>[4 Ú¤ñ8S…ÝoÂls«:QC\£ŒD€<œD“„¸ÏqJBzò\i*‡ÀL½\6 r:} HPÂÇ@™*Á„îä¢ßÀ5[ÖCŒgo¤ßÇHšÖEZp؃¸hšqû…î[p¥fW‚À„l1i@…ʤOIíÔá²€Dºˆlà#úá¶û¸ð¡‰ƒn2y+äéf¤Ð·À!>ã¡vu¯{c‹ª ÐlC{½ ÉOpg*†°°ðž.=–çì¤qC_ÀЀïS b’<›ƒŸ–í¦ŸSTÒ>mhbÝܳ¦Œ?8¨è žK»!h [È—õˆgeŠ•/à2äpÙR|CÔð*ÉyCVžHPŸ [“‡0_©+Ï¿à/“|Œ‚¾€§PÖO—Ô)èeŸ•©B»¢ïneo÷¿èehZÀåø…aNó5R#a>íßôÈ`k¸ŒîÏÆŸ,yd óî# hêØ>2@…gº À$3hä’ÆÙ¦FvðO,ý“d¿pÚKò‡ËŸ ŒÀæN6ô š7üÙ hº%S@ëû‚qD¢þ/+ce:¨ÁÏ6…|´ý43avþÃý¯äª IÂм7RM~/&¢cŸc'ïÔ‹À0:ƒ7£Söàÿ @DÒú<Ë2ù>©Ñ+A\†ï¨S¾oªÙ ß–ƒ“󿜈ÑAùùÙ4ì´æ&éMÖ4®…ªÊ#Ö«°mt€>ƒÒÎóB"?Ÿr@©Ÿ3Òˆ~ܺuôS°Ê,Í*S¤}ås’J¢©$ HœSb¬ò2)–% ¢¦%•é~% òjTç)ìj@óÖ6g­…“«¢,Xˆüb¸ņ’¼vœ à þ†ÍÁ±¤ñÁú^ôÛ'æÆ€·UÙ §›z óPÀŒÎs€òÛÃ%g/ÝŠ“Ésš˜úX’í ( E¡h@®cQ62jºU&}¾äËŒŒÈ[ºaì¤4Ì!›-KoÙ uJ±ÀÉV(+`jÂgÑ(e@£yÚ¹IB!Xˆ‡$üG^A‚%ä(4&>™›AP„GÄã•À.ó|!|’ôÞ$~RdêlÊ|‘ÃÞúzŽSÂ_÷’bE>*ÌáIb8Mr„ˆÓUà™ ?`ð´ÒŠ…Æ¢õk•n ŸÉ;qüIžX0…ä8v¥åŸofZžŽóBx·‚­Ò7+×™"O5}Ðí{'@‰XõçPW‹òH4ŠpQÄ1Ù-Û¨”|^°ç5@¯ .žÁ«¤Ð$ì-ÞÞ–¶†’pŽ ý2‘úû€t¶¥CEÆ‹¡ß?ÙÀÏt‡ãGþ¹“¸é‚?ÉàF©Eü{Ò.t`!9ˆñë¹ýí¤[ƒ@;„¾ï ääøó¬Ü%ØàJeÊåŽR²¶ªôÑŠ§\Ћj!§Ð)†’Lé3:íÌà¼7Ñ_P!Äžw`Õtê#5ÔþzN÷tR’ˆÈóà^‰ß“q\ÚŸÊ¡2ÏËG¼2Ò¢ßßGX?G¦=“©ùöƧIª¤N±¨<|^°<’¯Ju€ƒþy8*.Få¤ðíp—`dvÿÚÂH }!‡Ê~½TC8 ¯vÄÑrs@ÝÈ–(AöŒY=”Üò»"€˜¹ …'>¼‹Yf)Ðo ¤;Y‘­$OÙ¢‘ž¢çŒ\%®¤ð±žâƒ}†mú\õ¸ûU–‚8Ò"ÓÎ,û¡˜, ¬5\ÓŸ××´sÛ@2&Ï% §déGÞm°Ôõ¥8ÎÏksA3lläèo -b Ér¢ÐÁ‰ÅÔaVÞ¹¯eŽƒ4)h’@HGe PÓÁ?¯ @ž³5IqÉd·®‘hß^ÈÍʼn YŒ4A”k] 5•1Ó™¡J/_§ŒO¯ºÏIhå@#w§O«­M©LEõ(›)!ó+=À${ I2(ÌÉâp³W-óÏŠÂ,/°µógå­Ï ¾ÒñÛ~µdî$‚PLì/}Áx©n€åü áEW(I"I™`yò\L_J6Ò.ϨPT96Zh‹/Çs¨›Ùžzƒ\Mš)ŠÔÕvd–ÅÖ²|¹{;ﳟ²3w–Â#Y\1/ ¢, 6€ˆšwXÜU€`²5?Â9Ü%ûp‰øÓ \´X¿œÀ áÇÜÉà>x1I>ЬÉfÒ[*¦é½õbó Úi‚xË—ÌžJG0Ù¸œƒh¿ï ûƒÀtCÿZ%Y*<…å@×3ºà呲¼üÊÄóÔ§ç#"RºIA!1$G„ÙɳɄsù•5 4òBÏöµà¡iùýܶG¡q‚t§ê׆çCîç¸3±›ò‰Ò ª´Û¥Ï—¤¢9÷vÖ‡ —sè,K0½žWe³‚<>€a2—–˜ã‘E)lÿp y?À¶á{óç! ž¹îÍéË/˜ÊÏŠ SïÓæuv ¿V¶KÔKÂ¥Åþ¼@ö ªƒ÷5™~ñkD>ùd¾w½ÕÙ€2½‹’â0«“{1À„ *îÇíh!bÑ*Žubû&aŠHnf go€ „Ùcº'(QQnH¸Ž[Ób”ž­dN~«4'žÜ›"ñ¡ä”ß«y!£@ª•öf0Êú± jÏ"T?¦{ï’f/´SðÅ —2æ¶ÐýÈy`,ÀOåâml2•dÉLh¿à öŽº›~Dß b ,X@¥zá3aâohÊ,Û¨áÆ/ÙÔÂÉ@GsC´ÅHZyœâ“2ó!-î„<@‹ÌbZ,â} mƒ'âÏ5½Ë:’o’”>9]tÞ´á þéÂ_1Ù’üÛÞáé¥K§ÒåÀºµ`*/øreóCïùG[‘ÅÖIXÞ Y`üò§Ëál ’”ôh}Elé°@B­Æ§ÁP,2·­röý‡‹+/%ñÁÃF¦|`­9É„ ŠZ‹3øåÜ‘¯ç]å_@ÌAxÓ ˆ[½‘ìÚ( ~’c>H…Ë*ÊdÅEî0ƒŽ`„ób€aº13åC–f`×K‰º¶dT¥¿cœòŸ$"4ì¢Fʲb‹‰D"MÑ œG‰£ºFñ¼›Þô¬nìËrP×6AÅ…Ž(¿2é½ hÇ6f:*üI¶ã {ÛŸ3 #AJœÈÐÎ$Ç×tH83VªLë-:= å‹ïëÌùÙp9´[»w¹|q)èéÉÜôçÞh%\ŸÝá&V힘í`›þ8Î'v¾(vÇ|`ÑCQ#ëó‚•Êv”»Î?o+LK¾žb¾x/“ìFçL2i—î\À'²;kmþØ)ndÕPáÌ¢aŠÍ™LÿMÚL3±"!Á£kRp«P!—‰½¦ aˆßkœö¯Sýؽ,‘'§ê›I?cVIó˜u´T8Ä.ö—€;lþÀÒÞ#™7ƒ¸ø@‚Ú]ʺڢ<ÉzLUx zq0©VÕ’U¾£âÐ2¸÷y—ÚE«ƒ°ê^²à€Ïš !!ÂkWCZ™ÐHÒK¦ç'½i:>¢(DÓá]¤C³µ*°OÚý•1ŸÒ7*$Ck….Œj¯ÞqBÔLù÷yM Ç*UÍ’™Í9`³ÊÒ¸QXj¯&³· º*‘®(b Ð’†¹3³=¾g€átèd5…„F,\¤ìù¬NbBøµ*3s†ªò±ÀGeéת¦ŸïšÎ˜_MªKŽ›òkš½WÓ_+G 6›àj/M§ÊÛU”ëÅÍ+R8*GG‰ß8JîÇhYÂÛÅ M•»ùDiªRð¹7ÌU²º£@fØGÄ Þ»x^$‹˜°ð‚½5¦7º*$ÏBËi×} " ç=å Ѽ}³Ú‹ùÐef¼ä·3Þ‰/GyÀcKh˜KÀß÷ÞãaÒÖ)êé“zè 7šeùƒì·D: @â˜oñ  Ž@9ô>„åGì^ýC¾Oí½ŒÂ~dÇ]0yë5†ƒL@þù¤Ƽ·ú„¡òSøTo¥’1a‘+m'gs>vÃŽGÚq¤G¢™áä¨ß°&‹úR‘¸Ê©ä–)η­aé †ô3=®ÚÉÆ 2¹_Ó__î7Ű&ù×aͤ°?œ›Ê^í ê( ÌÜJ˜èªP:e«2Á ~9ÀÔïמ0ªƒ  0@#º1ˆIp¤Ø,.ÇüÔQ—Ú£`µ0IT\bÑSøÀC—=þD†"•¾ÊjFðDÙ‘UYú¥zÿ•Ë y¡Ï5;ãyQ*AUTšå1˜?$²£ûHR;+êÔ§<Ý +èPn.9êžò(ùa˜¨ jö«ÔéÙz¤$U…ѨèÝS½ ’í÷ªÜÕ"¿zªK?}ÜC{Ê>T½db9°=8U'4c$Éa ÂGÒÃ'ß ‡Ì®Â!5kAÍ™2¬šSÕ0ÐåGŒç¬KS9T€Ÿ‹)wm € D3$Ք⠢–ï¿§h„ª‰™áëA8Êað}èãX˦Ï&¯T–ÜG3é|´ÏMé»a¹^P¥‘¯†!› :|^x™ãzò?â÷&ßgoüºó\cÏž(ÞâJÇûyX¼4p²'TÍöv2ÑTéö ¤iö#¯EÐþŠè“²M—Âåu<‘1,¥.¹6ïó!ç%ÃÅäŸo§ÉžõO4ý( ù~è¶j°äSv(࣠Ý#°ÊÏÙîRèºtlSuÎG*sÒSþO”žN ŒaGŸ4mÀl¯ñ؆ÆëÆîsò€‡n~ò ªçäXSÞ X+§®ÉŠêãk{dˆ§ô¸§jaGY$q@y£ý¼8>]UeBk4Ê•µEBca@NÊ@Ž2@U.íªeÝw†XÑ”âC[kýelÝú'ø:ªóì5ÄßV`Í) M¾aðkÈò¦[‹Zñ¨¾=5¥ÀÑÓG¶Td>¸ÇH+‘u\ÊÉ1‰ÿ, ;AT}Ëÿ”[ÂiÅsh%ŽH·!w¦‘AߊÃ$~œóv  b^"-Àòâ‘VZ}téœÂ`rªÅI¹M=<ìÐd©®2µFšÊæpsTùQÞGËáZc±aq¥°s@øM¨e²ùS†¬áp@ÔÄÊÿ–ºCi9'’5Õ-¼à–c¾YÂë ahŽ©+ÌÄ*žDÈÐ?μ¬Þ"Äèõ+qo±ØÖ¯è‡é*m1ÚbYðL½è T¯_Y"寂›2Ë1)´©Ò ‰S†àc|Aªj ƒû¦ÜŒªú亯6CN6ðm†¤¤ž½O”ÎBVïþ*a£6§VET¥©’…_®r'ðbMàQêíˆ\@ØÕŸlCé5ÐÙò˜zy­Ôì*Ÿ]<»eêÇè l¿=f…Îh`©­D•57FUöµÆ6òmÅÓ•¶™Ò´­j/æ4ÎpI Èà‘çH—"Ô¨é5ÿyé^0vCwVùN! 1˜ª#³û }H I¾S¢vY'¸ßņ­äkºãÏ~<Õ+MYk]† mád:rtAuB‡Ê!ëþÃĆ8*¸7ØÂ°’Ç¢e5×r77(ï¿>l/°ôǹÉ)¢?wž¬õ¤®²7+¬“´Fy9zt''0öòœ™ ]I¦¦´nÃúqÞXWñç>g :6‰ŒUÖ”ºŠTÏ»­†< Šv@Ðü©DƒA’šO(–F‘ÚEp|90T®BÓ¸[„f×ð,®G{ 0zÖ-Á•Ö÷!¬æSNeì[JÜÁj ‡ØÂ·¤rCHøxµ q ½+Gª4W—ªB× æ3ÂÏí?ëÿF–ΡÝ8—æ¤q•³—Ì£%… Ê5D /†îu4°PÂ1ºI¨á¯åÊ{´ÛXÌéªq «’&0© œ å/¨Zá ë».ÿ¹Rk¶žòRµ{²è,Áb'Ï…%·üTÅ ]ÁÑÂÜU¸‚s‡•œì7ŽI)ßú'ìþ}ÃôEgdB’Q¼úH’"Þ•Åg£…Gܨ¥2"ž«‰càÈ5qg“t0¶‡Á–—Ñ©ÈUûâвöMç$ÿ(½`ØfñkzŠ»:àÃj ]êŠ͸W:Ë+ÉŠ9ÖJÖn@+#2XxFd°Q[t‘ד«s©5eå¶È0ï*‰ 5Ä–Ô–*7Ds¢íjen‰¹÷]I€×ÆNWK¬^<¦(ÏK'rÀ@ÆbH­ ˆr1½§«Ù†A-†:]Ñq—®ãù„¶âÎt Ù¨aGŸ´™KMG»Á×Ï3À½q:Í4qU¥(É…‡†7Ãu)̉êiëT,SS )zh«Ù º°6¾` ü£“ëG×GO¢t#C6ÑçڞýȚ—3YÏYs ¹­íwÖ…%OûFä„Wø3@.>#(þ k ¶ä?g Kz½Àç8‚H Cî’F’ŠÇL‘Ž?¸°D‘Ò©âØ$i§¦3@äµú$w{ Ÿð°MæÀÞ/Åz@{7˜©Š“¦k}1GƒUÏÙu‘õé@ÅHÿ‰©Ú„Fà¡âPyõ«£ m(õ 鈞PrcºÙM¢^ÏΠí;Üé,üœŸÄ^\?áæ-Œ[šÂƒE…†¾„™×c¥|¬X\N.å l.»cÓhyQª&£°!‹XðëÚšº´˜!Ú:1öBvÙdB=º¹Õ“bd©¡«w*–“NÜ,ÒBtŒäô@QÔ”˜i”ØpÞò°Ã{y½ýH¡Þ-&&å›cACMRÜòX†Ð3ÑÈÇ®³aãÖÇ)åCå¥U9OdôO PóWº'7·*ÞE1ݯŸfDY•3ø×“˜ð+í!Û)%Èœ?•ÝsÀë:E·ÝÛà¤Ïá²(¾ÍW٩̃WKÌlþšÑr-S‰HÕ{ÈÖÙÛ¼qc¦ŠÇ ¦`íS-O Æ”#6”,Ï2‰é€ßTˆÌ [¡«í÷À­›rWC‹*W¦Œ(všê©RÔw—[ã̤PÉ^*³È;ÝZÜ`ÚØtÆ÷§Ÿ¶Sgä§Ìp¨N1?Àú¾>ßuÒXò,;Ϩ»ÅÀ)u‰ÂTyP‘VJPÝ3)NЋ%©bÁç ÊT\0‡i:ÏÝ}ñ2'Ó…Š„•í6ý¸5z»bc=\Ó)R1¡Š@ºZÉÌÍ+j´ eÙ1à¡ù ýM%®Ä|ùòÏsy”ñ¾qA.G~›; î”ø@2©*ç\4-ï±¢é>K8CšÊ“f‰ ¦«z1 §jøœÔ-–K™Ž4çI|f¢ù[x²[oãjô[ïÚ©éda põ YeUDj”O0üf0F`¦‘Ž<`ò¯ºu¦êŠªø„ujØ9QÚ<í? *U¢­ˆÒǪ, ^›uÉ¿æœM§AOç=7A&§ÒìÄš%li»jf9Ö€~^Sú³C+-*è@¼IñMP¡@QW€UV¾£˜3G<ƒ¼k&ñ®èN2Ù†Ëà—Ïm¸“QϤA3ÅЙiSÁŸOÝd!ˆEð=ü˜Se EýÌ=‡Ðü¦¿®»7–I‚_îËJZ;,­‡OU¸úÞ‚ÿvŠŸ¿ìY{J½¼û ˆ+ÊÑ {†Á {#†­†XÁ° ÛÁ°§<‡aÏàçÁ°Õ’ðpì¢ú®­¾9¶»eŽ=ÃÖÒˆ®Á±§ÔËxF§{pl6ùz3ì)e+öT"N0lù ^ Û=òÞBŸü;8¶š/Žíl‡`È !½9öü•)«ç+8¤ö’…p¶­»Ã°×Iâ'C–btöRÞC<_N 2Ã6øbØwörô#¶]/—aÏG‡aO­à2lÅÐÃ^ [™c/™(Á±ùAIŽOqìˆ×‰@ ~pÖÃÔó;^Š–\v=O\ßø‘z“çÑAgΨ@0ºFk~—]Ÿ±ë©^„â×¹7·&Rf=£à©¥ê­¦òRaÊu’dòo¹6.˜õ f”$nMX®˜`ÖSõÒÁ­I.n<£…³ØµHûÉwˆRq±ëIÁ®G”]Š]w•U~Ü#Å3øu<ìxnûJwÀå‘à×jüÚÆÑå×j¤tøõ°b(† ˜‚õòëe1ÚšG× ÍÒ‚c‹'¾],Û Ø,û&Ë^Œ+Ò†F¥ Í3nåøsÃRëšq«¥^5Ÿ×sÇSÈ–x7jÔ† NV/…âú$0,¦²¨;¥Ÿ+¥˜ù«ýº@Ä(­}E¨ 0úUïË*¯ž!« +Åèêsbx×Wgb`€í¹áL}4½©JK‡Ð£×•M숩Î\ˆ0 ïš\Šj¹F”–;¸‚ÎqsžàŠÎÝ_ÐGhŸý /[œâŒª.a¨š,ñ~O§J\-æI``º`5¦±ãkͨѥª´f”‰mÐmu<@#½{‚ä½ÞñsOäa@9ÚœRDÖ<åÆ9–ß•æÏü‹¥ŽRåñí}º*‘ÙÀËÓ‹ó™ÚîÖ~§æ[Y?ˆÝeSxBÎ&^ZŒÁàmg`úåNšað/.8‹IÊÅffÞš. g"¡¡ÓkîÀÔ›âeQ§¹fô½qK (iŸ€5£˜™I3K7¾€rg` ¯î,â–„¥>ˆ ªëvi¾}‚X:Op^HëÐ/x±®÷ 5ž8UÉ5Û-ž-H÷-sq23º§[Øª× ¦¬yMO‘óƶÜ)]C5WòNÚØGGæ'…ªÀcϵQŒòÙæ®tÀ.˜„¬(gTPH‘ÕÑuÓâSÂûî ÐWkyv çQ*2Ò¡ nósÕd­[|N+!(éñþwéïmmCÈ—r½%»V]žMK¨ªiÂcv©¸È T/ã×ûËã¯Õ?¤zz³ÉYb:oۙ܈ôsºXr°;¿S2ysÉS£;ûS>õôº5ò)]óõüáå>Ó=í˽}2N„Ê™/dž9t|n-'E’èƒUÀqš£]HªÌ…ÙïîQ?B4Ñ`_ÑGÍøO.=Y‚êßô¶ìú6¨Û€ª²XdHÁX‹ }¸À'½A5| ·Æ“O°öõx žƒÙMïæÒëÕðs® èaBì ¢×êÆk^³õdJÍÓ„Û½t!v9¸ùÜ3EøHÚîû‚xK×#4s£ÒK¹MKqØŒú¢"ÒOoÙø’f BNÞlð‚ék$×ìÍÉ)äÊâ¼,š~Â$~×P"{ˆi6**Ħþš`»>ñjˆÇñY™×þt5/RãV|lãÞçø(ñÑ÷Þ³HQR®zã|çl©î1ŠÕQíÓšCÛÓ•B„z€åâEJTÖZìql5Öâhï{i. E:¥¹u:ãc'êJç!†È~V‹9ŠU»ÀÎ?"å¯êŒÜ•Kµ<´¬:à–ï k×ÔM rfŒjÎM=æ_&³@ßô@n¿”ÍQìXŒÖ4ƒ á?¾îà¹Ó|dåò͸idk•N ä}¤Ã¼VCŽ,«H£Ba¬ò9_`UDÉX ¼‡xHâå„oÏu#MüµÕ,»Ïõ.†-\t žŸ¸Z6ýÙ. uá¨×;ó¤P5Á×v†—XéR2€7nHèä‰9IUaýüøÊס®»ù±ÒqÏ…á‚!‡HvœW¾ée‘%羫g‚êvðº¬|(ŸªÓ`Â¥†@ƒöNŠ>úÝÆ½F†»°®“Üõ¨é;‹\t³aá'jþöÁÕC¹[IWú …ºº¯œ6Rȼ/R½’.F`¯^ºhʃVxþöéä(ÃÄ]¥˜"ÛJ7þâN]7#¾qÁÁáôÔ›Û¥ÊX‚šÎ:KÂLíRÑ‘œJÚӛ9 »Ù²Žn+ ’/“üÖôª‹ºÎ„4µ7JcÌA½õ|Ìœ-‡üpÂZs¦²zí¤ãËÕuµºZc¨ýq’îGŒÌºn8ÁÔeû5!ûN 湩 2–„C÷ç&«X$°µîÖ›ÞN7MÒ#ß§ ™rüÍè!• ËñAe…™»Ê3‡ôñÔ¶y@ûYîÀxLÞl“Ó„Âw]û¤jÑ ÿqxÏÒ­QBê"­œ·óUo›ouPêTœ‚.Q÷Àñ(¿äñé|Î!—ÕšNd¹ŸòZ"¹5|¦rcÎYrø~‡áâƒá;¯š¢#J1Gœ¥KrRznôU&y”ÿ÷IQ‹ ÷þ×ØÙ´”ƒ¼¼˜ãÀ¯r.Ì&=C^’¤‹Ø|ëkÖã>¯z¹¯æð<ýzÑþh(³—wrõN!<óQá:T£—†‘Ê  œ^ÀWȼq?uw(÷#Å¥â¢N-”ɘÅE“Ãë—†]q¶©wgÊf—ørܤ&„ø‰®R,‚ºk²šª šHœü”™Q× †ùxD¬#%Ceøfý!aSŠ?ñu©½´qkÕŸ;P±¢P{º<ÖW˜NßJìn¬€§8ªK¦Ât¨£‘òñjœ¯?–{ªÏ+«Xßem|YMŽÕ µKâÕUn»ê¦hrÒ`Éñ` Ë²ÊL±Õ“c5œW˜¬=N÷œ”?b5hΔËû¹Ú³‘lÄ÷5ù䪭TG;ñã—Må^ŧõ9˜;oÃjÚ‘á;©$I“NRã˜VÊÄ}-épé›le–¦ÙsC—>&Ýéð›9¥7è[º#ñÏW ÿûóPßtkCyæÝ¼Ùz¼+Õ“Ä©VW‘Û§NP‡ ½q£ÒZ‘û—ªÃå[ XÓ«ïßujÕݼÂq'Fî‘Í—|QÖtŽN•ìðÁ©ù2TåÙòÛ½˜×µ»Jå“5îJJ ò¯ê½`»_6gÜÓ;NèÃC꿞î«ËÙudŽ£}žä;ÒÊ}Îòv› óÜE)óýðb"ó¸”÷èVü'#k¶èØä 5x·xg•ér±öBöªrÚÍû.78cXK±.*\c:>‡£9À,F¡Kˆ±dºÊ¸»n2BïÑ›ê¿eÆ£ª ýµk®¦úEÚûĪŒDÙ«ÌêêST5_¨Çî$gÐGš¾ ÔÔÂ=~òyÚCocêR5‹ s^>O{ôÈ]ârz ~Ïq/#ðÔÝ)I¥Ö׿è÷ùü_üS9—„¦Ñ¯ ªW$H8}“z„è>%»J³‰!ñ.Q§šÄ€Üþ"žs¬ÓéÝO^³aL~²[u8k7WïÆT\Eà÷°(UzX%#²©ÇK©.ÍCê}ïA (]B¯ÓótêΪÊJ'!z ªYø¼;/®éDÛ.§ü/ñAòUœ«ÇvK9hNˆÆ&³©vå>7²If=§ízjÃiÀUÞ*Z Ÿ(íI32²¦;8ïoV»­Ð¾°9Ò%uRê·4HâW=‰fu/ cB ¿/³MqËwãð5Òúä jî'óyÊ¥vÅ7öª‹siBw·ëECx{‹ £w°UYòø]8Š ÎI „È­âWS 9^ZÙPÙ%®2°Å~²ò¯_H Ž 3²ß¦%ìk6âЖ°k:–ùJXF"GHXBå XFMØo—VA”~$,áü’°ŒtÕ#a™›pßG0½$,ãd­ «û‘°L]˜/ Ë6¸ã®d{0‰XÂ)]ËçˆX†|Ö±åîŽ7%»û¯§.M—CG–1@6»ñc]kb ËlÁ–°K2%$ìZ±VqUâWÂ.í Ë+k¯„EV—¾ÌÖ½†ˆ]]-d"#Mà±ÖZÂæ0Oïª »ºj|-`e.>JDËé-]‘MÆDD'Š@`٘äw¤«ÝBº:G/¤ë’áJW'(J¸2ÍŽH¦À×ú£‹V’H)~1EŒ'ÀZ¥[Þçã 9ÀóýtÖ‹!e‰°õHÙÈXùXÌ|¤ìppôSBÊ’úà— 1˵À¼°˜%u?GÌ’úuOûÈÁ[¸}!fÉlì«cÄHéâFGξ@ÉÙ3 9ËMáµ|^)§ä¬V0Cξxcì»`¿¨l1ÃõÊÙåZ5 Ú¥t„¤À¸rå,QP¹òç¹ñFÚ˜£GÐÆÐ´¸Ç¹‰²(ží¼:‚ÖÉÉ!hW„}Ñú%h?g$jÎLž´Ë",íòí4´k¸÷ºmGæ¾í²ŽgAë$×£KÍ…_.foV<_fHÉÑöT_b–$6Ž˜%MÙù®`ÿc'»Åìk@YovÅJÎ’~ËKÎ:µì'ÄìZ¡ÑÏð ”L)ûçÄú‘kä8±“és°Ÿ©McFšÃëDû™ö0…VE©…J`µ×©Â3„ 2/¸?Œ•:r3Zf2KY7Z>ºl^Ñþ )Øo8býe*h®¿½·˜þÁ¤ç*²‘¢ìÄšéWÎF Oól云öá°©#ýünêí2u‡#ýLEéGÄ.¦Gú±ËRqdÕ0ÿK^¥H/<§R§Ò”£L¡§ÛÉß<[ý¤?¯çóú7C .Š“‰K‘~€– õnbÅ5{~–E¡t³a}V¹S®p?±~ü†åÂPÂA7 ñ¥ˆõsÀõø¹8Œõ–A®Ä*ëÁDƒ~]Ùk…úùñÒ.$òF¤dZ´î¦¡~lå W*ñ×ùJR!ˆX?ddD—ߘ÷‰¤&ªGzý3¡ŒˆõT#7ÇúyÐ}`?`«^ðÁM^±~&:Ê禴P¹:RäyVGâÂíL´õÞxB‹H¿r†Óô‹ÐO ?ò:Ͼ—°#§©8gBò·Ä/bª¯áO÷l†4»Óe],%ðFâ`œ_ïkçço+æiÊ¢ýaž£ "æW*u~…ù•ép¼¨—è©<²f¿Ô﹤¨p˜Ÿ´ê,€®#M’›OŠ#Uòc#Ñ~Ì'ê" êçÈ:±~b„\LL8Nè?XC.GþRo¼kN#ØOüå—*U¨;.økìœÏ+ØÏ’ß­Š×ôCÐy`†]ájwû)D°ŸK•+]É™|àÈ-ɵìç|eI0Øÿ‚•ÁÝÝ*M‰Æ=’ìí”pL-ùì_?* ”-P½z]Ö;¬é;=*¢ý@‹ìÒLGí‚ÛŸp?¥°SüøQ>GcH³*%-Âý$[¥D­€â/ú¢:¦œp?I¹ö÷ý¥kE}=ç'ÜDºÎƒ`KA}/ð‹áä§ÙýHF…,ž›ÎšO¼]¤x½BÊ^U,>ÎÑ~i#9¢ùb`'¸oÊU&—ž·cŠòÂçÇä"Ú/:#ÚÏCc»q£èí„`ž=¢ýDŠùÚJ‘çˆh`hDûÿb0µ·ôèªn]¬µ‘:t•A‚ÒòNÃe%É}h`'ÁÐIº‹.ëÖhvq¦_ÏmÑEy„¡õÕà^I]sµÔ¿_ïêª|ŸÍ³åÞ¨ÌL'ÜèÝ$â&ö j>…É}N Õ+éÞÞÆ«!Ûòíéñwº  «³Ûzs¾Î¬®³€!³²òk "{!‘_i>¤<Š>–ŠtD¥“m k>D¢¶ –p*uRÜ2'7YÆo ÁHׄ¡ù°,Ò²Lah$uÇ=ÏU¼ VO¹×]HI=h²ƒîI;æLþ0XXÿè{²2wyQ*š¢—\Y’¨³M)rD9`wïÁ×@1f1ÙCKL”¢6cvò0Þ–ÈÙ¬†ˆ'Ñq)”5óPqUŒöjPIRËN“Q–Ó§ŒU=r$ÕÁ`ŸEñ %ñ˜€ýgß_š5èå¨rÇ‘É!…Ë*Ó¤òƒ¼Y"d÷Qƒçîyh”içyíJù MzÀ öŒ€óÏ'qX sRætDÛ’a•$äWp KBÝJd”×ô%’ö“ÒÌ-¹LH온ýÛ.+VrÆXµ¸wȰ½)ëÑa@Jx¢íí|‘k{']âqlïä[$m{Ã7mI¶wª.7•íªR_ÂöNUylïT#×zp*L£ñ}A[ß8æwª»át§(û;©nØßøõÖ¯ýÕÉÌ´ž|Ÿ p|LÇO5´Ákï¡ÿi-ä‚6ÀYýÆw’O#ŒïÔ">I 0é&™Ï5¾ƒ?ÙøNºU6ŒëÔ# ÍÖwÒ¥íØ6앦á¢Û0¿“:6‡ùíTYYßY*ßçßTÅOž=ÁÜŽñ °Œ—ñ쨖íÍÅ0ÎaãÛŠþ5¾1pmo@2ËtÃyÓÇöƈâ²½/L¾ËCb;2†ÃöæjØJÄÆ·“¯ÂøN#"\6¾Óð-hç¹BL6¾mÏ]ã;ÙÓ!ã; G9hZJýF1HtÅ„.#϶wRüê˜ÞɦLo€Ê#³éÔÍêÚÞŽÅáæÀ¥Mk§Ü„åýÁ€¶JuùVØÞI•×öN*ô´ñ-RÒ¾¬lJË/Û›”˜ñT/Æw*Qü§¤þ‰a|ÔFÒ0º ï;Àl?¿îÆw’nxï¤{Âúaçrµ†yy2¾¹5awÑ+æ²¾±H6ˆ²õlNŸ§ÊØ·õE×õ²¾“ÚF…õ ]E êq¨Ì=ŠFc™²c{3Uð˜Þ©GRvèÒ=<þç9“ylzcæ+Ï>Û@ Û;ÈÒ6ú¦–¸I‰w]ßÇ£Ûû‚¶½c`ÞçÔ_l{)Û›Ž÷ulï8Û[äZÐRº¦÷iy§GšôÇS–±Ë%½OŸ°¼¹­'Í>~ûZÞ©‹«^»g¦ðŠ?§—å ”¨ù˜Þ´DôNÑZþ×öRS£ûXYܲ¼S‹C°å±·åêÉíÍqÂk'@u…aix']Ú†wR9òµ-Î#‘’R‰PÕ„eP†÷…“ŸJ%…@äZ˜Ãy,ït,iZÞ©ú‚ª#}»+®J¬ßö Ë;éúmÖ©ùv¿0¼S\àvž7òOM›ÁÙðNê¼f»ß$—q §Áò„È-YŽÔb™5RCîœýØI·F´Ý}±•¹oäunBž®µ Í-eˆ6äl)*ny„¦cÅ-«iúQܲý¶VÜrh³·m¡¤¸åæ émYõãWoË®0³Þ–í>²ÞvAëm8z`gŽyº®¬·áçÊ8z[vÖoèm9:Å…Þ–åÙ²Ú–OBÕ6€z»Ô¶ '%\PmË=2Æ©¶åp1…ê–Õ¶h‚ÊËà×øúÏãnÌìxVOy$áúãêHBM©Ö¬ŽÌn5å‚SŽR†ŠýˆQÉ|Ê# –ú^œr;£§Wq!•ë# Ë GpÖÝz§<°¾ŽRß«êHBÊɱpD?]IPjXsIQ„­êHØ‘‡ò„Ìë:•?‚Ïã½§d9ªä@±ßQR“öÈ%-Ášy‡/lÿøTé2£q?`”Gæsk’š}æhi™ÄÆ5+\혟Ÿ`¦Íbt’òHŒ(7Z>nttz(v ú”rS¯ÓÐ-yŠ.ÞN*¸œ‰/ì*Q„ZxÞÅAHéÙhcÓuHNY.Õnë3A)U* @#P¡Ê#st·’-.Órzbq{cr.©<’ Ò»™wtîÓŒòÈ\t;`Ry$Á”£>òª@ò ¨Hp/Ç ;õþTTGr@J‘öÅUIªŽÌ%ÐŽÊUTHoÕŸ-,é£Tò‰É]êãóܶÉÇ„š³b-îG!|ªá°¬å‚X‹J#_è )ÇŠf¸`-·6R¿w*çµÕƒ#ëò€Qù`œ‰«£ÿ*yk˜÷u²9"C’.èr´‡Š3¢8’é¸è¹å+›ý9Å‘¹Ü¤8Ÿä£`e^Îíþ þÜB_ÏkÂ+‹ —£¬h <®F)`.ÙEšâ£n¶—ÆYNVæ×ðéäp,Rýyënñðaœ{ˆÍ@3X•GŠSŒ—Ç£(’#W­8ÍÓ£ü‘Œh¤[|ì>V±Ò¢2ðÆb¼¤H\xÌË[¹žð¢ôäÕ‘âõRüÙë°¤ðQžYÒ¤¨Ž”¨RFI[Gй:2GÿÆS™}—uZFã#6ü#U%g—ÓbÂ?‚=nRi™Ç_ÿH\rü#h´]ÇõÄ­eöl°½YÕpGqñ¿ròåá=¯Ü} ¨Ù¬iØ~X»G.h÷H ÿ£Ý#Åv‹Ü#€æ;¬…ŸË7¬UŽëTí¸GŠ¢á)Î]¶¤X¡ ÿHî)Èíĵ+åFµŠ.À¼îì£ÒDé)Ó}ïìÁ¾+rkÿÎ%ÝÈV9ΜŸ Ã7²z¿®^®6k¤*z]#U—lÛ3RŸßúrŒÔÇ6‰ý"õ‰¾.tŒÔÇ·®È’8Þ1­J¼;~‘êø¹ý"õ /ªý"õ #õ Ž.ÇHu4þ8FªïÇÈ…qþ•}BÃ@¯kä_¤ºå³ý"ŸKÈÕ Ç/RŸ(••_—Ø•uÌ)­±g¤¸Õ<#€¤ÓóAðk#%ÿ™ðܘî´ëýå)+òMåYë)î&q|#eFû&1ä9¡t~óA­vþçùÙLçHံs$è<œ#ÅnUï}9ž;GH‰7¬å oÂ9R"[1¼#¸°¦ß°ÀzÃZ´wäÈ;‚÷IÅY~½n ïoè¸Þ‘2ÎúvõZ ï.Ï€Þ‘¸dAÞ_x¼#ÅŽG{GJÔªÊ;Â[†ÛË;R¢Õž¼#q«‘½#¸ñH—Ä<®u´\VšD¸GJt„ ÷Yà lq9á³0»c‰­¸¢+Ã=8.ÿ µÞ³{¤FÛA>®Oäc1h÷H „{$.}´{$èá¸G|ceøGðåõúõ˺Yýw¾:|É?raúG–p`_Ö+²õyí”plEs, Oÿøõ”åZ¶êµCj÷HYÑ~Ê"`Ø,tÕLrkF+3»G|mÇ}9Ïø~Ü„1_Þ‘½Ãä)ò¼ïô;£´Œˆ¿Ð;»Îsd=_јÏ!t;HxMÖk]Дràä§¥^IÑUñ×AR\ž`IÑDòõåñ§…„šÈqÕù]÷XÜ+ßÔ7Ÿ÷øãx‡µp&ëÆµ|Kh?È)(œ#w Dr»A­²þ,nÆcçˆ1ó8Gþ`.•¶š•¥™#™4Š2˜jŽìN&}Vv½Ù˜U½ïsaf™gUF]Í,4­¾‹žðïÇ’í”é\ q¶2ö¤ù.tgëâš­])G±f×Gª…@®ÅÍat72`WDz1ü‰y”@Zzñ&„-ä̓JTJ«.Hî‘PsjSŒ舟×–6¶ ª9jDÜmºêR#k÷CSšöÆI8ýl|o§º—`qŒö†L%nxÒVFù›¶^AgÊìš#x2Zœ”®—Žƒ“óšm) «;îúæÛv¨r¹*«49ÑhÁ»ˆÂ¬Yrby5Ù.µaÊ¡Sž%q8ÊfeyQÇPXXݢƨ¬náëoÄhU)lnQl´¬I“Ãn±0¼6W÷1ϰúòI´µE}OuÈ,ÄNÐ,e¤éÆMƒF ú›ÏsÖÏëϹљùG¯÷+G>º¦ÿ¬{É Úk¶W£|Kóèæ²0¡Zsâµb2XÍè×gÞ(ØçÌäÄ3áÑÏé,ùÄ>˜æ„‰L„ûœ}Í ×Üm–Ï7C• ÍÓ݇ƒHÇ >‘‚F„5ϦpÁÑ<Ûˆ;\„”´îyDÐ'œoís„VÚ爀”´Ï”Ì3RÀBû\ºýhŸÑ™O4›BûŒ«êâé\/íÓ¿x´ÏþD²µÏþÈÓ*í³?¡ØZûÜê"bí³?qMµÏ Zû¼Ô>ûé;(í³G €•Ïî[¨¬|ö«´CŒ÷'Z[ùÄÚ×¼Êg—Ïð(Ÿa„î¹¢FEºçŠ+Ǭ{®`›¡{º"tÏ­À–i(/tÏ©´ûP=§ÛÎYõœº¡äªžC’9TÏ¡ÅÕóÀ¡zž©ž#lx©žÃ|êéû„B󜡩Jõ<í}Cõ\¡‹Š„BGõÄÆ>ó¥zâd"ZXcç,@«žÕ³?‘!@Ø—½Zóìê4p4Ï«ž+"#¡{úàB÷\ÔiBµTíÿK÷œºðL8ëÅל•tuÏ)XèžC¹§G÷ŒÐ`¨ž®½ÕsDêŸ4¨qîX°y&wéQ=›Ã¢R=/ÚÞ˜ší¼’³˜¢“UÏ6ÎÍXMhå~T-G\:ª§¼áŸ×ǘ¤|%?¼—3U#ísœNiŸêôøÒ>ÕÇúhŸÓÍ6´73ªéÐ_ªé¥~®SFÓÄ›.ýéów»êçŠË9†ù^z+Ÿ·Ã"î¹âî¡Ð=oBtO÷{ åÓ—\ísEóy©ŸKÖÊQ?—¬•£~®IýœºKûœ‘=Úç´<´Ï{ãA[z >ÈÂÿãóÿïŸ< endstream endobj 4 0 obj 21843 endobj 2 0 obj << /ExtGState << /a0 << /CA 1 /ca 1 >> >> >> endobj 5 0 obj << /Type /Page /Parent 1 0 R /MediaBox [ 0 0 374.399994 48 ] /Contents 3 0 R /Group << /Type /Group /S /Transparency /CS /DeviceRGB >> /Resources 2 0 R >> endobj 1 0 obj << /Type /Pages /Kids [ 5 0 R ] /Count 1 >> endobj 6 0 obj << /Creator (cairo 1.8.6 (http://cairographics.org)) /Producer (cairo 1.8.6 (http://cairographics.org)) >> endobj 7 0 obj << /Type /Catalog /Pages 1 0 R >> endobj xref 0 8 0000000000 65535 f 0000022236 00000 n 0000021958 00000 n 0000000015 00000 n 0000021934 00000 n 0000022030 00000 n 0000022301 00000 n 0000022426 00000 n trailer << /Size 8 /Root 7 0 R /Info 6 0 R >> startxref 22478 %%EOF fityk-1.3.1/doc/fityk-banner.png000066400000000000000000000254051302634723100165150ustar00rootroot00000000000000‰PNG  IHDR>Ó{—ƒsRGB®ÎébKGDÿÿÿ ½§“ pHYsííw"ÍdtIMEÙ ›†Fç IDATxÚí]gXW~·ÐADXŒ‚Ø{‰X0öˆb öB>[Dšh0¬ ƻػ‚ Dìˆ%HDlqméea—-÷ûAvÜawaY@ÐÌû<>²3gι3÷¾÷Ü{ι,BÁg ÿ:ÄÑ;!My"̧Q'plC×a1X]0`À€ƒªõ9‘!¢¿A|o+åÇb7샱çÀ6oÁ¼y 0øœÉƒ” I‚4%¤(l«Žà6ëN£ŽJ²%Ñ» [®>v£.0üîXl.óö0`Ààs$Éë[^˜’›\– ë°zÖÿNC‘âlniˆ +Ô«÷Í6èöðdÞ> h v]½1ij ŠPA CÉ(¾8óƒü›(ˆ¤/¯0ož ª€º9w#“@xa*@$å[&CÒz¸-] M} 91¥=dÞ< =B“&M0bÄ4lØ©u×ò¤=„,ã±F²â¸c–‘¥ÆúYFL`À "ܸqË—/G÷îÝ‘ššŠ~ýú!##CI.33AAAjõœ>}š©P†½¾^é•H$˜0a^¾|‰FÁÛÛaaaزe ÜÝÝa``™L†]»v¡wïÞU¶Bbbb^ üüü——‡É“'Wícg³±{÷n<}ú`*¶äää(uìÆÆÆ*ÛÊ›7opøða¬_¿^i]D,#==Gźuëðöí[š>6›ÍTö§RËå½!’DšË§'_!ù«X$Ôþœ®Z§LF$Ø#Dtw+óo™¨ R÷µyóf€èè訨(¥óÙÙÙÄËË‹p¹\€¸»»k]?&ȲeËetíÚ•L:µÚô-X°€XYY1[ìììHFF)**"7oÞ$¾¾¾äÚµkÔùëׯÒ¤IÂb±ˆ‡‡¹sçuþîÝ»döìÙÄÖÖ– “&M¢]_]H$$99™DGG“ââbæÅ}$Ôy”<>M |­idPð»%Åù w’äo4WIÅçÆYqvÝßÈ‘# âééYaG„Ò\(äöíÛZ•µcÇ€Lž<ù?û!‘´´4¥ãYYY„Åb‘›7oª½NÊëD‚ƒƒ òêÕ«*Ýsqq1ñóó#GŽ!ùùù´s©©©¤ @yÀG^¼xAýæóùå–«òøáljH$¢{ðàY±bÙ³gÉÊÊÒú¹îÝ»G¼¼¼ˆiÖ¬±··'ÎÎÎdÀ€döìÙ”\`` ¹pቋ‹#:::Jzˆ¿¿?yüø1155%999J2&L 2™Œú˜˜H‚‚‚¨ßùùùdÞ¼yäõë×*ïÕÏÏØÙÙWWW2þ|2xð`²jÕ*¦gÿ¨{Q¶Âóß‚Òш ¢ SP|a:@§;Œæ>…ÞàßÁi=œæý¡Ós ô'þýÑ'ÀÒ7«±{LHH <¸\¹©S§RÿöÛoZ•%Ÿ{OMMýÏX¼GEvv6õ{Æ ð÷÷W’»yó&¸\.¾úê+•zÖ¯_¯äôêÕ+ôïß_mÙ:uÄÇÇk}ÿñññpqqAff&2331sæLìÝ»—:¿gÏܸqCéºýû÷ãÑ£GÔï)S¦Ð·††"<<œ6e' i2R©«W¯†®niv™L†ï¾û§OŸÆ Aƒ ««‹~ýú•»ˆ]Þsy{{£¸¸l6çÏŸG||<‚‚‚àîîNÓéââWWW´k×õëׇH$¢é:t(ÜÜÜжm[XZZ¢¸¸X嚇¢N¡PˆÇKÝô3331dÈèééaÍš5JSaãÇÇÞ½{qùòe\¸p[·nÅ?þÈd2fZés[0—Ä¡äþÖòe‚ØntÚÛ¨!tãcæÂ•J¥HJJ´mÛ¶\ÙÎ;ÃÔÔyyy EFFx<^¥Ê377ÿÏ‘ÇÅ‹áàà€ ()øã?”änܸ֭[SeYL™2={öDçÎáææðôôÄ‚ ԖݰaC°X,huïùùù3f Ž;†Ž;ÒäÝÜÜÀãñ •Ï­HÈË˃‘‘\]]!•JáççGoÙ²%vïÞ… RÇ"##ѵkWê÷–-[Àår©Á‹££#êׯeË–áÈ‘#•z¶–-["44pæÌØÛÛX640À»wïT^gaa@===•çy<žÊ5====dgg£qãÆT[àóù€ùóçãÿûf̘A¾›7oFZZ®\¹B[—yðàlll˜u”Ï‘}úàìÙ³9r$¸\.5rV‡’’ÂÄÄD«{DZcÇ”Ž7jÔˆÖñ–iŸ8q‡f™šššÂËË <@bb¢’û°²²²ðæÍ4iÒb±ýõ¶n-µÞŸ={===x{{£aư³³C¿~ý°|ùrZ‡« ôõõiß¿¡¡¡Ê©§òÈ¡,¹”…múRGGyyy8vìV¯^MÕ‡â·xìØ1899Ñê(M¥ ;;;¦gÿø¨¶,—@ó¹H’T+•’žžw.˜4iôõõáääTéòy]°>š4iooï+C__yyyøùçŸñÅ_¨”ëÚµ+͵Sú÷ïÞ½{#//Om\Žò˜KKKí › [[[¥ãyyyˆŒŒ¤:Z@@#ËÓ§OC&“¡¤äCSýúõqéÒ%üüóϨW¯žÊò „€€@`` ©¸¢Æ£{÷îð÷÷ÇîÝ»±dɸººRß”6ëŠÄ¦”idd¤–<¬¬¬T’ƒâyUäbll¬dãÖ­[pvv¦—|íG"‘ /ˇ©S§¢cÇŽå’ƒO”<8ævKSc‡¯M­’‡‘‘‘FòÆÆÆ8zô(rss1|øp­-ª6öꜶKOOÇêÕ«k,ö¤qãÆ ³³3zõê©TŠääddffÒä&Mš„€€ZG¬ çÎÃÓ§OqæÌ,\¸§NR+ûìÙ3@³fÍ´º÷îÝ»ãéÓ§´cñññèׯš4iBu–ŠïÒËË :u‚i4›ÍÆøñê§h‡N‘ÇÎ;1ašeòìÙ3•Qó{÷î-·*‚™™m]ÈÌÌLí÷ШQ£r;mKKK•çÍÌÌhd*oO´u j°ÿþÇ‹/ •Jqþüy8;;cýúõX°`CŸ#y€£v£NšÝ¯ Øúõ? òPœªÐõêÕ£¦êyÈŸƒBu´Õ•+WâÎ;puuž}ûðþý{8;;+uN„6lØ V—P(ÄÒ¥KqîÜ9Œ5 7oÞÄÊ•+qéÒ%•òèÒ¥ µH[YŒ=sçÎEzz:$ Ñ¿lܸ‘"¤-Z 9¹t;k×®áâÅ‹8vìFE›Ú¬_¿>夃 Â?ÿüƒ€€äää`èС4+hΜ9pww§¦[ ñ¿ÿý´µmÈCþ ò{•J¥Pµ‘‘ÕnTÁÈÈHe”¹™™™’g”™™Í!@>Õ(/·sçÎX¹r%ºtéüúë¯8xð æÍ›{{{†<>Kò ÷ÍŠÕòG­UŠÜüVM[S[ê¼Y>&×ä^gÕ&Mš S§N…££#JJJpêÔ)%‡___øøøàîÝ»*uùùùÁÓÓݺuØÛÛãîÝ»*o‹‹‹qäÈLœ8Që{:t(¼¼¼àææ 88C† ¡dºu놛7obÇŽ˜3g.^¼ Œ;·nÝ¢½÷.]ºTø>Fމ &`íÚµJë"žžžèÑ£Ú·o^½z¡GpppÀ™3gªäuäîîŽW¯^Q¿-,,0lØ0•i]š6mZnŠ’¦M›ªœ’upp@‹ôm¡y<ž’—#‡Ã¡ ææÍ›‡W¯^ááÇxüø1åšÝ¢E †<>j#¸DtÇ—ä¯æ¨‰g‘âk¿ÖjðËĉ 2nܸ0YRBôôôòÓO?QÇÓÒÒHdd$ "OŸ>ýhÏŸ››K>úúúÖhY³gÏ&S§N% (7ÈÒÙÙ™ØÙÙ© ”J¥• È´°° ………ÕÝ\^0âêÕ«Iff&íxdd$õ÷Ó§OÉýû÷+,çõë×ääÉ“~GéééµÒfD"yöìY¹õôøñctݸqƒ”””hô¹zõjZ©D"!l6›ˆÅb&Šïs0—¼‰"…z‘üµú¥¤±F—îÿŠHø×k½R\\\2mÚ´RÞǩκyóæ¤gÏžÄÔÔ”:€p8’ðQîG,Så.^¼¸FËš:u* '³fÍ"111jå222ÈàÁƒÉêÕ«µ.K&“‘V­Z¦å …ÄÄĄЎ›™™©ÌVÀ zQkYu9_8ÀhÆm@&4÷8õ›l:aÉËFÌV'¤R)}:ºuë™L†ÌÌL­½éhØOÔþª œ_Ö©J‘{˜”\TT„;wîàÖ­[xøð!RSSqæÌ™r=x^¿~óçÏãÚµk¸yó¦ÚŽÐÒÒŽŽŽprrˆ#ÊíTk FFFÈÍÍ­ñ5˜Q£FáÅ‹8þ|…ÏÉb±P¿¾öNò¨kŸ „ØØX#,, ;vìÀ¬Y³˜XQå:¡éèùíH_GBš޹X{BçËÁÔï“ Í|iÂEHR€Íâ€mÝÜ–®`7Pÿ²eé ~u²”°MƒÝ¸tZ 85“´¤U«VˆG—.]p÷î]èèè %%QQQˆŠŠÂíÛ·‰„¾Çº‡‡öï߯RçÉ“'1mÚ4%·DU ˆuasœ–-["!!_~ùe-š3`Àà?fyâlˆBçAüä$uLÞŠ›:Bßå€2DQ›PrýW@Z:$€'' º¶zƒ~ƒnOú%â"”DüŒ’¿·£t þJ¶‡¾ëAp¬ºV[e…B\»vr9Œ‰‰½½=!4¯u'tSCCCØØØÀÌÌ vvv°³³C‹-`oo[[[´mÛiiiuf«ÕÆ#!!¡R–G^^Œ«´a >WËC&À¯d)«WjØFsŸ‚eø!rZt{J*Èk¥7lt»Oý.>3 ’çåPŸ gÇ‚Ó@ûµ€‚‚øûû# £5jÔ:t@ûöíÑ¡Ctèн{÷FQQLLL´ÞâtàÀ¸zõ*Ú¶m[. U„„……¡cÇŽ´Ke1yòd*GFFF…SJ‡Æ’%K0bÄ%VRRRéš|ôU‘§ÖíÛ·©¿{öì©1y(ZrâØ·oUWÁÁÁ”µÆ€AY°X¬j÷ÂZYº¯_¿¦%|üÔ‘‘‘¡õÆf*Çâ‰Ú6yÈd2…B­ôš™™•›>þSCÙ­|« ‡¿þú«úɃ¥k É¡`[wW}Þ´9 ÆS$@Míôú º7¨¶@¸Ðûf-Æ, Æž÷Ë¡ªË1°€Á˜ÓàTH0×òÐÖ|TÜšT[ò(Ïòxúô)Õ`ÊÛ\ròHIIÁôéÓ)â°¶¶Æ­[·h)È0P‡¢¢¢j'¹K{eõJ¥R$&&" cÆŒÁªU«P…$uÆÆÆÕJšB«s¶yKyÜ8ö$¯"!ˈÇ̬&=¡ÛiXº*öÁ`±¡×{)¸-]5NOÂ6±†ÁÄ0Hžžƒ8ù déÿ€]¯1ØÖ= ÛyX†¼©”ÊZŠäQ^>,M-ÊèÉdÔIy䡸1’&–‡"yBpøða@»víʬqü‡P\\Lm{û©’G~~>fΜ‰ˆˆÈd24oÞžžžèׯß'[¯r˜››W+yH¥Räåå©Ü§J–‡¢e Ói: \Àè»ûÐ}z=æ«&ÅŽÙ¢t{ýÃ1§ ?ú8t—›× ¸mÆÀ`Ä.yÜ…ÁØóÐ뽴ƈCÑòPŒß¨iËCGG‡Jú§­Žò¦­ã/š7o^)ò£wïÞˆŒŒdˆã3ƒL&Ã¥K—0wî\Œ1‚šÞ”cÛ¶m´œŽ?Ž.]º¨œ¢-))Á®]»ðã?"..Žê諲XNÁÉ“'±`ÁÊéCNeõ¦¤¤`Ó¦MpuuÅ?ü@9‘Ô«W>>>HIIÁ¡C‡`kk«–8¢££±téR 6¬JÙÄb1Ο?ï¾û#GŽÄÇiçW¬XAË÷ÇÀÑÑQ)gDEEañâÅ6l˜ÒÖÂ<O‰<­)@€ÐÐP%¹¹¹Ø´i-ZD½+yY+V¬P’ÏÌÌĆ °hÑ"ÄÇǼ¥Ï Ž= Ñíß yqD˜Wg“ÜâÐtÚê Eë£"—Û²„!o@êÜ|£££Ký®W¯^¥É£}ûö ƒ©©)ÓÛ~F¸uëzõê…»wïÂÃÛ7oÆ‚ hÖ¯å´wï^œ8qß~û-eÊ‘••…¯¾ú ¿ÿþ;ŠŠŠÐ«W/lܸ@ë E"œœœ0þ|°Ùl8;;cþüùq)ê>}:fΜ [[[ìÞ½õêÕ£âÀÆÆººº°°°PÙVÞ¾}‹¯¿þû÷“:„£G"::ºÒ÷ˆ¾}û")) óçÏÇÊ•+áááAÛr—ËåRžŒÞÞÞˆE·nÝHÉ$%%¡oß¾8uêÜÜÜpàÀlÛ¶ ÏŸ?§‘‡¢—çÙ³gi3 'NœÀ•+Wh÷÷×_ÁÙÙVVV˜8q"Ž9BNJJŠRìHPPFŒ?¬ù”ì²ü·Ï‚4© óéš@oðïÐí:³Î5(¹Å¡j»MusŽÕA–––HHH¨ôbž®®.Š‹‹Õ.ÖÿôÓO´ßš’‡")º¸¸|Ômy|´nÝ·oߦàpëÖ-899(ÝK…Ïç£iӦظq#bccñúõkøøøÐt7¦¦¦¸~ý:LMM1gÎ 0õë×ך<<==ÁçóñÏ?ÿà‹/¾À?þˆþýû#,,L‰<6lØ@ÛÃcΜ9pqqÁ/¿ü¢4RWÕNMMMJ‹Wš4i‚ƒƒ©-Ž5…ƒƒîܹCëC¬­­G­9š››ƒÏç#77xðà®_¿Ž+W®`ôèÑÔ½^¾|™ÊzcÇŽÅ¥K—ЪU+J¢ëñóçÏѦMš%1|øpÉ/[¶ ×®]£ƒŠ{ÆÐÈèÝ»wX»v-®]»Fõ Ý»w¯YËCVÁžNÊÄ%…Ì‚0ü‡:Kšâh¼:,mÈPíéuøða\»vM+òPœõõõ…ŸŸ_…)å|Z°°°Pšú±²²¢%åñxàóùسg.\###4iÒ„ö­‚ÏçÃßߟjíÚµCHH’’’´"GÁßßAAATÜ‘µµ5®^½J¹Ú*ê-»ùÇS™†‡Çã©´îMLL”]ËÖEeÚrÙÁ§ºzݺu+¼½½Áår•êÕÔÔ”Fªô4hЀÖÙçççSkAò)I[ÛL‘‘‘èܹ³ÚYCCCš¾ëׯÃÁÁAi&¦FÉC< (.!G|o+$¯nÕ©%ïŒ5>RÜ ¨*«üã¯.ò¸ÿ>fÏž­$¯©E¥HB¡°µµ…¯¯¯ÖŽ ê8€1cÆ`Á‚àr¹´ï˜ÇãáåË—¸~ý:fΜIYÛŠS?aaaøþûï•Y»wïŽ~ýúѦk4ÅåË—1nÜ8¥47nŒñãÇS£"¸|ùr…ä1~üx¤§§cÀ€¸yófÍ“‡,'ÒÄ` $ Äo¯SI1®iÀŸ"y¨ZìªiËCÞ`333©cOž<««+5òRüx4íøUy‚¼{÷K–,AÓ¦MñË/¿hQÏ nàõëט8q"lmm±oß>|ûí·Ø´i­sâñx¸pá¾þúkš‰â äÅ‹*½sä›§iÓ«Ó™œœŒóçÏ+ Ö~ÿýw`öìÙ8tèüýýÕ& -;šJ× 'Ož ¡Pˆß~û «V­‚ƒÇùÿ yIDATO…IDUáñãÇððð@×®]qèÐ!8::bûöí4]<€»»;ÍúQ$¶‚‚L˜0\.›7oÆO?ýÚûiذ!­êë룠 yyy˜5k¸\®R¦o???ìܹ0`mëk…Bj „ÍfãÔ©SØ´iŽ=Š!C† 55µæÈCZAÚvšì»¿ëTƒ’›gÚGU6s’7”Ê’ÇС¥±0ÁÁÁ …ˆˆˆ€££#ÒÒÒ^^^¸qã5=!ÿÐø|~¹»*No………aÙ²eTÂÄÜÜ\¬[·666ðöö®ÒÞâ j;vìÀüùóÑ¿˜™™!++ €ÖÉYXX ++‹š‡WáÊÑ®];¥Ãþþûo|ûí·èÙ³'­³ÓmÛ¶UÒ™œœ gggjÝ@®7//—.]ÂÚµkѼys4hÐñññj;~}}}¥¶‚¶mÛbüøñàñxàp8xóæVäáãã|õÕW033ŸÏ!¤Âze±X´è™3gЯ_?Œ5  „ 55•¦§,y´oßDŸ>}àîîŽ6mÚàôéÓJ‹æ:tÀÎ;±uëVlÛ¶:nff¦r¥k׮طo¼½½±{÷îš#R˜¦¹¬à} Ô‘»¢*Žä˃âÜaUÈCNZ•%1cÆÀãñ0xð`dggƒÅbÁ××ëÖ­C³fͨ¶½{÷ÂÁÁ666èÝ»7BBBÊ%3ù‡îããƒW¯^!00NNN`³ÙÈÏÏǪU«ÐªU+œ;wŽé?Á)+¡PˆÌÌLìܹ.\ÀâÅ‹iSRzzz011¡-–ýÖÇŒƒíÛ·cûöíˆŽŽ†··7¾ùæìÚµ ÞÞÞZ‘ÇðáÆ5kÖ ::[¶lA=àééIyzÉõŠD"H¥Ráþýû˜0a~ùåµy⌕ÚYQQÄb1 €%K–`Ó¦MZ‘GQQD"RRRàãツ„L™2…¦«Aƒ°´´¤Åx‰D"Ú:NQQJJJPPP€Ó§O«´†x<m:www̘1ëÖ­ÃâÅ‹!‹±k×.´mÛ@i.¤) K˨!ØV]À±h¥úJ™ÅgÇ@¨ú¼yiJõæ_3o±HHH€››‚‚‚*ܰ©<äää E‹ÈÊʇÃA\\îܹ¥ÁTšlâ$‰pïÞ=ôíÛWãàB |þ æ“ı‡!¼4(ɧ pì†AßùØ&V´ã%‘ëÕgAè?Fsƒ¥oÆÔ´†°··Ç“'Oª¬gÛ¶mT¦ÍÉ“'£uëÖT܇¦–Pê¦éèèȼ ÐÀѵNS"&]BÑžN|HÉ,¼‡èæÚ •“”DþÆÔr-Y0r,_¾вeË£.—©$ hOÒ7Q(‰ô)ŸŠÞCxÑãy¼½È4 †“¾½ÃÔr-@ Þ¸qcØÙ•î—bmmM"jšnž T’Gɽm©ØóFšt ÒÌÒòÒŒ8 e(,,—ËeȃU$›šIêÕÇꃡ?lKiП:°8ÐÿfØf¶L-׬¬¬pêÔ)XY•ºYß½{@iÖ`m·eÀ€`ëöú l‹6 êÛ–Þ‡]¹Xz¦0šÝîó¶])¯- ¦GB§ó ¦†kC‡ÅóçϱeË :”5΀Ú‚E!ÒŒ§žYæ3•„nŸŸ¡×z-ÒHßÇ2ÁnÔlãFLÍÖQÈd2Æê`À€Aõ‰%‘ å_ƒôßô$œF] ûÕ|pšôbjŠ Pø?tûÛÜ7ª¢IEND®B`‚fityk-1.3.1/doc/fityk-banner.svg000066400000000000000000000145321302634723100165270ustar00rootroot00000000000000 image/svg+xml fityk y(x) curve fitting and data analysis fityk-1.3.1/doc/fityk-logo.png000066400000000000000000000075251302634723100162130ustar00rootroot00000000000000‰PNG  IHDR—>©î pHYsííw"ÍdbKGDÿÿÿ ½§“õIDATxÚí\yTGWÅû$^Ïøy&^Á+}£b<ò¼/¢/ÏàKÔ\^ñ <#‚"Tˆr$Q‰º"JD<Q"hTPQ£¢Êž³;»ÃWP8,»3=½¸»øâÖÛ?`§¦g»ÝÕõ«ªžjů¶°w’Ô{'*6·—¯o¤ŠÊœ^ÃéµÅ©(Õ^Ù_ÆqœF¶Hî_]î_Íø£ÜÖÃðô¦¹WEN«ÔeFkŽ}«ŽófÎée˜(hÓÂLð+r{/ÎÀ:À«bÙ»É%F²6NLÂââÖ’SÈ×ÔC>ÚÔ-ðªEýÃtù*AlÔq³Ë`¾O€°D3v¬¼ªCÑÀ*úàa¯-æ/?2ŠŠà6ðª EöAšÄ"Û;±tSÜFVSþÒ×^•¡¨K •Xd[:”Y]¢š&~ž¼*CÜQ‰EôÒ UÄQµ\Í}ZÉÏÏðöööññY±bEHHHrr²B¡p h ׿Þ ‹úÛ¸² ´ð¶|]A&y5ù)7oÞl×®]53qrrPÕjµÅ—„‘Q·%Qˆ¿-÷„žåª"‡UPØÐD—+±õ²lŸ>}³-ZøùùÉd²ààà)S¦ÔªU ±ìÙ³§¥‹2==]¥R½¾(rE÷õ· ÏsËGùö óˆ ~TÑ£Í#8ú'Wuÿª=¿™Í=Åi¥GÓ¦M•««ëÙ³g¿/,,\¾|¹‹‹ \P黕•·,]ºôuDQ—õ›"°U¹Û²Ñ_gºÌXU¦˾©œ¦ðåŸ;nÜ8ô/¿üRðêÂ… qEž9s†²Á­[·‚þÌ™3_;™£ Ex½w™µT>֞ݨú}’*r¨æØ·ºœk=ºK—.0臼zéÒ%Dñã?¦l044ô===_/¹v>]f´ ·]½¾F0è·nÝÓiР(€i}òä M›±±± ßµk×× Eeh#ÜÜÎvýÉÉÉwvvGLçÝwßÅ勌¦Í„„Pnܸñk„"§UÊýÈtÌ©úsòäIñ7Þxƒ .+¢8þ|š6/^¼ˆú ÃØ#0¢ÓU=ŠúÇYdá¬ÑFCÃݹsg‚ÐŒ3f¸¹¹ýùçŸ4mÞ¹sQ„?l ¡R©tww÷õõ­j‹ªgÄR/>Õ šg6\gÀ¥ý/ê…UTTd©[[iAVS½zu‹è©möÅŸûbla6t–-[£0dÈë6‹,sïÞ½¶F1;;g ˜ñªöQ略F+’ sñññ!=z´u›mÞ¼94 ÝÖ(>xðQǸêù¢ö\ |•³¹-Õ$ùÚt¦OŸC0iÒ$ëº5kÖ„f/^Œßäå奤¤%½víšuÿóçÏÅÀÀÀW"v£¿V¹c€<À­4 QCî¡ÏýËÖs¸< ···ÛÌÈÈÀ‘mÛ¶m¿~ýn¢¥¹yÓš¥\@°åo¾ùæ•@±L ¬¾ §Ø +¶‹|ðÁ0S§NµJ!55ÜÅîÝ»›§G¿Áƒ>|Øê]puuµ´ ¯n%cå¤wïÞ0^^^æ—ÀëKLLTÆŽûÞ{ïåææ ¶p÷îÝM›63ÆxÍñ4`âĉ»víÊÏÏ·Q6l‚)b+ÁHjÏlP=å¯Ë9_X-ÿPSí¬Ù7M{v£¡ [x•æýͤnVÇÍf—ëþ9PlráN:ÁôêÕ ¹38 àX~õÕWú™¼Ì;×üöèèh à Jÿþýí0ß~ûmxV‡¬"§.Ðì›jšHÚ5Ø!ÎÀ¤¬“Ô¬ ¹º–Iá!§S1G˜ä§”Ûºë^¬tç5Í‘#Gp"ãÖ¦M›jââááaÞÈ`Àæ7cÆ ??¿¨¨¨´´´‚‚‚-ZPÒЗ—¡C‡Â³ÜÜÜ$ý °ù– h`•¿ôŠþØœS=-§Ò)kEÓ¿¶òjê߯ «­®¥/°ÌYËå`$ëÔ©#`ðᇂ¿yùòåÚµk×õêÕ£ʰaìç8&Ø Á«0ðgŒ6t¹iÓ¦¼G…"sz5©éé¼!5]…Æx¯®m(,É3è®DZSíD9Ïž=€Ïà›H³fÍfΜóø±iÌ–ßðž>}Jù,Ø A¿];Ú8>9ŠI±oéÒ¥øó.]º$¨°jÕ*T˜I"'_[_ÅË;+½å 0:  Ã{=2™Œ²ÙÀÀ@Ð÷•F¹oß¾ ,–0á‹ öìÙ#¨páÂTX¶l™1„Ÿ}öouL:•EU½Ew'Ž)¢·¨àÙJä­gUE°¥’”]yà”ÍîÞ½oáÝBÉYG6˜999‚ >D¾ÒÇBpâÒÓÓ+Ã4JYø Û=Ü"ï†9·‰T °µЕJ£8bÄÉJ§ž={Z”ë9vìÞþ½¤2zOb…?à’ÀÕF‰ƒÁÙÙ™ÏÌC”W°Y*ak4;¨öâ³¦Ž±3BÅ48½rG±e­¿öeœøQ£FAo?ýôS‚Îûᅢ²fÍÊfŸà-ÿþû¯¤2ºÍbÕÝÝ]2w†¬·uëÖÆ5‚ÉôR¬ßðôº9eT·eï$U‚õäÌ=Uņ¦ìÕ—MàyyyA‡¡ç>úÇ|Êf<¼åúõë’ʸ’Ž=j~éêÕ«ØÎ‚ -¼ù曘+ž={6êƒG–‘‘a§¿C}`À©Ù7•IÝ,VãKÌÔñŸ+Ã=À-ì9Õ“â— ÿÐg‚Î'Ÿ|‚C#æ% ò?¼%--Mbº ¨™ Fݸq#^ '4‚Ř¼tëÖÀ[þƒÑpàÐí… tfÍš…£C6¼‚V.))‰Eà?æW!®òâááÁC8pà@ÉÍØÊ(êŸ\ÓeDÀÂbs8Ísû£ˆA²©ÄzIB"èÙŠyžæ5>>Þä{XÇ<6@'-`X¤{÷î4GJ¬†¢¡è¾*jT…­nm=íÅívFsýßÿ=Aç»ï¾Ã19r$}ËèýôÓO”Þ9Ä07ÍþŠû‚dG¬Œ"x+æç.Ê¢¬²EöDŒ¤¤E À1`è[ÆÝÔßߟ’i˜Ð˜ˆˆã­H!¡…)S¦ š››ÛŽ;´Z­=PTE{êÙÜd»¡ˆOpíh°‚É)1™?>e!2ÆiiLjj*xyyôè‘ä\ä(¸Er¹Ü†(_¤9ªo^ò$ Ø:Þ½{Ó·ìçç·ÀŠ”ÔÄLõ×_ÿfeeaz„þ‘«upƘ¸W`` l‚¢.+Vê}mí†"Ö£’M%ðq—=zз¼e˸eРA”3 ¼!FsüøñÆóô477}ŸóçÏ—V V*óÉ)™LÃZ䱬_¿¾¯¯¯‰×jµçƒ%Âå«ksgÃÂÂ$+üOŸ>#BV3ØŸà–Ž;Jj&''cû˜»@þÎW&víÚ¾™3gN¿~ýðªy”gÆ ƵÅz½þàÁƒ£FrrrâóÞÆ%ÎV@‘½{šŒ¢jç@»­ÅÇãù}Â.’™™‰cË…¾e<BY!ÀgKpmøKcÆŒ1¶“ (**2¹=<<¯š€`)o™`Þ±›V@‘Ó©ÅÔ²—)üåo7ù—XȱØ(i –§%ÄiNP÷f ÄtíڵƎ &±æÍ› &I:„:»wï6¿š˜˜Èw€PæååYÇGÕeFr\i%€}„eY܇‘nÐ:`£è[æOPη’æ:Ç­\¹Ò¸F_L™„„„ˆuöô•`›¬,Ь†STøLÒJó£RÊÐÎú¼+v&þ`ƒ‡ ƒ‰\Êó‹|(“—>PBÈǵ1§"V=U\Z:‹ÏZ¿~=yÊîÛ·O¡PXŒ¢îòN嶘b£»æéE™ÅÐ?LWÇÍRnýŸ|]CUä°’7Ò²L±Ý%''ÇÓÓ“|6 9qâ„¥>‰ƒ£aéOÚ¾};gàkŸnܸA¸e„ ô§´ÊQä˜"ööIí¹ Ý•(}þ?BÆžUÇŽ0›š˜æ§þ£ã’XŽ^L q/„åuíÚ5ôuAÌSölÜ:uŠrž•¡¨Ëˆ0)‡QE4È+D‰´§üE7¿ÀVVyÉÉR0\ÀŸÂ3ë ’µQ‚"sr…XÅ0¤AùXþƒ+É=¾Ä˜ L›6͸p’?¡hÅ“É%Gì…–¯È²ôú! R¸k°0AÁJëÖ­ùo°Œ»·EõÞÉi¥{$¹<ë-€ f3Ú·oÏ¿¼Ùž¥û+ EEHG‰êÐ+Q4ÁRÇkgŤ¨¨O†ð¹*|_$9­aŠbo¯,¯];TŒï¹$'.â?w&&sçÎŤD||<_NˆZŒ"ée²X÷ý‚E¨ã¼EÕ*Ö3:Ä<æÇÉà ¸‹‹ á$‰Å(2§V‘P\×cä/åóFo®³ÊYwi‡*²Èd²–-[òá7úãWT(r,Cxm›Îè³¥®ªº¤N܈r(úâQ‡ÐlÁÁÁ#FŒ€mrÑ"k²”ðEý“«ÊÐÎæ+ x¤ðMz­þáE6[ÆÇÞb‘XÑ–VˆÝp¬†Iò-9³®x­@?l÷ª6‡X]þj¢ŒM!ÇãÇIEND®B`‚fityk-1.3.1/doc/fityk-manual.rst000066400000000000000000000003261302634723100165440ustar00rootroot00000000000000 .. title:: Contents =============================== Fityk |version| - User's Manual =============================== .. toctree:: :maxdepth: 3 intro getstarted data model fit script ref fityk-1.3.1/doc/fityk.1000066400000000000000000000035451302634723100146270ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH FITYK 1 "January 8, 2006" .\" Please adjust this date whenever revising the manpage. .\" .SH NAME fityk \- non-linear curve fitting and data analysis .SH SYNOPSIS .B fityk [\fIOPTION\fR]... [\fIFILE\fR]... .br .B cfityk [\fIOPTION\fR]... [\fIFILE\fR]... .SH DESCRIPTION This manpage documents briefly the .B fityk and .B cfityk programs for nonlinear fitting of analytical functions (especially peak-shaped) to data (usually experimental data). In other words, for nonlinear peak separation and analysis. .br It was developed for analyzing diffraction patterns, but can be also used in other fields, since concepts and operations specific for crystallography are separated from the rest of the program. .br Fityk offers various nonlinear fitting methods, subtracting background, calibrating data, easy placement of peaks and changing peak parameters, automation of common tasks with scripts, and much more. The main advantage of the program is a flexibility - parameters of peaks can be arbitrarily binded with each other, eg. width of peak can be an independent variable, can be the same as width of other peak or can be given by complicated - common for all peaks - formula. .br The program comes in two versions: .B fityk , the GUI version and .B cfityk , the command line version. .br A user manual for .B fityk and .B cfityk can be found in /usr/share/doc/fityk/html/fityk-manual.html. .PP .SH OPTIONS .IP "-h, --help" Print the usage and exit. .IP "-V, --version" Print the version number and exit. .PP Use \-\-help to see the full list of options. .SH AUTHOR This manual page was written by Carlo Segre and updated by Marcin Wojdyr. fityk-1.3.1/doc/fityk.ico000066400000000000000000000005061302634723100152330ustar00rootroot00000000000000 0( @òÿÿÿÿÇÿÿÿƒÿÿÿÿƒÿÿÇÿÿÿ¯ÿÿÿñÿÿÿðÿÿÿðÿÿðÿÿÿñÿÿÿÿÿÿÿÿñÿÿþpÿþ0þ0ÿü1ÿþ>ÿÿ?ÿÿÿÿÿÿÿþÿÿþÿÿüÿÿþÿÿÿPÿÿÿàçÿÿðCÿÿøƒÿÿýÃÿÿÿãÿÿÿ÷ÿÿÿÿÇÿÿÿƒÿÿÿÿƒÿÿÇÿÿÿ¯ÿÿÿñÿÿÿðÿÿÿðÿÿðÿÿÿñÿÿÿÿÿÿÿÿñÿÿþpÿþ0þ0ÿü1ÿþ>ÿÿ?ÿÿÿÿÿÿÿþÿÿþÿÿüÿÿþÿÿÿPÿÿÿàçÿÿðCÿÿøƒÿÿýÃÿÿÿãÿÿÿ÷fityk-1.3.1/doc/fityk_ext.py000066400000000000000000000031651302634723100157750ustar00rootroot00000000000000 import re from pygments.lexer import RegexLexer from pygments.token import Text, Name, Comment, String, Generic from sphinx import addnodes from docutils import nodes class FitykLexer(RegexLexer): name = 'fityklexer' tokens = { 'root': [ (r"'[^']*'", String.Single), (r'[#].*?$', Comment), (r'^=-> ', Generic.Prompt), (r"[^'#\n]+", Text), ], } comment_re = re.compile(r'(\(\*.*?\*\))') def doctree_read(app, doctree): env = app.builder.env for node in doctree.traverse(addnodes.productionlist): for production in node: if not isinstance(production, addnodes.production): continue if not isinstance(production[-1], nodes.Text): continue parts = comment_re.split(production.pop().astext()) new_nodes = [] for s in parts: if comment_re.match(s): new_nodes.append(nodes.emphasis(s, s)) elif s: new_nodes.append(nodes.Text(s)) production += new_nodes def role_ftype(name, rawtext, text, lineno, inliner, options={}, content=[]): node = nodes.strong(text, text) assert text.count('(') in (0, 1) assert text.count('(') == text.count(')') assert ')' not in text or text.endswith(')') m = re.search(r'\((.*?)\)', text) node['ids'] = [m.group(1) if m else text] return [node], [] def setup(app): app.add_lexer('fityk', FitykLexer()); app.connect('doctree-read', doctree_read) app.add_role('ftype', role_ftype) fityk-1.3.1/doc/getstarted.rst000066400000000000000000000220421302634723100163100ustar00rootroot00000000000000 .. _getstarted: Getting Started ############### Graphical Interface =================== That's how the :abbr:`GUI (Graphical User Interface)` looks like: .. image:: img/fityk-with-tooltip.png :align: center :scale: 50 The **main plot** can display data points, model that is to be fitted to the data and individual functions in the model. Use can configure what is displayed and how (through :menuselection:`GUI --> Configure` or context menu). The **helper plot** shows how well the model fits the data. You may have one, two or no helper plots (:menuselection:`GUI --> Show`). By default, the plot shows the difference between the data and the model. It can also show weighted or cumulative difference, and a couple of other things. The helper plot is also handy for zooming -- with left and middle mouse buttons. Selecting a horizontal span with the left button zooms into this span. The middle button goes back to the whole dataset (the same as |zoom-all-icon| in the toolbar). .. |zoom-all-icon| image:: img/zoom_all.png :alt: Zoom All :class: icon The **sidebar** is for switching between datasets, inspecting functions, and for changing function parameters. It also provides quick access to a few properties of the main plot, such as the size of data points. On the main plot, the meaning of the left and right mouse button depends on the current **mouse mode**. Mouse modes are switched using toolbar buttons: * |mode-zoom-icon| *normal mode* -- the left button zooms in and the right button shows pop-up menu, * |mode-range-icon| *data-range mode* -- for activating and de-activating data, i.e. for selecting regions of interest, * |mode-bg-icon| *baseline mode* -- manual baseline subtraction (in may never need it), * |mode-add-icon| *add-peak mode* -- for placing peaks and other functions. .. |mode-zoom-icon| image:: img/mode_zoom.png :alt: Normal Mode :class: icon .. |mode-range-icon| image:: img/mode_range_icon.png :alt: Data-Range Mode :class: icon .. |mode-bg-icon| image:: img/mode_bg_icon.png :alt: Baseline Mode :class: icon .. |mode-add-icon| image:: img/mode_add_icon.png :alt: Add-Peak Mode :class: icon The status bar shows a hint what the mouse does in the current mode. Finally, the **input field** and the **output window** provide alternative, console-like way of interacting with the program. Also, the GUI operations that change the state of the program (data, model, non-visual settings) are translated into textual commands and printed in the output window. .. note:: To save configuration of the GUI (visible windows, colors, etc.) for next session use :menuselection:`GUI --> Save current config`. Minimal Example =============== Let us analyze a diffraction pattern of NaCl. Our goal is to determine the position of the center of the highest peak. It is needed for calculating the pressure under which the sample was measured, but this later detail in the processing is irrelevent for the time being. The data file used in this example is distributed with the program and can be found in the :file:`samples` directory. .. role:: cli-title Textual commands that correspond to performed operations are shown in this section in :cli-title:`CLI` boxes. First load data from the :file:`nacl01.dat` file. Select :menuselection:`Data --> Load File` from the menu (or |load-data-icon| from the toolbar) and choose the file. .. |load-data-icon| image:: img/load_data_icon.png :alt: Load Data :class: icon .. admonition:: CLI @0 < nacl01.dat You can zoom-in to the biggest peak using the left mouse button on the residual (helper) plot. To zoom out, press |zoom-all-icon| on the toolbar. Now all data points are active. Only the biggest peak is of our interest, so we want to deactivate the remaining points. Change to the *range mode* (toolbar: |mode-range-icon|) and deactivate not needed points with the right mouse button. .. admonition:: CLI A = (x > 23.0 and x < 26.0) As our example data has no background to worry about, our next step is to define a peak with reasonable initial values and fit it to the data. We will use Gaussian. To see its formula, type: ``info Gaussian`` (or ``i Gaussian``) or look for it in the section :ref:`flist`. Select :guilabel:`Gaussian` from the list of functions on the toolbar and press |add-peak-icon|. .. |add-peak-icon| image:: img/add_peak_icon.png :alt: Auto Add :class: icon .. admonition:: CLI guess Gaussian Automatic peak detection works in this case, but if it wouldn't, you may set the initial peak position, height and width manually. Either with mouse in the *add-peak mode*, or with a command. .. admonition:: CLI F += Gaussian(~60000, ~24.6, ~0.2) Parameters of an existing function can be changed in the sideber, or by dragging that little square handle attached to each function (you should see a handle at the top of your Gaussian). If the peaks/functions are not named explicitely (like in this example), they get automatic names ``%_1``, ``%_2``, etc. Now let us fit the function. Select :menuselection:`Fit --> Run` from the menu or press |fit-icon|. .. |fit-icon| image:: img/fit_icon.png :alt: Fit :class: icon .. admonition:: CLI fit .. important:: Fitting minimizes the **weighted** sum of squared residuals (see :ref:`nonlinear`). The default :ref:`weights of points ` are not equal. Now you can check the peak position together with other parameters on the sidebar. Alternatively, right click the peak handle and select :menuselection:`Show Info` from the context menu. .. admonition:: CLI info prop %_1 That's it! By the way, you can save all the issued commands to a file (:menuselection:`Session --> Save History`) .. admonition:: CLI info history > myscript.fit and later use it as a macro (:menuselection:`Session --> Execute script`). .. admonition:: CLI exec myscript.fit .. _cli: Command Line ============ Fityk comes with a small domain-specific language (DSL). All operations in Fityk are driven by commands of this language. Commands can be typed in the input box in the GUI, but if all you want to do is to type commands, the program has a separate CLI version (cfityk) for this. .. admonition:: Do not worry you do not need to learn these commands. It is possible to use menus and dialogs in the GUI and completely avoid typing commands. When you use the GUI and perform an action using the menu, you can see the corresponding command in the output window. Fityk has less than 30 commands. Each performs a single actions, such as loading data from file, adding function, assigning variable, fitting, or writing results to a file. A sequence of commands written down in a file makes a script (macro), which can automate common tasks. Complex tasks may need to be programmed in a general-purpose language. That is why Fityk has embedded Lua interpreter (Lua is a lightweight programming language). It is also possible to use Fityk library from a program in Python, C, C++, Java, Ruby or Perl, and possibly from other languages supported by SWIG. Now a quick glimpse at the syntax. The ``=->`` prompt below marks an input:: =-> print pi 3.14159 =-> # this is a comment -- from `#' to the end of line =-> p '2+3=', 2+3 # p stands for print 2+3 = 5 =-> set numeric_format='%.9f' # show 9 digits after dot =-> pr pi, pi^2, pi^3 # pr, pri and prin also stand for print 3.141592654 9.869604401 31.006276680 Usually, one line has one command, but if it is really needed, two or more commands can be put in one line:: =-> $a = 3; $b = 5 # two commands separated with `;' or a backslash can be used to continue a command in the next line:: =-> print \ ... 'this' this If the user works simultaneously with multiple datasets, she can refer to a dataset using its number: the first dataset is ``@0``, the second -- ``@1``, etc:: =-> fit # perform fitting of the default dataset (the first one) =-> @2: fit # fit the third dataset (@2) =-> @2 @3: fit # fit the third dataset (@2) and then the fourth one (@3) =-> @*: fit # fit all datasets, one by one Settings in the program are changed with the command ``set``:: set key = value For example:: =-> set logfile = 'C:\log.fit' # log all commands to this file =-> set verbosity = 1 # make output from the program more verbose =-> set epsilon = 1e-14 The last example changes the *ε* value, which is used to test floating-point numbers *a* and *b* for equality (it is well known that due to rounding errors the equality test for two numbers should have some tolerance, and the tolerance should be tailored to the application): \|\ *a−b*\ | < *ε*. To run a single command with different settings, add ``with key=value`` before the command:: =-> print pi == 3.14 # default epsilon = 10^-12 0 =-> with epsilon = 0.1 print pi == 3.14 # abusing epsilon 1 .. highlight:: none Putting it all together, a line typically has a single command, often prefixed with datasets+\ ``:``, sometimes prefixed with ``with``. In general it is:: [[@...:] [with ...] command [";" command]...] [#comment] All the commands are described in next chapters. fityk-1.3.1/doc/img/000077500000000000000000000000001302634723100141645ustar00rootroot00000000000000fityk-1.3.1/doc/img/add_peak_icon.png000066400000000000000000000005611302634723100174340ustar00rootroot00000000000000‰PNG  IHDRשÍÊsRGB®Îé pHYsttÞfxtIMEÛ 7#a»¼mEPLTE1NkXt’£¹ª‰ˤÔ«á·&âº1ä¿=æÅQçÆTçÇXéÌfìÑuìÒwîØ‹ðÜ—ñÞœóã¬õè¼ÿÿÿ9üntRNS@æØfbKGD|Ѩ˜IDAT(Ï}IÂ0 C-[0CK÷¿*‹¶Þ$¶Þ—œˆü-óù'ß§ r8¦>9|tÃkYžqKéÑ)xG©3Ø W÷ˆ‹»ÃØg¤pªdç–ÂAUÕ^Xý*9"ÕHëR)2"B5ŠŒH&Õ~g‹T`¿l@íKÖ6ß3[äè|Œ§µU¸Û‘J²ø´ßM+Î$‡×’òøÜÎŽ¦ï#IEND®B`‚fityk-1.3.1/doc/img/copyfunc_icon.png000066400000000000000000000011531302634723100175300ustar00rootroot00000000000000‰PNG  IHDRשÍÊsRGB®Îé pHYsttÞfxtIMEÛ¥T¶öPLTE  '''(((222333444>>>@@@IIIJJJSSSTTTXRtYSv[[[^^^b[yr“}}}}£w~~~€€€‚‚‚………†††‹‹‹‘‘‘’’’“““•••–––———™™™šššœœœŸŸŸ   ¡¡¡­­­±±±³É¯ÅÅÅÉÉÉËËËÌÌÌÍÍÍÏÏÏÑÞÏÒÒÒÕÕÕØØØÙÙÙÚÚÚÛÛÛÝÝÝßßßâââãããääääìãæææèèèéééëëëìììîîîïïïñññþþþÿÿÿü .tRNS@æØfbKGDQ”i|*áIDAT(Ï…ÒÇZQ †áó‰4 VÐ3DPAGbÁŠ :# caîÿf\8‹óyÌ2ï&cþ)`^Ÿ¿zIÍ€gK©tÑZoâàˆõ»0ˆdLëTC°Dó~²¯Á_àêx‡ä«ôÁœPÄ[öè‹`~'N&gºAååaìFbš£vwé Ö–R颇1†'V†ï_߇ôDG>k×1îFÆ"B+ dpW6y]Æ¿Ñ‘ÚÆ"Õš†·è’üó†Nw›B½¡!úؤ25œç(7Û>oYŽ"ó®ìþÊÌÆ{†·%IEND®B`‚fityk-1.3.1/doc/img/eq_fwhm_icon.png000066400000000000000000000004521302634723100173310ustar00rootroot00000000000000‰PNG  IHDRY ËsRGB®Îé pHYsttÞfxtIMEÜ".g·PLTE1Nkÿÿÿ1Nk¾ÇÑÿÿÿ1Nkƒ”¦…qñtRNSLf”ÌЂü€bKGDf |drIDATÓc````.@áàøô°8 )ôhA°Y8RŒ U u 06H ‡L‹È (G"HIIµÊñL‚)PN ÔDˆ•0 1°AŒ`y¨V  ”DÔÆŽFG¸Ý"¸ýš·V+?PIEND®B`‚fityk-1.3.1/doc/img/eq_shape_icon.png000066400000000000000000000011071302634723100174660ustar00rootroot00000000000000‰PNG  IHDRשÍÊsRGB®Îé pHYsttÞfxtIMEÜ76²'ÆPLTE£¹£¹ ÿÿÿýýý*+ ,#1&4!4H"6J#.:%1=%2>)AY)BZ*7E1Nk9AJCYpHS^Ld~Ws‘Xt’l{Œ{ŒŸŒ ¶£¹×ÙÚèìñŠBð'tRNS +-.;<=@ABGILSk~ƒ†Ž’”–—˜™¦ÌÍ·ÁçbKGD%ÃÉÇIDAT(Ï­‘çŽ1 „MèýèmZèÕ¡0¼ÿK±Ë-B,9$$æG"Í—±-ÀUßxõ/ø\ßíØ5ûDF‚Äl"Œì—WŸœ‹¼Ä "¬èx"V|/ù˜Ôc¸;IUš:]³â es»¼È\½øÍOˆ:)ÂUû™ï8ÂsBÄ Ñ|y1e鬴¤ÆYDÃ)¶_ÍY‚êaѤ6"VRj°>¸ kY?šg“áxDöŽøiDͶiZsûíç\žð ÐѬ`IEND®B`‚fityk-1.3.1/doc/img/fit_icon.png000066400000000000000000000011511302634723100164620ustar00rootroot00000000000000‰PNG  IHDRשÍÊsRGB®Îé pHYsttÞfxtIMEÛ 7®)ôêPLTE ! ('$640@?:@?;BA#|!` ¨¬&„OŠFñrBIâýã ;™C!Ü!‰ë çÜá±5™á½o看â¦Mó*ï[ Œ‹'GnÙdoß"ôÖqÑÈÀp×&1’h÷×l î¿$y‚’ W¶Ó}Ž%á? 4㥘|ê2ÁÕ1_‚ùÍn»&€Î¯NeHC-JÔ1öܬ@ó†myzª©/McÓ-åjÔÄ?õ§cëQËCIi nª|Æ[!bµ°ñ%@ ÄQ(‚8b±Xˆºvÿ *xxz²?d ;R’ð«T€~ ªòt›öCªZ·…¿ô-ë^r8(á/&¿²‘3gÒ³<€†VÓW²¸ñËT~­1‰‘./y™Ikoa–¼h:v.㚺qeéh&n–°u{$YFS¡ /M™v~&Îþ4…+Α¢æ®ö¦Vû0,'ßçtš:ã—g5åî»÷¡¡¿BÔ¾e|øÙ:.§)€„[Ŷ<ùÌ£t¨ˆ; É‘‡Øøý7üºï6FfLþf,u¹ÉºïÞ«+áîw8üó§,ºÐg‡÷¡¾¿‰ë;–0ëË¿¸n°æÉ-¤5ýžyŒN ‚pÇLìÙmüº` ]JEÉbçl’{Ïç÷gBIþ{*#æžÁ·ç{|< qÞ`Ô7— ê÷!ïÿ/€øo2jÁ9ÈÕÞ&¼>< äk|;ú5~¿© ¯÷#_|˜†å,Ü>¼– I6ñKFVùÑúõ/“kY…0aþxÈ7ÙðÓIÂìDuÓFÞ|yg ù8³ˆš³~`PõRŒÊÞJ—Ç2°SmÊ»–d¢/ìaÙìùìL ¦ç˜WèU/71gw²bÁ"þ¼”ŠR˜2·û=ŠÍ+OQ¥K;ª{¸¹÷'>ýb-çS³æA–U¸WÊ%N4´ð"Out’‡sÖXWµaÚO“‰£Ø´ü8¡];RCoÎëšJ¹ç mPK}úQ:5ª„·Ƹ3¬y?ÜÌj»[¥.ü¯¡8ËçcdzúN½>ZÄÈš èÛ©›~¹ÍÑOFò|²‘c¿ef$$YÊEàsUYFv«L¯œòHÿœÄ×O¯2ny$&ñü@P†(Îé0ßÿý]Ûž|òÉ¥cKÃv^öïA™Gîœø‹Qþ?ðyÌdd•šà˹ªª‰ÂíW0%ÝÆ¯R]tîîyÜ®îÜÌÉ ¨ã ©'7³õR²cºµ ÅHr\'¶n§n¯6T×BìþìŠJ%êàiþ9±‡!m¨Ò©1Þ¿¯#AN»ºnÀ9Öl:G¼1Ä~=•3†·vtÏ|;ŽIß"ÍÍo÷BL÷ð£mM™sŸŸ YÝ C©Ä#Ï»sæø%ýÃhö4CZlgÊßIÈ>M>u÷yAÒÙlŽ ¡MËÆ<á<£œ!]ÎŒfI–Pù6Í5NŽUÄóäÜÐz:‹õ:?p‡M[ÿFÝ­=Õb]Rçžï«MxþÑ´ñ¢ó÷¡[hBÃ(¯N#Ý’ÕvÏ*õ¬ 9Çžæl‚Œ—7ܼ 5ýˆ¨†ÛQ˜t*ܼ=ñÒJvÃ* 9GdßûrUYFÎ-¯þÁigñuøñé Þî*ñ@Pf(îO=õ”ýÿï¾û.Ïëå´?»Ð"F˜î qÄß™å{ðåô)8Ä'èeYFuÏX¾:× ]ƒ^yˆ#)œ]û [›w¢N8Dþµˆ¹âñªÿ÷µ Â@‰åÀêT¹¯ ÕCŒœ]ùs˜ÑȲ÷vĵ¡kh7Ú¬gcp[ê»§ÿ`×m]mh}Eú¼5™rzg¿{׿?ƒÁÝŸlˆ{Ýg˜0¨n¤qráLŸ¾{]ÕÖÔs»ÌÒ£‰ht¶4 ø`onI'bìB¦wö¦RÌ›“ñèI+/ æwÞzísN™ýÙ9q>“ZU s÷J|·@²§±gæh¦î ä¹ùÓ§<į}ƒQs/S÷õ¥¼ÓFGh-=æÝi”‹èEk/àæ/|8w97åòÜ©ú /ÔmFïFžìÞš‚§ƒŽp.½;ÍBšîw–ˆª*Òn&£«ÔŒ0ß(W¸À® ZöΧ½Öiúº]iäÄ­gÊøO8n¦ÇÌùŒ¬-a ‘vv#;âZ磬ÌŸ3’ 뢑4dIŸ-G®s&å¶¶íRjñâîàSm=jÀ”t‡[‘¹zc +ß&Ù¨ ñºÀÒ7&›‚äá‰Ç¶H*~1šzåRÓ}1—¹€ežŠÚÞáO`ã¬÷ùú¸ßz¾z»3>­»PqÁI.:ˆ’¤Â/89–ä–s<Ýñpë©üóþ[|¸O¡:‚™Ý|2b= ­)·|/%®QoZ{I[xkäìMR¡ÕhP)?ǸRãî!®R1ÉZ4*°¤3nB=nг¬AvX72§âˆ„wž±*#ç–íb6¬^A%'ñ¥ÕêÄ"c@ þâȲeËì‚@ÿþýóu½ìûû÷ïoOËq›G÷„8b©ÛŸ…'!tíT…³~ ñBáÄûˆU»£·¯ ¦œ0œ`Ãæó=îFÔÞ•«T)ã›BŒœBªE…g–5´TjÙÏÈUŒS¡ °ýR|‹£’ÑêýSÒoTZ5˜e¼}¬×º}–Ûfw|ôZ"c`tåQ™lƒñ£8}5­§šôŒ%oÄèî…:=СÖj̪Ì4ƒcÖÒDz XUô˜M¦¬vzGrð*4 ¯Ê}MSÍ+‰ýßþIõáiÓ¼ Õu@ä>Î$jñÎË^ƒ½³)I¼Ëë3Ž?C”ɽDLdÔö±NUddãå|–Õ œˆGåí‡ÞM´Tiå˜M)ÆKÖ²7ŸYÁŠ£•y´ÁCƺƒq¨Ý}PÛÓŽaïîtš·lȈé#I™úÇ“,wÙ”ºO?•@L¢13¿ÞþYìALÓF¾ÜÚ¼ŸhI‡§Êv ³E…V£&³*!I )Ñ (!U'À}Qjw«øv;†4³m[ F‹ ­FehÌ&µ› ÉiF¯ç“ÏwkÏŽŒùÎ5 êêÙìLæÂáLÓ>÷£3_æ»ýû±$?Lˇ;¡â! 5Awò²×+Ó’Bjl" ù„àã¦%V­Ã/À3³Ìd YÎoYY}à¦U[Íîou)ÆKv[Œ—ø}ÖK¬”<)\…&ŽbPÓ†ôhÀþ¨! ¼¯2ÄþÍüÏ7pÁ\“g'$ %Éamü–¹µãnÝT=Ñ$«ñà íñ¼ý£r;÷8IOÑðû¬—XuWʳþu±EF£Ve‹u5åÛä–o I·ã­ö7¢ºÏ.¨dd$T’‚9[]~ýQÔ$À¯&á¾*n™ôT ³ÆáíãI–Txfˆ#™! e.ª*é‰hB˜·BÌñ=±ä#VUyäA‚ãK  l‘}Æ’%Kœ7hР¥“}ÛÒ¥Ks<® ö,]º4O{‚2!Ž8rãÂQc!qFvšÆZ»mÁ•!¸rþAIrè`ÉȲbí€Ø::²Œ¬¤“¨@°šˆgF3â|,—þ\Á?7M(wöñçé~ ©U‹Z€éЊ×àî«vè°$q|é vXÞãåûº2vlï¾ÿÓœ¬Æªó¥‚.g»U4+þÝ7AçÆ¡SdûÅÚ±£&ËI'6°/¥&Íý{1åí I®D³Æ:à›~?ƒAÝ)[YYvð‰õíI'6°7¹&-Êwå‘öE¦¡õ¥fýP®5‰«žM²Ùi!öÔiâ Æ'Ø ®îã|ì <®)´«¥ œÝ‰ÙMKJžö6w°’Ïl娡6 þÇ«#$ö¤×¤[ufùfä)eåàGÙ¹¿K+^®øfµÅ»ÞP&<êÉå3׸“¦¢bE«€ŸDšÙ¦u(HºòÔmÞ•êö"u,Ïü–¹c\GëñÓÑŠ#°ICt@âÎ œ7ªPgñ£BÂñõ¹ÆÉÍJÏðæãÎó`ômOÓźƒÍNó-‘xìv'Ö¢•wGÞš]ݧãÑWƼz_œsL_ÂtóoÖœèÁ3uk0ü7h~'&a€ùË×]ÅâæKhçAô®£Ç¯–u ŽËgxµB GVðó^ŽÇBޏ#1 ©ù‰Õ\ó #+©9Æ—@ AY"¿£0 3âÃQØÌk#“˜úéVn òº™rõ[˜xˆ‘Ütê¬×ÈÞaÌXRJ:Ì¢_ӯ뷢5rý k¾ýŠïOÐjîJ#§ï¶Ž³”t˜Å3¾$ú±>tlÙ‡%-š‹Çv°÷J2Þmï¶Ótë— ‰ÐBüÉ“ÄbäÚñ›P+¸ÂžKihÜ|‘ó´WÅ>ö³ðÓU Ü‹úâwv Û$òPo@vèü糬äÌsîöwiÅK*ŸŸh™Å%)’hUWšwk„NLq\Øö _¬¹F”n ?6Nߦíyvt]ŽnÜÍYÓCÔTßý6•ü–y¦}×ùý‡c„õéAE‘›{¾ã£GIsóÆO•ÕRÒ‘\â$´ò9åá¾÷·$¨@±q{¿åÇzÃrÌ·”xŒÅÓçõX:7®G« `Š;Ãï·âH6gK_‰eÇW }ü zµn@³ …ÄË;Xþõ—lˆRáéëŽ_í–´lî°ðs@Z@lÜo,ÛaÉébH!Ý¢Ã-1¯XÍ;¹Æ—JŒ @PvÈ>Rã™gžÉ×qM'¿k„䔎m{öïA©ßCŠ¢(£F¢aƹ{˵øå²øjv† ưaöXH‹‹!Éj/|u2Š1‰Øø4,²Î¾.bL!!1£@Bëã^#!y7ã•YÏQ+}7ÓŸû€#²/zm†ø¢H¸“€5ž~¾¸Ë&RâI6*HO|õîä»?#ùr߸ô‹šÆ°Ù§póóB-9¹†JÁ”G\ŠÉÍo«ø¡˜ÓIIJ!Íh¶íWiÑyzâ¡U!)âï$`´§a&56–d3hôåðÑ‚))–¸4 ²Î?/‡4“SH3˜3^ß«B­ ¤Û;ŸðTv;mþˆIÀ €¬óÅÏK%5–Ød3 ÆËßÍu9Ùëׂñ=O .ðõs“øÛ¬Ç]c ‰å#kt¸IR d7ü2|P ²RçàïÒˆ“¦Å;ÓxÎÁÅœJbb*F“%Ãÿ2j­;^^î¨1‘š˜HŠÁŒ"©Ðê´(i©~¾xÈÆ‚•y…¦Œùh$uå«,1Ž *L©©-*­ÞÞî9Äcq¢Ñâáå‰Fq’·xû#ž,L¬+yä[%ÙíI7˜±’¬Á]¯ÇCe¼Ëv#©Iɤ¦›°²Ú wO/Ü5 `LŒ!>ýn‘Sv÷ÅÏS"-‹O3&3å«ùÉCñ%@PZÌ›7yóæÙû\9‰!y±páÂ2›Î‘#G˜3gŽ(lA‰àtäȳ@VAô±u<湎s©}½¯_/’u¨”Œ‡Ž¸é) Ïz’›~nŽë]xPµU[ÕoG- ¶¯ádª‡õÐáà8OF‹§_ûš)óŒñ5ü°ã4F7w¼ìk0d¿h½ÊàuWo o?wë[UîB‡_–4d<Ëd±S«/Ov— »ãí›-Mµ/f§vfØšmÞʳÎr—½ºŠ-èÚ­;a1§¸*/ë/îröòÌs SV9ú»âE]íÉ5ü˜ÝÙ_ÿœ¢I‹§o¹¬±æíXRª‚•¹œõ-Aj7ÞžÞNc){<:;Nò Öc*t¬ç•ïÜìQÝm;nxú¸åxϺùT —Û6»O!XÍoœ¤!@P–(ÎYK3 ÔÄ‘§÷ð¼Ç"LŠÌ‚3ƒi*¢‚[ ’t‹}‰w\ ŽÖR_êvïK÷@H<½šO–Æ Óg\ˆ%†ÃÖž¢ÁËS‹ª¬.ÂXlvÊx†w¥gË`,±ÇYþÙ/\´hñQ9®=á²ru>Š/e¡ìîIÊ\—…ÿr¬ @ r¤¸^å[Úé¥&ŽHŠ•dáPbEz7TÅ*Hʸ{iîb,;ã·¿Ç‹Ær'ɲ½m~^è²ra>Š/¥\öéÇ™ûÒsÄGÇ[§ø£8rOź@ ÀóçÏÿW¦#”N×¹yr;!uÑûøùY×@ +°­ÍñoE¬9"(Iœ®9T§¸a@ @ ü'°‹#GŽÞ@ @ðŸÃ.޼5ùMá @ @ ” ¦¾ýŽp‚ ÄïW@ @ðŸFˆ#@ @ þÓØ§Õ(Š"¼!@ à?‡9"@ à?G@ @ ü§)ûÓjL×øæÖ|óðf6¿†F”ٽɽ^Ž÷¢ýâÞ>@ ù¢@#G ×Ö1m@{jDH­–t2‹¿c,Åh¡5º=J:Þ¥;ÌE‰eUok¾mŸàMé:`"ó·ßÀïÎÖe¾êX™ö_^ÂX 6Pw,{S‹³Cé$e¥ ë¯ôlö»° trMû§1“§•ñjD!íÊf¿Ð›æ5B¬vWªKÛGF3gÃER ý(SšÓâ½SYïË-¾ïLØóÛI¶—A0¡ƒ6“Xä²t–N2ÿ<_ƒÀî?pË‚@ @ 9’~œÌ\M¦/û˜!Z’®埿NbFñ“ŠÇBɶã?¤­ÕHJm|‹¢  ¡¾ï=~¯%î†db®cóOsy½ïÏlxo=KŸ®Ž6éØÓ+îüØlnù¿¼Ó›Kµå ×*Û`!gy,+åXXéüðp´ß…å8çÏõ$ZR94í Æ_{Žes¢‚ H:kh 7²+Ã.%ãþ..Ÿ§ú’'ºOåpíþŒŸ5––Õü‘“¯sjÏF~}o:u[~M·L!%‹-öÿ3¶;ì+’Í9¦£dµC)>@ ¥K¾Ä7ÝØÎ†ó>üoÆTžîÔ˜:µêѼ댙1…‡+fh,iYõÖã´¨L`P0µ:ã³Ý±˜”N÷ ݆L`¥:´ò ç yì3]ã›®UhûÙû/ô–øƒÌ{±+µƒƒ ªFó~ïðGdÆ^ã9>nS™ö3¿eúSm¨Lp­n¼ºâŠKFj¨ô¡„׬Iíúiýà@^_¸C}Ø2ùuÖFY€tN/ÉC-kZóR±Ý^ZÄÑ$HäÏAíxó¤SSî£RP0µ_fWJnç¸Àfß0ê7lHDƧaí<Ò0¡aYŸy`ÒVרÏèÝ)ùò£’v‘USŸà¾pkyWŠxq¿Ÿe½³<&¸¸s‹™âð—ÅÑ~çåXXª×·]«>á~$ÏPê6°nkP9™ß^¹ß¹òòá]ýbð™é ËÆ¼Ãî“øcÕ,^èÝŽ& êѨÕý<1ê}~Þðôe¼Ì­ÞÊNF\¶ò9ãû4§vXeBôbâê«Å?L @ ”¾8¢Ò‡¨çÐæ£Ä˜œ`‰cËľŒþ'ŒW¾ßƾÝ2§ç>~ê~¹aÆtå;F¼öÕ&¬`×ÁƒìûóÆw«„›D®ûîÂ|“U#çݵ˜´òovýùÿKú†ÁýfsÌ>ûÀÈéù?¡}i%ǯ\dûÔ ~{u¡•Gnç”&¹øÑ˦ñ}xî{xôÓõìÚ·ƒ?>LO/:;Í£k˱@1ãrœ—£ËÉËGùò¡£ŽázŸ™on懃*ھܟZnÎjUÙ^õ9z+§ûâìüåøNXÏñóçÙý^8ëF à£éâ‰"@ Ü£äZ_Þ}·'OŒÿu¾¨@ͦÍhÙæ~éÿ?Z»a¹µŽY+u _;…~µ­“K*zŸ—VÝϢͷéUï*1ª*´ë؈ªA* ¤R-…ô¸œ÷)&Å6¦EQ0F®eî_jý~:Zè‘cì§ãÙÐæ3æÉG­CßË÷yƒZ•G T{h(íßΆ3)ô)ïY8O)vp÷4 U¹Ú„{8w1£R•úƒGRß¶³â“Ly{kÆ­æÌ[Íh¤Î6]îçè(‚Í éëŸ$<(ssØø­lžqílSD2,³Û–“{V]ìåéôZøcºú"T¬j̓éòÝyT\[ŽÝ½r‰¥üõ’{ûÅY9•Ì4QŒ×s÷ÑÁyø°IVŸ›ã\ï³ô'¸A íªzا ¤î›H«^‹¹@yžZµ‹Ù9LCR²OsÉù>sEYÚil­óLQ¹×[>¦8-wÏ&ñb+?d‚»g|DK¦/:ʸ÷šŠ§Š@ @p/‹#y£#|à×ìþßnßÁžý»ÙòË8þdc×,ç…´]œK½ÄÞNU™íÌj×bQ=ü8ë.bL‹–,ëv?;÷à‘‡ÛQÍS­FÎû²c¸~˜«RÃëzcÛ« jN‹òñ:›€¹1ähu\ IDAT€†€Z™ë¨<)§KçJJ1­Àh_WCÌDÿ3— Sæ³þxtæP{÷Ä›ròxç u‹wøåfkhÈxWAͱ|œ›³Ó¯îã¢Rƒ!>fàAQËÑ­qþcÆ5þŠ*ñ›3/¥*yø°IÖô rŸ]ýÑüºi©Qkxñ‰…”Þº§ÙË •ƒÓŸdBÆl²ô+¹×[&¼œÞ•šTÍLSåKÍú~ĽqD @ ¸)ðˆw•Weš=ð/NúˆŸ6¯á¥#|6{'IŠ‚¢jœC׸yãz–ÏÎqµÑº×eôªÃl]:–ncÙòÁÜ×~<[â,Û¾:=ä±G’³£P\Ë)š¢Or>ÙŠUýï¬côàˆ¼ÿ#6;Oäõëœ_þ¾ªœ¯n)Ä9*3¿êÔk؆ Ò°a}Â+h‘¤ -'›ÈcÉvÁâõcʱÀ1SD•b?÷=RþÏ,ŸiƒêÄ-Ž^H²G…¤ $¼NêÖ ÁÃVÃH*4jCŠ!kôX $@¥Q‹³–eFyúi²Ä|®õ–ÓTÌFs.ß@ Á=+Ž(ŽÃÆóûÑVÒâ’*6£:'Y¹+sNÇ«ôÔìЗ¦~ÁªŸÓ&z5ßMÉ{Ÿ­S¬(hBªœgËÉD{º†›{ÙíCÝpo$'Ãôg*ŸJÖé!Y¶YØ;o'umx4Âõ=74乡ó×!c$úøIâL¶s%d ³%Óþ<Ïq±ÍŠ‚"¹ãçɱ)öò2ÆžçZ²%ëT›ü¨­Ô”jÒÖŠÃrWúwç±XÊ1·˜qµ¿îz«Jy,ò'ÿ>rˇïzŒ‹}&v _#3ÏùŽSiwï· êòÔ®¨ææ¾£Ü1eî·$fûe…zAhòS.)ËLŸh+å£ÞÊæC0qyû1bÍÛ 7Ø»?¿zU] â#>â#>â#>â#>ÿí@P*âH^˜¯ÿ°~/3ë» ì>všÓÇv²|Öh¦TѬw¾Á1î1o6½ò3V൫œ?´‰%Ó'³èŒ´ãóxwîJvžºÊÍ[—Ø¿n§MÔÐæº/;êàî¼ÐÅÈϯ¾Á²½¸|b=¾ô>'ÃòlCbw˜9ñçΜáôÉÃì\ÿ-3‡>@ßoâé8åmzTQÔ¥²|Ž?¶ßĈBÊÙŸ™òщ̟ñÕzBCÔDþ³ƒ37£‰‰KFÊëœâ@J»û|8±øWN¦(()çY1ý3Ž+ù»¨*èA^ùŸ¿Á'Žr)ò2ǶþÌÒM70:É£ÉÅåX˜)œäÑå—ÈÃGõa±øL]…§>œH³33èÙw<_ý¶ƒ'Nrt÷–~ög,ÜTHþ´¾'úýSùÁ*vŸ<Ë©ýëølô«¬5µeèC 2ÇÏe¨‚r¯·r¸k“ïæbäY6:–Y§ªÑ`}ñD@ îQòÝ‘}êÓ©ÖZ¾ýd]Mĸ‡4¦Ç?2u`42tœ¹š…o0ýµ^|–¸ѰãŒ÷‘‘µÜ\÷ƒ§_!A·ô›=Ÿá54ÈçsÞw×û4Uôùô¢'ŒçÝ>íˆÃжÏðÍc¨§ƒâ}Ÿ¦‚içk<Ø1Ã'^!Ômu?oÿ4ЧÛ¡êÃì™;xnü}ԧǯRkž~éAvͶM]ÐÓfìZ }ƒ®Mƃïc¬Ü÷^çž4Ÿ8‡ç‡¦GÍÐU¨CÏ/Òá¯9ù ?:¿·‚Ï}^cÆðî¼—ÚÀÆ<ñn;$gyÜ5Ö¥å(»å3%ÂÝy¼qâc÷Üóðyì7•ŒÏÜë¼ÀO[ª3÷½¹,xõ;¦$) ñ'¼e7^Yò)C›¸àßõ}V~<ƒ7>ÇÃs’7‚›öæÝŸ§Ò¯¢ºtj@Ù7×zË9jE•µ/Ðîõ[˜ýóôçKSÏMʲ¨’Ý6!–@  ´È—8⬓m2™ˆŠŠ" 0Fƒ$ËHRÉLo‰þJj*¿Ÿ8Á€Aƒ1 ¢4³‘_Á¡,ˆ(Ž6¡D @ %I¦8’mZfúŒ\OT ©))hQÉ2²,#É²Ë »óâ 9îÓÚþj´Dß¾me 1-H`Å8qbŽûòŠƒâ@3ÍQ(™( H A ééF,‹pÆY–Qk4¸¹¹ g‚b#sÍ‘láüH öuJ$ë: …9rgÄ‹N·ç7%ÛCQH#ÅÔøÈAœ()ÑDq!’@ HMN&22’£G#ò/G–eôz=uëÕ£J•ª¸{z §‚âé{¹³«( dˆyŒÞp*„ˆ÷ÞÞzì߉Å)˜h„H"øÓ©SgÒÓÓ1™LYÞ¶ÿ¾]]ã ÇúǕ酢Ú$8‹QW¹cHOçZä5öíÝKç.]©Rµ*•J8æ_ŒÉdâò¥‹lÙô‹…ð5ÑþGG8>ËÊB]‘“=Ùû Á½‚š©Sé¾{7té\èDìˆÃÈ‘hgÓb…Aƒ‡8mà¯\þKÑr’‘¥ÿ€,ûv©(ù‚T|zÖý6ÏZÑ%Äçxœqâ„»EùLnݼA¥Ð*9¯c_xbÞ"I§Î]œw&÷í-έ°GØSÚ´m‡,ËtéÒ…† R®\9, ·oßfÏž=4hГÉÄÉÇ]zÝÇЪu;RS’KÜ÷Ñ·ã@ƒûÎpÿƒ-\"¤ñ%¾üüSú÷ïÏ—ŸÍÄlJÂ]§Ábˆá—e³8ê'¦½ó n>9¦“’”À§o.M¥éÏûóÉÕäöœ+Î|o´!õ žÏÚÿB¼åf¿ÉhäøÑ£tîÒ•êaáâ&ø/tVÔjÂÂk I;þù›Š+¢Õj UO”äýíÊûÐ1ì¡q“™‚j)ÕY9ÙS¾™@PöÄqû…áȹ(÷O<5 ×þƒ={c2™Ø°nmášb8Ö‘âÊ·%(®TV€K¯ß)•yã7hÚ¼U¡|gÈ&bhg¸ft‰Mt18IÚæÕ™lÉdâ„‹;“9!ìö–æÍ[кuky䬋_K‹…ÀÀ@ÂÃÃ騱#Ë–-£jµê\¼xÁå6”dÓFïÐØ:}ò ûwŸÎÒK(bpïî$ÇG"aÄœ¸‡Ø£ ¸w´;h\¥+WöNäçßóõ§Ó¨Ô¶1&ç<é©…öMqú³´Ÿ¥eÏÉ“'³|¿pá>ø`ÓÙ³g-[¶,ré !ؘn·Ã¸Çó.féx5æ‹3Þö²ŽZkÚ¨Y±]Ùý‹…¸¸8ªV­&Zñÿ1*W©Âk~Çh4æ;¶õz’oþ‰)å)7×¹äYRZ÷áåË—Xûû 6¬ÿƒÙ³¦‘œ”È›Sf–ÚÒ6{Ö¯[ˬ÷ß!1!ž©ïÎ"6r~»‰%÷¸8RˆÞÞ¥ÚNÑh5h%s ’lô}ôñ|7ðÛuèĶ-› Qó(ÅslqœŸß†åôòY™—&E—hp̘ùsæÌ \@ˆý!óúë¯óÚøq…JÓ0a‚ƒP2³ÈOíôF¬4oÑ2ß±V­Zu.^8_¼[a°§4jÜ„Gy„Ç{ wwwt:^^^èt:Ôj5‹…¤¤$üüü=z4þþþT®\…+—/¹¸UW²Í›Ô”4ì=ƒF“ùxšùÖR&LXd[6¯Y€lŠ$õÖZnìœ)5Ž1ºONA£Yƒ,ÿÁ¶_‡²hÅU~š÷6Š¢Ø×Ó’3ÞÈ&IÑÑÑT¯¾ pö“?KûyQÚö$'gþ2›ššJbbb©Ä¼ÞÇ—¿O&q=%ž}?ÌeÒÃU*‹KJ È*ÈønLM!èÁG1ÝjƒqŽq?Ųtå1ºt¹Ÿ>CÇ¢öУ×ûWæî_›0°ÿàÞâHr°ßb±Xý*~™.óÜ¿‡¦Í[¹dá\•ÊúìS¥@±mJ¹DâåÅ܈¼X*ϵ¢^Oïã À×_~Jtt4§Ïœ£v­š”/ïgo›©ž(‚=·oßæô™sÔ¬μKˆ½±%v³Ý.%iŸ@àqÄ‹Î^£&f³9Ëÿ€½#ç|¿Ì~Ï+âHý†8vä½î[à~›vøgÛ–»Òú¯àب¸4)šªÓËSuzùkðÚ*¾çuãÃ÷Þ‹‘%“[°í„´iÓ˜6mZ‘+:GQ#G¡$?ÉŒ™&N(\g²JU×w&‹Ò¹ö”9{ž{Îúêðo¿ý¶Äì‰hÔ˜Ö­[Ó¯_?<==ÑëõøúúÚÅEQ°X,¨Õj<==ñññaèСDFFZ¹ W¯\.•º«wŸ‡ó<¦|ùòH’Ä‚ùóîÚ—‡»‡Ž¤Ä8gß>aêÀ"Õ7z_6ü¶w9’./ áò>L©qìËâÅ‹yúé§Y¸p! `ÅŠôêÕ‹š6mJ“f-Ø¿wwÖëäB~4Ù¥K—äûØ¢^Ë\ÌhH*%|m_¾žö êVÇ¿œ·¯£¼ÅDݦéÐ;ŒIcž`ëŽ#è}|‰wQE—>qW¤ÒŸ› •GÇÎä¤I“Ðh4h4dYæÇDQúõëgñŒF#&L°w&¯¸¨39pà Ž=Z${:wîlß·dÉâ¢wü‹ØÙ¾ââÎö½bOïÞ½íÇôíÛ—Õ«W—ˆ=‹…Aƒááᯯ/þþþH’d_tÐÖq0›ÍxzzR½zu†γÏ>ëÒz¢ imÞ¼9ÏcŒF#çÎcîç_°`Á‚»”ÃËÛƒ¸ØDþÞt˜ SWä<µjQŸ¤Ë ¬×8¿€Iß{²}ûF¼¼¼$‰Úµk³cǧbˆ3q¤,M«)­çŽbï,â©&ƒ‹µŒEÂb¶ sÓq3Ɍʨ‹’ɨ`Q{ÐbÊlÒ/ÞGú^£ÝfáªÃ|Ô£¯r\ÕèQ»y!Ér‘íqµÏQÄö])Æòý׌ IÜHßЧðZu‘%¼Š÷Z¦Ë|Þ²Ÿ÷;ÄÁñ5ÑÜ#.2™L¨Õj—Ć/1§>À’@ZÌ*VkNܹ×H½½Õ¥íXWƱƒ°c³/,¼“&Ž¥i“x ;¡¡¡ìؾÍ.Œ”ô½^ƒ‰^¥QD–¯øØÈ (ñ;î:.¸JÁUÂ8¼Ò»Äü-¸Dq¼­Lf“ýÿ”qcmOû|'zôðAzö~˜©S§âááÁ!Cð÷÷gèСȲÌ!CP…!C†`6›4hƒ‘#G²sçNöîÝ›%­|´F\âj3*Xvoß-®Ø:©Å8/Ëõ®sqâmªÍ¨@µéåÚæJâãbññµÕëÚ@Ï} ÊÓ®Ûز–×ÒXòç-ûq®ö…2y2†¤D´3 6’䥘êet&µZ­}¡.Û/¿ŽIEQP©TY:“®Î‡cç¶0ö8îs…mÙ;Û;wî䨱c¼þúëÈ p“É”cg»8ýcëü˲lÿØìyÿý÷©_¿>íÛ·/Q{*T¨À[o½u×q³fÍb̘1ÅꟺõêÓ·o_‚ƒƒñôôÄÛÛÛ^6@–Æ£M0±ù­Q£Fôèу  `n޸R)Ä)¹ŸãëëË /¼@pp0>>¾Öºä®:ÈÛ¥õŒV§Ã”m[rr2~~~YG¤W¯^èt:~ýõWç#GJhZ­>ÎŽÿkj\z«dŸeÍÃ_Í©Þy,W7Í"´óX47gaº–ùýê¦Yl¯Ô™-‡×ñgŠ…è]ãy±÷„,ûC;E·w–Kžñ&‹EmÁÓ[EËÉïÞuoȲLú¹V¤/Ïk?G²pÕa6n܈¿¿?œyÿ}´n:[[¬(ö¸°nÚh†0Ò4KºM#š²ÿÐ~öÜgÝçÒF’k=“c]£ÜáçŽ<¹=s“®bKž|}.k„¾¤)™R®õ£9’EÃ鱄 k#@vÜ™ÂîQµh³a(‡¿E½œ^Ö"yP«gúÔ÷FR”¼;ͦ |Ò¬ß<}„}cŠMLÉ-ßäÉ'Ÿäûï¿§qãÆ.‰mg5âo¬Îú¬7D“tõ;â¢/ðÍêÝ éÕ¢„Ê?ÿØÖí@Qìír_._¾LB|,ÛÿÙBrJj±Üëùí'øèõL˜ô[V¼êTq$´f[¥:}æ eTÉäÒ… T[¼˜ôôt6ÿµ‘îö$===ET¹ë!Õ¡S `oàëõú,C”³Ôã94ð[´jMjj*GpIfz:«È‘ƒ0aû¿¸EˆâV\e³­âòñõãÏ£ œx®Ý]&$$„nݺ±aÆbÍ‹mm’üˆ$sç~N:uì±fë<þüóÏYbí§Ÿ~Âl6Ó¯_?{,Ú;“Á!.éL.]²ø®Îí?þˆJ¥²ŠÈnOzz:F£‘ôôt»=«W¯vYç6»=_ý5Û¶mcÔ¨QYì±uúœv¶]ägöäT7H’DDDsæÌáèÑ£ 6¬ÄìY¶l»ví¢mÛ¶üóÏ?H’DûöíÙºu+ 4 cÇŽÅæŸôôtÚ´iƒV«ÅËË £ÑˆŸŸ×®]ÃÇÇ'Ëè‘ìõ®$ItíÚ•+V”J”Ÿùÿ‹…„„‚ƒƒyì±ÇHMM¥YóìÛ»ÇiäªN¼)ñ¤S_ßÿýx{{c6›Y·n]¸ôóóËx{ˆ;íÚ·gûöí¥2­Æ×Ï5ë–Ñ ËöC ­>o‹.UW¢Ï‹²f@h籘ô½ ~¸7&Àܬ ºÚÔð»ë©ycÝë±>™I;Kmš°¶-lÇ…v˜Rä2S–t‹ÓûC–eÒNµ$u¿ãW^eÞ÷‡ðMM¤ù uƒêâïïZ­F–eÌfÓ¿¦±¹ÿÐ~× 'y"¡n?—¿ç¶Ã#í&{Œaø‹= ÖiæuЗMG©‚ypdGxú ÖßìËÀ‡$îcÞO7©7öIjæö[¹<§|Mç{$6<È<@LL <ðëׯϿ@’›¸pr·¢¬uJpEëâ½æ´[DÝIÉrÜîÃÖ…¿‹] )èó4~±7¶âãëgŽŸ`}IBÇ­Ù²u‡Ó6»+Ÿ¡y1a’õG¤Žÿû/G¸q_çÒšOXGôUšVX—%OAYCvÖ)­¶8S<èþ`Ï<Ê’U ±ýnkà{{{Û‡Êgo<çÖÀ7›Í>¸?Ë1Ù?®…[Íq›M\± ,Å%n8^¿0纚gŸ}Ö(²õݾ}{ºuëÂß/Íñ×CW‹$Ž‹¸:Ãl6S¹rå,±æ¬£æ,fcÍU8vn½½½sì8–†=C† aÛ¶mtèСÀ÷bqù'¯º¡C‡lÛ¶–˜=ÿý7Æ £~ýúöxjذ!£FâØ±cÅê³ÙLhh(Z­Ö.ŒÄÇÇÛ_-l[Î6ýȱìÂÃËæ«-mŒÇb± ÓéèÑ£Ï>û,7)–ë¦&^$æÄ GïÚwø3/>z¥ ;vì`÷îÝøùùáï¦Ûí0pgÄ×9|ø0?üðC©ˆ#ž4hP—ÛwÎÛ?—ocšñT÷®‚ûÏ}^”5{®nš•ã¾Q«_cº)ô­×‹¾õz1â¾al:ÿ7çî\Èw:Œvû¸äÀìß¿Y–I9Ò‚ä}nŒü!žùË1x¦U˜Ùzþ/þ9¶Í>­K£V‘žn(SâP(Ãvni ö©J­:u¨×¸ϼÿÏÞfÃÊ3¤*Éœøf÷U²®q¥ÖÐàѹœ¶ý˜zŽŸÇv£¦µZM…ˆ~|ðÏÌ){x©’'÷ÿæðÆ“Ä<âÌÐíÖ…-wþfzïšx©Õ¨[òÂwçIs°Ë·—9›¨Q£V{S£ûV]12ºŒàív>ÿíZ–Ñnñ;¿del†?ZUŽçcVÓÔ“ïŸÁh{®ÜÞÌÛ=kØíþå<äÀÓÛ®óÇÃõxõX:ÇÇÕÂ]­F0„Jè ФGLž<™„„&OžL=8xð`‘Ò‹¥r·ƒ4pæ®áj½Ï¢î¤Ø·5pƽGpúŒUùæ·=eï¹»™Økkíb‚MP° #ÎD‘kW3§ùúøú[[ÝÑ€ásÓÙtÈy~ 7vΧB9/V}ÚAô¾eš,o«IŸð( ii™U¸ãÿ¹´zïêܘL&BCCqssËÒùq<Îñ{N üˆÆM9t`_¾Þi¤;ㄨ»ö;;¶¸WGÏ;ê3¨6£‚ÝV€ê3ŠÍ¶ú‡ ØuàÍ›7ç‡~ j•Pš5mƶ­áãëG\lL±ç?ýµ×p›ùžÓã- z½KF¬}ûí·¨2V±wkK–,Áh4’–––%Ö\å;[çÖûÎÄgBDöØw¥=»víbÙ²eömÛ¶mcÛ¶mÌ;7Ëõ7n܈››éééÅjOöºÁ6íèþûï¿ËgŽŒ3†°°°b·çË/¿´Šs_}õ’$ѳgOT*½{÷&&&¦Xýc‹ë   R/âî]¤¤$t:f³­Vkic±X0›ÍFL&“õ‡. ’N÷%Ý©´± ó—¾™í¼Ì΢¢(¤¤¤píÚ5’““IHH uëÖhµZ—×_q±1¸{û“žEò¥ÏïÚÇïYºöÿ„ÃY§>hÜÝ©;üUnlAüßÞZÇš¢Øpð2ÝWaÀ€öQN…-ó‚œÓ´ys>›fí«¥¤bÉyp$ê[.ï –Mõ¨S¯&'Žvú¼¨šm*KQžE±'æ=k7¯ªbµÇ×Ï€ÁƒC`Ñž_¡ÇâlŒÅ·bùñßè[¯-B›2 ñã칺ŸOw|Euÿª„—«ž%˜Rä8´(³‰¸¸8û/à¶7u\>מ÷WoäÛ‡Ù°aþþþ˜Xuú'îoñ›ufíZë“¡Èu‹Ëê”\ÓkÑ„ý‡÷³ïÐ>šFd (ûï/’-y®7—ã´»ÅÖú@rÃS ¦4#†‹ß0hÄÔ™»™¥Ý*£Š;Ǿ} hQPÌ1l|© CôbÎïŸÐ¾b:G—¾Âàžý 8ú;ƒü3Òs¬gŸí¦H¾ºoíÇ7»ÖÑVÞ͇C†³>QKÿŒý?>ÝWŽöâóMËèì}Š…#òH-ûöN%¯/ôÖÓã«\~æeªkå[¾XKÊ}ŸÐ+ø?>žËù[Î3ì1_ãÛ}˜~}0‹öŒ¡¥¼Ÿ¹ÃŸg}¢LÅ›î+Žóasë´š½£«gL«Q\>KÃYYMš4‰3fXë`Ĉxzz2iÒ$û}PØØ°µMmu#-]Ï’Ÿ3§Ü,ùy5ƒë]líû"Ýà {ˆÜ`oo;¶¹}|ý¸rå ‡ÄÇ×îÝ:±qúw넯3gLeÂÄ·Š¥­žÝÏ6_4:7Ò12ɾÝ:ª$ŽøË{¨ÞØ*Þ4%(³ÈÎ6nÙô':7Ý]ÿ¨q`± Ijµ³ÙìôckÔ;þŸ½Ÿa¤(ØŠŽbƒãwdždYÄѾìyp{`ðè/xjÔ»4î=‚™ï}ÀÞ}{ñõ)Çß/uúà)Ò'xRq³ IDAT¼–ãCDZæ*Ìfs™³'§uN#±JÚ?Ù¢ìBRq ”¹Ù“Û9Åå“ÉÄÙ³g '=%ŠÔ«Ö‘|-[¶$,,ŒáÇóÃ?M||@Wžú jŠŸ9|ýü³|Ò[ŸÃËYŸ3Šö¼(Š=¶˜p´'66–E‹ùù•Óˆ ë¦Ð8¤aa E¨µóþ÷ÅùJ§ÀíŸ4 fÙ‚¯¯¯½¾R©TôéT:}g±ð§La$((ˆö5:ÖÑ#YêBK)ÝÇë×Û?EÁQqLJã,z›…WÝiÚ5 uì%bÔÕé|sÂ*†Pµ^{}º'Uµ`¾ñïü¤cô’Y j[›ªÕ"è5ñ ÆWÚÎWÞ"¯Òš®®âã<3ï4­FÕÆO0sn‚2äÓÕUÌþCCÿ¯ç0´m-Â"úðÖâ©Ô?ó5ŸHô´zîŽÌãÇóVÌrû/¾üÓLÇ»Sáz^çg·g5Ÿnñåùy3è׸*U#áíÏž!´ ,w»zõj»0bÃöòWbJ¹ÄÈ‹\Œ4fÙ>è±Þ z,sáõ…¿ï-“m}%~[V¼êôy`ÿ^’“âX¸àsúõ{ÌúCE÷ûùbîlÒRéÞ­S‰Ú:f¾'­~~ãõqôè~?Ãç¦s#Æ‚!îÕ«”½oA™Æéš#Ý{ôtúNS%«‚Žõ/^¤bÅŠÆ,£Gu³X,˜L&Ìf³Ó~£&Í8¸ß5•Õ’Å‹\ê¼×&Lä½™3ŠU¤ÉŽí×Àì¢Mq# ßË’ŸWS«f--µ6’jÕ¬½G0nÜüæùСC'V®ø_?ÿbS¥mä6r$66_‹£ÑÈ!C$‰eË–9µAƒa±Xøøã‹¥3i6›³Ä¾N§CQL&“S{ï™â²§yóæŒ3†!C†Ð¶m[êׯÏC=„»»;IIIÄÅÅåx/—$I"!!•JÅo¿ý–ÅžuëÖqìØ1þùçÞ}÷]¶mÛVìö w 5 ¤§§»Eáã?&=ùš}´CÒµ_QyT!-%…eßýÊ /¼À Aƒxùå—ñðð@’$L&ééé¬_ÿöÎ;>ŠêëÃÏìn6=! ¡zh Ò,(X° X±¡(Ä‚ØÅÞQ±ü|í¢‚ ½ƒÔHè @ }ëÌûÇf7»Kzƒó|>“ìÎ̽÷̹³3s¿sï¹ ]o©kš»G¿äúüÙ×S¸wÌ+Û?™=EÑ1tèP:uêDfæ8HNNÛ·o¯6»ÎœÎ gŸlX;SÚdEÜÍå7¿ãÆœ3#™ôºÑ'~:Íìß¶3oÞ<O*ì۳眈#zƒ£¯‘̬G\"“½^Ǿ G·éŸÆ´lÙ„f÷ÆðЄ»ñ÷ ÅÇèƒNQðõõÅèëÃÕ¿^ÃÐqýi<º¾t•º_TÔž+ Î$UyÿŠ8‰”ßû»‚«68‰íßÜ €éä¿Üu-{þ×͵ýÆ“øÚ¨ðÛŽ¹\𾫮|Ò”Õs¤ùKx®b1PÌ:P „„„ÇõAnLç¦×‡3¤þ5œ:u UU±X,tñëAÛðüœð\ÐÛ•O¨¡ÐWÍ_‰àÀ”êƒö÷Â…\1t¨Ç÷ˆè‡»hâ¾o÷ÎÝÙ²m‹‡(rn… ÓÜ«©ï ƒD×û¿æÃk"°ÞÁÝ>ážÖ­ùâš«rÅFÝ4ˆ–A ¦ƒ«Ù·õ]‚xÅ+Ç–‡Nc-­þlæ°®-Ou(VØní}vm?¤Äñh§œWŸ†½éyš-Ég°÷ $°Û=Üû9_~—Ìc/µçäß³Ò0”ŸE`ÝYJúž^ö¤lá°.Ž)­\ëü[ ­ßלkŠ›¦<³Ö”åúï.*8{´‰kãZ×&®«÷Èù‚»X»~—•ñš‹=¶Ù_8ž-^†¯QO»ö9súyùùü½hyµ?Ÿ{Ûã´uË–D|zÀϯdÛû¥å-ÔqDUU|^}ü'Ÿ ÇVØÊýsÑ S;6hªêšvÎù¹hÑ".ºè"Æ ^¯÷ˆ ál4Z­Vòóó1›ÍøÿY‹ÕZú¸[÷FfY‰{³»'+1½sÛ—_|îú>åÙç*\nec÷¤c.ÛËbEøöïÂñž=;·aô…Á±’w'óö· ¹{ôP~øþ[†ÂG¾G½°pN¦Ÿ¨øÏx£Ä·5ûöí£CÁ0»ÝŽN§Ãb±y®9{jxŸkUåCMÓ<Î}÷†vQöEžûÕaÏ—_~ÉgŸ}Æš5kh×®f³™üü|ß÷[¬.ÿx_Üí±Ûí¬Y³†K.¹„[o½•¼¼¼±Ç)Ð8‡9ë¨&ü“ŸŸïjÄ»„™¬¡ fƨaaô‹»ŽÎ#¾Áb±pÿý÷€¦iìÚµ‹ùóçs2ýD•ÙSž|>™=ÙC´tÿîj`ëõ¸†#uïîðû¼yóøàƒªüZæ$11ßÀFd>ÂÀÑ’œœÌîÝ»Ñ4öíÛcJêIÞŽÜÿé~~˜»ƒ·ß~›~ýú±åÇ¥Xlö"őШZž4ÇÓN¢×éIM=¯¯¦¼<EÇÞÓÈËÍÇhÁÏß‹-sv6š]CÑ)hªŠ]Õ¸>j¿¥ÎC¦Tú~QQ{œœ>í€Ï¿§²u~\¹ë%ÃØŸ\2Œÿ&±0ä*ºh‡¹©ómbÆÒüŽÇ"CÁÿ6qÉìúïgrºOwmßµk0•fÏE  T*l—ÎGè@^Z]»v%Û”Íè/n$=ó]b»1¸û`‚‚‚ Äh4¢( öu&)c>Ó“Øì*v›£Þlj:?¥ÚÏ7Õn÷H£Úí¨âïüù󉊊¢w¯^FTUu }2d;t&a{aý®ñÝ*U¿%¥uôÞ+FªÐÌØTCŸ™,œÙ‹@} š4%:Pª ³>ŽÇíåÊsùkѼp%Ó^Ëëßå‹ UŸ&/å¶è":XçoFT«³¹`è¹ÙŒMÕëT;šN‡b3ášËÀz†ÝjƬ³£¡a³˜0› ä ³UÍjÆb6¡ÓµdÔmÍy÷Û/Øúèlý诚CÏ@3fkiémØ4Ðlû,V;*V‹›=+*ö˜ÍûW—´îò•Wý%„”eZßòœWÎgÓÒžmÁñbÐ}}MßG½Y–haâç×q8ójáxIêì²råJNœHçèÑ£ìÜ™Ìý÷ßËÖ­[¸bÈe.q¨*žÑ‹ÃÝž!CóؤgÈÌÌâøñ4‚±¨ŒáÍHÞë°¡ªÚ ‚Pmâˆ{#ôð¡ƒ4ûêkrssX³jC¯FnnN± œÝ¦ÝzŽ˜Íf~þùgFŽI«V­°Z­FqÄù¶ÓÙà°X,äçç»ð7¬_CKú°aýš*9Ø;ïºÛCä(«÷f#vO*œ‰Â)ŒœKvO:ÆÑ[TkÞʺ·Âþö· ¹åÖ¡|>ëcn¼á:ΜɤADd•^ìüg¼Qê>}”·ßycÁP»ÝަiŒ=€Y³f¡( wÝu—«!®ªªÇ¹VU6ßy×Ý\~ùåçþ}÷Ýç1Kqö¼úê«ö”÷|-ŽÃ‡Ò¤i3—=ãÆ#..Ž%K–п|}aïóòòŠý-VezÛã}mp·gÉ’%ÜqÇtïÞ½Fíqv‡w 5Î8Õퟑd>‚)íìæãÅîçœïÒ±?0räH‚‚‚P…™3gž³^#G¯p/5¼Ë%–Œ÷Z‘âÉYÇÞ AµÛwÍ5×pQŸ+xçÇŨªJ\\z½Þ$óÁŸÂÈO?ýD»ví<ïsÔ|Ï‘œœ|¬6•Œô3˜­V>ùðGÒO¾œÍ\f3·Ìù)ŠBÄŒ(ÒO¯q{œ½GÏœ9ãFúõëÇk¯½Vå~ÛŸ»‡yÉsèÒ¨;£º-rŸw†ÊïÿýÌÆ”õûÓ¡ TЬr`±k˜,6|»`Ê”)ì7ïa‘áwêÛ#iµ'ž·V¾…UÓaÀŽ£[C`€w|‹þÆ›ÐëŽçšöø)"Suâ=¢S0å›ÉÎÌfРAØm6,V Ë–-óEÜéß´Ô”°V+5æˆ!´9í:t Øë·ìPjCi;èvÚº‰“†qM»Gø:ñ5´êIK~ã×5éÜrCäÙãÏ '#»Œ°eì%%W%LÓ0Æt%V[˦Ã&®ê踟™la_¾F}MÃØ¸Mµ,ý/››.uXfM]Ïúôzt‹ -˜~×Hë›ÇÑnÆ|ö{(‰‰áŒ˜~1Aš†­Ôô§<â­w!Ö¾ŒU{ò¸æ"‡ðŸ¿oÉ&MCÓt:Ð žªëL+ª®n¸án¸á×óÀ·ß~˯¿þÊï¿ÿ~NžmϧÞ#îˆóÁýyãðáCü÷ïVާ¥b¶ØÙ¿ÿÇŸ $4„¡W^Ë¡ƒû1Å6fì7óÕ7?V¹â-¸¸Ûsë-7²vízÒÓOT09=°{ž¤U«æìÝ{@ZáBíGZ¶ŽƒW^Áßbaè‹/V(ãukVÒoÀ@^{í5Þ}÷]ŒF#&“Éõ–Ä'Â9Æß 377×㿪„‘ªW6lÀ+/¿T%ùº÷\¢Gã›÷y!Ç, îû»ï[YJRÖŸ »³ɬO5î¾k,iÇW‰@RQÄUU]çšóœr 999®sÍ)FØív²²²ª­1i³Ù*eó\«{ŒF#Ý»w§W¯^äææzØSÒo±:íq¿6¸Û3qâD¬V+9995jÏþýûyä‘G<öqŽ‹ž9sfµùçdú BÂ"Yý㣄¤-ŠyO‰÷믿rå•W2{öl¶oß~NßÄ4Zà~ò±ÛÃðÇ_>]âñNWíöÍ;—„ƒ§X¶aIII@aÌþÜÁã?NãÆÙ·oMš4qÅÏ8yò$Š¢pêÔ©ó©¦An¾™5«¶°iãzƒ ØU[9Ò;{gÚ°Ym€.ëÏÊå«jÜç½Íš5ôë×Ý{7WÚž¢È-èñÚ,¼ä#:Žä÷ÿ~¦Gl/FuË›¦áÛA‡š«±÷…ԊיUÃl¶\/]xŒÙ ú¡í‹ŠÁ Çd±àëúMèt:ÚÞFRÖ ŽEgÑX¯ãHÄZ|Ãt¨&½Ï¦ÖØ9ç.x¬X¹‚üÜ|z÷îMzzºkø›û>îb @|§Ba1-5…膱ÕöÛ(W@V7ò·ÄkK#2´-Ãlþ{»¬ ¹7Ê€®áµLõ*×=0š©êKŒî…–žÄª?—¢Þ2{Ú6a@ßPÞ™õÿ]÷ÙËO/¼ÅvM!^ÓÐ7ºšûMå‰ç¿ãæÿ%޽ü0õcölŸ0äî|p½>ŸÄ€Àd¾™ø2;Z?ħý]Çdh:‚»â§2i«Ðð!>Šwl+Kz÷€±†FWsÿçyøÁçéùéCôÐmãÓ‰ßpÇú`š4Ò“²b5;o ¦±¡aª¼¾Î®«©S§2bÄuäää0zôh¾ùæfÌxƒßŸSå;Ëólûíß UÞ{¤¼¬ßeõF6m\ÇÅ=z{´š4iÊC.ãæ›GÒ¥KgöíÝKn^“³ÉÄÑci¤¤åïEË«\Iغ‘®Ýz”hÏîädòòM ¾ürþïûiÔŽÑÃ_Cj…8â~ë°X ǵÙ_xÞ±ý‰'йÚNãë~÷¹¤w?þY·š~òÊ+¯0qâD|||0 ®7oÎF…s ^^3gÎdûöíü³n5š¦¹ò©ÈE·¤}ÛÌlì¸>~´Ä´É¥ÍÌÆÄ½Ùˆ¾\åZÿòKÓ*uáv–ï]–{o£?¶pE{ö~Ówì§–E^°*úFЧ²~ûÐ.ŧSaO?qœˆÈ(¬6Ï>óþþ4ˆˆ¬-Ê´iøåç•ûÍÅý©Çx©q ¯¼ò Ï=÷œÇ¹–ªª¼üòËçÚôéÓÙ¾};é'ŽWÙMø‹Ïg6+aOEÏíâ8z$ÅeOy‹UéŸÚdOqdeeU«=ÎßÓ’o$"óì1á™ûV{,‘†½îæ÷0üáÿcãÆìÝ»×u-¨ªë@yÏ¿ûïœÀG_<ÉwÍp}®®ò*Cdd$õë×wÉt _C† !::š¸¸8¬V«‡h]i[Ë›æ¤9äå哸5™ ê³ç`ùî‡6›Ý±Xm˜-ÎœÉÆdΫ°Ÿ+k@ÇŽ¢Ô‘í•¶§(Žä Gl¯÷sï=²1e=ËRbÞ¡rðËÔJÙ£³‚ŠJFV:Ž ¿@$báèÉuB´Õ®¢ÚmhhXMfS ´‚CÙÿ’©í!'ìp¥í©Hº„í…Èz!dÎfíÚuÂGê±¶ÿ»«@(ì‘>-õˆÇ÷… ¹_¥í×T´âÄiM-ˆÿìØÇ;ÅèCê¼iÜ2õYø5¾„Q~Ëí h„2ðÍ…|ù$Ó&^ÎÛ™€Cº º)! šêOÏç>áqpY£WñlψG'pÙß3å)ÑÜøÙÿqpüÃ\ÚôY|ÚÐoÌCô[ñaÁö(®ût'ŸÈóCºs?𠏇ÿ}1‰N¾*šót¸úž<ùà?4»mmÛJKoó:v]Cnžõ=‡î›Àø~Ÿb®×™1Sž¡ÿ®™øê445˜~“Ÿ¤×è'èÛv„ÝÊ‚Ñ; ŠÅ‘"ê*¾S'æüö+ÃG\Ç“O>EXXü>‡øNНÛJœÛåy¶­ÊkREòrÆí8tè óçÍaÙÒżõæ+äædóÜÔé®û|DdãïÏ¡ƒû™úâ téz1§3N1oî—0RUÏ*N{-\Pª=O=ý]»]LëÖmØ0ïA~ž»íœÜï¡Bâˆ;)‡Ѳu‹Ùõ™7oòó½D­`º/GPV7Åsí*4McÕŠ¥ôídüøñ´hÑNçñƒ°X,ìÞ½›Y³f±cÇ—¸²~í*W>ç§@â.ŒT¥(â,£¸†RQ4ºiŸK itÓ>ÒoªšcýßÂDe½8îy­Ç4hÎ]nnMœàº@–µ‘æÿÆÄžL‡Ø¦¶ýØÑ#D7lTîs­Û·²xÓn̹CØË"šã«ÌžŠˆ".1øL6v»>}z£ÓéX½zK$)NìˆnãH¢ÆÝ0¦ZìU5P‹}> cø‚S w8û¬8>­ïä“EwU{¨`Œåªg¿çªg‹*WCip)ÏÍÝ‰Ç ëûî+ÜÞ—'~JÀã‰ù©Ç\Û éÎ}³Vq߬³óv“Ùˆ5ŸS£\?¢Âã()½>†»V¥r—[¥~žú%眖¤×émäÊ(ªþ'ðÓö gû¡Jë«è ;ÅÇ3gÎoÜyç]|ùåtŠ/¡^köÙö|¸_}öÉûœK—³{/:EáÈ]ã<¶­[³Ò£ãÚÕ+èÝwË—ŸýC]W €hŸGÝ>Æõ€ß«ï×ö®ºe>è6oÅT(ݳ>+wš¢Xëç7FîuåMúñ4Ð4Çú*(§¼üoÑ6× áŽ‘×rûÎ%ÚàTØ{vnãÚ/ýxQÑ<ñä3®ãñDÞ,Ë}¼ÂȤ³Ê8‘–êòiQçZúñ4—Ó§qqÏK<“ÇÓªÔ¯bØSa¤à÷ä^nDT4W<Ÿç9%žÛoÀÙóeóæÍlÞ¼¹ò6•ã:ôð½3yïÓÇ*û]c×¼VõüèÛ€5jDvv6ÿlØÀû?.äºK{ 4hQµ¶•#ó•û¯¿ îÄb1a6[ ¨šŠNÑaWí¨ª†^¯ÃnwôAQ°˜-ØU³É‚Åb%åps~[ÂñÔÔ Keì:ènW@ÖÿþûÕ«WÓ¯_?æÏŸÏ'~[eõþ÷Á¹åN3ªëFuÃÎ;âH%mQqêñÕCF¸£…Aï)ådga-˜É,¼~ÁA!øùû£ íñò¨7y걇+gO¹Òjdgfß©ÑÑŽç¤E‹ƒ¦qÙ¥X´x1ÑÑÑDFFÒ»w/ôz½+ÞÈÁƒ«çGZ‚ýš¦•:ôBpÔ«=ë_¾ž0‰ ÇÍ@ -.¿Ÿ¯ßMS½Û0žê¶¢”ºÒëtå«Ï2žÛUñl[“×}wZ¶jÍ3“'ѽ[g†½‚ØØXÖ­]å"œÏßÿð‹ë³ÅjeÙrÇKœ –>?TÁ±TÄž—õu¥w #Ue T¯8âFÊá‚a5f³Ççâ.ºóål 0‚ÓÙ_¹ŠIŠºÉ¹ã|Àÿä“O\¢JqiËÒž~îùHM-hV+,é±#ÔôOÓ)Œû¹•«»ü‰ãiœ— g0ªÒ|zÛÎ|·h›ÇÍç¶!]ÇâLP1¤ä=1©ôFn1 Bïã:«1]lÚJ5ºÅ±§‚vDFE»Êu~×Ç^Î_Kvže“sûäÉ“1¬[·®R6•çºôÎÇV"@­Vîò*ƒÙl¦yǬD7<øFóÍ›SÈÌÌ$6&†#©ÇHJÍa@S]…|Qþ̧ÒmtwzŒïËæÄ…ØíjaLž‚ÿš[ÿw»ÝcD-Elv;šªqæL6 ;ññ1Tø8*jÏ#ñ˜©ÆÙsÄ)Tæ÷âÛYaÚªÉXmV–vØÔ3¼/o_ûI¹órÆ—©L=ûvVørãDÒ3Ó9d^pUëkxýŠw¹÷—;\¾²XL¨vAÁDF7ÂÏ/›ÍŠ^³ ÚŽçkø*–JÛSž´ÑœH;‰¤¦!/ßêè\°}p²hñbW§(Rm3œ”Òà”ž#e#´ïË,üïåRŸ½«U©â²Ê“[U<ÛÖ”­Þ÷òz¡¡:tˆ¬ÌÓ¬]³‚ܼ||ÝŸ¹—0â~]­ ÏŸoöBõ‰#/¼Àß§N1ÀmeIÃjŠüÅ+Îÿ…§û¡qcàËÙ»7¶Ì†­]µœ>ý/còäɬ\¹’uëÖѧߥ¬]U¾îaÏ=ÿB‘ë“;RngÝ}Ͻ|îìAR °šæ;/e½¬8§>k׆{¶-®v;Ë"ŠTô‚ïÞ˜Œ¬¦·Ø#öTÕuÂõ½¨mN›ÆÏÑ£G9tèPøâÔˆN®Ïás¶3ñwyû£G˜øÀ»®õE}¯iÌV+ö‚Àã~~~DÖ£M›¶®Æ»ÑhDµšÑéu œSLyfüŒäææc³Ù f¹ÂÕÈvLîèª`³;D›Õ^ÌØêÚ/õX: ¬%åpJÛã$,,Ì#¯Ó§OWÊ–¶oÅ`ˆU°Z­,KYH‹ ÖDøF1,p${öìÁÇÇEQ°ìÓ=@ IDATÙl ,K‘뜤§§W‰=gÒS9dÙD˜¾–c9Lýé'Ò°Û쮢ٔOXx"¢âëë‡ÙlBUíXÌ|T UÕÐìö?ßš5qZu?Ü©¶^"å²rrrÐëõç7M›µ¨²YÔœ3ÿÕä³mUˆ#•áɧ‘m.Л+וø\PÏAç›=‚Põ∳Ñ9éqÞ|‹ÙäÚÁýsɉš£çÈ—_9ÆÇß9v _~õuá ÏïcÇÐô«¯Y³r} ,ö?@Ó¦M9tèP‰Ó¶••¤‰)5ØMÕ“†7î!õ—Ö®Ïçº[Ùw‹·»>'ïNvÝœ9}Š=»“1›L¡Çn1aÑ©hÎÞ¸5ô¼Õ´#ÄwlëVsλ¾S~HHÇÓR‰nØHžäëÇÓÒ¨W¯ž#žQ çfEŸmûÜ68žïo盟ÿôèIrÛàø½¦8‡ùFF7t Îuçâ·y¾Ù#Õ*Ž8OéÜ‚FhÀ›e¡•°~ÜØ1%þ?8v Ìþú¬ÿ«W.óÈ÷СCg­+‹ Ó^œ À=÷ÞW꾕9Þ2?€Ü¸§Jò©*œAªÚÄ9ÄQƒã]¶wxÛÞ ~¶ít¨óÛ·©²nÀ.Q¤Fnº©D4&§¥žóú{Ğʖs¼à¡¥¦ºå?þÐ{ßß|ÿ!2oì ÀK ïâÍ÷*µ¤ê®Ç§?Ï­w=LžâG ÿ\rssydÔ¬\¹’´´4‚‚‚ˆ åÈÝŠ fÛ¶­Uf›VÁº®,>>ޤ¤Tê*c38ëÛo ãæ‘#*eÓ®‰)U~ŽT…=QÑ IÆà÷ï¾,GŽ˜)û·o%iëªJ_KÊ›6ª@9_žO´bÎ¥víÛ³qÃ.îѓȨ¨rõ&jªªrâøq6mÚH||<ŸRÏÑ’žmËŠ³ 8zžhçàšâ~/?_~›ç›=‚P•(š¦i&LàÙg&»SÀ›3ÏZg³Yùï߉‰‰ÇŸ!eì×çµk×òø“O“qòdµ—{Ï}ã˜õé'Ì ðKþ¥çoߺ¾wjQ±ÿî÷œ¹¡¢ù8‘Çå—)µƒÑ§ÂiwìØIÿþ8žz¬ZmŒªà›æê¶K„ò5–:HrRYYY•ˆu$Ôt:¡¡õhÓ¶ QQQøû”úlëΨË;Uø¹*ò*Ç˯¾Æ{ï½'Žj„2‰#î8…§8Ò8¦1Š¢è"J@JJ ½úô%?/OÙÅÔUm@AAÊŠ¦iX­×Ð.áo°( ƒF£QœQÇqD¨IÎVS¹XS~>ëüžw&¦Wjöæ¤(Š««nUйçYC=°‰µÕÇ‚ ‚ ÔªÖ2>F_|Œ¾â‹:„È`‚ T'…qøË©º+ŠBXx8I7$ ÀßÑg¤@¨hòõ75b¼ªjøø£ij•^.ß|SÎŒ*$÷ñ"„yË#‚ ‚ ‚ œ'Tx’B½^OǎظáÚµk‡Ÿ¯/jAƒ÷УÏÚ¿é×ßV™ÑŠ¢8‚3¥§Ó¼y l6›ÔäyB‘BHEίƒÑ¥G—–Šþøqòî»Oœ+‚ ‚ ‚ T G qmÚÂ?ëÖ‘‘qªÄ€Xÿ´i]äú>K——»lEQð÷÷§yó„…‡a6™¤&k˜ªAŠÃï×_ÅÉ‚ ‚ ‚ BPs¤Ã,f3±±Mh5&½^_1 ž|ºØMÊ´—ŠÝ¦i*6« S¾#ÕEîãQBTkÙÞÙK°5AAA¡º0T6ƒ¼Ü\òrs«ÇºñeJ8ó-©ÉrP¢è!‚ ‚ ‚ u —8²oßžÚ{#®©P²ØÙ_ÕêÊK7¶b kA]Çž>åy¬µùüAAAÎk\âÈC&Š7j nÝ—–æñýÓ„mRß‚ ‚ T«V®8kÕjekr*¿­ÜÅá´3çµýzŽÆ‘!\? ÝÚ4” .P~5†¡º p6r7±5(ˆyytÌÍ%ÔnÇ¢(÷ñáßÀ@Žø:æ©oa2Ñ)7—V+( z=»Øáïïš*Ø_U¥}^MÍfÂl6|4 ›¢©×sÔ×—þþd ek„GG—{ƒ¦Ñ>/&a6Mâ(œ18b4’ìïONåûª*óòhf2Q¯`Æ|ŽiR |r¡ùÜI ÝN§Ü\š˜Í„Øíd ,ãqW—ÿAA¨›lMNåË¿éÕ½4@¯ÓŸ·¶ÚU•Ôã§øb^¹99ôëÞZ*Pá|Gœ´2™°ÛéŸ_ظÕ4šX,4±XØD¨ÝN[·íh‘6‘YY46›YvV¾ÍL&.ÍÌÄ×+`§¦ÑÀf£ÍF§Ü\6³-0°Ê+Ðn皌 B ÷Nü4h«•h«•V&?FDxlod6sù™3ø{Ù¬ª›L´4™8èëËÒÐPl:Ýçó&—efbðÊ#Üf#¼ S3ׄÿAA¨[üºb]:u$4¬¹& °×ö†„†Ñ5¾ 6íqD¡¶ˆ#a6a%4z{æä”˜¾¹ÙL›¼<’<éCΜA)¥lpIv66`G $}²²ÎF¼Ùïççñ½¡ÙÌU§OSÚ»ˆff3CϜᯰ°b{pÔFŸÇJ}^SþA¡n‘v2‹ë‘c²×›‚ëqüTkW¯$+3S*±E!8$„Öqmس;YüUFEFE‹C„:¡¦ ÌÑé˜N¾¢0 +‹ff³Çö£‘•¡¡¨Àe™™ÄZ,®mmòó] u_UåÒÌLö~??6‘¥×h·Ó9/yy®í½²³9èçG®¾êºHƸÙ°*$„Ýþþ(½(:åå±×M1¨*—gfºöÙ:kBC9f4¢V+}³²hP jÄX,Ä™Lìö÷¿ |nÐ4.óÊ#ÕLJÁÁ¤ûøàS0T¦{13 ÿ ‚ ‚PG„¨¤ܪªµÌnŽñ]ˆˆŒD'=f‹DUUÒOœ`ëæ¨v;õì%þ*ƒ¿6oDq¤:XÊé‚XkCBh–žî±}I½zX .Rÿ{ªpÖ’ún½ Úçåy ë8j4²¸^=×÷lƒ5!!øª*­L&ô@‡¼<6WÛñí÷óî( (¤¤ÛÛåçàvÃ]\¯énû7YR¯·œ<é!PT¦q>ù¼m^þnÇŸn00/<µ g‡]¯gspp±âȹ🠂 u½^zàêZg÷MOÌÂßßœì,©Äð÷÷£]ûìNN•Ñ_mÛw`Or’ˆ#‚ˆ#ÕAª[Ìœ"zpXÜÔÛÓ^=n sïÞÅŶØàj¨4öêéQYRŒFZ¸ÙrÅéÓ¬ á¤O‘û7s³àúŒŒR˨oµ^0>oê•GBPK) ç‚ ‚ Ô ô: Í+¦Ym°»¶Ù|®­W¼Ü\ñW9ü•-Žê†óÙ8­„Fs=¯X'Š#Ny5öClUXëŸà`Z,®À ÑV+7œ:Å1£‘·aœ„W |C ^¼«Ûçõ½òH-&â8ßý'‚ B-~0ÖªjPËž "Ž”EQÐ4MüUN B¸ÔVÃ}¼~¤æbõV¯õ¾UüãÎ6ø£~}ž9C¤[ý‘ÅB#‹…dV„„¸‚V¤ü,ƒá‚ñ¹¯×^S9ÇyÖfÿ ‚ ‚p~£W€ZØpÖ+"Ž”ñ— ÞÔÚV£YQðs»¨5 KuïÆ´µf-É4˜Ó ÍM&ºå丂‚#ÞÅ)ƒ † ØÅ£'ב‘XkI ¨ªð¹]Qйm÷Ñ´rÕImöŸ ‚ ç¹È sÄ£Ö «‘·ûåEü%‚7µVÉ4ðs‹%Qßjõˆ­á$Ò+ÞÄ™Rz(šVâÐ’’8àçÇ__zæäÐÅ- h»¼<—8’­×{L¯ÛÐbá°×T¿²Ïót:©#¬VŽ‘GqÔfÿ ‚ ‚pž?ë@SUTM­}vKc¿\ˆ¿Að¦Ö¾rOñjPwÈÏ/êªGg¯YO{ÍãÝó¡žÝs^ûÆ^DKEQØä±Ê] 8êUþE99=).tŸ§yÅéR̬4ÅQ›ý'‚ Âù^ZA@Ör/Y‹Ù !cWeW,}%g@VYʶ8ÅYÊî/AqäM¤Å‚^Óð³Ûé–“S¼ µØ‚ ‚ œÿâ(Õ_íï_TîïîÇZEvK#^ÄG¡rÔÚa5&½žÕ!!\–™éZ×!/yyŦYLž—rÀÏH·Æx¬ÅÂéée¶£m^-–§>à6ìãŒÁÀæ  .v+3ÒfãªÓ§‹LÛÂdbŸ— P›}~Ì×—ƒ¾¾Ó75›Ïšâ·8j³ÿAA¨âHE„šæxS–ô®í Ð*GJC=³‘w|”ÖŸÀî7˜o6}L¿Àt°ý(ß Ì·ÃþbÁøæç´!rNýå=~ë>>¸róG/æÏ11gïùS.ju$ËÝþþ¬ ¡´É]mÀÊv{õø/0ð¬©g½Ó–DËRõ齆Ùl b}p0eÍ_‚ðP[}¾,4ô¬á1å¡6ûOj‰ ‰®E¡.áœõESK_ì'W3ýº„ùà߸/~¿“¨ššÏÎïäÒöQøûàÔ”Þw~Jb–Цfñ÷ ]xâ?3;žêHˆþîaMvIiJ¶Åew‰‹#¿¿ÄLJ0kÅFþ™I¯€jìq`;ÌW¶gè燰:×áOËÃÜ&Ð%"Õ©ž#å>~/ñ­Ø^ÒsDª‚Z/0î à°¯/íóòˆ1›©g·»f@9£×“âëË΀r½zŒ¸ñŠÂáátËÍ¥¹ÉDÝŽVö˜ÑÈŽ€n=y²Øòÿ §Cn.-ÌfBl6ô8☜6ØççÇ΀Ô"¼n d¿Ÿòòhl6b·cÔ4ì€Y§#[¯ç¸ÏyÙ롲>·êtÌ £•ÉD\~> ¬V|5 ›¢©×³×ߟ^ÙÙ%ÚP›ý'ç»0âý½K×.âAêÆƒ±ëµa) B{*?Ýu=ÓöÝĬÕÒ[·™wî}ˆÅ9>ÜêØ‹®cßyYqõ±^Î{Mä†g;‘øÎ% ýy+3z_ÄW·ofý„æ8"²å±­„4A¥Ù]j#Ö©}'Ñ7ïC÷˜zCõÎÊãÖpw}VêÑûÑWè]Ýe—˾šBÅj )ßñ;÷Ñ´¢÷×4Ç©ªQëfX„:)Ž|]­Ûrôz6³18¸B6Zu:6³¡˜ô%Ù`ÒéØÌ– ”£×;ʬ ÝµÙç( {ýýÙ[Œx±=0ðœùOA„º‰^§”©iK™Ë{K3ÿ5ní4çåw×òÇå?¤ þÞljw&ˆÃk¯/`΄ßHzõºûÊ/Îö-”’Æ¿»K1ú¯[ã™°à~:·ßA_°ñí`Þt;û^ZÇÿ?K¹–—“mðêåĽ „^ÇË'tÛPþ7l.ÝÛ  fm盩Ïóþ¼]œÑüˆís;S^}”Á|Àº¿äòµ|öüòO½ý;ÛÒí ¥Õ  |üöí´0–¦;”쯃ŸcÈÿðûÂ'h_0'–µŠ‡/{óôe|6ØŸ½ß<Ë䯖‘’úút¼æ!^›z+í—íšDïm_ñó¦4>ð)·.ˆ]ÇofOIyô±ŸZÇÛc>à³µ©¨õ»rÛó3™rUc|\çŽÛð,Ó!þzëÞøa=)ù7”ñ/N㮋ꡯ„¿¡. ‚ ‚ ‚£†#˜{É‹ùèëÚpyû@׺À¶ƒhç«|·‘¾ò nëÕœzAAÑðúydf¤i÷+á¶”–¦øÅP†€¬Wý_"¿ÜÚß^“°;‰÷!Ð+NŠçPç +{¾žƒÏ=ÿÇÆ‰,z:‚ùÏ<Ïßév4ûiV>+~ÑþƯ,]¾ˆ_§¢½>YÀ”8#q“‘´;‰½›^ã"¯!-¶ãÌ›4–—¶´âñïæ³ô7¹:÷Œ÷!;óK/ß–ò3=¿’¦~ÇÒÕ«XñǶ´E¼÷§…+gÌäÁAíiÒ(–v}‡sK¿(ônCBгÁ–º˜ÏWþÊsÜܽ9MÚâ‘hsà¾þ/¯Ôò­™G8chB¯¾iAãÖqÅõ—ÒØPyqDßh 7Æà¯¹{1iššÉ–ŸÖ£õI÷`Ð4_Úº‡û¶§i£†´¸è&OéOþò¿Ù“_x¬ÁCŸà¾Qø(:üôÂSYó0öx‚n½ˆ¦ZÒï¾—™Øæ ?üß.ò¼ýyb ïýåËo>ÅõÝ[Ð8¦-Ç¿È} ·òÝš“˜+á/A¨ HPcAÁƒ„Ä7nŒs¬s $ãÆ ‚pA‹#.Õ¢|c»«­esЉ«Cc.ÌG·°/_£>–”õükíÂ+ &®¾XIÿw§íM òV‚†jw•Uzš’í¶ZK›ØŠÍhv¬V«c a› Pm¶ÂôV*ªÍŠÕjCÕ|hÐ"Å™Fõ¥ž¯™”l3¹‡¶pHkÁ¨¶þؼ˷۰k Ùykv«Ç:kÊ6ŽÐŒ1-} Ó‡ÇÓ%<“{20µ+¹|]»aŒŒûžÉ/çÇËúÓ§ß ®¹òš”>séþŠ ÿˆ8¦Ïþ“¤ZÓδ‘ïÿÞ3âñ·Y±¢’±áK¦ÍøË’3 '+ðÄi“«Ñ†ªˆn…Þi»×ñkeÊCOÌE- °[±ÚÂè_ŒûÈ4×óôçÁMìÏ?ÌÖaùÐëhš¤œBRq B]@zŽ‚ .œ=D¼EçwéA"Â…/Ž”>¬ÆÐøjê’Ï^øŽä<-7?Lý˜ýŠOTšêvóçªcXQÉMþŽg^ÿ”‚ü Á4i¤'eåjv;Á©Ó9(¥¥)a)WÏïš#÷uª£§ îi¼fÃñž‚¸\=UÜ×áȼ¸ž”V¾o÷~³”?>¼ŸK£Ï°öƒû¸âÚi¬=c¯‚ÙjtD AÜÉ…ü¹7Ÿ3[~e£Ò›º¦aÏXÊ”‡?%õÒiü¾jÛ·ocÓì« Õ»¿‚Î1æ©Èã/[Þ>,ìñs–?5M׉W—%°ãßmË‚ZâS  ‚ˆ#‚ BÃ)„$$$¸–¢A„ NQœõR]cFÎú‡´·éß4†¦]ư¸óÃôЦ kx#¾}{&t¦QL+º[N—ǯ%\OAõè?åiz'=Aï6­hÚy›CKKSü¢/ƒ€â¶pQü¨çy™y¨ëìYIÍ+!Û:c£Î4Qö±|G¦ChñXœ½cÔbm0Fw¤1Y·'×µÎv"„ŒÚ4BWJù >˜V}†sÏS3øö—éôÈø›_“òËç‡âD§èþÜØö ÿÜÌÚ_6¡ïsƒÛ¬© $YÛqÇm}hæ‹^±‘‘¼‡L[Ù|Wö<ìÙ´›,µà»=íÛOS¯m,:/6êBSö°`K†«>ÏZ*ì/A¸ð‘a5‚ B (ò`$BÝy0.ëT¾€¾~?žþu;O»¯œ<Éõ±Õm³î¶=Ò<ñPaÞ]á×xfZJš’ì.Ó̰n4ŸFô¼(˜/ü‹ÝCÆÇ!æ½ý%I´£ˆØ(îi5ÐE büUðÀ3“‰{éa®jDÎDþU{p}ß EéIýg3{® "Ê× ·<4ÐG]ÆØ~ïòäóÓéöÚÝô 8À¯/Èîfwðj{ÿRË7íúŽ×…Ó¿gš„Ú9¶r9{m‘ŒªïSª?ÊÔ!B‰¤ßõíxõé¼aö¡ßÇñ”o¨GŒnK7ž`ðH¬ûÿdÆ'»Aiì9ón1¶kZÙó°lz‹W~jÀ„þõH™û ï'7aôKmðÕ2<ý1ˆ‡Ä}ÏOâm"×Å7€Œýl\ºuØ£\gý¹ÂþGA„:Žãi)!!‘®ÁZA.Tô:¥¬ÚÈygwéÜ­m÷áþt}øeF?ñ<·ôúßú­F'–}ÀCï%Gßè® q&cšJõGÙ†‹(Dô¹ŽÓ^$1øj®ëàJ§D åÅ)›x|Ú0z¾D½FsÓ݃Øò±Z¢ïÜ¿lyøÐjì]4Zô$Ã^IG­×‘›§¿Ï½mŒhvÍËŸ!ô~ækÞ­ÿ:ï¾t_d~‘´ï=œ‡Bt]q B]@Ñ4M›0a«W¯o‚ Ôqœ1Eºtéê!†$$$‚Rð@¨)®YmAj+«V®8kÝWßý½ãFaµZj×µû¿piïnR©ed{bñ]ºŠ#Êá¯+‡]{NÊžúâ4Þ{ï=©¡F˜#‚ ‚‹qãÆÑµk<7( a 1!Qœ%‡cXRúT¾çÙb(c YYÊsD‰9"Ô±{€¸@ApGÓÄ_‚ x#∠‚ ¢‡ ‚4öÅ_‚ ÔYDAA„Zߨˆ¿A¨ "Ž‚ ‚ Bf³©VÚ´s‡Tžø«ÚX0ïÏ)G§ÓB\›¶4ˆˆÇ 5Šˆ#‚ B¹¸#‚ \ȇ„’•Y«l¾mÌRqÂ)?ŸƒöòßöítŒï,jGA;Aj1µMÌ„’¨ß ‚v:²'9Iœ!Ô("Ž‚ ‚ ‚V«Uœ ç£Ñ—à`²DôjGAA¡Âë7'B ’qê$:EQPUU"Ô("Ž‚ ‚ B1X,æZa§Ñè+¶ R_‚P tâA¡¼8ƒ² ‚ ‚ Â…€ôA¨ãH0VA„âÑ4Ml­ã¶ R_BÝ@ÄAAA¸…b« õ%GÄA„:H¢ ‰A(k«Pl­ë¶ R_B@ÄA„:†#‚ åiJoŒºn« õ%Ô $ « ‚P!$(« u¢QXÔ¢eðËà #ñS6×¶–ÝEèÕóÉ,.m5-”i?Œ?‡3àKRì*ÇJìÕs8©y—×ÒôaÖçUÆ>Ïrk“_e)ë¹Uue Ây+Ž(m¹ùåïY²f-kÖ,åÛ‡ÛáëØB`»ÑÌüm1‹-á¯Ï¡w}gvÕ±MA¨Ž‡~EÜ ‚PüuRÓŠ\Ð ŸESß#!×}[Ééªk)[™ùìY¶—°~ݨ¯Ë#iá~¢v$Ïã2ôzƒ…«W±º`Y3ÿI:ú‘_öFµîÇ;{,å*·6»"jW IDATùU­Fý.ç¯8¢«ÏÀ©0–ٌؗ¾ý¯å‰ßŽ`ðmÇ}¯Æúþ- :œ§¶ `Úä~„*Õ´MA¨ºxÍLÓEfªA(I)zAOÈå÷qiÆ,žû%»k=@á~ê™Í|tgšIÇkŸeîasñùVt)ÉVçb=Á–Mùtèß?ó!V'êé~IC|¼ò1„µ"¾Kº,]Ú5&P)"?ÕŽ)7«ª–«ÜÊû5Ÿ]ßÍ Ž &(´ýîùŒmÙv˜“™Ñµ>=_û‘#㉠&¼ý¼µé4™[?fÌÅŽt͇LeÅI[aÙyûøíékèLPP01=FóöÚS…6ÔÕ¥,çVU–%ç£8¢‹À˜KŽòé{K8jÑ@Í%íh6*`l2þ¾ëøñŸS¨Z.I¿ÿNF—a´ ¨žm‚ BÕ $"Š‚ ”E)æ-7 kp/LhÊÚ—ßbCvázœ=1lÇøåîkxr][^X°‰mk>ç†ìϸuÄëlË«¹·û¹§CxAa™”x‚?¯kLPýž¼š|„o†DÙ·’ÍgÛ_Ö7ýå,·Ò~ÕTÌJ;Ƽ=Äÿ±yÞótÚ4™‘ÏýCŽË. ;ÞŸAò wYúÏ^ﺙçGÞÌMþC÷Wç³qÉG >8“{^ÛJ®¦¡Ù3XòøUŒ_ÙŠ§~ÛÈŽíkøtøIf\?Žïؤçˆôêº8bŒî@”9‡}Á¯sÿâÏo_ctçPt€Oýf„d"ÃêØ×vúÆhêªe› ‚ ‚ œOâŠ/mî~‘ëò¿åÙïbuÿÐé¬Gæòî"nþðMÆöjMóNWóÌgSè°çK>IÈ­±¬_üdlIdýgC oþlNdõ{} mÿ ·&²}ãÜÙ̧à¸4Ló¯§QH(ÁK×ד0—à‡ò–[Y¿jšñ÷<Êí;Ó"&†¸Þ£yuúåä.˜CR^a>!ƒ§3óžþtl׋۟K³“‰„Lz“v¢íÅ#yòvœZ¹†£ [ê_¼ö‹ö £zÅÛ´#W>þ6Ŭçó¥'°‹8"âˆPwÄ‘„„@Ñé0Ö§Áêg¹õÚáÜý•Ê3§{ 8NAAtáyæ±6$LŸÁšLÏÆåÈV+­Ü!ØßɧaO.‰8û3±×Šo81M£1oM"xÈ \Ò:’¼Íˆ¾æºµlF³& ñqí¡×ë,X¹‚U+W°jå*~Û Çæ\VÝKHh=Ç3’E™I¼xQdẾ³H±•\neý vÒWÍdtŸÖÔ/(7æÆùdf!ÓåTb/j³º!¤!¡ÆÆtkTPB…¢äž"׿CëØ“¿Ÿ×{EKƒ‹y1ÙDFÊi¬rª Âk*ß®]»žµÑzê§ò“˜»ú( Nüó; Ò.ÜÀ¶SÉ iJ¸²!¬)áÖ4RsU¬Õ°MA8ÿpÎXÓU†è‚pb±XÎ^©Y±©€jÅbш½õn|÷¦ÌËÕ±Ýb± ÚT@Ãfµ`±È#v 4»«ÅR¥I‘¶æ¬äî‹næ÷SÎçéAD}êÜØ‹ˆ×ƒèûÑz~…®à¸ôaÍhÛ¾=Áîí‹ÐÓiÊ<–ÝoqôðÈÛÈä›?¦ãGŸs[¬}`,aªKFñåj_Wί¦SóË NÝ7›U¿ô¡E¸?¦õÐå¶\, ¬Ø5»£»UEEA±[p­aµ©hšÍQ?Vš¾l›Ï-Qº¢œ‹E~ÕŽ¢H°IáÜQâx[ê¦4b`×ptèíp)mìûÙ{Ú†åðrV[zss¯úè”@Ú]wቑœGµlAª5AJ§,±6¹„I“:“üÎ –ŸV]Ã?|w%VÛËòÙ®t–Ô l8JûV!(51ô! ¯-ÞÀ¦…/Ñ5¸ //ÜÀ†¹OÓ.´7o/ÛÈæM+øäÊú.[ ¬˜rbÚÒ)>žøøxâ;4'Ä@Ã6ßããéÐ2 ŸRÊ­¬_-)ØaíÌø{Ò*ÜVNþ·‹Ó6Üò)ÎGnû¸Í€cŒéA v1gÝÉ:=„F†Õ"އõßNþîÿžEK3ç¹Xæ=ûÿäæ|:ù;ü&üÄ’%s™ÑyS_]Å­š¶ ‚ ‚ Ây"ŽhÛõÄŽ|ŽQ¾‹ùtm>jAÃ\} ²òã£Ïð톽üo3œÎ®Vc¸;Þ¿f°øR¿q,ùÿ’Öh—vhJýìmœlv ýÛ4¡I“"tžÇUærñ3ÊZn¥ýÑž&ÊþZŠESÉÝý#ÏÍÜᘛÞÅÛ.\AK¼ŽÕQ–.újž¼9„¥ÞÅËs6³7å0{–ðÕËSøÒ¬VÄG„ C)·LûãÙ[~+r[Î_ó舯kh› ‚ ‚ Ô¼8RÄJÏÙS»ñÈS½ùnâ:ìÎõº(†ð#'Ÿ~’i×ôá ¾Äö»“ÙŸL¤ƒ¯Vå3—߸´rxMJ×Q46ä³{Å.‚ûÚé­àñ ¥­ß¥’Bê†jp÷ƒ!Ai;K!v‹¬þ¶©Â2ú-«5LƒÆ¶ÓI[vhub=õi¦0Ož–þ¶E_orÉ+‹tlª³;Ũy›dx´cã}ñ{švºÍCXl¡êÚ½‰†´«£º!’7/WKÿØ¢[ŠžÓàZÊUoG€`PcŽXBÂÔºŽ¡‹óUpp½77[ë²m:©]¶y*YÎCKTV £ômª²Œ~Ëj’,jÐ1^Ëç¬×¤Ù>Å·m¡û5Ñú]µ,Ï"«‘¯Å¿¥ê“ý^Y££Õ¿_S]Ö#OOÿ–#—Å®v§´Ñ…Íòôã/ÿ(%ݧ°Ø(5;Ü¡¦Ðu•ãZª7'Â@•p8’«|&8žª3±†„(ÒâÕÞ|ß‘õ^2 ¤ˆ(›,ÆáGô —óHîQV8R´ûIu•ÑoYž;{ãNÍßå–GRê¦T­ëÕBb-JÉõjǪ=Úqhû¬Íü=F]úŪÞÙÚ£Á­,ú{îfÍÝæ5Ë’•ono =‘†!K9®% zpÂ!Ê:TÅqŽ,+ú^ø¾òáˆQ´õ„$ɪփºèÚV¶"Ûv8ç$ ?ô!m»ž˜‘ªUXF¿e5 I†²2\r:–Ï«U 6sutãú×»¾:%Øu¸ÄžL…[ Ù¢£T×’¯E©ùŒ':”ú˜ç,ǵø¯7':Â"´ì€r<ÈWãq¼.·r ›bÃ,GÖ[mŠ“r³½ò–ãüÆQ–E¶ñiÛ’uz~¹EI²Giì°úÚ9³–d›[ùÜ.í÷I¾*,cie=4®‡Q¬¼’¤ðXwFCE¯Ü¤ggek_¾O! [èþ¡¶2®Ïÿõ—çZŽv\'&ÂÀ—Ç[}ÇÉÍÑÚõk*mÌ–K’5"Bm¢½Úº#O¹å8wiå4¼æã½×ë•Ësä1ß•™­¬CB­Êõy•¾/K3j+£ß²Z½ò’áóÉåñšÓíÊüÓðz勈T#[®¾^–¡íù’dQT\¸"-.y<^åff)ÕˆUÇx‹þÈò 2¬ƒÇö–ãZJ«7'6¦òü… Õ9•¯7O,ËRDÇÓ:Rõb4¨S5ÏNÕ¼]žJMk U㺑jg—]VÅÅG¨ib¸âì¥èÞ2–9•¯¹°Ä2C†<9¹J3ÂÕ­qˆ¬†¡¸DÕ#R‡ºÁx³Ó5k½Oɧ·ÔJŒ U“¦‰êÛÌÜÞ¥ÐñÜyZºpµ–.,y®ùŸ,Öür\K¹ê À ‡pðû _³Žs¼Ž¬e\G¿òEŸä“+8ÛWuÛP›Æ…` 5á Ê8ÉL à„QíÝjjX9kS@U#€ Ah{ï}Å+5: €Ê#ü>ÈSÎ`.+€àB8ø}7(g—@p!üxáZå â²âˆ¼¼\*'<ÂÀˆˆH*8†òr apüX©ÌG@P#ApP¥Žd9)Tj ÂNgŠŽd*ðƒp5ÂÔG@P#Ap5ÂÔG@P#€XŠ3E)Δc~^‡#YÎãp^ "Gàu(1$Y }Páj„# ¨ŽÀ *Ù‘\æg&Â8 DF€ÒŽ€ F8‚áj„#€jáp$ËéL¡"PãŽÀ ÌéL‘ƒÁX€2Ž€ F8‚áj„# ¨Ž€ F8‚áj„#€jãp$ËéL¡"P£Ž€ F8'(§3EG2áj„# ¨Ž€ F8‚áj„# ¨Ž€ F8¨VG²œÎ*5ᜀœÎ9ÉTÂÔG@P³S€ê’ÂX#¨h9¨Ń‚ÔT„# ¨Ž€ F8¨ÉŦNfjaÔP È ¨6‡Æ@ FË@µs8’å$ @ E8'§3Eº°#Ap5ÂÔ˜­¨FÃP›ü|9rr”œ-GNŽFtîLÅ@ B8‚Ê} C×ïÚ¥1éé’¤¯ôZ£FòX,Tޤù+V¨Ž×KE@M~¶¥ P7îÚ¥Ë÷î=üùʃï_nܘʑF `ÌTÊèƒ-F ëgj†.—.Û³GŸ¬YCeÀA´‚À¸}û42#C=rrD‡'(Š–#¨”™ %–Íð³ Ç×ÃÛ·«'ÁŽ3‡#YNg €'°pÄ«>ü(§ó#×ðÐ.Eu¼DÏ|ñ£~œ=Gß¾u«ú&Vç:ÔD/7l¨÷ë×WšÝ®4»]ïÕ¯¯W5¢b€ãÄéL‘ÑLEå@ò`QÌÉ7ê¦hm¶qdqXG]ûä%r¿4^ÆÕ=Ëê±ûú+ÖRMëP#y¬V=߸±ÎèÒEgté¢7f¦@­rÔpÄR§§®¿¥ž>yöG¥šx#´ùé¶HÓO“ÏÈÑš¯¾Rzò(uˆ¬žuÕ¡ìY-Ñê~ýíjöÅzzWK )´*$1I1V*Ým~ödlQzè5вjE5¬SޝÖV²3åHûÏ5¹Y3Ù}>MO×àÌLµÏÏWGùV«2ìv­ŠŒÔ¯11ú>.N«™_%ºÝ“ž®ÞYYjŸ¯XGù6›v††jIt´¦×­«íaae–£U^žN;p@ÝrrÔ¢ @uÝn…ûÌzͶٴ+4T«##õSLŒ~‰‘QF Â×ä#9ù¨ûÍÕ-[*ÄçÓ™pà€:äæ*ÎãQˆa(Ãnךˆ͋ӷññ‡ë¢:îË!}ºuÓ(?÷%Ën×–ÐP9££õsl¬ÖEDTëw&ÑíÖ™ééêsð~Ç{½’a(Ën×Ö°0ý¥ïããµþ(å(ë>•¶®´{'|8ât:‹> 9º+*ù:ý»õ ÝóìNyÃZR[U`lzºæÇÆê®íÛÕÜå*².ÄçS—KÍ]. ÏÌÔM»véáæÍåÈÎÖ•{÷*Ä0Šnïõª}^žÚçåéÂÔTMiÔHï4hPê¹_Û°Aõ<¿ëâ¼^Ååå©c^žÎNKÓ†°0=Ü¢…VEV_³Aû÷khF†nݹSÝîëëy<ª—•¥þYYºbÏÝ”¤"«·ÑgkÖ¨i)÷¥±Ë¥S²³uÃîÝZX§Žþ¯iSí8J U^6ÃÐ5»wë²½{Vì~KR‚Ç£GÉ99ºrï^͉ÕM›*=$„TýHâ(¶*D º÷Pó.côáÜë%K¸bꄪÏGï)îš«ô~Úfˆi¡„i‹G²Ç·P‚{·våøä®†u'ŠÃÐK7´m·[¯oØØCµ¤›wí’OÒ{¥$«"#5ðÀ€Ž×º @o¯[§«Ú´Ñʨ¨j© «¤'·l hÛ.—Þ^¿^W´m{ÔÖ•Q<)Í©YYšöÏ?º£eKý]%çŽôzõ¦Mê™ð>gì߯n¹¹º¶ukmço4¨àói)ÜÚøö…:µß 8PGÜ¡…ûWë© /×›ë\rmýI \}uÁ)‰²Z¢ÔqÜ8%¤|«µ¹ª–uÌM»v©IAßuåmnztÛ6ÉO †ã!ÚçÓã[¶ÈZCÊãõêéM›Ô À@¥,ÃÐÓå F©ïvë• T§”VA€²U|‡‚Uzý¾© ¿åÍ™óž:é=úø/Ê4ªib“tþ¾}~×U¤‹L›ü|õ®À{ui›Ÿ¯Aû÷טòÄy½ºgÇŽJç¢ÔTR‰znìvë¶;ù@ØÞ2çWÝ|Ú¯…Ê^ñ¾n;ë}?WǺËouêèËÄD¥DE)ÓfS#·[cÒÒtÙÞ½~oŠ!izݺš^·®v‡†ª±Ë¥s÷íÓûö•H¸z•ò½2"BË"#53!A)QQÚª|«U>ŸZæçkDF†Æû9Þ©è:uŠ,+>¨__)QQ’a¨m~¾&ìÙ£Óütœ™©¹qqÕr_VDDè½ ôgt´²l6…û|jàr©c^žFfd¨oVV‰}î߯fÚVÁñG"¼^]³gß{þEb¢¾LLÔ†°0‹šhHf¦.KMU„¯hw³±ééz½aCí -qŸüÝ#^€ò†#¨R7´n]äóÖ°0½Ü¸±òl6Ý´kW‰íiÞ\ß$$þ¼1<\O5mªÃйiiE¶m\J7Œ]Þ®]‰å96›VDEiET”v„…é®b-!:äVo¿¦g7Ö‡õëY¶<*J··l©W7lPŸbaOçj,ÏeíÚÉWh–ž›M#"´1"Bß&$hdzº&mÝZ$@²J:=3Sï—1nY†ffªŽ×[bù-ZhV||‘e#"ôzD„ÆÄèõëZ¨‹‘MÒðÌL}P¬.šÄáH–Ó™"‡ƒp5‡•*¨Yf{>¤p0Rاuë–XæïA;P3üœ¿iŒ©Q–K{˜·X4µ^½‹ëû™Ù¦ªøÊ˜¾X’¾KHÐ ?÷â¤J6ýü´Žù..®D0RØÊ¨(M÷sï{Ö .P8ö€Š¡åH ³§P—ˆ@ló³½å(û4r¹tzf¦99j•Ÿ¯ºn·"|¾R¿ ±Çq O㤄çYgÆÇë¬ôô"ËZçåUøxíýìûUbâQ÷›§KRS‹–#?Ÿ”áH-—g³¼m=—KÿÞ¹SC23ËÕd(ì8†ûí5ï+ºÎÏTÂ1•h­SÏOK˜5LW¼ÑÏÔ½ ÕØªNT„#A¢Cn®^Ù°A xˆ?ž}¯¼K«Ë\?TT%Â-ar½ò¬%ïL¨ÁÔNP›ž{qŒÔñxôâÆ FP’¿ $¿-xJìë' $lñ7¶L•Ÿ4”ORAàâÔTÕ;Žã†œh:ø#$£áȾËZ0vˆ¿±JRËÓ ‰V& ‰n5AáôýûK,[®iõêiyd¤ö†„(Çf;Ü…Å™’B¥•a\±©“%iƒŸñ?µ>"BÍŠÍ443SË¢£ËÜoŒŸr¬`¬’Cêx½Ê²óWðdš”XvM›6Êðó`ÜÔ϶’d1 5pücm|jª†ef–X¾¸N ó÷èh *`—–¦ÙññZåwŸ¡é§”£½²³57.ŽÈ ÅI  TÝj‚€QÊC~C—K6ÃÍ0TÏíÖÌL½°q£ßcÔ ’ñJžÜ¼Y½²²T×í–Í0åõªu^žÆ¦¥éíuëtÏŽ%öÉ·Xôc9B†Èbu9;>^Å‚§ÃÐkë×ëº]»Ô:/Oa>ŸÂ|>uÌÍÕ}Û¶é‰-[J·ÀbÑ¥”#ÇÏX$÷nß®323UÇã‘Õ0T÷àwàõëùÑÔ"Ń‚ üh9v‡†ªE±!×ìÙ£köì ø- ´,º` ÍÌÔP?-2ÊòIݺJó3nˆdSÅÛÛÔu»µµÐ%™v»>®[W—¥¦Ù.Ü0tíž=º6Àûôq½z¥N}¼%,LŠQR×ãÑ7oæ‚cÎáH–Ó™"‡#™Ê@@Ë‘ ° &¦ÒÇàgÜH+"#õJ£F¥®ÏöÓbãäììË^kØPÂÂ*\Žõááz­aÃR×ÿËÍ:Áù â†p$¼_¿¾öWb6I¿oŸÚçæR™…,‹ŒÔ­-[ÊUÆô¹ü :aï^EëZ“o³éæÖ­µ-4´Ü娦[µR~åø¸^=í*¥u j·äb­/’i”áHØ¢[·ÖžŽÿŽŒÔV?è‘>ŸN"‘$eÙlz­aC]Ù¶­ÒR§_&$”XÖØåÒ~º³ì ÕEíÚéÛøx2É®OÒ× º¸];í=J¨’m³éÆÖ­µ¥­SPs DF€ŠaÌ‘ ±22Rçtè qii¸¿Úäç+ÚëUÕª=!!Z©Ÿccõsl¬â¼^]·k—í߯xGi!!ú.>^Ÿ$&žðõtU›6’‘¡äœÕw»íõ*ÛfS†Ý®Õ‘‘Z­ãâ”`Kœ‰‰jàvë‚}ûãõjoHˆ~ŽÕ› øÝ>Ën׃-ZèÍ tfF†zdg+© @1$é€Ý®ÍaaZ­o´­aǦðp]о½ÎLO×àýûÕ./O±^¯¬†¡|«Uiv»¶„…éÏ£L! '‘cÀ‘œ\#¶Ï±Ùôaýúú°~ €D IDATý2·Ë°ÛõD³fz¢Y³*/oy¯­¢ûTÔŸÑÑU¼Ù°¡Þ,c<¶„‡kJc™TTÕª/êÖÕuëòÃÇ–Ï'­X!-\xäµuë‰nµáÌÜnéᇥ÷Þ3?_q…4q¢TÕã•%&Jåœð„87€Zpf>(=õÔ‘ÏOÒ!ÒYg™-kŽfåJiÆ é·ß¤þ1›k®‹•Z´zôÆŽ•FŒ¬ ýèïþ†´aƒ4eŠôãæû‚óíÛKçž+Ýq¿  G€ÚhãFéŠ+Ì@Â_°“#mÞ,}ÿ½ôðÃÒg˜ÔUiÑ"éöÛÍ`¦¸;Ì×âÅÒ“O–ï¸?ü Ýx£ùð_\Zšùúýwé¿ÿ5ƒŸW_•š6-ß9Zµ’òó‹.KM5_+V˜ÁI³fÒ£J&”}¬!CÌ@ÄŸCåýë/éÍ7¥NÌé“{ö,}¿ø¢t×]’ËUtyzºÌ$%ñ»*ˆÙj€ÚfçNéÔSý#¥éÞ½jËðê«ÒÀþƒ‘Êxì1³u…¿`ÄŸ™3Ík[º´|ç)Œø³m›tå•Ò%—”½}y‚ŽU«¤*Vo·ÞZ29Äb‘î»ßPA„#@móðÃ¥·Tðû¯~«tÝuUwþ×^“n¸Ál¡R•{Lzä‘òué‘ÌÖÇ›-eªÃ‡š­tJ+Wy[ä噡Ky¯³,£FI]»òÛ*ˆp¨mfÎ,ßöÇK-[V͹ÿøCºå–ª¿¦9sÌ.,•–vôî/•ññÇÒ /ø_W‘.2+VHsçV]ùßP „#€ãÂáH–Ó™BE@Eƒ€â®»ÎÕã1[$~}ûmÉí ¯/»î’Üî’Ë›5“žxÂì.’‘an³s§4}ºÙ¤,†a.ÅËÒ¼¹ôòËæ §ùùf—’íÛ¥Ï>“úõ+yœŸ~’æÏì:F2Ç6Ù·Ï,ëþýf`ñæ›RïÞþ÷™4Él¶¸ž=¥SN1»ýý·tà€yöï7ÇF¹åÿƒ°~÷]ùï}x¸ôøãfݾ‡}úð»*Y€Ú¦yss@ÖžyFŠŒ¬Þó.\(-XPrù¹çJï½'EE]Þ¨‘tþù櫬Ùq~øAZ½ºè²nÝÌ #.®èò&M¤sΑƓ.¸À J ›:Õ åh¾ù¦è瘩sgóu啿`¯÷ÜSt›ôt飤ë¯/º¼~}spÚâbbÌ ¥wosØÛn+ºþ¯¿ÊWÿ6›ôõ×ÒСü€*F˨ŜÎ9ÉTSã>ø 9–Eu*(Hfˆ1mZÉ`¤<¾ü²ä²7Þ(Œy’±š-UŠóR”—Å"Ý}·ÿzž5«bǼ첒ˊ\Gsýõ#@5!j›{ï5§„-ì¹çÌ®-·Üb¶ððùªþ¼?ÿ\rÙÝwK!!•;î”\Ö§R”õjÛ¶ä~U9(kñ"’Ùõ¦4[¶˜÷áœs¤ŽÍp'$Ä,k||Éíýu*KuŽ©9 ¶©SÇ̳øØiiÒK/Iýû›]Zn¾¹dw•ÊØ¾½ä²ÓN«üq7mªº22Eo N:©ä²½{K.Û±ÃleÒª•tÇÒ_HkÖ˜cŽ”5£OyËÚ±#ß} š޵QÆf ‘gŸ•êÖõÿÿòËR—.f ˆª üµt¨_¿òÇÍήºziܸêŽQrYñ9ý%9æÀ³åm­SÞíÃÃùÞÕ„p¨­ìvéöÛ¥­[¥wÞ‘† 1í,þþÚkÒØ±•ïjc÷3ŸCU•í–S˜¿Öµo_Ée…ƒ¨Œ sÖ›ÔT¾‹@-G8ÔvÒWH³g›Aɽ÷JaaE·™=Ûœ¦¶2J.[º´òå÷×òe÷î’Sòò7hlE-^\rYÓ¦GÞ?÷œ´kß?à@8œH76gqùôÓ’ëÞy§rÇö7ê /T¾ÌÅ—•¤?>þu9eJÉeýûyïo–.]Ìêï¿ÍnHn÷‘à@E8œˆ.¹låÊÊsÀ€’˾ýVºçÉë­øqý êúÀþgÇ)îùç¥~¨Úº3 éᇥ,¹nøð#ï×­+¹~Þ<骫¤®]Í–6‡º"mØàÿ\Õ1«€r#7G²œÎ**âí·ÍPáùç¥ß7ǽp»ÍÙQþùGºé¦’û”5sJ Î;Ïœ–¶¸§ž2Çúxás€ÒÌLó\»wKŸ|â?¨)ì_ÿ’¬ÅMrrÌý.ºÈì*³c‡är™×¸e‹4mšÙŠãöÛͺ(¯±cÍmssÍcfdHþ)½òŠÔ³§4iRÉ}zô :òÙ_]¼ô’ÙµÉã1_;wš­xFö_ŽÌL¾Ë@ `§ ÇC ¡TγÏJ«VIó羿î+åÑ©“4fŒôõ×%×­\)Ýv[ÅŽ›”$]~yÉn?>Ÿ‚L›Vöþ3fHééþÇD)kŸ3ßÞb1»+Ö¼¹D6i’ÿ`¥4kÖH}ûò}Ž3ZŽ@-åt¦ÈáH®•e/Œ”@9ýðƒŒ”×WTþÜ/¿,Õ«Wõ×ôÌ3R«VÛ· @š:µzëü‘GÌÙ€ ;óÌÊ·*Pa„#@móÜsåßgð`éúë+î¦MÍ–#þf˜©Œ¸8sŒ6m*¶e›-ÅbŽ?òðÃ%×ÝuWùZ«øóòË’ÓÉw8ÎG€Úfܸ¢SÊ–Ån—n½Uš9óÈà •uÊ)Ò’%ÒСm_§N`ÛµjeN |íµ’ÍxyZ¶”î¿?°m“’¤~ýÛ¶[7sÀÙ‰ý/Ò¨‘ôý÷Ý‹>}ü?ÙÙÒo¿ñŽ3ÆsÉŽä"]i’ki÷ 8n®½Öì"óùçÒgŸI))Ò®]R~¾n¶fèØÑ°õ¢‹Ì@ ª%%™Ý{þøÃ,Çüùæ@¤iiæàª‰‰f0p 9{K‹76Vzí5s¶š>’~úÉÏdÏsàÔ°0³ÕJË–R÷îÒˆÒg¦Øíæø%}ú˜eŸ:ÕÌvÇs|“ÄDs*äþýÍYi† ñŠvòÉfùÞzËÃdÅ iÿ~)" Mzõ2;Ö¬›G‘¾úÊ@·aCóþTE‹„#€ÚH’o*&4TºðBóUY†Qñ}{÷6_U}Žfͤ»ï6_Õq}Ç–·2bb¤;î0_e©WOš2Å|Uç=Pnt«Ap5ÂÔGǕÑ,'ãŽà8"€ZÈéL‘ƒ^€*A8‚áj„# ¨Ž€ F8‚áj„# ¨ŽŽ;‡#YNg €ã‚pj§3EG2TÂÔG@P#Ap5ÂÔG@P#ApP#8Ér:S¨s„#P‹8)r8’©  Ž€ F8‚áj„# ¨Ž@-‘rp&—ftªáÔŠꎀ F8¨1Žd9i€cŒpjdG² I–BŸT ;Uµ¡Põh9‚áj„# ¨Ž€ F8‚á Fq8’åt¦P8fG p:Sä`_ ZŽ€ F8‚áj„# ¨Ž€ F8‚á Æq8’åt¦P8&Ê Glõé®7¿ÑÏ‹iÑ¢ŸõåsWÈ{h‹¢:^¢g¾øQ?Ξ£oߺU}«s'§3EG2T“²“ߥ¼{«Æôï«~§]ªB/×ÿÝÔYá’ÖQ×>y‰Ü/×°acuϲzì¾þеTÓ:€jPf8âMûS?.Ú¨^ÉpíÐï¿ìTD“…H m~º„-ÒôßÓä3r´æ«¯”žYg8&—²ÖPöŠ÷uÛYï£u|œÎ9ÉTP˜Pc$à8°S€š¤H@˜#Ž£ô´}TB5Y0ÿ' 1J¹¹9µò=€-GSÃFŒªÕïœxh9à˜*Üú¢6¾pâ¡å€cjÁüŸUkß8ñŽ èÌ›3[¡¡a%ÞãØ [ €š†n5€ËáHf:cÕbøÈÑ~ß6kæ * (§£ÆhóæÍúëÏ¥JMM-s[«ÕªÄÄDuïÑSIIITŽ+¨¡ ú¸\~ßwÑe¨, @SßG›7oÒ¯ ꌡCÕ²ekÙl6>Ÿ Ã!C·Ç|oø”uà€öìÙ£_.Å"µh‘D%⸡[ ‚Ýj€êñÓܹ:餓Ԯ]Y­Vy=y<¹Ýn¹].åçç)//W¹¹¹²Z­jР’’’4oÎ*Çá‚N ÝjŠ3²×èó‰k@›x…X,²„&ªí  zò›õÊ5‚¸2=[ôŠ#\žüGn¾ZA_?n·[½úô=Ø:$°F—.]åvóíÁñE8€ ãrîNSø}iò×½§u飇VwÔMþ©=¹ùÊÚþ»Þ¹¢¡æßØ]½nþV{¼…vð¦jÞ¤Ñjm‘Å¢ÆýnÐÔuy—Ï»wž?ï$Õ·[d±XT§õ`ÝöÑ:åÖôîÐGgÅÊb±hàçUvþò=QD©Ãè‹uVטÀ.<õ|·pu}vCÕ„9 ty¢YOE_¡1sùê³ÒAˆŸk+oýÔr†¤ÐÐЀƒI²Ûí2øk „#À±Užn5FÆ<Ý>â~åÜÿ»þüèß§•"Â]¿­ú_ú¸fþ=Kc»J¾¾ñà±G[Þ9_gNÜ !oü¡U)ßè–¨©ºxøCZœ@á|»õ饣ôÀ¢NzäÇåZ·æ½5.SSþ5ZO­,âx´íÃkuÕZ–"Ë+uþr?QÔÕàÇÞÒã#ÊvÐI ¤ËO®SŽú¬®'®ã\?5„aÚ±}[¹BàX"@Ð ¼[MV½t›fõ}[ï^ÕA?ÿ Žë§G?¾SÙO=¢ùû%¹þÑûÿýYqW¿¥§þÕKO®;ß|R'oySÏ,:pôÂìÐâ•ùjwýúzPµißK<ø¨…lÐÂMù‡7sozWW>©[ß¾QíC í_Þó»Öhr‡0uú÷u}ÿ$Õ­¦ð†}uÓ'›å:¸‰/s±^¸È¡ºV‹,–Hµz·¾Úzpmñn#×åÁ7tÿÈvŠµÈ–ÐC×|´I.Ðwc:èöåZñï6 µXdI¼\ ²s´òí+Õ»QˆÙê#$QÎ~YkÉ.¬QjÖ¥»zôèa¾Nª¯msÖªÎÈ›5¤¾5àú<"_+_ºD}[›-r,öêyé9³Ž<ÔyëõÉÃÔ.Æl‰Ö¸·®ûlµfø»¶ý…ëÇ­uOwUHÒ=J)tj#s–΋Ñè¯ÒÌyëõÉg¨u´yü„®çé©iòÖâ`dùß)ú;Å© ë×I$  |Mç U)àn5ù«õÁGÒ„{+Ñ*å­}W—u‹‘ÅbQ½Þtßøv:ùÙ R«ñº¶é¯šúwŽŒýkî†0u?³³¢ÆÞ°¯†´ÈÒÒ_¶¨@nmx¶«,uÎ×Ü,?ç o£QÃiëgSõën— ï­øô-ý>@t;xD×z½1áQåÝùŽnê^ôAô¨ç÷[#ZýâTÅÿg©ödeiÝ«ôõ%gjòßù’w§¦_r†n[ØY“ç¯Ö:ç4ÏzYã†MRJ©=u\Zùâû »göäjÍ3õéÕ×é‹=Ñ9cžë¦.Ϭ—Ë0d¤½§Sö¾­K®ÿNmþó‹Ömß¡MÎ/4qt …YÊoÝ›>Ñ+‹cuÖM”` °>‹ðÉeí¬«¦ÌÓ?›7kռǕüÇí}Ï"eK’/Mß_ª.xWºøƒ¥Z·y~÷9¢ëh„Ÿkë_ä!J7AwN×´Õ‡ÒC™¿¾¥½ƒtõ€Y|éš}Óiš0¯½šµJ›68õÞ9©š<òB}¸½öÅ#†aèï§2ÓÓÕ¾c'¥§íÓÆ ë H@88:¦ñ€êh·_FŠyNѤPɽNSþu«– úŸÖ¥§ë÷‡4ó“uÊ—$[œÚµ•6mË‘{ÿv¥±jšrä@öxµˆ—2¶fÈ#«Â›8Ô÷”еû9©%V§¿4[O6zU§7 “Õ«®×oÒ¥ŸOׄvIZûÊeú÷½sC;…ÛÝsÔóû=öÿt÷Àº²)TÍÆLÒc=ÖëWSt`Û—zú»]üö+º¦µI>Kÿ7I]×¾¦—þ,½ŸNýñOéÎ b‰PÛsoÕ?5su®ßm=›•fo­ÁÃz©M“ÆJê2Pç]1ZI¡å½³ZóÁëZÞp¼nè`})Ç÷j°jÛ¢…:¸RÏøHÕCmZ´‘cØeºvxS…PÂc5¡ËNMŸ¶Êüîúõ­92_­þñyw}­‰G莟Õåý;*©U²Æ<ðºîm¶P¯ÎÞ#_-û­ýò—²²öëô!ÃÔ¦m;õìÕGì׿M›ø‹„#Àñh·oö^åE7Q¬]2ÒëËMÝõȃcÔ&>^­Ï¼_“†Äüµ!w¾O¡!:zc›š\ð~ý˜zFøKdÒôígêîÕCõüwKô·óg}pK¸Þ8w¼ÞØà–kÍ ºôÿìzàëÔ6´ªj$D-z·>ÜÒD¶ur$h_Ê:íÛ²D›-í5¼[Ìák iÜOýêgèï5™¥tõUÃÎu8r²ÕQ½ˆ|¥åø´ïx™®é¶TW¶l©¾çÜ ‰oý¨õÙhY÷·Þ~wƒ’.½ZɑէŸ»®½ó×¹É Ì®1‹âF~­Ì´­ÊôHù›i½ÑIczÆËR‘ª¶7ט Ý´û“iZ•/ õæ<‹†\}ªâ,Rþ¦Z›»^“º†\6´ƒî_§´-éµnÆ› iÀ 3äõzåóùdµZÕõ$‡5i¢Ð0¦ÐápÜÚ­ÆUWáÙ»´ßc ’E–ÃOÄ…Þç­Õ¬e‰:½S”ì±M•hÙ¯íé…c=Ú’!Å7—ý(e3öý ÇßMÕ°—§èÖ=Õ5y .yâMÝ’8Oÿ}gµÒW~«Å{ÑÍmÃÌçØ‘úÎeè—sdéý¦vGWäü†¼no¡CÌÏG””¶Æbµ”8‡QÚœ$‘'é…»´bæ£Ý,M?<Üž|åyЇ YdÈ•ëRô÷´|Ù2-;ôúõeõ³JާÑòiçªQBEÎïÑÆŸR”q(‹pïТßÒ”˜ÜFu“z)ÉX«ÙË âÞù«~ݯnâ*ð@a•Í*¾bÁ‡=^‡MÐ}ÏO×”4hït½íÌ ü°F†¼ü¹Ò»_¯ñmB®Ïâñ‹kë¯Zæê¡Ûo¡õ"e³x”ºl¹ÒöG Oê«6–Uš±4ÃOXRʵGšŽÒUÉ{ôé¿è‡7’}ØU:%îÐñû©­–kú/©µ® @8Ô"ÏVÑY—žS ×ŸúYövºiê3JþáBµ‰V×{¶kØ-µùÅ»45êAýðö85°I m§KïZ¢5ÿ g®¹WKš_­÷‹‘äÕŽé—ªßЇµÔÏ€¦Öz§êüîyúúæÛôúÏ+µaíb}úèuznS8«½¢cZªK·nêvèÕ¥•bíÕIê¢.­ãe?êùýsýrnš²@ë·®Ö÷O\¥GW´ÕÕ×:Óô,Ý9Ò¥®ºYoýú6.ûZ^ú–·¿N7÷ˆ*åÛc•ÔÔ®­sÖÊ{µ/=[Y)Ïëž'?Òü›µsçzýþÕWZén¬.B%ù´?å#½üÆÚ^FŸ_ê½ômžúÞt¶ %r´ú,Þ³)¤a7µ´®Ñ—?í[†rV¿¯OZv¸‰Œ­ÉÙzø_aúôÒiòŒ¿´aë9g¿¯×gm—ÛϵùãÅÖD#¯ê®½ïܬ;Õˆ«ú(öðªs4ñ²Xͺò\ÝÿñïúgËf­]ò^»ïVMYU )_)“Gªß¿>пe€p4˜±@U x¶…«ÛÏhМ+tÕûëeéx•>\™-Ã0”¶ä]=1u£r÷ý­ožåïpjÑokv×)þtÞN·|õµîëð‡îÔEm:ôÖ¥S-ºøÍÙzf@@Ò‡£œßŸPu¹ûµúb¼:´è¤/åëÒißéÁäpÉÖXüïG=Ê2Ýsj{µN¯i‘7ê‹ïRrDEj?Nƒ&>¬SWß,GÓª×ö&ýá ÕίÐØn-Õ¤I[ þÏýÎúwÇPI^¥Î™¬›ïz_ëJí…áÕ®o_Ò\ãtÝ|f#Ù*QŸ¶&ãõÖ«£´öÚÖŠo ÎVûÎVâ¡ÀÅš¨¯-дK\z{¼9 ë)—OQJ®E?×ö›ß1kmj<âjõÌY¯]uÎÔ•½ …VÖ ›²H_Þ§ן¢öI-Õá´kôÖÚX%ÅÛ$yuàŸßµè¯mÊ£i Pe,†a·Ür‹,X@m@ ÀL5Ô €ê÷èC÷køÈÑr¹ 4oÎl 9ZŸMŸ¦‹.› ¬ûåv»5kæ ]tÙI†rV¼¦‹†Ý¯ÍCÔÄ[Î×ÀN šµYKøŸžü™š¼¾X/¨S±:{R´F“»¤Oo\«¥7'uL”cï€fŸ—¤K"¦kíûCgáû[SM}ÿmݾ£Âû_{Ýõ ÑûõóÜ9úãϽøâ‹T,Ž ;U€`p·I’EQ]®×+OÑ´'&iòØGtÖöÉ– öÎÒ„g¾ÕÍýki0Rä¯×ìU­uûç Fj5®Ö:{ô0>C^ÃáóÉkH†ÏPÛ˜Õë+ºÜôû<W„#Pƒ¤ì:’âLQ2­$ ÚîFSz—š¢¬qɺøÉÏuñ“Ôß1Þ]O¯\B=Ô2Yùy}†|>ßÁ? å»<òùŒËê0¥/Ž?Æ€"¥Ø˜)Œ±Õ&ÐÙj‚Bh=°¦@)5²K „#:åëV8Ñ èT¤[ àÄE˨!’É2¤Ãú1æHQLç  *UI·Ï½âW§'ÿ‘Ûßç`àZ£É”üÒfy‚áz¹ÇY³5.&Q—ÌÏ®²Óú2jâMd·Xd‰§Y«ßÒÉáíôØ*÷ ¨"„#PÃ$;’ F šÜ­ÆHÓ'ý-²Xнê_£EùQê0úbÕ5&øþQA+ÒŽ IDATíÙ¤»'jè§©2‚©ŒÖcxÏ——6O½E“×ÓŒ©Jß5Uƒ´Ñˆ Ǩk¬UòlÔóÝÂÕõÙ UÊÕ†û TºÕ 蔯[EöS_ÐÜçû*êÐ’°újYWQ½¥ÁAXÞÝóôñ¦Žºº_¢vÖ‚2VÙ ÀÖº\­÷Ü'—K µ*ŒR'ï–­íPõkYW±’¤ÓôØ»§™»xjY5-GtÊÛ­ÆžÐNÉ=z¨ÇÁW÷.Íå  ‹EÞz}rÇjm¶8IèzžžZ&¯t¸kC—ßÐý#Û)>Ô"[B]óÑ&™%òµò¥KÔ·u¬ÙZÅÞ@=/"gÖÁÿÃ?¸·Ç¦jò˜6Š´X–4JOþ‘¡Ì?_Ôø.æ~ ܯ¹û¼•)Àø´…Ó´¦õx ªo>Nøö/ÑóçwRŒÅ"K‘k|™‹õÂEÕµZd±DªÕлõÕVW5_á2^ “©˜¦7kqž¹|×§Êj‰Ñù?07͘¡3cêšE¹G/¯Ÿn5¾´_4yTkEX,²Ô=Y×NÝ üƒ©Åƺ+´ù¿õgÞ‘¢é3uv\¬Æ}“.ãàõw¾û9Ý2°¹¢,vu{bµ\‡ÊßjˆRωVŸ)»”?w¬âŠ´`j§ÇVíÓwc:èöåZñï6 µXdI¼Xï?~”ó–HAR5ûŽ®ŠlxŽÞY—_ê}G€È1™­Æ—®Ù7¦ óÚë¡Y«´iƒSÉ#/Ô‡Û=Æ»´òÅ÷vÏí-ÈÕšgëÓ«¯Ó{|’|rY;ëª)óôÏæÍZ5ïq%ÿq»Fß³HGF³più³ÿÑꡯë·å¿èùžèÞÑc4öúEêõÌÏZ±è] ßø„.¸T¹•É­ Ïv•¥Îùš›UÊu™ú}ê25>gˆšØ–áé‡ôW¿ç4å}6Á«÷®ëe6I)yÕu …Ë8TO¥6i?ë—nIÙZþÍJY" ´ô‡õÊ—”»f–œ†C#;DXÞ¡ÂN}tÉ™zhí`½±dƒ6ξCö)wéû,C’]-ιQ½R?ÒÛ)9‡‡}s_ѶQºa@ÂÁÖ.­zá…ß¿Hé^—þüw;…*ÿ¹ãuûo9úíº† åx)Sc5¹àýzAéוó÷t- ¦;Ú*uˆš÷i«èCÍBÕ4º@›r|*ضD›-íuG·˜Ã­B÷S¿úZº&SÞ^Õs žÂe o£¡½ÂôÎÌ•Úß{¹~Î:IÏ;Sÿ¼ò©œç)ÿ»ÍjxF_5°ëèåíSô|Û–h‹µ£îëRçð²¨NÃÔ9lºùÁZ_Cn*÷e¯iÑþÓtÆþo4å·Dª§¢ï¢f=[*¢Ô:Î-ÿ< óºô÷†j¼u´>NyKç7µå>WÜÙç—Ïg(ßå‘ÏgÈë3äóùø‹5 -GtÊÛ­¦è˜#uhvô* Ÿ [o½·Ó+ã`wˆC¯u»D,ÖâG2dÈ/õ+M;IÛF¿«¿÷æÈã3”õóÅJ°…ÆŒ°Èj+ôOz‹E²Xe/¼H’ £\e*]žV6W¾AçªSD)eE–ƒ×P¨¥ÄNÕq ÅË¥.£;+÷·Ùúë·oµµÍuoÙGCê®ÒÌ%K4sE¸zm£ðb¥*½¼En•dµ+´ðå[Cb=²G€›4Úö½^¿G›¾|U5¹TºE9ª-ÄVèØþ긼9¯MMŽPÛsôÁ·•Ôû Ž'”òu«©˜ð¤~j«åšþKª*òä®­¿j™«‡n¿u„:Ô‹”ÍâQê²åJ÷¿2©`½¾ž•£~ã“ µ@(]Xó^J2Öjöò#˜¸wþª_÷Æ«[‡¸ =ŒõJ”Ѫ„ž#ÔbçWzçåª?´—êF¶Ôà^†~~óMÍÏë¬Q]¢*TÞ°æ=ÕÜØ¤?¶ùþl_¢õy…†<é£΋ּçßÐ+¯®Rë+/Q‡°ª«cÉ*›U2Š·Ä8êymJ<ý)Íýì­ºi .›ºåHW±r—¡lt«áP•w¶šŠ°59G/‹Õ¬+ÏÕýÿ®¶lÖÚ%ßéµûnÕ”UGcBvSKë}ùÓ¹e(gõûú÷¤eªÌœªG/“W;¦_ª~CÖR?º·ÌÒWûzè“c:Ÿ½éYºs¤K\u³Þúõm\öµ½ô!-onîU-×ௌ¡ÍOSÿ˜5š:×­Þƒ“ªHu:³½v|õv¶¡“¬*¯½Ù8Ý>(USî}O«s ykõáý/j}‘­"•|õŪûÓÃz~m']sA…–q}å­cÙc•ÔÔ®­sÖÊ{µ/=ûà쾜׮Fc¦hþ§iÁå§é†¯wÉS‘2ÅÙç×Yç\ á£ÏÑÐ3ÏÖàãøK„#ÀñvLf«±&hØ”EúòÖ8͸þµOj©§]£·ÖÆ*)Þ@0^o½:Jk¯m­Øøêpálõ¸ïl%Ú«³L>åïpjÑok´¿D vÎùTÛ»\¤¾ñ&4¶Æºà?êùS–éžSÛ«uòxM‹¼Q_|ÿ’#ªã ÿeŒè 3{„I!ê)É¢¸gþ?{÷EÕ·qü»-…’Bè¡„Þ$‚ˆ ‚R°‹ ‚ØŠ AÑÇ‚Àò(6DåU‘Þ¥(”Þkè!¤g뼄„ž²ûs]s%;õÌ™³»s~{ΚծêJ=Ÿ"¦×ÊÀog1‚·¸<$jMngþeÏЭâùÕ,¿–C¸¯˜:=Ê­ay]À"ä1At;†.Ûž ²N ª5yœÕI…9®zwMå÷É­™yGwž[|ŒÃ…NƒHùg2 Ã>|8+W®Tnˆˆ”! 4ª¼‘Ò³â÷åÙæÍþå' FB|N§“ysf3hÈ0eV:Ͼº¦%“ýËê‡ëa¹ÓèÚÃû—µbê°­lxªaÁŸn‘ô6îÉîwv³øîZ¹ÿB]Üé/èq‹) Ó¾ú‚…{ý¸¥oOâ“¯Îøaz¶u»õìv¹A•ʾ¬Y³Š÷‡_Íf#>>ŽåK³výF&Nœ¨÷ž” =­FDD•ýrccÔFe‚ˆ‹Â=­FÒ*õËëýk{g`¤„Óh8㈎šËœ}þ4kYµ`)ÃIBÌ1¶~=ŠïR{3½wͼÅ•þ·„óPO«‘ò@Á)²F6Fm$B%)¢RéVs±ñ ãÖçž¼dÓ˜¼v—]5 ;>dÊÕ‹#q÷ÔëÉLWc~þ½BL¥“þ·¼]g‘ àˆˆˆˆˆ\r2?¦$žT#ŸŠ]¾à„ñEá6ª|=¿$¥ŸØ²:®H9¦YEDDDä’SO«‘òCÁ)²v¡Q—¹êV#""™)8"""åFDd‘DFF¥ÁYEä8öŒî4™ÿ÷z®LŠô£å[;q–§ /‹t',俀ÿž¨/"ùRpDD¤ŒéI5""¥OÝj2qícâe!\?ã$¥:J…û$KÇõ¥i%&“ÚW>Ê´])g:9ôÓ³ÜÔ¹Õ¬&L¦pÞÝ]‚a×^>hãGë÷ö”¯ “ˆGDDDDä’£n5ç¸-åû}-¸ëÊL¥vT¾¸ƒÆîáºOײu㯠¯8»{æ¯$G’‰ºÝâõq}T‘‘¦àˆˆˆˆˆ\r Ü­ÆHbËç÷ѱ– “É„ÉBË[þË;@*[>LçFiˬ5hÏd¢ζ¿plg|s_Ú¼6ñýSÁdÂ7ìFÞZË™õž¶]«_bÉ)÷yÛ´|æ¹*Œª•}ñ«Ù™ÇÜ#·“IÙÍO÷ Q%&“‰*­oçí•1¸óM?€‡˜?¾c{£t ÚÉøæ¾„¿ü)/õiJ° K•v<8}ßÙcçs¾€‘²›ŸíIÓ€´´øÖîÈÃÿ+ÛØÉWï,'èÿñöÀËiѶÏ~ö|Æ„Uñ€îy‡Æ?Í=ÝR¡QOÌ ÆßØ“ SÕ<4m©KóJ{QpDDDDDä"VÐn5®}Ÿ3ø‘¹4~}»G³/êgÆö­¯)-°à0·âþÉKÙ¹?[—¾AÄÚô¹Šs£\8ØôÞël»þVoZÁí×òBß~ôd—OXÎæUSéµ÷MäLÛl›8à××qÞ•aK›1zÞVöí‰âË[O2¾Ï]|{ØOúã k¦ýCí[¯#Ôšvì-¿ÂwäJNØ“Ù>¡63x˜Ÿ{ò?_O óéÂSáî¯×±kÿ.ÖL}”ÈJF¶î:FÜ¿,ÙãËe7´¢âÙyÖš¹®~ëV Ð#À¸0}ð ŒÞÑOÿÞÃÞ…Ocüó37y¥=€>³·ó~k_Â'ìÆa1_rUE½OD.%VeˆHÙÑx#E—>(«òODŠ¢ Ýj\±û‰±6¢{ÏËijÐÚ„…§/­@äc/™þ²þ}LøàW~zhÛ&\IKÚìÀÞ2éñîÍÇ<È»m? 𳙌肉pF˜À÷_üÎagGšžÝU¥þÿáùkªbêöÇkíòÒ”Œü¨Öù1£³û½?O¯}¡áiž°QŸð‘LYxœÛÛæ•~ a=ßýU…~¯‡acռͳ×ÔÀ4¹íI®{zs¶%3 F¥<Ï÷²S?3vZ*·ÏœÎ誤uÑ©ß8m}×óó5î01F Í«Ø2ÕL‚© ±cq…ÆuèÞ[Xû–N`pûÊ@CÞž²‚Ÿ»|_°keÓ{BäR§–#""""rÉ)h·¿Cx°Í:îkЀη>ÊØÿ-bwbzk7'–¾Ám5Òºb˜Lõ™Å™˜ƒœÉèGb£^ÇÆçZG†èS‡M+ŸßÃJ`h ¦¤S$¹ÏmS¿c£Œm°T¡edNmÜE‚çüô¥î[ÉŽäÝŒkí—Ö]ÄdÂäÓœ—¶¥sà4–<ÓIÿþÀ~=¹©iz(‡š­jŸ LX*SÍ?•˜$O¾ç›º»–ôk\Šc—¤±ú›æô ¯œ1¯bËž´Êh"Sk%Å©²Ÿ•ÊþVü­T°XÁFPE‚+¥MU*ùP¥²/!•}•YâÔrDDDDD.9K/¤WŸ¾8öŒÿsT¡-£þ8ÊMK~aö¼ü:æz^}ílü˜î™ ë?Ž“OýÄ¿‹ºÒ¤jRV ¦~ßÄLÝHL˜-™~4™ÀdÆšy€‘¹ã‰Ûéδ´×92<–Ž|yhCjåü»gn鿾Šmÿ·O·/ié郚˜ÌYCž“9ßVBëbŠãðéLφqÅr ‚ë¾’bf+>™³ÀlÃvöuq¦]ò÷ó¯ ” ¢àˆˆˆˆˆˆ·+ÔÓj¬Á´ê9ŒV=‡1ò¥›éQï!>z«ƒþäG;Þy²7Í«š'ÿÙÄiWƒ L‹½Ë6ûBsj˜g4«VÇÒ¥1•³Ä?ü®¤ 3øaÅIßY#çfṤÿú.û˜5/‰+?Œ RRå8˜÷ùú…u¦±éf¯‹ePz·š\˜Ûн‘)s·tcg*®c«Xt 2í¯ªOaÛøÖkO=c%kÚé”¶µýðßìN1¨Z€´ƒ‹ GoŽ Ô½~­Û´ÅæãƒÅb)ðv¯]£Ì“2¥n5""Rn¥;""RXíV“²ñF¾5ß7ïçȑݬ™9“-ÎÚ„×òÁV³ ÌÛùeY4N ’¶}Å3ãþ¡8ú”8VŒäñÉ+Ù}póß¼ŸW77á‡"©e=Kè­Œȼûnã¥ï×°óÀ~vü=—_|’É[íy¦ßy`3Oµã®JS~çk ½…1}™qÏ@ÆÏÞÀžƒ{ˆZøŸÌ;Œ3ëÎ|šrϳ]9ó錜þ7Ûÿ]À„_àïzðÌ•iéqÇífãúõDm;ŽÝHâÐæ ¬ß°‰ƒ‰ •ãûpåÀ¯9àkÝ›Ñí$“_ø’mÉFʾ}i"» ˜v¬„Õ±rpÉr¶DŸàÔéDÔÛFDÁ)LTD¤Ü,ûùpdæ(ú·i@hhº¿Í-_üÌ3-|°„àSndÇC ®Aó»ÒîÅ[¹à¶Ù>„??І? yý–ôþ(•{¾›ËË~9$° ='¯â—'ƒ˜ýÈ4 k@ó®ò¿„[òH¿™#‹gp8|ƒ ÍÉ÷|Í!ôþx%ß vðù€v4®ß˜+†Nfc²)‡x‘•°û~`Θ,¸ÿrZ´íÃûñwñÍ‚q\~v°•øÅ÷Ù¾=WÁiö3ñæN´ow5£Ö'nâw®aÕ†C¤xK(¿ÅÞâò@ª5¹ù—=C·Šæ‚¥ ºC—mOY§Õš<Îj=ÊWä’b2 Ã>|8+W®Tnˆˆ(8¢|‘KŠߗg›7û—Ÿ4d ñq8NæÍ™Í !ÃJ7aŽíŒoÓ–í`Ýa%×Þs„¯®iɤAÿ²úázXT$¤Lûê Ünw‘»ÕÜØÿfl6ññq,_²˜µë72qâDe¬” µ)ÏvÙ¨.!""R\*õËëýk+0""‚‚#""¥.k@D’ £qGDDŠÀ'Œ[Ÿ{’ëkéù "" §Õˆˆ” ƒb¯ODD.6>͵ÝÎ(儈H©R˹¤)8""RÊ"² ¡ÁDEDDDDÊ”ºÕˆˆ”EŠOú¸#zjˆ\r\˜Ô¡“üË?#›b+ê:åé|Ä«E=FôÑcÊ)w)eªÄ‹ˆ”#F ?^]•;ÿ87ËX¶]ú2ô™y¨[(>ªôïåƒËZòùÐ-lxºQÑ*ý9íÃ\‘æ}ïæ¦ÖiM‹ã8ÞÆ}’¥o ãá·æ°+ÉJ­ÎðΗÔÄprè§yb¯üù×NN¹[ñή(žm¬°JYùâ( Ã87yfí–-lŠZËâ©/q½uO^Û‚¾ïÂ^¦wóUéþÚÿx£OÍ‹ô‘¼.|q7ŒÝÃuŸ®eëÆ_^qw÷Í_IŽ$u»=Äëãú¨Âê5<n··Ë…ËåÂétât8HMM!%%™ääd’“’HJL$11A&eNÁ‘|XÃhÞ²%á—Óõæ‡xó— ,ÌÂOðË1Ê–Ó¹Q &“ “µíï™LT‚Ä3·_sFl²³ù™Æø˜L˜B†²2)¯m²Êeq˜éGË·vâÌõ89ì.e7?>݃F•L˜L&ª´¾·WÆà.Hf8¶3¾¹/á/ÊK}šìcÂR¥N߇òÉ‹4FÊn~|¶'MÒŽï[»#ÿ_4®lÇÚÉWï,'èÿñöÀËiѶÏ~ö|Æ„Uñ€îy‡Æ?Í=ÝRA‚GDDäR–>H©0ÒùÉ´N]Î7ÇæVÜ?y);÷ïgëÒ7ˆX;‚¾#W‘H}foçýÖ¾„OØÃ00b¾äªŠym“Unû(ì:€ç4 ïʰ¥Í=o+ûöDñå­'ßç.¾=ìœìy¯5¦Êw°$×ôl™ø¾#WržÌö µ™ñÀÃü|Ü“O^žæ?Ò…;§ÂÝ_¯c×þ]¬™ú(‘• ²†…Œ¸Y²Ç—ËnhEúiXkvæºú ¬[q l[툈‚#""R4o¤äl<Ù¨‰ˆ”kõÖ4¯dçÐîÓ¸¨@äc/0¬g;šÔ¯O‹«ïc½Iš3ƒm)¹í¡(Û\8÷ÑYŒýÞŸ§¿}¡Wµ ¬aýF} uÿ`ÊÂãx0ãIç+š˜Ç…ռͳ×ÔÀfò§ÉmOrm=s¶%ç{^îèŸ;-•Û¿žÎè›ÚѸ~c"{á¡^u²‘âŠ;LŒH*™–Xƒ© ±c³·4¯3kÖ,bccÏ›wæÌæÎ«Ì¯¢àˆˆˆ”{Y" ˆH©0ζt0™7'–¾Ám5Òº³˜Lõ™Å™˜ƒœÉµ_”m.\꾕ìHÞ͸Ö~iÝ^L&L>Íyi[ 1NãÄBè_óçÂ×hïŸÛ^|¨Ùª6¾é/-•©æŸJL’'ßóJÝ¿ŠÝFKúµF½`.~ ,àÆ¾}3$±±g¸ýö;Xºt™2G¼Š‚#"""""Eà:±‰‰~Ôk\óÉ™ ë?ŽC}§òï‰$\ƒ„åwSÅ’½«H:O¶)†ÃÒ‘/¸Ï¢ˆa°klø¹€G>L次´§‘çyYëbŠãðig¦Œå@,× Ö£7Ëÿþ÷¿´iÓ†®ÝºñâK/ѳW/ÂÃÃyûí·”9âU)%êRSòLP² ‘Œ8@«>ü€MþÝÜ!ÇÁ?ùÇÑŽOö¦yµ XL.Nþ³‰Ó®s·Ý3OÆ.òß&û­{Ö}e¿°+iÂ&~XqO dM~çå֙Ʀ­Ì^›ïg¶)° ÝÙÙ0w éãÊºŽ­bÑÊ´¿ª~9R†N³™Iÿý/W^y%“&MæŠ+®`„w1›U/+«Ê)ï"²"„‘bæŠÛÏö­[Ùòï:~Ÿõ)£nmG×béùÞ‡ÜTÃŒ­f˜·ó˲hœ$mûŠgÆýCF¿k au¬\²œ-Ñ'8u:S~Ûd•Ã>\EXÇz+c‡2ï¾Ûxéû5ì<°ŸÏåãŸdòV;à&ú‡{¸òú1¬+ÂØ'ùå…%ôÆ ôeÆ=?{{î!jáW|2ï0ά;óiÊ=Ïvå̧0rúßlÿw|¿ë=À3WàŽÛÍÆõë‰Úv»‘Ä¡ÍX¿a=*¸^ ùïGññ”)¼ÿÞFDÁ‘’ ((""%ÃÀõûÃtlÕŠð¶¸vðëÌsôäƒ%Û˜ýp|Kèþ7åFv<ÔˆÀà4¿k!í^¼…Œ~At;†.Ûž ²N ª5yœ¿‚òÛ&«ìûXT„uÌUè9y¿<ÄìG® YXšw}ÿí$,ØxHŽbÕêíÄaì“|óÂBïWòÝ`ŸHõŠ¡“Ù˜lÊ!.d%쾘3¦ mûð~ü]|³`—Ÿ}|Müâûˆlßž+‡Îà4û™xs'Ú·»šQë“Ut½,@2pà] Œˆ×2†a >œ•+W*7DDJˆºÔ(¿EÄ»¬ø}y¶y³ù‰AC†‘‡Óédޜ٠2L™%R@Ó¾ú‚C‡£yüÉøúúâñx0<û×ápðÃ÷ÓyðáG°ÙlÄÇDZ|ÉbÖ®ßÈĉ•±R*¶‘ba³ÙX»zU¡¶Ù¼y6›M™'eJÁ¹èDFF¥ÇùŠˆˆ”ºnÝ{°uëví܉˕w¿,ÇÃñãÇÙ¿?×öè¡Ì“2¥§_‰ˆ”g+çÆÙʺˆˆ”?Ó¾úB™ Raaa¬ús%¿Îž‰'''™ÍfBBBèrÕUÔ¯¦Ì“2¥àˆˆH ؘ¥ÕÂÆ¨,TD¤œé}c?e‚H„……eIDÊ GDDJAîOd”’•ÞµF­vDäB¸ÝnÊjrîgÒekŽK騹Mñ ¹%¨÷üžP¾®c O}8ÎBíODÁ‘rjcÔÆŒIDDD¼„k/FT¤íû{Ð0Ÿe#**Šððp¢¢¢”âõ¹™"ic[ˆ÷Rë‘ÒEÏž=Ù½{7={öT€D¼ž‚#""Å@‘ò#s€D­~D¤@Ÿñ¹uð$²å‹û¹¢ŽV««_uÂo›ÄŽTÃHûrðÄý͇ ¶Z±VëÀCÓ÷a?»½;ö/&nG ›«µ2{dæ;†á!fæ ×Î_ɆáæÈ×Wc³3`Q\Ú±OϦop(­JÊ1m¹ïÛÀ°oç–h3ú3FÝØœªþV|²¤-ý»Í0œìØÿϲ>ùÜþ=1s¸-¤ ·þƒ§Pùb`$ïæÇg®§I «ÕJµ¶wòÎÊS¸²»`ë{’wóãs½iœ¶¼BÝ+xäÿ¶1û¦V<³ÙΖçšáoµb­>Œ•‰ùïÏ}joôkB%«kŽ<üÝRÓ ‚ºÓ°[͆ èÝ»7cÆŒ!..Ž1cÆÐ»wo6lØ n5¢àˆˆˆ#â’t ˆHa¹öOeÈcóiüÚ2¶ï?À®u3xåÆzød|)8ØüÞ+DužÀÒ×ðÃP7_?ø(¿÷€û?íÉÓ¶bÜÒÍl_÷ w&Læ¶>ãù'ÅD@Ä 4Šù•Gœ@"›ÛŠÉßκ…iõäóÙhDл™ö„å¹ïsiÛú߯ñ}n9G’âÙòNm~zølÚÎc¥ÞÍÒáä|ñOÒÙyN-ÂbË <|U•lßyæ‹ç4‹†wçeMyyÎ&ví\Çç·œä;w3í°;û¹ä·¾'†_ÃÀ¯`ÐÔµlß½?ÿ÷0‘•*Ñë—-L÷¥Õ;;Hv:qÿœ.þùìÏ}„ï‡öã•×2eÍNvÍ{ 딑,HPå½0FÅ›o¾Éc=F… xì±ÇxóÍ75j”2G¼–UY "’¿ÌçÌO<‰ˆŒ€\–‰wK¼¯["RäàHì~N[ríuhjÐÚ„µÊˆ=Øó}>züz‚LñÒ8zþï^ænOæÖú³xožAs'r—@L4㕯Æò[‹·ùï†çù¬Ýt¯ùs×Å2"ô0 £‚ôl{æÏYÅ1W8Ε+8ÝøQ"²йå³ïiëU¿ã?<}u l@ã[ž Ç³ƒ˜»=™;¯<–Ú}xìª<õÙ:Þìt •=ÇYðñ *Þ4—N…Ëwô¯ŒûѧV½Ë=­|{q ÏÏhÏ'‹s÷ÝYâûÐu,ªÀ½‹Þáîv•ügÒJf^ó£ |!Ìž=«õüªæÐ¡C¹;ëñ"j9""RˆÀHÖ×éO§I"Š”ÏIN×\ÝmD$?~ÍïáþÖëy I®ºãqÆ}±˜=‰™?UlÔíØ„Jéñ ŸB+Ù‰Iò`?¼Ž¦¦\ß: #Hk«Õ™ÎÕcÙ´ã n¿F\×Á—Ís·wl¿'¶åÖÛn§á¡ßˆŠaݼÔì~5rø©3ß}§%†­j㛩LUÿTb’<9ÔªÓã±ëpÎù”Õqà>ü¯ áŽÚQ©ù’º%;“÷0>¢6›-mªÐŠ—·§s 6ÛÀ©ù­Ÿp`{ŒÜØ.¸@Áîüö—xxÍ͹¾UåŒm*¶¸ž–¾ ¥FÖÀH~óE¼¢Ü* DD²=ò t¤wÉÐc{˯ˆÈ6Fm̤_Ëœ‚a |‰\ºœN'.W.Ï:±4åé…»é½üW~[¸˜y¯ôæµqC™µúCºW´ã2L˜ 'v{jZ@ÂîÄc¸©Øn \ŽTìö³o»†ÓŽÃn¡IÏæ$ŸÇ_+ÿá`ÃÛhU+‚nU^ã×Õ«IÝìK»çë`²§bÏÉwßv\àqdJ›wzÚÎ.7\vìöT<@ÅŽ÷ÓÛ<)KR÷À¢jàæ&ìöÔBåK'‡ ¥=ŸìX š9üNk?xÞ±ù¬Ÿ´ÊçüsMçÊ~öüö÷§ÃlÆäJÅžž±.°˜ ÜN;v»ªOÙ.YeÀåråÉm¾ˆ7P˹$ƒ Y[l,ÄøéiF.ŽIÄÙkYЧبU‰È¥&Ÿ)-4ï~7ϼõ% W}ÁÕ'â«Éç˜Ì6èdÚäzõ],Ùœ±Ìqt5«OѪi &ÃDPäuÔ=:‡¯¿ÞBµk/£Š}®io°bêTþHmA¯þ9¦)ÿ}ç6ÃHoU—iy¥ÛNƒ{Ðħðùâ[·#ØÂOœÄã¶ç;¿õ}ëv¤¡i;¿mˆÍ>0¬aÂlÃí>oý¼öçS'’ºÆ~þ>˜š1/õðzö¤µ²Þzë­|ýõ×çÍûú믹õÖ[5 «(8’oy´“Òá}éP^”N:òªðå´,**ªÐÛå8yÍÏ+ yÍ/h$sšŒ[Æì­ETF/ŽÏô‰‘Ïû$·×¹½OŠú~PÙP^(^1rZMò?“ýÞ Vn9À‘#{øë×9lsÖ¢E kÚ:Y és Kí~½ƒï{–/Wïbß¿sxã×ÙÒdµM zØêt¡såü°ÜIûkêa3ühv}cŽÎ™ÇѺ×qY)Çtdßy¥-cùyûõ#|È„¬Ϥ]͸÷–ØŠ/æZý50…æÕ±ëàv®_Àÿ^yžO·¥f;v~ë›kõå…Û}ùåa¼ýÛFöÚËÆ%Óø|a4KeêÕ¶phùJ¶FŸàÔéD<ùìÏRû»êŸ™Æödžä|ÿêö‚"…޼ú꫌=†)S¦˜˜ÈäÉ“=z ¯¾úª‚#âµ²µiºé¦›2þŸ9sæ/+è6¥uœò²Mæ›î¬Í¹ójúŸÛ² Ù&§&å%qœ¼¶Éš†Ò΃ü*Izœ²ÈÓÌËòêFPÐ.Ù¦(Ç)L‡¢l“ÿ ûÆó*ÏrqK¿ÆF!¯{I”í’úŒñ¶Ïs}§”ï{•ò~_VÀðH®7“¯£s^cÀ«ˆ7À/´'}ÃMmÎ\‚ éÍ5¹ùÓ™œxú)Æ\ߎXü¨wÍ|ûÅs´ö;û(`ß&\áË—ËÛЫ©†=iÌ N\q%ulg×Ë*¿};òI[FóLËßfwqO“x=è~úÕµ-_LA\;a!Óª?Ïk#zð~à_‹ˆƒhÎ~ìüÖ7Óãýy|4‚±÷^Íë)à[³ƒÞé FW½4’+î~Ž.͇Cð]ÌÛ:%ïý™kqÛgÓÙÿÐãt­ÿ2¾UêqÕǹjù¤sy#YˆÙó¤M›6üòËÏôïÏ??’àà`fÍšI›6m”‡âµL†aÇgåÊ•9~Y¤™eYa¶yå•WˆŒŒ,ñãä·MTTcÇŽ-ñãäµÍƨ˜2 +•ÛMvA–]È6™ÓQ’ÇÉk›¬i(í<ÈtkDddd±§°ûKOGi_‡¬Ë¢¢¢Î+£eQFrKÃ…\#—ÊrÞ”¨Œ²Q–”Ž’ICÖî6¦B”ÓœÊhY|–ö;¥´>ÏõYj÷7¹móÊ+¯äzßS÷yÝ•ôýßÓ#žÊ¶Îì_~bÐa$ÄÇ‘”˜È?|Ï?‚ÃáP­ y OFÞÂÞ×¢˜ug õÏ¿ÄíÞ¹v:w&×uþùçî½wS§~AÛ¶móÜßW_|Nß~ý¨Z­:ññq,_²˜µë72qâDe¶” †#"­óyu[PëÉCÖ2ad-K¹•­¨€I )ïß%†áñ\â™à$ñô ¶ÿ0Ž©=ø¼{ULúý_€<ßmZ·fíšÕX­V½Äëe´QDNDDDD. ñqÙæåÔräþÎù‰,—’Äe nv;¿¹pÛÄŸ˜tG=l*B—¼½{vÑ®C'bOÇËþ¾ùêKµ‘2•Ñr$§¦—RŸSoÛ¦<Ž[¡mÊ÷µï¢Ï¿Kk9RúÛäÔ­&'g‚Š]ùúðÉL™b¨Õˆd** rq8oÌ‘KÁŠß—g›—SË‘aCM›sçëÓYüÇŸüñǾy¢¾Ê6ïºQ6›ILLÔc[5iÊaªÖ“'O˾\.f³î#¥li@Ö²ä‰gãÔ'ùdí^,õ¸éýoøÏãëè?~©ÎÌxþV>9™„Û\‰Ö~Ô—®aŃ 8­–kâ e4íÖž€ñxµìHl¨üï*Ÿ©Ûøàö{øúKy%ÞWFÍ!\ûêj›!×."ÚUšµÌ8•k^Ãd2ÀÉcǨQ«–2D¤™¸˜h‡ž$ŽE' g9xÑM²ÙL‹–-Y»v ÇŽÅãq«µ€&MÅú—²£–#^ÂT±w¨Ê_“6“”>Ó§÷}ú ÷µ Áÿøž¼îÜ2‘².£¦J\öÈêþü,ïmÀuÊ"ñ¶ÏPßf<ôÕBî3Û9ôçw¼ûö46Æ©ê)ÞQF}j¶¢†=‘VOÎàVÕ±ù—ïþ‡iÿÄ)@â%,V+õê‡ax…×ÇöfÓ¿qBßËRæeÔDň‡y¦ÑlF¾w·oå‘x×g¨ëßÞ߃IÇbqUhL¿W?æƒÑéÿÜïÄ©žxA5™Íø„´¡êÊÜõâq‚®Ë´ ϰ½ÿþÖ/!^Ãf³Ñ Qcj‡ÖÁårê©"%Àd2có±)0"eNÁ‘2¿aªC¿ñ“¹çÌ»Üÿî*bs |8O±~æBâ>íL=¿ß8‘¬l“².£Vj\ÖŽzáýøvÉ#`ò# ²¦IЃ÷óÙ.‡òMÊö3Ô“ÂÉ£)iÿ'ífÁwðÈk‘Ô²ýNœŠ§xAuÆì#&e;¿®ŒÆaÀ‰5¿±Åú-ªXù;Iãäx‹ÅB…Š‹´­ÃnÇét–y‹³ÙŒÕfÃ×WCþŠw–O³Ù¢ "eNÁ‘2Íýšôzõctý—Æ/9oÌs@CšgÇá$<–`ÚÞx=ÕŽüÈ»²M¼¡Œ:Ùûù]tùüìËŠWòÑo±â®¡Ì8¦¦M⟡kQÇ/†C1ð©Eç›:á`'Tç/)£®£°àÐ\Y…忟¡r«®4sïåÇXÒ‹ErR{÷î寵k8qâx±V@kb€X³ÙLppZµ §ióæxÜ$LT>ErüÚV”¿÷ñlïPª¤ŽbƲQ¤¬#І¡ŸäÊê6Lf71ÿÎd싳8¢Ï ñ’2£ˆxóghpgFLN‡`+f‹“ãÿÈ ¯.å´Ê­xËg¨sß¼ø9/¿1…£­˜SvòÓË/³&Qùv1pØíìÝ»‡å˖ѳwj×-ÖÇ”Nÿîžyî…­ët:Ù·oË–,¦r`õêÖÃnׯm*ŸÞ[>5¶(8r JÝ4ž‘ãs^xx&#o™©Lï-£™%ýÉ]ÿT†‰}†þĈ¾?)“Ä‹?C R÷þÌË~VF]„œN'ýµ–^½ûpy§+Jì8ÅjµÒ¤I30L¬^ý5VpDåÓ»Ëgjª.’” =ÊWDDDD¤y<N?NÍZµK´âix<Ù&§Ã‘ãüúõêq:&¦X[ˆÊ§Ê§\LTúDDDDDJ j±”à “†‘VÍ4mذVáálذ!Û2«Í¦î ¢ò)’u«)o•[ÃÀ“©ÛBTT}úôáôéÓôêÝ›¹sçYèýÚív…ìv˜{ ×!>ïщÿݲ‚ÃaËúºòªØÏÉK…„T+Ðzûã÷”Ûò)R’)w Ãs¶â¹‘o¼‘—_ÅСCùòË/¹á†˜3g‘‘…Ú«Ãn'*j=k׬Îw]³ÅÂå—w䆾ý‰‹+ØÌiÒëvú´¬\jMØKüœ¼Tõ)Õ8ñȉ‹¦|Š”$GDDDDD )¤j5bN,ÄÉüóÁ#<ûíj¶Mü¨Õ®?¿ö*÷D:P`ç¼=z4ãÇ¿Î!Cxä‘G¨P¡£Gæ×_gúÜþþk-¯ŒŸ¿žë¥¦¤0îµ1ÜзÁwn®ÂÕ/|ÀÕ¥|½Jôœ¼DLÌùå±ÛÇÝØvÇ–óæ'ŸóÜ1üùÑÓŒœ´˜}ÉVª·Èè^á–~…NKI–O‘’’Yñûr冈H–.^H¯>}q8ìåò)Šh¦ÀHHÕjÙæåÄ|w¾4˜VõC°&ìbáG/3j@"¡«?áº`S¡kŸ†'­òùóO?aµZ3^Ü3øÞ5ð¼yåñxò "øùûãq» ·ó¬Ýj»xïê®üÔïMzý;‰©¿ï%¡bî~{*oÝR€Ô}Ìÿ,ã¾ZÁþdjÑ—'ßy—Ç:UÁRçd$³}Ú‹<ñÆl8ák0M{>Ï7ŸÝOcï(ŸÝ®í~ÞÿË–.ÉïÂpøû‡üÞ)|øS›Å²`Ü#<1ÈŸ†‹ÇQ¯)Ÿ"%E²Šˆä£WŸ¾åúñò$÷ßÒƒ+ÚEÒ¡ë<7nõÿeÝQG¡÷–6¥Ãð`±˜3þÏÔh^ó\åÛR‰ª~©œNö`?°šÝ)ûx÷ªPBªVK›j]Á¸©œ>[&©õm:€!­62ü²vôúÔ­FDDr“SK’¼T¼üMæ/>Cò©,ùô5Æ|‰†‹ÞåÚ*…ûÍÒÀàç?xý›o»Ã«óÑd6åp†FÚ_K;&ý;—5¼äw]ÿV<ýÛú¬˜Ëü%K™ÿŸÛyëÝÁüßòwé¬ßž/Æò)—†ŒàHDäeÊ ¹$lŒÚP¤írˆ5óëü$æJuhÖ¢NDëJlj÷“ÿ|™n}«P˜ö#.§‹[nPàõSSSÊåuò­{9 ™Å/«b¸ãæjÞÓìÝDókÒüÚ q7·y†o7£ÛÕËe>[*×"ØÏ‘3™Úˆ¸ãˆŽƒ Ð Bÿ¢~©”O¹¸¨åˆˆˆˆˆH!e Œdž¿ïž‚íÄíÄé1ŠôăԔ‹¿Bi©u#/ x‹ÛŸ¼—×y•Aík`œÚÁÊ9KñÜñ*÷5+ýaPS7Â[K«Ñãº4 vqpá\¶»jò@ [¹ÍgS@ ºÔwðõ’$÷hOÀub+W¢MÇÐB6{©”O¹¸(8"""""RÒ’72ñ­eT½âršÖôÇyb+ >yß-W3±c…uäì˜.— «5ûm}nóËs0×¾3oª¿À¸g{óaà_‹¶×äÅ ²iGbòµqlîxîwx|C;2pâ—<ÖÔ§üæ³­!·=|½ôã;¾Ï½Íΰ`Üx6†d|‡Ê…ß_¦òi&SöžÛ|‘²¢àˆˆˆˆˆHI³øS1f)=õ.S :ßÌÛ¿¼ÄÍ5-E¨{žÄrР»éß¿?wÝu®Ãôéß3kÖ,¾ÿ~záãf3)))øûûç¹^rr2K>i·Öå¾åÑÜ—ÛkŸ&<½&š§3oãߎ··<÷Ú§.}FM£Ï¨¢gqž“o“aL™?ÌëŠXHH–ÖLÿœÏùó÷ÇïɱZX÷®ùúäÓŒ|ö¾L1Sí²ALüîy"*pAåsÓ?QÔ ­CÕL­­Ž=©“'i‰Ç£ÇøŠwPpDDDDD¤bṈkMÌ©“$ÄÇçP£nÆ}ÿýõ\PàBy Œ³•Ê—^|‘˜˜È]îä»éßóÁ‡òýwÓ2Ö)ŒË;vâõׯàq»ó8X,tìØ©\\¯‹ñœòS}JuN<<œéÓ¾åλ2zÌ‚‚‚øaúw„‡‡ú©Üз?7ôí_àmìv»W—ˆ‹ñœr,1ç—¿nw`Û[ΛŸ@|©–O???ÚDDòOÔ¶oÝ‚ÍLJkºuÇãvãt:õ‘%^ôí!""""rÑ0aó78²z:Ë—tf䳡%[!-Å€Èy•ÏLc:@Z€äûï¾ãáGåãÉ“‹IÛ¯A|\ÜEU".ÆsÊO·k»Ÿ÷ÿ²¥KÊ´|úúúÑ&â2¶oÝB§+»àv¹q:ú¸¯¢àˆˆˆˆˆ”Ÿ›×:˜:oŒïͽ߯…ü‘_Šæ™ÞÙ{ÂÉÁ_þÃXÀ¯m†¡e>x²?Z…·bÙÒ%X­ÖlËäÒRÚÁ‚”O__.»¼#N— §Cñ>feˆˆˆˆ”®Ã3ùÚzÚ¾ü6wÔµáÛô>Þº.‹^z…'ÜÞs“m6ãr¹JîFZ·…¬“ÅbÉq¾ÛíÆlÖ­¿”mùt:8ìv•OñJj9"""""创#?¿È+½æóúÄ1DT¸ƒZócè¢SxKhÄl6S½F :Hý°°ª{…ÈòtÌ)ª„„èÉ ¢ò)’Û{CY """"åŠû(³Gå惡µêoŒ|m)1^T§²Úl\Þ±K—,fû¶­%ò }ú˜ùM‡S§N±ví:vºBÝDåS$·÷†²@DDDDÊ3•›t ™`«Gý +œöžJ•mÚFÀo¿ÎæøñcÅú‹xÍZµ˜úÅgË)³™*UB¸¦Ûµ4lФ¤$ŸKœ·—O›Í¦‹$eBÁ)WÌA]xñ[‰ÿäA&4x‡qïaÅ€ÏØí%ñ“É„Çí¦I“¦´l^æc)x<œ‡#¢ò)’GDDDD¤ü0sõ¨w¸éÌdnþh ;*¢ëü÷™0tw|º;`©\Ÿfõ+ãר*>&j5 '¼R §÷íâHrá~!w»ÝxÜî"=×a·_PÖl6c±Z‹-=Z¡Î)=»§ÓYêcE˜Íf¬6¾¾¾^?Þ–žÌìv;ö (£"›¼ƒ#¾-yaѯÜ’D²ðœb΃7òÒ_É€‰ŠáÃxwÂýDT6áØÿ £‡¿ËŠSî X&""""’k•˜*]_æí~1Lºù¶¦) yõÅ…,˜ø>Ã–ßÆ”v*]ù~tyÆVC>þ‰!Ä3sà•<³6¹ÀGs:‰>ÌæM›ˆ-ÕŠ@@-Z¶¤^ý°ŒnÞ–žä¤$âΜáèÑ#$&&”jÅ¿bÅJÔªJhݺxÜn]¯¤GD.$8²™·úÜÊg² ÔãÎð‰÷áx³/]§þÌÏ|2v=½_Ìß".ÓãØEDDD$WN/}†Ë›ežçæÔÂá´k~nNÜü»hÔèÂŽäv»9rø0ëÖýM·î=kЋÅR*gét:Ù¿o/+–/Ã0 4L;oJÛå"îÌ<@ë¶m ©Z­ÔÒc·Û‰9u’m[·P9 €’““u½òHOiJ(çÆ IDAT[äâŽäÂ'ìzºû­ä…?Oá6`ËŒÿ#æÇ›hUa1×-Ú²?ÕÍLDDDD¼€Çífó–Í\Û½ 7)ÕcÛl6š4m†Édbͪ?©];›ÍæUé1 ƒ£ÇŽÐºmÕkÔÀív—ÈSOrb±X¨^£&`b×ÎíÔ¼¦ž„]¯<ÒS¡bE½©Eò‘ÿè;~-þ«Ù°~%¿¼wí‚Ò¢Ž¶ª ŒÛKÌÙ¯\§÷ãS›ÐJæ"/ñ†awæ õ4,³4Ô #..—Ëéuéñx<$%&R·Ë…áñ¤?¿µÔ¦0›Íº^ù¤GDò—ÑrdÏž=ç-hÔ¨8÷3u`'Þ?rgŦÜúŸoøôtl1NLy춨ËDDDDD¼ƒÇã)Óî6›'c0OoJÉ”@2[,eVù6[,ç tªë•wzD$oÁ‘F9uÌô$s<úì U‰;ùíËåŒx§=µ}³ûÔââû\`­Ò€ç¢=8‹¸LDDDDÄÛx[åR•]]/)~yöe1W %¬š/&ÀäÊÕwtÁß¿w‚cÿ"–9®bp—ªXL ¿ãvª®ŸÉÖä¢/ñv‹¥D¦rŠÀ0 6Í›7/c*è6ùM""Å%ÏYÍU®âÅožçŠ*6LfÇÖ|Ë“/, Ƥnbâ“SywÂ\Ö¼n"uÏOŒ¾ŒXã–‰ˆˆˆˆ”·Wôþ󿥮ûƒ€[†Ð¬A§¶`:û3¤Å5«Âø§L¸Rãq%Ÿ[¸’S¡Ú•u~ÍŸ?_…FD¼ZžÁסïy¨ë÷¹,5Høç3êñY1.ñ~®èý8vü{Þ<ûöèÔzuI›—1ŸvÏãJÆ™°#ÓB3©'——ߌ0H 5“‚BæÏ›@¯^½T˜DÄ+X•"""""¹Ôý/ û†É|.(b1gš™ñ×|Þ¼‚'¿ôX­E»½/êcx³SÖy5Æápàv»9r$³ÙLÍšµ2ºùøø°gÏn /º^ÞV~D¤t)8R˜ ƒ¦íSS3¦«ê×WúE×MDDÄ‹¸ÏVüMæ´iÏŽµ¼þ|'Ƽ³†ºõ[fT–݆ÃV‹ S1?ÈÑåre äø(j0%Sõ?[Ë ƒÍ›‘œœÌñãÇ9}˜à  5l€†aP¡BöìÞ•}Ûâ®ìXK®ºSÔ€’ˆx'GÊ àñ(ý¢ë&""âÅ,g¿7-&ð¸ü»ìMS\X,VÞüp'N&PÅ?SDÄd.‘J{æ €Õj͵"ŸS0¥¸¬X±"ã¸111¬ZµŠV­ZaõKñ—òÄÈë:åµLDŠé=¨,ð~彂ª ¶®›ˆˆÈÅ&eÕ{·g¼6™LÄüö#UƒáLìQ0™ÀV¡Mˆ? @Rì.*$n“& ñ›K$ PÐÉɡۈq¶1ÉUW]ÍÚµkIJJ¢uëÖãããáC‡2ÖQ—“ì×,ëuJ¿Ž ˆ”,GD¤\¨årÑ71‘›éS§Ž2DDDJMNøÀæºþ[Ϥµ y⡇p¥ÄðÆèþ4¿ì–BçBÖs:Øl¶ó*ÙN§3ÇõJ"HqâÄ ’’’àôéÓÄÆÆ}^ºJúz¥¿¶Ùly’S>”fùɳ‚–é:eÍ'“DJŽYY "ÞìÎøx¾;r„•2òôiš9Ê)sn·‹äøâOE§M1GÙöçl¶nÝÊâÅ‹IJJ·ƒþ}ûœ·í¯ŽdîÏßspÎ3ûIÝ4µÄÒ™5PÜA #É×Ïðó÷Çbµbw88Í5]»²ióæóÖ7AŽû˜7AÆ”ÓòÂæEiFŠz½rºNÞœn‘‹ZŽˆˆW{ãÔ)e‚ˆˆx¤ØãÄÝ—1fˆÉd"áT4«V­âþûïçÞ»šÔ¯‹ÇíÂl±bxÜT­BÌé3¼õò#ôïÙ…ºÆ®¯pg®lk€ ‡Gù¦‡.¢£>>6މf×®]tíÚ•“§NÐ*¼%[6oÃ`þ‚g7ËòHàôù»-ÞVY™ó$ó²Ü%¬È) "Rr)ŠL‘Ìï¿ÿ~âã™öõç`„7o˜xþ‰‡1 ƒ¡wÞLDçn |-›ÔÇ\1¡Ä“Z¢’†Ûí FÔ©S‹ÅÂòåËiÞ €Vá­˜¿`×]w‹-Ê )Y"é¯óš_ÒÝs²^+FDJ‡‚#"""""¹p¹œ9‚™K`$]R™´#‰Ã1q¸“c¨]¿ gNâT•Çã ì;tŒÐ°´Ê¯Ãa/zzòQ±b¥óÓ—”X ãå›· G–.¯.— —Ëʼn'p¹\8NÜn7‹…š5kòÏÆ2$í;´çࡃ¸\.êÖ­€ÛíæÈ‘hÌf35kÖÂßߟ={vg;NAó'ëyf~Û²¬ù•>?·¿Åy½²Ûf³¥uÑ‘¥1GDDDDDr‘þD•ÌSºÌ“ÉtÞcyÁq¤$ÓãêÎìܱ…þ7ôäø‘ƒ »£?mž³¦³Ûe=NNƒo攞ü¦¬•íÄÄ„Bï#·ôä&)) —ËE`` uêÔ9è¨Ixx8-Z´`Ëæ-T®\™„„s­fš6mB³fM©R%€   6l@‹Í‹|½²ækæ×¹-«X±‰‰ SúüÜþçõÊz­2LJòz‰ˆZŽ”kW¤¤p{B‘©©Ts»1§Íf6ûú²´BfV®Œ3˯ù±×%%Ñ+)‰6v;5].¬@¼ÙÌ~›¿ýüøµR%¶úúûùìÙ»7Û¼–aaÜ’˜H¯¤$šÛíz<¤šÍÄeJÏ¢ ØQÈô÷yæ”öF RÏéäîøxº¤¤PÏéÄÇ0H0›Ùk³1¯bE¾ òú¼*¬ª.7'&Ò%%…&ÁgËfF:üýùµR%vøøúó[Ö¨aC}0ˆˆHq‡Gr¬dßógŽí?%I nÞ¶&ã;%9™È 9zìÕƒ*âp8°º’8qìA!Õ‰9q»Ó…5yßy'7•+œ÷:!!¾x+ÍYÇ»hÑ"–/[@Ü™3,[º4Ûf×]wGŽ9/ŠpòÄ ¶nÝšÑÒâtL «W­¢wïÞ9>2¸ ù“×ëÜ–å7?·õ.äze¾V ñÙæUªT9c¾ˆ(8"g}pü8}Ï>-³Ún7µ““¹>9™'Μá±êÕÙäçW }^•œÌØS§¨ŸCÓ¿`‡`»H»ãâXZ¡£«V嘵d‹ÐüÇ©—%=6‡Êu\.º¤¤0"6–åþþ¼Zµ*‡ 0{iç¸8^ˆ‰!k Èãá2»ÃÅœw%‘W… 8=˃qqøæpPÕ㡪ÝN{»GΜa~ÅŠŒ !ƪ!ñâЈ‘s¸Éå½rÝÆl‚£Çޱî¯5\Þ¦ nÃÀž’‚ÙlÂj±òwÔâãÓZ$¼ðúd^È¥¢^˜ôä$ ð¼×ññq¥Úšàºë®Ë6/=x’þ7³êÕ«S½zuÖ¬YCbb"ááá_ðõ*lp$>>.[P©¨Á‘‚^¯Ì×*óuŠ;oYåÊÄÇÇé)¢àˆ¤Ë)0’U¨ËÅ÷GrgíÚlΧµÀ±±<KAÛ™\›œLÛǹ¯V-6•`K„zì£Ù5%…YÑÑ<\£ùû{Åyމ‰Éý‹ø¸_ö¥W…QÑãáÓcÇ蔚Zàmz%%‘šÊàZµØ›O+‘2 äø”·ËEêÉçÍ;ù÷jÂúÝÊ„_ßã™'Gвu bN N­ª¤¦ØñõõÁj±°{Ï>øäKn¿c0áè™¶<>´ZŸÆbh½€Àó[§ÆÇÉu»€À ´å%Ékù¢E‹¸ñÆ9xð 'NœÀãñ˜˜6¾†Ãá &&†ÀÀÀ »^g_§Ÿg@@ ñqg²åIæ×ÙòÃ02–gý{¡×+óµÊiŸñqg2Ö)Ø1EDÁÉÆÏ0øðøq®¯[w.]lžˆå©ØØBï;ÄãaêÑ£ô %º˜[!E ÇÃäãÇé[§GshàMç¹´B…|»•”e^†É0˜|üx¡#éjºÝ|yì7††o±è +""^ɹ[DêÉ$Ø &3&sÚ=VòñcÔ­NÇÛ¯dî'sèØ±ÇǀǿŸ/1gR®‚`àO`pöŸ(h Ô½$0èü`âÎÄæºMúºEmQbpac[¤Q½zuL&±±iiõ÷÷§FX,–¡aäÞ­&=òÊÒ*?Y¯OÖ´æ¶ŽÆQpD.@˜ËEŸ¤$~­”}€§ÎÉÉ6’{…4S`$ó`¬µÃjÑ­ÿ5\Ñòr†Ý~?¾ .·Là4 EËn¼ãjÔ¬…J˜LžW|óë¦\%ß`InAвtüøqL¦ÿgï¾££¨ÞŽg7»é½jè:ÒA:ŠJQ~ 6°RDADÅWQiì*4€4é-ô ’@¤lʶÙ÷„ÔM)ð|8œ³;wçÎ;³›½ÏÞ¢pùrfo½^OBBŠ¢àêêZ¬ëUšçV˜aPBˆÒ%Á‘rìgg¾õô$ÂÉ Ð4#ƒ×®^¥a.ËœuÎ-8b³ñnBBŽ!&1Ìõôd«‹ 1¨€¯ÕJ㌠žMJ¢¹ñÖ%ËZgdÐ"=ý¶ ѸY„£#_yz²ËÙ™dg›`‹…úF#½ :äÒ(ïš–F³™¨ë½þ–5©5@ÔTæeÕOi§x>0­..%rOÜŽº*¬žªšcûk¬ÊŒ;¥×sÊLJ\\ø5&†›gpÑ |SzÔÜ‹A‘ü‚yJ$`"„¸·$¹»90r=`  ÁÃË€*Õªc2›ñôòäZbz'=é&P2'×tpÐÕ”ïqì-ÏU;ë…ͳ¤\ï9rõêÕÁš+W® ( •+W.ò¹§NnWIhD Žˆ;èë<‘&Ea†·7óãânÙîkµæxm÷\&u}ËÏ/GÀà–wEaºOŽ AÓ"Ì7aµ€¥ˆsw§uF§¤Ü²½ÉMå)­ó\èáQb‘ÛUW…Õ1—Þ(«ÜÜrFnáäÄOO†&Ý:Óz«Œ ¾‘·v™ Š(É+`"Á!Ä]ɣǂ))‘ø}»oHÂù?W°+m3Š¢ðù•id¤¹x8–|É3#`H¹Ì™h=Î{38sÞt# PÔò”µú±?Àù/0(´´4Ì3žžž„T A«Õfö¹þï¬!„GD1ìÏeé^÷\>”çÒ›dyLL‘ŽYÑΕRî„nn9üµnZTZç¹ÄݽÌÝÕUaÕÍ¥nÛqÞººæŽÔ,F9 °§Ñ7FnçùfÏëvç/„e y›kãÖ«VÝ<÷xÙ|žisfôɧ!m+ryʳիWßò<))‰7ÞÖëUÖî!DÙ#Á‘»PºFc_C?ÛP“âp,Åý㹬úâyÓPÒ:ÏÓe`ŸìÖÄ«@¶áÈ܃JÁÁ…W [¼hÍ‘X®0ï[B­ó“¯®èå(jCþNåWµ·HQê¤<HŠzÍK‚—„([r[%%>Û¾·óXE)O)7ý‹Už®]ºþßó®]ï®ú±IpDˆòâFpäÉ'Ÿ”Ú(Þ{÷½ÛÓ8´cW-·mdL¥|Êdoù‹ØÖ™lñ7­zcß9Ï\Ê~üì¹;w£¡®B«‡â`³goÙî‘Wc¬àù%œÓr¾Æ·Y5¼ â£Í¥ŽéE/Gi5F ÓÀ.­oIEÊb€$¿ëS–e9p#nóßü‰ïI%”‹è™c#¤ß‚‚& B”$FCZÚ?$èt:ªU¯A…ŠX,æ]uDQ4èôº[¶e©<Š¢ Z­øúúÔ±B‰Ïm¡ª*f“‰ÔT¹^ö–§¼°X,(Š"ó¥ Žˆ’sQ§c™»;gj¡zåñëþͺ¤¦âiµ’TÀð9§õ·XHµcÅC©©<”Ko‡ü,ððàÊMó‰”Ôy–¶ÛQW…½n×´Z~òð๤['µs²Ù•˜È¨ÄD»Êñ£‡‰yÔïYŽ&Ó­å°Z™}ùò]ù¾¼—ƒB”6OOΟ;‹¯Ÿ?z½FƒN§Ã©€á¢%©¬•GUUŒ¹üS’õQ–맬•§<F22ÒI5ððð” %g’-ÓÓ©œmÞ{8½ ~*`îƒFƒ{¶n„­328WŒ¹.òrÐÑ‘™¹¬”RçYÞäUW…½nŸy{Ó1-šfs‘ÊqB§ã³|Êñ·«kŽàˆBq'Ô¬U›ÃÔ­_wR[…Eˆ{•¢( )Žˆ ¬A#Ö­ß(•"JŒGîq)Z-OóCl,U‹8x<%¥À Á ŽæÙ–Ò}11‘Õnn¤ÜÆîrûy10S.y–Äy–'ùÕUa¯[ºFóAA,ˆÍ19kAÎêt<LF>åøÉÓ“))T(ÂuB! ÃÏ?€°† 9yâ8)ÉÉ%6G„"“F£ÁÝððó÷— %J‚#‚hŽ>+2.!))Ø;x$ÚÁ9^^¾n‰‡ÍããoÙVÑbáÓK—z–6KÖhøÞÓ“Ù^^Xóù…çNŸgy`o]öºÅètô áÝ„z ô;› ,ssc’Ÿ_²†§ƒ‚˜{éÕŠØ;E!„°—Ÿ~þRwØ–My ç#¤¦Êåc!ÄÝG±Ùl¶Q£FñÇHm”Q‘grNRX=4ô¶ïl±ðˆÁ@«ôtjšLøY­è“¢pU£á‚NÇa½žM..lsvFµ³»éˆk×’œŒ‡ÕÊ%þvqa¶·÷-óLäVæÿóPj*Í22´XpWUR4®jµvtd»“º¹Ù5¹ë<Ï¢Ö÷í¼'îD]Ùsݲ«f2ÑÇ` eFÕL&¼²~uKÔh8«×³Ýɉ•îîDé ·¬œ£ªÒ×` Gj*uM&<­V´@º¢pE«å¬NÇ.ggæÝ%,!„wÖýûrl3K¾Ä¸ºfNÄžšj(—EÉxoâûÌš5K*BHpDHèN¤®„Bˆ{—G„(û$8"J’¬$„B!„(Q[6m¼Ñ£<>BÜ}¤çˆ(3¤7„Ô•BQR¤çHé’a5ÂÒsD”$™U!„BQ¢n0”ÇÇBˆ» «B!„B!Ä=M‚#B!„BQX–h¾íBëY‘È€,!Ê? Ž!„B!neKaÿçƒhR%„ U[òô7ÇH·]O4rtfšÚÈ5Û/Që˜ùÂC4 Ä×ÏßàÚ´î;ŠO×½©L¥Ñ’r¥æÓ³ž»4ª„¸ ÈûX!„Bq óÙù¼úy:¯m>ËÙ¿Ÿåâ´1,‰±f¦›Ï?Wæ ðVîl92Ž}ÉãmŸàÓ3µxöã%üµq#ë—Ψûõlžò!ÛRJ³%åC‡ñŸòN×´rËQîIpD”ÕCCsüRWB!„(yæ¸#Äv U°ÇÊmhë}‰£—Ì`aÅ›sÐ~Ÿ‡²…L§ø¸U­ÿï Æ>Ü”šUB¨P·'ãVFc*J!,çYðÊDvÔœÀ_«?axŸ4kFãÖÝùßè,ß0ÎFŽý24 ÍìYX—Î/G„!«[Iú^ÆÕ ¡ÏÚäÿò6ldHµ:ŒÜ‘¶4Ž/x…nõ‚3÷ªE맾ᴉüÓr «) YõÓvòO|0°%¡Áþø×è«ËÏ­~„B!„BÜ9úÆÅm`sti§7°éZ‚µ\ Ÿi׆òÑ€Jy,{iâä¼¥x¾Îñ¨³ìžQƒ?_þ1æòZ3gçtÀ·ÊP6粌5v= ÷iiÿêê8æÖ’Ñf5fTLšÚ ™¾‚Ýû÷±}åì}‡Aw“jǹZÎ/ä¥×à }k{bÿÆߣúÒr²§&ŽÏûÇQ«9ÍÎ÷ƒømôXVÇ«rÓ QÊ$8"„B!„¸…CåA|öF?ÿ´œì+‡_ß÷ÑÆâDh¯çé¨;È_'Ó妢”.8âXñ›#9}$‚ˆˆ"l`r —¬D×°¡|¹n;ÛÿÝÁ¦Ÿß ƒŸ¶˜iB!„Bˆ§¸6ìk¶?ù£ë™=8„“Ÿ¿ÉæNSx2áC^ù£_íÙÇm71f|8WoLŒª£R³ª\o! õ¦v/®>ƒ!Gç-Á}góçÒñ4v²¯XN ^ã·Í›Ø¸t,µPÉÌÒÊ•-ŸòtǺeNª ü“¤«I²ØÑÄ©5§ê`TÓf<ðô8>šÿgSm¦åf±£zëý×óD놟SWÓ¤çˆå+8~˜i=›Ò°aC6îÌ[»Ò²>©Â5k(¦ЮmFíëÌG;á¥#M!„BQêŒ'¿fìŠ0>x½1W7À¹Ûc4õö ¬ïCxÞÈ™=#lXÍVþ d>/ }P=‚‰ã`¤áF~ŠS5ëÕ£~í\²Z2jŸŒ|b{|Ζç¹ÏùUã­µeî§dý¿™ l×3u®ÏkaÛÏãxÆlæ IDAT ä*¦>Nó6cØxMÍ?-›Ëqý49 së+„å#8’ׇWÕîtqÚÂümW°ÚR9²d) ÍûPߥèiB!„BˆRf‰æ—7~$ð­ÿ£‹¯Õªþ×ÀW4(ª…ÿB¢¶&éús,»ö\Ã;¬n…lyhƒ;3¨‰•ÍŸ.à¸1ï×™/ìä°¹/=ß…š¾Îh WåÚõÞ|\ õjÚrZ®Eráæ ^Ôé<ˆÑ“¾aͦy´‹_É‚C駦Bˆ»,8âT—QK·³oïV|<”f^™C`t~¡x&!!kªeËÕ³$è+â¦)ršB!„¢4Y¹ôûf©Ãù°WZ©Ò¾† k8žšNäÚµ$ÔºŸÐ›&L5mŸqßíàì…“¬ÿt4ÓŽ…òäÓ qÎ%ïØÃy°ßTä67ˆCžøt÷ø¼Æœß¶°ïÈQ"v¬å‡Y?sBuÀÉAÁ! >U”Óü±536ÒN.â™Gþë-¢¯L‡¶žù~ GÓlØÒN³ìƒÏ8”É8<—‰³–³íX4qqgÙ³f Ç-AÔ Ôå›–£¸•CQ¦Ý˜ú(22ò–„êÕ«ç|µùßjÅ'1W1»ÖⱩó™79Š.ÃÃ1çû®/jšB!„¢´¨W7ñþ¤†,x‚ªºÌïî>]&3iÍ úÖœƒZù¦üò ~7~×ÔSwä«T]ý-ÇÇaõmʳó~eLXnËͨdÄb×î ’óè]á\+¶UgÖäÏùú•¼c°Î‡š­àõ_¾ä…fÎh•¾|6cÏŽ¹ª¯¹ãS©ϼò0Û§_ï'âJË sxièHºUŠc@=zIÇ¿?Îl8êˆ[3‰'>8O² CZ2hÖ ¯¥G9wÙF iƒ *‡¢,Sl6›mÔ¨QüñÇÙ’tT{æ{æ¿T =¶Œ~„1ÿÞº–Kói„O¿Æ°¦rºÚÖ|Àø®o°' ª<ÇoK1¹ÓvW*ZÚ¶T¹@B!„âö;°_Žmf³Y*¦8L§ø¸CG~ºƒõÏåµÔ¯ö{oâûÌš5K*B”ˆ|Æ®˜9ûý´kÑ‚-:3æßT4®!TõwÌœÓHB‡þíp>Á%3˜ÎýÍFS{†´óC«¸Öÿqüö®ähZÑÓ„B!„B!î´Bt5>íysþ8ZûèP4&âv,à•ñëHPŒCÌzå{fÌ\ÃŽ2"—ñƨ\³#M!„B!„âËgXB!„w'V#DÙ'ÃjDI’%a„B!„BqO“àˆB!„B!îi2‰´B!„PüÕV,Ñ|Ûµß<º™Í£ª£»ÓÇ»žÑˆÙlFUeÉØ’¦ÑhpÐéptt”Ê¢œ“àˆB!„·¥¥ìJͧg=÷ÛÓ=ÛÅWÛ°`à66¾\5×`KZj*碢ػoññW$@R’—[£ÁßßfÍš†jµJ¥QŽIpD!„BˆÛÒZö¡ÃøOéPB‡3œ;Å–mÛèÖ­AAAh42j¾¤X­V¢££Ù¼y3T Åh4JÅQNIpD!„Bˆ›¨Éûùjè@¦ÿvƒWCžüè{¦=Z=@ÆYVNË?næ\xÕ}„W¦Ï`x+´¹ «±&laæðÑ|~£Ocž|ó\œ8ߟ÷óeóüŽçͦ'ZóöQ3üß}ýà=Õ?§µKæ~f³™½û÷Ó­[7š7o.®TªT ???Ö®]K:u$8"D9&Á!„B!n0qtö"Þ˜Ìï㼉Z8šçF¥}û_yÔ7‰oôfäÁùhñÚ›8ºèm^ðÛe`@¶¬¬1,ya03ãó冗h®9ÈׯŽf½AC{Ž·`;“òV£ª*ñññÊe+E¡¡¡\¾|Ùî^;¾~þ$\‰/Õr«ªÊÎ;8qüx±‚:ÎÎÎÔªU›-[JÏ%Q®IpD!„Bˆ›xt™Ìôç;á©@Ã1oÓå§áüu2Þ¡kùh¹/ÿõÿ«« ò«3½²ßmŒ§ÿ€[ó±\\ÃÜ­ž<óÇÿñhCg 2oOßÍo]¶ëx¶´¯«Õj墕fƒÊÁÁ®¹^š4mÆOƒ5«g×δjÝZnQ~ßËRB!„B\§£b³P\•¬§zo*¸‰JS1FmçtúYvµaF¶½ª]¸†·[¶™.$ZSƒ±ÕolsªÖ–ZŽ¿Øuœ9†Îv¥—ªª¢ª*ééé7¶ÅÅÅPä<ßünW±ÊÔÀ‰A‘ìÁ‘ñ¯eêôù>ÎÍÊËŠ=Ìkìo’œ”$8B‚#B!„B”EÚà‡?p¿ò òƒ›b»r‚-«7 ö¡Õ³}ÑyÚ½ÏèÑïÓrÎË4×ä›×r  ØñMÝJÁ\ؼãzPÁÉOo׿À›ÏýÄ3½Þ%¾ç|º¨õÉœ?•ŒÛhŽ‚®éD~Ô—¬çzŸP®þÑz7eÀ[C¨_Ň”SüõùÞh dû\ºyÛ0§+Th;„7ºmáéó(……˜åã˜Õˆ*l˧°gøöéÁÌLÌÇ+çÒÌ9šÕSFòì“nü½z85) ]W>îÍ›þn„ÕjÎàä±ÃT­T‘ÊU*bÌ0g^ E!..ή|;¶oSä2%ì>…jUQP­Öé7oËëqv]»uÇÕÅ¥ÈeZ½úwù B!„¢LÓxÓyúŸÌÏcä³$À9˜Fñ¦W.ýHBè?oç_ÍðNß`ôjÈ7ÇÓþøÇèµvGð¤ýø±´zz<¼–c)ß\Ù’Ø2e*šÎ`ËÇýÊú¿I‹lEó ¥~ÆäœÂ…°§^!ìÆó&4 8Ãêî+Ùk¢›·#Uú½Ã‡@ÆóÌœ–{pÄr~c¦&3ìÛØÒgiy…PbÖ³ø ;}—N _sW &/Mê6³ø6âY>ôË?}j3çry+ùúù³ð³q´màF×_¦`6¥:Ÿtcñ†Ÿ˜LF@Áb1çHËÈÈ(ðqvZ­­ƒ41…G„B!„(¿ô5ymÇE^»y›s3>:rþ¦×T¢çÛ éùvnTbè?zscÑ·o,ÞÇףǧÓÖÀƒA:»ŽçÚh$‹ö,Dkù(¿mI£æÓqLïÓŒU×p®Þ!¦òjç ¬/ÿ6Ò7© !„Èņð¿x ç#˜LÆrùX!Di±‘¼ÿWV%4àþFAû/ߌùŒ Þ£G…;Ó€´¥^äL’…ƒŸ}GÅ÷f²lª '~‹1C¢„¯cl]üÛ½ÄĶõhXÅ•ÔÓáÌ}2ýŸ°±~ÕjeÅ?R6 ¡á ˜¼:2qùDZ»ÛÓÛÅDä¯ð™:œåO‡¢Ë8—c¤B{îžÊâaÐì' sŠcýŸs¼p ¥€t å78¢( Vc21WÓ©[? “1«G†bÿ„¦÷ùø7æQ¬¹LÈzó¶¼g÷ÇêßeiiQþƒ#B!r÷@ÏGÊõc!„¥G5æ§W^ç•KFÀ•Ю/ñã'OQõÍ•a³e®sãÔe2Ó†uÂ[†ï|‘¿ä—_1bbcªöy™a×whz-ª%Ó®Ïü|lï5rÀµÅÖ†'’vå$ëç½ÏÄAoú÷ :ûä? ­ùô7ŒúÂQ¿=I5Q@òú·ïrá…wy Þ;Tè4˜g‰Ð(àÜ ÿôò|o¨*æŒ4=t‰8xË•;濯—?½ûX±Ž?}ÚT¬YsŽX³õ7þÍÛòzœ›‡ÄÓÓSÞøB‚#Bq7ºùËJy|,„¢´(xµŸÄ_G&•Ø5Îþ8Á•º•q½;p¬@ƒ`øáÜ5Ì€S¶}\j´¡ªò gþKÕ¸U¤vÝŠ@¸q¨ÙsÌÙ6Nøä;•lÚ‰õ¸²ƒm«2áæ„çëÒø#ö¬Lð- 4¸7zžïvU½s &¤þ—s6_ªùäj°š1«6ljÁÃ=Ü:|Âúðp¯ÿÿm÷i ìÿ–³~ÎÃøç9âÂ÷€ŠTðÑq9ü¶›ëÒ«mZ»ÓËôNÎT v!òÔÎdýçóÍWPµ^´zñUZœÅ[P³^“Û¶[÷óçþ‘#Ûñ _íHÄ  «Ä#¯=‹ÏÊ©,¸Ü„_½Ÿ¨¯?fut懃®ÂƒŒ~¹g¿ÎÒ³wW\Ãxj\–NãÛC©Üßv¤æàq äW>Z˜yŽZ¯–¼0¦ —~˜É²ÈÌü5¾m>º¾™ÉŠ(•za¨ïJ¦|{;ªç,‡¯V/òjëcÌžµËÙ{®iý¹ä+tN\ÄG?"Õh|i7|4í£¾æÓ=õñBEÖ~ô ‡Rm€ïÖ/2¦{"?L]ÈiKκu¨ð ¯rW ^|µ5G>ÿ‚MW¬€‚kƒaŒëÍÜO×çÚœçÆ¤þô‹"³àëjÊãÂ9SkÀX†øüÍÇswp-«0Š{S^|ã’šÆÂ“YƒgµAt=‚&ǾäÓ51âz~¼9˜¡ù•ï‚K¡Þ;?žvÎùþ+L !„åÐÁû9wîûöî!>>>ß×j4|}}iÚ¬9U«VE§ÓÝ¥µ¢Á·ÛtMz›±Ó£Ó5p©Ò‘˜Á+uÁè„㥿˜9ò3.gº=ô6K&>Om=`sÆ5aŸžÁù@ñ Z›¾|´â-úf­ lØ<†îÏï¸qÄo‡>Ì·xðØÒ=ÌjíZ@ù¬¤DîeÏ¡ûȰ(v˜Ÿ'Nab àU‡žc~fÒðÖx(ö¤—O WâñõóÏ;ýé¸S4ZµjMýúa·!/-ŽŽzY©FÜÁ‘B±IL¶âY½F’Íf2ÒsÙf*d¶ÉÇø÷LúôéAÔ²­D«hÕ«9ž¨@.Ýøô騵&†³Q\N1£u ¦N»ÔP#Y•žË&âŽÆ¡éR_‡SÄXÀš|”­'ºÓ¿ïÃD-ÙD¤ÑŸf½ºxeKcL`ÏHF{Ê¡è ªáCÚ™Ó7ܹÑVëÁ#-“ùûx>MzÓ90—Æ`Lõ%ÑÖ„zÕ<8r8ÿÆ<Ø1HÌ3/ÕWè} ¢&aÃþ.<ÕwÝX˾èp ´~M”ýkÙŸË}PÐ>WsG܆Î5 œ;ÊÅ›¾ƒTùßWüó¿¯òl®äŸ^¾$e»»»|˜Qäàœ]¿‘¨A0|\HßÇ×ÓWäÜ6cC!xI\²ï~}é÷r+´é1ì çLÀýXs㨚0ºÕâþ~]ðvl$œ=Èʯ×q09·ßÎmNí$êáÎÔóý›˜KVPS8´ôÜzõ¢Çs£qÆBbä~^¼‘X{— ·£Šc%WJçðüXòÎÖÊ¥-›¸Vo ¯<ìŽ&õ»ÿÈÆX *‡Xñ[5ô~wúdví »6¥jg%Ÿ@Fá÷)-S«æ²0åaº÷~N€9™˜SûÏÈëÞX^À>¹”ÝbŽn7žè棖¤(ö­ø™mW¬vÞË‹p]5¸×jMu%’%'Sní}¡^aûÂ…8÷îA÷¡£èX’Îs`å÷üyÎXèë ÜwÚâ¿'øþb!êPƒ£_%*WˆÊ ô\!„(}ׯç¾-¨U«V««Å‚ªª¨ªŠÍ¦b4o<×h4RµjU6„‡ßÝÁ!„…¦Øl6Û¨Q£X±bE™, 6 3£FÔcç'_òïµÛñsµ#U{¤Ÿº˜Y¿ŸÇT2ÕŒ{£§Þæ_ÏÝFBnq;†–ˆrD®§BqÇ ñyFy¬V+¶¬@HnÁ‘ëi&“‰E¿þÂð‘£räg6›ËÕù§$'3÷ëo1b*T¢½õÖ[¼ÿþÄb¯ #nõÞÄ÷™5k–T„(elµǦ4«Œ—«^ÂèöX¼.îáXÒíj^9¿a ÇôUñ+©ù‚4®„„رzWU¹é„B!n ×ë±Ùlvïãàà€MªN!Dö¿e­@Ç š÷íE_wÀHÂÉ­ü¼r×ncPAM9ÊËJð¤TÇ×,å¸ÜoB!„wþ«—ªòË/¿Ð·oŸ»þ\5 V«ôQ-M‹F#!D9WÆ‚#6ÒϬaî´5÷Þ•°Æ³éÓwÙ$÷¤\O!„B™ªªŒ9’ùóç³yËfΘ~מ«F£Áßߟ .P©R%¹ø¥äÌ™3 ªÒE\ˆrý™*U „B!2|Äþý÷_FÉöíÛ3fì]ÛhuÐéhÖ¬)›6mâĉX,¹ JÅbáĉ,_¾œŽïÇl2I¥Qž?S¥ „B!ÄÝ`ĈDDD°qü¼<1|ýúõcܸ7˜þÑ´»î|õz=aaa¸»{°nÝZ._Ž—Þ %H£ÑàOÏžR»V-RSS¥R„(Ç$8r;9Ö`ð¸Ì`éY£Ô‡B!D êÑ£|ðžžžØl*ÞÞ^,Y²˜­[·Þ•ç«( ªÕJê¡Ô­[Gæ½(ªªb6™$0"Ä]@‚#B!„â®Ð»wïK÷^çååEÏž=±ÝÅ=*ŒF#F£ü0'„Åq†—´ZE®¾B!„B!noÏEçKX×GèÚ¼¾Ž`M¹ÀÞ?~æÃɨNiÝ«7㢘¹¹“5+þæX¢´þÜ?rެæXp;ZÖðÅÑÃÞßá÷ˆ$¼Ú gT«“|õé:b³æ™Rœj1`ì–Ídá±4l:_tíE÷ûªã­‡ôK‡Ù¼jÛ¢ÒP³òo|ü/"+¶¡YU’6|Îìn´¬/jyãv‘=áûðìÑ•ÔëÃbòËP\ªÒá±ÇèT;sÿÝá{É\€X!„B!„åÅí Ž(.Ô|äyÔeýÒ9DÄqô¯BElwô{†žAÇYõÍb"M~4íÕŸÁOY˜='œX@K@«&^0ÉóMx7ÀK}zù#GŽîãr÷Ö4 XOlŒPpªÒœšÊY–œKǦ8Sãá¡ô­pŒß\ÍÙd‚šôäñ':ëGö2ó÷oݘ æñá·´z á~÷½,³h[­ûô¥¦£Ê€‚òLq¥a¿!tõ=IJ/7e«D»ÇúPÓÑš¹¿B!„B!Ê…ÛÑxÔ£S#ÿ¼ˆN¤cHL Ðzµ¤]m•?®bw”ñ¬_NÑhUa3+.dæa8´Ž­gSQ„#;8ݳ?uô:”}q=hÛ0€ð˜,ŠUšW‡3KˆÊ°¡q¯Kç†fþýj û/YHüç767Î}Õ]Ù03ã‘ul<•„À¹6­«f°û›uŠ1×_U‰°—šežOyOTš3!þNh.X1\NÎ \¨FRÍøèk2ÇöÅñ@»F„Ç««BóP8½è6ÐyWÅOçKå‘é˜íØ Þ.hP•Ä‹W1_/“W¼‰çŸ+æ¯5'œ%ÞÒ4ó| ÈSï‚ñl¾ôß ÓåS\²6»J!„¢„Ñ a#tz=Z­ÖîývïÜQò…µDñUç6,¸/WEw›²MKMå\T{÷í#>þŠHJF£ÁßßfÍš†jµJ¥QŽ•‰Õj®Lljö°ÊõIS­¤ßK܃hN¢gsªÙNñëùÿ1ŠÍòéóØ—bËy­?`CµªfÖüòÔWl*–›“Tù{$„B!î “ ôúÌ5LF#çÎE±eÛ6ºuëFPP,ç[‚¬V+ÑÑÑlÞ¼ª‡†ÊªAB”c·-8bIŒ"ÁV:8x}XÍõޤ‹\SêP#PÏACæ†Æ£2U\Ò¹Ÿ‚»¡Y“O°7¶'÷7©ÊEŸj¨§~á|ÆõcŸç «êÂþC©Øìù0KŠ!Q©I¨ŸŽ£Ñ™½Gt>ÕðwP0Ø‘§51†DªQÑKËñ¸Ì(±Ö3‚¬r.„BQ>Ù2ÎòÛä7˜ôÓFÎ@Ø”AS~`Z¯`2βrÒX>øq3çÒÀ«î#¼2}Ã[ù 5âãYÖk DÌæûMgHqmÈ}Ï´G½ÙôDkÞ>j†ÿ» ÿ¼²úàç´ÖœçÒÞ¡ÃÞ¯X°=†q›Ù9®f³™½û÷Ó­[7š7o.¯TªT ???Ö®]K:u$8"ÄÝq øþA<xˆÅËö“h-èù­©ÉGÙÑ•'ûõ'nÙßDÄeàäW•ŠšHöœ>ÊÖÝéß÷a¢–l"ÒèO³^] ¼²¥1&ûJª&sbO =ø0:¨œš}cU5ùöw᩾ƒèÆZöE§€k¡õk¢ì_ËΫ¹[Žñï™ôéÓƒ¨e[‰V+ЪWsZ<…¶Á&Ž.z›¼@Àö_è`âø¼_éýójNüâNô/Cé:z,íÛÿÊ£ ¶3)û°õ_-8ÏóÑ}Á" ÀšþßOvªªO`` \»RÊåË—íîµãëç@•øÒ½ÝU•;wpâøñbuœ©U«6-Z¶”žKân Žhpô«Då QYc zž-S«¾aqz/ºx™®º¬¥|WŸFQS8´ôÜzõ¢Çs£qÆBbä~^¼‘X3`×Q•”S»¹ØûQ*g`OôMo`[:§VÍeaÊÃtïýœs21§öž‘GvÖ$.Y€w¿¾ô{¹Úôö„‡s&à~¬ª­à<Õd"–.Äû±¾¼øv¬i‰œÙ³•3¡íò¨O!„BQ–YcÿࣥFzÏŸËØnޙñ+U£!`ý…–;ñò_á'{½ IDATð¿ºz*¿:“Ñ+;ñÝÆxú?ž™‡_ß÷ÑÆÚëy:¾ó<LçÑ–¹ïÒZ»òôxø=Æt®Ù×Ú5g·0ó­ˆ;Рrp°k®—&M›ñÄO³³3“&OaΜ9\¼]*åÞµs')))<;ìy<<<ŠœÁ``ÍêßÙµs'­Z·–BÜ Áç–Mb‚ÝÏs‰˜¯±æ;"Ö䒘Ϳ‹góïâÜþųéÓwÙtó6s4¿O›xë‡Ò>æ½³/¿f‰ _À±ðÜsÉPS#Ùðã 6d=×tf”ƒãɪy‚šz†?ÍdãÍ7üw”‚êK!„B”Æè]œµÕfXc¯óÔ£¶s:ý,»Ú‡0#[Zµ ×0ãè ¬„þz‚Ö ?§ Î¥åÞp¶/O!«à$—§Ü{þùçiÓ¦ Æ #66–/¾øŸR+ÏÉ“'xêégpwwÇVŒ‰]œéÞ£óú‘úaa¸»»ËÅå=8r¯Qp iB˜k,‘SÀ³*­zwÀëâZŽ%É!„Bq36m3fG¬a``.CL§2¿aj”œûå9#ž=y*huÚB-* ÊžŽ:3{ölzôèÁ…èótêÜ… &àëç_è!6)ÉÉÅ.Szz:®nn¨ªµØ«¹º¹‘––†!%l¶båååãƒÕb‘›F”8‡{ùä5ŽA4ïÛ‹¾î€‘„“[ùyå.®ÉŠ3B!„÷ÇJ-¨¦¬aíD¿>¬æ¦´P~cÅ¿ ôïëOágVÐ Õ€Í¦ÞÆÔéþ,ïLIÇÀl_ý­q¬|®#Ã×¥ÐjÞQ–=ä™3¿´Œ¾ïQ–$ælFtúñ0 :ò?^åIãà§/1vÁvŽÆ¦N7ë͈÷ßãÉÆYubÃpl“&|ÌâÉÀ…VC™;ÛH˳N\¨P§nÄT.°à­Hܺ¼M? (¯ tžz…°éMhp†ÕÝW²'ÖD7¯ ¶L™Ê¦3Øòq?‚²:%4iQ¾o5_?~6޶ ÜèúË̦ôBç“n,Þð“É(X,æi>ÎN«Õ¢u&¦àˆB!D™ñzR/ 7žHI`š§g¹: Œ”,Å©:MZÁc“rIÔW¢çÛ éùvn{ÖäµyíæMÎÍøèÈùO]dÑþ‘Ùö+dž…fÜnDuôÁ×9+àb>Ç‚×f’ñâRž©~Ž-…ÈÍý;ßpçE-ñRì<^!Ò­)çøgñZbƒî§c%=¤ïã·-iÔ|:Žé}š±*âÎÕ;0dÂT^íT®3í›×'-1žä˧9—ˆÙlº~Ò½a_;ƒ#æb•AUUn_Ï$8"Ê}pDëEË_¥Õ¡Ïù|óJ}Ú ­?÷AØŽOøjG"2Ej s¬Áàq0.˜ÁҳƸÞeèþ+kï…²¤$êFê¿äÎÕèò¿þtuGc>ÆSrÚxoÝÁ }ÒÓ雚J÷  {êúß çþxZÎßÂû§¦–»àˆÅjü&nããÉÛ ´”¶ž `"ò‡WøLÎò§CÑeœ+Dn&N/™ÏqÿÞLoênçñìKOÙ0„†C6`ðêÈÄåií®`‹¿È™$ ?ûŽŠïÍdÙTNþüc† D _ÇØºŽå÷ï°¢`5&s5ºõÃ0³zd(öD#î/òñoÌ9¢(Xs™õæmy=ÎîÕ¿ËÒÒâ.Ž‘gƒÄ›6/¦Ù¾Ï˜½íj!$ ŽAMèñpgšTõB‡‰ÄsÛYôÓßD›²ÿ¥4såÄŽÆeó˜·áܲ—¥4é«ðèëÏÑÔ9ÇW N-˜ÄÇwß½U–ê@ãJh‡¾ôîP_½•”ó{Y»ìO&˜‹ðz žõ{ðpÛÚT®è‡«æ2k?ù‚­ ¥ÒâÕ¸'|²`æ¢ÓL˜Œ¹¿u¾u¹¿Ûý4©‚§0^åÜÑÝlZ¿ÓIz†½Å€*ÿíaIŽæà?¿³fw Fmýõ|Ágá—þ t+î4}a]ûžÁXÂ÷Æÿ ú¦¥ÑÊdºçV€¸—Ï]ˆ{-õó†eiÈ›¬|«î ˜Oè/õÛ“TÓ…ùHÍ8Ê/‹¢¨ôø`ê;Ûw<{Ó][Lamx"iWN²~ÞûLô¡Ï £-s­§.“™6¬Þ 4|çŽüõ ¿üzŒ—ÛeŽUUÅœ‘F ‡Ž#³†¸dªÜ1ÿ}½||øéÝÇŠuüéÓ¦bÍšsÄš­7ȸñoÞØ–×ãܼ8|$ž€)ë´Z°ZmRÆ:¦Ö·ƒŸï‰ûÑ¿Yþýy-Žxù;‘aËõ¯7‘á+ˆ, çvGÊRDæXÖ3‡ÚÿÎÉ­~?žl—ľ¦»æ›\Ù©´x5È“ÝØ»ô+\v¦îƒyüi3 ŸÿÉSa_¯ ÕÛH:³›õ'ªÓ£›WiF}pósC½rЍk©äfӵ癗º³‹ð%uÕ„Î3˜šMÚðP§h欼 ذžý¯WŬs'¤ùCôéõÄÌŠè²yo|”˜xÏþá¿—Î}©‹ /Ý4¬`‰««|û÷F`$íß<û32^`ѯ/Rß%3‘vb=®ìà@ÛªL¸y‡çëÒø#ö¬Lp?üöÿÄò¸š<׿ŽvÏÞt[Ej×­„Ѹ‡š=ÇœmèÔÑŸ'¸R·2®×wq¬@ƒ`øáÜ5ÌPnƒ#¨TÕBL2Ôiس)ó‹…=Ó"Y-–b¯èâììLrR"...ù•±Gjª ))xwipDçKƒ®½è~_u¼õ~é0›W­b[TÞí†3ªÕI¾út±Yó)Nµ0vËf²ðX¶<÷OCÍ6ÓèÈjŽ·£e _1ìýý~¸vã×E[u:=Ó™Õ=Q çÙõÇbÖÊfcGþÿEdÅ64«êA҆ϙ½Óöõ¥C-oÒ.²'|ž=º’ZÐð‘¬ü\NDH:ÖñA“x‚õ‹–²ËÚ˜ÞýºÒ ÀCÔ&–ü¼žÈTp  Uú´­KeoGP ÄDldåﻈ1Ún䙽Œ_ìp¡ícÑ©vfw‡ïÅ«G·Ì2^à‘1Ãð_9™ï®÷p¬Áàq“þÓL–G©·í˜™ ë©5øUzjàÁ×xÿA }_O_NT~msÅ™êݺQ1z%Ÿ.ßOrÖãÑQyÕïÍÝåS¨‘×1m…½æ_²8­ çZyœÛŒ  »µë¾âT‘Ö½zÓ±A0.Š™k‘;Y³âoŽ%ZoÔiž÷²¢' éC<Ú­1Ý´`M'þÄz.ÚÁ•‚þÙL$]Š!é¦zjñˆ/Æë8f»ï[þùÝ?9ŽU©÷c9¨­MÚW#cÏ<ÖE\À\]±Žú¯õ m¥ ,Š4úõW÷¯e5 «èM§®GŠSöüê-É‘7z{<Á;‚åøLYpêÖ ‰Æ‡æ}»Qéòß|ñÝ&.]ï,CÔ‰ýlsÕa&ó´ÍxøøxŒÄséÏߨXÿyêÔóC]”À«£}÷F‘>—3ß#p!—p2Œë.3=ë×Ë~YÃk–¸¸0ÃÃC*FÜ‘ã|ûl_&_}ŠŸ—¼J3÷ÿæöpëð ëÃS¹ñ霺“7û¾Mú„å|ö@üóaKb×÷kHl0ŽÞUuvÏžôœ-3fÕ†MµKM:ÕѰåäÒlõÐ+€)Ž£—À§‰7ºò|Рwr¦j°Jä©#X²‚#(Påþ;üZµj³mÛVZ´h‰k1Ç©©©ìÚµ“5j¢‘!5â® Ž(ÎÔxx(}+ã÷Ws6Ù &=yüɤÎú‘G÷q¹{k¬'6Æ(8UiNMå,KÎ¥c+`ÿ}-­špxÁ<&Ï7áÝd/õéMdäÊÈLl߉ø?—ðÙŠT|÷b`ÿ§H‹ŸÍúK:»ò÷oݘ æñá·´z á~÷½,³h[­ûô¥¦£Ê»ªKK`»Žüýsÿ¶P¹ó z=ñµ“9öç·l4Ò~àcôëtœWGcFÁÁv™=«þeY|¯ê´ëÓ‹'zÄñÙª¨¬FHö2º6àºxdé—[ˆ¶U¤mß>…(cÑÙÕ÷˾ÜD”­íëCMG+0qrá'¬É1ÄEƒOÛá¼Ö9žï?ú•ìmDtA4¬®'~§;]žGƒÌWN³{í*6œL. bÌý˜Š35úöš;à×8ïúÈõ8Z/n}¯q§A¿gètœUß,&ÒäGÓ^ýü”…Ùs‰Uó¿—ê›Ñ¯wm®üö-KN]ÃêìGÅGŠ2·¸Æ+Œ–ûþ,é¶;ð¾ÅÁŽû§0ò¿Ëzý+NAT÷±óç%®Ç­)ç9•¤§Q5/´‘—n™©°¯/ðÇ«÷Nõvèë‰$öÃPß•Lùþx®×VëQ‹¦!¶ÿgï¼Ã£¬²þ›žIï…¡„*MŠHEÁ^uÅ‚ísÕÕ]ŵ¬u]ݵëZWAi¢" *½÷BBBz2}Þ÷ûc$3“Ì$ôp~Ï3áÞ÷¶sßvÏ{ιd|·ž|/"k¥4~¶ëS]8]Tù7äL·wn4ä¾\uðî#>5uÒ²±TÔ# §FÃ+ÑѼ-Âh¤üv0Œßîk@É0Æ5V¡82øêž±<·¹O4а¬ílÍ´fRÚµ%!¢i«_~˜]³4ÒZFvv¼3‘§÷\Ãûo_O³ªÕ‚R¸ŒÏ³Òû•ÑÇÓ‚jOs î|÷Þyýâû÷¡}²gþN|üKtƒx§o4†Ñ\É«zšÉS"yä3{§>ŧ9íyøæŽç¯ÕP’»KÑlÖr¢—Öó°=S1;úôíËÚµkX¸pV«µÁõ˜ÍfÚµkOç.]0rcŸrDÑ‘¡Ýœ¬üh›Žx^çKÿÀÒ®rqj›¶ìdcÞHtKdQn..M-{§BÆ÷´©A”÷´S±mËT¢…;V³oô¤%ÙVØÛ1ŸŸÖdR¡Bá²ÙüÖùQõIaùâ„ ê·ïXÀ饞‰¹ý[ÙX÷é¶å:bÍmN—I½‚eßû3sWïÇü±Ž À6g*+Ó-¨ä±xÅ¥tëÝŠ(í!Ž*Nr×,%÷øpóæ¥ñ—k:o8HŽâ¿—¤:XÿÙ|¶æ8€bÌmI§ûºû*ذ6Û:Ùðù/lαWµÙŠÎ÷t«³%WÙa²²K°ùYKh QÄ™µ4ÒŸ’_fñé\I½¯fì„»Pß{Ÿßòê¿` öœª>6·Ý”<ê\ FvâÒ ›ÿ7—uí¨ðÛŒE¤=:ˆ~M–2;»îsy—=šPw!ûöeSX¦@Y9%Gr¹êHèч¤Š­Ì9d?-×m°çO=–&çµü5!Q„b¥ÀR­£ª•R+„D™Ñ—r¤~ÇlßÜð¾”ÛÁÀÚ¨d")#ý¨ í?´¡4é5”^QNî/ÄÅé÷;®Ï}¹(ÜsøãâÔ06m,Gö„ó‹kÇŒDUTÜªŠª(¸UP»Óªª¸•šé*°zõÊF+µ| ³—Kyå¶¥ÕrZóÄðçöl-Ü”ïßÀúmWs…v“ÿÛç,S/å½a‰èêÑÞ£qúÓÒLXáï¼ûè¿È*4‘´¾dÿœý4ãªöíþÓ^~†'^¿ŽËŠ!´åîÿò_üßyŒµðhqñ µçßyúû Õjéׯ?;w9ué0™Œ²SÐ8•#ú˜VÄâhñð ñ¾XcBѺ²kcW\z‰‹r9lhIï6°oZ&6 Ê£n*òËN,;•N=±Æ7â¢y÷p—“}ÈŠ9%ŽÐØ`êW(É)âØk°.º 1°øè‰cgá \=ƒ—BÉ¡ÂãßAU[9Vw)ÙGíU/Ó*¶2Â0jEKx›AŒÕŽ)á7 tî$ä¸ý¶W£šM‹ Nø¬8 öQàº(Ø[SƒÛ\zäĂۑŸÎw×:eQ¶mÿÝVÛªÎÓ²sÏ\~X™ŽE…Üù3IN{€^=“X:/‡ún<¦©ÿœ'‹Ì¨¦Ä¨¬Ès_4)eY´˜iš‚6›:ÏeWö&ÖåõãÚǧ÷ž=ìÛ»ƒ-Û2(´×s fH¦WÏXJ6­ç°óô\·§B^õ?ÏùŸ\ ï{@¹´žÂžjO¾†ï.YI“;ˆþíCL³ËP•Ç´zJÞ~™¢ð æ;Uv‚3€>tp4¤Œ¿cåj·6æ9BggÍÕØ„6˜ê^Ètr8XŸüÿ#Ù@f½ívfÔ«µ«º~1›¹7.£ªr­ÅÂ0«•®N'±Š‚AU)ÔjÙa42ÏlfVh(NMüì/µÙn³Ñ×n'Éí&RQ(ÔjÉÓéXÂfs½ëLp»¹Îba ÍFûª>kàøù¸Ædâ‡ÐPv×q=ží9¬ï¹WnsáVTE©úWÅæp¡(ªOzlÄù» êŽ7Žrêa1”¯3«ßBé÷öNrj>UH¾iojH{ò;p÷{?rw¯t½óÜùN£š«Â£çD?"""dU,ˆ9¢Q1ëÿ²±Üÿ‹xùî äÄE‰‹(‰êMk5ï²N|a¬³¼Î£)UÕç%;Èwñ êWQÜÊ) äy¨Vÿ?¨¨µ¬S4awÛÂV}û_ ÐâÄÐêzžoªÖ'¯>j‚€ê+ ÍI¶‰ªàª^¯¢ œ„u¹ê,§Â •GŠ9¾Žs•‘[ ýbCÑ6ô_Ï9N'{VP÷¹ìÌcɧ¯±«MG:¶kG‡aw1ô²õ|ùÞ쳿@75ëËE‘¬Ú”_§£ÂÉ\· ’×IŸç®üU[)ÌD…V;c5f¢Ì`+µúXÔ÷ø€œ¢s'¨ió§v(Í£Œ4‰ A“Wé·ŒNUÿûL®[ñ3z—âõ* ñŠ‹ø“÷À<³™g¢£9jÔaÔâRPOé}ùì°(/–^Áì ªJ¤ÛMs·›Av;O”•ñGH“££Éjä_Ö¦…†ò¢W ÀûË˹'ÀÂúF¯­wo´Xx>ÀÂúþòòÓ2†‘V+c,ž.-¥™Ÿ@…IŠB’ÍÆP›Ë˹?66  :½ìvž+)¡‡ÓWÛ¢(¤( =œN¨ÇøtªÊ£eeÜ_^î×Õ ^Qˆw8¸Øáà¡òò×£þÆ0‡‚ ‚Pj]£ºJ²8J2]Z…Öºˆq—íaÃápºôhEÛÞ­QÒדe ¾|yb['s<˜µ.œfÍÍØa)ªýîÒ\J4 ´‰?ñ¥ÄÛšý鉩¬‹jA²>‡«Ò)¨t¢¨:B““0סp—äR¬I m‰ CBê‰>*,0†[gŽ#ʨ9©6Kˆ¥Y´®Zß›kÐT[|xöb~QW@z¾Jhb4Æã$%*‹,A ø¶Ùs*°<Í]šC±&ž¶I'æDÙ‚–¡Vò ‚t7p[ÉOßÈ’yÓøäýid„w¥W“zødjÌ´ìÛ™ÐÜ5l)ª}‰}²×m½ÏŸ“>Ïmù«¶<öéhÒ>‰cGë"ZÐ.ÊAvf‰åHýŽç4öýTÈÍ]¶—M¹ZR÷"Aïûøˆ7ø¶ ›[—ü裩ÑV+óŽ¡-á´‰ÕPšW†›óŸ–AFù¿Ìfãç#Gèg·Ó˜™ŠwÌî6mœµÛ êU•±^ ë± zµö³µÓÉ[Í}HO•dµÀEE~#Þ´v¹˜QP@š38›ÈÛ+*˜QPàW1ÒPÂ…oåÑZ#u]©~úÑæPAN‰rD)ÛÁï›l´w+û6'>:šø¦íé3âJú c­”±g}.á=¯bT[…ô ‡Ž?Ђ*Ìâ¶Í\Ù§%qÑ ´x-ÃRŠX·.{êw—íbeFI×&ÑD'wbØÕ½‰ª²9Õ(y”¨ tj‰ Ƅ`1²“•ûMôwÝšDÒ•W÷$òXÿÜ%ìÏ´‘Ü·;IF c<ÝF&E£ž\›¡ôÑ‹ƒ!žî#úwü;%en¢R[“N˜Ù„-‘]¯çÞ».§©?«\¥”‹·ãNØ‹[‘ß”.ÃÇÒ?ª€õv©ñÓ¦¦sP~Çæ+Ÿå{tôw½[Ɠܑ¡×]NÒÑu¬Î ¼®!åFêFë¤h""âhÞ±‰Ú2Ž”y¢šRºÑïâvDÕ¡ÀÒ„¥Ò¿ƒ¬Õ;)­ã=ý¤¯Ûúž?'{>žëòw±iùBzcd·¦$$·cÀØ‘4-]ÏŠ,; 'eðî½±Ѻ`Ž­)Ž”&MHI G¯1•Ø”&M’ˆ6iêÙw¯¶O±Ü<XÌú9‹ÈNÁ}C¿Ž-i’Ü„–í{2ü¦I̶Óß^÷œEazñ^º[·³rGiÐÊ‘Æÿ>ZUùoa!).•Ž_½ÜA´À}^ÛêVg˜ÍFœ—Ébœ¢0Ìká\ûülùkÜPNªÊ;……hÕºß'ÆWTðJI §ÒvHSuNõo€Ò-EQ˜rô(Q^²¿çPA¸°©ýÙ¬ZIŸû1S˯bÄ5÷1(p–‘›¾‘EÇŸq åéëȹæZZØ6³¾zÈ Ê\!sdÙJ:ßÌÿ‰@[™ÍÚéÿãÃ.ÀUÿúÝ¥lù~ 1×ãúú¡³æ²~Ñ"2ã> fÙJÙ6fÿК›®yŒgÇÚ°g°véNZ ÕÔUˆ­3¦sݵ\÷@t¶\6üºô—W`'ë×鬸éz&={9®Š<¶/[ÆþöƒO²Í©Ä\7ŽûŸ‰ÛRBÆúåd´¹´ê~ûƒƒ·ŽáÁ'ÇVm«;‡òÈZ4Ó{bGøž@TîžÃ?Žaìåù¿Pp¥³|êŒÕ_›³ê=çåá§ýîUI9Ûf|IøÕW3òžG1ã¢dÿj¾™þ‡'öG€›ârÑq8ã‡Ç`Ò€«ô gÊ£n@Kxꮺ,ü­é”Úýë0#Ú÷'U³Ÿï÷–×mus’×mýÏŸ“=Ïuù»)Ù0¯ÃÇqõ¸Iô5¨TZÇŒ/‘íðÌ)¾9-š¬ÚJ0Ðñ`j;Žoiu¼…þ·ÝGllþì ŸíÄëî»Ñ«mê'· Pqä.å‹÷Š<| ƒoîK„°‘üõW´:TÒàûcBY ¯ü—MÆà·UmÖˆ¾Ñ¾`|Ê•^»\WYÉ‘‘~Ý8n¨¬ô[Ï ••,ð³X>WÛiaa\eµž•1wt¹iµòKh¨ßüîv;/–”œòv'VT0è$¬‘š¹Ý<]RÂS±±çÌ Á£Õjq»Ý"ˆ³ˆËåB«ÕŠ á'Ð;%…"¯Åø“¥¥<ì«â°VKß”Ôj®z'+€%&GD°Îèq!Ls:y¨¼ÜÇ`ŽÙÌÃqq~뙑ŸO_‡¯åV®NÇÿÂÂX½žJ†8E¡ÝÎôóSæØNçõx®Ìa] ýÓë\;f$eg:Rãd IDAT½²®^½’÷¿Ò·¯§ÐÕéLPYQÁ¬9?ЧOú÷ï/¨³ÄÞ½{™?>÷ßCç”òü /òÎ;ïˆ „3¦âÔ`jÚ“^íSˆ 'ºI†_7ˆèœõì*»pÐÇÑ.©ˆ•K2ea.ò?ocµú,ĉå¯11l1±jµØ4ö ü;*Š›|âè€kÎÒþSÍ5‰‰üJ±N‡[£¡B«e¯ÁÀ¬°0nOHà‘˜«/-0ª‘ŒßŠFÃL?·WT`öZl³X¨mßCU~uB…Ûý¸wÌ zQ,/FE1>!e!!Ø´Z¬Z-›L&c™Ÿà¤9ü»­]l·ûUŒül63$)‰"#Ùb4R¦ÕâÖhÈ×éø)4”ÏÚõØXæ°Q?Æ zõêÉ’%Kسg®Fì®w.âr¹Ø³g³fÍbÈÁ8Š œÏ÷Ô mÀZS2½Ç]͸=`§pïr¾™³–ÒØA<òèü¾‚üÊÛï-¡@ô'Â)ªæòËÛŠDþç—ùùZ>ÛlfN-®›Fþν^‹¡þv;7‚-•‹¹Ùaa\b·s³×±§Ýx Åi¡¡<äõ5ZU¹¥²’Ï«ûF?®Õ¹Ñbá³jÇßRYI´…Àô:ÎÁ†òImó£Ñðix8½¬‚’kqo¸Ü"l—ÁÀC±±¸NBpº¯ÇÆ0‡£ÑH—.]ˆˆˆdÁ‚ùäç œÌvƒBýÖZ-‰‰ Œ=ŠíÛSY‹k™ ¢9Q±fÌãã×çùÉ[Ê;“—ž›Ý¶ïcê?^–³U„s‚N~¾Œ}DŒ€ŸÍfŸÅXûóÌ„ýd˜ê£éÐÈÇŸi0°Öh¤×9sOEÿ Ç­ÑÐÉá S9tr:éäp°ÓhD§ªÜãÇâ`ÑH¦ÁpFÇ·Õϵµ…õ,õȈ“RŒœ‰ë±±ÏáùŽF£Aq»i›Ú†ŽÓ$îÅY@Qœ‡(F¡ ‚ õ!ÙÏWÉÆÀÛ §ûYôÄ_@Awû‘Q´Úøý¹¦‡…ù,¬›¹ÝŒ±Z™ê×âàÃðp&y-žo´XxÞhäj«•¦~Λég!ˆgq=¢)~ú¼Ê[ιx=žos8ëûï|Ò.yM£¾Îìv;v»Ä¥A8D½,‚ Ô‹? úò ¾~[ücº€äVágüá€ùûf³ß¹¿¯¼½ª2Öka½Ã`à•èhvz-ÞÇZ,èU•ûü;¬Ôhøñ,lÿꮇÕGŒŸ¹>z ¾òŸ‰ëñ|›Ãko¸™±×ÝÄc®cÄ•×2lÔ8¹q ‚ åÈy‚±Ù(}ì*Z˜DµŸÍ‘t¿ãIîîhwWAN›ŸERD‘~‡¶ (ð¢?Eˆå¿E«å'?‹Þ.N'Ï—”ç%—ªâR|äû"NQx¾¤„Î~Ü7~2›±žãîþ)a§ÀrèL\2‡‚ Â…Àq·š¸óèÀ,>y󲪞Y¦Ô›yò®.”-ø7ï.+ôDÚ×DÐãž'Sù5¯OÝ‹+º#C¯AŸ ˜5à¶søÀ&þð•*ººò-fºN|š›Zžèb)`ïÚüøÇn‚Ý@FÞ–Wf@ÇDÌE髸iÖïì-wF𹑱·&%Ê8)ÍÚÆÒyóX›mC5¶äÚ¿ÜCOŸg¾Bú”—ù_FrÝù»ý™0j0%÷`äUCéÑ*J2W1í«_9ä&ß{ÑEç=°¯þ{Cå8¿ÞãІÑfÐ8®”FœÑMyÖæÏü…-…U'P]ùÚ(Ò``´ˆ A£Trd÷jæÿ¸„ôr4&š^z#· iK%ìþõf¬9‚Sõœ¶ICîå¶Ø…|8{Öcï€J»ïføƒh¶e.źTN G´ZZy™Ä·s:YÀEÀß‚èH=CZU øô¤PU8õwñ3þ¢ Ǿ}ZX˜_׋;¼|ô³uºãÖsÍfžÒéj¸_ÜQ‹Oÿ´³àRS_J´ZB½®›nËBB΋ëñ|šÃ Ñ­FA8…Ê‘²Ì *®hK›hYn@O\û¦h*D·oŠyy!•*`L¦c2ùé0}2Ãî¼KÝëùù«™,uaŠiB›öI„´ O಺ò=od¸üÈ'sàЇß~ × ¿…ŠÞâó¥48ÖÅÓïö 5®gö'ߒ匡ˈ¸ív;ï}¼”7¨Öl6-\ϼâJSTŒ+¢5Æ çŽ nÞþh)…ѽ;ÐÀâ÷^d³¾/f‹v}ÊúRmloÆô*fáÇ'#UØsÖ³]½‹m‘µË‚ìÎ*§žÝƒÏblŒÕp1v£ŸEÑîZ‚/*øš66q»ÉÖû•Õäl_¥ª”žFÁ-~Æ¿×ÏøãØ×šLÐéh ÆÌ'U>ÁciñIx8Ï—–ÖYæ€^Ï:Ó¹oVy@¯§‰×øï®¨8iåÈ™¸Ï·9¼ö†›Q›Ã…¢¨¸5ø\é¼5h?ܽšßîi~rÁùNe]š²Ûq:²SÍY@«Õ¢70™Ä¼[rÄyt/‡}h×,”%娺Z¶6‘µ| ‘:’lÜÊ~;âÛÓÌPÈÚC´‘ÝèoeÛg¿°ö@Õgúü<²öT-®cSȩ̈ê=LµSPP€ÈÏ·Ó¤w·ŒF„rDÕžMílùl›²ì@Ëø._Fÿ¦«˜›å wÍbr—8Dvy<]¼ˆ‘:v[”Éåøc[MŸ1qØ÷,`ŸE5@¾73©Ã‡ÓìÐþ3keU8t0È|ß[.1i݉+^Ï ¥Árø¹"œœõ‡.–[c[ÿ_lÍÆÍ^@çÇF2 ùïLËŒ¬;³?ɨÖà!òÜ-yê¶Î´ _Nid áåû9XæÆ¥É$ÓÒŸä”GÐíÊKq-ù”]þäá:ÊÎýn&ôjAÈ®ÝXå„SÎò®ðÚ>t|EsÍf6Ôòr8ÆbaœŸ­L—ײ0,×hˆòr g±ðnd¤Ï±Ñn7žô¸.±Ùøå4m#zWEWûÿ ?ãolc?Æô°0ž*+«5¿D£ñÙeåÛ°0-+«3pí´ódë×5&¼f³Ùø[I ¯GE5Ø2èL\2‡ç6–ÊJ2dÃÆÉVŒ$$ÄÓ«W/ºté‚r„F­Á‘Ç®#®ê„qS9SÒbŠÙ±{)}¯¥]œžý¹*­ÚaÉ$£Äb,¥Üm¦iÛ²2©ôº(öºó}ï0&bÚõ KŒ›üƒ%UVZb<ÈcC øâŸß±ßËUBÕêÑâÆé:ñ PÜÜš0Z6@›UTCÁ¢5ÅÑ®g'"ËÒI/öí6º }›ÙÙõÅ«„`ò1$Ó-ÕHÁš†Ýó$]›†â<ºuóçòûÞ2”@ù~”-)íc±ådSQ‡üÊaOýähjH2©±nr9Â1ûwyé¥F.j>/±Î|Ýþ#>V0ZƒËB¥CÅ]’CYdÚĬ¤Tß–6¡¥¬*sÖ~$ÃBWó¿M%µXÑ89z ýȶÄv“픋\N5sÍf&—”P}e¾-(ࣈ~ å`••C;§“›++ïç+µ­ª.äêõDy™ý?ZV†M£aVh(%Z-)n7WX­|8ÉÉɲïÄívsèÐ!–.]Jdd$©mÚÈ®A‚Ð(”#ª…ì½E/nGœaG:`ÙÏ¡’|ÊóÍ\Ö"Ýa'M;ÄãÊù•¨Î=üüóvî¸z"XIAÖA23v³eÃV–ºP+ä{VÿèÓîàÙ—N,n³Åw[NX¸Ê“•]‚ÍÏûŸRºŸ}¥Ãé9´맯ã°3‚ƒÓ (6£Ãc¢lj?§'´÷ê´¦3ï“y°{k7t$ôèCRÅVæòwc ”Cqf-M‡ô§ä—Y|:×ARï«;á.Ô÷Þç÷òºóËó2Ö†“©Á²¯’ºtKä@r v8£ÅJ¥Z)ÕJ©B¢ÌèCêÎ×U½Ð¥2lDkÊ×J†MÅmÛÈìßZpÃÄ¿2‚Bvü2펖Œº"‘­ßÿJüˆ‰ÜÕ+Mþf~š6¥ÇÚQq••à M$RˆrDN9Å:_†‡s¿×6fàÏååü¹–E7_„‡S¢ó>y£ÑHG/ø{i)`¢ z=ݼêOT>.*jP}c¬VÆXëg«öUx8~ƾ=Xòôz–˜L\ægá`>¯õ<¹·¼ÜïN*KCBÈÓ!¸Ó †„0ÒËÊ ƒËÅ œÛ3q=žosxRn5ÇÞ«Ê6ñÑÝ7óÆ{©ˆîÆ„~Áë×6§rÞÍtª ³×½JÏ…#ÓÆÐùÁ\=c+Ÿ‰€’ùÜÜý1R¦oàßÝ몫Æ*·›Ù׽͸ͯóæ‚L”æÃùë§p§þ{ðUfï.'¾ß£|ò¿¿2(ÎWNN§“ ›61|øpz÷î-¨³@óæÍ‰gþüù¤¥¥‰rD…r7%™TK¥U¸Wjst¹?Qä´cÝSBLZL›¬tHÑ’ÿëa€Æ£­wî™Ë+Ó±¨;&ÉiЫgË–Ö¿t^NÍõ¼F‡Qnç U‚¹ÓŸøÛ­mª¾Ü²øÝwXt$€‚”S°ãX¾æÔ„S n»…î¥ ùdaVÕ¹e'oõ4Þ]}\ø4~ möýÄ—a#˜Ô)—oßü÷¥÷sÛUÈüfǼœ·z : HÔA8-¼ÉP›ö Œw±[¯ç-?n"ǘÊm¾˜Ÿ ÌfÁ™d“ÁÀQQÜØ§‡…ù]XÏ ãh- 䎙¡¡Üê'èùæŽ19:šÞùù>»»œë×ã…7‡v¾ÿ*[Ÿz…ŸŒáàÔG¹ç‘'8ð;®î:‚6Eÿcåa'=[ÛØ¹`š›?€}H7”ôߨªveB»€u]U•ÿá[t~úML6²öŸwð—[dz¨E £^ü'"vðΟfÒW°þµ^xÛö(ŠBAAIIIò`:‹´iÓ†üüü ­vââ=y…G Îj¿EaÍšÕìÙ½û¤”:f³™öí;Чo_±\‹rœ»Éuõ C³8í"(X‡÷¡ ¬ƒÓh’TN˶¬¨ae Ø‹ÉÚ]LÖî,ÿc5#y€C[±bÊ^ìuåOÍ@µq$/;yä}k¤ùc£Õe#_m.{Î ¦þk¦ˆHB”JÊÕvÜþTo* *Ž['¨öòóJ€\²sì¤ø€œìCg¥ßk׬¡¼¼œ?M¼—È ¤þ¨¨¨`ÞO?²vÍúõï/'„pÞRóIh?Ìî|-M.êJ—Ø2Òs¬¨€«p9Ú–tíÚ(Ûö×ñàu•SP ³ ½&@¾ŸlwéV~ßî¤í^ÄÕë>¯`//¡´ÒMDZ_ZëòØ–Q‹rE«G¯ÕÔôûÕ˜iÙ·3¡¹kØRäg|òOh˜HÏW MŒÆx¬]$)‘PYdA ”ï3¬ru–y\^ª½„‚‚‚ª_1•nµrRNúiËc‘Ž&í“8¦¶ÑE´ ]”ƒìÌ\ò݀ƘDÿ[ïadè¾úò²ìµm×M¯1SñëÒ+U4Z ê±—2T´ÕæR‡9!}Y6%.¹Àát’£×sUR³BCƒ²ÑRð|%¾*1‘<}à}‰á÷ vòPoêùõ¹\«e||<zý“W©FÃ[‘‘\—PëöÆ:öc84æxõwaHuì’Qå’RÙf3ÎÓ¹½ñib£ÉÄ•‰‰, rg‹Š Çxº¯Ç k 4ëÕ†°c]3ÆÐ$ÌN‘ESk.ëibׂݔå­eyE®¹úZå,d[i1›~Í"qpõAÔU-ÿ˜Dõ‘)D›Ð#5¼êÝFODJK•gõ¼çÞ{ïåòË/gâĉ :”Áƒ3yòä³ÖŸ½{÷0räDDD *Jƒ¡f3#FŽ$=}/åAºò ¹Hͧ¡RAÖ¾̃Ò¶b=¿‹ãàÈcOa ×÷×âÞÿùǾÐGõàÆq©äoßÎþÜ"¬„‘Üi0£›)dý”=²7בï÷›˜j#sùzJèǀ櫘“é$²ëµÜÜ»„Ÿ§,"ÇÇXGL×tÒ&»ØEXóž ™JùêÏX_¤€±C.oGŃä—;Ñ…§véHÚ*û™qÐzüB–Jÿ²~ÜI©?ÝH­ùzRßʘ¤mLŸ¹‰w);ogømcs±?2œ$]| ý£ X²ñNÅ]w¾ïky;óÐK%NŸNn­ þr˜_Ïq¸U6-?Àà1ã™9ƒÕù¡t¼b$MK×óc–ÜEuçëâés˽ŒnžÍÂïvbI¡I €“Òü£TºÔãú»ˆNW2P³œÏ·—£ ¡8ãÆ‘I4åãJK#¬` EÇä¢1’Ü6KÆ>Š%`¸ œþ¿VËÿÅÆòvD×Z,ô³ÛIu¹ˆ®ú‚V¢Õ²_¯g¥ÉĬ°02뱫Ôj¹#>žË­V®³XèápWõU¼H§cÁÀz£‘¹f3™ƒ_“ýºØg002)‰k++eµÒÉé$ZQÐV†­–«ƒXÄÞÀU ;$»ÝD( åZ-…Z-ÛŒFVšLüd6Sä×ùóiìõeZXwUsú(""¨rEDÔˆ×1í< Äêl½žñ t·ÛmµÒÏn§©ÛMŒ¢ à±¨ÈÔëYm2ñmXkòòÎúõxaÍ¡­N[ãÿTTT ŒŽ#;`ym1[×o%§Í8.jÙ!±o°`Ó&ì»CèõDëjñUêªËO¾FhÑWOPÅö|gÈeCyÿý÷9r$Ù‡²¸lè0&OžL\|B½]lÊëØ9*X¬V+aáá(Šû¤w9 Çb±PQ^~Òçktl,n—|åζr7Åûbƒ1w/ÇÎIÕJÎÞ"hOþ®œãnª-—ôüN\<ä.‹6¡œ¥‡Ø5ÿ æ­+Æ­7Ö™¯àÿk—ëÈZ–ç\ÊÈAíXtp'úÈZ4Óâ÷Rc ½G`” °açï_òãÒØT@q`oÏàë‡cò(_ laÎ' ØrlZ´D´ïOªf?ßïõgmRW¾S|sZ49ˆ¡ª?•»çðÅc{ùDþ/Eé,Ÿ:‡ÅUÁVå{¯"} ¯J§¸_É=RÛŠ?€æ×%¦ñuø8®7‰¾•ÊCë˜ñå"²žs©®|MX.jgRqG*#Ž£ßÞ~‡? <ãÔ„¦2|x$¦¬§Xñô˲÷'æušÀŸžÅ;øùëTT“Ssº7·²ýëËUÎ ÿª%†ÆÉ²ÈlfQ¦÷Í›5«wÝ6†oÂÃù&€K@ V›L§E‘p>Œ½¾ì0Ôßõ&SƒÊÕ§Ìé®ß›Í&›ƒ8oêÛÆé¼ÏÆž[h‰î~9Íó¦3ujñC^$ÖÜ‚A=UþêkìÖ<×ñˆ£â.dÅ»ñÔû‹8`Ñ“ØûVžýÏs\ÛÚŸEš‹ÜŸ_aòÇ¿²nsEî<»b!÷·ò£¿‹B7„µÀ-O¾Îß®iMˆ&pùsEQPk5—ɼ¼<’\çß>_{R}êÂq¥ˆ·rä¯y‚×ÞøWûcÎì™'íæõÄS£ì „“TŽ€ýÀ ^ž<ÃûNHÁ’ÿ0y‰×rÜ~„ ó¦²a^m7æùXØöɳøÄZu³úÃg9‹sÅ»L^Që­†â Óx{Ã4ÿÙ®|VMÿ˜Uuß®(Ûø ߨ|™3_frMÁ»f¬™Q‹#@¾÷á{X¼u×÷iÊÒ³p4Dó0¥‚ý|Í¿ÿ ÞùjåVþ;ykà±[Ò™õVº×ùQ–™ï°e¦÷ÑÂ;\B«’U|’+ªAAN=Æfèñ2_-åÖ'[`ÄL‡ám9¢[p“nµŸœµ´¢(h8u–#z½½(GQŽ‚ ‚ ‚p6q—¦X¤mtµ×|]M£ $§ÔS9â`ÿ—ÿÇÛʃ̺³ [f½ÚsVæQêbËÛŸÓìù7™ùZ({¿yšÇo¿Í¢<ÑQOÂ¥“xa@'ºµ £rß">~ñn¯òÛ܇hoŒ`ÀKßòÌÄk¹¡Ç;Uõ§qϔﹹ™P”?wçJ£Ñà¶—‘[d¥cç.8ìUšàšnݲ©Áí9¢ÑàöµzZm{óóO?ÊÖÒÂy‹(GAAAð‹sß§<òžžG~˜@k`«_yUõìÍ2ì^Ÿx1èöì¿Ù±pß~·‹‡^èN«±0ñXžÓ§u—Žý’ovMäù®Vÿ}/¥æ…¯ïãÒ$ Û¿‰¿Ý;‰ÔS¹½¥±îò…œ³²U§ÍBR¤[·T¹¸xh1¤î²Ñ±±|õÜu'Õ³yV IDATþ¯¿†»*æˆÛËäÉ¿þíxZmûãþ&ê4„„Ó‰(GAA„óšˆ=nUEUÜ*¨ŠJˆA‹ªª¸•šé}S\]D 1š2rKªÅ¢p—’S ÑM£ëýòoÙó›®fó€V5÷ßÛ‰¦Ýÿɺ/ênÏh¶‘G;¶ LS•ojB×ø2³'à­¾m{ ­4ß’QèD-ZÌ»Ó òÙ«LêYt§µ{ƒ} FðáwéÜôTGK˜êå}k?—´#.ÅEn¤uëÓáq«Ñhu»\'½£‹Ùl¦¬´„ÐÐÐ:]e‚¡²²‚ÐÐP*ÊËÑÈ-Iåˆ ‚ ‚ œ9ÒŒûÙ¹àƒ”k¼2ÑDväÒ–¾úm–Ë{ ¸ò׳4;œn}›Ö;ÞHø óÛ¢ÊJ¥Ê5ümÜ3X'Ïâí+ÒHŒ9Rw{¡\–¦eÙÞl,j'ŒÀ‘ÇÎ#Û#ƒŸ6-ûV’©Æqu¬ÕmÇæ‚(mõ%· *«%@ùs-Æ3­Rö§ïÀU¥A-ŸþöÛ·ïÀŠËéÓ§/aa ßô¸²²’µk×жm;´âR#œÇˆrDAêAófÍD‚pñÔßžñ¸nû)J•+‡ŠËéªJWªå«|ôÑW †6\Þ}ú/¼Ü÷ßÜÕ¡„ÿx™ÍMoåå‹#;;Þ™ÈÓ{®áý·¯§™Üå™ì>P†5½‡j!w÷6¶–›‰kÓž¦-HëX­þòÃDè4蚥‘Ö2 «»=]£¹’Wÿô4“§DòÈ%föN}ŠOsÚóðÍ ±læí—wé%¤¥˜(O_Ä_üŠ‚ÎOqk§´Ú>Œéjã“ÿΔ7'10Ñʶéç¿Y \725`ùs™’ÜXŠŽ`³–¸´žàªg*fGŸ¾}Y»v .Àjµ6¸³ÙL»víéÜ¥ &£QnJ‚(GAAál ( Š¢ Vý«( ªª`·Ûýæ5ö×ûæ·|ÄWñÔWò¥UKBÏÛxç›'é à¦|ÿÖo»[•9HÅÒÇqïêã5|v÷U|F$×ÍXÏ;ýÃN²=-qÃß`ÚËÏðÄë×qY1„¶Âý_þ‹ÿëh{¦# yóá·É·†D.ºò¾á^:Úp÷ç_PòÔK¼|ýPÊS“Þ\ÿÆ·ü½_88•?7)hµZúõëOçÎ]NA]:L&£ìT#ˆrDAA„s]<—þù+VüÙ_f(ýÞÞINµ”¨+g’“dÝCù:3»íÚºÞù î|Ç7Ï”ÆýŸ-âþ:š44Î_¿Î_ýeQþ\¥ðhÁ9шˆ¹fЊAAAA¸åˆ ‚ ‚Ð(8œ›s|Çc8NŽä‹pA„:åˆ ‚ ‚Ð(ÈÏ?šÕ+q9=-N'[7oÄRiÁh2‰€A„Z‘˜#‚ ‚ B£ ÛE=ضe+—/%!)‘#‡“˜”L—nQZRÜ(ǬÕjq»Ý2ùg—Ë…V+ßœἿŸŠAA„Æ€F£¡s׋ˆKHàÀþý$¥4¡ëE=(++mœ/òZ- dggËäŸE222HLL¼vB„ÆXŽçÿ‹ªÒÁé¤ÃÁÅv;}ú¦¤ˆ`AáB|/ÐhèÔ¹+ññ 4iÖœòFªÐ ôêÕ“%K–Kjjªl¥zq¹\ìß¿ŸÙ³g3zô(Ÿx7‚ œg÷TA5a¨*O”•qCe%ÓÃÂx32—F#Â9‡Ù–›K”ªŠ AA< ’Ĥ$*+Êõ8F#]ºt!""’ 擟_ Ö g­VKbb£G¢CûöTV­!A8Oõ"‚ü¥´”**Žÿÿ¡rÏõõ¨(Î9Œ(FAáÂDX,Lõ¶êr¹h,Ÿ½4 ŠÛMÛÔ6tì˜&q/Ί¢àt8D1"QŽTã‹Å'íÆÊJQŽœ).c­VÆUV2"9Y"‚ Â)Ã`0°fÕJ ¹,è2Û·oÃ`04*9Øívìv»œ‚ '(G„ÓÂ-Œ³Xèçp NI‚ ‚ œ.v9+–/#¥ISZ¶j…®Ë EQ8rä™™™ ½ürž ‚PQŽTcFh(“ª¹Õ|&‚iÿ,)!‚ ‚pZiÕª+W,ãǹsꌷ¡Õj‰‹‹ãÒiÙ²•OA¨ÁqåÈ–Í›pØí8Î 3˜“ÃAé›o>{×^ÇU?ÆUÌôòŒÐ&Õ'iùÒ%ç[‚ ‚ œ5´Z-zƒáxŒ‘ò²2âbc>|D½Ë ‚ BujXŽX*+É=ïÛAáì ÕjIHˆ§W¯^téÒÅíæûï§]6&&–λÐ>- Åí ‚ 58®qØídfdÙŠ >œääd‰x-4œW_õIz衇Îÿ¶AA8+¸Ýn:ÄÒ¥K‰ŒŒ$µMÿË_ƒ*ët:9p`?ü¶ˆˆ¨HZ4o![Þ ‚ 5ÐWhlØ´‰áÇӻwï K š!CkÛ*¶z¹k¯…™3Án‡)Sà§Ÿ`ãF8zHH€=àºë`üx0ëß'‹¾úÊÓΖ-P\ ¡¡íÚÁÀpÍ5Э[ÃÆhKÜ`ÊÔ!Ë&M›ÖO¾'A>ý~ùvî„ÊJœ’’ _?>ÆŽ <ÞäåÁ×_ï¿ÂŽžùUÕs0hÜr tíZw=·Ýß|ã›>u*Üz«ÿ2S§zÎuM™"w3A¡ÑÓ¼ysâãã™?>iiiU¯ß#ôz=íÚuUêUËIMm‹Ýf ‚ ¾ÊEQ((( ))I¤ÒæÌiÓà©§ààAßüÇ=¿yóàµ×`útèÞ½~mté5ÓJK=¿ÌLÏ‚ýï‡Q£à½÷ M› w>Ú´ï—ž‚Ïoûvâ¤ysxþyøÓŸ×çrÁ‹/ÂoøÖ Ÿïù­Xá±d¹î:xÿ}2Æ|+Wzæ­:<—^ -ZÔL?x|зžV­Z­UUQýX€¸\.ôzß}Z¶hÁÏ?Šu´ ‚àC'ƒ¢(èt:‘JCP¸ùfÿŠoÒÓað`ض­~mx+Fjã—_ woXr% ækСCp÷Ýpûíu_^î±4ùÇ?‚«<Ö=½zÁîÝþó£¢<ÖÞ×[i©§?Õ_ôÅ“VZZóXÎcM)ן ‚pÁ ×ëO¸Ä¨ªGARí·qãF:wéÂÆ}òôƒ¸Ó‚ ~µùÙ¢¬Ìãqº‚{¬Ybʸë.ÿî=Šâ‘ãâÅõ¯7'®¸Â3þ0žyÆ7}éRxýõÿí5X¶Ì÷¸É“á’KdþA„ EUkü6lÜÈ£F±ÿ~®5Š 7ú#‚ þåÈÙdÛ6;Î颰yDä ß}o¿í›þŸÿxÜ•ÊÁƒð䓵ç?û,ôïï›þÜs°a¬_ïqýñæ’Kꛞ“|Ý,Ƈ;ïôM_µJæÅ{.ž|Ò@×›_~ñÿ÷1n½µö­vúôñ¿«L ˜%ãÇ{¶Ä­·z¬IAA¨²ñ¸ËètÚî3µ¥ ‚ ‚?D9r&éÝÛ7Íj=µmÜ~»oÚöí"{LšT·¬6oöÍ¿ûîÀõ^½oÚŽË}ø!´lY{¾lÛ+‚ 5PñÝ­&ÐOAü!Ê‘3I\Üéo£[7ß´ÚvK¹Ð¹è"ß´üüçæúæ÷è¸ÞN|ÓŽ \.*ÊãU_}å9FAÕbŽˆrDA8ô"‚3)í3 îˆß´²2‘½?Ìfß4¥š¹­?«ïÀ©þð”Õn®O+VÔž·r% (ó&‚ U¨¨Ìú~ZÐÇ»þFš ‚à¹."hdøS„ø[¬ žl¼‰?ñ·ÙìÙ‰Æ[¾11u×ë/ˆ«?EŒ7ë×Ãßÿ^{þ³Ï°aþݳAáÄåtqí 7}¼Íf¡ ‚ ~·šÆÆ¦Mu/øëÂí>½};×LY×®õMkÖìÄß))¾ù;w®×_¬uU§¢ÂlÕ{ÛÞêÛÞ·²RÎsAAÀc9bµZ‚þ‰[ ‚P¢il|ú©oZçÎ~fÞÏÔ:T{½YY'ß7gÁM«»­tíê›?}zàz¿øÂ7Í_]ÕyøaHO\÷Þ½žcAA¨sDQ¿1F¼ÓAÁ¢iL¼û.Lóãw;l˜oš¿ØS§ú¯·°n¸áäû÷ûïçÈ‹”êq_ùõWß¼+®8ñ÷å—ûæô‘'öGmL›ß|ã›î¯®cLŸ_~é›~Ûmþ· þâ øþ{9ßA„ žê»ÕlÛ²‰‚‚üŠÃ¹9lߺF#ÊA¡ND9r>qÓMðÛopø0¸\žøÛ·ÃçŸÃ AðÈ#¾eÌfÿŠ-|Ó^|Þz˳c‹Ë™™ðï{,Oü¹ Ô…¿À°=3fxvÏq»=ãøþ{:ôÔËêšk`ùrO̧ÓÓæ† ðþûž˜ÿø‡o™^½à²ËjÊ;$¤æ1‡GÑñÜsÙ[­žß† ðÀþ•!!žºü‘•÷Ýç›~lÛÞ>ðüíͽ÷Ömé#‚ ŠŠª(¨ŠBjÛöìÛ³›#y‡q9dgäÀþ}ôèÕÛ£©:NAü!YÏ'¦Oέ£:<ÉɾéýúÁÖ­¾ ÿÇ÷üN–öí= ƒêäå ”`˜;×ó ^}µfZ|¼G¡ó¯ÕL·Z=Ф_ ®î‡ö¿³Û ãÇûºét+žcÖ=S¦ÀàÁ5c””xÊþñ‡)AA¸8f9B·î=زi#»wîÀ`42ø²a(n7κbz ‚ b9Ò¸éÓ^zÉÞ„ §·í±cÏ/Y=÷ î›þüóЩSÃëíÒÅS‡?^y–-óMöY¸ä’ÿ0&Oö=néRO‚ ‚p¢V‹9¢ª*&Sݺ÷$<<‚Á— Ãírãp8$æˆ ‚QŽ4Vú÷÷XNx»…T_p_ýékÿá‡ý»îœkh4žø#µm¡óæAjjýënß~ùBC}óV¯öoyrÉ%þ!Þ “c¼ð‚§.AA¸QQQÔš?£ÉDÏ>}qº\ØvŸ|AAðG åˆV«Å}º·sN/ÑÑK…¥K!)©îc?ÿFN0qbýúóç{g’V­<ŠŸ`èÖ ~þÙ£`Ðhj?®eKX·ÎãÆR×q'.$¸ë.Oœ–ê[£¬Ì›Ä媙éq§Ñé|Ëèt÷ï@º.—'pkY™œû‚ ÂËåB{Ì¥ÔÏî4ªªât8pØí>én·ûDYAA¨†þÄzNKBBÙÙÙ4oÞ\$s.²x±'æÈŠ“¥¥%DB‰`¢7Üà?ª?""<Ê„¯¿†5k<ÁXÁSg—.k…›n‚víüo\;ÂæÍžºgÍ‚-[ ¨È;#4Ô£¼ißÞO㔜ÍzÏN1ýúÁ‚EÃêÕY)Š'îG“&žíz¯¸ÂãFŒ² &Æ3ŽÉ“=JŠ%K`ÏÏxbc¡CÏÜ~;´m[{]<ø¦×|õ­[{Ž?¾fzF†§Î)SäA=$&&žØ¢·AV‹ ‡"YAÄþý›ëYKäæÂcÕ¿Ž={óŽ…z¡QUU}ä‘GøÛ_ŸbFË—¯`ܸq¤¦¦¢×K¼Ö³73~íb *‚ ŠËåbÿþýÌž=›Ñ£G‘Ú¦ 6›ŠòÀÖ“ªªRTTÄÚµ«üÿìÝwTTÇÛÀñï6X@Ä*VlØP쉨‰h¢‰±wc‰%–DcIQ‰cb¬11Mc}!ùÙb‹%±D%V+ HgËûÇJïÅÊó9gÏqïÝ{ïÌ3w9γ3s_zg—,$²p«Ï–™³f³xñâ§sñY³Ò¿Ÿ1#ÿç˜?bbÌÿÖé`âDiÔgXJöÂ:uê`kkÇöíÿãîÝ{’UвZfóƒ>À!„¢XR*•”-[†N^¥FõêÄÄÄðÝê•y>ÖÁ¡m^z™*•«ƒF£‘  !žF#\¿—.™_£GKL (%9¢P(0 Tu«B­Z5e>æÓ–ñ±²ÀìÙ³$.B!„(Æ}#I‰‰Ä<ú%ö½ñ |¬B>æe ºty<×ð󃄉uÈ4o&!! îSçŶ¨ÈH ŒB!Düß(§)4ƒ£ÁPdþU((•JT¦¬ž?''Š…ZîuŠyj™_“ôÝ‹Œ,*"„B!Ä#III„Þ áÜÙ³DDDú|J¥;;;j¹»ãâZ FC³æ­$ТXˆ|!AÏ IŽ!„t`ß^éÔ…˜˜ètÿB<Ÿ ¡!!;v”—ÚyS©rT*U¡Î™””ĵ«WØ¿w&“‰ÊUܤÃ(òÍÒÏ}Ë–è›7Guâ$êÇQDD€…££#úÆ0V® €òâEÔÇŽ¡¼s L¥J¡¯SCìŸÖ‡úÔ)”—/£¼I‰ Ñ`²/‰¡’+Löö9–/Yü¤IùÿLR’ùú/š¯¯O¢Ýñã°z5T©Õõãâàßá¸߼M§ƒŠÍÇäôÉü¸}0¯ïVVæk4mj~ªdZ³²Y!㢮ɟss3?uôŸÌõ½llÌO³lÞÊ–ÍÛ5rZH6) ŽƒóçáÞ=ó{­J—Î9Æ’B!DN^éÔ%Ë !žOFƒsçx¹7UªV+’sj4ªU¯B¡àÈ¡ƒ8::a­ÓI°‹˜^¯Ïô¤Í„„öìÛéӧ©èäD¯·z:Ùõ´©/ ˆŽFuêTšŠÆ£¼z‹«Wзn"⪳gÒ§¸}ÍíÛ¨®_#±[·LçU^ ÂâÏ?!!>ýŽÄDwï ¾{õ±cè[·FïéYô{øíºuædOÚï^ÁÁæ×¹s0jTúã®^…!66ýöÈHó+ jÔ€7Þ ‹Â•qÕ*0RßÇĘÕ{ñ"x{C‹?÷åËðÍ7•¹§OÃٳе+Ô­[ðkDEÁš5æÄKZqq9Ǹ‘UW…BˆЉ‰N)’ößBˆç“Éd"òÁ\*UÆd2éËŵ‘‘‘èõò¸àÇáÖ­Ðtï¯\¹Ì‚E ‰ ÏÛ}ˆ‹ãÀÁ¿Ÿûz*Âî§OŒd Þ¿?Sb$]ç/(Õ™3™#[ÿ/sb$#£õÞ½¨Nœ(òzYìÚ•)1’‰»{ú÷×®ÁÏ?gNŒdtñ"üú+v ¡´‰‘Œví‚›7 wþ¨¨cÏÖ­©#c âÏ?3'Fr‹q1##GžQá÷ïI„â'Ój„xñFÔju‘-ÆšL£Ñ`4‹ü¼Â,ôV(ÎÎ.˜L&þ>ô7öï§ç[½¨R¥ m[·å·m¿Ñ¶u›¢¾&[[}}1YYa±};ÊÿþKWªL⫯€BÅ¢¼v5eŸêÜ9 õê™ßÄÅ™GŒ¤¹/5jÔ²%&{{¢>zÕÉ“©÷òž=ªU[Û"«òúõtï“:tÄP§6;£cè4`€yºI4‹»&&¦M© ‹%ÌO†©T ”J …?þ0O…¸rΜúõ ^ÈÒ¥¡sgpr‚ؼ>LÝÿÏ?æ*:•eÖ¬ü_ÃÇœáÎs“9b.CN×È8u'Ù•+éßwîlއÑhŽSÆKrD!„y%Ój„x1%öH«Wï·Ò½_ûó¯¨gÈÝ{÷¸}û6Ûwl'6>Ž1£ßÃÆ&uúRùò¸•€ P¼õMòñÁTº´ùßÞÞh3$G_ë––æýmÛ ý>59¢¼›ú#¬úÔ©t#FŒ®®$¾þzêwÁÞž¤öí!>U``J']}â$ú6­[ý 5ªƒZA¥ó+­' :;¾æ¤E2ggèÞ¾þ:uÛ©S…KŽôëg^ÌIX·.uppá+Þ¿¿y½GGèÐ!ý5®^-º »»CòT´¬b\ É´!„¢€dZÅËúuY¿ncÊû†ÍšÓ°Yólß¿÷ ÁµtJexµYŒ0Fž`ù°—¨V¦ ¥J;Ó°û,þILí|ç´?1ˆ…ÍœhõùFön‚Sé2Thð6_@äé• nY…R¥ËP£ó§ìK?ÅÁ±¼#›ÿo3•*WbøaØØè0ùç?üükþ8‚mþ,Y¿‹5?­áð‘ÃÆç¶Œi:²&;»Ìx”R’(©™“ÔG¿ª2$UôMšd¬ððH÷^uãzÑÖ§R¥tï-6oF‘<ê#+.¤¿j•yEÚWÚĤŽ")¨äÄH²G£’R¤ERP×#ʘ°ÈiêMnÜÜÒ¿_»nÝ’?ì’B! ïÀ¾=èt6™þ-„xþe\3`ç_²ó¯?Sö[[Ybme‰Éd¢Wï·¨áæL 7gzõ~+ËuG^ºßpéf¡7C½yË;ã ªF»F¨ ·Ù2âM>ø§&n;ı½Ë齊>¾ 8ä¶ßÜsçüÒ…\ziÛlãSãÌ~ûÞ™ø/ goåàŸ_Ñîú"F|~Џ4åjÔ¨#‡¤M«6(=e×_»xEÿ¾)ïÖ_¯Š”wkBÿ¾xÎÎÝ;3W°  šø«üßô7iäbN¹µÈâ#áÒœ³Åg?ðqϦT©P†2UÛ1nó âŽ3É݉®ÿKÓñÞCŸÊ5}$¶z|Ùwùaé× 0V¨uò¢L™ôÇE<(Òû*©m[°²N-òÍ›høÏÀ@ób¥ݽ[€‹ñz?Mú÷9­IRPi’\€ù 6Õ¾=X§Æ˜à`X±Â¼HkV1–äˆB!òJ¦ÕQ¼¬\ñ-+W|›ò¾dI{J–L}ìeÆ‘%/fïAƒV«E«ÕBðZFÛMÍ`rC†›þ|½KC/çѯY5*×éÄ”¥Sqÿï{VžŠEŸËþdví>ÅopkêÔjFï‰}©v»ñóñr]j6y“÷GÔ"üÀ!Bsèë^»~ƒÁÀ›oôÀ„‘‡±‰üó_8Q1 $$ÄÓýÍž$$ÆsízVÓò™ 1F°gòëŒ>P•‰ëròø–t cá[ÃØjH9ç…ëÐŽù‹¡Áü3»<[ß›Èï÷žò蕤Ĝ;ãÉ2>é%·Å[óÉdoOBï·1•/Ÿn»CTüô“y1Ò´ Æø\ßÁáùû¾)ŠpXÉ’0p yºNº/˵¬c\ Éš#B!D¥F#Sj„x±ýòÓ:ú ÀšoW›ûö%Ò}&yTIq`zx”9}¦sñ••ìT-zŠ`EUFÖ¶MY×CSÞ“¦¥#9I9ï74ÐP±Q’ßVÛUÀΑn6ŽQc[ÁEl819äNœ¾OxHæ.¼åj–'%¥ ²¡´e<á±OwäˆÑ¡dúÎa6ÓU”Ö¦0•ÊeF!Ös1V¯NB¿¾è›6M¿ãøñÔÛÛ§ßwýºüáJiœ<Œþ¨U †…-²±$G„B‘W2­FˆµoaÂh4fz9Ø—ÀÁ¾DÊBži§Ñ|»r55kÖ¤fÍš|»ru–Ç¿ùïÛ!Œø³ÿ8OÛÔ”‡…SœM—Ùs>u$]Òíùç~ jW+e.û‹²cb0Ðh,xý€+×/xé U]Ëróöuî?¸‹ÞdÀRk‰Á`Ì2M“¿ “ªKîvÿ^º×±ÉµHÏ PfL™0a2Ÿ,ó®'2ÃÁX9ý¨Õ©SYv¶ÕG¦oå ‹‘Z¤µ¡O¿–‰òÚµüL¡@ß<ÃâÆiÏ™¡ÜìÝûxÖüx.zôÊìã”KŒiÓ¦`ÇJrD!„iÉÓj„xQ³#FLÆÌ/ÎÎÓ£DGºZ3ìÏêõBüÝ;áÇ;Ó/Ðéíl"!!„„ &ÔŽåȯïMåÇ.s-àOæœÃùªýâaëþ¢f0¨ââFš™^•ÝHHóÔ–ÂÐ:{R…ól9FZYiƒ5ĄǦ¯¸LHÌãÏŽè=<Ò-,ªºpÍÎ(<£EX¿ý†òÆÔƒ4ô‰kÊ0Eó×ó£v“’P;‡Åÿm͹ bñë¯(/_6OíÑëQœOÿ™´‹‰6i’~=Ž[·`õjøï?HL4\‰Š‚ӧᇠ5’å™—ñiE;v@d¤¹Îwï¦MæíQQæX¥Ä˜3g²q1$kŽ!„t`ß^éÔ…˜˜ètÿB<ߌFŽd4lðpóþGûÒ.Îj43í…ßE!‚ áø}xêö:sN°{ˆ3Ý–näþû˜åÓŒ´¸´Ì+&P× |Îû‹¶¬‰‰ ܽw•JR©Àd2a0ˆ‹‹ãat$•\ÝŠä:ª ™Òs¾cð 3éݸ¦û9ðû_{ÌdPå\N`áBë%XüÝÎwEm.³éã/9k‚º»Au:’Ú·GóÇ©õ9yÕɓْäí ¶é§‘ªWGfý 嵫X~óMÞ;¥§Ï ¼~‹œ¦ÇÔª•úïÒ¥¡m[س'u[h(üüsÖÇž?u꼘_Êš5áÈ‘Ô÷—.™_i½ù&œ8W¯š_y‰±$G„B‘W2­Fˆ“ÉdNädÙ7Ë3%TŠ—!{ ’ÃJ4bØŠ½ [‘õneNû-ª1þÈMƧMÿ1–äˆB!òBžV#Ä‹G©Tý•JU¤ç5 (•2£ýI±+aÇå«—Q«U„G„`2Izô„“’%¸~ã¶v¶é,h‚ÆÂ™NþL§³*MæsbÕ¿€Ô©*ªÒm™¾õ,ÓÓ~fØÐ'/CŒnUP<…êÚ5áæé)˜J:`¨\}°µÍú o÷B}äªK—PDER‰©¤Fgô  ]¹2Ûë'ôê‰úÄIó±"Ìë‡Xhy`k ¯¼CVßI//pw‡£Gáʈˆ0OQ©ÀÊʼpkÅŠ/nbÌO<6?…&,Ì?µÚÜ^ÉGîßþý×ü™ðpóg´Z(Sj×Î>ÆÅˆÂd2™ÆŒÃÌÉ_Q!„"dZ/–¤ÄD¶ÿïO4lDù ŠôÜ·oßâôÉS´lÕ »%$ØÙ×ÙèõêÖÃÅÙFƒÉœ!!11‘kׯ2oîçÌž9“jÕªKâê5sÖl/^,O„ŒB! H¦ÕñbQ*•ÔrwçŸ#‡ñlÖŒ²eË¢P®Ól2¹{÷.Gÿù‡ºõꡱÐH ŸWZÇOçøñcèÓLéP«ÕX[[³kçnœ+ºðáS)Q¢„$H„(æ$9"„BL«âÅ¢R«qq­„ÉhäÔ‰“DEEzqU¥R‰½½=uëÕ£\ùòXYYK ŸW\\\³ùûÃHF³}ûvTJ%S§NÁÎÎN$Bc’B!„âFCe·ª8:UD¯OÂT ­*J4IŒ<ƒöïß——VVVŒ÷¶¶¶’ ¢˜JIŽÌœ5[¢!„B!„xá%/ÌZ¥JöíÛ‡——ÿüû/XXXÍSl„Ï…ÉTLž;&„B!„˜§ÕØØØ˜˜ˆF£áôéÓ´mÛ–É“'3räHlmm%A"D1#Ój„B!„Å’Á`@­VS¿~}¶oßNûöí±´´dРAØØØH‚DˆbD’#B!„BˆbI¯×£R©Ðh4xzzâïïOçα´´äwÞA§ÓI‚DˆbB’#B!„BˆbÉ`0¤ŒQ(´lÙ’7òæ›obii‰¯¯/ÖÖÖ’ ¢5G„B!„ÅJòš#÷ïßÇÒÒ­V‹Zú»±¿¿?½zõ`Ô¨*xy•E«UJ‚DˆœŒB!„BKƒ!ejJ¥JI€øøøðí·ß3tè`êÕ{æÍai)O±âE&ñB!„BKÉÓj’_iùúú²xñ×¼ûî×ìÝ{š„„$dн/.™V#„B!„(V’§Õܸq­V›ò²°° ~ýú\¹r0Jâââ(YÒ† >¢qã¨Õ*  / ™V#„B!„(–’GŒÜºu‹ƒÒ¯_?ÌŠ+xùe# tF©T Õj°´Ôb0%9"Ä JFŽ!„B!Š•ä‘#AAADDDðæ›oÉåË—±¶¶ÆÙÙ™>}Ê1zôX[kQ(h4*´Z J¥¬L Ä‹H¾ÙB!„BˆbéæÍ›tíÚÜÝÝùꫯ°°°`̘1ìÛ˜°µµÂÎÎ++mÑ'FCðóxfKï Ïj¿þ.˽ºÒpáM’žÕ FŸ g¹ž :WàSÄûºË8ýÝ<ÛÆÆÚ×ûòÊ·Ù´åóêq߃ÏÐ=.É!„B!D±Ô³gO¼¼¼3f S§N嫯¾"**бcÇrùr4'OþGb⣮®é!›Úw¦T<,P'ð6_{v¥Éâ[yï*-©Ñé%ºÔ¶~q;n†ûl™¾Ûá]iló×CUŠ.“=¹ê·£_ öyÖîÁ‚|òZUù“(„B!„(n íÛ·çÝwߥAƒ¼üòË4lØ%K–`kk‹‡G} ..á)vLíh;},³:–äE]é$ñò_,:îÄà®eÓ‚˜&ŸÌJ6 _å Õ¾ØûfíŠbp¦TUþ, !„B!Š¥RÉÌ™3;v,õë×§dÉ’X[[óÁ0þ|^yåΞ=ƒ£c©zõæ)1gý݆àhÓF­¿Cb¦DzÝw“’8?u0ö:tr0Ö¼×Ä’>Ã)§óA—ö§˜â \ó%mª¼†N烮DOöÚFPBöåóœ³?ßÁ”ÖùP²ÖL&òäoôkì‹NçC¥kØfL9Ìy‰%FãlãƒN×Ú]V³-8u¢ˆ1ü~o¢”Îó{Œ^w‹ø´× eÓ”©SÖΧ&søâàC YQÏuÿ=\®ÔŠVå”yŽkŽe|t|£ÿ‰ûSF×ÏÏñI¾c‘HàÒù¼\ǼOg×›–ƒý9CÚÃÒ‰.mÔø!È<Þ‹y©KÞ¶y.õÌx°L §nblû8—{‡Ê¿)›Ïç“l¾G1’B!„Bˆ|³°°`ܸq¸»»cooR©D©TÒ¼ys~ùåj×®Mÿþδk×Î2‡3é üfÚñŸs=b 'ç–bó¨¯Ùz7cÚšŽ–3¯¶÷9«xãOLÈxZX›Ï°èGN5ÊŽã‹ø¹¯‘ŸFfuÐ_ÛÁ ±G©2Ã3A?rþð‡LëT Eöå X¼Ž íF±ç¨~ /2½ûlzŒ ¤Ñܹûkí¯®gðgAÄÂÙ8è&veæöåœ9<‰îÑÛèùÚZÎÄ™÷o4“ÙA|}à[¶uC½b5;“;ÒÆ‡ì?…{˜²eçÏ}ÅŠ®‘Ì{cën3ÏË™í·°mXrê<Æ5·2>:þÂ7»Ñ¾?Ÿ‡[98Ö M~c‰D¥+ýÍátàwœø£õŽ­ û´@²Ÿ5£¥j› $œ8ÁyY‚%uÉÛ=VÀ6/P=ó_¦‹ßìÁþ£/¹vgg¾tæ÷Á3ñ;—˜Ï˜dó=Òé¹²x$ºrsØ[ˆ)M’B!„B+*• ¬¬¬Ò-²ªÕjñööfÆŒ´jUŽÊ•Ë£Ñä<Ù£Œï@ƶ²G£° j·×i§âÏ‹ñù*]‡a,Ùú5«ÑuJ?Ú«²>‡þÁÂÕxÉ»:nޏº×å>MqµÈá܇±h¸uÝkÓwê«T¾ÿv“F2ÚÛZMÛ2e´+a{Ïr3 ô!‡ør»šžKG0°EEÜêy1mUjýÁÒ“ñèC±x·–~ß ¦WÃòTòhÃ'_¾L¹G“H ·ðÙF-£WáθV®‚ϤQLt `åîdJ$Fj TÕhò×ÜʘRﮃ˜â]­R…N§F‘ÏX€–úÃ|éë]•ª.e©Ñ²sýóçß\Ì6ñ¡ÀÚ±–a7ÍÃl¬¼Ö%¿÷Øã¯gþËdÓyã[Ù¡BMEŸ>LoÊê•W%hò“Œi KG7šy:cWˆ¹?jùÓ(„B!„(n E–Û´Z-Z­[[ š\»Såj•B›ÒG³¢´UWcò³â„ç&Žè’‹£±ÅÉ&‰kYœÃ²†7ëø3Â} ßûxâÝÁ‹·º{àf£ÈþܱN~gW ;‹Ò4ªf…ù%*èPÄFk€„K\W81¦Ž5)Å©àŽW™hN\Š!Ît‰Jg&Ö¶J¹‚®VCji÷-€K±¡iÒ•¹Jâvã!I8¤Æ À¤'&,,Õ~µÏ>®¹•ÑÐØ||Åå°,D,й·oïMþ ÿ³Rÿ´ö"Òdsk(5hŒ Ä%™EŽ-Ÿ×ºäï{õ,@™šTH)*[jÖ·%ìT(ÑF‡üÅÄ3ëäˆc÷ ìî^¸¿ 2rD!„B! šdÉÔ£2aÊçrœJUÚN´Ev簮̤]?qlÓÛtªÅ®§Q¯Ñ×ìŽ0åíÜ @¡@­L¿ “‰ [²®« Pª°H[g¥Mò{““ª+.ÿNLŒº×™i®é#*KÊèÄF$dZ“$ç¸æPÆäSk”™>•ŸXïfxu„tz¯o&*ÚŸ;ÿ{‰’Jrl]cÜC4¶Øky½ƒrÝ“ß{ìIÔ3e2aH2¦Ùk~_˜˜<’B!„BˆÇŸFA¥“©Ï1QÛPË»ý¦°ëÈdZßÛÏšÓñERB­s \M!ì HO‘të<‡ïÙP§ºKçj8›ns48õ!ª 7/q%Î\'KWwªrGbÌË5öÔ­nÁÝ€°lçÌo‹ªƒ›|ž³‰Uõncª—Ö¢R¸ö†œŽ2vé‰NÕq±|vêRôõÌ/×ö]áAòM‘Æ?ÿDáPÏe~cRDß#IŽ!„B!ÄS Öáê¤"xÏC‡>Ÿ§ˆ;³•i ÷qàünÝ åßm‡ LrÀ½¼¦hŠèäÅØŽz~¹ŒïßäêÙ#|:äGªubDKÔ›3ºu$+¦ïâb¬ S\ëfüÆåGÇ«[0­·Ž#?cƆ ݸCÐñ£¬úh9+.$eqEkê¾Vã™S\‰/š2M¹ÊTR³m_I˜ˆ¹¸›©s¯æá#Ÿ¬ã–cűñ¬ÿ1£Ûí}°uèõÊ‘‹è}ó(§3×7í+yºPŽ×&oeËo IŽ!„B!ijŸÝã§0b¯S¶,ãü¹¯XÑ5’yoÌc]¨Ž7wnfÏà’X¶ýˆ[1þ„­o‰ï†åÌ«­Á}Î*Äø2žº¬N®'`ñ:.´Åž£~ø5¼Èôî³é16Fsçrì¯q´¿ºžÁŸ `gã ˜tØ•™Û—sæð$ºGo£çkk9—{Uô×v0hìQªÌðãLМ?ü!Ó:•ÅB‘K=of×q×sþ‹µ\ö™È±À¥l®áç~3ð;—[ZÂšŽ™b4ÙþYÄÍ2/uÖøÍ.´ã?çzÄNÎ-ÅæQ_³õ® ÐseñHtåæ°7‹µ`lZMàFض¶‘€ïZà ªHû&v¨r‹·!oeËW IŽ!„B!ijÆpûŸmÔ2zõÞiáŒkå*øLÅD§Vî~@aï·ë8ŒEÃ=¨ë^›¾S_¥òýÿ°›4’ÑÞnÔjÚ–)£] Û{–›I 9Ä—ÛÕô\:‚-*âVÏ‹i«úP;è–žŒÏ=9òàáê ¼ä]7G\ÝëòFŸ¦¸Z¼žÚVƒX8´U]\h?q,ÓëÜdõÊ+EÖÑÏkËødl+{4 ªv{vê þ¼(±tt£™§3vª¬zÒj´–XZZ ÞÅðQÇpŸ;i­0ärí¼–-?m, OÖB!„Bˆ"-€K±¡iÒ•¹ö¹ÝxHºBuãœ;büήv¥iTÍ *JTСˆ"Ö !—¸®pbLëGûASÁ¯2Ñœ¸ƒÁ#ç«YÖðf`F¸ä{O¼;xñVwÜly¨§ÚLgTQ©u%쓪W;ÐÄÓŽ°3¡DŠ$þ¹Ö¹±9Žåj•J-ŸÒŠÒVI\1J»O`w÷œ¯czÈì+¹à3™#Ã*¢br¹vœ)oeËO£‘ïœ$G„B!„âYc2bRÕ`Å¥ô.¯Èªû^¨Ó+UiΩ ÔÊô›0™È°%K …ù•¾ü`L>ܺ2“výD—½‡ðßq‚?>žÆ§s^á·#£h–k=ó)·²ä÷d¹ìQdšKaÂD/fgë˜Oøš®l_Üœòªü\;÷²å¿E¡¾S!„B!„(Z–®îTåÿŽÌÇ*%˜Š¸Ã«u®«)„]© Œ$Ý:Ïá{6Ô©®C©´ÄA1á )eÕ‡ß$8&MÉÕ6ÔòîÀD¿)ì:2™Ö÷ö³æt|ëiàÚþkô2GþM$Êy_ØÑc\2<äÒÀlM³§îüÕü=¢\.ñv(dÙÄã 0™d’’B!„B¤µsgZ´xO!D1!Ój„B!„BQ¬IrD!„B!„Åš$G„B!„BQ¬IrD!„B!„Åš$G„B!„BQ¬IrD!„B!ý]–{u¥á›$ååó‰!øy¼N³¥wÐטI ÄS"É!„B!„x,½-Kjtz‰.µ­‹¦ã¥¿Íמ]i²øVÞ’-ÅQV1’¸‰Tê°†½aÆÔkF^bÉ€Ñ8Ûø Óu£v—Õl ~4±%ö"ãªt¥“š‹EŸ gù·~(Lñ®ù’6U^C§óAW¢' {m#(áÑgãBÙ4åCê”õA§óÁ©É¾8øCá4Ü?Í']úc¯óÁ¶ÒÆoºCb®e Ï"FŸð‘OÖq˱ÎâØxÖÿ˜ÑmŽö>ئ´EÞï‡ü¶CŽ±Ê­L¹µ“äˆB!„B<~z.|³íûó y¸•ƒcФïñ³nÀ,æ{²ìàjÎûwÇöÇ5ìŒ6¥;GÀ¢9Õl(;Ž/âç¾F~ù5[ïZÑqÃræÕÖà>gbü‰ O ]ÖåX¼Ž íF±ç¨~ /2½ûlzŒ ¤Ñܹûkí¯®gðgAÄÂÙ8è&veæöåœ9<‰îÑÛèùÚZÎÄå¡Ö×v0hìQªÌðãLМ?ü!Ó:•ÅB²{üFìubÊ–eœ?÷+ºF2ïy¬»iÌ6Žç¿XËeŸ‰ \Êæá~î7¿s¹¥%¬³ˆÑ4fûg7˼ÔYOà7»ÐŽÿœë[89·›G}ÍÖ»&@Ï•Å#Ñ•›ÃÞèìï‡|µCžb•S™„$G„B!„â`×uS¼K£UªÐéÔ(Òv•C³d¿Ž!KàëQ×z-ùhQ*’¾ck×a‹F6¤~ÍjtÒöª þ¼˜¿_þí:cÑpêº×¦ïÔW©|ÿ?ì&d´·µš¶eÊhWÂöžåfèCñåv5=—Ž``‹Š¸ÕóbÚª>Ôúƒ¥'s¿®þÁÂÕxÉ»:nޏº×å>MqµÃí#|¶QËèÕCx§…3®•«à3iX¹ûÙ¥G´­±phªº¸Ð~âX¦×¹Éê•WÌI„¢Hcå±Îe|2¶•=…U»½N;ur[(±E³À< IDATtt£™§3vª¢i‡¼Æ*û2‰Â5G„B!„¢ˆºW”Ã2›½ ÁAÜPVdJ5mÊ6+·ºÔ°Ü™îÎMÑ%gU4¶8Ù$q-Æ”¯r87vÄ:ù])ì,JÓ¨šÕ£dŠt(b£ˆ5@BÈ%®+œSÇ:%™£©àŽW™hN\ŠÁà‘óÕ,kx3°Ž?#Üò½'Þ¼x«»n6 â¯p)6”#Mº27Ãqn7’„ÚLgTQ©u%ì“ÊW;ÐÄÓŽ°3¡DФ¥r­scsËÕ*•Z>¥¥­’¸c”8vŸÀîîE×¹ÇJ•K™„$G„B!„â Ò(Ó)¥*í(0aÂTðs(…µ2ý&L&2lÉ’Ba~¥ccòáÖ•™´ë'ºì=„ÿŽüññ4>ó ¿E3““ª+.- wyEáœ[Yò{²\ö(2͵È_[ä«r‹UbHÎe*ÒØ?2­F!„B!žmÅj8BØŸ²R)Ä]9ËÅø¼ö^¨”`2moWë\WS»RIºužÃ÷l¨S]‡Ri‰ƒbÂR¦vèÃo“fRŒÚ†ZÞ˜è7…]G&ÓúÞ~ÖœŽÇÒÕª\cãß‘ÙN¡ÉÌÀµý×xr±Žþ…C=GlÔ¹•%«eÞ–kŸÂýQ°X¥íÝç¡Döá“!„B!Ä㧮،w[ǰräwl<}‡gññ{;1)Èà t¸:©Þs†ÀЄEÄ¡/Šr9y1¶£ž_F.ãûÃ7¹zöŸù‘€jÑÀ´eiÛRǹ•cÂÂúë9c2—9îÌV¦-ÜÇów¸u+”·&0É÷òTŽ-˜Ö[ÇŽ‘Ÿ1cÂnÜ!èøQV}´œ’²-SÂo™°*€ËÁÁìZ°ˆÏ:2`P¬s)K–1Êb¹Õ9WFB7. ]—Ÿ8W4÷GAc•"·ØIŽ!„B!ÄÓÏŽ”¡×÷1Éñ_†6H­WÖùö;´Ñ©ÑªóÒÕÑzZ/š_\†WµÞ¸Ô]Ê?1EÑ+w û·Ÿâ×ô Ó¼‡R§Ù<Ö[ufíÖ^Ô³°ÂkÖDFYo¥uùnT¨?ŸMºó²¹ÌJK5·¶­¡‡ç@ªV‚ϼ0^_615Ô ´Å{Ñ|ÖÔá?vµâñÊW|¤ÃÕ>»î¨÷÷ÞÂeË\ÔÎëKèõÝ,&׳ȵ,YÇ(‹mñ¹Õ9÷äH|èeŽüL”¡¨zç‰UZ¹ÅFäDa*ê1YB!„BñœÛ¹³-Z¼÷د“ø M¼1ôä—¼[Y%â)‘Y…B!„â‰0u|[î»ñR=Dz1¸Ñ` *JbDˆ§I’#B!„Bñ„£¯òÝÈoy;°¢j‡n¬]ò*•5!ž&IŽ!„B!Ä¡À¾ÍPö^*¡â# ² !„B!„¢X“äˆB!„B!Š5IŽ!„B!Äã–‚ŸÇë4[z}VûõwYîÕ•† o’ôh“1â,¿Ú;ºÒŸ°;ú1—1‹2ä¦@eÌ-¢ÐíòDÎõ‚‘äˆB!„B„G˜Ñ}m}Ðé|(á4ˆ6oÿ̾0Szf–Ôèô]j[?ꤸ±v ®4gCÀZn^yŸ6–·ùÚ³+MßzF:¶O©Œú,®¡ÖbS„uËtoˆÇAdB!„BˆÂŠ¿Êœ×>f‘æl‡WE ¯ÿǾ×¹kÛ\ŽWÚÑvúXÚ¦I<Ü z€ªjC¼*Ùah˜Eô z7Xƒç [­¨»ETFñˆ‰ÄDcî ñ8HâI!„B! Izš?‚lð]8˜Áí«S»Veš½ÒžÉ ãë¬Jùœ1*ˆ%}†SNçƒÎi £Öß!ÒOw0=dSûn´]NüÞÙTÐùPªÇßlðÆä€$ÎOŒ½Î]Å…ŒÉ­¿m$.&±à£)âBÙ4åCê”5†qj2‡/>ÄPe4Ü?Í']úc¯óÁ¶ÒÆoz‹Ø‹Œ«Ò•NþiŒ>AÏòo3üP8Û3]ã>òÉúºÆÈK,0gtºnÔmÁ28¦÷4žõ?ft‚£½¶iÛ$çç¿/GR¢Öwœ‰OîÈc¼ãØîÛbÊ)~i®ßèÃÿcbÇþ”Ñu¦d™!™ë•y*Œ).”MS§S¿œù¼%ÝÆ1fKz \:Ÿ—ëø¢Óù ³ëMËÁþœŽ6婹£÷Í3ß›^ÉS rŒ'y‹·çœ=øù¦´Î‡’µf²ðh4‘'£_cs™+uXÃÞ0£$G„B!„ây£*QšòÚhNìºL˜>ûuÀ¢9Õl(;Ž/âç¾F~ù5[ïfè¸*lysçfö .‰eÛ¸ãOØú–ønXμÚÜç¬âAŒ?1!ãi¡{Œ•2>d÷ø)ŒØëÄ”-Ë8î+VtdÞóXª+dõœÿb-—}&r,p)›‡kø¹ß üÎå––°¦c¦kLc¶×µ gã ˜tØ•™Û—sæð$ºGo£çkk9—ZŽÀov¡ÿ9×#¶prn)6Jn=WDWn{3­¥¢ÆµKjÝÚϯ“Ël"òðvvê1 ¥ ŠœâwÓ˜rý ßìFûþ|BþÆÝÐåÌÍXëÌí²sìûôýz®ú’3+Ù»¼3õmL˜0‘¨t¥ÿ¢9œüŽô£Þ±tŸH^–ƒ±i5a[ ÛBXØF¾kƒª"í›Ø¡2äOCÞâ°xÚbÏQ?ü^dz÷ÙôH£¹s9ö×8Ú_]ÏàÏ‚ˆ•äˆB!„B<_¥<™ÿyKâæOÆ¥touü„ÑŸîà¤M}ØuÆ¢‘ ©_³]§ô£½*ˆ?/Æ?“u2Ü>ÂgµŒ^=„wZ8ãZ¹ >“F1Ñ)€•»PØßöµ­±phªº¸Ð~âX¦×¹Éê•WЬS¬9Ä—ÛÕô\:‚-*âVÏ‹i«úP;è–žLyߌmeFaAÕn¯ÓNÜ&J,ÝhæéŒ*óù5.ÍèëΦ_ƒ‰0EsøûS˜^z…öŠ<ÇÏ®ë ¦x—F«T¡Ó©QäÖ.¡ùì×$ÞX5‰)]ªâæâH}ïv j_ Zêó¥¯wUªº”¥FËÌõkLÌŸs1./5ZK ,--Pïbø¨c¸ÏδÆVr‰g^ãm×q‹†{P×½6}§¾Jåûÿa7i$£½Ý¨Õ´-SF»¶÷,7Ÿðâ1²æˆB!„BšÕMåÜ[w8¶ï4Gþ9Ïε_ÑÑÏŸöÎãƒÚæî—sGtɽ_-N6I\‹1a9âØß¿/¯nHŸbØîñ:3’ßÔAàθäÒŒ¿À¥ØPŽ4éÊÜ ûÜn<$‰Â [QQ©u%ì“®W;ÐÄÓŽ°3¡DŠ$ !—¸®pbL딄ƒ¦‚;^e¢9q)Ccs›”«U mJrÀŠÒVI\1J»O`w÷ìzÓeðé[‰íåÂGnÔ;Ïw{´[S› ˆÍ5~*@MÅå°ÌG½â¯rÙäÌð†6Y$RŒÜÛ·÷&ÿ†ÿÙ©Ó©¬½ˆ4š¼]Ãô0Ù=VrÁg2G†UD ÄäÏ8SÞâíÜØ‘äÁ0j»RØY”¦Q5«GǨ(QA‡"6ŠØ|”W’#B!„Bñ QÙ”£©Ošút`ì”Î|Ôd,_Ì9ËèŸ*˜ûÞª´ÝY ÌS!ŠŽ% gÎÁ±zóYcÎ3±Ûê­œB_WÕ£2–¥|^z‚&#&U V\Z@ïòYgHxe~j¦3Ÿ;·ø%†˜Ï¢Qæ:Z$¯Œ÷3¼Ç:î¿ûÿþ^·RZâþžOÍîñy¿Ë áló _Ó•í‹›S^•Ÿxæïtß P VføœÉôÄ¿»2­F!„B!Kª—†¸q$I_OJ ¦;Ž l\*áÑ * T¥A}GJh,qªíf~ß *õªÙa‘—⻺S•klü;2ShòRF×ö_ãAÊÒý7 ‡zŽØ¨-qÐALxBÊuõá7 Ž1æpÌÛ´Î5p5…°+ u>IÒ­ó¾gCêº"é «<é_/‚Í¿œc×wgP·ïHÓ7~–®µpSã":SÂ#1ø>‘Dƒ u.ñT:Þ’B!„BˆçšÒÞöî±ìð[À+ÍGÒ¸ùÞý9†öŸ~ƯƒËÑÒ :ZOëEó‹ËðªÖ—ºKù'æqVÊïEóY7R‡ÿØ xÔˆÇ+_ñ}W{e!˨Æý½·pÙ2—5‡óú’z}7‹Éõ,+¼fMd”õVZ—ïF…úó9Ф;/Û(r¸FÛâèþí§ø5½Â4ï¡Ôi6õVY»µõ¬ò#ñ¡—9òo0Q†ì»Ô:t¤aL(·mšÐ¿‰uÑÇ/6s»tXìÇwoëYÓo uk楡¿s&VÚ±5K¾ôäÒèATpìMƒ~'h0±9ª¼Õ7ìè1.²uà@Ê•êF©G¯Ö+î¢WåOUaãýt)L¦§0™G!„B!ža;wv E‹÷$B2rD!„B!„Åš$G„B!„BQ¬IrD!„B!„Åš$G„B!„BQ¬IrD!„B!„Åš$G„B!„âqK ÁÏãuš-½ƒ>«ýú»,÷êJÃ…7Iz´Éq–_íƒÎ]éOØýÊE¹ UÏ'uŽç¡ÍŸD{<ë÷Ë3D’#B!„BQnaF÷T´õA§ó¡„Ó Ú¼ý3ûÂLyè™YR£ÓKt©mý¨“fàÆÚ,¸Òœ k¹yå}ÚXÞækÏ®4Y|ëÉu<3•«°ç'P‡¬®¡ ±{Úãi·Õ3D-„B!„¢â¯2çµY¤y…›ÇáUQÃÃëÿ±oÇuîÆÁ6·N¯m§¥mÊ÷‚ ªÚ¯JvØ~}‚Þ ÖàùÇÆVËo÷ÏD¢Þ6C¹ÄÓ#íñ8ÉÈ!„B!„($}èiþ²Áwá`·¯NíZ•iöJ{&/Œ¯³*åsƨ –ôN9:§1ŒZ‡DH?ÁôMí»ÑvE8ñ{gSAçC©³Áw“’8?u0ö:tr0&·þ´‘¸˜Ä|M‰iôáÿ1±cÊèºà9÷_e˜&a¸šÏº ¤”Îó{ŒZéO×r=t .—zƲ=u0Ü?Í']úc¯óÁ¶ÒÆoz«Ø‹Œ«Ò•NþiŒ>AÏòo3üPx×ø„|²¾®1òKŒÆÙÆ®µ»¬f[°>]<Ïú3º ÁÑÞÛ´m–GÙ¶9y»~Ní½ožù¼^ÉSy ^¿ìÚ*‘À¥óy¹Ž¯ùZv½i9ØŸÓѦ<Å¢PåÍc}<çìÁÏw0¥u>”¬5“…G£‰<ùý›Ë\©Ãö†%9"„B!„EMU¢4åµÑœØu™°lGxè Xô#§š eÇñEüÜ×ÈO#¿fëÝ K…-oîÜÌžÁ%±lû·bü [ßß Ë™W[ƒûœU<ˆñ'&d<-tEžæáÂ7»Ñ¾?Ÿ‡[98Ö MúŒëÌb^°'Ë®æ¼wl\ÃÎtãìêiEÇ<×AÏù/ÖrÙg"Ç—²y¸†ŸûÍÀï\ni ë,®1ÙþY\×2œƒ>`ÒaWfn_ΙÓ轞¯­åL\j9¿Ù…vüç\ØÂɹ¥Ø<*¹Íô\Y<]¹9ì.@›òvýœÚæÕn„m!,l aa ø®ªŠ´ob‡ÊP˜úe×V&•®ô_4‡Óßqâ~Ô;¶‚îÓÉË’8…*oë°xÚbÏQ?ü^dz÷ÙôH£¹s9ö×8Ú_]ÏàÏ‚ˆ•äˆB!„B-E)OæÞ’¸ù“q)Ý›F?aô§;øûf"iÓv†±hdCê׬F×)ýh¯ âÏ‹ñÏT]ìºbŠwi´J:EÚ®~Èa–ì×1dé|=ÊáZ¯%-ê@EÒ'xŠ¢žÚVƒX8´U]\h?q,ÓëÜdõÊ+™:µN…âËíjz.ÁÀq«çÅ´U}¨ôKO¦–µŒï@ƶ²G£° j·×i§N®‹KG7šy:c§Ê!žÙÄ"¯×Ï©=PªÑZZ`ii"xÃGÃ}ît¦5¶ÂPèúeÙ*ÔæK_ïªTu)K–˜ëט˜?ÿæb\‚^ˆòæ9^‡±h¸uÝkÓwê«T¾ÿv“F2ÚÛZMÛ2e´+a{Ïr3I’#B!„BQÄ,¨>h*çî¬æ¯ŸûÑ·© W×~EG÷÷ùìdü£Ôç&Žè’{·[œl’1a9âØßß7uÊBùl¼Á ×S·yýÎlG·¨©Ø ÿßÞ‡eUçÿÞÜ7ë­D`¢,¢â2¢’˜šh™Û$YÚ-µÜ—TÜÆhBMËÊÔ,×Ô®šÑQËŸ™5niåVšM(¢0® f‰+›À}Ÿß¸‹r³˜N¼×å÷9œó~Þ‡ãu}Þ|ιÝn³÷RrÇhQÓõê6÷àúÔv3ÝpŽ’ÓLÕUñº2cµxÓ¸‰'iq©¤ÛK§R—R9fò§m=« çÊ!„?”Î¾Ä l—Çâ[LJ«£ur§‚û•±8á9ŠMkºÓÐýöõ¼]-§ëq…q1‰]p b ÀµTÆW;¿}ó/^húBþ£6Ö*wÚÉù3¿rÞæxí‹“o–ƒã lä‡Ç•ê{úàéRGjº_>ÆÌ•­˜2/i»ùJ‰ˆˆˆˆˆH©0—óåш¶<Ñ–¨è§×8Šw§ìeè'•óçžæë›&L”fsĆßb[T^þY3ö3ºÓ*BDÓ3È|9ÇŠTºÃLÐììtãê„b¸«ã4éæ °Åfeß‚¯‰Ï002RX>~9q†éö1 ؆8Qíòøçà¹,Ùq‚#{w2©ßÇÄ×lÏ 07ªa'uå;´êð {²ŠQËÇ7HßýºD£Íì‘ô 4ÈÎÎ!;;‡›QòóP3“o5ª:%³æ›4r1È8¸‰W§Á±¥F%Ë·äõ*d¸úoLDDDDD¤dœ¼‚i²E±ï0õXvÀ# 6OOšLlßJ8ÛSJ!Š•1Ýhöü\Âk¾¶býÁ»ñ5wšA>D·%ã8Ögý›­á’W0/ëÎ ÿÂÕb*Å1XþWª¬šJ؈3Ø|jÑoñ^ Í_ó>a4CzL§E¥Opõ­J§‘üù«Ý!ƈãF~8‰ß†¿GLëþœÅ… –O³tI7BÝ¡ðï뵓zˆ?äpÁVŒZš½K?m×nmIìÝ›Õ×í©ÿö"¶ò-áù ªãÞŸG¡}¨<ÄŠw•PúŽnÆÖÉŽ¬*a¾”´^wf2 _Ï$"""""R¦lØÐ–æÍ‡«ÈIø'÷Óÿ§™¼\ͬ‚Èÿ$­\øq#«Nód˜7¤îcî°ëMû5Fä—š#""""""â0{úþ€Á¿äîÔhÛ‰¥ï?E5gÕFþw©9"""""""2áõD¶ê¯RÈо­FDDDDDDDÊ45GDDDDDDD¤LSsDDDDDDä^Ëû•yái8ý¹}¾WÒ÷ÐÕ·+}¾ËÒ5ºÛ×ä~¹æe”š#""""""…1.òi›§ñ鲇‹ªF=»Q»ý“t¨ëqL¤ó~av“Ž4žuRÍ”R ²ŠˆˆˆˆˆˆÆÉ“–c£h©Jü1/¯J """""RD9)Ä6x–FþÍøNýðóŠ ¼ÿ0†,?ENÁ0çmþ\¯3VkVÏx¬ïZ~N7J¿É”ÍÄvîKkÖyé»Ò9ÿÓç¼Ø(?NÕ¶±%Í~õ0ûùDÞï5”ÀrX­¨Ûak’ó®í?³Øÿëƒ5kàp†.;Iöõq³Rù4ú5êUŒÀjÀ¿ñÞÝv€‘MÂG3y¢ú3ùc| + »­!é’cCºcnE­w±êSÈ5ºù±—bæÔðÕO‰jÓ‹@ßgñ®6Š‘ŸÞîwæN5Éd]缟ËþWûâeÀ0mº5Õù]å‘ðÁF\G¾Å±³«øiªŸ ™Íê_ jxä8ñÒŒ)üœ°˜=_¾HèîùDÆ$^‚øñ³–q Õ6ïŠ%¶áAÆFN¤KTLÊî¯GÐæÈrúNN"Àv†•}þΘA¼¾nq;Æ™¾†®Ï,%.+ÿŠ>¯31©³¿ûø5°Ì_Ć+ÍûE6ŒfТWÍeÿ¾÷˜ßñ<Óž›Æ²vòŽ®§OÔ.ª%.écöïx˜öq190”Âr+r½‹QŸb]£¢çtðƒÍx›ÉÑSŸ73/ú¾N쾜"Öăv+æ1­®3!Sr.c-)#inÍãð¬ÁX}§°%]w¨š#""""""¿ƒ‡:÷&êq/œM.Ôèô,­,I|u0»€ŸtåáéÙº5ªT¤öcm™ÛˆŒ¯¶r°ï:õl7€P?¤.=_}Šj§ÿ‹ç˜Á mLG[=4ˆ´-{9‘ y)Û™¹ÎB×9ƒèÝ<€àÐpbö nÒ—Ìù)›¼”íÌÚäÊ‹ô¥[ÃJTmðoÎü3¾äOôm¿ìdòJW†.êG÷æU«NĘ!ŒögÁ¦säœ;ÅKežl]‹`?o‚Bêó\G rq ÍSHnE¯wÑëSÜkTÔœÊ=Ý‹‘{bÆB@DƆ¥²hÁáË š¢×äæ)¾›_0M›âiÖýYz爈ˆˆˆˆH1§S¾u|p½:/u§‚{.G2 Z5`ç·oV0ü•ÏY»÷ܵhz„sÞ8/~`#?<®|òôÁÓ¥Ôt'±†™*[1e^ Ó—R9fògX=®,æp®BøCéìIÌ ËHä¸S £ëº_`­Ó:®ß}4žÄÌTv6îÈÔ›2 >~sdkz×[Ë Þ,‰hBë¶áü5²Áå _:RXn¶FE­wÑëƒsq®Q1rj\ùjN˜Ëó§‡Ë“öŸTÒíÞE«I“‚›#~‘£Ø©»³¨´rDDDDDD¤˜L·Ì¨ nÛOï``—e¤´ÎÇ>ãBúZNýûIt£ñÌ×5L€É„ÅéÆM×G¸}£ÂdNf\®““ç+Ÿ ;†¹6ó}AFÆÚþÅÅáêQ1?a÷§ÏÓ>à߈!ô‘Ùl:ëèM…îq´ÞÅ©Oq¯QÑr2°åÚ¯Û›ÿ¹$5‘ҡ戈ˆˆˆˆÈ]–“¼Ÿ½95òr#jUpÅl²qzïQÎÚ~¿\kd¤°1þÚ3"¹'÷³ã·rÔ«eÅ-°&Æ/ìJ¾öŰ—N$r8+*ïB ޲rëyn;·”£Në¶ŒŽfãÎWhñÛ·|ôsv‰ssúÃ\#G¿9̹+ÌMãûï/àêG9§¢ÖĄ٠ÃÐ V Թ˜}«QÕ)™5ߤ‘‹AÆÁM¼:õÈïúç‹8Qíòøçà¹,Ùq‚#{w2©ßÇÄ×lÏ 07,ÍÚâ<óÇnä`¦‘•²ñŸsèòñf¿æÄ¼`eýàÉŒ_q€¤ã§Húq ÇÍcþ\²âV3ý¾ÛŠ“ú²µ}IDAT'SùaÍr½ ©ä \ˆû†¹‹ö\~¿GÑrû#]£œm‹9?žCÉÉlx{&“öûÓ«OõkÚ8Z‹• 3É›ãHH=GÚÙ,ò°“ºòZuø„=YºïŠt¨""""""w—Ù¯ïÏŒ£ÇÐ>TbÅ»J(}G7cëäßñ¯þfo"?œÄoÃß#¦uÎâBP˧Yº¤¡î>tY4Ž£}gÐ"ðC\¼}y¢×s´Ø²*ÿx§ò´žñ6Ë|ç2>jÓÏ>„µnËX/'œ.X8¹æ#ºŒ;ÅÜêÒ}n Ãj[€<~Ûü/FM©JH—†ø;1·œ?Ê5²2¢+UWO%lÔl>µè·x¯„º@^Q¯—•1Ýhöü\Âk¾¶býÁaTN=ÄÎr¸`Ó}W&CkpDDDDDDn°aC[š7®B”šL6uïE·h~^Æeñ…9)Ä6y™ÏÌgë _­T¸ÏèzˆˆˆˆˆˆÈÝ•}’ •º´~ÙlŒÈ}O͹»Ü‚™òã ÕAî[jŽˆˆˆˆˆˆˆÜm.ŒùÏjƨ÷%}[ˆˆˆˆˆˆˆ”ijŽˆˆˆˆˆˆˆH™¦æˆˆˆˆˆˆÈ½÷+óÂ;Òpú ro÷3é{èêÛ•>ße¾ß‘óý‘å¤ÛàYšÎ9uË·âŠFÍ‘{2s£vû'éP×C³ûAÞ/ÌnґƳN^k.´MþôBV‘{ÁÉ“–c£h©JˆÜûÛQ%)¡Ët4™²™ØÎ}©`àÁ:¯3}W:çúœuÆj jÛØ’fÏ?¦€Ç`ìgöû}ð±F` ÎÐe'ɾ.Laûo‘•ʧѯQ¯bVkþ§ðî¶‹ØJk €ý|"ï÷J`¹¬ÖNÔí°ˆ5É—lÉ<Ȉêi¿6ãZœô=t­ô<·gƒ‘MÂG3y¢ú3X­XèJÃnkHºTŒü/³þ™7;¼„—5‚òUG1òÓSäšËÖuÀ+ñ¹ìµ/^Ö¬o2.âæmÓÙ–QȘ/ױф3¾S?ü¼"(ï?Œ!Ë/çQˆôo¦ákÍïõÿ®<.tÇØ8–[Q¯±š#""""""â <âg-ã@«!lÞKlÃŒœH—¨™:•Ý_ Í‘åôœDf³ú3¬èó:“0û»‰_Ó ËüElH7Û3ûE6ŒfТWÍeÿ¾÷˜ßñ<Óž›Æ²öÒƒí +ûü1;‚x}Ý<âvŒ!2} ]ŸYJ\–;ºž>Q»¨>>–¸¤Ù¿ã5bÚWÄÅTüü÷¿»”C£Ù0‡Ï:óÇ»¯°¶„íVÌcZ]gB¦,ä\ÆZ2Rb˜¸öæm#iîæÈ˜óHø`#®#ßâØÙUü4ՇφÌfõ¯ÇáYƒ±úNaKú­™”{|ÇÓV‘–¶Š´´•Ä/nŽ·9€6=1Vo›c¹•è÷T͹Ïv˜1°õCêÒóÕ§¨vú¿xŽÌÐÖÁÔy´%ÑCƒHÛ²—¼À"/e;³6¹òâ}éÖ°U<Á›3ÿŒ/†Cûoéµü²“É+]º¨Ý›T­:c†0Ú?ž›Îa/…1ä¥lgæ: ]ç ¢wó‚CÉY؃ºI_2ç§ì›#çNqÆR™'[×"ØÏ› ú<×ãQ‚\ŠŸ¿ëã}˜Þ¿5ªT¡Íè(ÆÖ;Á¢‡Km¢ïè˜êÜ›¨Ç½p6¹P£Ó³´²$ñÕÁlÀ 7¿`š6 ÄÓ\Ð,Ý‚«› nn.˜’72pÈnB¦Ž%¦‘;¶Bb;š[I~Oÿ¨ôΑRš^6òÃãÊ'O<]*ðHMwL˜y ²Sæ2m·ÎÆ.¥$rÜ)Ñuݯn³ÖiH×oÚ³ì£ñ$f¦²³qG¦Þ´/øøErñƵ„c¸”’È1“?Ãêy\ÞΕC(=‰Øܹbnµ[Ó»ÞZ…ôfIDZ· 篑 .g*fþfª¶¨Š×•eo7ñ$-.•t»©\åBÇÜ(¿Ž¾u|®åçäN÷\Žd€~‘£Øyç8ÆÅ&vYÀˆWØ9 W £ØY†c¹é÷ÔYÍ)'³éÚ`2aqºqÆmƒ1'3.ׯïw²àìäàþ[ÎgÇ0×f~â;¼PÉtÇpûs›Lùÿn§ýÊáÕ³ñ:lÙÎÚõ{øò&Mù ŸïBÓbæûd É¥¨'+dÉéÖ là`0ÛV{“ÙtdݬfT2%vṕè÷ôzïê¿/‘{Ï5°&Æ/ìJ¾ö,Ã¥‰Î2Ú3· jp”•[Ïc¿k9×&ÈHacüµŒäžÜÏŽßÊQ¯–''7¼­qæÒÕòΜ 9㺌,å¨Óº-£c£Ù¸óZüö-ýœ]Ìümýö(ç®;Ë®.àêG9Ka¹˜0;qSãçæm…޹ÄUÍ%iÞ4ú}À”å=hZÞäpl·»ž›š#""""""rYš1´ÅyæÝÈÁL#+…eã?çƒûofökNÌ VÖžÌøH:~Фw±pÜ<æ(—IXüÉj—Ç?ÏeÉŽÙ»“Iý>&¾f{…¹kEZ>feß‚¯‰Ï002RX>~9qFþ„?+n51Ó¿á»ý§8y2•Öì !×›JÎÅÎÿÒw2ja<‡’“ÙøÎ ÞØëG¯>Õñ($,V‚üÍ$oŽ#!õig³È+`…¹PvRW¾C«Ÿ°ç–—Ö¤ïþ]¢ÑföHzdgçCŽÍ(´Þ–çV†ï?•@DDDDDä>`ö¡Ë¢qí;ƒââí˽ž£Å–UŽí¿™SyZÏx›e¾s5ŠéçÂZ·e¬W)ýÜìM䇓ømø{Ä´îÏY\jù4K—t#ÔÀð £Òc:-*}‚«oU:ˆäÏ_ý+?E7 '×|D—q§¸`€[@]ºÏaXm ˜Š“¿…á¥Êª©„8ƒÍ§ýOà•P€;æVZÄt£Ùós ¯ù<ØŠõG°mäÇ\è÷õÚÉN=ÄÎr¸`»u_Ú®Ý$Ú.’Ø»7«¯ÛSÿíElä[H½½K˜[Ùe2Œ2ö ‘ˆˆˆˆˆH!6lhKóæÃU‘2BÕˆˆˆˆˆˆˆH™¦æˆˆˆˆˆˆˆˆ”ijŽˆˆˆˆˆˆˆH™¦æˆˆˆˆˆˆˆˆ”ijŽˆˆˆˆˆˆˆH™¦æˆˆˆˆˆˆÈý$ïWæ…w¤áôäÞç¶ŸÝËOõÀӵ›lJwà œbNNQbv²2rŠ¿š"+•O£_£^ÅüÕ.þ§ðî¶‹ØŒ‹|Ú¦-çŸ!{ËD*[#ð鲕#£àSÛNÿÌ›^ÂËAùª£ùé©ü±edDõŽ´_{Ýé{èZéyn?ú[b¼É¸ˆ‚ãÚÏ'ò~¯¡–‹ÀjíDÝ‹X“|¹QtùñžFþÍøNýðóŠ ¼ÿ0†,?åPÓ¿™†¯õò* ëþ]y\莱q,·&S6Û¹/¬Ø„ëßÞ&åâj¶Eùãü{%n¿È¦‘Ñ ÚâOôª¹ìß÷ó;žgÚsÓX–jåÿ6|Ææ¾âÖr'3Ö’¶ü1:4kUaÿ»K91šÝ søl 3ÿxq<±û kKxÐî–1L\[@\·3¬ìówÆìâõuóˆÛ1†Èô5t}f)qY×òHø`#®#ßâØÙUü4ՇφÌfõ¯ÇáYƒ±úNaKïR)÷ø(ާ­"-mii+‰_Üosm{b¶ÛæXnñ³–q Õ6ïŠ%¶áAÆFN¤KTLÊî¯GÐæÈrúNNrp周9""""""rä¤!Âj¸c*Æñžûݺ®Nf¬VK±ÎQ¶_v2y¥+Cõ£{ó@‚ªU'bÌFûdz`Ó9Jº^Áõñ>Lï_UªÐftcë`тå6ÑÏKÙÎÌuºÎDïæ‡†³°u“¾dÎOÙWî¡Î½‰zÜ g“ 5:=K+K_Ìœpó ¦i“@<Í͘-¸º¹àææ‚)y#‡ì&dêXb¹c+$¶£¹y¶ÀŒ ¨R—ž¯>EµÓÿÅsÌ`†¶¦Î£-‰DÚ–½œÐ‹Vî*=.&"""""r§ea¾¸9üóY|ûROžZqc‹a]ƒgåCè ¾{š*…Ìø²Æ“˜™ÊÎÆ™zÓ¾àãÉÅZ‚q™©Ú¢*^Wþ$oñ¦qOÒâRI·û—Jå.¥$rÌäϰzWJΕC(=‰Øå××·Ž®WîTpÏåH†8á9ŠM‘wŽc\L`b—ˆx…p2 ‰e8–[`#?<®”ÈÓO— &¾f{…9ò ’Ô•ïЪÃ'ìɺyŸAúîÐ%úmf¤g AvvÙÙ9äØ ,…Ķ”87ù=鱑3a}¸ k¿÷#vü Þêù¿\ÊW汎í™þZm¬XhÓfÏÏ%¼æ{ð`+ÖïëroÓv*Oëo³Ìw.ã£F1ý<àáCXë¶Œõr‚דXoÇÁ‚¾±ÆBÈð¿ReÕTÂFœÁæS‹~‹'ðJhþš–ð £Òc:-*}‚«oU:ˆäÏ_ýë1F7òÃIü6ü=bZ÷ç,.µ|š¥Kºê…_¯ìÔCìü!‡ ¶[÷¥íÚM¢í"‰½{³úº=õß^ÄÖA¾wŽw s“ßõ6 =¼$"""""r½ ÚÒ¼ùpB¤ŒÐc5"""""""R¦©9""""""""ešš#"""""""R¦©9""""""""ešš#"""""""R¦©9""""""r?Éû•yái8ý¹÷c¼œb‘÷{ %°\Vk'êvXÄšä¼êÑh¿ß©~^”¿:ÇëÙdÊfb;÷¥‚5‚ë¼Îô]éœÿés^lÔ«5‚ªm?bKšýÚqY©|ýõ*æ¯0òo<…w·]ÄæHNw¬M¶îE5GDDDDDDî¼ÔÝ|¼ÇÌ“cþBˆûÍ{-xUôæ©ó˜V×™) 9—±–Œ”‘4÷ÈãÀ›pýÛÛ¤\\Ͷ(œïn¶wŽg;Ͳ^˜–Ü„¹Û±m$å?þˆ éÆ çˆŸñ1ÿiÚŸõ?Îà=í|2x6«u§]Aã´œÇþw—r(b4»æðÙ@gþñâxb÷Ö–ð( F ××í +ûü1;‚x}Ý<âvŒ!2} ]ŸYJ\Öµ<>؈ëÈ·8vv?Mõá³!³Yý«äqxÖ`¬¾SØ’~ûzÆÏZÆVCؼ+–؆9‘.Q <2u*»¿A›#Ëé;9)õý"›FF3h‹?Ñ«æ²ß{ÌïxžiÏMcÙ »9‰š#""""""÷¡œÔ#¤âCX wLÅ8Þ³c¢[WÀÕÉŒÕj)Ö9J+^^ÊÞÿÖJ¿9½èÜÀ— ÐÇ7£-Ü81÷l;€ƒòðŸjÒ1úEÚ˜“øê`ÑV.¸>Þ‡éýëQ£JÚŒŽbl½,ZpØÁG ——²™ë,t3ˆÞÍ 'faê&}ÉœŸ®åúPçÞD=Ʌž¥•åÊXœpó ¦i“@<ïðÌ‘g»ÌØ€ú!uéùêST;ý_<Ç fhë`ê<Ú’è¡A¤mÙˉ\°ý²“É+]º¨Ý›T­:c†0Ú?ž›Îa/4'¹,*ˆˆˆˆˆÈ½–„ùâæðÏgñíK=yjÅ-„u žeü•¡ƒHøîiªXŠïRrLj®ézu›{p}j»m¸áý°^éª8—Ç¿\.G3в²ÁLÕUñºò'{‹7›x’—JºÝ¿T*{)%‘c&†Õó¸Úr®BøCéìIÌÀÖ(,¾u|¸:Z'w*¸çr$Üð‹ŦÈ;_¿ÀF~x\ùä郧K©y¥QfæÊVL™È´AöÑx3SÙÙ¸#So:Sðñ‹äb.$'¹;w¡ˆˆˆˆˆˆ”ˆ‹_5üØÄeaÔw.òʳ³SŽq£áÄ·Ø•—¿–#c?£;­"tA4=ƒò—7˜ËU¤’¥´âÌÉ|ýL˜00(¥É» L7'h€Ý(æÉ Ùcºå™Š¢å†Z˜“ ‹ÓMqŒËç3ìæÚÌO|‡*[NÊs*ÕÚÈÕk¨ˆˆˆˆˆˆ”ŒÅ¯ÝÃll~k=nyò!s¿faDŽ٠£¤³XåªT¥AX ÂÂjö°8»á_78ÿsX BkzâR̳»Ô$Ж·I—®nË:¼—ƒÙ†Ãù96NG¿=ʹ«¯Ù8Ë®.àêG9‹ÞVÈ8séêc&ygNœa¿CŒ[·¹Ö&ÈHacüµÉæžÜÏŽßÊQ¯–õžLˆÝ‚B¨ÁQVn=½X³øÂj#Å*«J """""RBΕxéý<²1OFÌaîñü¼ï;Ö­çQ´ˆ,‹• 3É›ãHH=GÚÙ,òîáXšòr‹  ^ÌÊŸOq|ïvÞ¾ž”ü%œÀñq^úîCF-ŒçPr2ß™Á{ýèÕ§:®iù˜•} ¾&>ÃÀÈHaùøåĦÛÇ(`þáDµË㟃ç²dÇ ŽìÝɤ~_³=ƒÂyÉNêÊwhÕáöd•N}Í~͉yÁÊúÁ“¿âIÇO‘ôã.Ž›Çü|çPaµ5GDDDDDDî Ö‡»°öûhTLà­žchöè0Z¿¸œ­ÖVL­6V¬´ˆéF³ƒs ¯ùUêÏáûÌûp(–‡è¶dcü~ ³ÞÔùË2Î?ß'¬\-ŽLÀ g_åk!dø_©²j*aȳï_¢Ûâ ¼ê¸>a4CB­®´WJ3ÑÁ¤°DÐÒÜÝÝ体$àÖÇùÐWðóúúýÿ[]bÒœéãÞÙ­7ÿØ•‹nÀÀÁÝ»rÿÍ ÿÿÿ8ya~tRNS@æØfbKGDˆH pHYs  šœtIMEÖ 1Ú q¨IDATÓMÌׂ@PzYéEXºHlˆ¢±£{ÿÿ¯,Ùy›“Ì0Ì5†ŠMÉS ¸UŽ4•e™=b‘ç.{ˆžíáòßK”ìA'æLø(1ÉïVÇ ïóÐiø H„È÷a–“î˜iLÖcg«lý$¬kvè¡åÊ^ pº9—ãÅÔmuÔàåÊBωUX›sL·Æë¶18[OÍ¡oo!¾ÿ#y,ùIEND®B`‚fityk-1.3.1/doc/img/ico-win.png000066400000000000000000000013421302634723100162370ustar00rootroot00000000000000‰PNG  IHDR(-S€PLTEúùýò¾ÿÓÿ̱¼–w–ÿ’ªÿ‰¾)Œ¥ÿÊÈ·¸K)üfÀéwÔÖíÙÇgýW\y÷·–g˜=UèÕGŠÕŠÇ«šGRyk¦êU§’"þþþ§Y§–mW‰z‰â׬Ç5v¸ÿ‹4,>ßååéÿ–Bââáÿ›MÍ¢ÿsÿ}$qþ´v[ÚÙÕþ¦dœÚ+ÜŽ]àßäg‡ýþ½‘ÀÀÅinÇoŽ;À›x 9ß¼5þèÚšÞx¢(Ø¡x]ƒ‘Ò›Ý&éíþAMÝîðåI^ã[ÿ¹»ÅúÏ!’¡â—àš°ü‚ ÿzÄíÀËÎè¯ÕmôÉ¢¦áöøîÿßÄÓ§ŠÊ·¦Ž¥Ž™\ÂѬÝÙ½¼ªTÖÓÅÑ­ß´ º1ðïíþöñ¦‡¼¯sèq8EaðQnôÆ7Ƨ"ض í~.»Êþæèîn¯Éç’ùûÿãâÛÐÐÔýÁœÝÝÝêŵ{µ'иhŬ@Ò¹U·_B§®iœ•Ëÿ,ÿÿÿü îVtRNS@æØfbKGDˆH pHYs  šœtIMEÖ ¹¯ÉäÛIDATÓc`ÀÌ 5¸ÓÊ|[-Une®h7˜@‰.¿®”²¾£PP; P€_UKG*QNBHÅIT’(P§¡Ê-Â%!)f$j¯ÎÀ–ãn,Rm)Ÿ/æì/ TÀëíë§W!!¯âä“2‚••M/]ͼƺ<“]V“ÁŃÃTØU\ºŠÏ¦¨ ×Ã×O@ÍB:E;€‰1(À¡Ç¦—¡©$¨̤²T@ÁNÁ]MNÉ*Á‹9 h)C  Тi%ŽXÏR˜ócÄã³+9‹5^,Š3ÈÑÏ+$¸’kÂIEND®B`‚fityk-1.3.1/doc/img/load_data_icon.png000066400000000000000000000017011302634723100176110ustar00rootroot00000000000000‰PNG  IHDRàw=øsRGB®ÎébKGDÿÿÿ ½§“ pHYsttÞfxtIMEÛ 5oŽ:>AIDATHÇå•Ík\UÆç~d&ªdŒl«bâ¦"-XÅ`íÆ•‚(¢ ‚›æ/pÑ…Qé?Ð…¨-B +¨UƒVMÓš0!j­tÒ$343wæ|»¸ó‘T'µ;_8Üsï=<ïû>ÏsÎÿ]ä'"ŸŸˆ|¯ëÅNÁ7¾WŽqGlÜþöoI¢tÐKÅÿ~»‘Ÿˆüà{ÛsÞ‹€øÉÓ'Ûô3Q O~rˆl# ÔnËÀÀ@ޱ±}¬”‹]pÝàƒéã<¼ëA*k;NÐî,Ýë?üè}Iƒz=¡ÑhráÚ<ß\ù‘8Ž8p×ãÜ¿û^+M†þV¦¬±<¸ŸKÅYÊ•*««UÊ«UJ7–ÎñØØ#ŒŽîE±E#9çB ´ ^9fDF!}™>ÖnÖÐZ#›Š0 (V®°'ÞÍÈÈ<ôæÞy÷ ú³w÷ÅBÉdèËÄ<ÿÅ <ûÚS|}æ¬o¿Ý]t}i•0)•–Éd²4“!.ݸœjQo sŠlejÈõu¼õˆ@àÃ:Ï‘ûs²4I8(¶ØY¾°øŸv©5Ç?þ”•åÊm{]ˆÛ{/:6õê É÷ßýʹŸ§É튰Îô¾¼ÇƒÖ£ óÒ‹/û¹ß "ø²pŠ$ipþ·††îañ³=¶Ã›mJQ­®Ó”IºÑr‡f—f©jÌÌL“4×pÎml!Ä&ÀIœsã0ÚД­ óùëêRš óhÀTñ+¢sy†‡‡)¿m9PïAˆ”ƉKÁ­±hmPZ£¤¢\^ãÂìq"HÎ9Þ>ò:¼šC©&Rªnµœw"À:‹sž0 °6­!PRaC6Ji®þ¹Ä©“gp®%r}Ò±ÿ•<ñÖ!~9?€µç\:o=½ëRdmʹkkñÎS­®333OGH©»‡]3‘ôôQ¯70Æb­íP’Òáp΃÷›®SJwÖ•®­0uú¤ÔbÓiúô3ϱXœ£TZFk‹1¦% ïT,)¸uR:S.¥T,.·ôÛz£ù;q_Çq„ÖÿíRÚqü _¶Á¿øÔIEND®B`‚fityk-1.3.1/doc/img/lock_icon.png000066400000000000000000000010141302634723100166260ustar00rootroot00000000000000‰PNG  IHDR ½ýìsRGB®ÎébKGDÿÿÿ ½§“ pHYsttÞfxtIMEÛ ŠÄžŒIDAT(Ï’ÏnQÆ÷ÎT:!Õ„š%]ª ±+ŒïÁ‚%™GpEâ3¸á tÁºòøјª …à¨MƒÔÌÜùù.hm]xv_r~çû¾›«¸>öŠVÿÕjÕv:Úí6žç0™L‡ôû}Œ1 À½|ß§Õjáû>³Ù €f³I·Û¥T*Ñëõr›z½nG£‘õ<ïj† ö2ªD„(Š® ‚€òÞÞFk€`>åøÃ;îÞ¡X,X×ÑÖu´Ýr[Ù-òuú…ýÝ⦴}ñü)=Àâ&¹S–%D§'½âÙËñºô“ÃáâËïŸ8 ¤i²yÄ,6Tv„Zy}ÌPJ±Š—ÌÏ"î×’Äæbß’™ŸÓ1"«RR¾¹Åøí’$Î#Å!û;‚Ö8 "ó%Ük’&ëHJ$†Ó¯QÚÍ‹æÆ¶ÇAEø|<&»P°Šq»°MAÈÅü=áÙ7LtÎ- Ó)Žã`5H¦Xœ›¿þ’åÿFýÔk«©•VIEND®B`‚fityk-1.3.1/doc/img/mode_add_icon.png000066400000000000000000000007621302634723100174430ustar00rootroot00000000000000‰PNG  IHDRשÍÊsRGB®Îé pHYsttÞfxtIMEÛ 78ëÞu¨PLTE1Nk555D-FFFXXXXt’^DcccdT5g^Fnnlnnnxwuyyy{{{}Z"†…ƒˆ`‹Š†‹‹ˆŒŒ‰£¹–•’š…X›™–œ›—Ÿ‹_ i¢~6¨§£°¯¬¸³›º iÀ¿½ÂÁ½Ç¯ẕvÒÐÐÖÀŽØÂ‘Ù‹ÛÚØÞÅßÊ–áÌ™êèãëèÓïíéóå¾ôçÂþüèþþíÿÿÿ÷£HÊtRNS@æØfbKGD70¸¸G¶IDAT(ÏmÂ0³˜rÔй@€Ð;„úÿ§áTÅŲܿæV²ãäŽ}`m'<­  ü€žÙ­ÏwÙ„.aº¿Ü߇ÇmnTú›a–à„RÕ8£6 LÂX”ánwa9ÇGÝaAÌ$à_W aQFðò  r%IüpMˆÆ,l£ ¤»,€ºP…ô€QFâÂB–$1ˆ2Õ0èBŸŸI½P&‹R‡“>ÄÊ'PÒ™Y©Ï_þEwp¤÷$IEND®B`‚fityk-1.3.1/doc/img/mode_bg_icon.png000066400000000000000000000004031302634723100172730ustar00rootroot00000000000000‰PNG  IHDRY ËsRGB®Îé pHYsttÞfxtIMEÛ:.íËyPLTEwÑ” ÿÿÿ(nætRNS@æØfbKGDhÙQ`IDATÁ 0 0?#ð1¨r“ÊŸÛm@:Ò)€Œ(€’!!C!ƒJ!ƒê@!-(耂ó =Ͻ»hg÷²{µµ‹óh}Îüž/€Ý À.΀?w +ú†r¶IEND®B`‚fityk-1.3.1/doc/img/mode_range_icon.png000066400000000000000000000004101302634723100177750ustar00rootroot00000000000000‰PNG  IHDRY ËsRGB®Îé pHYsttÞfxtIMEÛ 9 Ê9PLTEwNNNgggÿÿÿ×tRNS@æØfbKGDhÙQeIDATÓ}í À0DŸfí†.P’ýw붉¥‚à;ð¸ƒÛh¼€Æ/<=)â6@Ü|ˆ1ÁAì28¡ˆÛAC pJ]7ÐpYV°DÊrX‹Ï´­Ú¸{«3po©ÜöÕtú)³öÕYIEND®B`‚fityk-1.3.1/doc/img/mode_zoom.png000066400000000000000000000012371302634723100166650ustar00rootroot00000000000000‰PNG  IHDRJ~õsgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿ‡Ì¿ºIDAT8˵ӱkAðßì]. jPI »  #hc#ˆMk»´)ý#,¬íAÔÊ.j%Š`)0 Z5 ¢&¹½Ýgq›ËÞ%¨ï1Ì0ïûæí·óMÒs±¥£«ÉÑÜYÎFæ‚YãJ_¼ÒŽŽµ]¤ÞÆÉ˜·`¤”ÛôÑ]/­§AB MÇ‚«FØoDSé‡uŸÝñÈ·D ×ÅVäQDÈc3¾Ç×X‹1ÖGÈ8W±Ï˜$“zÙÉœrÉhˆ¡áœ–’ýè­“‹ŠÚÏÉè8f¸‚׳¬æ•èí{(%MEu]ÝJ¡P*ä:rÑß!÷^)—ëT™W£-×öVÑß!yl¡Ô*¹ [¶,+kvߌ¦VEHUŸ¶ +®+“ئ$hÅ·´dZºµB!·é§%¯k竾 ÅeK†4%I‰BÛ/7=éaÌ׈Y‹¦e•¾¶U·½@õ±SdÎ;k ï¼ð|Çœ5Ò ß뾩jSÁ‡>ìn7²5¯üSĘïQºÓßGLF×#½·ôç{*þ/ñ³ÌçŠr¿%tEXtdate:create2011-11-01T00:33:07+00:00ÆÎò %tEXtdate:modify2011-11-01T00:33:07+00:00·“J°IEND®B`‚fityk-1.3.1/doc/img/mouse16.png000066400000000000000000000013101302634723100161640ustar00rootroot00000000000000‰PNG  IHDRóÿasBIT|dˆIDAT8uÒKHTQÇñï9÷Þy4ši©4#™QD/¢dZ…D¢DDIFE¸3Z ´hSæN‚GZTDˤQ‹ìAb‰”Ê|?ƹ/ï=-20»þÖÿÿçðÿq@]]]¤££ÃbEjjj²þU„8­Pï'Ǧ.÷ôô,±*À4çwý»|ú°’þs Ž'ꜛ6^\½  ø‚ràmss³üÔÿ±Å%áË+ÝÝݯjk«î(ÁMàn  |J«««wôõ}¼Ž G—¡ÊήÎÉ¿Cn8Ö ­ÛR!ÔJ@üy¡ºV ÎϺ»ÞT{{»±°8[)ï|&šÈš‹î Çì'’ù––Èûë³s\ •z˜R+åtfîiQQáÑÇO†So¦¨Läða(›šƒ•YOž=º016QTjAÅ´Þj©*ÈßtíLíÙ¨íX¼˜ççœi¹”êØHÿ2ðysEòH¿ bÑh[2y4–É,¢I݉l†'2ì,Žâù>3ÓSTT$cë"‘¶@À´ìüâ¢bÇF7 Ží)"Y8Αí¹hRbZâ[X¶¯žç Ã1›želòÛ| Ž Gð<_Ë[ã¥HùMKKKØŽ ,ÿƒ 8ŽÍøÄ/4MGJR Ïó0M“…ô%‰Òµ!„²lKÌÌN …Ѥ†¯|\ÇÁ´2¤Ó¸®‹Bšü:X¢ëÓ3S(åãº.yyFhr(ðh|ùòŃ}{÷Åâ[â†ú£à8#£Ãôö¾[b­Z[[Ni†lñ<¿L)Zqž£irÀsýMM7ÿÓL "£H˜)IEND®B`‚fityk-1.3.1/doc/img/open_lock_icon.png000066400000000000000000000006521302634723100176560ustar00rootroot00000000000000‰PNG  IHDR ½ýìsRGB®ÎébKGDÿÿÿ ½§“ pHYsttÞfxtIMEÛ ¨±*IDAT(Ï’½JÃ`†ŸüT ZS:ªµY,]Ä›êàÐ97 Î.Ýzzê]JT(¥…¦ý¿ã*B"¾p–sÎÃûÂ9ð[’W©L€f³)ƒÁ@Â0$Š"úý¾8ŽSA ãñXz½žxž'£ÑH‚ (:ŽL&q]w·àû¾ ‡ÃÂx¦Ö­5I’ìšqÓ¨×ù·Žkòp'-ïDªÕ}±-SlË”Šm‰Q°/·7\]ž#X¤êÇÝ.r¸î¶Y/>Y~¼ð/HS•OŒbÀ0 ¾¶Kfó„³öj»ÉR h­I7kµ Óð ¥¶GBgh1[©ß%U*w.“=Ç¥u¬y¦d9@°˜=³ž¿³IV™™`YFÉ)Jÿè2Pƒ‚!ÒIEND®B`‚fityk-1.3.1/doc/img/strip_bg_icon.png000066400000000000000000000006121302634723100175120ustar00rootroot00000000000000‰PNG  IHDRשÍÊsRGB®Îé pHYsttÞfxtIMEÛ8ú³åêcPLTE %( L wNNNTQM}zr‘gš” ”¿»±Ã¼ÇÄ»ÈĸÈŹÊÅ»ÌÊÆÐÌÁÑ” ÑÎÃØÖÑÙØÒàÞÙäâÝåãÝÿÿÿ“œtRNS@æØfbKGD ³k=€“IDAT(Ï­G1 C%Ê z/¢Þÿ–,œÉð2a^ùéG²ü4Ò7½J$©ê‘êaIꓨ,Ô3æ-’H:JéAÔ:Àùùq'sND >o»pvî:î×d<¢ˆ$ÍHÛaql’¤ñät!Û„0¨!IL·ÇW{#õ¦\l×OdÚKù¬ ¡#Ææ JhÞŒÿºIEND®B`‚fityk-1.3.1/doc/img/zoom_all.png000066400000000000000000000010471302634723100165100ustar00rootroot00000000000000‰PNG  IHDRJ~õssRGB®ÎébKGDÿ‡Ì¿ pHYsttÞfxtIMEÛ 8)öI¼«IDAT8Ë•Ó?kTQðß}Ù5ñ_%"b »`‘&´±Ä&„€Al¶µS¿€U>Aº …¦K!¨­"ˆ­ˆÑB-”€Ê’dwß}c‘eÝÝ$`¦šáž3çÌ0—F,§£¥”ÁzÚ‹Pû—NEá²)'T~z«¥¯i_…ó1kÎIuI¥cÛw½±‘ö$LÄœy‡9fLM¥iÃ+ÖüJ»,‹ ¨«+<„ÐqÏ7ïâw¥€Ê-G2ª Iˆ 1<ôé¸î”£jXíz|*[.¸j-¶RŸBËE‡—èu‹^–\鮹§1*yd¤ !¬èØ&‡-eIMîöÙéœe•¬£Ô˜¢ û¬ÒqÓ ¥RÙ…-º­£í〥‚𶶬ÒÖÒÒÒÖVÉZZž«-m¦Õ˜7) ‹X–Ü*•-<¸¸J5»Ž³¦¦,ËJ, ôïqëqÍ]u5IR!kÛ´äåÐE÷Š‘˜Ò0¡èî¤mݲ÷»>A…KfŒã“×^í¼Ç røÞc·úxðe/ì¾˜Ž¾kùÊý˜=(¥gDà€ð^ü`»°ŽèõÙ\IEND®B`‚fityk-1.3.1/doc/index.rst000066400000000000000000000147441302634723100152630ustar00rootroot00000000000000 .. title:: Fityk --- curve fitting and peak fitting software .. meta:: :description: Fityk. Open-source curve-fitting and data analysis software. Linux, Windows, Mac OS X. :keywords: curve fitting, peak fitting, software, Voigt, Doniach-Sunjic .. role:: smallfont :class: smallfont .. role:: html(raw) :format: html .. image:: fityk-banner.png :align: center :target: http://fityk.nieto.pl :class: banner .. raw:: html

Excellent GUI and command-line curve fitting tool
- John Allspaw in The art of capacity planning

[screenshot]

see more screenshots

Fityk *[fi:tik]* is a program for data processing and nonlinear **curve fitting**. Primarily used * by scientists (150+ citations_ per year) who analyse data from powder diffraction, chromatography, photoluminescence and photoelectron spectroscopy, infrared and Raman spectroscopy, and other experimental techniques, .. * to fit peaks -- bell-shaped functions (Gaussian, Lorentzian, Voigt, Pearson VII, bifurcated Gaussian, EMG, Doniach-Sunjic, etc.), but the program is suitable for fitting any curve to 2D (*x*,\ *y*) data. .. _citations: https://scholar.google.com/citations?view_op=view_citation&hl=en&citation_for_view=aCtDUBMAAAAJ:u5HHmVD_uO8C .. _contents: :ref:`Features` | :ref:`Download` | :ref:`Documentation` | :ref:`Support ` .. _Features: Features ======== * intuitive graphical interface (and also command line interface), * support for many data file formats, thanks to the `xylib library `_, * dozens of built-in functions and support for user-defined functions, * equality constraints, * fitting systematic errors of the *x* coordinate of points (for example instrumental zero error or sample displacement correction in powder diffraction), * manual, graphical placement of peaks and auto-placement using peak detection algorithm, * various optimization methods (standard Marquardt least-squares algorithm, Genetic Algorithms, Nelder-Mead simplex), * handling series of datasets, * automation with macros (scripts) and embedded Lua for more complex scripting * the accuracy of nonlinear regression :wiki:`verified ` with reference datasets from NIST, * an add-on for powder diffraction data (Pawley refinement) * modular :wiki:`architecture `, * open source licence (GPLv2+). .. _Download: Download ======== In an attempt to make this software self-sustaining and actively developed in the future, `new binaries `_ are available to subscribers only: |ico-win| MS Windows: :subscribers_download:`-setup.exe` $ |ico-osx| Mac OS X (10.6 or later): :subscribers_download:`-osx.zip` $ |ico-tux| Linux: binary `RPM and deb packages `_ :smallfont:`for about 10 distros (incl. Ubuntu, Fedora, Suse), 32- and 64-bit.` .. raw:: html
Subscribers have access to all versions of the program and to e-mail support. The program can be installed on many computers and can be also used after the end of subscription. * `1 month subscription `_: $115 (≈ €90) * `1 year subscription `_: $199 (≈ €150) * `2 years subscription `_: $299 (≈ €225) .. raw:: html
Fityk is usually bought by companies and institutions. If you're a home user or a student in an institution that won't buy software for you - email wojdyr@gmail.com for info about discount. .. raw:: html
Versions 0.9.8 and older are free: for `Windows `_ and Linux (Ubuntu PPA_ and RPMs from OBS_). Source code: `GitHub `_ (`releases `_) Version 1.3.1 was released on 2016-12-19 (`changelog `_). New version `notifications `_ are delivered via email and feeds. .. _OBS: http://download.opensuse.org/repositories/home://wojdyr/ .. _PPA: https://launchpad.net/~wojdyr/+archive/fityk .. |ico-win| image:: img/ico-win.png .. |ico-tux| image:: img/ico-tux.png .. |ico-osx| image:: img/ico-osx.png .. _Documentation: Documentation ============= * `Manual `_ (chapters :ref:`intro`, :ref:`getstarted`, :ref:`data`, :ref:`model`, :ref:`fit`, :ref:`scripts`, :ref:`ref`). * PDF, ePUB and older versions of the manual can be downloaded `from Read the Docs `_. * `Fityk Wiki `_ (you are welcome to contribute). Citing Fityk in academic papers: M. Wojdyr, `J. Appl. Cryst. 43, 1126-1128 `_ (2010) [`reprint `_] .. _Support: Questions? ========== * Google group `fityk-users `_ (you may select "no mail" and use it like forum) * or wojdyr@gmail.com Feel free to send questions, comments, requests, bug reports, and success stories. Asking for a new feature usually results in adding the request to the `TODO list `_ or, if it already is in the list, in assigning higher priority to it. .. raw:: html fityk-1.3.1/doc/intro.rst000066400000000000000000000075041302634723100153030ustar00rootroot00000000000000.. _intro: Introduction ############ Fityk is a program for nonlinear fitting of analytical functions (especially peak-shaped) to data (usually experimental data). To put it differently, it is primarily peak fitting software, but can handle other types of functions as well. Apart from the actual fitting, the program helps with data processing and provides ergonomic graphical interface (and also command line interface and scripting API -- but if the program is popular in some fields, it's thanks to its graphical interface). It is reportedly__ used in crystallography, chromatography, photoluminescence and photoelectron spectroscopy, infrared and Raman spectroscopy, to name but a few. __ https://scholar.google.com/citations?view_op=view_citation&citation_for_view=aCtDUBMAAAAJ:u5HHmVD_uO8C Fityk offers various nonlinear fitting methods, simple background subtraction and other manipulations to the dataset, easy placement of peaks and changing of peak parameters, support for analysis of series of datasets, automation of common tasks with scripts, and much more. In simple cases, the program can be operated with mouse only. Let say that you want to model the data with multiple peaks or other function shapes. You select a built-in function type (such as Gaussian, Voigt, sigmoid, polynomial and dozens of others) place it with the mouse, place other functions and click a button to fit it. But the program can also handle quite complex scenarios. You can define your own function types. You can specify sophisticated dependencies between parameters of the functions (say, peak widths given as a function of peak positions). You can fit multiple datasets together using common set of parameters. You can model zero-shift in your instrument or do more complicated refinement of the X scale. And you can automate all this work. If you don't know how to handle your case, do not hesistate to ask on the `users group`__ or contact the author. __ http://groups.google.com/group/fityk-users/ To download the latest version of the program or to contact the author visit `fityk.nieto.pl `_. Reference for academic papers: M. Wojdyr, `J. Appl. Cryst. 43, 1126-1128 `_ (2010) [`reprint `_] Open Source =========== Fityk is open-source (`GPL2+ `_). If you are interested, please find `the source code at GitHub`__. __ https://github.com/wojdyr/fityk/ It uses a few open source projects: * NLopt_ for several optional fitting methods * one of the fitting methods uses MPFIT_ library (MINPACK-1 Least Squares Fitting Library in C), which includes software developed by the University of Chicago, as Operator of Argonne National Laboratory. * xylib_ library handles reading data files * Lua_ interpreter is embedded for scripting * and a few popular libraries and tools that make programming much easier: wxWidgets (GUI), Boost (misc), zlib (compression), readline (CLI), SWIG (bindings), Catch (testing). .. _NLopt: http://ab-initio.mit.edu/wiki/index.php/NLopt .. _MPFIT: http://www.physics.wisc.edu/~craigm/idl/cmpfit.html .. _Lua: http://www.lua.org/ .. _xylib: http://xylib.sourceforge.net/ About this manual ================= This manual is written in ReStructuredText. All corrections and improvements are welcome. Use the ``Show Source`` link to get the source of the page, edit it and send me either the modified version or a patch. Alternatively, go to `GitHub `_, open corresponding rst file, press *Fork and edit this file* button, do edits in your web browser and click *Propose file change*. The following people have contributed to this manual (in chronological order): Marcin Wojdyr (maintainer), Stan Gierlotka, Jaap Folmer, Michael Richardson. fityk-1.3.1/doc/math.lyx000066400000000000000000000176321302634723100151100ustar00rootroot00000000000000#LyX 1.4.2 created this file. For more info see http://www.lyx.org/ \lyxformat 245 \begin_document \begin_header \textclass article \language english \inputencoding auto \fontscheme default \graphics default \paperfontsize 12 \spacing single \papersize default \use_geometry false \use_amsmath 1 \cite_engine basic \use_bibtopic false \paperorientation portrait \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \defskip medskip \quotes_language english \papercolumns 1 \papersides 1 \paperpagestyle default \tracking_changes false \output_changes true \end_header \begin_body \begin_layout Title Equations for fityk help \end_layout \begin_layout Section* various symbols and equations \end_layout \begin_layout Standard \begin_inset Formula $2\theta$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula $\sigma$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula $w_{i}=1/\sigma_{i}^{2}$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula \[ w_{i}=\frac{1}{\sigma_{i}^{2}}\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula $S=\sum_{i}f_{i}$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula \[ S=\sum_{i}f_{i}\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula $S(x;\mathbf{a})=\sum_{i}f_{i}(x+z(x;\mathbf{a});\mathbf{a})$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula \[ S(x;\mathbf{a})=\sum_{i}f_{i}(x+z(x;\mathbf{a});\mathbf{a})\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula $z(x;\mathbf{a})=\sum_{j}z_{j}(x;\mathbf{a})$ \end_inset \begin_inset Formula \[ z(x;\mathbf{a})=\sum_{j}z_{j}(x;\mathbf{a})\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula \[ a_{0}\exp\left[-\ln(2)\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\right]\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula \[ \chi^{2}(\mathbf{a})=\sum_{i=1}^{N}\left[\frac{y_{i}-y(x_{i};\mathbf{a})}{\sigma_{i}}\right]^{2}=\sum_{i=1}^{N}w_{i}\left[y_{i}-y(x_{i};\mathbf{a})\right]^{2}\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula $voigt(a,b)\equiv\frac{b}{\pi}\int_{-\infty}^{+\infty}\frac{\exp(-t^{2})}{b^{2}+(a-t)^{2}}dt$ \end_inset \end_layout \begin_layout Section* f-functions \end_layout \begin_layout Standard Gaussian \end_layout \begin_layout Standard \begin_inset Formula \[ y=a_{0}\exp\left[-\ln(2)\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\right]\] \end_inset \end_layout \begin_layout Standard SplitGaussian \begin_inset Formula \[ y(x;a_{0},a_{1},a_{2},a_{3})=\begin{cases} \textrm{Gaussian}(x;a_{0},a_{1},a_{2}) & x\leq a_{1}\\ \textrm{Gaussian}(x;a_{0},a_{1},a_{3}) & x>a_{1}\end{cases}\] \end_inset \end_layout \begin_layout Standard GaussianA \end_layout \begin_layout Standard \begin_inset Formula \[ y=\sqrt{\frac{\ln(2)}{\pi}}\frac{a_{0}}{a_{2}}\exp\left[-\ln(2)\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\right]\] \end_inset \end_layout \begin_layout Standard Lorentzian \begin_inset Formula \[ y=\frac{a_{0}}{1+\left(\frac{x-a_{1}}{a_{2}}\right)^{2}}\] \end_inset \end_layout \begin_layout Standard LorentzianA \begin_inset Formula \[ y=\frac{a_{0}}{\pi a_{2}\left[1+\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\right]}\] \end_inset \end_layout \begin_layout Standard PseudoVoigt \begin_inset Formula \[ y=a_{0}\left[(1-a_{3})\exp\left(-\ln(2)\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\right)+\frac{a_{3}}{1+\left(\frac{x-a_{1}}{a_{2}}\right)^{2}}\right]\] \end_inset \end_layout \begin_layout Standard GaussianLorentzianSumA \begin_inset Formula \[ y=a_{0}\left[\frac{(1-a_{3})\sqrt{\ln2}}{a_{2}\sqrt{\pi}}\exp\left(-\ln2\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\right)+\frac{a_{3}}{\pi a_{2}\left[1+\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\right]}\right]\] \end_inset \end_layout \begin_layout Standard Pearson7 \begin_inset Formula \[ y=\frac{a_{0}}{\left[1+\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\left(2^{\frac{1}{a_{3}}}-1\right)\right]^{a_{3}}}\] \end_inset \end_layout \begin_layout Standard SplitPearson7 \begin_inset Formula \[ y(x;a_{0},a_{1},a_{2},a_{3},a_{4},a_{5})=\begin{cases} \textrm{Pearson7}(x;a_{0},a_{1},a_{2},a_{4}) & x\leq a_{1}\\ \textrm{Pearson7}(x;a_{0},a_{1},a_{3},a_{5}) & x>a_{1}\end{cases}\] \end_inset \end_layout \begin_layout Standard Pearson7A \begin_inset Formula \[ y=\frac{a_{0}\Gamma(a_{3})\sqrt{2^{\frac{1}{a_{3}}}-1}}{a_{2}\Gamma(a_{3}-\frac{1}{2})\sqrt{\pi}\left[1+\left(\frac{x-a_{1}}{a_{2}}\right)^{2}\left(2^{\frac{1}{a_{3}}}-1\right)\right]^{a_{3}}}\] \end_inset \end_layout \begin_layout Standard Voigt \begin_inset Formula \[ y=\frac{a_{0}\int_{-\infty}^{+\infty}\frac{\exp(-t^{2})}{a_{3}^{2}+(\frac{x-a_{1}}{a_{2}}-t)^{2}}dt}{\int_{-\infty}^{+\infty}\frac{\exp(-t^{2})}{a_{3}^{2}+t^{2}}dt}\] \end_inset \end_layout \begin_layout Standard VoigtA \begin_inset Formula \[ y=\frac{a_{0}}{\sqrt{\pi}a_{2}}\int_{-\infty}^{+\infty}\frac{\exp(-t^{2})}{a_{3}^{2}+(\frac{x-a_{1}}{a_{2}}-t)^{2}}dt\] \end_inset \end_layout \begin_layout Standard Polynomial \begin_inset Formula \[ y=a_{0}+a_{1}x+a_{2}x^{2}+a_{3}x^{3}+a_{4}x^{4}+a_{5}x^{5}\] \end_inset \end_layout \begin_layout Standard EMG \begin_inset Formula \[ y=\frac{ac\sqrt{2\pi}}{2d}\exp\left(\frac{b-x}{d}+\frac{c^{2}}{2d^{2}}\right)\left[\frac{d}{\left|d\right|}-\textrm{erf}\left(\frac{b-x}{\sqrt{2}c}+\frac{c}{\sqrt{2}d}\right)\right]\] \end_inset \end_layout \begin_layout Standard DoniachSunjic \begin_inset Formula \[ y=\frac{h\left[\frac{\pi a}{2}+(1-a)\arctan\left(\frac{x-E}{F}\right)\right]}{F+(x-E)^{2}}\] \end_inset \end_layout \begin_layout Section* zero-shifts \end_layout \begin_layout Standard \begin_inset Formula $z=a_{0}$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula $z=a_{0}\cos(x[\textrm{RAD}]/2)$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula $z=a_{0}\sin(x[\textrm{RAD}])$ \end_inset \end_layout \begin_layout Section* Xtal \end_layout \begin_layout Standard Mod-TCH pV \end_layout \begin_layout Standard \begin_inset Formula $a_{3}=1.36603q-0.47719q^{2}+0.1116q^{3}$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula $q=\Gamma_{L}/\Gamma$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula \[ \Gamma=(\Gamma_{G}^{5}+2.69269\Gamma_{G}^{4}\Gamma_{L}+2.42843\Gamma_{G}^{3}\Gamma_{L}^{2}+4.47163\Gamma_{G}^{2}\Gamma_{L}^{3}+0.07842\Gamma_{G}\Gamma_{L}^{4}+\Gamma_{L}^{5})^{0.2}=H_{K}=2a_{2}\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula \begin{eqnarray*} \Gamma & = & (\Gamma_{G}^{5}+A\Gamma_{G}^{4}\Gamma_{L}+B\Gamma_{G}^{3}\Gamma_{L}^{2}+C\Gamma_{G}^{2}\Gamma_{L}^{3}+D\Gamma_{G}\Gamma_{L}^{4}+\Gamma_{L}^{5})^{0.2}=H_{K}=2a_{2}\end{eqnarray*} \end_inset \end_layout \begin_layout Standard \begin_inset Formula \[ A=2.69269,B=2.42843,C=4.47163,D=0.07842\] \end_inset \end_layout \begin_layout Standard \begin_inset Formula $\Gamma=(\Gamma_{G}^{5}+2.69269\Gamma_{G}^{4}\Gamma_{L}+2.42843\Gamma_{G}^{3}\Gamma_{L}^{2}+4.47163\Gamma_{G}^{2}\Gamma_{L}^{3}+0.07842\Gamma_{G}\Gamma_{L}^{4}+\Gamma_{L}^{5})^{0.2}=H_{K}=2a_{2}$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula $\Gamma_{G}=(U\tan^{2}\theta+V\tan\theta+W+Z/\cos^{2}\theta)^{1/2}$ \end_inset \end_layout \begin_layout Standard \begin_inset Formula $\Gamma_{L}=X\tan\theta+Y/\cos\theta$ \end_inset \end_layout \begin_layout Standard Pearson: \end_layout \begin_layout Standard \begin_inset Formula $a_{3}=A+B/2\theta+C/(2\theta)^{2}$ \end_inset \end_layout \begin_layout Standard Pseudo-Voigt: \end_layout \begin_layout Standard \begin_inset Formula $a_{3}=A+B*(2\theta)$ \end_inset \end_layout \begin_layout Standard Caglioti: \end_layout \begin_layout Standard \begin_inset Formula $(2a_{2})^{2}=H_{K}^{2}=U\tan^{2}\theta+V\tan\theta+W$ \end_inset \end_layout \begin_layout Standard Lowe-Ma \end_layout \begin_layout Standard \begin_inset Formula $(2a_{2})^{2}=H_{K}^{2}=U\tan^{2}\theta+V\tan\theta+W+CT\cot^{2}\theta$ \end_inset \end_layout \end_body \end_document fityk-1.3.1/doc/model.rst000066400000000000000000000641541302634723100152540ustar00rootroot00000000000000.. _model: Models ====== From `Numerical Recipes `_, chapter 15.0: Given a set of observations, one often wants to condense and summarize the data by fitting it to a "model" that depends on adjustable parameters. Sometimes the model is simply a convenient class of functions, such as polynomials or Gaussians, and the fit supplies the appropriate coefficients. Other times, the model's parameters come from some underlying theory that the data are supposed to satisfy; examples are coefficients of rate equations in a complex network of chemical reactions, or orbital elements of a binary star. Modeling can also be used as a kind of constrained interpolation, where you want to extend a few data points into a continuous function, but with some underlying idea of what that function should look like. This chapter shows how to construct the model. Complex models are often a sum of many functions. That is why in Fityk the model *F* is constructed as a list of component functions and is computed as :math:`F = \sum_i f_i`. Each component function :math:`f_i` is one of predefined functions, such as Gaussian or polynomial. This is not a limitation, because the user can add any function to the predefined functions. To avoid confusion, the name *function* will be used only when referring to a component function, not when when referring to the sum (model), which mathematically is also a function. The predefined functions will be sometimes called *function types*. Function :math:`f_i=f_i(x; \boldsymbol{a})` is a function of *x*, and depends on a vector of parameters :math:`\boldsymbol{a}`. The parameters :math:`\boldsymbol{a}` will be fitted to achieve agreement of the model and data. In experiments we often have the situation that the measured *x* values are subject to systematic errors caused, for example, by instrumental zero shift or, in powder diffraction measurements, by displacement of sample in the instrument. If this is the case, such errors should be a part of the model. In Fityk, this part of the model is called :dfn:`x-correction`. The final formula for the model is: .. _model_formula: .. math:: F(x; \boldsymbol{a}) = \sum_i f_i(x+Z(x; \boldsymbol{a}); \boldsymbol{a}) where :math:`Z(x; \boldsymbol{a}) = \sum_i z_i(x; \boldsymbol{a})` is the *x*-correction. *Z* is constructed as a list of components, analogously to *F*, although in practice it has rarely more than one component. Each component function is created by specifying a function type and binding *variables* to type's parameters. The next section explains what are *variables* in Fityk, and then we get back to functions. .. _variables: Variables --------- Variables have names prefixed with the dollar symbol ($) and are created by assigning a value:: $foo=~5.3 # simple-variable $bar=5*sin($foo) # compound-variable $c=3.1 # constant (the simplest compound-variable) The numbers prefixed with the tilde (~) are adjustable when the model is fitted to the data. Variable created by assigning ``~``\ *number* (like ``$foo`` in the example above) will be called a :dfn:`simple-variable`. All other variables are called :dfn:`compound-variables`. Compound variables either depend on other variables (``$bar`` above) or are constant (``$c``). .. important:: Unlike in popular programming languages, variable can store either a single numeric (floating-point) value or a mathematical expression. Nothing else. In case of expression, if we define ``$b=2*$a`` the value of ``$b`` will be recalculated every time ``$a`` changes. To assign a value (constant) of another variable, use: ``$b={$a}``. Braces return the current value of the enclosed expression. The left brace can be preceded by the tilde (``~``). The assignment ``$b=~{$a}`` creates a simple variable. Compound-variables can be build using operators +, -, \*, /, ^ and the functions ``sqrt``, ``exp``, ``log10``, ``ln``, ``sin``, ``cos``, ``tan``, ``sinh``, ``cosh``, ``tanh``, ``atan``, ``asin``, ``acos``, ``erf``, ``erfc``, ``lgamma``, ``abs``, ``voigt``. This is a subset of the functions used in :ref:`data transformations `. The braces may contain any data expression:: $x0 = {x[0]} $min_y = {min(y if a)} $c = {max2($a, $b)} $t = {max(x) < 78 ? $a : $b} Sometimes it is useful to freeze a variable, i.e. to prevent it from changing while fitting:: $a = ~12.3 # $a is fittable (simple-variable) $a = {$a} # $a is not fittable (constant) $a = ~{$a} # $a is fittable (simple-variable) again .. admonition:: In the GUI a variable can be switched between constant and simple-variable by clicking the padlock button on the sidebar. The icons |open-lock-icon| and |lock-icon| show that the variable is fittable and frozen, respectively. .. |open-lock-icon| image:: img/open_lock_icon.png :alt: open lock .. |lock-icon| image:: img/lock_icon.png :alt: lock If the assigned expression contains tildes:: $bleh=~9.1*exp(~2) it automatically creates simple-variables corresponding to the tilde-prefixed numbers. In the example above two simple-variables (with values 9.1 and 2) are created. Automatically created variables are named ``$_1``, ``$_2``, ``$_3``, and so on. Variables can be deleted using the command:: delete $variable .. _domain: Domains ------- Simple-variables may have a :dfn:`domain`, which is used for two things when fitting. Most importantly, fitting methods that support bound constraints use the domain as lower and/or upper bounds. See the section :ref:`bound_constraints` for details. The other use is for randomizing parameters (simple-variables) of the model. Methods that stochastically initialize or modify parameters (usually generating a set of initial points) need well-defined domains (minimum and maximum values for parameters) to work effectively. Such methods include Nelder-Mead simplex and Genetic Algorithms, but not the default Lev-Mar method, so in most cases you do not need to worry about it. The syntax is as follows:: $a = ~12.3 [0:20] # initial values are drawn from the (0, 20) range $a = ~12.3 [0:] # only lower bound $a = ~12.3 [:20] # only upper bound $a = ~15.0 # domain stays the same $a = ~15.0 [] # no domain $a = ~{$a} [0:20] # domain is set again If the domain is not specified but it is required (for the latter use) by the fitting method, we assume it to be ±\ *p*\ % of the current value, where *p* can be set using the :option:`domain_percent` option. Function Types and Functions ---------------------------- Function types have names that start with upper case letter (``Linear``, ``Voigt``). Functions have names prefixed with the percent symbol (``%func``). Every function has a type and variables bound to its parameters. One way to create a function is to specify both type and variables:: %f1 = Gaussian(~66254., ~24.7, ~0.264) %f2 = Gaussian(~6e4, $ctr, $b+$c) %f3 = Gaussian(height=~66254., hwhm=~0.264, center=~24.7) Every expression which is valid on the right-hand side of a variable assignment can be used as a variable. If it is not just a name of a variable, an automatic variable is created. In the above examples, two variables were implicitely created for ``%f2``: first for value ``6e4`` and the second for ``$b+$c``). If the names of function's parameters are given (like for ``%f3`` above), the variables can be given in any order. Function types can can have specified default values for some parameters. The variables for such parameters can be omitted, e.g.:: =-> i Pearson7 Pearson7(height, center, hwhm, shape=2) = height/(1+((x-center)/hwhm)^2*(2^(1/shape)-1))^shape =-> %f4 = Pearson7(height=~66254., center=~24.7, hwhm=~0.264) # no shape is given New function %f4 was created. Functions can be copied. The following command creates a deep copy (i.e. all variables are also duplicated) of %foo:: %bar = copy(%foo) Functions can be also created with the command ``guess``, as described in :ref:`guess`. Variables bound to the function parameters can be changed at any time:: =-> %f = Pearson7(height=~66254., center=~24.7, fwhm=~0.264) New function %f was created. =-> %f.center=~24.8 =-> $h = ~66254 =-> %f.height=$h =-> info %f %f = Pearson7($h, $_5, $_3, $_4) =-> $h = ~60000 # variables are kept by name, so this also changes %f =-> %p1.center = %p2.center + 3 # keep fixed distance between %p1 and %p2 Functions can be deleted using the command:: delete %function .. _flist: Built-In Functions ------------------ The list of all functions can be obtained using ``i types``. Some formulae here have long parameter names (like "height", "center" and "hwhm") replaced with :math:`a_i` :ftype:`Gaussian`: .. math:: y = a_0 \exp\left[-\ln(2)\left(\frac{x-a_1}{a_2}\right)^{2}\right] :math:`a_2` here is half width at half maximum (HWHM=FWHM/2, where FWHM stands for full width...), which is proportional to the standard deviation: :math:`a_2=\sqrt{2\ln2}\sigma`. :ftype:`SplitGaussian`: .. math:: y(x;a_0,a_1,a_2,a_3) = \begin{cases} \textrm{Gaussian}(x;a_0,a_1,a_2) & x\leq a_1\\ \textrm{Gaussian}(x;a_0,a_1,a_3) & x>a_1\end{cases} :ftype:`GaussianA`: .. math:: y = \sqrt{\frac{\ln(2)}{\pi}}\frac{a_0}{a_2} \exp\left[-\ln(2)\left(\frac{x-a_1}{a_2}\right)^{2}\right] :ftype:`Lorentzian`: .. math:: y = \frac{a_0}{1+\left(\frac{x-a_1}{a_2}\right)^2} :ftype:`SplitLorentzian`: .. math:: y(x;a_0,a_1,a_2,a_3) = \begin{cases} \textrm{Lorentzian}(x;a_0,a_1,a_2) & x\leq a_1\\ \textrm{Lorentzian}(x;a_0,a_1,a_3) & x>a_1\end{cases} :ftype:`LorentzianA`: .. math:: y = \frac{a_0}{\pi a_2\left[1+\left(\frac{x-a_1}{a_2}\right)^2\right]} :ftype:`Pearson VII (Pearson7)`: .. math:: y = \frac{a_0} {\left[1+\left(\frac{x-a_1}{a_2}\right)^2 \left(2^{\frac{1}{a_3}}-1\right)\right]^{a_3}} :ftype:`split Pearson VII (SplitPearson7)`: .. math:: y(x;a_{0},a_{1},a_{2},a_{3},a_{4},a_{5}) = \begin{cases} \textrm{Pearson7}(x;a_0,a_1,a_2,a_4) & x\leq a_1\\ \textrm{Pearson7}(x;a_0,a_1,a_3,a_5) & x>a_1\end{cases} :ftype:`Pearson VII Area (Pearson7A)`: .. math:: y = \frac{a_0\Gamma(a_3)\sqrt{2^{\frac{1}{a_3}}-1}} {a_2\Gamma(a_3-\frac{1}{2})\sqrt{\pi} \left[ 1 + \left(\frac{x-a_1}{a_2}\right)^2 \left(2^{\frac{1}{a_3}}-1\right) \right]^{a_3}} :ftype:`Pseudo-Voigt (PseudoVoigt)`: .. math:: y = a_0 \left[(1-a_3)\exp\left(-\ln(2)\left(\frac{x-a_1}{a_2}\right)^2\right) + \frac{a_3}{1+\left(\frac{x-a_1}{a_2}\right)^2} \right] Pseudo-Voigt is a name given to the sum of Gaussian and Lorentzian. :math:`a_3` parameters in Pearson VII and Pseudo-Voigt are not related. :ftype:`split Pseudo-Voigt (SplitPseudoVoigt)`: .. math:: y(x;a_{0},a_{1},a_{2},a_{3},a_{4},a_{5}) = \begin{cases} \textrm{PseudoVoigt}(x;a_0,a_1,a_2,a_4) & x\leq a_1\\ \textrm{PseudoVoigt}(x;a_0,a_1,a_3,a_5) & x>a_1\end{cases} :ftype:`Pseudo-Voigt Area (PseudoVoigtA)`: .. math:: y = a_0 \left[\frac{(1-a_3)\sqrt{\ln(2)}}{a_2\sqrt{\pi}} \exp\left(-\ln2\left(\frac{x-a_1}{a_2}\right)^2\right) + \frac{a_3}{\pi a_2 \left[1+\left(\frac{x-a_1}{a_2}\right)^2\right]} \right] :ftype:`Voigt`: .. math:: y = \frac {a_0 \int_{-\infty}^{+\infty} \frac{\exp(-t^2)}{a_3^2+(\frac{x-a_1}{a_2}-t)^2} dt} {\int_{-\infty}^{+\infty} \frac{\exp(-t^2)}{a_3^2+t^2} dt} The Voigt function is a convolution of Gaussian and Lorentzian functions. :math:`a_0` = heigth, :math:`a_1` = center, :math:`a_2` is proportional to the Gaussian width, and :math:`a_3` is proportional to the ratio of Lorentzian and Gaussian widths. Voigt is computed according to R.J.Wells, *Rapid approximation to the Voigt/Faddeeva function and its derivatives*, Journal of Quantitative Spectroscopy & Radiative Transfer 62 (1999) 29-48. The approximation is very fast, but not very exact. FWHM is estimated using an approximation called *modified Whiting* (`Olivero and Longbothum, 1977, JQSRT 17, 233`__): :math:`0.5346 w_L + \sqrt{0.2169 w_L^2 + w_G^2}`, where :math:`w_G=2\sqrt{\ln(2)} |a_2|, w_L=2 |a_2| a_3`. __ http://dx.doi.org/10.1016/0022-4073(77)90161-3 :ftype:`VoigtA`: .. math:: y = \frac{a_0}{\sqrt{\pi}a_2} \int_{-\infty}^{+\infty} \frac{\exp(-t^2)}{a_3^2+(\frac{x-a_1}{a_2}-t)^2} dt :ftype:`split Voigt (SplitVoigt)`: .. math:: y(x;a_{0},a_{1},a_{2},a_{3},a_{4},a_{5}) = \begin{cases} \textrm{Voigt}(x;a_0,a_1,a_2,a_4) & x\leq a_1\\ \textrm{Voigt}(x;a_0,a_1,a_3,a_5) & x>a_1\end{cases} :ftype:`Exponentially Modified Gaussian (EMG)`: .. math:: y = \frac{ac\sqrt{2\pi}}{2d} \exp\left(\frac{c^2}{2d^2}-\frac{x-b}{d}\right) \left[\frac{d}{\left|d\right|} +\textrm{erf}\left(\frac{x-b}{\sqrt{2}c} - \frac{c}{\sqrt{2}d}\right) \right] The exponentially modified Gaussian is a convolution of Gaussian and exponential probability density. *a* = Gaussian heigth, *b* = location parameter (Gaussian center), *c* = Gaussian width, *d* = distortion parameter (a.k.a. modification factor or time constant). :ftype:`LogNormal`: .. math:: y = h \exp\left\{ -\ln(2) \left[ \frac{\ln\left(1+2b\frac{x-c}{w}\right)}{b} \right]^{2} \right\} :ftype:`Doniach-Sunjic (DoniachSunjic)`: .. math:: y = \frac{h\left[\frac{\pi a}{2} + (1-a)\arctan\left(\frac{x-E}{F}\right)\right]} {F+(x-E)^2} :ftype:`Polynomial5`: .. math:: y = a_0 + a_1 x +a_2 x^2 + a_3 x^3 + a_4 x^4 + a_5 x^5 :ftype:`Sigmoid`: .. math:: y = L + \frac{U-L}{1+\exp\left(-\frac{x-x_{mid}}{w}\right)} :ftype:`FCJAsymm`: Axial asymmetry peak shape in the Finger, Cox and Jephcoat model, see `J. Appl. Cryst. (1994) 27, 892 `_ and `J. Appl. Cryst. (2013) 46, 1219 `_. Variadic Functions ------------------ *Variadic* function types have variable number of parameters. Two variadic function types are defined:: Spline(x1, y1, x2, y2, ...) Polyline(x1, y1, x2, y2, ...) This example:: %f = Spline(22.1, 37.9, 48.1, 17.2, 93.0, 20.7) creates a function that is a *natural cubic spline* interpolation through points (22.1, 37.9), (48.1, 17.2), .... The ``Polyline`` function is a polyline interpolation (spline of order 1). Both ``Spline`` and ``Polyline`` functions are primarily used for the manual baseline subtraction via the GUI. The derivatives of Spline function are not calculated, so this function is not refined by the default, derivative-based fitting algorithm. Since the Polyline derivatives are calculated, it is possible to perform weighted least squares approximation by broken lines, although non-linear fitting algorithms are not optimal for this task. .. _udf: User-Defined Functions (UDF) ---------------------------- User-defined function types can be added using command ``define``, and then used in the same way as built-in functions. Example:: define MyGaussian(height, center, hwhm) = height*exp(-ln(2)*((x-center)/hwhm)^2) - The name of new type must start with an upper-case letter, contain only letters and digits and have at least two characters. - The name of the type is followed by parameters in brackets. - Parameter name must start with lowercase letter and, contain only lowercase letters, digits and the underscore ('_'). - The name "x" is reserved, do not put it into parameter list, just use it on the right-hand side of the definition. - There are special names of parameters that Fityk understands: * if the functions is peak-like (bell-shaped): ``height``, ``center``, ``hwhm``, ``area``, * if the functions is S-shaped (sigmoidal) or step-like: ``lower``, ``upper``, ``xmid``, ``wsig``, * if the function is more like linear: ``slope``, ``intercept``, ``avgy``. The initial values of these parameters can be guessed (command ``guess``) from the data. ``hwhm`` means half width at half maximum, the other names are self-explaining. - Each parameter may have a default value (see the examples below). The default value can be either a number or an expression that depends on the parameters listed above (e.g. ``0.8*hwhm``). The default value always binds a simple-variable to the parameter. UDFs can be defined in a few ways: - by giving a full formula, like in the example above, - as a :dfn:`re-parametrization` of existing function (see the ``GaussianArea`` example below), - as a sum of already defined functions (see the ``GLSum`` example below), - as a splitted (bifurcated) function: ``x <`` *expression* ``?`` *Function1(...)* ``:`` *Function2(...)* (see the ``SplitL`` example below). When giving a full formula, the right-hand side of the equality sign is similar to the :ref:`definiton of variable `, but the formula can also depend on *x*. Hopefully the examples can make the syntax clear:: # this is how some built-in functions could be defined define MyGaussian(height, center, hwhm) = height*exp(-ln(2)*((x-center)/hwhm)^2) define MyLorentzian(height, center, hwhm) = height/(1+((x-center)/hwhm)^2) define MyCubic(a0=height,a1=0, a2=0, a3=0) = a0 + a1*x + a2*x^2 + a3*x^3 # supersonic beam arrival time distribution define SuBeArTiDi(c, s, v0, dv) = c*(s/x)^3*exp(-(((s/x)-v0)/dv)^2)/x # area-based Gaussian can be defined as modification of built-in Gaussian # (it is the same as built-in GaussianA function) define GaussianArea(area, center, hwhm) = Gaussian(area/hwhm/sqrt(pi/ln(2)), center, hwhm) # sum of Gaussian and Lorentzian, a.k.a. PseudoVoigt (should be in one line) define GLSum(height, center, hwhm, shape) = Gaussian(height*(1-shape), center, hwhm) + Lorentzian(height*shape, center, hwhm) # split-Gaussian, the same as built-in SplitGaussian (should be in one line) define SplitG(height, center, hwhm1=fwhm*0.5, hwhm2=fwhm*0.5) = x < center ? Lorentzian(height, center, hwhm1) : Lorentzian(height, center, hwhm2) There is a simple substitution mechanism that makes writing complicated functions easier. Substitutions must be assigned in the same line, after the keyword ``where``. Example:: define ReadShockley(sigma0=1, a=1) = sigma0 * t * (a - ln(t)) where t=x*pi/180 # more complicated example, with nested substitutions define FullGBE(k, alpha) = k * alpha * eta * (eta / tanh(eta) - ln (2*sinh(eta))) where eta = 2*pi/alpha * sin(theta/2), theta=x*pi/180 .. admonition:: How it works internally The formula is parsed, derivatives of the formula are calculated symbolically, expressions are simplified and bytecode for virtual machine (VM) is created. When fitting, the VM calculates the value of the function and derivatives for every point. Defined functions can be undefined using command ``undefine``:: undefine GaussianArea It is common to add own definitions to the :file:`init` file. See the section :ref:`invoking` for details. .. _function_cutoff: Cutoff ------ With default settings, the value of every function is calculated at every point. Peak functions, such as Gaussian, often have non-negligible values only in a small fraction of all points, so if you have many narrow peaks (like `here `_), the basic optimization is to calculate values of each peak function only near the function's center. If the option :option:`function_cutoff` is set to a non-zero value, each function is evaluated only in the range where its values are greater than the :option:`function_cutoff`. This optimization is supported only by some built-in functions. Model, F and Z -------------- As already discussed, each dataset has a separate model that can be fitted to the data. As can be seen from the :ref:`formula ` at the beginning of this chapter, the model is defined as a set functions :math:`f_i` and a set of functions :math:`z_i`. These sets are named *F* and *Z* respectively. The model is constructed by specifying names of functions in these two sets. In many cases :dfn:`x-correction` Z is not used. The fitted curve is thus the sum of all functions in F. Command:: F += %function adds *%function* to F, and :: Z += %function adds *%function* to Z. A few examples:: # create and add function to F %g = Gaussian(height=~66254., hwhm=~0.264, center=~24.7) F += %g # create unnamed function and add it to F F += Gaussian(height=~66254., hwhm=~0.264, center=~24.7) # clear F F = 0 # clear F and put three functions in it F = %a + %b + %c # show info about the first and the last function in F info F[0], F[-1] The next sections shows an easier way to add a function (command ``guess``). If there is more than one dataset, F and Z can be prefixed with the dataset number (e.g. ``@1.F``). The model can be copied. To copy the model from ``@0`` to ``@1`` we type one of the two commands:: @1.F = @0.F # shallow copy @1.F = copy(@0.F) # deep copy The former command uses the same functions in both models: if you shift a peak in ``@1``, it will be also shifted in ``@0``. The latter command (deep copy) duplicates all functions and variables and makes an independent model. .. admonition:: In the GUI click the button |copyfunc-icon| on the sidebar to make a deep copy. .. |copyfunc-icon| image:: img/copyfunc_icon.png :alt: Copy-Model :class: icon It is often required to keep the width or shape of peaks constant for all peaks in the dataset. To change the variables bound to parameters with a given name for all functions in F, use the command:: F[*].param = variable Examples:: # Set hwhm of all functions in F that have a parameter hwhm to $foo # (hwhm here means half-width-at-half-maximum) F[*].hwhm = $foo # Bound the variable used for the shape of peak %_1 to shapes of all # functions in F F[*].shape = %_1.shape # Create a new simple-variable for each function in F and bound the # variable to parameter hwhm. All hwhm parameters will be independent. F[*].hwhm = ~0.2 .. admonition:: In the GUI buttons |same-hwhm-icon| and |same-shape-icon| on the sidebar make, respectively, the HWHM and shape of all functions the same. Pressing the buttons again will make all the parameters independent. .. |same-hwhm-icon| image:: img/eq_fwhm_icon.png :alt: =W :class: icon .. |same-shape-icon| image:: img/eq_shape_icon.png :alt: =S :class: icon .. _guess: Guessing Initial Parameters --------------------------- The program can automatically set initial parameters of peaks (using peak-detection algorithm) and lines (using linear regression). Choosing initial parameters of a function by the program will be called :dfn:`guessing`. It is possible to guess peak location and add it to *F* with the command:: guess [%name =] PeakType [(initial values...)] [[x1:x2]] Examples:: # add Gaussian in the given range @0: guess Gaussian [22.1:30.5] # the same, but name the new function %f1 @0: guess %f1 = Gaussian [22.1:30.5] # search for the peak in the whole dataset @0: guess Gaussian # add one Gaussian to each dataset @*: guess Gaussian # set the center and shape explicitely (determine height and width) guess PseudoVoigt(center=$ctr, shape=~0.3) [22.1:30.5] - Name of the function is optional. - Some of the parameters can be specified in brackets. - If the range is omitted, the whole dataset will be searched. Fityk offers a simple algorithm for peak-detection. It finds the highest point in the given range (``center`` and ``height``), and than tries to find the width of the peak (``hwhm``, and ``area`` = *height* × *hwhm*). If the highest point is at boundary of the given range, the points from the boundary to the nearest local minimum are ignored. The values of height and width found by the algorithm are multiplied by the values of options :option:`height_correction` and :option:`width_correction`, respectively. The default value for both options is 1. Another simple algorithm can roughly estimate initial parameters of sigmoidal functions. The linear traits ``slope`` and ``intercept`` are calculated using linear regression (without weights of points). ``avgy`` is calculated as average value of *y*. .. admonition:: In the GUI select a function from the list of functions on the toolbar and press |add-peak-icon| to add (guess) the selected function. To choose a data range change the GUI mode to |mode-add-icon| and select the range with the right mouse button. .. |add-peak-icon| image:: img/add_peak_icon.png :alt: Auto Add :class: icon .. |mode-add-icon| image:: img/mode_add_icon.png :alt: Add-Peak Mode :class: icon Displaying Information ---------------------- The ``info`` command can be show useful information when constructing the model. ``info types`` shows the list of available function types. ``info FunctionType`` (e.g. ``info Pearson7``) shows the formula (definition). ``info guess [range]`` shows where the ``guess`` command would locate a peak. ``info functions`` lists all defined functions. ``info variables`` lists all defined variables. ``info F`` lists components of *F*. ``info Z`` lists components of *Z*. ``info formula`` shows the full mathematical formula of the fitted model. ``info simplified_formula`` shows the same, but the formula is simplified. ``info gnuplot_formula`` shows same as ``formula``, but the output is readable by gnuplot, e.g. ``x^2`` is replaced by ``x**2``. ``info simplified_gnuplot_formula`` shows the simplified formula in the gnuplot format. ``info peaks`` show a formatted list of parameters of functions in *F*. ``info peaks_err`` shows the same data, additionally including uncertainties of the parameters. ``info models`` a script that reconstructs all variables, functions and models. The last two commands are often redirected to a file (``info peaks > filename``). The complete list of ``info`` arguments can be found in :ref:`info`. .. admonition:: In the GUI most of the above commands has clickable equivalents. fityk-1.3.1/doc/ref.rst000066400000000000000000000300611302634723100147160ustar00rootroot00000000000000.. _ref: All the Rest ############ .. _settings: Settings ======== The syntax is simple: * ``set option = value`` changes the *option*, * ``info set option`` shows the current value, * ``info set`` lists all available options. .. admonition:: In the GUI the options can be set in a dialog (:menuselection:`Session --> Settings`). The GUI configuration (colors, fonts, etc.) is changed in a different way (:menuselection:`GUI --> ...`) and is not covered here. It is possible to change the value of the option temporarily:: with option1=value1 [,option2=value2] command args... For example:: info set fitting_method # show the current fitting method set fitting_method = nelder_mead_simplex # change the method # change the method only for this one fit command with fitting_method = levenberg_marquardt fit # and now the default method is back Nelder-Mead # multiple comma-separated options can be given with fitting_method=levenberg_marquardt, verbosity=quiet fit The list of available options: autoplot See :ref:`autoplot `. cwd Current working directory or empty string if it was not set explicitely. Affects relative paths. default_sigma Default *y* standard deviation. See :ref:`weights`. Possible values: ``sqrt`` max(*y*:sup:`1/2`, 1) and ``one`` (1). domain_percent See :ref:`the section about variables `. .. _epsilon: epsilon The *ε* value used to test floating-point numbers *a* and *b* for equality (it is well known that due to rounding errors the equality test for two numbers should have some tolerance, and the tolerance should be tailored to the application): \|\ *a−b*\ | < *ε*. Default value: 10\ :sup:`-12`. You may need to decrease it when working with very small numbers. fit_replot Refresh the plot when fitting (0/1). fitting_method See :ref:`fitting_cmd`. function_cutoff See :ref:`description in the chapter about model `. height_correction See :ref:`guess`. lm_* Setting to tune the :ref:`Levenberg-Marquardt ` fitting method. logfile String. File where the commands are logged. Empty -- no logging. log_output When logfile is set, log output together with input (0/1). max_fitting_time Stop fitting when this number of seconds of processor time is exceeded. See :ref:`fitting_cmd`. max_wssr_evaluations See :ref:`fitting_cmd`. nm_* Setting to tune the :ref:`Nelder-Mead downhill simplex ` fitting method. .. _numeric_format: numeric_format Format of numbers printed by the ``info`` command. It takes as a value a format string, the same as ``sprintf()`` in the C language. For example ``set numeric_format='%.3f'`` changes the precision of numbers to 3 digits after the decimal point. Default value: ``%g``. on_error Action performed on error. If the option is set to ``stop`` (default) and the error happens in script, the script is stopped. Other possible values are ``nothing`` (do nothing) and ``exit`` (finish program -- ensures that no error can be overlooked). pseudo_random_seed Some fitting methods and functions, such as ``randnormal`` in data expressions use a pseudo-random number generator. In some situations one may want to have repeatable and predictable results of the fitting, e.g. to make a presentation. Seed for a new sequence of pseudo-random numbers can be set using the option :option:`pseudo_random_seed`. If it is set to 0, the seed is based on the current time and a sequence of pseudo-random numbers is different each time. refresh_period During time-consuming computations (like fitting) user interface can remain not changed for this time (in seconds). This option was introduced, because on one hand frequent refreshing of the program's window notably slows down fitting, and on the other hand irresponsive program is a frustrating experience. verbosity Possible values: -1 (silent), 0 (normal), 1 (verbose), 2 (very verbose). width_correction See :ref:`guess`. Data View ========= The command ``plot`` controls the region of the graph that is displayed:: plot [[xrange] yrange] [@n, ...] *xrange* and *yrange* has syntax ``[min:max]``. If the boundaries are skipped, they are automatically determined using the given datasets. .. admonition:: In the GUI there is hardly ever a need to use this command directly. The CLI version on Unix systems visualizes the data using the ``gnuplot`` program, which has similar syntax for the plot range. Examples:: plot [20.4:50] [10:20] # show x from 20.4 to 50 and y from 10 to 20 plot [20.4:] # x from 20.4 to the end, # y range will be adjusted to encompass all data plot # all data will be shown .. _autoplot: The values of the options :option:`autoplot` and :option:`fit_replot` change the automatic plotting behaviour. By default, the plot is refreshed automatically after changing the data or the model (``autoplot=1``). It is also possible to replot the model when fitting, to show the progress (see the options :option:`fit_replot` and :option:`refresh_period`). Redirecting the plot command to a file saves a plot as an image:: plot [20.4:50] [10:20] > myplot.png For now, it works only in fityk (not cfityk) and is less flexible than :menuselection:`Session --> Save as Image`. .. _info: Information Display =================== First, there is an option :option:`verbosity` which sets the amount of messages displayed when executing commands. There are three commands that print explicitely requested information: * ``info`` -- used to show preformatted information * ``print`` -- mainly used to output numbers (expression values) * ``debug`` -- used for testing the program itself The output of ``info`` and ``print`` can be redirected to a file:: info args > filename # truncate the file info args >> filename # append to the file info args > 'filename' # the filename can (and sometimes must) be in quotes The redirection can create a file, so there is also a command to delete it:: delete file filename info ---- The following ``info`` arguments are recognized: * *TypeName* -- definition * *$variable_name* -- formula and value * *%function_name* -- formula * ``F`` -- the list of functions in *F* * ``Z`` -- the list of functions in *Z* * ``compiler`` -- options used when compiling the program * ``confidence level @n`` -- confidence limits for given confidence level * ``cov @n`` -- covariance matrix * ``data`` -- number of points, data filename and title * ``dataset_count`` -- number of datasets * ``errors @n`` -- estimated uncertainties of parameters * ``filename`` -- dataset filename * ``fit`` -- goodness of fit * ``fit_history`` -- info about recorded parameter sets * ``formula`` -- full formula of the model * ``functions`` -- the list of %functions * ``gnuplot_formula`` -- full formula of the model, gnuplot style * ``guess`` -- peak-detection and linear regression info * ``guess [from:to]`` -- the same, but in the given range * ``history`` -- the list of all the command issued in this session * ``history [m:n]`` -- selected commands from the history * ``history_summary`` -- the summary of command history * ``models`` -- script that re-constructs all variables, functions and models * ``peaks`` -- formatted list of parameters of functions in *F*. * ``peaks_err`` -- the same as peaks + uncertainties * ``prop`` *%function_name* -- parameters of the function * ``refs`` *$variable_name* -- references to the variable * ``set`` -- the list of settings * ``set`` *option* -- the current value of the option * ``simplified_formula`` -- simplified formula * ``simplified_gnuplot_formula`` -- simplified formula, gnuplot style * ``state`` -- generates a script that can reproduce the current state of the program. The scripts embeds all datasets. * ``title`` -- dataset title * ``types`` -- the list of function types * ``variables`` -- the list of variables * ``version`` -- version number * ``view`` -- boundaries of the visualized rectangle Both ``info state`` and ``info history`` can be used to restore the current session. .. admonition:: In the GUI :menuselection:`Session --> Save State` and :menuselection:`Session --> Save History`. print ----- The print command is followed by a comma-separated list of expressions and/or strings:: =-> p pi, pi^2, pi^3 3.14159 9.8696 31.0063 =-> with numeric_format='%.15f' print pi 3.141592653589793 =-> p '2+3 =', 2+3 2+3 = 5 The other valid arguments are ``filename`` and ``title``. They are useful for listing the same values for multiple datasets, e.g.:: =-> @*: print filename, F[0].area, F[0].area.error ``print`` can also print a list where each line corresponds to one data point, as described in the section :ref:`dexport`. As an exception, ``print expression > filename`` does not work if the filename is not enclosed in single quotes. That is because the parser interprets ``>`` as a part of the expression. Just use quotes (``print 2+3 > 'tmp.dat'``). debug ----- Only a few ``debug`` sub-commands are documented here: * ``der`` *mathematic-function* -- shows derivatives:: =-> debug der sin(a) + 3*exp(b/a) f(a, b) = sin(a)+3*exp(b/a) df / d a = cos(a)-3*exp(b/a)*b/a^2 df / d b = 3*exp(b/a)/a * ``df`` *x* -- compares the symbolic and numerical derivatives of *F* in *x*. * ``lex`` *command* -- the list of tokens from the Fityk lexer * ``parse`` *command* -- show the command as stored after parsing * ``expr`` *expression* -- VM code from the expression * ``rd`` -- derivatives for all variables * ``%function`` -- bytecode, if available * ``$variable`` -- derivatives Other Commands ============== * ``reset`` -- reset the session * ``sleep`` *sec* -- makes the program wait *sec* seconds. * ``quit`` -- works as expected; if it is found in a script it quits the program, not only the script. * ``!`` -- commands that start with ``!`` are passed (without the ``!``) to the ``system()`` call (i.e. to the operating system). .. _invoking: Starting fityk and cfityk ========================= On startup, the program runs a script from the :file:`$HOME/.fityk/init` file (on MS Windows XP: :file:`C:\\Documents and Settings\\USERNAME\\.fityk\\init`). Following this, the program executes command passed with the ``--cmd`` option, if given, and processes command line arguments: - if the argument starts with ``=->``, the string following ``=->`` is regarded as a command and executed (otherwise, it is regarded as a filename), - if the filename has extension ".fit" or the file begins with a "# Fityk" string, it is assumed to be a script and is executed, - otherwise, it is assumed to be a data file; columns and data blocks can be specified in the normal way, see :ref:`dataload`. .. highlight:: none There are also other parameters to the CLI and GUI versions of the program. Option "-h" ("/h" on MS Windows) gives the full listing:: wojdyr@ubu:~/fityk/src$ ./fityk -h Usage: fityk \[-h] \[-V] \[-c ] \[-I] \[-r] \[script or data file...] -h, --help show this help message -V, --version output version information and exit -c, --cmd= script passed in as string -g, --config= choose GUI configuration -I, --no-init don't process $HOME/.fityk/init file -r, --reorder reorder data (50.xy before 100.xy) wojdyr@ubu:~/foo$ cfityk -h Usage: cfityk \[-h] \[-V] \[-c ] \[script or data file...] -h, --help show this help message -V, --version output version information and exit -c, --cmd= script passed in as string -I, --no-init don't process $HOME/.fityk/init file -n, --no-plot disable plotting (gnuplot) -q, --quit don't enter interactive shell The example of non-interactive using CLI version on Linux:: wojdyr@ubu:~/foo$ ls *.rdf dat_a.rdf dat_r.rdf out.rdf wojdyr@ubu:~/foo$ cfityk -q -I "=-> set verbosity=-1, autoplot=0" \ > *.rdf "=-> @*: print min(x if y > 0)" in @0 dat_a: 1.8875 in @1 dat_r: 1.5105 in @2 out: 1.8305 fityk-1.3.1/doc/requirements.txt000066400000000000000000000000161302634723100166710ustar00rootroot00000000000000Sphinx>=1.5.1 fityk-1.3.1/doc/screens.rst000066400000000000000000000024561302634723100156130ustar00rootroot00000000000000 .. title:: Fityk -- peak fitting program -- Screenshots .. meta:: :description: Fityk screenshots. Windows, Mac OS X and Linux. :keywords: peak fitting, curve fitting .. image:: fityk-banner.png :align: center :target: http://fityk.nieto.pl Screenshots =========== Mac OS X -------- .. figure:: screenshots/fityk-1.0.1-osx-full.png :align: center :scale: 80 Southern Oscillation Index. .. figure:: screenshots/fityk-1.0.1-osx-zn.png :align: center Powder diffraction data. MS Windows ---------- .. figure:: screenshots/fityk-1.0.1-win-err.png :align: center Test data *Gauss3* from NIST StRD. .. figure:: screenshots/fityk-1.0.1-win-prefs.png :scale: 90 :align: center The main plot configuration dialog. .. figure:: screenshots/fityk-1.0.1-win-udf.png :align: center User-defined function. Log-log plot. Linux ----- .. figure:: screenshots/fityk-1.0.1-gtk-multi.png :scale: 90 :align: center Data series. Older versions -------------- .. figure:: screenshots/lammps2.png :align: center Statistics from molecular dynamics simulation. .. figure:: screenshots/fityk076.png :align: center Data series. .. raw:: html fityk-1.3.1/doc/screenshots/000077500000000000000000000000001302634723100157505ustar00rootroot00000000000000fityk-1.3.1/doc/screenshots/fityk076.png000066400000000000000000002231021302634723100200410ustar00rootroot00000000000000‰PNG  IHDR ^›2e# pHYs : ëšÃ€ìtIMEÖ  ]6- IDATxÚìwX¹ÇßÙNPl`Å^PQ±b½°W,¿;{;±œ½ÝÙ={?öް6@”^wÙÝé¿?‚ãÞë –Ëçáá™Í$óN2™ä;o20˜……5!kUé<Ï¡úõ\‚Cžã’Á`0L>à8N×î<ˆ‰ONIWjH 懃 ‚ç9àácBRð³g“wSÈe …B&“‰Åb‚ p)a0 櫨Õj/1ó)’å8žçqÑ`~8xøRo?|JÐ’”\.·³³µµµ577—Édzòˆçy–esWZYžç9ƒ·†D$¡øèÉC/ –hù¾ðÕb,xÙæv}³‡ãFòǽʹ]>|•¿Ÿ«\”·söh¨ OˆGÛHHISkIžçq ŽùÑ!I’"5$IÒ4 R©T.—£Jª7¯ƒî݈âävs# 'Á7×7i‚óÝ’bðUÆü×®2MÓb±˜$IôS™†a9ž‹DðøÁZɱϳ𹋿lˆDR©¼y»®øBb¾5YwÇDz4¥ÍÌTɤ333‰DÂó¼T*‹Åb±8Žc†eYäà‰D"‘H"‘¶±”Á`0˜ÂcïÞ½)))4M³,˲l޲5ÈÓ§O/²$jµZ$‘ZyD’4ͰÇs"2•Êq£‹eŠÄ” e¦†Éi‚f˜±ñÏýýhšÁó]ˆ£¬çŽ!µç¯ù•u,kna%W˜I¥Ò6Mê·µ‘J¥Z’ò½À±,Ë2<Ëà`o×µ–™™™\.G: Ë# ƒ)$âããûöí[²dI$Yr.$I†„„œ?^£ÑY’”” ZýE1,K3,Çq¬H,GY|º6YI2,ð¼>Oï «ÛÐj™ØÑ$¥¡˜‰§†µtnakmIàµ`Ëîß'€×‚-y*»ü¥Âü‡åÑ—z_¢T™ Žeä2‰H,¡Ä’¤4ÍûwáJÛstI333¥Zñ>¶iÃz ÉiJµJ£ý— t.kocccii‰¦rÆIbÉ…Á`0 ÑhJ”(aaaAQ”8‘‘‘H¸vµZäÏó™ºòˆfXŠfX–EK³ŸS’”´2S£÷€.4ðu¦2-•Õ’Ô¿½Gƒ»¶´±²˜½þÀÇød!Å9°Ò†ÍÞ`d RöK!‹<4èÔÚ˜ø¤ÏB…"YÙ©”{ÃZµœì‹Yq›˜ú0(ôò½g,—õr¸½UïMêT­`ma¦Tkž‡¿ÿçú£¤ÔŒ¯ZDF35ÚW‘ÑÏßIÍPéî6{Ãè¾Z5¬Ÿœ¶póµ–s…|é”A%í‹Ý |¹ëÔ5Kó‘½ÚÖ®RN&•fj´)éÊù›ÎlóúÕ{µs+nk”šqúºÿƒ P½S0p ¾Z&¹Y1¼«JùÒ»´¬èè¡Òœ¾ñèNàK¥gL Ñ‹©+¤r3™™B,£J«%ÓÕªt•2#9Ybmm­¥©Dlna©ü”Lò"ŠeFšh ‚@õ_"‘`y„Á`0…EQ<Ïk4¤crD©T¦¤¤dff¢Y¤L²~ýú† ¶lÙÅ|òäÉåË—çÍ›‡’¨T*”D¥R™™™iþ-Šfh–‘rp,“š®RSúE×Ä0 DZ KSô¿Ö°±²€¨˜8ôsÀÌÕÙD±kÓ0g­–ˆÅ¥JØvhê2®ç&.ÕÖþ}†¢™á=Ûø=~á{; !%ÝÚÒ¼_§æ»¶t°·Ù~ü سZ2y °aÿ¹ˆ±UÊ—ñæQ·Z…¹VH(×±¸{«†ƒº¹+dRŸ'ôòµóÄÕò¥KT(ëàÕ§ýÚ¿ÏŒíçQÒ¾XTLüΓWi†ñêÓ¾~J«÷œ‹*_Æ¡W;7Ã¥Q¯zÅñ:_¾÷ôï!Ý[Ð9%CöN÷”Œ)+ÃebÀŠ]åJ—˜3¦ÏëȘ)>;YŽëש¹á¼ä£†è9M“)|®«)É)™éêLUºT,‰X2”ª¨ Q1 @j5é)É3>--ÍÜÜ\¡PˆÅbaŽi –G èÅa–e&W'Ã0<Ï“$)D’ìܹ388X7rÕªU§Nš[’uëÖ;PLtä¦.ÕfŽê)"D»O]»à÷$W‚¤˜Èq‘â25dŸM{µkràÜí«öqTjrû±+m×i^¿Æ¦ƒ oÇf6Vë÷Ÿ }Ï^Gí=sÓ{˜GŸMQ„¯Z¢—–¢Vì8ñôUdþ®„îúÞòïÓ¡iKך{N]Õ‹V§Š$¥f øõªW€Àç¡Bò€PzÕ+éЀE±ˆ’¢õ⣟1± k÷ž^0aа­EÁó°zÏ?ã?K­µå†Ù^þÏÃÂÞÆ¾x“œ¦4`ѹ\iˆMH¢iæSB" ѵ{lí,±XœœvãQð‰Ë÷„Á2Ã蕉+vÕrv€iúW(ã@Rôý ×;Ž_ÖhõË0{ ÙzÈ·bÙ’£z·CÄÈ^m#>Än9t~ý¾3z1ÿ½– ×ó‘S‰e–aÂ"¢jU¯Â§e|JHMOÏøø).-1X†á96%5b¸ä4¥–áiJ‰DZ¶¤½T*E:© {0 F¤EŒ‘GHè%Éq*AeOâææ6~üø;w>þüùóçP¥J•qãÆµhÑ"==]×Çqúò8ŽeŠãÅ("ð ó¹s° Ís,ÇóLNJ/P÷§°}äÂífõktuwõ½õZ5® '¯Ü"tnQò¸¤Ô…›~ø”ãi\ÙµLØî4z~.>º/Ö’SÀÎÆRï K·0° Ïó;O\B»l¬Ì 5]É}V©éJžc–õ,J$â®-]àNàóÜJãþÓ—áïbªUt€W‘½â¬Þ}rü€®åÊ8tlV¿c³ú Ën>xéȱ0“€F«åyže‚ <?qùnèÛhKs³ñ»ëÑÆÆÒlëa߯ÖàìebÀŠ]6–æpË?øìG½;4óìÓQ*­ÜyÂ@é K·Úºp✱ý ÔrÉÖC­6‡+«ûêðhümˆ$ÒRŽâ”lRÐ[‘DBR´Z«}ó*X­Lžàr¹[“f/?$kéD†'Ò2TeÚÒià …°"€I” –G c¤9‚n9^g5y„ðÝ,ƒ0 Æ`™5!š¦éòåË+•ÿšY[©R%š¦…a/4Ô¥—äÅ‹_Þ=ª\¹²$7nÜøøñc¹rå†îîî¸mÛ¶„„„+W®T¨P%Ñ•G:òˆå²$8–aYŽe8–Õé`tÞaããXôt.§5µõÑÏ}'/ ïÝùðÆEàÞÚuèÌÕÅÞž5œËï&nÅŸ®ø ŽmáÔ‘(Âäá½'ï-ÄGç—4fö*¯Ý—x{ÚXY¦+UÁ¯ö¿—˜òui̲™©>î{sô@i£ú.\·Kw¯÷¨~Ne¢¢c7ì>†"oØ}¬¦sù Ž¥½Gõ]¾õ€Z£7¸‡]1k‰D’ž¡º|çÑÖý§¹\¾¢ ž<÷Ù²oDŸ.=;´ˆKH^¶eŸÿ³,Ûqßýºµ]ìí)—I?Å%í8rîðÙk\.S³ —‰+v=|ò|鯽#úv3Ð#-CuèÌÕÝÇ|uó"lëÕïQýÊ•)é³eßÛ÷`íÎ#ó&ðÕoùÖýz1ùÏJˆçxÁQƒ¾!È/T]Že9–IJM­èTÚÂÂ’bX–aãµ™Àó q,Ã2 IÑææ Ñj ‘ˆ¢©DÌó¼X,–H$ð ú ‡LI$žã¤R©ÞŠÛX'a0LŽò}ê›eÙ#FäA˜?$h|'?~<Ô«W¯I“&,Ë6hÐ`Ò¤I7nÜðööV©TºIômæn8ðôå›ôÄ"‘¢^ToØŠ$5”VóE¡ú?o³™ü1*#éSÍæúæšH$º°w­T*é=vv†*×L~\µ}ÈÌH¦´š\æu|~è'.¯BD“µ­,ÍOøÞHKÏÀ•“?xM¤³xi£k‰¬d¹*6v%ÐOš"cß¿IŠw.ïˆÂ"ßOX¼8ô]LtlbjFf§è”Oï322xŽ“Ë夆¬[³zÍÚµ_„¿KJMONNJˆ‰Òdf&''[[[#…”Û7I°3 ƒÁ`Ø úðá.¹},V£ÑˆD"’$‹ ‰V«…™B·¡þ"xŽãD"qìÛW,Kq,Ãqä8• D!•™¡¥’òÇ™]kJØ=Øq蟂§èytnoöÀ&=Fý@v¿U Ié‡äY­ÊP«²´8ËÐÉñ%l‹•°1GsŒâ“Ó‚Ãß=|ä–®W¥&¨•©ÊŒ †aÌÍÍ)š‰ON׿ J›©LMÔªmRSS³TÏ Þ#¬‡0 &;R©tïÞ½Z­­R›p‹ÅÖÖÖH¸v¤¨ììítŸou½G¬ˆ@™ÊµóÐ3·À`Žôôœñƒ^]·î#~t»ß* E#òP{yŽB"‘|öýHÞ}L iUlžãšR«Õhââ”´t’—|ÞËq C‘Z¥R©P(d2™H$*¤/Úb0ÌÏAÇŽŒ„KÑ$)fc‹&•êË#žãX‚ÃWóê£,•”îÏ+hgMÑF‘‰¬ÿŸ—®‰Åb™L&“ÉDbqrZ:MÓ‹^‚àxžc†$I‰DbYf¦†g¢½Ëϳ,CQ”V«•Éd€×0 æG|´¶µ-–‘‘‘ƒ<€ÔØ÷¸¼0?`ÿj.륶lpC‰D™™™ •JIMæ§ðµ2…c³’LMMU«Õ™™™„D–û>#9V›©ÊÚKkÔJeª„`YV¥R!¾" óÃacm-|V_½ º ó_#àùÓví 3°÷cX0.C ƒùÑùí·ßržš-– /ŠàïŠc0 ƒù¯€T‘°ü¯¾<ˆ|ó ƒÁ`0˜Ÿ¿Û9¯8çI`0 ƒÁ`y„Á`0 ƒåƒÁ`0 –G ƒÁ`0Xa0 ƒÁ`y„Á|?8W­… ƒÁ`°<½ î­ñ•Å`0Ìφ$¯ ”JåÆM[¯_¿geiéæÖhØÐ!Mš46ÉÙD„¿,š~š  ''G÷–ͽ:väà³':´o7wî‚‚Aÿ~}>~þ¯gõþ¥×’¥>qqñJ¥rÅÊÕ9žg¾ËÓðÕ)¹áW™6uòþ‡7mþ3&&†eYµZ}÷îý/ÕrÐÀ9sSEQTppÈœy  PH·MnU]Ÿå+Q/óYÙ³GwÜÖ`0ÌÏì=š6eÒ¾ý,Z¢Re/^¼e‹f›6fÍK7vôŽ»‡ðŒO¨\©Ò¤‰ãPxëÖ­ÆŽ›S©RÅukV˜9}Ú’¥>mÚu€n]»L÷žbÂ<;W­E„™™YùrN-Z4?öŸâÅíÑ®?Vú,[¾rÒïÒ¥K=êâÅË(|Ìh¯_z÷W«ÕhÀ%·hÁgÙ’ÙslÙú—ƒC‰qcG_¾|Õpü©S&®\µ¦»Ç/<ð“'MÈñ<ó]ž†¯NAÈí ¿JÙ²eN?¼ióÖþ‡%''[YYÕ¯ç²g×öÏuÏËÜÜlÞüÅQïÞ@Å  è;lèàBºmr«êº4lèÚ¥[OµZݵKç©S&ᶃÁ`~ ˜»áÀÓ—oRbßøîãy>òÍ+\.L%8^@ƒÁ`¾ün_÷; RSSß½{wúôéeË–A>¼G9¾+ôõ¹½ëTÄY(¤U³¿sê»6Þs|öä‘••Õw{ᾓz‚Á`0˜oBžåÑÞ=|'çÿßìeŸ=yô£”–A ó_F„‹ƒÁê ƒÁ`0Xa0 ƒÁ`y„Á`0 ƒåƒÁ`0L>Èaj¶ßíë¸\0 ƒÁ`y”Eþ>†Á`0 óÓÊ#žçs‹J„½ ƒÁ`0?9:†r\ËqÕlaÄ ¯©Á`0 æç · E9/ Y¹JM2èÌéSEpƽ~éƒ/ƒÁ`0¨_þïd– ˆo¾z\Îò(òÍ+¤rÓI³~[X¨§EÓÔû¨7ø~À`0 F4Ÿˆî IDATèšÿ ÙüNÞ“¾ Ò=¿¸²b0 ƒùùÈyÝ#]'žl„Á`0 &OøÝ¾þC¯”³ÿƒk†ñžñI’ ð,‹Böìú ×cp®Z Ðó­8x„Þ{Ñ÷ô÷y›è…×dO›'ðíùC´¢øJa EéJ¢¼j£‰“§‹D¢víÚÕ­[×ÞÞžã¸ÄÄÄ€€€¡Ã½†9zx_ÏxƬ9°nÍŠŸõ®¾|~§Iòjº·nÿ}vØÊ÷f¥wßA9Þ¹í;vcæöÍ+E\¿JRbððìq8tèÚ8OiÇOœ²íÏÍC† Ù¶e%˨ÌRŽJ9yhͰ©ÇÀç÷õr›ì©ÔªŒÍK½¿U~¿s-òýÈMçªµèØæšgvÖylH¿Ÿk÷¬Eù®u…'‚óùæZnx™Ø¬Y³>}ú888H¥R‚ 8Ž+Y²¤³³sëÖ­:Ôó—þgO/ÊB4¹œj¼Û¼‚M~ª›¶l×FMLuÀQc¦æéòR‰­|ÿVºyô6|çº5u÷èW4õÐø–1ìõ‡'þaB ñ e ÿƒÌôЬ2 õùîø´mòÛúåÛœsâ|ðŽÍ>Ž-¤0ú+ÅѤ¦Èò[xíLaXyýúµ°ýöíÛ®]»“* ÀÍÍÍä:ŒIlIÈ'íŒÊ‡É$×Î?0hÚÑqÖúeëý_ÓF™q×õ;uÜåÒ…6Þb‚Áµîíàžßá#ÇôéÓ§_¿~fff …ÂÒÒR¡PH$ŽãT*•­­­···]÷}|ÏÒMø]Ôš  Ó¶\»÷Ü´iØ;”A—Þ¼y£F .²¬j‰­|ÏV:vö0æÎmظùã€ûßɨQkŸ†K¥Y-ØÊEf/f|ò[v‹˜šø‹±w1š´Ø®óBµTzA$ºäwjôß§£ï\Êó}ÚÃãL™2®®®mÛw¹yýÒu1„¦=l5Þíb– =âŒÞqíªùÀÑû6ö{ÅûøøøøøÍ]]4$¶Rp+cÇŽ€ƒšÊJ‡NÝ›5k6`À kkëbÅŠ!Æó<Çq‰ÄÂÂÂÆÆfôèÑ?~tmÔìIà“W¿Ñc'å¶«xñâA¬ðY¬þÒÌ\¡RªƒŸF ÙK†y§8W­uõü~…•½êýîŒ÷MÚÃ×ô²³%""BÌÍÍß¾};ÌÓsÿþýH ÂHà‡ngŠØŠÉÑòª÷‘ïRÒÝ…Ì4à€¡(›q ©0¯³xÓLëo6eOâÞ3A³Ý½4³úÿ&²ˆ4J“™nnGÚÈ­Q½€R¡ør 4y_i‚Á5äþ2ÌsÉ’%æææžžžvvv£G‰Džžž<Ï{zz²,;|øpŠ¢&OžüðáÃÀÀÀ|û¾í¬£ÂhAœ«ÖÚá3°NÍJvö¶‰Ñ/ŠsLM×Ö­zTž;}à!EðÜ#tsçΕJ¥R©T$;vŒçùð<ÏóÜÜܼX±bvvvAˆÅb@úX–µ°°¨T©Òøñã½¼¼ £Þºu+·]4MGDDœ8uv÷îÝ—/žÕUH–Væi©Ê»7ƒ×FYÝXãÚª÷» =ò6Ì=bqÿþ5KKK‚ ªW¯þàÁ"w~Üvæ[YA~ú÷à# xž'8–SÈq*VLË€ã4ÏIÌ/^GF5%SÿNÜ{6x}—6RKûh©µDnIˆDE“G¤=„t49’’’2ë×9kþXagg—§¾2%t5G&€6%ÊVl”14‰wL>Êfš7×ßèÑZÿ&3Ý6Âv·Fõ¾CÌ7|­O£ÑŽ7)88d̸I÷ï53SŸVjQ1=öÜ—F’JRE€´¤wpÞ?ÆÃÍÑTçiše!ÅbqóæÍe2™••z†ÖméøÏ nûöíY–ÍŸ6š1kòFäæ.Öõòqá/#Â_^žñûá·ŽªÌþûýõWâŽ;ÁÙ¶jÓ±G¨ƒDâ‰'Nœ8:ƒãÇ=zT˜!tyuø=yòD°rìØ±Ã‡g·ràÀ¿ÿþ[°réÒ¥Õ«–åÉu¤›—;vlݺÕÅÅEèÒ­ì}AJ,ûÃA...[·nݺu« ­:tèÑ£G-Z´@&Zµjåççwýúõæ…$ItçZZZÒ4maa‘ššJ’$º[s»s Cå¦8ŽËÈȰ±±éׯß_ýÕ¥[¯ì7Žñ]Ò Œòµ^!tèÐá—_~ñðð‹Å¨žØÚÚÞ:Áÿ3ÃÌÝݽ0äQ•jµ.\>"ü…¿ „íLÑX§¶³ë¥{ù1Ö=؆‡eWúTQf°­Ùó^¼®æœlÊ®KežsÕQ8úïÔvVž M À‘œ^͉DÚP7Íù¯‡¢w~j÷›ä#û¡T©Rööö‰D$±E"rô!RŽZÊ„¦›6oE’¤^`F†²[÷_ÒÓ3rëqòªªM˲Þ3f‡@ppˆ÷ŒYyjRR_ûÄ~Œ¦±ÚxôSCòàvÞ?¦påQ^—…dÆÉÉI.— Ú(;Ç ÛÎÎÎðyj¶Iäˆp£§Ý[:79U@§” µ‘rˆDbpwwïØ±ÝÑ# ¯šêuHÚê=Äëõ[ùî u­dw˜ÜЧ§§ŸŸ_«V­Œ‘é,±|6l˜©¬Ü½{w̘1µk×FרnݺS§N}ñâE󲬓““L&£iÚÖÖÒÓÓÑò ›ýÎ-£éééÇ)Š.]ºxyyuèÔ=ÿ­Ê¨”W‹©ŒçºÁ[,×ÏhðàÁ[[[;;;[[[&±%óÔlÒŽ¨àà`á Á„òÈÜÜ¢Nš‰É‘èï}Ü‹Ù~­dUÞ샅 Û™¢±Ñ7sðM=÷ÛìË‹{×òè]ËcRÓ1p3ònDò[éŒñ0>{öìéÓ§Ož<‰DêÆ™å“¦ïú'häÊÁp'òƽ~hT*“$UØuÍ:Êî%ÊQ3!?“ ­»º68yJÃG޹¸Ôµ±±þÞWK_~ãÆ—Áô7n-ýÝØgàˆð—å:>k44¦ÑÐK§Á¬F? ©ßcRXxò!™äTM3¸ÆqA‰„eY¡ú Èq˲4M3 CÓ4Ïó¦Y+úy…Ù=Òt\ÕnÝvï~ô4´Q£FG­PÞ©¡kC¿;7 ÕŠ:H$m<(‹…þ^èŸöïßOÓ´V«Íw©kEOé©–‚tÃ,Ë>zôèСCè§ŸŸŸŸŸßÖ­[…#_»vM.—#ïˆIòÂó<(ìСƒnÖ„ÈÓ§O¯\¹rÁ­lÛ¶ (ŠÚ¾};AÝ»w‹Å=zôHII)`^Ðý[ªT)2Ê̪¢J¥R(,ËÊd2äË~çš¼vÞßÙñZó]è Qk8ž‰D! ¯n¿PÍ®²«u=÷6­ýnÝÖkgíª8:$OíLž¬¤¬b _7ptz$9r$”46GNmgé¹h>;þÏËó½ky4vrZ¿?D?Ùü`{%» Îö•„T‹/7Ž'8–IKK«_¿>ª·ð>Âýsמ¾zõªB ;Þ¡q§¶ Û^¼x8¦ÐåQÖ¬£Fú³°³¯ ïµ™Ðú„qc¦zÏ4°¿P?iš>xèðý{H’\²tùÅK—À£{×óç ÛGèS´Zíü…K®\¹jaaáå9rÕk…É…4ßyÉâK/Èwrt>z^ƒõ®ì?‘5â¶ÿĹáýz¢÷(¯ƒk4MGEEqGÓ4jF„V•aŠ¢hš¦(*,,ŒeY“xrœßbˆMσ•?ê÷˜4Òû¯ÁS—Õï1iåªÕ‹Ùت‰eY]i« ês”¶ß­•ìOšº.L!š ó¢çêŒæðÌ[`+9F+H^†yóæ³³3©NÐDï77·Ê•+?þèÑ£IIIéééZ­VïÎ5y%¼<ü²Ž6ú—Zà|||V¬X±nݺmÛ¶©Õê|ßá/åæåG‹åY=¢Íˆãv=[·Lý1Zó¡æø™LbKë·Ö³&mÙ÷xäÿ–íØ±t&$™æ¦cX7·‘ÁÉ)iIIiÉIi±© à (^»Ngg§*Õj£¡@ôG¾ä‚¨Õ¯64Þel;“'+¨Ä+©©©ÿý·ñ­Yv?Ðìˋ뗩+h#hìä w£äÛ{Äi9VÄ+V >OUìÙ¦DÞköÏÒF¥J•r¯Ò9¾Ü˜œékìCÇ«Ö:pè¸/‘®rÒÓF¦T«VM''Ç+W® !ç}/ºÔ­S±B…uë7%$$ܸvéúÕ‹ÑÑ16nÑK»~Ãf•Jåwûú…ógëJ<\=Œú]ìǨ¨´2¼_A™Ädše! ‚¸zõjÆ Quä8 á Mj¾5 I’$I^¹r…㸢smõÚMÿ›™·OÀYHwb÷Ùâ\µªÕ†¸ÕªVƒ“þ÷¿Ù¶;mZµjsæôÉBò!±,U¶lYš¦=== ‚8tèz A—’a˜áÇs·aÆ|wºV ªzV©]+5š>}º§§'´hÑ¢víÚݺu333•J•––Ʋl;{ݼ‘‘‘!‹ÏŸ?/X¹|ùò‹/îݻ˖-óóó+¸Šú×0EQ$I|Ú´iæææA0 #ܹ&¯„£‡ýŽ6vì›7v„¾mï‚uêÔ©N:ééiQQïT*UHHHAlE„¿tkÞÝÿþEmÜÙŒ£ÛØ€”(zåŒjŠVÍÙûOˆ¯¯oPùæÉå‘X"–Éeé*š¦I-%‹"SÞ€£´låÊå*Œuœ V®_¿>|øpWWWZA H¡é8Ï‹sÕZ©1Ú¸³,Ÿƒ? ªËí¿5­GíׯZH¸sMÎÇÎÎð{i/$•ÆZ¡'›t)^¼xÁ-zxx4lÞyñkÇU­ZU,£¾“Ž¿=zþåñãÇkÔ¨!èT“Ë#•JC3\JbIÓÛ¶KLHAá{áü^8ÿUW}•?j¿ {aZ+¨¹NKKCÚ¨eË–+VäÓOÿ6óoØéze\³/t´¡çö3/ND?vYt‰,ž6j\˜by-ÅÈ][Í›7ï-ùæªäŒ=ëàü¦îº;ëh^$V*•€%” l<¶Î]Ö_,"â3I‹î"‘‚„`Á;fÁK´téÒqkÅ" ó±d͢ſ:|T7dÈà™”[×Yp’iרM»Î>>>Ó§O—J¥‰µ&¨=E£jµzíÚµ!!!HÜ{d¼œ*]º4äod EG¡kvo±â è:BH#ÒÎíüh¯‘qññ&WH à i‹„,Ò.*• I[$\X–ÍÈÈ(H™W+ù{ßP°"“É\]]›6mš™™)XÉQ¦Њð0 X™>}:MÓ*•Ê„VÞ¾};mÚ4a×È‘#`íÚµÉKDøKk[ǻǼ­wéí²©ÜÚº|ÃÒ•k\>uêT—.]öîÝRHsÊ\z}–#í™­+Mô]¦˜}þüùgï’oú@hh(|žá{ôÜË™3g–-[622²\¹rè¥ôMDrr²é¼¶©!ïù= xha%a9æ«ÞD†ahšah@Ú³WŸ³ÿœ2­¤îݻײeËðˆÇÆ[Ñ#“Q@»J9îíU»ß™';5Ü`äêÀ¥òZ".“<Õ¨1/žæI’µ*æ(²+'Sö65l«v’HÄZб2—£ #‰ª͸ý©TFY±(¦Ä}¹­ˆÓò'…˜êò¡aØþ5[Ö]<íw‰˜«S·¾à1ÆÝ–,Y‚TT@@Àí=¿´ö<ýÏºŽ½gŠBjÛ¶õÚõÏœ9—’’âîÞvëÖÙgŪ•Ëçyø}Ù îúßÂëÞ­Ëò,÷YÂó¼ÏŠU_ZëÈ·Q•+U4ùy.\07.>^xy­]»6 Ì5ᨋn×Y@’i×ʹuãr«6ß½{7~üøJ•*¡ÿ²T?E…‡‡ïܹóåË—‚0*Ô‘5ÁÔ²*„ñÚHoZ·®s(óª›Ëdü{>¿®ë(³ý‘þÍñB"ŒžWh†™?÷7s33Ó*¤W/žÕ¨UÏÇÇgÁ‚‚´U*•Ç-[¶L¶+W®Ì_‰Ü?ëÖ¬(T+zy1F¦ÿXV²GÈÈÈ( T¯®˜T"}ŸnxzäíÌOA¥›Ž>»¹UÏ)‡""" ÐV“›à¹þÜýëD¯?ÐF‘¹èìííÑ _¤8;vìXªT©ªU«Ò4-H±R¥J™ÖîÙÐÓjµ&èiXñâöoÞÝ5 Š>ke–aX†fHŠJKSjIuaX€ÚµkÀû˜ã­è£þšæ¸Wp D?¼}…|ɯ{nä‘E4pÀ¥d¨E"QÀ³“àM}Lz€|8–ãX†žÖ’„Öœá½òy:ÿFeû!OVŒA˜K´wÝþ‰'z{{7lØi ”´n7ÖÕIÆôÿg]ÇÖž§‘BBž'axÎT1nŒ×¯³çý±êË{ò3§O[²Ô§M»ÎЭk—éÞSôRM÷ž:Á¢–­Ú[ZZŒ1ÌÏï 3Úë—ÞýÕjµÉïw±X¼aÝš¡ÃG‡¸¸Ôݰn Z¦¿ ®#]§é½Gy\ü@wn]mÙªýĉÝÝÝ›6mZ¡BˆŒŒ¼ÿ>š©Š¦A‘|VwV‘Ú(ûûnÙåWöêbÑÑ_ð-E„ç_ÿfß;¼_á}EÔ“efªfLŸjòŽêõË j5ê#m b[)ˆ•Ù³gëYyúôiÁ­ zuóÐ4ûÔÝHúÀ¶Iò¦5ÒÒß”u® p'""¢P_÷ݲóÀq¼°Q¨’HÈ Ü z go%NûuA­:.Uª×LÒBÒ»DŽãb’Ó²ßõ&y‡Ô¢»(8.8-TõìÙCµ6]ðQ¡ÙÙ_{ä8Ža8†f´$ISÌ«çob¢ãLnm YGIiñöí[aîÝ»ÌHˆOHϹ5œæ:{ã“•Õíj@¦/ëŒv¹IcYàÙ°;çlj‰HЫËІžèü3UÊ´ôTJ« zz-0œÌìW+ÈêæÕŠa„·ÏÐÿQ³F,úu‰\ÂÇÄÄ8::.Z´èöž_²ß½g\E É®˜Eá½Ö³§GÏžº! …bÅòßW,ÿ=·^ÌÌL±vͪµ¨¯uôØI>~ÜèñãFÒyš™)vnߊ>*’§%³ó×ušXåupMWåܽs©½ï( qîùÝ:Ü Þ½{—ñµ<½¹àœï5!a„:½Áµì © ú7Çp7GTüƒÃÐO¡YŸ1}êÊU«M[eÃ^‡T©VÛ€´5I‰­|‡V²|H{GdùÆo%//+ìc*¹4}Ûwì†î\ÓªsžçòÙ”â)*!}ñ®3I±1v%ËÄj öY(0, @HÄ¢˪àFåµDW"¯IíB#ïðÊAσ e8Žç8ŽeXšf(š¦H*99=$8L*›ÜŠ®÷(..ÉH+ˆJ•*©T*¸øöÌ«Œ^µûywú_n‘½«üÏÁÁaÞ¥“ëýo)äi†ϰ p\´üÕGòM÷ê½BO‡ŽÛ>V¬\›’’HjÔZºa“æG/>(­h$¢e©¾v‘5RÀd®£iGÇýÞuõ!C-Z„þè×ëä?ç÷íÙþþýû›7®¾ƒÑ9Þ…4¦Vp|–¯švå—։╠Ã"ù’›ÐÛ †[P”–$©Ï+`Çs"BÄr,Çñb±ˆe9†f€ (’b9ŽÔREGˆ;ýÏõðЦµÒ©Ýh45ûÅ‹wïÞmÙ²åÅ‹W-ß׬]~wÞ˜hƒë\Ä«W¯ò$8bÙé IDATxäbH±‹‰Î ŒJ™ASØÙ—°²´V˜™¥Ù†Ë¯ùmÆ0<Ú8pû!CìŠY Òß¹j­aCú÷ííqàÐñAúmÞúWRbìÇË–-[#h…Aùòå:vî¦Ñh;th7mê$øÈG×i2y”×Áµ¼ê4Ä6gΜ;wîƒk…ô…5ÝIÖ…zuý‹.°‹çáæèáæxÞ¿ÚþçÎûW¿¹B2m‰­|WVœ«Öò÷tâ|°a?“©t^±SY†8Ž_»e*ú¯"l€©¦íÚ¶µdŽãd2Y©R¥”ÊL©™yS”J%H¤ÛG—LA‡ŽßD¾ŒM i–ažçQîX–%€`X–c9ä="I }¨†$©°Ð¨<9ÏŒ´"ÄŸ>kIRn>’§¼Èk‰Ð;hÏ£CÉà×—àva”˜¼–(‚ ,¡vv8ÛÑOû;::Nœ0¾¸C)°°´¶²²‘H¤i©ÉoÂÃH­ÖÄ,¥¥D„ Oî˜Å¤¥—rœ)aT”]§ ×òýöY^¢·Ïò=ÕÚx…T—Í)C‹YyÁ6F2#F™Zxçoò[ù®¬|õ8Æߘz8sòßðšÍ“ÓûÖ€ßK{­Ù<9§è¦ÑG[W.ä5EM(*™efffNÜîܹgiiéheþ¾¤UpðÓ<Ö˜üF„¿t*›Ÿ)R©äõË`ã/¢ñVÐíõkö ž¤ýz}Û‡Õ­8W­¡pöО¯v¦ð6äièS?#««‘m¦]1‹Âžg]¨­÷Mt_‘Gy}s­ÞÌ/È7×¾„ëdäFÑò4ˬ°/\Ñ<}ú… ðÆ`0ßq}n¤pé7úŒÃEƒÉ“»—þükûôiS oqÅQxýçüuy´téÒ:uê$&&¢7…BŸÇàâââš5k6dÈsÑ¢EU«VMMM­Zµê¢Eøí ó-!øl<.LÑù6ªiS·ÂÓ?âªÖ?Ä9}Õì?R›c`JJJûöíñÍ€Á`¾vœ˜ð@` Ð`~sí?EQ .¹xé²………—çH!<::æwŸ0 Ó¸qÃÕ«V”(Q¹ŽÐô݉£åõ$üмj6ƒù9™ °`@4  ° `?Ào¸hþKlظ%%%õέkΟñ÷ÂÇŽŸä9rDÀ£»þýœ+WöY¾JDá/…oråÍx§§…{;a#û^´qæìù¾ý·nÛÉÓk\dä[Î0Ìæ-uóèݹkÏ£ÇNf? îA(ŠZõÇÚN]<:uñX½f=MÓ†þèQÀ°^­ÛvêÛð¹s¾yÊW7ÞJ¥Rø™‘¡ôèÙG©T~úûÛœù:uoӮ󌙿¥¤¤çpôØÉÞ}¶lÕ^÷œs‹‡õèÙ§}Ç®+V®ò"ÀqÜ¶í»º÷èÓ®C×E‹W«ÕÏ–G æ?° € €À À6<¾öãì9ßùófÛÙÙÙÛÛÍŸ7[¿tál“& …••ÕÌÞ÷<Ì1¹‘Ñr"Ýó»ñÕá¤'Ožþ¹uãå‹g[¶l±rÕ¸gï¾È·o÷îÞ~âØÁøøxÃܱsORRòÑÃŽÞÿéSì®Ý{ üwŸ•^ž#®]ñݺyÃëа<å«u«–ç}/êòùíÛYYYý6gþ€þ}}Ï:îTùòå6mþSˆ¶wÏö»w®ëÇ@ü àýï>~ìPRrò®=ëÀþ‡ÂÂÂ÷ìÞvþìI¹\þ×¶Ï–G ƒù¯””äèXm;9}Y/((xÐàáu\:W­UÇÅUï½ì¼F+8³fMw(QB¡P Ø?üM ¼|ùÚ ï©%¬¬¬¦Mdø×oÜœ6u’­m1;[ÛéÞS®^»aøàr¹,))9%%µdI‡ß~™§³íׯÏéÓç8Ž–eÏ»0 _8°owƒúõär¹¥…Ÿ±£?’L™4ÞÆÆFï8âO›–•ï©“¯]Õׂ¾.y{Ov(QÂÜÜ|üø1wîÜ-x¦ôÀ¢ æç¤,ÀÿÙ;ó¸¨êýÿ¿ŽÞTF¸Ê –¢)•–p¯ÙÅ›¹e!)æ½póBI*©¤ôµrcÓ\Î9墘–}ëþ¬ô–]ƒÌ¸a¸‘ŠVö•Ò4pa² ÜÏï3sæÌÊ0 ³½Ÿzæ3ç|Îç|f9¯yÞK>ð°˜ ¼ < | <üF³ã7téÒ¥¦FÕ«×ÝjjTRûK3çÌŸ—ñèðaæÁ‡6{¸»9N§?ŠE“Ñ¡Cû[·niµÝÅ‹aaÝmìA­®ïÞ½›öÍÖ]­®·ÞùÒ%üûÿýÞûÿn߾ݜY/>ÔöÑöîu÷Ýw÷Ü_zà±~ùå¾?ý)òÎ;»¨¨¨\ÿÖ;?8yõêUº)‡„„˜öceÿîÝ´×Ò½{·‹²E7‘ÚÚº §H¥¹(’GAø«€b`$0 8¬FK€`2ÍŽß÷·¥Ë³³—/aé²RûÕ«×Ú·kß¾}ûšÕÊUyz%Ñé§«ªï½'ÜúnöѶmÛ«W¯uèÐÀåßo^Û…„üüó¹ÑË JeðÏ.ô ðóÏ”Êf Ã÷{àþìåK|óÍ·ËV¬l©’x:ñŸ›þýác#ý¸`kzÚl±qÑâW_|ñ…AƒþÚQ¡hjjûwëXÙ_º– ~ Q* Q¾ýÖ¦nò^”[³fAxOy@°è ¼4¹ÀšbÖ̃;w>"æÉ¿ýã¯(µç¬XºlEΟ8é¹”AÿUjŸö|ÊSãž–²YÚÍ>úô¹ï£ÿ||õêµÚÚºÜÜæÅÖ˜1£òÖ¬û­¶¶ñÊ•7Þü_±1((èì¹s¦;Œ~|Ýo]ºt©¾þÒšµoÄŒŒ¶Þ9ÿê²sçÎ߸qó¶p[2)ÙÎü|ùò§Ÿ~¦PôísŸØxíÚµvíîh߮݅ ¿¬È^Õl'Vö_»n½x-¯¯}ó‰QÆy’þ—³rµJõó­[·NWU³ÜkN¹(9ÆÖ#³ûA^GGÝï¿+1̦PÒÔøíÛ·Ï^±4{ÅRú™*nDG?ý˜´Û„gÇ‹/¤>ÿBêóR»¥Ýì#3cîŠ+ßßøïåÄ I_îÝo}ÿ)““ß\ÿöä)ÓS&OÒá™ç§Íhjj2òΞ>mêê5ëž? ÀÈèǦ=?ÅzçC† Êœ·àÂ…_î¾»çâEó[z- Ã$$Œ[·6w¥>ý+ó3×¾±~á"¾k×Ðg“ž)ùr¯õN¬ìÿ`ÿþ“žKijjŠ~ü±”)Ï8qBÒ‡›?š5'½®îb¯»{>÷ÜD§\”ÁxeÍ¿¿«8©¾pöÛÏ7Òg‰ ß`° (4lŒ>¤Ùñf¤¨{‘{ûDœ>YéÆñìß»{êôYÞ˜žÑ:ß|}0=k±]—xQFo!÷õ¬¯¯?sæÌ§Ÿ~ºdÉPäA¾J0Óô×*°„¦† ˆæ ×l‚ |“"À´ôãDš‚ l€¬GAA$‚ðWÊšM„ ÐâA~…æa d="‚ ‚ yDAAòˆ # ø h>îöW/®45A4‡±ï‘¼–eÐ&Â{¡škDëðèc1§NTÜÛ'ÂÇ®kèðè´ÌEþpQfÕ!ÂaCŸÈ©›6;¤iyÝ:`¹¬æÚšÂ¸7s7áthq ÔF:^G`C©æA–Ø¿w·Ùv ì'Â79Ôã#ÎÜ(¼¿ØP_  /@¿ñ}ÏYÞbFî©â‡ð¬ØüHá›ä UÌùº©ðþvÚÇl(øZª¹æ·w»VC²F¸k0n€o@‹kAø|-€¢>íb’;=3ȧù!‚äA~ ˆ¢™ ‚äA„ž¾¯|÷öµ¦¥uŸnù½{Ãí|íUà; ‚¦† ’GAøe@ÔÛ+‹ú†g=qäøµ¯6\úè oÒôAòˆ ÿdèùK«÷¾ºtçë@¯Ë·Vg¼ ¬¡©!¢9(k6A>Ê[Böâ—šô/…;Ñ,ÆÖ#FÍA^*æ„_|˜ ´fg;µûõ™ö GÍqß74K„[ÙòqAZÆ<o®ÿßå+V:½Ûÿí Iv¾<"‚ð^m†ZñlèK@{䑇;tè”6wöÁ¯¾–žZº„ïÖí®€€S&?§Ñh^ã‹S¦N./×j»ü‚O-zå®»îìØ±cFúÜ;wyûÛ†JÒᛌBÿ@¾-Af$¿aÎì—Ÿ™ðØcŒú‹ÔxñâÅž={ˆÛ½î¾»®®Î¥c šeËsìÚ½gnZæÆ÷ÿßPN2µ$É[îëiºƒi·öÍÆ‘#G³sV•WT655Á0³OçÎÅ€€Foݺ%nÿò˯£cÿ¦ÿÀyð;Y‚ðbÂXcÓ‘FИþWÙhöü‡;î¸#7gù‚…¬Ü'&$$¤¦F%nŸ;¾K—..éß~SÚ©ÓOþT^ôù§=zôWÖ†šØìöÝw^·c6^š9gâĤ¯|yò§ò£ßkàÖ,]»†,-‘üÊOþTNòˆ ÂmÚÈ0NaÓñ´âæOÜwß½Ï&=ÿºTj;6véòlµZ}ñ¢úµ%Ëÿþ·']=†ï¿?Ú¿ÿŸ†ùþû£QQ¹±[ÓÙ¸zõZûvíÛ·o_S£š¿`qKÇðlÒ3 rçοuëÖO'NÌšîkòHA'‚ ¼BU•ö0O\/ ©"%yÒ„ZÙ ZÚœY!Jåã#c£cbïºó®9³_v¹<:rDLt$á»±[£ÙÈY±tÙŠœ??8pÒs)ƒþkKÇ:ýùÿ2鹩‘þËܹY£GÅxû»…ðÊšWqR}áì·Ÿo¤ÏAÞ‚±G¶¤¸³’IÅi(d_y†ÚˆQÐ4zFþ7÷ö‰8}²R¾á^öïÝ=uú,AÜ5·À»§ @}}ý™3g>ýôÓ%K–€\³ ‚ð^T¼^!ÉíFâS"§;‰ ‚B¯Ha’GAx¹H’ #Πœ‚  §•P’`Òª"Zb#Â2äšM„×ÂXŒ ´‘ µ‘D $°L"«÷«”ç$‚ yD„o#@a)ñ Ã…DžB"‚äAA„£òèŸÿüç?þxíÚµo¾ù桇´ ‚ƒƒwíÚuõêÕÝ»w[i$‚pa¨•9E'nI¦#½¿ ª` r=ÍAÍÒ¼kö3Ï<“””túôééÓ§oÙ²¥oß¾xž?yòd|||nn.Ïó3gδÔHáZøZ°±ú‡Ü8p@‚6¤MÅó0IÀp¡§ a£ø5bÿÞÝ4Ïœ ÏäÑÇbì—GO?ý´¸ñî»ï._¾\Ü;vìèÑ£5M^^^qq±¨„Ì6A¸^!ë_ NöT‹^Å#ŒåU<)sëeéFx5UçËíƒñªg­€i »È#‰9sæäçç‹Û={ö<{ö,€3gÎôèÑÃJ#A„+…Q-°±Úú²L¢ù2la, [c¸P«¥ˆŸÜꢥË#y-¹öœ6mZ\\\LL MA„|YÍ2òÅ5ÇRPl ­/çÞ>2’Ó'+Ý;·À]¬ÊyÍögÍw¶ú¤­òȬ9nîܹÏ=÷\ttô¥K—Ä–óçÏ÷êÕëÔ©S½{÷®©©±ÒHátÌ£•«œ^ò=BOÓEþCZæ"[vcfÖÜyVvh~qmÑ¢E‰‰‰ÑÑÑ/^”·oß>wîÜôôô9sæYi$‚p6 C± z’Aº#Q…‹{‰¤( ŒábNÁ –¦Ô—h©Ï Õ_÷=š-6g‹Ózóý¯¾úêŸÿüçÚÚZAAèС–eûöí[__ß·o_–Õ~W™m$‚h ¸­f<†ëâ×6é¿‘T›XƒÕ4n+MAF4o=2«ÄÕjµ©’ÙF‚ ˆÖÐFzk€F«nð#MTHaÉ23’QŒáC,Aó6¡… ×|Â"”5› /C^ƒV…PÉ$@—Ê(œ¬×A€Z­žú|ªZ­&yD„¯Ã׊ÂH€ÖBªõ$†‹@i! vîÜ9jÔ¨€€€.]º$''×ÕÕ9Þg]]]Ïž=-ùE™m!+++88X©TΟ?ßn)Æff´§NLû¼téÒøñãCCC9Žsú˜ESÓÕi©/îß`Zê‹MMWIá"ILzÃÌ×÷d# (3ÔCÕ¼²Êj@8«5/%‘‰0êU«æÌ™SWWwìØ±Î;'%%9Þ'Çq©©©-:äwÞ)--­¬¬,//ß»wï† ì>» £ÙÉw^»víôéÓM;œ1cF@@À¹sç~ú駪ªª÷Þ{Ïécvœ[·nÍž›~ôèŽýaöÜô[·n‘<"Â`cãPÇ"Ž…s‹{²÷©æ(a¨„¢hî‹ìرc̘1;v ]±bEii©ƒ?~¼¨¨(--­EGmܸqÉ’%ݺuëÞ½ûÒ¥Kßÿ}§_©õݸqcíÚµ³gÏ6}ê¿ÿýïêÕ«•J¥R©\³fÍ»ï¾Ûjc¶W_[¶gÏ—ÒÃ={¾|õµe¶þú$á¥ÄÁj:Çj›3 T|0ÏÎ;ì`'éééÇ´è¨ŠŠŠjõ|TTE…ý9ÁCBBÂÃÃ'Ožœ™™Ù¶m[[öÁ ><,,ÌÌ'ÆÐ U^^îô1;Ï-â¹EvÞÆôš-™à‚ 0‘Û·oçääddd˜}v̘1õõõõõõéééγ'ÐÆú Fáù|ÆA³&ФHÞÈt¤Ö¥…Ôº•ÑœͰoß¾§žzjË–-}ûöu¤Ÿ´´´ÜÜÜ6mš1F˜Ú&%ÙÑÐÐäÈ0Ú¶mÛ¿ÿÍ›7K ^–&òÉ'ŸôéÓ§_¿~fŸ}ë­·ÔjuXXX¿~ýz÷îÝ¥KWŒÙ³äA„‡ÆB…P°±…²„×qœÁÒXœ¡¯‘¬¼HÚ4‘ëi2 ³lÙ²e„ QQŽú©=z4&&Fn%²ñÀÈÈÈÇ‹Ûeee‘‘‘N¸å·isûöm[¶|ùò¬¬,KýtéÒeëÖ­æ—_~éÙ³çã?îº1» ò="ÂË´´eeµò°’ÝÑÈ)[ ÞÀ“"1ùº{ù€Õ«W¿þúë»ví²d;iF…Þmw\INN^¸pá'Ÿ|"‚ RRRì@RRÒ‚ xàsçÎÍš5+!!¡Ù}ñÅC‡5êJÚmÊ”)<χ††îرƒã¸;v8wÌbKÍ’GAøš6Òn£8 (D¬ 3ÐÄ™K_$×F¢IIH€Èõà1œF€"D¶áψ‘\úŠ÷ ’KM«‘ššZUU%#55Õn©1nܸ &TVVÞyçO?ýôÒ¥K›=dÙ²e™™™Vv2dÈ#L< 7±ˆB\¤VßV°°¢uØPÙƒ2%“ ŠE!t¸.2ÉRz#½ IDATÏfÛ†ÉÉÉÉÉÉq𤉉‰‰‰‰-˜¥\ÒnÓ¦M›6mšëÆìöï!yD„ßk#n+$»Q u梸H‘ø¼™ÜaÐæÝªÙC4«>ÕS#„\³ ‚ðT†ö BNŠ_¥s!*à%€a¬lAÍxy®VÞ‰$‚ $ÈzD„£/C  šG”[QsE”BÛ·Þ”´pd="ÂkCú ]à?Í@#pÅ4ÃA˜—G”5› ÏFâºXjÅœF…¼a(~b¶TbV®ŸŒ´”|yNµÉØÔ¤k\ ¿Äxq’eáÚHD¾ Çê’eß“mðD«,À†±¼¬[œ#pÒ·\+ÓF›!ù‘H¢oäôÉJŒgΆ/È#‚ ûu <ìfï_Ï¿yÂøfíâ|10ÎJnIÂ+¸·O„çh#÷ÆípŸ8«#ò="Âi¬Š%p8ì‚ï€w,G´‰Å­Œž«&C‘OÁ´š1‚äA®å hÖ]×& ãX·’ü’¬Ö©èžlã' xùÒX >l&É PÃ#,™G5M3¤‘ 4ÍGºáûÐâAN££î'×@ P:Ø/ ÔŠY£P+V¢k‰ *[REFYR9%Ô®æPzá|ûlȃ~ŠRG–!ëANã0B·-ÝyúÎòCm¡%5“`P^-È{?Ïæ€GR¦û ¶F®ÂY¹¨¢à5‚ Há4r€™&¯Kî9 ˆ“'¹æ¶šÝÍld~4Xù⛸݃…`(Œší‡ðŠŠŠFŒÑ¡C‡ñãÇ«T*Çû¬««ëÙ³§%W'³í‚ dee+•ÊùóçÛmǺ¯•éÀlôÍ2»ƒ³ÆLòˆ ߺ¯1&|Ǻ• £8Ô‚ÛªO–Ÿ%×4Òö­\ããm9›™vB É?ÉËËKKKûõ×_Ïœ9Ñl=W[à8.55µE‡¼óÎ;¥¥¥•••ååå{÷îݰaƒÝg·’ÑÐìÀlÉ€höY'ŽÙíïA>A»ÕLòzà1œF! ©"¿f÷îÝÒvFFÆòåËìðøñãEEE•••‹-²ý¨7.Y²¤[·n–.]ºxñâçŸÞ¹WjßÀÜ;æf:<ږ݆¹qã:É#‚ Z‰)ÀTàO@ P| ¼ w¹02Cø‘`M´¥’ TóŒäÌdaÁŽð[®\¹²nݺ‘#G:ØOzz:Çq-:ª¢¢bàÀÚ7mTTEE…Ý ihhŸâvCCCPP#ÃhÛ¶mÿþý7oÞüþûï[˜¥ýmÁ¹cö,yDa7F6ú?vC\t¾(ÄòŸìàGÚàŠ” Vàké…#Ì”––öí·ß:ÒÉÑ£Gcbb$£ƒí¦‡ÈÈÈÇ‹Ûeee‘‘‘N¸å·isûömÛ&ßß]c&yD„×ó9° ‚•@1 ¸ìÄs„7#z¢ísÐfæ· ÿcâĉ•••7oÞ¼páÂÂ… ìHo¦V"LNN^¸pá… ~þùç Lž<Ù¾$%%•——ß¼y³ªª*%%%!!ÁúÀ,ío‹¶sÖ˜IáS¼´ÎçNÀt€Ýe2o!"l,¡Š×†ô‹È*¦ £ð=ðÚF©EòÑ_ 6÷dƒÇ@ã͹Z'Ÿ””0`À€‹/nÙ²Å-ÃHMM6lXDDDddäˆ#RRRìëgܸq&LxôÑGûôéóÆo8e¹ÙI’Mγ'@‘kA8KÀ³&SìîŽ …>Mvn+ 3íTeÉý²•`è¶u+kzl¹“¨¢yv3Ë?˳ ˆ9¾“Ñ+HHLLtJ®#S,™ŽÌ¶3 ““““““Ó —#€•ý廹tÌ$‚ðAÂtZDÅ[|ª‰gáèe@ŽÐ @P=5‚äAž©Äí=Ì-­°|ÏZR0WaMŸ,»9J^bš a#’GA!¦rB,þj*’dQ÷a¬¡=‰U‘<¦,ÊøøÄlÛVÈ#Ž5pf²7½’Þü&$ß1Âk6AN£Xù8î[€,z°` FÐô°Ù7[ lhjeuÖ¢€(ðÅà‹µ ŒB¯ x.Ò]o˲ÊO,`3Ëg€eyx¿Ö;;J‹„ÿBY³ ‚p\ãÝ_¾ynõcXû‰6;œ…héÁiwSqÚ²0NB/“T5*@[(n±±W¬Í)FrØ÷ñ‰³:"ß#‚ œ©¤…³Ý#Ç2G4¢û‘‘H ³qg¥CDäeB k夦ñü–j‰ÈóűrÏò,äÕE¸­r…¤«$ƒ’WÁ´š1‚äA­„ÞØÃõ2s3RH:Q¥û+ «ÕF|±íñü°9¤_ÅkER™ ;“B"ƒ×‚p”0Ö‚62 Ff¤Î`7yà~ ·¸­à¹–JÌcÊL%‹Ý¹ŽÊ,8Û5áqDÛÞ_B¦#Ây$ŲÉfÜ‚ƒƒ?þøãáÇ8p 11±¾¾žæ— üG­‘ˆãâY"Vq¦+Ü¡B¬®d­žB]ââ:—^¦z© ”…• J,RÌ{$m[ƒ'­¯)ò="?¥ùÅ5K«³¦ ·<ÏŸ†a:uê^YYùÑGÑg‰ ZÕÀ1@ ¼l7SЬÕ룉j¢õ†ë• }ƒ_Ä /£ÓLÚ£ÝwËëkƒq(Ž‹äMÙ˜­N€Ï3‰,³Em¤]ž+Ðþ‰kje\¸0·’]¯¿ª+⯤§§sàÆÞ***(nGEEUTTØ=€víÚÝÿýË—/¿uë–íÛ¹sçàÁƒ[46Kçò:Êš][[˲ìå˗ŇçÏŸïիשS§z÷î]SSC0‚pOý ° 8| $8&œ × 3&ƒOz¢GÀL,{Fë$ #§ì8NÁpZ…Ä$²Ÿ¥3D™qŽvdµË|mZ%Xo¤µh„|¥ÅñCöìÙ£R©&MšäÒތÁOÚ5ó   †; Äbo·nݪ¨¨˜={öo¿ý–——gËe9r$==}ûöí¦OY›¥sy#ùuêÔiþüùGŽˆùذ}ûö¹sç*Š9sæÑgŒ \AGèÃ͓π~00­¨b€pàžÅZRÛ ¯4sl§`Y&‘òy!Ÿ×»åg‰;HAjök#V÷gÔ(¿E±¡òÚ´„’–––››Û¦M—öf´VcºtØØ¨-\ØÐÐäÈ0Ú¶mÛ¿ÿÍ›7K aÖ/sß¾}O=õÔ–-[úöíkú¬õ±™žË7å‘Ñ‹'oüå—_† 2aÂí÷ ËöíÛ·¾¾¾oß¾,KFi‚p ¥À£òo1 Í4D¾ C­ ¡F ÀmÝáß^ûŸó¡¶öÆ$² 4ò„CÒRšø'ßY­¶¬Àó™`WÒŽ üZ\#/ýy$md ËȲVŠÒ-¬üϾ³G™l;Yꤘmr%{HZ_Sƒ§´~cˆSú¬««ëÙ³§¥Þ̶ ‚••¬T*çÏŸo·”¥Ë)**1bD‡BBBƯR‰þ„¸téÒøñãCCC9Žk¶[+çêÔ©É#‚ Z É{d Swl³b(lX­«Íªc%xQEé¶ÍŠãí–PDó3JØõôNógœžã¸ÔÔ–eçwJKK+++ËËË÷îÝ»aÃç^N^^^ZZÚ¯¿þzæÌ™ˆˆ©”ìŒ3Î;÷ÓO?UUU½÷Þ{Vú´r¢µk×NŸ>äA­Š˜÷(Ý}y´1ke(ܤW7Œ‰µÑH (CªãÁêþµª–¢Á–€_ ~¥ùÃ;º¾g¤h(¶‰pèÓzüxQQQZZZ‹ŽÚ¸qã’%KºuëÖ½{÷¥K—¾ÿþûÎÕîÝ»ãââ:uꔑ‘ñý÷ß‹íÿýïW¯^­T*•Jåš5kÞ}÷];:¿qãÆÚµkgÏží½¯ÚL¥ŸþKRD„gÓúyäÙàÆƒâ’y1¿¢¬R'bléJ\ÀŠæYˆñbV«£[ea+ŒÅOà¡O^Fï1ÿ$$$¤¡¡!<<|òäÉ™™™mÛ¶u¤·ôôtŽãZtTEEÅÀÅí¨¨¨ŠŠ ]Ε+WÖ­[7räHS ¼¼ÜŽ3~ðÁÇ óÞ÷€±õÈé ®Aø Ü8q(ŽK6“îèHËû‹æ­©Ÿæãù[Ž˜8[.ŒôÛ¨¥WØŸáâÅ‹MMMùùù»víJOOwè7Ìž=*•jÒ¤IÖﶦ7ßÆÆÆÀÀ@q;((¨¡¡Á—Ã0L```^^Þš5kÄ–1cÆdddÔ×××××§§§766¶ôŒ·oßÎÉÉÉÈÈðê·-®„O|¡»>ûQ«×WÏ韊³A±Déþœ{Õ k®#ë0l¨À×"œÜ±ý”¶mÛöïßóæÍ®j¥¥¥åææ¶iÓL…SS÷ ÀÀ@Iš444¹ârAøý÷ß_~ùå©S§Š-o½õ–Z­ ëׯ_ïÞ½»téÒÒs}òÉ'}úôéׯÉ#‚ Ü ãâØþ0ÇD‚¤Š¬ø eð¬ÞI·W†èÁm -¡(éâZx”,ůùmÚ´¹}û¶#==z4&&Fn%²ñÀÈÈÈÇ‹Ûeee‘‘‘.ºœ   ´´´o¿ýV|Ø¥K—­[·j4š_~ù¥gÏž?þxKϲ|ùò¬,¯¯âLòˆ '"Û SEÚ(3VïOm–ZFP&:kóZƒ$Œä6'k5hmÖ-rU$n«d½j·7Í08&Á X ½â>LRRRyyùÍ›7«ªªRRRéÍÔJdãÉÉÉ .¼páÂÏ?ÿ¼`Á‚É“';÷r&NœXYYyóæÍ .,\¸pðàÁbû”)SÎ;×ÔÔ´mÛ6Žã/^¬ÿfƒ¶ûâ‹/†êíoJ ID Pqš0N…l\¤VSòÈ #½­È¬âe ‰ ݉ʀ °F¨Ì4’ŸÕnF$Ù¹¦âÆê´_ v=x ù&‘òy&‘UÐ[À÷7nÜ„ *++ï¼óΧŸ~zéÒ¥nFjjjUUUDD„¸’’âÜˉOJJª¬¬T*•cƌٲe‹Ø>dÈGyäòåËC† Ù¶mÛ<`¶[I*‰’ì[¶lYff¦¼ H„—ä{€ÙÀ»ÀÃÀ×À3Ào®SE¼~}­†“ÈJÂHR0r5SÞš…Ū|)“ ,ó‘c¬k/SEÕHü›ÄÄD) s±d:2ÛÎ0LNNNNNŽ‹.ÇRû´iÓ¦M›Öì8-]Kii©o¼ H„—± (F³€ƒÀ:`4°È&»î¬l(P«ÒG¼#.’/¬°j¨áe:¦…‚£Ì†ó'² yØZ¡å±1l¬À3‡ü­òkPS97χ꩎A¾G­Êdà_€`à?@ð;°¦©!læ hÖ]×& ÓŠcÐ.«XU ¬.CcsZ¢ÄFµa¡&ð`ÌÊ/Û:+ä­ #óð$ŒÂO ëQ«ò :¿½ \zéŒoOÓì¶ÑQ÷³æ @Ì…R ([åìRH«W%²’d–œ¯­+¤hû"Ôø–©"Âç(ǹ߳ïn’G^F0 Œzê¶ç545„ÍF…dÁü}JWž4 µºdÙ ÓgõÂÍ$¿¶[!•Xðòn ¸­ô®#oÁYI­©¨H«r | \6ÌR£¡©!l&˜£“G¯K\yR}! ÓÄq Smsõh[„´Ê-×[€»âè£ùA@±öûAPЗ"Axú}vÿ—È#’D.% ØüXäs¹'l§(2iœØ*§Ö–¡•t’ËŒ7ÆÞH¼«’è£Ý¢ QƒwP.âôÉJŒgΆ7B‹k­ÊQ`4ÀÑ@`ððð.M á±°¡fU…EX³†ÔUkY’¢ù%ìz†ÓŒ‚ÈÂëÜÛ'bÝÚÕž0’'ÇÄnÿ¢ØŸ@òˆh1'€gi¸ ¼¬T­¢´õY9…´¾Ç)äK{d5h%¬‹]‚x@¬¶æšîRE3Ùô–ó.fÎJkÑþk__E“F˜Býáeü8ìÞ\]òQ^»^€‚aÇ)ŒLGâBØ­6r§« ¹‡DA<"\F_à;  øèì®ß45DKXD¥ÀV h…âFZÓQ¸µÈ2;âù=Qö•„ÓÛÍ;4ÍÿÉ#á  Ž_ßBàMš¢…ÜÞ"뀃@¼ëO—Ì›Š$ðSŽc ŠÔšAª¼&诚 Ó„C¾G­ÊPàà*ð:À««À ‹¦†°‹Û@>Œ^>svÿ*ÄŠY ²A&ó…²R²ZÇ#yd»^ɷ͸œ'Ò_Nä!85‘á±té:tèðnÝî]»úÍ×_;Vá`‡ã“&™uyæ\³íC‡üS@(ÿñ‡¯¾:`ß©_ž9WþP:QïÞ÷ü%jà]wu»qãÆùsgØ×ØØhºÿõë×ßþß7¬÷)ßGzÊCÜäIy ‚¹)É+á __¸¢_YFD£tGÑ`ȶµ¡ø|+}ˆZ3‰¾ò·ÕlVLÂÇèÜ9xìßâ”î-**ìÐ!àáA8.4¸üÇÜ‚•ð?ý©÷î=>üà}€yrìß##ÿ\Qñ£}g7«T<ô—ï¿/SÕÔ€3æïùùíüàƒYïÐhñ)#ýäÐâZ«r˜ ´fg¹@{`ð M aûÝÚ šÞ Ý‘È Ûáí zd𷇾:}úÔÍ›7Jöìr°Ãà`eïÞ÷|ÿ}Y‹Žê×/òë¯^¹råʕƯ¿:Ø/"Ò¹—¹íÓ‚êªÓׯ_»~ýúwßíjœÂ£M›6>øÐÑ#ßYÓ6ìã¥PÖìVå%` 0(†ï¿•ÀšÂaÆV9Q¡­&‰i!-^_ ¶ ˆ’·© ,ÐmÓÊš/Ò£ÇÝëꦦ¤¶oßþLuUIÉîk×®:Òá°á~{è«›7o¶è(eHÈo¿ý"nÿöÛ¯JeˆÝ˜6}F»ví~ÿýò±Êв²ÿ3*KwÇwôð¡óçÏuÿý~þY%®¸Y–}|D‘$r)'€‡dGÑŒ-§ ð0øHNèÚœmX cMÒY^ë¦,^”Ü IŸúH›³ *)$ÒF¾J@@@çààÍn0üÑÇ|dqq‘ݽõìywÇŽAÇ3j7Z~’?×§î¸ãŽ7nˆ-7n\o×®}{c&$¤ËðG P(J÷ï5:oS“&?ÿ?Fb *ê¯Û‹ ­ôlË>¾#‚ðpVÇ€x`°xF{÷v2a¬6˜_€¢TdÃд/ÖÖÐnK!ý,|G3¥ Ô¯åóL"K¥E|˜7n”îß'ZŒJ÷ïâ@é>#ƒ Ýw̺f߸qãŽ;î¸~ý:€;îh'nØ uuµ;Š·Oœ4Y.Ö­]Ý®]»|(&fô'[¤ö{ïëséÒ%µZm¥O[öñ^È÷¨U¡¼G„ã< ¼h€m@P`´öã$ä5hUœ&.’/¬00‰akjðjÖ×$B ¦ÄÔ“Oa¦¾O]]­‘°p¤·.]BÿñTÂË3çŠvÛ}–Õ/víz—¸ÝµëjõEÇ/MÓ5¢ëׯÿ}ÙwÞ%o8ðá²ÃßZ`‡? IDATïÍ–}H6AyÇé½›ô`2ð™ËÒg›uÊŽ+†­¹Åvâê°µ0™”Æ |1‰$?áXeŰá¶oß¡}ûÆ8s¦Ê‘ÞÖ­]-ý¡%áîÇŽW <´cÇŽ;2ôX¥Ñs£cdž„tiÓ¦M§NbbF:¥]5zŒRÒ¦M›Ž;>2xè/~–éÕ+üæÍ›d-"rmgiŸ×ZÊ{D8N)ð¨,Œ´FñÉfãù½3ãQ‹ˆæg€ÖÑü†ÊÊò ?þqRò”;î¸CtÍvË0Êü¡S§Î&NP^þƒÝQý§OŸ•F£9uò§¯¿>(¶WUû¤RríÚÕ3gÎ|ñ…Þ¿jà_þ®ìÿ¬wkiIB‰Þ›ý¨yy$Ùå¹ààà?þxøðáHLL¬¯¯·ÔH˜þöå=" H3Ìr´œ\W“QHU´éŽÂYTóãù½\<ˆ!lf}Ï£ùô®ó7}óÕ¡o¾rz·–´‚¥öƒö<°ßÁ“ž:yâÔɶ·;!Y§-ûx5Í/®1 cºTÉóüÉ“'•Jå‰'xž·ÒH¼×)ïá0;Ñ&«¾äÄÆŠ™²¥TÚŠ"-ú1 Ã‹¦WÅlGó3JØõÆ;q”ÒãaÍÿ„#òÈ,cÇŽ]½zµF£ÉËË;v¬•FBÎK@gΜ¢¢"+D³PÂ#`cÍ4ðR²ìh™Zi{*HA€[­>¶ #ù¶µò)÷d£ H` ”;Ûs8}²òÉ1±2·Äs¦¢5Ùöé'­'${¸d!À²ìÇ\___ZZš˜˜¨ýv5×H„i£0NQÃA4…q U¸ÖïZÒFG€@‰uÅ/®£¡Í¥ëõ&ªuH–¤\,¾F ÉC¸·§ 8}²Ò½ƒqûÜG+Ê#³ßhjµ:&&Æ–F‚ ¼n+€(zpƒ€Jr< gQmõXmÀˆ?¨tßúôiÞ3ú´F")Še òL"­Ãy"-UáähK˜…ŠŠ´6S€R ¸\6Фž¡´²€Ó¨*XUÉ7Ÿëˆ7Õ­£äš-ù3zìH¾šf¼²Æ×Šåi6–n¤á'PQ‘Ö½÷ñ€\à pØüøžf‡pºÒôrì¸H½FˆKæïçÙ2ÝÃ(iq­9íäÜÕ4W;0‰ªÈ’kvØ•8è‚÷äg)™l¸©öÑÜÛeMóû0³iž’GÁ‹Àý€îêà šÂc´‘)e6—±.bopÓ6;E+ÙõÑü  Uú‰jA«‚ð1hq­U 0|øGÀ`M áF¸³òGqœBn:‘k£ ~)˜©.Bø"Œ!:ur¼Ïºººž={Z²§šm!+++88X©TΟ?ßn)£Ë‘Ú‹ŠŠFŒÑ¡C‡ñãÇ«T*Û/çΣF èÒ¥Krrr]]Ø~âĉQ£FuìØ±cÇŽ£F:qâÉ#Â&>VÁ@0°RWe=¸LSC´‚Fû'ÓF’é(Î\5±FÞVd[,CŒg'úkÓ~ý‘±víÚéÓ§;á7Ç¥¦¦¶èwÞy§´´´²²²¼¼|ïÞ½6lpÊIyyyiii¿þúë™3g"""¤xs[.ÕªUsæÌ©««;vìXçΓ’’ÄögžyfÈ!*•ª¦¦fРAãÇ÷Þ·-®µ*/ës|ˆo:”y—hUd¡ÅʲšíÂÈW C-Be7ºqà¶2ÐP0Ô À~ŸåÆk׮ݻw¯ƒý?~¼¨¨¨²²rÑ¢E¶µqãÆ%K–tëÖ ÀÒ¥K/^üüóÏ;ñêvïÞ-mgdd,_¾ÜöËß±c‡¸Ñ±cÇ+V(•Jñá±cǾùæ›öíÛX°`Ann®ïÈ#¹´ôî$%É%àY“Æ)4/Dëk#é«.Gdëkj–o}1ÐúKa¬HR!ˆbX|1ƒqúX?$|•>ø`øðáaaaö“žžÎq\@@@‹Žª¨¨8p ¸UQQa÷BBBÂÃÃ'Ožœ™™Ù¶m[ù³W®\Y·nÝÈ‘#í»ü;w|óÍ7‡ºxñb½zõúꫯÜòÚ>Yi}‡ý{w7Û ùµ*]€]ÀUàK ¯¬½¦†p¡Ò˜FÚˆQ QU¸‰-ܤO“}ÄŸfKîxeô_ ¾X»mÎI‹ð%>ùä“>}úôë×ÏÁ~ÒÒÒrssÛ´i¦¼©{P```c£ö‡sCCCPP#ÃhÛ¶mÿþý7oÞüþûï ã÷ßùå—§NÚÒËß·oßSO=µeË–¾}µ7´)S¦$''××׫ÕêI“&M™âÅ«#$Z•ÕÀ1@ ¼l7ýò%G4øÇÆjÿ,i#®—E]åaœB[A¬ q‘¼$ŒÌË}AõÛþ·–¤jî’•`•äCè[,_¾<++Ëñ~Ž=#EÙ¾Dyøðaq»¬¬,22Ò ·ü6mnß¾mÔ”––öí·ß¶èò·lÙ2a„‚‚‚¨¨(¹`Z°`Aç΃ƒƒ,X°oß>’G„M< ¼h€m@P@ ‰p–*Ò«Ÿ­Oí…ÀÕ2\¨¨ŠÄ?­ÕDž#»š‡Ù|Ù¼EmÔÒÅ2_k^‰¬Ræ½N Égøâ‹/†ê„Ϩ‰•ÈÆ“““.\xáÂ…ŸþyÁ‚“'O¶oIIIååå7oÞ¬ªªJIIIHHÛ'NœXYYyóæÍ .,\¸Pò²rù’¶[½zuffæ®]»äÚ@DDÄòåË/_¾|éÒ¥+VDDxqÝ7’G­JGè=Ž“Ï€~4/„ÝÂÈÜV3 † µ‘F9²µ7{¿ [3ª."V^3vÕ<ÂÅÊk¼:Þ‹>ȲeË233Ý;†ÔÔÔaÆEDDDFFŽ1"%%ž~Æ7a„€€€G}´OŸ>o¼ñ†ØŸ””0`À€‹/nÙ²ÅöËOKK;wî\DD„”I\üðÃ÷ïßß­[·nݺíÛ·ïƒ>pã²Ük÷õ”ÿ±Ük¶Ný­J)ð(ð…îá> M—ýˆ Z¦lÜ ÝM]®t‘êrÌš0Mµ‘[ÖtWѪ~Üæ«‹ˆ•×øZ„³¨æå³¦N€²€Þ”¾õ]]Zê’w²Ó‘Ùv†arrrrrrd¬…"yÐâšçüššBB©T¾ûÿÞ¶ã@ÊšíŸg2 ¦ÚÍd»Ö~N͹ZÛBe¸²fªJÀ»èÝëÉëkbñµB«V!†‹òy†£w-Aø”5› <sÑg2a¡‘ŒCìCœBÅɲYÀÔåH—ëÈX ”К´Ákòð~†øbREáGòˆp)dó%l! ÅT&ÂÈ`ùŒëD‰u/äkgaÍes65é gQ퉟÷þhûÃX¨°¡@™6Ú+¯i'\ žjÓº—fKIøÕ`>qÖ"E®„ –‘y …q ÓÐ3KÚHUÁšF–´‘¾ŠˆL¥´Ö¥{xúl+ó†*]É… ,(c¶§üm!4c¾Ä¬¹ónܸnãŸõ®ÈzÔºŸÛ¶þ¢tnFÆùŠLË$†5mTÀ« Ì–nðÄÜáÚ‡JÕµ•þ½NdT›¶Ìâ‡W#ä+ÈÉX•ó€ÜìWí8Êf wÏÇ'þö˜5wÞÙê“ÎêäA¸ÅHë]„æÓaÛh4’\‰ãX«ÚÈD ð{ad ÝÊÀ×2‚F`ŒÍéˉÖ!-s‘M¿T†âÿ[Ã"À0öïq°“¡Ã£m<׬¹óœ8x’GáNUd]5ëg  †Ó~Ë3‰ÄêiÍöWÓ”æžТ‹p’áÓJx¿gù6ñµ€èm139h»‘f]’%¿]v^nœâÝÒ×”äAø‚62+Œ$I¤ª`- ùÍ—‚ ðÄü„ñl3Ú€:܌݈ÐO¯7¼š¦Å=Ù MwÂFÞÉ#‚p‡@²`1µ‘è*ÉV°´ºGFÒnŸL8—¬Ýó3“[³(˜L½°MUå:’+$XZ¬æµ"IrЦڴÉíÛ·—-ÏY¸`M…o°déŠWæg¶iãòÀ2ÊšM®G¿%j#ëÂH&qxL‚þþ¦KY$íÏi?§qÉÆbƽé: gÍ £i#ÿMõÎׂ Ú¢«Q0‰¬Ï3‰ºæq\½z5-=kÇÎÝ$|†÷7þûÂ… «r³;tèàÒQÖl‚p¹6’œ©k¸b=8HùräÞEQ:ÆÀÞi¿EGì —)›jmo#=&ñx½e”;;,À—°‡Ìî¬fy²Á¹úúúi©/9r”¦ÂÇØ±s÷¯ÉSÿõö›ÁÁÁ­'‚p:#•Ñj§WE’ÈHIHëe-ÕCr¢« „å£yV®Šö€—?ô´e5LÚÒ"‡ü­Úz,‘¼:JžÌHAZÆ<ÒF¾Ê‘#GÓ2æÙWk–äAx„6‚¹Õ4§ ãrsQ¼ëo©Ñ&·mQ‰"‰ìÆ-¢„]oé)5Ë+yrÍv?«V® 둯2`Àƒ«V®pé)(k6A¸R#é’_›>|Æã3ñ¬mdÖ‡Ú,xö€L÷àYeµAHZ´å2jbJhF·¶%ØœÀZðg9e5°_B VI‰´ÝJppð›Þ=*†¦ÂÇ=*æƒMïºte d="× #XÈf$0Ú•5³#…ÑCSP#oâmÝ\qÙ(ÃôŒLúÀêÇ“ÝÄàµ2m ¶Z}~Hýà5B¾BtÝ”«"Šðw/:tX·6oÙòš Ÿaòs“ܹF„šHŸÐÈRþk1Õrœ…|rmT¸I¨/©Ÿ#&‡Ø‘¬H\Ô³”›q«HòLa$Í›XZ$L®ta´oFAŸ¢M›6¶æK´Ú«Iòˆ œ©LF’’|ŒŒ´‘sQ£‰·}™å%ÃJÀ—Øpˆ$’Ü¥¼býŽÑé]zû„Aòˆ Ȩ¬²l4²â|mI)«íÏa-E¨IØ]C1gFrpa¼Ë«‰7_üNtÍ–¶im­•±½¾„+*Qî}MI„i#§ €9m$ºÉ…Q³®E¢Wµ#ÚÈH!•8v‡öóµ6yiɧâè“Cê&J#@Áà¡fyJž%mÔÊØžº’üùÞkJòˆ Ü,vIŵd4E³áú¢R‡ëšFRz¤•¬ö~k ~,ë$N¹CËE’*$qºœa¦¯©XM¬."¦8çI¹Ysç9·f;á ܸqÝ#ä!ˆfµ‘, 6ŒŒF¢_‘¥Õ´Â ÖlØ#Õ­¨"½úUé­Ú•÷eÆ_’£ôÙL8+TóR- , t/)¥ÖâlõIšÂUòˆ$AXF£–8­¶©ÑÈHnb ê¨Á¼ `ª‡Àƒ…j¾õÄP³"‰ñ¶ÎA\e+lÉ„«Aù! WqoŸ§OVºú!É#‚ š×F€äi³žFÂH¤L¯z”H‘¹°˜R&š…Ì.ÉyÒMÖíqmnG—I–u31›É×ù ãÚ´¬Ç½|„opúdå}}#O¨põC’GA˜Ã0l[°ÁÛÈÿZY Ý`UÜM½Æÿ\¶¥ü’H*áyÑÕ†¦>Ó•5Ze#\ Zá!É#‚ ì×FZדMÆG+-8µϸ³šš‹\aFòL'³ù!%JØC–ƒüÕ,‰#ÂÉYw\÷äAV”™5ÑhݱV„‘uÄø2kahÞpWu®É˼¿ÙPQ_̰±Ú–^tÍVʲO‘R+@yŒuýeÛwž5wžwþæå‘ÙX¶ààà?þxøðáHLL¬¯¯§W…ð9A¤‘k##aÇ)>㡽#nd½'³¦#¹‘¥à|/ºŸú§7’®´H™l4‚ `éóã¦NŸE“à¿ßÙ‚°*çµ´ÌE6}e1Œõ4°±ã/mž?yòd|||nn.Ïó3gΤ†ðzD­#/¡eÁh¤×Fƒ$¿"¦/²"Œ …å[Á; >ì$ÏYÈäwÐ"çäg!j™ÛÑš÷Hš?Dj×lØ-†F;ׯŽ;zôhF“——W\\LòÈA¤ß–ÌïÍî@´)¹Ÿ º5”;k¤Da$¯’&†î3 ,*Œ=Pä jæ-F¬«"-CN1#yfu)?¤í¨´ ‰>¹á]Ø$._¾Ü¶mÛ½{÷¾øâ‹gÏžгgOqãÌ™3=zô ytÈ\!»)*ÁªÁ‰!¥,–‰t’sµ€0kug°š£Qa+ð!`ÕáZaÔ"#ïF­©o<yN—©Vÿ¹äk­Ô¦•¢ ‚ðVydêi$þš‘‘ñÑG 2„fÍT CPcœv‹Û d©%1Ähe:A×R` “H$9Ž\IÚÈ@qãDað!`mWEþ)ŒŒ|ÔI´!©øZy…Ý…‹Å×(ûA¸µZž9?7g¹R©tHYÊš][[˲ìåËZŸðóçÏ÷êÕëÔ©S½{÷®©©¡À&mÄmgaCýë*dÉÕµá’~"ZŠ˜©±3ŽÛ‡ÎhÆ)¤u7¡€gX”™F€#&§˜–ááÕûŒ:ŒcÇz¦%I¾¸Ç¢PöT4“  DÈÒ7ðbÆ#}x?}^[‹sçέZµêóÏ??þ|``ààÁƒgÏžýÄOÈ÷ùꫯ²²²>ܵk×Å‹§¤¤Ð¼ùMMW§¥¾xôèÓR_ü`Ó{l?¶ûuêÔiþüùGŽhoÛ·oŸ;w®B¡˜3gNQQ½…‘äíkA9ª‹…,%X2Ý·èÞÇ" (ä4¦ÚˆÆŒ6â‹™pÖl>ǺſÝßJ³F#³÷E?¸YŠBÇgÝee$1û‘(’´™!uyL· —²cÇŽ}þùçW®\ùé§Ÿ&L˜ðÒK/Í;WÚçÇ9r¤B¡8}úôáÇËÊÊhÞ|‰[·nÍž›~ôèŽýaöÜô[·nÙ~¸­ýW¯^=xðà„ ´÷}–ýøãëëëKKK)†Õ™Ï/´ÚÈø‡¸ÂæûŠÆ…2#µä?¬äÚHà‹W• # ѵ²Ùø|}‰l4#yu^FTÒ(Ž®ˆk良µ:UUU&LضmÛ°aÃÄ–ÐÐÐgŸ}öïÿ{LL̆ D+ÑÒ¥K¯^½š——×½{wëׯ§©ó%^}mÙž=_J÷ìùòÕ×–ñÜ"o^™]nS«Õ1114ûFzȸÅ¢H2ÒC¶ˆ³BÊÊj! ¢L- ‘ÔŒ62dÉbdзšå¬„ë¯ôÎtŽ6¿£ZŸHŒ$ð/ÂX¨ +ÉÇ×(²dißWùYIä„äz–/_>kÖ¬aÆýøã“&M:vìX|||~~¾ yyy/¼ð‚(öíÛ 99ùÇT(ãÆ[³fMPPM oÀs‹lCöÈ#ÂòMC+VTFªHw—­áÄÿ3 ݆!÷æzÜNÌ9š‘J ¬?KR5ÊfõÉ@ƒÄlÐUªá赑²ÚLYyY‰ŸÖFÎ7±è6¼WNòcõï±0ÔêòCÊ| ¥Ÿ. €.¨B_Z„J°¹’âââxî¹ç¦OŸ>yòä 6äçç8pàñãÇÅÝjkkŒ?þàÁƒyyyóçÏ¿zõê‡~HH<²ÿlî$¡SEfŒ˜>§L¿§Ö£Çè”V¨øm«“M†j ¡Ò}_Ði,ýY"·UtßV2~'’Ìj#iMž»(ŽS|Æé¦ŽëÌ ÚĪy&œ5rÁ6ë’åëF#×)$øJ~í(ËoS‘dœ"’’Ëøõ×_ÃÂÂüøãS¦L HIIóó={¶K—.ânAAA—.]úŸÿùŸöíÛ¿ôÒKóçÏß¶mÍAòÈ¡°%S,Øuä÷fñ+õ3à† ÔðЃ…Q^ƒ_¥ú;u†Ó:}ëÏk¨ØÔB³•¾YéÉ ±åå3¹Q!§‰ã…œFk4âB^P1C¼¿ Õ<Sm4ÀFaä£ÚÈE:ÆÔŒä]‚)Êp[4!3l¨À3n«6¼?QÿÖT³¼’g jÓ’Br ]»vU©T½zõúóŸÿüî»ïN™2eÆ Ž?>uêÔ©S§j_¸¨¨={öÈ  Ù#Hµ­Í¼Ø’0²â$.5"žÅgA܆vMÇä.Âju’øP…PÝÕ(àÆ1ˆ½¿Íè³ü,ub¶²À@;ø€Z2ЬnVI|ÆA¿ÖÉA»¦¦ÓF¢0²žùÚ¢ 6ÝäìRHͪ"oqW?¡*Äj¿"¸qØ4Uô&q111ùùùéééï½÷^rròܹsãââ<þøã/¼ðÂÂ… ÅÝÒÒÒöìÙóÖ[oÍœ9ó7ÞœœL³ç8¥81É£i#Ù·!§PIvsÂH.‰â-ÜÂã9ÆH0Q¼VõÐé$Ã*˜Q²‰ÆŒ\Ë×¥MJÔù‡æëFË(|õå2«LËÊJ‹"fÔÌVñ£QkŠ$Ÿ‰ù—2°Gó&UŠ ãüÕ,½i\ȼyó{ì±'Ÿ|òÁ¨†Ö9Ç/¿4ìU„‘À<¤Ñèw.aDZ‰"QÕ4t.G „Ñ#†.cG‹6[…Û›-õNA”GÕ×F†l¼n+…Ñ8ðsQ3ê8'i#¨žAÕÏÑ( þ¥3xDðàv†/ÔõVqßæT~Zqâ,߯‹H B¢éÃD)Ò„)2+äw€•ÓÓ¸ÇÑ"ÑV$¾d©K —Ia´hIB8ùUâCFW¿F d³¥ÿãJµéš ($ÑFvô¯^:a@£(@ÿ– ¨ö;˜-@~¥Òë$>‘_RÁÌ™ÆZVÅ3é ΈåÛx¦•ñ+!J$ñŠìk †¤—§9÷mâFÜ60R ݶ=€ˆŽ(‰ÅŸö/x *¹H-òÄOmšáìšmlœ‚éš]Ãí– Î0W…‡T/V]äÝJ¥‚…Q¥K/‡A8Bl'ÊÁ(‹îBÓÙ4™%èïªî’Zõ˜ÂE’БÄ*¢°"*›ÔI”*ÒŒUé|Û‰ç•C #|ýT©dùÙi8Œ—§åkö"À NàËí  ’9üñü Sïæ*Ü5›'BÀx~܉W¯^]³fÍ;w F­Ë&yÃ%ª#)jüy ¯’BP-äQ•ùáôÚèç7¶ç$H7£ØŸ½˜ä“MxFÙdЯ‘ö›TAŠD% ÈÕÇë¤*Frñ2i•<šF 35%‡Ï²FTø_s¿l¨`ÀŽDU¤ZÒ Tb9ÛŠv+Vì1iÝ«ÂíFt/l2G^¬]»ÖÛÛûôéÓùùùË—/wuu½v횢?ª~(d°(a|£iþ×'Ù4#‘Cf54'….Ô$%’®¤3ÞðÄ–ä×I<‡Š¦Ž øN±ô…h#W8rê¼<.äü?Á)ìHGSxÓ‘Ø¿Y…¬Yøãhs/)]áD³2c…Îe«!®\¹Bn„„„˜˜˜´—„„„„……ååå=zÛ¶m:::PXX8{öìãÇ€««ë† ÈtʾBĶmÛBBBÒÒÒÚ´i³oß¾¶mÛ’ò…ü—Ìvùòå ÄÇÇ7hÐ`ñâÅS¦L‘ó&$$Ì;÷æÍ›%%%½zõÚ¿ÿ¯¿þ %%%¾¾¾ÿýwii©¿¿¿á ‚øúõkëÖ­ããã+ YYÖÖÖ¯_¿®]»öÒ¥KÃÃÃóòòœwíÚU«V-Åoü“BÙµ¹Í#αò¹Ã<’V…ç ¡Ï!ô‰ÚHȸ€ÊŸnl}ïžcWüñ‹¤³l8ˆh>ÿhg–¾›YKdÏý³,8Ëú)_È*=ÇÊOåª^Fådå§ò9ÅSÔIÉdB„ ™^÷;ÀW`¶½mÄæúC”YŠ‘ IÑ:)ò¡#$4 €64„/?ÇINø’~HdÔ1Ú&Š¥E+Ò;›SSSmmíÖ­[—••1?òÕ«W»té"𫨨¨/^$$$|úô)  â5±téÒ´´´·o߯ÇÇ'$$,[¶ŒÇ7nܽ{7;;{èСžžž”ªà~Õº»»³ÙìÜÜܨ¨¨'Ožˆ,§Ô/ÐÙÙÙÛÛ;###==ÝÚÚšŠ0Îb±^¼xñôéÓ„„„¤¤$…“áÇïÞ½›JÙ±cÇØ±cƒ‚‚¢££Ÿ>}šžž®§§çëë«”Ö#e_T¤!³E'„YŒ(lÙ`Ë%w†/bÓk#Åðà^÷€„\Ú–\Á­QmÔi!:I°‡@˜›þí¨/àø?ƒ&ü\$Ž_qOC#ÝŒ*#Ͱk܆‡¦#9¸]¶°ÌUŒÖ,`GTQsU£DŠø•ÅĵQý|’„¸f“¯í²²²ØØØ¹sçfdd¬[·ŽÉ1Ÿ={6þüK—. üvÆ õêÕ#7ìííCBBàÈ‘#·nÝ"Ó7mÚdooÊÛYmß¾ÝÔÔæÏŸ¿|ùr×ÓÓKKKKOOoҤɮ]»D<§2¸À—/_R% ²°¨˜ì|àÀëׯ7nܘ¼p!÷òò8p ¦¦fiiéÎ;oß¾ ááá5€víÚmݺUùä‘Jª"þW²¡4ý‘ðƒ ‘A ÓO¥r’ôRªxµ° &’øë™¥ÏcìáCüЇ¹Ø¨ˆZDM˾™hü/¡UÀ^¼ž×l©ˆLÕ’¢‰$»ªÛv焎¯‰ç×ÈÚA©Ç”7&Q³555Û¶m{øðakkk&êáöíÛ&L8yò¤¥¥¥À Íš5«è¥š7ÿüù3¹žžÞ¼yó ›V‹ééé-=䆾¾~ii©ÀƒÿóÏ?Ë—/ ÔÓÓÛ¸qãСCEXºøðáÃ… >}úôÇܶ’OŸ>µhÑ‚ÉM±¶¶nݺõ™3g†~âĉ®]»6iÒRSS­­­•Î £ òˆÎóš×ŽfüF#ãhØ”¡÷IeÓ¼ZÌ8ì/\¦€ÊId€;J5dæŽ-–õˆNQJèŸ6ârÍù)õØ´wU‘¢šŽª9²FI Õï’cÙ¤·ŸsoL|naDC¬“ª©òTó‰`8¥_CC£¼¼\d¶cÇŽÍ›7ïìÙ³vv´ï“ÄÄÄ–-[’¤_˜››Sé æææ’]Îÿþ÷¿sçÎÀåË—'NœÈDI÷G޹fÍGGÇÚµkçååÕ®]›L¯_¿~BBdäaîܹAAAÇß°aömÛ¨#>>[·n­U«VûöíÉÄiÓ¦M™2eãÆ¯^½Z¹råÑ£G…\Ê#Iàž’Æm4¢[¦4•r3b‘¯ö¤ŠÑ´G`GTzóÅ Uô}L‰$¢ò @%pú²;ET1óØÍ€‘?݃~ª¢ê§oåªg‘Í*{ÿÄ*'íKïjM¬¨Âb€–!å6IE YФE÷6nR…B:ÀIÐ'NTF¨· Ȫ:“ÑTYøÕ o«x#Ô£f»¸¸Œ7...ÎÜÜ|Ô¨Q+W®äVÜä»yÞ¼y`cóÓ×;77×ÐÐç°=zôhÓ¦M^^Þ¨Q£X,™¸råÊY³f‘ÃO£G¦s-âgáÂ…ÿûßÿòòòÈ2899 <811±uëÖ$óÜ»w¯[·nò¹À½{÷z{{1¢qãÆ , çâ@@@À‚ ÚµkÇáp(ÇsžÂsŸ}Μ9³fÍâvoZ´hQhh¨½½}ZZš••ÕÒ¥K•æ¸xýßOcßf}Jz|a¿Rh#ÞΈÙr”Åèg¿#²QKŸGžWË‚Êë§ A”Öé›(Þ‘ùGÊè0ïŒ]Y0ô%R yTýÓ‰}ú`%’÷oãZ´²Y»jù¼…þ"W›!›JIIqRâ[r²³³?|øpúôé+V€ªÆ=<1SÙlF=[M_Ã<¿¿Wó]ßD±;`;š«AÔ’œl¾÷ª"µ7 7 )Ž%)•ÏcÊã£]¹ØˆäbEdŠtS½8“£lbâš­DFFbïTS(´<¢[ „✨'x…ÃÎ_ÀB_-‘•Ô·jUR&Ÿ¾ìž;vŪg¤ŠYçlE1 6Rö3Ö¬HJeóŽ¯ æ„oÖÈPñW‘@BɼÄ?{Nö½¨Â®¶†Ô8Q·®«¦522š3gޝ¯ïÖ­[ɯnܸq÷î]ccãµk×zzz>~üœ7mÚtìØ±ââ ooï#GŽù¯_¿~ûömSSÓuëÖ999 0àúõ릦¦k×®ýñã‡üt» 9"#455ׇ­ïîñüyL»vmׇ­!µC„EÍÂïþ w'.‰€ô¶Ž“D0!BÍDCmT£zªiMJj"Œ ¦­V„\Ê@ˆÿŒðx‘óè$rá‘D}LØÓ²,*6̨PEÍ*OÜm9…á–©l'…¨Ùõë×ðàAÆ æ9räš5kk×®——W»vm™ž‘ zzº»vl™¿Ðoͪ`==]±öå•Gt’ˆ¡ÿ@=$BQ¿{¢ÜÙYÕümÈL IýEKHOu! (Œ@a¦ÈrÔâã‡Hà<;R'9T nBTv¿t¿3XI•TŠKEwÛ©"%: Òª¤Ü:©ÚQ³§M›6eÊ”7ZXX¼zõjåÊ•G’¿  @WWWWW711ÑÏÏOŠ§Ã˜L2ÅÄÄdÏîì¨UMį„ê¡*OõˆŸCæä¨9­­5 ‰!‰ß(¨–”Q‚… j¨~QšÀZ:Ç®2ÜÆcLù´R"ÿÿé®dëY:ñ¾?« YQj‰Bœâ©ê»f/Z´(44ÔÞÞ>--ÍÊÊjéÒ¥ÂóïÝ»×ÛÛ{Ĉ7^°`ÁñãÇez:¤ÆoæšH%•Æ!zè'¶lÈÒ¶QÉW B¾ÉP-IpO …)bÞ)¢¦«‹`ø}ºðü O¢I‰äÝcÆD éXÍréËî9¢Šbª"k eTƒë"Ôþ V0BI•"Ô¡ÀQ6ŽÀŽ‘­Ü“Wè;gaý9‹ÚŠ¨Ø‹Å´¨Ý«ª´Hê 2Àwt…xrv¯(ñ¹•r*±ŠÛS÷ʃ™ö€•³0Ü Ô^´Þä:q•œƒŠÎUŽåK—¡;Ó×™>JHi«ã¯¨Â;BJ³µøŸÁ¨rõŸŸD4p%sPICî ±D² QR)©ŒF2e_«¤fí” ×x>Ç®ò-]È&JØo]‰T”X"ô™Þ®ö6‘¶¨8P¥Þxù,òòY$yôÓO¨rÔy «)ïi6Ê j)”;Š£œªs ·B B ZެïC‘Ä­–ê¤!]¸3 "®œb®±$—V´UD{9={ÿ‰¦#DZðY(?¡J¿éÕ5¤Šø#ŸÊA¦(‹²·rÔª<F‚¢s”³9IëNIËeGéZ2!ÕVA0I +ùM?œ*`„+Ÿ¡²á»:= d­±$~öÈHH²ííq¾˜Õ%VØ©8 ÉPqØ Tµb5C™v±ŠÖ‰# ¨› i4Ž‚=VÌËŒH´ºˆÁ»Òˆ 0#ÿw†ŠEs©‰ksÚX?KA °«ª·˜h,™"SÓõòF•ì´¹¸‡œíݵ‘‘<· Ü^*Xù†W³á(ËÍ’Í+Ÿƒ-YÙûFöQh*‡­/×[TÓ" ‘µ^‘Ò£,ÚÔ'ü‡«Ñðö êøn@°%iï±äiêÙûOe,|5í|Zb‰)A©Y$^H‘ÉsÔsSr˜×ψ#Þ¿_ZZúîÝ»aÆ©måŒ=úõë×ÅÅÅÿý÷ߟþ©,}rKKÛjþ¡ˆQgjÞzDTÂý(ºººÖ©SçÈ‘#ÇŽ#ÙlöÛ·oMLLâããÙlu‰°Ä°r&båPévvvsæÌw Iu¨œ±cÇΚ5ËÉÉISSS­ÖÖÏ®]»fÍše``àåå®¶•3hÐ GGG##£   jy¥è“ËËÊŠ?¾§þrNí€Ö9ùq&,áLX™´”³d=J Ó‹ó‹$‘ù_î¡>@y¤pŒ5êåË—{öìiÔ¨™èää–ŸŸ¿nÝ:'''µ½a+G`"V™hnn¾sçÎ1cƘššªó£.°r¼½½,XðòåKŒæ"°~RRR r*Mrr²ÚVŽ››Û‡HcjjªõÉ¥©ŠßÄPE¯Ÿ@çvàØúwÇîЯ´³(/Í/É}S’óª$÷MIîÛ‚Ï—Q¨¹¹¹=§æææ*“<úþý{^^Þ… ,,,x¾òöö>qâ¹Ý¸q㤤$øðáƒú(†•#\TTtðàA777u®‡SXX¸cǪ”½O&4@ƒ 45*?Wü«ñó#"UZ¶²¥þbžÇÄ<áN‘ÝyËÊÊfÌôŠŠº;c¦WYY™rÈ#‚ ŒŒŒš5kwäÈî¯&Ožììììå奶-IÜÊQ«cX9Û·o?pàÀ½{÷@}ä󖣩©ùáÇzõêmÙ²e÷îÝX?<õ³iÓ¦%K–,[¶lãÆê\9AÔ®]{ݺuÛ¶mSÞ«+ÓÔ$•¡ïß<úË™xÿæQA~.©ÿÊ8š¥e9º(5AP=&EöÊÊÊšè95++K²Ýëm«Wo[=ù5pyЃ‡àÁÃG˃î¥a!¿|ùðýûw*ÅÇÇ篿þêÛ·ï·oßÈ”ääd ‹wïÞ5mÚ”´x« L*‡.+ÇÃÃÃÃÃcÏž=Ô/`õñ°aøXíÙ³'???<<|íÚµjõóƒIýtìØÑÁÁ¡   <<|õêÕê\9››»zõjåí“5ËË@“€òÒ☛Áy¥ššZÁî@Æ—\=â§e JAAáä©3Ÿ?™¹àþ‚'wÈ¿Âï~½xê÷ìO@PV ¹9_àGöÛÂ/· 3£ 2£ 2nç¨×ã eees}æ?ÏŸÇÌõ™Ï|ĪBUNé2·ŸÃáøúú›˜˜øùùÉß?²†­GäÞ»woܸqdb`` ùó…ü¨§§WXXpüøñììì;wîŒ9Rš óʘˆ•£õPÍÊa±X‡ {óæúøÖ0¯OOÏ;wnÞ¼ùÍ›7žžžj[9111Ïž=311áNTŠ>ÙhÌþÄÐyÌž:µ´ ‚ü‡€UÔ= \tãÆO«Ï7—17ÏðH"—®§Ná϶sçÎ;wîÄÅÅq8œáLJ‡‡Ëù¬ay$ð×¼ÀĬ¬,*Þ†šÀ¼rÔ0Ö¹õ >µÄ¼r¾}û6pà@l¶´´ d/ã/žp$«b.¨öïß¿bÅŠúõëÀÊ•+—-[VÃòƒµ#‚ ªÁìôìO‰¤/A¹™©pÿþ}OOOñã@ZY4./+ÕÐÔâ”—Õ­kú5ë[èÒéCúwoÌy+î¹æ/ð[зO¯Ì̯›·l§äÑý9hdT{wø¾Å‹ýOýs ¦L›à¿dãúµ%%%6nYº~ÝjX¿asVVöí›×8ð]´„:xغ7®]æp8ó,Z¿aóÂ>=ztüäßV­Z¦¥}b9öﯧ§ûøÉ¿={tg^lÅ“” "u’@»IllìüAnÛÙÙÅÆÊ[œháóƒ âÒ¢• p­w(»‚T—JmDýë›+X% IDATéé™›“sè@8p8m¬š gOãp8Fû½k77w›V¹âžGWW'###3ókƒõƒVþŒ“¹"0 N:à9Écó–Šy—/ž­ÜKwžÏ\jÍ׳ç.>¸ÏÄÄ–.Ytëv™~þÂ¥Ã÷™ššÀ²e‹ÝÜ'-\àÓ³{·sç/Ž;æÜù‹ÚÚÚ—#®¸ òèñ“aCœ™[`ñ¼¼""EmTaUÊýÆápÊŠ¤|ý^–ÿµE“Üo_tëÔMIIÑHLþܰi‰¸§Ú²yÃæ-Û6mÞ¦««³Ìq¿?íÉtR|€žž.åÂüìÙóÐUk_ÆÆp—-33³Q£†ävãÆ?£I}ýú•úhѤIff&téÒ‰½|%œ;!$xÅîð½.Æ<{ö|UÈJæÅXgÔ«c YV¬Uú#ûsr)§ükF:•”jå'Š{.Ÿy KJJÊËËKKE˜a ‹t´utttRRRý–,£Ò‡8Zš••µ2(„Jwrr\š••õõkÖòÁƒŲèÙ£ÇÊàÐ!΃Ày°;p…@Ç#k«Ýá{ ÓÓÓ—.«îyËüÛÛ÷¡>ÚÛ÷Yæ¿Xê÷ÎÝÝ}éÒ¥Ÿ>}JKK[²dÉ„ äÜxx­G¤ë‰µÍýñÑ£Gݺu+--ÕÒÒº{÷nçÎñ9” žŠEkE U6|ÜTƒãGÿf˜³UGGV>}þüïã‡Û¶*ãpŠ 44-M­'ÿÝÈÉÉ€E+¶.¿T½{÷š2ufrrJóæÍÂÖ„ ϼ*d加™³çÖ¯_²§Ç¥KͼæÌ\أן††“&Nˆ¼y›LŸçíÅ\ÙÇÞœðž;»Ru [·aà€þ0hÐÀÐUk{’G+W°-öß¼e[½zfS§xFD\­Nýkjj®[3ÞÝãùó˜víÚ®[£©©)õ»®‚ ˆ¢QVZZøåçêË“M‡¯=6ÏËÛæ7믙ê×-,(ÒÑÑÖÒÔ|÷>iýŽ}#G¹û×§oífM0ë\΃œó.ÍËc ¦>öíÛ»oßÞTú¸±cÈ Е¡•ÎC“='’ºººÁA˃ƒ–óßÚÚêÍ«r»ž™µÍƒõ¹3'©ãǹ /žHôôtwíØ2¡ßšUÁ Cf‹ A«V­ZµjUM5 }îÞ½;~üøuëÖ7îÎ;ø"‚ ŠFá—Œ¼¤ 4 òÓ?€yÃzFv»´ãB§NÿKOÿ åÅzº:_¿›™êp@ÏȸՇ ÖžpLLLöìÞ!Ö.UÖ}Ð~¦ì¹µA¡.P´<ŠŽŽæÞ ÍKÛ·o ½uëÖÿýçëë‹ AQD*µå—Ý iý>Czu±é8q¤§Ž¦fiYPÂk›ßšlþk=}C‚(Çš“)äz´Óå1út÷ÞÃØ¸×ä¶­U÷nŒÜDË#Ãm999Ó§OÇŒ ‚(²4"45+¦Íkh:Ú:FFF®#Ç}Nù˜“›[\\¢«¯£g`hjf®£¯½dé–_´-M¬<éSSKÒvíÒñG~á‡Z¶léæ>!/÷û—ŒORG‚ *ÉÓè§ì:`=¨¸BªÔF¤Z4jשÍZ—”Õ1Êþö][W» °¨U«¶–Ö/_²Š±êd÷’´BgK >½ºÞÑÒrww/*,`¢P!¢¾Ú+A‘éܹ³»»{ûöí îÞ½&AÀžâïß¾<}RúHƒøxù<Î"bSf(楾ü´fð6YÇ /7#!Y[/º0á#Ê#™k#y*$mmí~ö=ËËKÓ?¥0ÜE ß#`<¯ ADñé`× H ‹››Û¡C‡æÍ›§««ëéé4cÆ qRÇÒš?q†™€iû[× Å:—¿6’§B*//ÿ”ú‘y~FÖ#TE‚(B¤ª"ÅÁÏÏ/..îìÙŠ5Ȇjmm>>¯^½’ÃëP>/]D8Ò²W1ñ<ž‡©ï‘¡¡¡››Û›7oðæ!"»©ê™ûLÆÎjv| ‡öôôôV¬Xáïï]RR:qâÄâââñãÇ»ººÎ˜1#11‘Éq*âÉùœEmáph-¦û‹‹‹Ÿ={¶téR¼¢hJ…¢tPÞòSú@vþÔg‰VÄkWs…´hÑ¢ãÇ“/šÛ·o7jÔhÑ¢EÞÞÞpòäÏ…T{ô葟Ÿ_ƒoV‚ ð,²;K‹V6ŸE³%\TQáŸïˆÝq21::šˆ&€Ëã˜îÔvu´^ê”—´ú4fnÇpêªÕ\!p«0ÕZ‹Å:¾€žVPÝ?ú·Jš+P‘_)ÈMÑ’¬Ê”jÚÅ ˜+Öƒ*äù2‚#‡j¬ÎÅ2 ‡#diÏêDÁ‘b͈ånŰ´RJ®Ñ™{b‰Õ$h6ÂOÊä. ®áèj]ZN” ©È¹‡+›ÀAd‘M—a çnr"Ã{V_¨Iå^´´´}ö&9ýkΫW¯ZZÚJëeÌÜ ‚šÌÏgSzzVAᣧÖhÿ¢3lÐL}½Z`nn6[A­GÊõüW³ã“¸`B]‰] ä_iKˤ~ø½|ÔÄ%‚GyÐ9Tñ GqïNõ«”ù¾Ì…µÀfO·»@§æU³Ru¬,Š/§èîcuÚ•ÈyyŠó Iÿšsýñ›ôäD)ó]|,·B¨$H’Êð“Bi² µ³>|øpîܹ#ÿ”wéÚiÁW33³²²²¦M›¢Oøïä½£þû.w ¨håIly¥¡¡òéÓ'|-!R#"I‘çÞ# …¹Ií‡/?ð§çü(zŸÊ’ù9EŠç•µBâVEä¶À”êÉq_ˆT®‚ÃáäççÀ AƒÜÜÜtuuÛ5oïÿ·/øÿíÛÒÒ6%3¹QÝÆ51’Wñ{Q)vvvdб±±»»{PP‡‡>x‚¨ r^I‘g¯ÝMÏøRE05n¹¹¹ùß2dw^éoÄ=£Œ+-wÿþ}(++ûå—_êׯïîî¾Ü-”THçÞqy3LÇîðHÍšZÈmæ?¯<âw-âOÉÎÎÞ¾}{TT>u‚ÔR Ó •bà½PpÎ¥ ÈÎÍÏÿ–q`íUÒFü£l²\ÕWHñññß¿ïСƒ›››ŽŽÎСC]\\~ûí·n Î?:ý8þ!™ì¡¡¡qúôé#ÿ”wêü?oß‘;v¬1yÄCCC77·7oÞàƒ‡ HÍŠ$yJ1CÊ«xÞîêeçæËN»È_ÉZäñ83I¬È#XYYÀÓ§O---¹¿MÉL&íF$>>>dx¤¨¨¨Þ½{“CrŠ(ȶâââgÏž-]ºŸ:AT[!*I]cC9H 9k#‰cN2ÔF Uo*³ÒÕmÌ8hРôë×ïõë×›6mêܹ³<‰xòHygõ#‚ Cd “uE$VÜNÖ§Ù Œ±Äãµ-±6âQH’]Ý^<‘'9NxxøåË—‹ŠŠÈðHÙÙÙwïÞýã?T!‚ "±6ªÎñ%:Õ9—¸_I‘AƒijjÞ¿¿¼¼¼iÓ¦C‡ÕÓÓ“çÝDy„ "4©ÙY_Ó“ßûš.#m5§GŸxñ¢††ÆÅ‹ nݺ‘‘‘ÚÚÚ-[¶TPyÄ=ÉŸJ¬]»vHHHûöíŸ={æë뛓“ƒ÷AQL¤î£#1Týã+‡¸³³3A'Nœ€J'$…¶ñDB"™:ujrr²··÷Ô©SW¯^‚ ¢È IÁ¨ÔÊF*\¼x‘ ˆ{÷î@YYYddä/¿ü2iÒ$¹@£ú‡èÑ£ÇÁƒ :Ô£G|ðA©ÎÎζ¶¶ß¿·³³sssfò$::§"*ÜŠªlÊû¸=~ZÍ#¨Òº(üþõQ·®ïÙ¹»µE* 'öãB"‚ rF¸è›”×>(2¼òˆÿ§.$‚ "O1Ä #‘àx4R}ø>E[Ò£G™3g’ ‰lÞ¼å‚ HõUŠ!„!d*0¡ì>ª-¢­GÁ…DA¤%ŒP!@Nt¥Œg²ûˆò€±õAAa„Ô¬6’ÃG”GâI¢ôôôúõë'''7hÐ ##ëA…"O0¼ˆ\åCëÑÝ»wÇ¿nݺqãÆÝ¹sëA…‚¨¬<â—D”`"7È Û·o ½uëÖÿýçëë‹õˆ "\¡0B%–GüÖ#6¤œœœéÓ§cõ!‚ˆŒÙˆªA”^¡;6‚ ˆXªÕ‚¨¾<5òòòzõê%rAÖC¨ŠDíä]Ôl˜8q¢¹¹¹À£ *BDå…ê!Q_yDg "bÈ!~~~Xe‚¨›6Ba„ ê.èì@vvvqq‚£ŒGEEihhDGG‡„„Ñ´A\ô0̉ÚAPÑZ†zæÌ:寯ÆîîîAAAX­‚(¸0Bу â¢V+hðk *±V­ZÝ»w¿té’eggoß¾ÝÆÆ‚ Š øÿ È‘2ÔFHMu·sמ»ö¼sç•xêôÙÁC†—–– ß÷îÝû<&ÛþÖáŽÝæ/ôËÎΦ¾zõúǤ)¿µû£{Ͼÿœ:ä$‰>téÖ«¨¨ˆ'=''×iаïßsøw©Ti5FÖ£}öâÅ ·nÞøýû÷›¶w*²$Íš6µ³ëpòŸÓãÆŽáN?|äX»vmŒj«ùbä{4tèÐ 6Ðõ2¤¢*..~öìÙÒ¥K±õ#"7U„v D¹ø˜œÜ½[W‡ó198Î"¿¥þ²´l%rß}{v‘zzz æûØý¯ ùqãÆ-sæÌtè÷'èéé­d ÜhlúÔÉsæÎs3JC£b(©¤¤äà¡Ã»wm_¼$àÒåcÎáƒûLMM`Ù²Ånî“xäÑ…‹—>`ll K/мy[õî”xQ³Q%=¾°ŸÃá”JdPìßÿƒbK|±©• ’‘iG‘[‘B• 7ÕàøÑ¿±‡÷ ‰“<§Ýм¢ÔWÑÒÒ6;;ûǧOŸ^±b0Ÿ¹FÅŽŠŠÂ¦€ Â5à‚ ªÎÊ ÐY3§—””„†®vìßOõ.©ïÅFT^Óˆ j AdÀ¥9m¸Ê¢‰ƒ£SAAa¿~ö^sfª¾<â·aPlD•TjA¥pÜ?Îuü8W¾ ¢­G8T( úA•ƒ ‚ÈO¡BA¡úAAHñ[ìíí§NÚ¤I“7oÞñ»a¨$5—2Rõ‚ ¢¸òˆ_ß888øùù¥¤¤¸¸¸„„„ 6Œÿ(¨ŠÔJ¡”AAÔKñ›‚|}}ÉgÏž={6V™ú¨"”A‚ Ê£Ÿ’H ãÆ»víšÀ¯0¬¶RË P!‚ (ª@çH4lذ^½zMŸ>ÿd62¬vPP†Õ®Ae#(ƒA„‘<h=?~ü Aƒ¦Nš››Kw «-O„ÊAD¡ˆºu]y ß³÷ŸxEÈ#~ë‘§§g¿~ý¦Núýûw!°Ú"5@¸×ZG„ ¢¼Lœâ¥ŒÅæp8ï߯áí!ø­Gä€Ú7È]ºt)..æ^ÙQ©Ãj×øu\#ADeà^Ö])@aÄT1ŒšÍ¨,owJÍ3‚ ‚ˆG*iÉ …*!A‘5gNÿ£ø…ôòY””øV y¤b!°Q!‚ ˆÄ´´´ñWÉíÜ¥›ð Ýzô•Q ‚¸u£úÇQëÎðBQó·¸tº—ú•޾?~|LLŒžžÞÖmÛ¶nÝú2&ZŠÇ—…Û“ç*–õHbGi”A‚ ª)2eÊ”®]»zzz~úôióæÍ&&&5URôÈ9ú€\­G"ÕªADH¬êªoß¾M›6íÂ… zzz3gÎd±Xdz||ü¬Y³îÝ»ݺuÛ¼y³¥¥%Ã} ‚àÎÆ=Kîùóç¾¾¾wïÞ566^¾|ù„ ž‹ŽaÃÇlÙ²¥ÿþ/žÿ .#\—.]ZƒšÒcò9O²Ó’@ÄH ªAD˜1c†žžÞÇ`îܹ{÷î%—”=zô!CŽ?ÎápÂÂÂÆŒóôéS†ûMà€øøø¡C‡†……:u*++‹Íf“òˆÉ¹è(//////(( ?~þüÙ¼^=µºƒ¼òèøÑ¿á­ÌÎv^Þ¿;~ôo¬DU[‘B• 7Õæð‘c;vîNOϰ´lµ*4Ȫµ%”••­[¿ñø‰Sùùùö}û­d—¨°°pé2ö•+W &Mœºj-e á? é§ÌÄ[ùüùó?~466€õë×2„”8¯^½zøð¡ŽŽ,Y²dÍš5Ì÷¥ƒÅb±X¬aÆ€¾¾þ®]»Èt&ç¢ãìéãÜ×XVR—MÜ IDATÿêeÓÆÚµïPTXA¼Š‹Qáæ¤O‚ˆK‹V6-ZÙÈá#‚ ̹ÿàá±#ÿ‹~ØïOûÅ‹ýÉÄmÛw½|wîÌÉG¢tuuV­ãÙkÝúMyyyQ·®_<æÉ“…” ïâcEŽ1ñ˜y^¾|In8::®Zµêû÷ïß¾} uttd¾/˜ššjkk·nÝ:88¸¬¬ŒLŒŒŒLKKkРÁ¨Q£²³³™Ÿ‹ --m7²¦õûÍðæ‘à—WvÇ]Ûwm{ìÕmªÝœP!ˆ„vò¤¬?"¿þj®§§ç9É#6î™xâä?þþ‹ýÕÜÀÀ`Á|Ÿ+W¯ñìuáâå%~¾ÆÆÆ¦¦&K/y@† 0`Á‚ÙÙÙÙÙÙóçÏÏËË#Ó·lÙ^§Nccã½{÷nÙ²…ù¾çëׯ'Nœ¸víÚüùóÉôÌÌÌøøø/^$''ëêêR‹Ç39Czüa[ø=óËÛ{Ñw.F߈¾}÷ Ê#AP!ˆ¢S§NrCOO—²¬|þœÞßqPKKÛ––¶»öüú5‹g¯ÌÌÌ ê“Û5y@†lÛ¶-++«aÆÖÖÖM›6­[·.™îáááîîž••åææ&pÔŒn_MMͶmÛ>|xß¾}dŠAXX˜©©©‰‰Éúõë/^¼Èü\ !¢¬('-«ÀÚ¶•µ•µ••j7'-|¢DxLë²ûˆ Hu¨WÏìäñÃææætLMMÓÒ>5nÜRRR¥uÞºuëž:uŠÜÞ»woŸ>}ÈíÛ·oŸ?žò¢“}«Ø644ÊËËÉí¶mÛòHæçbHyyyIa¾yí_bcž‘‰Ûª“<êܵW`` À¬û÷ïÿþ=YËaaa¤C»¾¾¾ÏŠ+žï×_6lØÎ;§OŸ¾yóæY³fíØ±cÚ´i'Nœøüù3Ï 633ëÞ½»¡¡á„¸lÙ2‚ Œ‡úàÁƒW¯^‰[†††sæÌ ¢Rš6mêâârôèÑ´´4þüúúúÎÎΖ––………?îØ±ãªU«„ÔÏŒ3"""¨“ÇqwwOII¹ÿ>A]»vmذ!Ïõò@íÛ¸qc‡ üòË/Àápx.äc`` ‹Å"0 eË–‘ÓGY,V`` •Îb±„ŸN$¤K`QQèêêúøøpW²ð<"÷å¹::è.ÊÇÇgß¾}YYY5Õ>ÿúë¯õë×3©IêÙ$ /‹Š¥K§k¥t­šI/ÁÿÄÑÝPáO"7<7´¦Ú÷¥ÑuÂ|!—¬££Ó¹sç–-[†‡‡s·ºI“&½xñâÑ£G^^^—/_ÖÐÐpppظq£-MÎ,Z0‡yf‘kAð0Öuô’¥¬eþ‹6lðîýû­[wnX_ÅCyÓ€ àUA+Ùgep¨ÈÕ~ŸØ¢y3áÙ<<<Øl¶™™Ù•+WX,Ö•+CQ666ÁÁÁÞÞÞgýúõ666Ü7‘ô:¢Û×ÕÕuÉ’%VVV?~ôòò1bu®ùó瓞×óæÍ4hÈs‰¯JËËKÓrÀªí%ÅÅP5È€zX–-[¦¯¯ïååbff6~üø°°*¾léééÜÅZ øóçÏA´k×.%%’““;wî\VVÆóî!›‘‘qþüy???†_q8œ¬¬¬“'ON›6-11±°°Nê ìÔ8wT‰6mÚ8::>|˜®GÎÏÏ?z´b2^ûöí…×ϯ¿þJN¶äé[›6mzèÐ!Òr{ûöí%K–0¬ÌÑ£GGDD¼{÷®¨¨H[[›ùŽÜ¦còEbllL oçååQéÜ¿6èN'²’ÓÓÓ6lH¾A4h‘‘ÁŸ™.“}™@wQ©©©7¦Þ¦rnŸ¤èLMMeX“<íVK—N×JéZ5“^‚牣Cä“È Ï ­©¶Ç}it…_ø%Ý»w¯wïÞ܉ݻw/--}üø1ù8'$$p8œ1cÆP¸[š2o¡?“lAxù,ëÈS§xîÜîö×ÄôôŒ͛Ϝ1•'ƒ÷Ü9KýzôúÓÐÐ`Â_nQQw…p²ç¤a.£òóó…z»víÚ¹sçïß¿wíÚõÌ™3VVCQ‡š5kÖªU«8NçÎ<È|_—qãÆÅÅÅ™››5jåÊ•dúĉ“’’,--óóóœœvìØÁü\L›4hhëê5­_þþmliq1ís‘Oóð˜œ>}št”Ä™kˆºSƒïŒ#GŽ`ý«Ò UX”®¥eeeÍ_è·fU°|–A?Îuü8Wl'²Ê Æ=BAˆ‚‚ÂÉSgFEÝ‚ R#ܺ¡W1qŠ—2›Ãá S9?‚]³¹`x ßÿýâŋ߿/((¸t陨¶mÛË—/ÿøñ#//ïÒ¥KmÛ¶¥òŸ;w.''§¤¤äÞ½{õë×€‡vìØQCC444þøãr-ë:\¾|9''§¨¨èêÕ«666ÔA"""Hm¿ýöÛåË—óóóüøA.·NB·{Û¶m/]ºÄŸAA$–ÊÅ»øX¼k‘šï‘¡¡aVVO¢µzVV–¡¡!õ%kJJJHIôåË—ÌÌL++«¸¸8[[Û?’ P×®]›{ñjîÀ¹¹¹Üøþý;¹M­\-dwCCC*UHAA©Å=ÊËË366þúõ+wâ?êÔ©CÊ&ccã¼¼<á¹ÿ~¯^½âââºtérþüyJíÚµ+''Gø¾?~ü022"…N:u¸%”ÀÝóòò¨²qçGADbΜþGñ éå³HøÒ¹âÉ£‚‚33³/_¾ðõìÙ3''§3gÎ÷êÕëÊ•+ðòåËœ>}š ''§/^?þû÷ï бcÇ¢¢¢OŸ>‘‰Ožsú&Ö#æòˆ=L¢w‰õˆ§!µ´´ÍÎÎþðáÃéÓ§W¬X Q  §§ghhèàà‹Þø‚ ˆp"U×öP*ýêÕ«zzzuëÖuwwÏÌ̤¾zþü¹£££¡¡aãÆ÷íÛ'ò˜FFFdz||¼ƒƒƒƒƒC||¼ðü 6|LÏž=œœ¿yåVä•ukCüýý---¥XQ ñ˜ÔÑÑ€%K–¬Y³Fx~†|NK~ûêeÓÆÚµïPTXAØ´jò)9¡©Ê·( |¨AegÃÆ-ñoÞž;sòæ«©©idâ¶í»^¾Œ;wæä£Qºº:«VÿtH½ÿàá±#ÿ‹~ØïOûÅ‹ý)Iô.>–šœ%d÷/^ž?ûpmdjjª­­Ýºuëàà`rA-®^½Ú¥Kr;222--­Aƒ£FïàÁƒ=zôhذ!ùÑÑÑqÕªUß¿ÿöí[hh¨£££ðüLhii»‘5­ßo†7¿¼²;îÚö¸kÛc¯n;²a^+Í×Sû7•ÿøšœÑ‡ AQvNŸ9{`xýú¿€ÿR?2ñÄÉö„ïüõWsX0ßgó06ËŸüjE`ñÎs’Çæ-ÛSÈî~~ …”‡P+++‹;wnFFƺuë¸3<{ölþüùÔ"™™™ñññ/^¼ bîܹӧO?zô¨À#———¯ZµêÔ©STÊ–-[ºuëFÎ(·°°àYE”??Czüa›ÿíKNÆ»Ÿ¿•”QZTX¿V¹­¹¦Ê·(•GÍš5sqq122bHÜü@ ©gÏž 6;vlÞ¼ygÏžµ³³£¹×$å‘b<oÚ´‰;åöíÛçÏŸ§|xÖàÏÏòòò’Â|óÚ¿ÄÆ~üèåå5bÄ2=,,lÆ ×®]ã1çxxxÌŸ?Ÿôªž7oÞ AU¬VÔÜ·Ë—/ëééuëV%ªMpp°··7‡ÃY¿~=÷Âíó3ÖG¥åå¥i9`Õö’âb (/.Ì|s‡ÐP}ÏaKÒa``йsgWW×m۶ɵXZZtÖN©ä—­[·&MVùùùÉÉÉVVVd¼%]]]+++CCCr™9kkë?æçç»»»geeíÙ³'''GWW·Y³f}úô!5ШQ£è¾¢îˆ®®n§NFŒ±uëÖj–\à+³k×®<8räÈ/¿üÒ§OŸ‘#Gîß¿Ÿ'ÏàÁƒKKK×®] ŽŽŽíÛ·ÿï¿ÿH¹3vìØˆˆˆ#GŽèééõéÓ‡[õéÓçÉ“'öÿoï¾ÃšHڀφT’ЂŠ( x§žRT@ÄÂééù¢x6<Û¡`=°}§¢gùìzöŠ]ÏrX°w$¨€ Tôºß‹{¹„€H»÷÷øø$“ÙÝ™Ù%ûffv×ߟLùþûïŸ}zìØ1©TJ|ÿÿÏ;Wã­®¥ˆ~üø³gϸ\®žðÈÕÕõõë×䮬4]} ļ´/^ø§¨g[†¨êæªW}­»RkJKKííí1 #®OîÞ½;FKKK«¸TYY—Ë…³;õJNOÿ¥û>›V=“«êKÀ­5Uý\+‰ÈŸ]ºtÙ¹s'ñuyîܹñãÇ“Žz–Ò:»å ¹ººnݺU("„NŸ>Qixtüøq¢×®]ëÕ«—úzˆô3gÎ×èÚÇÄœ®®®7oÞlÕªÕùó烂‚ˆÞŽŒŒ ¢›dïÞ½={öìß¿¿•••@ xòäIjjªD"Ñÿ‘úáóùZg‚Wi²Ù«gmmݯ_?6›}æÌõ M›6 عsgÅe³³³ˆË"èt:I[YY­]»!8`À€ „Ú´icbb¢>ÐF8yòdtt´ŸŸq*Õ?½=''ÇÕÕõöíÛ®®®J¥²cÇŽ<°··'V»fÍ"›B¡8þ<ÑwMtêp¹\.—[ZZªÞ›UqöìÙ³â5´ºÒõ×W} …B§íëßV¥ªº¹êU_×®ÔZ†Ó§O<!tøða __ßM›6988„……á8®>!I}^ ^EHÕ[0vj\¥y>ß) ¡…Gä¹–ÉdvïÞ½_¿~Dÿ¹‰‰É¤I“ é$T§g)>Ÿ_ãUb³Ùä µŠ‹‹9N¥‹!š\.§P(dÏ9!]׺—Ë-..&ÞÞ¿?,,ìÎ;ÆÆÆyyyt:F£uîÜ™èÌ@I$’ .\¸pÃ0kkëž={†‡‡CZz>"ö†aææælÖ¬™þ™òR©Tœxð oß¾DÐðêÕ«^½z3— QQQ;väp8 ÅÄĤwïÞä‰AÏGêÊÊÊrss5îAœ5µÒZì¡C‡ÚØØP(¢;ŠœîááÑ·oß;vTŒÈðkРAfffT*ÕÉÉÉ××—|ˆÏýû÷X,‹Å T¿/ƒzaÈ"y{{3™L&“éåå¥~«­¡^NNNPP±7ÓÓÓƒƒƒÉéJT*U¡PÈår33³ÐÐPr‘!C†XYYQ©T ÃÈNA íÚµS(gYéJ'˦«¾ƒnÒ¤ …Bár¹½{÷Ö:«ªÛÒ£›S_m•ª¯kWê)C“&M<===J„¥¥¥mÚ´qppPïŽuvv~öìY•j uÓ{¤~£ÜÜ\rRÅÕ«W½¼¼"""¸\îÇÉSãµk×bbbèt:ñ©ñV×RU¥±Z]Ο?ß¿ÿŸþ™•.^¼H¤?~|àÀ½zõâóùiiiê×Ujõ×_…„„LŸ>]"‘\¿~½}ûöóðx¼€€sssòëþÑ£GdxôòåK …òèÑ#2jjj= À`0ÁóçÏ÷ïß_éGîÞ½Û§Oâçxõdff2ÄÚÚZ ðx<òâ;âI=ê#¡‰‰‰óÄ_¿~=fÌ&“™››»wï^rðåþýûfff±±±4˜ª¬¿ ‡ öòò"ºÙ>L¤·jÕJë9>;;Ûßߟ?~Ü·o_ròJJJJPPаaÃÊÊÊÒÒÒˆ‹BYYY#FŒ077/**:tèÖbøøøh½²CW:IW}Ÿ>}:tèPkkk±Xœ••UqBªp¦Öméj ÕØ\Tß2 2äܹsäXðéÓ§‰«ÈÝmaaagg§kïÐà<Ï΄Fh0„Ðìä÷yÙÅù¯oŸÜaeeR%ÄuyÕžT 4DFF^ºt‰³ƒvhÜÕ>|øÛ·oá¡"ÿrq3&»¹zßÂî^õsjË•Kêäö<ÕÕG—’’’W¯^¥¤¤$&&"x$m üIÀ7{Ú¶m4¿§àa… ñüTîÕ‚ŒÆÂ#uÌÓËÏl†Õÿ „G@ͨ´ë¥Nn þµ(Ðê ÷øR ºsË»Wo؃ 8<*:YdÕߪ¾­êë‘w’ó§òUÖªú_Ô†Ò¤PGÀ×56¶!Çq˜T^Â#I€DÞQÎ]Î}/Â98{ v†a¤³‘C¿A‡¦€ðÐPB†U`Œt©³¹G 'í !¤è  >¥ê:ÛÕቶÎשl­¤ß¡×BMKÖ• õg'c¨d}I]5¾ÊDU¼»§þýSÿ÷ãhp^¼§Xe¢Òº,ÄFjD ô•þ^ʸÈ`\bPJ«lÉ;șǙ!E{g-ö„–_!4)jcC˜“õÑo–‡b27&Áê,`/£PŸPen2F!„spY™Ê\E)¡ „dî2j&•R—@=u4åpý/dìÔ8ý÷­ðˆ½…-ñ“ˆ†‹h™4ÆEý“ë<¹Ê;É?-þTW­.Ô@ñöâŠ?ý‰Þ âò#I?‰hˆHe¡¢æR9+8ÔWT„¢ áBi€gâô[tÎj&Ö,NÅ…“„ÒžRLŒ±RXdº²©R8V(w•#*¢¦S¹+¹”JÅMk͆’u• £„ÊJJ1Åø€1ó,SWy*®Sû²:ª_t²ˆ½™-(VYª¬Xá4\ø“PÚSŠb\f°7°1Fäç¬ãˆ‹•J£wFœõ•J.R6QRó¨œåêk-{œuˆ%,"Ã#Ñ`ë ‹?›¯§‰ˆm©‰\›¢¢,¡ŒuˆÅ:ÁÒí"ßê¯;ó"SÒGB„GòörDAr'9ã:!$í-ežaêÚãäúq:.˜(yʈÝ-ŒêßD»U<´t6ð/áàè‚ÊÉâUi©JoƒnபóƒÃÒ®\ü*½GºFUt\ÐÒhi8—yÊ$AÁãƒq‘AŒif~L³êo%í)•ö‘šÌ3÷+”œdŽÖÍUœJ"ï,7›i† 0q˜X0Y`6Õ !$ )f“Í0!&'F 9ë4W()R™¨Ì#͆? Èô²9eœ î.¢!Ñ‘pŒ»Œ[qÓZ³!„Óì5lúm:n‹†‰ÐY¤«<שuY=ÕW´S˜M6#:ND£D* •ùs„!þ4¾h¤ˆ½½|ò–ì™iœ)V†‰CÅeóËèwé¦ ¦XÙç›fV±©7¢Q"yG9-ƒ&ï$Ç98ã&ƒøúë®Q¤ò­÷ & 8«9ô[ú†õ×~‡.øI 2QQÊ( ý>]á¬`\g¨,UŠÖ úz¥{\ô£7ÆËww¬ Òý¨óÐÒqØw@ 5ЕÞXùõ9rdzz:‹ÅZ·~ýºuë2ÒïÕàú¿Æ´§¼~¢5.Ñú¯’xM‚1.2LãMMšÊºÈ>ý÷“žÌòoå´4âœD{H3¼¸œµJ“`¬#,EÛò‘'I_ g‡RDÁĘñ6c™‡–{ªJ}¥ìlJ…ò‰ÂÞø÷4pó æ´t&Ã0!f¼ÃXþ\ëvuf“"•… ·À)…ÎjŽáåѵ¬þ^:2‘úHÙÙ”OJ)…³#õ•’Ù¸k¸”Lбޱp&ÎYÇ)›ÂR8è«S!Öa–8\Œ³Ž° ÒDêEB‰ˆã&óLôÇF•×]i i/)BHî,7Þc,w–#„¤~RÆURTÞÂRo){óçݽɠݭõÐÒuØM¿ÐeìØ±½{÷ŽŽŽöóóóññIHH¨«’\¹t¡öï›PÁ5²{I=f™¸ÌC&ñ“(Û(éitæE¦þeBÂh!BHæ.ãOç›&˜'aeå£f˜CFŸOî–ª’ÿ•üIÛu*s•QAùä „¢ƒB)T´UàL\ײz²™,6 ‰#)"¯23¤<º–ÕÉÿˆ¨ÌTFï?W'ßHe¦ÒÞD:Z¬"f*S4B$ñ—(ì&¿šRw"!„Äabæy&5§òƒªÒº3.0S¬Ó,WE}JÅ™8ÎÀ%þ¢³§ÒV™«Œ ?·O¡A»[û¡¥ã°4•v}IwŽãqqq7nÄ0,&&fÑ¢E¦9ëãÔ©SË–-»uë›ÍîÓ§ÏòåË[´h¡Yò…ú%rYYY'N¼víBÈÓÓsÍš5ŽŽŽê™+.R©°ÁÃÖ®]ðøÑ]„Р!Ãê°ÿ,rÌäZ¾È®:ƒkš^ßÈ%¾Y-“Æ<äߢó`t­De¢*ÙXb9ÜRÑJÁŸË7mþ¥=`ųéf”ú¦ëRJ(J¥Q¾BHÙDI¦—Å•±·°é÷é˜ÙøÇƒµ.®+5‹j²Ð!$ë*LXܰ0°<º–5´Ê¥jÕiª¬Ò¤xzˆuŒ%ˆ°·±‘Ü ºWdgZ¶¸ `¬£Ÿ§é(ÎÀ‰@ 7Á ¯;õ!$ñ“вh!ÚSšd€“cDz¥-L)¥(›(‰²»»ÒÃôÛ¸qãÕ«W333q>> eåÊ•C‡½~ýºþe‰G#îùþûïCCC8€ãøŠ+† vÿþýj„Dÿø‘©R©T*±XL¼}ÿþ½M“&ÿª=XƒkÂÑBêKªyŒ¹ÉBÆ5†žØ¨ü¼“‚–EC8R8)¨™úz0¦lYù9‰y†)˜$P6U"#¤°SðáWÌÃHeÇU&*•‰J8Føw4MÇ19†¤Hi£TŸ¤¢±i]ÙøÓùÊ–JDCˆ‚È.]åÑX§Öe ĸò¹:¦*aŒq™ñå‡ëË*Īâd]u¯È¨ÐÈ4ÎT,“QŽxgà*K•`‚ Jug\dˆ"D´tBˆ–N 1.0 ÜãŒ+ áè*ìní¬ã°Ô7‰dúÌY:wuóðÞ´y+1pæ×;0;;‡ÈrôØç¾–l¿ÞHmpM&“ýO.Kvÿ«ÁíÙ»ßÇ·OçÎ!‡<}–¥§<;vìHLLlÖ¬YóæÍ“’’¶oß^1Ï… BBBLMM¹\îŒ32ZôIe¡¢¾¥²öj¹ÂÈx·±p¢°d{ &ÂX),Y÷òÙ*Üd®p¬P9KiTdÄ:Ì"®«¸i]ÙèwéesË”6J£7Fœß8úË£±N­ËÈøcáOÂ’-%!ÆU†ñNã¯wˆèª»öpûÅôÓO‹>áTÜxŸ1çwŽ`Š@4LD)¦6–zêk7-¡I¤ö˜†¢eÐp*ÎHe¸Çw & Êw÷q–¬‹¬uÑsØê›•É¿ ‚+—.¨Tø¬Ùå³d¼¼zÞ¾s·];‡wïò,\Àb1oß¹ëíÕS}ÙäUkŠ‹K.§žÇqôK\<‘˜“Å«8–týÆÍý{w™ššlÞ²}öì9Gï×U×­[7âu×®]y<}cRB¡ð÷ß÷÷÷¯Æ²¡ÀÀÀeË–Mž<ÇñU«V’YZZòùüÖ­[GDDÌœ9ÓȨ:“]v¯šéÙ‰Ó{ïb„\&þ7Qup×löŽò)®œ••Ĭƒ,ÖA–z·–F/×çN@Ä:ÀbÐwÝ5&Ç8+9äY‡Ë3ÓoÓé·ÿžøÂ<ÍÔºi]Ù—ŒKznt”GcÚ—ÕZÁ uÇdg‡³Š£g‘JßêITO×Uw]+§SÌÇ™“½Gf“ÿŽž™'™Ö!D)£X ü¼Î¢¿_ëia² ˜ãþV~Iš²¥R ©^]t6€úæä©3ûöüannŽŠŸ÷Wêe„wOÏã'NøaØñ§ètú™³ ½uûNXhÈ?zJŽŸÜ³k»……B(!>îÒå+º¶’¸pž™™B(ztäšµëõ”G p8å_\.—Ïçë<=aB¨I“&Ää¡*-KX»v­§§çܹsBvvvÄú<²¦T*y<Þ”)S W®\Y½æõêæ"*ýPV˜“û¾T.'~(bß ólÄGÜ^4NÂ1Bœƒ«ÌTÂ(!ý<˜€F®¨¨¨yófÄë–-[/ÜÝ{ŸËåêʉãxYYÙ¤I“¢¢¢ªº,!22rÔ¨Q%%%ÅÅÅ?þøcdd¤ú§FFF®®®{öì©tN_†)¥eïŠÅN.;89wprîàÜ¡qQÆÉ(ߨdCIÉæLˆï1† q³´´|÷.ŸxýæÍ[â…±±±­mË3gþd³Ù~¾>"‘è¯ÔËvv­X¬ô[YY‘‹/¾‹‹ËÝ»w‰×÷îÝsqÑw.—;mÚ´Û·oWcY„ÐåË—ãããɹG—/_Ör²§PT*Uµ«£R©ä‘ —þˆ÷8÷8—þÂ#æI¦Å Ë!–ÜåÜ:|F  vôZ´xу’´x)™îíå•´xihH„PÈ€à 5&!„BCú'-^Z¾ì¢%dº©©Éó/«WžQ£F%$$äçç¿{÷.>>>""‚üˆ¼îläÈ‘™™™ …"???!!ÁÝݽÒeµrvv^¼xñ§OŸJKK—,YâììL¤><##C¡P¼xñbôèÑC† ©~ûª*•â]êàÚÍÉõ;'×ïœ;׸(*üQ¨s_xß¿Ÿ§LN˜3Ï˧7‡ÃŽøÏW®¤}¹ÃÊ žy öÄ͘<ý—¹f–ËeúŸ$Šzþâåèèq—þú³–û¨±±Õ¾ÏP]yžÙ¶³þ;.:8º<Ü7]T\ óB …!dddd²Xkþ£)‡ yæÚ¶M«¿F¢ÆÆò̵î^ê’ƒ£KIIÉ«W¯RRRô¨sFo<­.iÑÒ‰~’ËåK—þ70 ´jM!îq %]Gxô廲>€ð@Ý«ô‘•޾ÙÙµê,Kúôñ<š´f#$Ã3ÇN«4Ïç»@x|M#G 9b8´C«tô³A€+× <Ð ×Ôóæÿº{Ï>õ”? [0NC)¥3¨„G@ÕÌ3û}AÁÅ‹©Ä[ß¹sf7”Â7¸«ú„G##£ä¿ùèQzçήÉ+~«ÞCækŸw¯ÞÐuÔ˜ÀÜ#õ‹ÅÜ´a­·wÏMÖ²XLhP' ÷@ýbaa±uóhP‡ ÷à ÷øR_øHݺåÝ«7ìA@xQ󢯯6Äbã8“Ê!<PïÔÿ”j4¬C`¤ Ì=P—b§ÆÉå2ÿAsÚ¡Ù{´lÑhµfç¶õUÊeê¹£)‡DP®ÿѹZ×èè)€†ÇqÃ×`¢L-sptAådñª´”›»§þ ž^~_©À†¥]¹øåë¡ê:þà˜ðµ±!Uzê©ê%G—ªž×ɯwÐÈ‘#ÓÓÓY,Öºõë×­[—‘~¯Æw}ͪÁ þ05@= •@=1vìXèèèüüü5kÖXXXÔUIˆ §–Uaj6PÃpÿå—_ÌÍÍ-,,fÍš¥µc û'SSSò£Gr8[[ÛíÛ·‰§Nòñña2™–––Æ {ûö-‘^ZZ:lØ0‡cmm=þüJË ¾Q]å<ÌÛÛ;88xÏ®m©ÏΙ3ÇÑÑ‘h«‘c&×ò!<jØÆ¯^½š™™™‘‘qéÒ¥-[¶h ¡H«W¯;v,‘ž••5pàÀ˜˜˜ÂÂÂ7n\»vH_¹rå´iÓ ^½zåìì¾}:8w8äé³,"1/ïÍØq\¿ùιã·Qc>|("Ò]6lÜÒÃÝ«Sç®q³d²òû(•Êß–¯ìîæÕѵkì”éB¡°ÒòìØ±#11±Y³fÍ›7OJJ"{€´’Ëå«W¯ž2e ñvþüùóçÏ 366nÙ²å¦M›ˆô .„„„˜ššr¹Ü3f½ýgÏ.¿sÍØq¢"þsûæÕ[7®8´m›´h)™ÿλ§OK½x®ðÇU«×‰ëÿ·)##óøÑC·n\a2Ëþ»¢Òòðx¼nݺ¯»víÊãé›!¾k×.//¯-Zoÿúë¯wïÞ5oÞœÍf‡‡‡—””hä …«V­ò÷÷'ÞjteddX†]»vÒ¶Ž.«çëÓ‰“ºwqÆŸ›3Ïÿ/óüÿxçÖ7îƒÂ#õËÂ_ݸy !tãæ­…¿.2d&“QXXXTô±yóf‹’é‰ ç5mjÃb±¢GGò2Ÿ‰gNssëÎd2¹\î´©S®]¿A染0ËÒÒÂÊÊrN¬cÇO‰ž3gvÓ¦6l6{Æô©ž;_iy‡Ã!^s¹\=Ý`*•jÙ²e3fÌ SŠŠŠ²²²?~œ——Çd2úé'õü†q8œ•+W&'')AAA3fÌ()))))™>}º@ 0¤ Äv Ü#^Ý\$ŸŠ>d_»wõÔ½´³÷ÒÎÞKû³q„på€úeÁü9 æWíÅk׬Z³výïkÖ3™Œ¹sf÷é]Þ³bffF¼`±˜dGÔÇ–.[žÁË$æÖ¨ÏPnÙ²¼ §•­-9èöþ}A@`õ¥Òòp8@`bb‚âóù\.WWÎÇ·k×ÎÉɉLa³Ù+V¬077G%''ÛÙÙ©çÇqœÏç¯Zµ***êÊ•+¡õë×;¶E‹&&&ãÇ·²²2¤ Äv l^ ÔҲwÅb'—Ž2©!„°F~ 4x®:nüßZ„Ðå+Wãf%á‘V'ÿ<+n†·WO‡#‰:ÛüèÍ›·vv­Byyo¬­ËãŒ&M¬Øccccxy\\\îÞ½ëç燺wïž‹‹Îk¾/^üûï¿ÿ£.®®¡‰Æ"\.wÚ´i‰‰‰Ä[++«#Gޝ·mÛæëëkH*nW•J%—ˆlLh¼ôG2™”HtkÔ³`p @ƒ7uÚÌ/_Êår•J¥PT2]I"‘2è ƒñæÍÛYñsÕ?JZ´¤¸¸øãÇâĤ%¡!å=F? ÿ>>a~nnžR©|–•;ez¥å5jTBBB~~þ»wïâãã#""´†;gΜa±Xžžÿ¸ÇtddäôéÓ‰Á²iÓ¦õï_^Œ‘#Gfff*Šüüü„„www2nn®X,>zôèüùóçÎ[i´nWo|¤P©ïÊP×nN®ß9¹~çÜù»Æ}DAï€záKnyÜ«—ÏØ˜ yyoÚ´i½â·¥ú3/[’”¸hÉ„ISš5k6&:òôé³äGݺu ‰Dý‚'Oš@$ƌ޸iËÿ‰*((lۦ̈́ñ1•–'&&æÅ‹ÎÎÎÄëÑ£GkͶhÑ¢™3gj$FEE½~ýÚÑÑQ$oذH >|xff¦……EPPÐþýû‰t77·OŸ>yxx=z´C‡•–AëvõÀ…ÎdÙ7S=Ïæ)ˆ ú0ôm§Aµs`ÔþMBBhvòÎû¼ìâü×·OîØºqUÔØXx¨€Zð<;³m;g¢OŇŠ|Õg®}ÉCH®\ºÐÏžDûëoRG—‡û¦‹Š $b>BH¡#„ŒŒŒìBkÍ4å°!Ï\Û¶iõרQÔØXCž¹ÖÃÝKý‘´Ž.%%%¯^½JII!F-¡÷@}9UC#ÔC9Y<­÷ËÎÑ¢ªÏ«} ’Éð̱Sã*Í#—Ë <[tQ´j¸ <P¿¤]»ÉË|J¼vqîÐÓÓ ÚÔ2¸°@ýâáÞÝÞÞ!äààðã¨ë&Í M@-ƒÞ#õì‡;…âëãq•J5j”T"þP˜ßPJ³Ë!<¾:ÞÇß[¥Rä¿i(e†{â@x|]*•*ÿmnC)­w¯ÞÐuÔ˜ÀÜ#€ÐÞ{!0€Zö%ેG0z  6=ÏÎ4äžCp_"Pgጞ¨eW.]¨“ÇŽ`hxÔ2øeꘚ ðÚ{ví9M_Û¼yóÈ^øâ…Ö€Ö¨Ûv®<y,õâ¹ÂV­^£ñ©Ö¢êo k¡«åB×oÜÜ¿w׃{7ûôöŸ={±ø¢¾C²Íš5ÓÜÜœx}ðÐá9sf7mjÃf³gLŸúç¹óDzÊÑcóæÅ7kÖÔÔÔdNÂ, píúÝ{ö­\ñ_â퉓§âã,--¬¬,çÎ}ìøIý顤ÄÍš5e±˜‘ÿ‰D¿.˜K¼‘‘Á«©P7'aQ’9 ³ÔKRiQõ0¤ºZ!”¸p^Ó¦6,+zt$/ó ØõLÍ€úE½÷Âði7M¬­É×ïßö'ßbF¼øð¡È®U«ª&çù¼ù¿îض™Íf)?~´µmI¼¶kÕª¨¨H:BÈÌÌŒxÁb15Þ*•ʯÑ-[¶ ^´²µýð¡HãS=EÕÃZèjùªÖ@x †5ib}èÀtkk«Ü¼¼Ööö®çãÇâñb—.IjÑ¢9™hiiùæÍ[;»V¡Ü¼<+++ýéu‚,I^ÞkkÍ’|½¢êjy]ŒŒŒÄb o•––¡[Àà46? ÿ>>a~nnžR©|–•;e:‘>(là‚…IïßðùüÅKÊËLMMž¿x©u=1?M7nL×.ߪ'&-^Z\\üñcñ¯‰‹ôï§?½N$-ZB”$1iIhHOuUOS|aËëâìÔaó–mb±¤   aî8t!<ðµÄŒîÖ­Ëÿ‰réÔeêÔ_úö&Ò'Oïжmÿa½üú6mZÞÃ1&ztØ p­ó{>|4ó—ÙW®Mû9ÖÒÂÂ×?Яw`S›¦?O™¤?½NtëÖ5(8´—_KK‹É“&h|ª«¨zšâ [^g—¸àü…‹ßté>$ü·ÝáЭ?0„Ðìä÷yÙÅù¯oŸÜAŒìîÚspäC¡uà«jÛÎùyv&ñšøâý7?e¬¦Z£qÜݱbkÀßË×kgG—’’’W¯^¥¤¤$&&"˜{õ ÜZÔ0¸á€Æ úœ„G5LçÜ£¶íœ¡u 6Á/´´F½Fþ0”œ0 À/´´F} ” 9‚Çà_L¥Rý#<²¶u˜¼ÚBè>/;ëÎ_G rrr²µµ 9nXDŒáéfff ÃÈÈHý¹c4T?h¡y9r©äãÇùùù!¹TBœ& LÿôéƒÁ P(†‡5´uÂÒ>|ûö­™™™°ôy²0$ÉdR©T ®42ÿ’°ÎIâ.!IEND®B`‚fityk-1.3.1/doc/script.rst000066400000000000000000000474661302634723100154670ustar00rootroot00000000000000 Scripts ####### Working with Scripts ==================== Scripts can be executed using the command:: exec filename The file can be either a fityk script (usually with extension ``fit``), or a Lua script (extension ``lua``). .. note:: Fityk can save its state to a script (``info state > file.fit``). It can also save all commands executed (directly or via GUI) in the session to a script (``info history > file.fit``). Since a Fityk script with all the data inside can be a large file, the files may be stored compressed and it is possible to directly read gzip-compressed fityk script (``.fit.gz``). Embedded Lua interpreter can execute any program in Lua 5.1. One-liners can be run with command ``lua``:: =-> lua print(_VERSION) Lua 5.1 =-> lua print(os.date("Today is %A.")) Today is Thursday. =-> lua for n,f in F:all_functions() do print(n, f, f:get_template_name()) end 0 %_1 Constant 1 %_2 Cycle (The Lua ``print`` function in fityk is redefined to show the output in the GUI instead of writing to ``stdout``). Like in the Lua interpreter, ``=`` at the beginning of line can be used to save some typing:: =-> = os.date("Today is %A.") Today is Thursday. Similarly, ``exec=`` also interprets the rest of line as Lua expressions, but this time the resulting string is executed as a fityk command:: =-> = string.format("fit @%d", math.random(0,5)) fit 17 =-> exec= string.format("fit @%d", math.random(0,5)) # fitting random dataset (useless example) The Lua interpreter in Fityk has defined global object ``F`` which enables interaction with the program:: =-> = F:get_info("version") Fityk 1.2.1 Now the first example that can be useful. For each dataset write output of the ``info peaks`` command to a file named after the data file, with appended ".out":: =-> @*: lua F:execute("info peaks >'%s.out'" % F:get_info("filename")) This and other methods of ``F`` are documented in the next section. Here is an example of Lua-Fityk interactions: .. code-block:: lua -- load data from files file01.dat, file02.dat, ... file13.dat for i=1,13 do F:execute("@+ < file%02d.dat:0:1::" % i) end -- print some statistics about the loaded data n = F:get_dataset_count() print(n .. " datasets loaded.") total_max_y = 0 for i=0, n-1 do max_y = F:calculate_expr("max(y)", i) if max_y > total_max_y then total_max_y = max_y end end print("The largest y: " .. total_max_y) If a fityk command executed from Lua script fails, the whole script is stopped, unless you catch the error: .. code-block:: lua -- wrap F:execute() in pcall to handle possible errors status, err = pcall(function() F:execute("fit") end) if status == false then print("Error: " .. err) end The Lua interpreter was added in ver. 1.0.3. If you have any questions about it, feel free to ask. Older, but still supported way to automate Fityk is to prepare a stand-alone program that writes a valid fityk script to the standard output. To run such program and execute the output use command:: exec ! program [args...] Fityk DSL ========= As was described in :ref:`cli`, each line has a syntax: [[@...:] [with ...] command [";" command]...] [#comment] The datasets listed before the colon (``:``) make a *foreach* loop. Here is a silly example:: =-> $a=0 =-> @0 @0 @0: $a={$a+1}; print $a 1 2 3 Command that follows the colon is run for each specified dataset in the context of that dataset. This is to say that:: =-> @2 @4: guess Voigt is equivalent to:: =-> use @2 =-> guess Voigt =-> use @4 =-> guess Voigt (except that the letter sets permenently default dataset to ``@4``. ``@*`` stands for all datasets, from ``@0`` to the last one. Usually, when working with multiple datasets, one executes a command either for a single dataset or for all of them:: =-> @3: guess Voigt # just for @3 =-> @*: guess Voigt # for all datasets The whole line is parsed and partly validated before the execution. This may lead to unexpected errors when the line has multiple semicolon-separated commands:: =-> $a=4; print $a # print gives unexpected error Error: undefined variable: $a =-> $b=2 =-> $b=4; print $b # $b is already defined at the check time 4 Therefore, it is recommended to have one command in one line. Grammar ------- The grammar is expressed in EBNF-like notation: * ``(*this is a comment*)`` * ``A*`` means 0 or more occurrences of A. * ``A+`` means 1 or more occurrences of A. * ``A % B`` means ``A (B A)*`` and the ``%`` operator has the highest precedence. For example: ``term % "+" comment`` is the same as ``term ("+" term)* comment``. * The colon ``:`` in quoted string means that the string can be shortened, e.g. ``"del:ete"`` means that any of ``del``, ``dele``, ``delet`` and ``delete`` can be used. The functions that can be used in ``p_expr`` and ``v_expr`` are available :ref:`here ` and :ref:`here `, respectively. ``v_expr`` contains only a subset of functions from ``p_expr`` (partly, because we need to calculate symbolical derivatives of ``v_expr``) **Line structure** .. productionlist:: line: [`statement`] [`comment`] statement: [Dataset+ ":"] [`with_opts`] `command` % ";" with_opts: "w:ith" (Lname "=" `value`) % "," comment: "#" AllChars* **Commands** The kCmd* names in the comments correspond to constants in the code. .. productionlist:: command: ( : "deb:ug" RestOfLine | (*kCmdDebug*) : "def:ine" `define` | (*kCmdDefine*) : "del:ete" `delete` | (*kCmdDelete*) : "del:ete" `delete_points` | (*kCmdDeleteP*) : "e:xecute" `exec` | (*kCmdExec*) : "f:it" `fit` | (*kCmdFit*) : "g:uess" `guess` | (*kCmdGuess*) : "i:nfo" `info_arg` % "," [`redir`] | (*kCmdInfo*) : "l:ua" RestOfLine | (*kCmdLua*) : "=" RestOfLine | (*kCmdLua*) : "pl:ot" [`range`] [`range`] Dataset* [`redir`] | (*kCmdPlot*) : "p:rint" `print_args` [`redir`] | (*kCmdPrint*) : "quit" | (*kCmdQuit*) : "reset" | (*kCmdReset*) : "s:et" (Lname "=" `value`) % "," | (*kCmdSet*) : "sleep" `expr` | (*kCmdSleep*) : "title" "=" `filename` | (*kCmdTitle*) : "undef:ine" Uname % "," | (*kCmdUndef*) : "use" Dataset | (*kCmdUse*) : "!" RestOfLine | (*kCmdShell*) : Dataset "<" `load_arg` | (*kCmdLoad*) : Dataset "=" `dataset_expr` | (*kCmdDatasetTr*) : Funcname "=" `func_rhs` | (*kCmdNameFunc*) : `param_lhs` "=" `v_expr` | (*kCmdAssignParam*) : Varname "=" `v_expr` | (*kCmdNameVar*) : Varname "=" "copy" "(" `var_id` ")" | (*kCmdNameVar*) : `model_id` ("="|"+=") `model_rhs` | (*kCmdChangeModel*) : (`p_attr` "[" `expr` "]" "=" `p_expr`) % "," | (*kCmdPointTr*) : (`p_attr` "=" `p_expr`) % "," | (*kCmdAllPointsTr*) : "M" "=" `expr` ) (*kCmdResizeP*) **Other rules** .. productionlist:: define: Uname "(" (Lname [ "=" `v_expr`]) % "," ")" "=" : ( `v_expr` | : `component_func` % "+" | : "x" "<" `v_expr` "?" `component_func` ":" `component_func` : ) component_func: Uname "(" `v_expr` % "," ")" delete: (Varname | `func_id` | Dataset | "file" `filename`) % "," delete_points: "(" `p_expr` ")" exec: `filename` | : "!" RestOfLine | : "=" RestOfLine fit: [Number] [Dataset*] | : "undo" | : "redo" | : "history" Number | : "clear_history" guess: [Funcname "="] Uname ["(" (Lname "=" `v_expr`) % "," ")"] [`range`] info_arg: ...TODO print_args: [("all" | ("if" `p_expr` ":")] : (`p_expr` | QuotedString | "title" | "filename") % "," redir: (">"|">>") `filename` value: (Lname | QuotedString | `expr`) (*value type depends on the option*) model_rhs: "0" | : `func_id` | : `func_rhs` | : `model_id` | : "copy" "(" `model_id` ")" func_rhs: Uname "(" ([Lname "="] `v_expr`) % "," ")" | : "copy" "(" `func_id` ")" load_arg: `filename` Lname* | : "." p_attr: ("X" | "Y" | "S" | "A") model_id: [Dataset "."] ("F"|"Z") func_id: Funcname | : `model_id` "[" Number "]" param_lhs: Funcname "." Lname | : `model_id` "[" (Number | "*") "]" "." Lname var_id: Varname | : `func_id` "." Lname range: "[" [`expr`] ":" [`expr`] "]" filename: QuotedString | NonblankString **Mathematical expressions** .. productionlist:: expr: expr_or ? expr_or : expr_or expr_or: expr_and % "or" expr_and: expr_not % "and" expr_not: "not" expr_not | comparison comparison: arith % ("<"|">"|"=="|">="|"<="|"!=") arith: term % ("+"|"-") term: factor % ("*"|"/") factor: ('+'|'-') factor | power power: atom ['**' factor] atom: Number | "true" | "false" | "pi" | : math_func | braced_expr | ?others? math_func: "sqrt" "(" expr ")" | : "gamma" "(" expr ")" | : ... braced_expr: "{" [Dataset+ ":"] `p_expr` "}" The ``atom`` rule also accepts some fityk expressions, such as $variable, %function.parameter, %function(expr), etc. ``p_expr`` and ``v_expr`` are similar to ``expr``, but they use additional variables in the ``atom`` rule. ``p_expr`` recognizes ``n``, ``M``, ``x``, ``y``, ``s``, ``a``, ``X``, ``Y``, ``S`` and ``A``. All of them but ``n`` and ``M`` can be indexed (e.g. ``x[4]``). Example: ``(x+x[n-1])/2``. ``v_expr`` uses all unknown names (``Lname``) as variables (example: ``a+b*x^2``). Only a subset of functions (``math_func``) from ``expr`` is supported. The tilde (``~``) can be used to create simple-variables (``~5``), optionally with a domain in square brackets (``~5[1:6]``). Since ``v_expr`` is used to define variables and user-defined functions, the program calculates symbolically derivatives of ``v_expr``. That is why not all the function from ``expr`` are supported (they may be added in the future). ``dataset_expr`` supports very limited set of operators and a few functions that take Dataset token as argument (example: ``@0 - shirley_bg(@0)``). **Lexer** Below, some of the tokens produced by the fityk lexer are defined. The lexer is context-dependend: ``NonblankString`` and ``RestOfLine`` are produced only when they are expected in the grammar. ``Uname`` is used only for function types (Gaussian) and pseudo-parameters (%f.Area). .. productionlist:: Dataset: "@"(Digit+|"+"|"*") Varname: "$" Lname Funcname: "%" Lname QuotedString: "'" (AllChars - "'")* "'" Lname: (LowerCase | "_") (LowerCase | Digit | "_")* Uname: UpperCase AlphaNum+ Number: ?number read by strtod()? NonblankString: (AllChars - (WhiteSpace | ";" | "#" ))* RestOfLine: AllChars* Fityk library API ================= Fityk comes with embedded Lua interpreter and this language is used in this section. The API for other supported languages is similar. Lua communicates with Fityk using object ``F`` of type ``Fityk``. To call the methods listed below use ``F:method()``, for example ``F:get_dof()`` (not ``Fityk.get_dof()``). .. note:: Other supported languages include C++, C, Python, Perl, Ruby and Java. Except for C, all APIs are similar. Unlike in built-in Lua, in other cases it is necessary to create an instance of the Fityk class first. Then you use this object in the same way as ``F`` is used below. The `fityk.h`_ header file is the best reference. Additionally, C++ and Python have access to functions from the `ui_api.h`_ header. These functions are used in command line versions of fityk (``cfityk`` or its equivalent -- ``samples/cfityk.py``). Examples of scripts in all the listed languages and in the `samples`_ directory. .. _fityk.h: https://github.com/wojdyr/fityk/blob/master/src/fityk.h .. _ui_api.h: https://github.com/wojdyr/fityk/blob/master/src/ui_api.h .. _samples: https://github.com/wojdyr/fityk/blob/master/samples/ Here is the most general function: .. method:: Fityk.execute(cmd) Executes a fityk command. Example: ``F:execute("fit")``. .. highlight:: lua The ``%`` operator for the string type is pre-set to support Python-like formatting:: = "%d pigs" % 3 = "%d %s" % {3, "pigs"} Input / output -------------- .. method:: Fityk.input(prompt) Query user. In the CLI user is asked for input in the command line, and in the GUI in a pop-up box. As a special case, if the prompt contains string "[y/n]" the GUI shows Yes/No buttons instead of text entry. Example: TODO .. method:: Fityk.out(s) Print string in the output area. The ``print()`` function in built-in Lua is redefined to do the same. Settings -------- .. method:: Fityk.set_option_as_string(opt, val) Set option *opt* to value *val*. Equivalent of fityk command ``set opt=val``. .. method:: Fityk.set_option_as_number(opt, val) Set option *opt* to numeric value *val*. .. method:: Fityk.get_option_as_string(opt) Returns value of *opt* (string). .. method:: Fityk.get_option_as_number(opt) Returns value of *opt* (real number). Data ---- .. method:: Fityk.load(spec [, d]) Load data to @*d* slot. The first argument is either a string with path or LoadSpec struct that apart from the ``path`` has also the following optional members: ``x_col``, ``y_col``, ``sig_col``, ``blocks``, ``format``, ``options``. The meaning of these parameters is the same as described in :ref:`dataload`. .. method:: Fityk.load_data(d, xx, yy, sigmas [, title]) Load data to @*d* slot. *xx* and *yy* must be numeric arrays of the same size, *sigmas* must either be empty or have the same size. *title* is an optional data title (string). .. method:: Fityk.add_point(x, y, sigma [, d]) Add one data point ((*x*, *y*) with std. dev. set to *sigma*) to an existing dataset *d*. If *d* is not specified, the default dataset is used. Example: ``F:add_point(30, 7.5, 1)``. .. method:: Fityk.get_dataset_count() Returns number of datasets (n >= 1). .. method:: Fityk.get_default_dataset() Returns default dataset. Default dataset is set by the "use @n" command. .. method:: Fityk.get_data([d]) Returns points for dataset *d*. * in C++ -- returns vector * in Lua -- userdata with array-like methods, indexed from 0. Each point has 4 properties: ``x``, ``y``, ``sigma`` (real numbers) and ``is_active`` (bool). Example:: points = F:get_data() for i = 0, #points-1 do p = points[i] if p.is_active then print(i, p.x, p.y, p.sigma) end end .. code-block:: none 1 4.24 1.06 1 2 6.73 1.39 1 3 8.8 1.61 1 ... General Info ------------ .. method:: Fityk.get_info(s [, d]) Returns output of the fityk ``info`` command as a string. If *d* is not specified, the default dataset is used (the dataset is relevant for few arguments of the ``info`` command). Example: ``F:get_info("history")`` -- returns a multiline string containing all fityk commands issued in this session. .. method:: Fityk.calculate_expr(s, [, d]) Returns output of the fityk ``print`` command as a number. If *d* is not specified, the default dataset is used. Example: ``F:calculate_expr("argmax(y)", 0)``. .. method:: Fityk.get_view_boundary(side) Get coordinates of the plotted rectangle, which is set by the ``plot`` command. Return numeric value corresponding to given *side*, which should be a letter ``L``\ (eft), ``R``\ (ight), ``T``\ (op) or ``B``\ (ottom). Model info ---------- .. method:: Fityk.get_parameter_count() Returns number of simple-variables (parameters that can be fitted) .. method:: Fityk.all_parameters() Returns array of simple-variables. * in C++ -- vector * in Lua -- userdata with array-like methods, indexed from 0. .. method:: Fityk.all_variables() Returns array of all defined variables. * in C++ -- vector * in Lua -- userdata with array-like methods, indexed from 0. Example:: variables = F:all_variables() for i = 0, #variables-1 do v = variables[i] print(i, v.name, v:value(), v.domain.lo, v.domain.hi, v:gpos(), v:is_simple()) end ``Var.is_simple()`` returns true for simple-variables. ``Var.gpos()`` returns position of the variable in the global array of parameters (Fityk.all_parameters()), or -1 for compound variables. .. method:: Fityk.get_variable(name) Returns variable *$name*. .. method:: Fityk.all_functions() Returns array of functions. * in C++ -- vector * in Lua -- userdata with array-like methods, indexed from 0. Example:: f = F:all_functions()[0] -- first functions print(f.name, f:get_template_name()) -- _1 Gaussian print(f:get_param(0), f:get_param(1)) -- height center print("$" .. f:var_name("height")) -- $_4 print("center:", f:get_param_value("center")) -- center: 24.72235945525 print("f(25)=", f:value_at(25)) -- f(25)= 4386.95533969 .. method:: Fityk.get_function(name) Return the function with given *name*, or NULL if there is no such function. Example:: f = F:get_function("_1") print("f(25)=", f:value_at(25)) -- f(25)= 4386.95533969 .. method:: Fityk.get_components(d [, fz]) Returns %functions used in dataset *d*. If *fz* is ``Z``, returns zero-shift functions. Example:: func = F:get_components(1)[3] -- get 4th (index 3) function in @1 print(func) -- vname = func:var_name("hwhm") print(vname) -- _21 v = get_variable(vname) print(v, v:value()) -- 0.1406587 .. method:: Fityk.get_model_value(x [, d]) Returns the value of the model for dataset ``@``\ *d* at *x*. Fit statistics -------------- .. method:: Fityk.get_wssr([d]) Returns WSSR (weighted sum of squared residuals). .. method:: Fityk.get_ssr([d]) Returns SSR (sum of squared residuals). .. method:: Fityk.get_rsquared([d]) Returns R-squared. .. method:: Fityk.get_dof([d]) Returns the number of degrees of freedom (#points - #parameters). .. method:: Fityk.get_covariance_matrix([d]) Returns covariance matrix. Examples in Lua =============== Show how the peak center moves between datasets:: -- file list-max.lua prev_x = nil for n = 0, F:get_dataset_count()-1 do local path = F:get_info("filename", n) local filename = string.match(path, "[^/\\]+$") or "" -- local x = F:calculate_expr("argmax(y)", n) local x = F:calculate_expr("F[0].center", n) s = string.format("%s: max at x=%.4f", filename, x) if prev_x ~= nil then s = s .. string.format(" (%+.4f)", x-prev_x) end prev_x = x print(s) end .. code-block:: fityk =-> exec list-max.lua frame-000.dat: max at x=-0.0197 frame-001.dat: max at x=-0.0209 (-0.0012) frame-002.dat: max at x=-0.0216 (-0.0007) frame-003.dat: max at x=-0.0224 (-0.0008) Write to file values of the model F(x) at chosen x's (in this example x = 0, 1.5, 3, ... 150):: -- file tabular-f.lua file = io.open("output.dat", "w") for x = 0, 150, 1.5 do file:write(string.format("%g\t%g\n", x, F:get_model_value(x))) end file:close() .. code-block:: fityk =-> exec tabular-f.lua =-> !head -5 output.dat 0 12.1761 1.5 12.3004 3 10.9096 4.5 9.12635 6 8.27044 fityk-1.3.1/doxygen/000077500000000000000000000000001302634723100143205ustar00rootroot00000000000000fityk-1.3.1/doxygen/Doxyfile000066400000000000000000001736201302634723100160370ustar00rootroot00000000000000# Doxyfile 1.6.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = fityk # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = NO # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text " # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../src/ \ docs.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = */sample*.* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # When the SEARCHENGINE tag is enable doxygen will generate a search box for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP) or Qt help (GENERATE_QHP) # there is already a search function so this one should typically # be disabled. SEARCHENGINE = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = "WXUNUSED(x)= " # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES fityk-1.3.1/doxygen/docs.h000066400000000000000000000031041302634723100154170ustar00rootroot00000000000000/*! \mainpage Documentation of libfityk internals. * * This is a documentation of source for developers. * * If you want to use libfityk in your program, first see * the namespace #fityk, where the public API is documented. * * \b directories * - src/ - fityk library (libfityk) * - src/wxgui/ - wxWidgets-based GUI * - src/cli/ - readline/gnuplot based CLI * - swig/ - bindings to libfityk * * symbolic calculation of derivatives * * (can be outdated) * Fityk calculates derivatives of functions symbolically. * It parses expression to AST based on struct OpTree, * calculates recursively derivatives, tries to simplify a bit all expressions * (these steps are performed in calculate_deriv()), * and then produces bytecode (AnyFormula::tree_to_bytecode()) * that can be executed by VM (AnyFormula::run_vm()). * In case of $variables, values and derivatives are always calculated together. * In case of UDFs, when using non-derivative algorithm, * it's significantly more efficient to skip calculation of derivatives, * that's what class AnyFormulaO was introduced for. * Note, that UDF bytecode is executed n times more than $variable bytecode, * where n is the number of data points, and usually n >> 1. * * \b reusability * * There are small pieces of code designed to be reusable. * They can have more liberal licence than GPL. * * - GUI input line, see: http://wxforum.shadonet.com/viewtopic.php?t=13005 * - controls for input of real numbers in wxgui/fancyrc.* * (see outdated post at http://wxforum.shadonet.com/viewtopic.php?t=13471) */ fityk-1.3.1/doxygen/footer.html000066400000000000000000000003041302634723100165010ustar00rootroot00000000000000
Generated on $datetime for Fityk by Doxygen $doxygenversion
fityk-1.3.1/doxygen/header.html000066400000000000000000000003631302634723100164400ustar00rootroot00000000000000 $title fityk-1.3.1/doxygen/stylesheet.css000066400000000000000000000113341302634723100172250ustar00rootroot00000000000000H1 { text-align: center; font-family: Arial, Helvetica, sans-serif; } H2 { font-family: Geneva, Arial, Helvetica, sans-serif; } CAPTION { font-weight: bold } DIV.qindex { width: 100%; background-color: #eeeeff; border: 4px solid #eeeeff; text-align: center; margin-bottom: 2px } A.qindex { text-decoration: none; font-weight: bold; color: #0000ee } A.qindex:visited { text-decoration: none; font-weight: bold; color: #0000ee } A.qindex:hover { text-decoration: none; background-color: #ddddff } A.qindexHL { text-decoration: none; font-weight: bold; background-color: #6666cc; color: #ffffff } A.qindexHL:hover { text-decoration: none; background-color: #6666cc; color: #ffffff } A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } A.el { text-decoration: none; font-weight: bold } A.elRef { font-weight: bold } A.code { text-decoration: none; font-weight: normal; color: #4444ee } A.codeRef { font-weight: normal; color: #4444ee } A:hover { text-decoration: none; background-color: #f2f2ff } DL.el { margin-left: -1cm } DIV.fragment { width: 98%; border: 1px solid #CCCCCC; background-color: #f5f5f5; padding-left: 4px; margin: 4px; } DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } TD.md { background-color: #f2f2ff; font-weight: bold; } TD.mdname1 { background-color: #f2f2ff; font-weight: bold; color: #602020; } TD.mdname { background-color: #f2f2ff; font-weight: bold; color: #602020; width: 600px; } DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold } DIV.groupText { margin-left: 16px; font-style: italic; font-size: smaller } BODY { background: white; color: black; margin-right: 20px; margin-left: 20px; } TD.indexkey { background-color: #eeeeff; font-weight: bold; padding-right : 10px; padding-top : 2px; padding-left : 10px; padding-bottom : 2px; margin-left : 0px; margin-right : 0px; margin-top : 2px; margin-bottom : 2px } TD.indexvalue { background-color: #eeeeff; font-style: italic; padding-right : 10px; padding-top : 2px; padding-left : 10px; padding-bottom : 2px; margin-left : 0px; margin-right : 0px; margin-top : 2px; margin-bottom : 2px } TR.memlist { background-color: #f0f0f0; } P.formulaDsp { text-align: center; } IMG.formulaDsp { } IMG.formulaInl { vertical-align: middle; } SPAN.keyword { color: #008000 } SPAN.keywordtype { color: #604020 } SPAN.keywordflow { color: #e08000 } SPAN.comment { color: #800000 } SPAN.preprocessor { color: #806020 } SPAN.stringliteral { color: #002080 } SPAN.charliteral { color: #008080 } .mdTable { border: 1px solid #868686; background-color: #f2f2ff; } .mdRow { padding: 8px 20px; } .mdescLeft { font-size: smaller; font-family: Arial, Helvetica, sans-serif; background-color: #FAFAFA; padding-left: 8px; border-top: 1px none #E0E0E0; border-right: 1px none #E0E0E0; border-bottom: 1px none #E0E0E0; border-left: 1px none #E0E0E0; margin: 0px; } .mdescRight { font-size: smaller; font-family: Arial, Helvetica, sans-serif; font-style: italic; background-color: #FAFAFA; padding-left: 4px; border-top: 1px none #E0E0E0; border-right: 1px none #E0E0E0; border-bottom: 1px none #E0E0E0; border-left: 1px none #E0E0E0; margin: 0px; padding-bottom: 0px; padding-right: 8px; } .memItemLeft { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-family: Geneva, Arial, Helvetica, sans-serif; font-size: 12px; } .memItemRight { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-family: Geneva, Arial, Helvetica, sans-serif; font-size: 13px; } .search { color: #0000ee; font-weight: bold; } FORM.search { margin-bottom: 0px; margin-top: 0px; } INPUT.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #eeeeff; } TD.tiny { font-size: 75%; } fityk-1.3.1/fityk.desktop000066400000000000000000000013171302634723100153660ustar00rootroot00000000000000[Desktop Entry] Type=Application Name=fityk Comment=Curve fitting (esp. peak fitting) and data analysis GenericName=Curve Fitter Icon=fityk Exec=fityk %F Terminal=false StartupNotify=true MimeType=application/x-fityk; # according to: http://standards.freedesktop.org/menu-spec/latest/apa.html # we need one category from Main Categories list. Two reasonable choices are # Office and Education. Education is not the best category for fityk, but # Science is a subcategory of Education and that's were scientific software # is usually put. #Categories=Education;Science;DataVisualization;GTK; # Update (2014): Now Science is in the Main Categories Categories=Science;DataVisualization;Chemistry;Physics;Engineering;GTK; fityk-1.3.1/fityk.iss.in000066400000000000000000000052371302634723100151250ustar00rootroot00000000000000; InnoSetup script. It is used to make MS Windows installer. [Setup] AppName=Fityk AppId=fityk AppPublisher=Marcin Wojdyr AppPublisherURL=http://www.nieto.pl AppVersion=@VERSION@ VersionInfoVersion=@VERSION@ AppVerName=Fityk @VERSION@ OutputBaseFilename=fityk-@VERSION@-setup UninstallFilesDir={app} DefaultDirName={pf}\Fityk DefaultGroupName=Fityk ;LicenseFile=COPYING SolidCompression=yes ChangesAssociations=yes [Files] Source: fityk\*.exe; DestDir: {app} Source: fityk\*.dll; DestDir: {app} Source: COPYING; DestDir: {app} Source: TODO; DestDir: {app} Source: NEWS; DestDir: {app} Source: html\*; DestDir: {app}\html\; Flags: recursesubdirs Source: samples\README; DestDir: {app}\samples\ Source: samples\*.dat; DestDir: {app}\samples\ Source: samples\*.fit; DestDir: {app}\samples\ Source: fityk.url; DestDir: {app} [Icons] Name: {group}\Fityk; Filename: {app}\fityk.exe; WorkingDir: {app}; IconFilename: {app}\fityk.exe; IconIndex: 0 Name: {group}\Fityk CLI; Filename: {app}\cfityk.exe; WorkingDir: {app}; Name: {group}\xyConvert; Filename: {app}\xyconvert.exe; WorkingDir: {app}; Name: {group}\Fityk Manual; Filename: {app}\html\fityk-manual.html; WorkingDir: {app}; Flags: useapppaths Name: "{group}\Fityk Web Site"; Filename: {app}\fityk.url ;Name: {group}\Uninstall Fityk; Filename: {uninstallexe} Name: {userdesktop}\Fityk; Filename: {app}\fityk.exe; WorkingDir: {app}; Tasks: desktopicon Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Fityk"; Filename: {app}\fityk.exe; WorkingDir: {app}; Tasks: quicklaunchicon [Tasks] Name: desktopicon; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:" Name: quicklaunchicon; Description: "Create a &Quick Launch icon"; GroupDescription: "Additional icons:"; Flags: unchecked Name: associate; Description: "&Associate .fit files"; GroupDescription: "Other tasks:"; Flags: unchecked [INI] [Registry] Root: HKCU; SubKey: Software\.fityk\; ValueName: dummy; ValueType: none; Flags: createvalueifdoesntexist Root: HKCR; Subkey: ".fit"; ValueType: string; ValueName: ""; ValueData: "FitykScript"; Flags: uninsdeletevalue; Tasks: associate Root: HKCR; Subkey: "FitykScript"; ValueType: string; ValueName: ""; ValueData: "Fityk Script"; Flags: uninsdeletekey; Tasks: associate Root: HKCR; Subkey: "FitykScript\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\fityk.exe,0"; Tasks: associate Root: HKCR; Subkey: "FitykScript\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\fityk.exe"" ""%1"""; Tasks: associate [UninstallDelete] [InstallDelete] [Run] Filename: "{app}\fityk.exe"; Description: "Launch application"; Flags: postinstall nowait skipifsilent unchecked [UninstallRun] fityk-1.3.1/fityk.png000066400000000000000000000017011302634723100144760ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDØ@Æç pHYs  šœtIMEÖ 39ëJÊNIDATXýÖ_hVuðÏ;fY'ºš%£TÆ‚ Œ—•&ÝÓúc I HÑMnº<½DuQxá…DΤ-dd¤`œ‰Å¢cŽÞ¶¦ÛÛÅž·Îæ|·÷O>p8ç<çwÎ÷ûûþ¾Ïó;W ÆK ؉M8†' ›*ŽÃÚ[ 68ï¾k|ÞG[\/[^9¶ÎJ¡Õà]%`+Ná ~Ç ¬GœDO–šnÿÀàÚÚŒg¸DéeÕ‹öVI±;À«ÊÞ‡µøoDnûâÜÁú†W°'f½_cO–ªÈ1m¼«d7ÄÞFǼ%8„§²ÔèBßÚÖÙÙ8'§âÏx$HükÂ,5º­³žÞ”Â`í9oÄ#©½òyuP¸˜;rÍø1d®–ÖÎÂuè^âGÚêEÍÍ⽨ï‰ðÀ«¨÷{…EêúVÜ„_pjEêâ¼çkщ?ðÃHêïêóîfäÀ?ÃjLâu¼²"uq¼¤÷`Î$½ÉWCÊê_@Îå‡ÃhÕ5¾€AêY¼Œå8IoÒ?qjÚ̯“Ûñ¾Ãþ,5RlÀY¬É©à¥ p4¼VÍ»¢'|„«"OÔ"QË„'æÝOÐê˜y~«"÷t€â؈[juÏZžÃ7áòQ¼h¶¾Ïá·˜aUãᓺ£íreíóaôàN¼›ô&SIor::Ý—ø ŸbgÒ›LFiN©Jôý3 —a>Ö$sîËý嶘ÀLÒ›ÌÀÉ e]%—˜p²8…bz Qî/oÁöHÈ^ÓWœ\|§,Ö«Àeþí¶„ä+#ue©¾b õj•a½{Áý^%¾2r}ƒ9 b3&\$Ærî¯VÀX3¿rK"0øŸ¬‡1„é8†"×pj­[˜®·áœÆõ¸;†ÏÒÙW‹ÍˆÍgnÀH–Îîë]%ø÷†Zßâñ,un©&[t |+Ž„œŸQÏ›quüTöàÉéÖÂh ÙWÍë kâ|åZë…ȵ”ÀH˜« 2Ë!KÁ£± }]Yj¿H?Ç„ã³Ëð|̼?K½™©§³µ´ ¯DüÖ'´+lÊMIEND®B`‚fityk-1.3.1/fityk.svg000066400000000000000000000105361302634723100145170ustar00rootroot00000000000000 image/svg+xml fityk-1.3.1/fityk.url000066400000000000000000000000561302634723100145160ustar00rootroot00000000000000[InternetShortcut] URL=http://fityk.nieto.pl/ fityk-1.3.1/fityk.xml000066400000000000000000000010421302634723100145100ustar00rootroot00000000000000 fityk script fityk data file fityk-1.3.1/fityk/000077500000000000000000000000001302634723100137715ustar00rootroot00000000000000fityk-1.3.1/fityk/CMPfit.cpp000066400000000000000000000206071302634723100156240ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "CMPfit.h" #include "logic.h" #include "var.h" using namespace std; namespace fityk { #ifndef NDEBUG bool debug_deriv_in_mpfit=false; // changed only for tests (must be non-static) #endif static int calculate_for_mpfit(int m, int npar, double *par, double *deviates, double **derivs, void *mpfit) { return static_cast(mpfit)-> calculate(m, npar, par, deviates, derivs); } /* void on_mpfit_iteration(void *mpfit) { static_cast(mpfit)->on_iteration(); } */ int MPfit::on_iteration() { return (int) common_termination_criteria(); } int MPfit::calculate(int /*m*/, int npar, double *par, double *deviates, double **derivs) { // MP_NO_ITER is used only to calculate covariance matrix if (mp_conf_.maxiter != MP_NO_ITER) { int stop = on_iteration(); if (stop) return -1; // error code reserved for user function } vector A(par, par+npar); if (F_->get_verbosity() >= 1) output_tried_parameters(A); if (!derivs) compute_deviates(A, deviates); else compute_derivatives_mp(A, fitted_datas_, derivs, deviates); return 0; } static const char* mpstatus_to_string(int n) { switch (n) { case MP_ERR_INPUT: return "General input parameter error"; case MP_ERR_NAN: return "User function produced non-finite values"; case MP_ERR_FUNC: return "No user function was supplied"; case MP_ERR_NPOINTS: return "No user data points were supplied"; case MP_ERR_NFREE: return "No free parameters"; case MP_ERR_MEMORY: return "Memory allocation error"; case MP_ERR_INITBOUNDS: return "Initial values inconsistent w constraints"; case MP_ERR_BOUNDS: return "Initial constraints inconsistent"; case MP_ERR_PARAM: return "General input parameter error"; case MP_ERR_DOF: return "Not enough degrees of freedom"; // Potential success status codes case MP_OK_CHI: return "Convergence in chi-square value"; case MP_OK_PAR: return "Convergence in parameter value"; case MP_OK_BOTH: return "Convergence in chi2 and parameter value"; case MP_OK_DIR: return "Convergence in orthogonality"; case MP_MAXITER: return "Maximum number of evaluations reached"; case MP_FTOL: return "ftol is too small; no further improvement"; case MP_XTOL: return "xtol is too small; no further improvement"; case MP_GTOL: return "gtol is too small; no further improvement"; // user-defined codes case -1: return "One of user-defined criteria stopped fitting."; default: return "unexpected status code"; } } static mp_par* allocate_and_init_mp_par(const std::vector& par_usage) { mp_par *pars = new mp_par[par_usage.size()]; for (size_t i = 0; i < par_usage.size(); ++i) { mp_par& p = pars[i]; p.fixed = !par_usage[i]; p.limited[0] = 0; // no lower limit p.limited[1] = 0; // no upper limit p.limits[0] = 0.; p.limits[1] = 0.; p.parname = NULL; p.step = 0.; // step size for finite difference p.relstep = 0.; // relative step size for finite difference p.side = 3; // Sidedness of finite difference derivative // 0 - one-sided derivative computed automatically // 1 - one-sided derivative (f(x+h) - f(x) )/h // -1 - one-sided derivative (f(x) - f(x-h))/h // 2 - two-sided derivative (f(x+h) - f(x-h))/(2*h) // 3 - user-computed analytical derivatives p.deriv_debug = 0; p.deriv_reltol = 0.; p.deriv_abstol = 0.; } return pars; } static void zero_init_result(mp_result *result) { result->bestnorm = result->orignorm = 0.; result->niter = result->nfev = result->status = 0; result->npar = result->nfree = result->npegged = result->nfunc = 0; result->resid = result->covar = NULL; result->xerror = NULL; } static void init_config(mp_config_struct* mp_conf) { // 0 value means default mp_conf->ftol = 0.; mp_conf->xtol = 0.; mp_conf->gtol = 1e-100; mp_conf->epsfcn = 0.; mp_conf->stepfactor = 0.; mp_conf->covtol = 0.; mp_conf->maxiter = 0; mp_conf->maxfev = 0; mp_conf->nprint = 0; mp_conf->douserscale = 0; mp_conf->nofinitecheck = 0; mp_conf->iterproc = NULL; } // final_a either has the same size as parameters or is NULL int MPfit::run_mpfit(const vector& datas, const vector& parameters, const vector& param_usage, double *final_a) { assert(param_usage.size() == parameters.size()); double *a = final_a ? final_a : new double[parameters.size()]; for (size_t i = 0; i != parameters.size(); ++i) a[i] = parameters[i]; mp_par *pars = allocate_and_init_mp_par(param_usage); if (F_->get_settings()->box_constraints) { for (size_t i = 0; i < parameters.size(); ++i) { const Var* var = F_->mgr.gpos_to_var(i); if (!var->domain.lo_inf()) { pars[i].limited[0] = 1; pars[i].limits[0] = var->domain.lo; } if (!var->domain.hi_inf()) { pars[i].limited[1] = 1; pars[i].limits[1] = var->domain.hi; } } } #ifndef NDEBUG if (debug_deriv_in_mpfit) for (size_t i = 0; i < parameters.size(); ++i) { // don't use side=2 (two-side) because of bug in CMPFIT pars[i].side = 1; pars[i].deriv_debug = 1; } #endif // datas cannot be easily passed to the calculate_for_mpfit() callback // in a different way than through member variable (fitted_datas_). int status; if (&datas != &fitted_datas_) { vector saved = datas; fitted_datas_.swap(saved); status = mpfit(calculate_for_mpfit, count_points(datas), parameters.size(), a, pars, &mp_conf_, this, &result_); fitted_datas_.swap(saved); } else status = mpfit(calculate_for_mpfit, count_points(datas), parameters.size(), a, pars, &mp_conf_, this, &result_); soft_assert(status == result_.status); delete [] pars; if (final_a == NULL) delete [] a; return status; } double MPfit::run_method(vector* best_a) { init_config(&mp_conf_); mp_conf_.maxiter = -2; // can't use 0 or 1 here (0=default, -1=MP_NO_ITER) mp_conf_.maxfev = max_eval() - 1; // MPFIT has 1 evaluation extra mp_conf_.ftol = F_->get_settings()->ftol_rel; mp_conf_.xtol = F_->get_settings()->xtol_rel; //mp_conf_.gtol = F_->get_settings()->mpfit_gtol; zero_init_result(&result_); double *a = new double[na_]; int status = run_mpfit(fitted_datas_, a_orig_, par_usage(), a); //soft_assert(result_.nfev + 1 == evaluations_); F_->msg("mpfit status: " + S(mpstatus_to_string(status))); best_a->assign(a, a+na_); delete [] a; return result_.bestnorm; } vector MPfit::get_covariance_matrix(const vector& datas) { update_par_usage(datas); vector alpha(na_*na_, 0.); init_config(&mp_conf_); mp_conf_.maxiter = MP_NO_ITER; zero_init_result(&result_); result_.covar = &alpha[0]; // that's legal, vectors use contiguous storage int status = run_mpfit(datas, F_->mgr.parameters(), par_usage()); soft_assert(status == MP_MAXITER); result_.covar = NULL; return alpha; } vector MPfit::get_standard_errors(const vector& datas) { double wssr = compute_wssr(F_->mgr.parameters(), datas, true); double err_factor = sqrt(wssr / get_dof(datas)); // `na_' was set by get_dof() above, from update_par_usage() vector errors(na_, 0.); init_config(&mp_conf_); mp_conf_.maxiter = MP_NO_ITER; zero_init_result(&result_); result_.xerror = &errors[0]; // that's legal int status = run_mpfit(datas, F_->mgr.parameters(), par_usage()); soft_assert(status == MP_MAXITER || status == MP_OK_DIR); result_.xerror = NULL; for (int i = 0; i < na_; ++i) errors[i] *= err_factor; return errors; } } // namespace fityk fityk-1.3.1/fityk/CMPfit.h000066400000000000000000000023641302634723100152710ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// wrapper around MPFIT (cmpfit) library, /// http://www.physics.wisc.edu/~craigm/idl/cmpfit.html /// which is Levenberg-Marquardt implementation based on MINPACK-1 #ifndef FITYK_MPFIT_H_ #define FITYK_MPFIT_H_ #include "fit.h" #include "cmpfit/mpfit.h" namespace fityk { /// Wrapper around CMPFIT class MPfit : public Fit { public: MPfit(Full* F, const char* name) : Fit(F, name) {} virtual double run_method(std::vector* best_a); // implementation (must be public to be called inside callback function) int calculate(int m, int npar, double *par, double *deviates, double **derivs); int on_iteration(); virtual std::vector get_covariance_matrix(const std::vector& datas); virtual std::vector get_standard_errors(const std::vector& datas); private: mp_config_struct mp_conf_; mp_result result_; int run_mpfit(const std::vector& datas, const std::vector& parameters, const std::vector& param_usage, double *final_a=NULL); }; } // namespace fityk #endif fityk-1.3.1/fityk/GAfit.cpp000066400000000000000000000360151302634723100154740ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "GAfit.h" #include #include #include #include #include #include "common.h" #include "logic.h" #include "settings.h" #include "numfuncs.h" using namespace std; namespace fityk { GAfit::GAfit(Full* F, const char* name) : Fit(F, name), popsize (100), elitism(0), mutation_type('u'), p_mutation(0.1), mutate_all_genes(false), mutation_strength(0.1), crossover_type('u'), p_crossover(0.3), selection_type('r'), rank_scoring(false), tournament_size(2), window_size(-1), linear_scaling_a(1.), linear_scaling_c(2.), linear_scaling_b (1.), std_dev_stop(0), iter_with_no_progresss_stop(0), autoplot_indiv_nr(-1), pop(0), opop(0), best_indiv(0) { /* irpar["population-size"] = IntRange (&popsize, 2, 9999); irpar["steady-size"] = IntRange (&elitism, 0, 9999); epar.insert(pair("mutation-type", Enum_string (Distrib_enum, &mutation_type))); fpar["p-mutation"] = &p_mutation; bpar["mutate-all-genes"] = &mutate_all_genes; fpar["mutation-strength"] = &mutation_strength; */ Crossover_enum ['u'] = "uniform"; Crossover_enum ['o'] = "one-point"; Crossover_enum ['t'] = "two-point"; Crossover_enum ['a'] = "arithmetic1"; Crossover_enum ['A'] = "arithmetic2"; Crossover_enum ['g'] = "guaranteed-avg"; /* epar.insert(pair("crossover-type", Enum_string (Crossover_enum, &crossover_type))); fpar["p-crossover"] = &p_crossover; */ Selection_enum ['r'] = "roulette"; Selection_enum ['t'] = "tournament"; Selection_enum ['s'] = "srs"; Selection_enum ['d'] = "ds"; /* epar.insert (pair("selection-type", Enum_string (Selection_enum, &selection_type))); bpar["rank-scoring"] = &rank_scoring; irpar["tournament-size"] = IntRange (&tournament_size, 2, 999); irpar["window-size"] = IntRange (&window_size, -1, 199); fpar["linear-scaling-a"] = &linear_scaling_a; fpar["linear-scaling-c"] = &linear_scaling_c; fpar["linear-scaling-b"] = &linear_scaling_b; fpar["rel-std-dev-stop"] = &std_dev_stop; ipar["iterations-with-no-progresss-stop"] = &iter_with_no_progresss_stop; irpar["autoplot-indiv-nr"] = IntRange(&autoplot_indiv_nr, -1, 999999999); */ } GAfit::~GAfit() {} double GAfit::run_method(std::vector* best_a) { pop = &pop1; opop = &pop2; pop->resize (popsize); vector::iterator best = pop->begin(); for (vector::iterator i = pop->begin(); i != pop->end(); ++i) { i->g.resize(na_); for (int j = 0; j < na_; ++j) i->g[j] = draw_a_from_distribution(j); compute_wssr_for_ind (i); if (i->raw_score < best->raw_score) best = i; } best_indiv = *best; assert (pop && opop); if (elitism >= popsize) { F_->ui()->warn("hmm, now elitism >= popsize, setting elitism = 1"); elitism = 1; } for (int iter = 0; !termination_criteria_and_print_info(iter); iter++) { autoplot_in_run(); pre_selection(); crossover(); mutation(); post_selection(); } *best_a = best_indiv.g; return best_indiv.raw_score; } void GAfit::compute_wssr_for_ind (vector::iterator ind) { ind->raw_score = compute_wssr(ind->g, fitted_datas_); } void GAfit::autoplot_in_run() { const Individual& indiv = is_index(autoplot_indiv_nr, *pop) ? (*pop)[autoplot_indiv_nr] : best_indiv; iteration_plot(indiv.g, indiv.raw_score); } void GAfit::mutation() { for (vector::iterator i = pop->begin(); i != pop->end(); ++i) { if (mutate_all_genes) { if (rand() < RAND_MAX * p_mutation) { for (int j = 0; j < na_; ++j) i->g[j] = draw_a_from_distribution(j, mutation_type, mutation_strength); compute_wssr_for_ind (i); } } else for (int j = 0; j < na_; ++j) if (rand() < RAND_MAX * p_mutation) { i->g[j] = draw_a_from_distribution(j, mutation_type, mutation_strength); compute_wssr_for_ind (i); } } } void GAfit::crossover() { for (vector::iterator i = pop->begin(); i != pop->end(); ++i) if (rand() < RAND_MAX / 2 * p_crossover) { vector::iterator i2 = pop->begin() + rand()%pop->size(); switch (crossover_type) { case 'u': uniform_crossover (i, i2); break; case 'o': one_point_crossover (i, i2); break; case 't': two_points_crossover (i, i2); break; case 'a': arithmetic_crossover1 (i, i2); break; case 'A': arithmetic_crossover2 (i, i2); break; case 'g': guaranteed_avarage_crossover (i, i2); break; default: F_->ui()->warn("No such crossover-type: " + S(crossover_type) + ". Setting to 'u'"); crossover_type = 'u'; uniform_crossover (i, i2); break; } compute_wssr_for_ind (i); compute_wssr_for_ind (i2); } } void GAfit::uniform_crossover (vector::iterator c1, vector::iterator c2) { for (int i = 0; i < na_; ++i) if (rand() % 2) swap(c1->g[i], c2->g[i]); } void GAfit::one_point_crossover (vector::iterator c1, vector::iterator c2) { int p = rand() % na_; for (int j = 0; j < p; ++j) swap(c1->g[j], c2->g[j]); } void GAfit::two_points_crossover (vector::iterator c1, vector::iterator c2) { int p1 = rand() % na_; int p2 = rand() % na_; for (int j = min(p1, p2); j < max(p1, p2); ++j) swap(c1->g[j], c2->g[j]); } void GAfit::arithmetic_crossover1 (vector::iterator c1, vector::iterator c2) { realt a = rand_0_1(); for (int j = 0; j < na_; ++j) { c1->g[j] = a * c1->g[j] + (1 - a) * c2->g[j]; c2->g[j] = (1 - a) * c1->g[j] + a * c2->g[j]; ; } } void GAfit::arithmetic_crossover2 (vector::iterator c1, vector::iterator c2) { for (int j = 0; j < na_; ++j) { realt a = rand_0_1(); c1->g[j] = a * c1->g[j] + (1 - a) * c2->g[j]; c2->g[j] = (1 - a) * c1->g[j] + a * c2->g[j]; ; } } void GAfit::guaranteed_avarage_crossover (vector::iterator c1, vector::iterator c2) { for (int j = 0; j < na_; ++j) c1->g[j] = c2->g[j] = (c1->g[j] + c2->g[j]) / 2; } void GAfit::pre_selection() { vector next(popsize - elitism); switch (selection_type) { case 'r': scale_score(); roulette_wheel_selection(next); break; case 't': tournament_selection(next); break; case 's': scale_score(); stochastic_remainder_sampling(next); break; case 'd': scale_score(); deterministic_sampling_selection(next); break; default: F_->ui()->warn("No such selection-type: " + S((char)selection_type) + ". Setting to 'r'"); selection_type = 'r'; pre_selection (); return; } opop->resize(next.size(), Individual(na_)); for (int i = 0; i < size(next); ++i) (*opop)[i] = (*pop)[next[i]]; swap (pop, opop); } void GAfit::post_selection() { if (elitism == 0) return; do_rank_scoring (opop); for (vector::iterator i = opop->begin(); i != opop->end(); ++i) if (i->phase_2_score < elitism) pop->push_back (*i); assert (size(*pop) == popsize); } struct ind_raw_sc_cmp { bool operator() (Individual* a, Individual* b) { return a->raw_score < b->raw_score; } }; void GAfit::do_rank_scoring(vector *popp) { // rank in population is assigned to phase_2_score // e.g. 0 - the best, 1 - second, (popp.size() - 1) - worst static vector ind_p; ind_p.resize(popp->size()); for (unsigned int i = 0; i < popp->size(); ++i) ind_p[i] = &(*popp)[i]; sort (ind_p.begin(), ind_p.end(), ind_raw_sc_cmp()); for (unsigned int i = 0; i < popp->size(); ++i) ind_p[i]->phase_2_score = i; } void GAfit::roulette_wheel_selection(vector& next) { vector roulette(pop->size()); //preparing roulette unsigned int t = 0; for (int i = 0; i < size(*pop) - 1; ++i) { t += static_cast ((*pop)[i].norm_score * RAND_MAX / size(*pop)); roulette[i] = t; } roulette[size(*pop) - 1] = RAND_MAX; //end of preparing roulette for (vector::iterator i = next.begin(); i != next.end(); ++i) *i = lower_bound (roulette.begin(), roulette.end(), static_cast(rand())) - roulette.begin(); } void GAfit::tournament_selection(vector& next) { for (vector::iterator i = next.begin(); i != next.end(); ++i) { int best = rand() % pop->size(); for (int j = 1; j < tournament_size; ++j) { int n = rand() % pop->size(); if ((*pop)[n].raw_score < (*pop)[best].raw_score) best = n; } *i = best; } } vector::iterator GAfit::SRS_and_DS_common (vector& next) { vector::iterator r = next.begin(); realt f = 1.0 * next.size() / pop->size(); // rescaling for steady-state for (unsigned int i = 0; i < pop->size(); ++i) { int n = static_cast((*pop)[i].norm_score * f); fill (r, min (r + n, next.end()), i); r += n; } return min (r, next.end()); } void GAfit::stochastic_remainder_sampling(vector& next) { vector::iterator r = SRS_and_DS_common (next); if (r == next.end()) return; vector rest_of_next (next.end() - r); copy (rest_of_next.begin(), rest_of_next.end(), r); } struct Remainder_and_ptr { int ind; realt r; bool operator< (const Remainder_and_ptr &b) const { return r < b.r; } }; void GAfit::deterministic_sampling_selection(vector& next) { vector::iterator r = SRS_and_DS_common (next); if (r == next.end()) return; static vector rem; rem.resize(pop->size()); for (unsigned int i = 0; i < pop->size(); ++i) { rem[i].ind = i; realt x = (*pop)[i].norm_score; rem[i].r = x - floor(x); } int rest = next.end() - r; partial_sort (rem.begin(), rem.begin() + rest, rem.end()); for (int i = 0; i < rest; ++i, ++r) *r = rem[i].ind; assert (r == next.end()); } void GAfit::scale_score () //return value - are individuals varying? { if (rank_scoring) do_rank_scoring(pop); else for (vector::iterator i = pop->begin(); i !=pop->end(); ++i) i->phase_2_score = i->raw_score; //scaling p -> q - p; p -> p /

realt q = max_in_window(); if (q < 0) q = std_dev_based_q(); q += linear_scaling_b; realt sum = 0; for (vector::iterator i = pop->begin(); i != pop->end(); ++i) { i->reversed_score = max(q - i->phase_2_score, (realt) 0.); sum += i->reversed_score; } if (sum == 0) //to avoid x/0 return; realt avg_rev_sc = sum / pop->size(); for (vector::iterator i = pop->begin(); i != pop->end(); ++i) i->norm_score = i->reversed_score / avg_rev_sc; } realt GAfit::std_dev_based_q() { realt sum_p = 0, sum_p2 = 0; for (vector::iterator i = pop->begin(); i != pop->end(); ++i) { sum_p += i->phase_2_score; sum_p2 += i->phase_2_score * i->phase_2_score; } realt avg_p2 = sum_p2 / pop->size(); realt avg_p = sum_p / pop->size(); realt sq_sigma = avg_p2 - avg_p * avg_p; realt sigma = sq_sigma > 0 ? sqrt (sq_sigma) : 0; //because of problem with return linear_scaling_a * avg_p + linear_scaling_c * sigma; // sqrt(0) } realt GAfit::max_in_window () { // stores the worst raw_score in every of last hist_len generations // return the worst (max) raw_score in last window_size generations const int hist_len = 200; static deque max_raw_history (hist_len, 0); max_raw_history.push_front (tmp_max); max_raw_history.pop_back(); assert (window_size <= hist_len); if (window_size > 0) { if (rank_scoring) return size(*pop) - 1; else return *max_element (max_raw_history.begin(), max_raw_history.begin() + window_size); } else return -1; } bool GAfit::termination_criteria_and_print_info(int iter) { static int no_progress_iters = 0; realt sum = 0; realt min = pop->front().raw_score; tmp_max = min; vector::iterator ibest = pop->begin(); for (vector::iterator i = pop->begin(); i != pop->end(); ++i) { if (i->raw_score < min) { min = i->raw_score; ibest = i; } if (i->raw_score > tmp_max) tmp_max = i->raw_score; sum += i->raw_score; } realt avg = sum / pop->size(); realt sq_sum = 0; for (vector::iterator i = pop->begin(); i != pop->end(); ++i) { realt d = i->raw_score - avg; sq_sum += d * d; } realt std_dev = sq_sum > 0 ? sqrt (sq_sum / pop->size()) : 0; F_->msg("Population #" + S(iter) + ": best " + S(min) + ", avg " + S(avg) + ", worst " + S(tmp_max) + ", std dev. " + S(std_dev)); if (min < best_indiv.raw_score) { best_indiv = *ibest; no_progress_iters = 0; } else no_progress_iters ++; //checking stop conditions bool stop = false; if (common_termination_criteria()) stop = true; if (std_dev < std_dev_stop * avg) { F_->msg("Standard deviation of results is small enough to stop"); stop = true; } if (iter_with_no_progresss_stop > 0 && no_progress_iters >= iter_with_no_progresss_stop) { F_->msg("No progress in " + S(no_progress_iters) + " iterations. Stop"); stop = true; } return stop; } } // namespace fityk fityk-1.3.1/fityk/GAfit.h000066400000000000000000000057201302634723100151400ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_GAFIT_H_ #define FITYK_GAFIT_H_ #include #include #include "fityk.h" // realt #include "fit.h" namespace fityk { /// Individual in Genetic Algorithms (i.e. candidate solutions) struct Individual { std::vector g; realt raw_score, phase_2_score, reversed_score, norm_score; Individual (int n) : g(n), raw_score(0) {} Individual () : g(), raw_score(0) {} }; /// Genetic Algorithm method class GAfit : public Fit { public: GAfit(Full* F, const char* name); ~GAfit(); virtual double run_method(std::vector* best_a); private: int popsize; int elitism; // = 0, 1, ... popsize char mutation_type; realt p_mutation; bool mutate_all_genes; realt mutation_strength; char crossover_type; realt p_crossover; char selection_type; bool rank_scoring; int tournament_size; int window_size; realt linear_scaling_a, linear_scaling_c, linear_scaling_b; realt std_dev_stop; int iter_with_no_progresss_stop; int autoplot_indiv_nr; std::vector pop1, pop2, *pop, *opop; int iteration; Individual best_indiv; realt tmp_max; std::map Crossover_enum; std::map Selection_enum; void mutation(); void crossover(); void uniform_crossover (std::vector::iterator c1, std::vector::iterator c2); void one_point_crossover (std::vector::iterator c1, std::vector::iterator c2); void two_points_crossover (std::vector::iterator c1, std::vector::iterator c2); void arithmetic_crossover1 (std::vector::iterator c1, std::vector::iterator c2); void arithmetic_crossover2 (std::vector::iterator c1, std::vector::iterator c2); void guaranteed_avarage_crossover (std::vector::iterator c1, std::vector::iterator c2); void scale_score (); void pre_selection(); void post_selection(); realt max_in_window (); realt std_dev_based_q(); void do_rank_scoring(std::vector *popp); void roulette_wheel_selection (std::vector& next); void tournament_selection (std::vector& next); void stochastic_remainder_sampling(std::vector& next); void deterministic_sampling_selection(std::vector& next); std::vector::iterator SRS_and_DS_common (std::vector& next); bool termination_criteria_and_print_info (int iter); void print_post_fit_info (realt wssr_before); void autoplot_in_run(); void compute_wssr_for_ind (std::vector::iterator ind); }; } // namespace fityk #endif fityk-1.3.1/fityk/LMfit.cpp000066400000000000000000000122151302634723100155110ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "LMfit.h" #include #include #include "common.h" #include "ui.h" #include "settings.h" #include "logic.h" #include "numfuncs.h" using namespace std; namespace fityk { // note: WSSR is also called chi2 double LMfit::run_method(std::vector* best_a) { const realt stop_rel = F_->get_settings()->lm_stop_rel_change; const realt max_lambda = F_->get_settings()->lm_max_lambda; double lambda = F_->get_settings()->lm_lambda_start; alpha_.resize(na_*na_); beta_.resize(na_); *best_a = a_orig_; if (F_->get_verbosity() >= 2) { F_->ui()->mesg(format_matrix(a_orig_, 1, na_, "Initial A")); F_->ui()->mesg("Starting with lambda=" + S(lambda)); if (stop_rel > 0) F_->ui()->mesg("Will stop when relative change of WSSR is " "twice in row below " + S(stop_rel * 100.) + "%"); } realt chi2 = initial_wssr_; compute_derivatives(a_orig_, fitted_datas_, alpha_, beta_); int small_change_counter = 0; for (int iter = 0; !common_termination_criteria(); iter++) { prepare_next_parameters(lambda, *best_a); // -> temp_beta_ double new_chi2 = compute_wssr(temp_beta_, fitted_datas_); if (F_->get_verbosity() >= 1) F_->ui()->mesg(iteration_info(new_chi2) + format1(" lambda=%.5g", lambda) + format1(" iter #%d", iter)); if (new_chi2 < chi2) { realt rel_change = (chi2 - new_chi2) / chi2; chi2 = new_chi2; *best_a = temp_beta_; // termination criterium: negligible change of chi2 if (rel_change < stop_rel || chi2 == 0) { small_change_counter++; if (small_change_counter >= 2 || chi2 == 0) { F_->msg("... converged."); break; } } else small_change_counter = 0; compute_derivatives(*best_a, fitted_datas_, alpha_, beta_); lambda /= F_->get_settings()->lm_lambda_down_factor; } else { // worse fitting // termination criterium: large lambda if (lambda > max_lambda) { F_->msg("In L-M method: lambda=" + S(lambda) + " > " + S(max_lambda) + ", stopped."); break; } lambda *= F_->get_settings()->lm_lambda_up_factor; } iteration_plot(*best_a, chi2); } return chi2; } // puts result into temp_beta_ void LMfit::prepare_next_parameters(double lambda, const vector &a) { temp_alpha_ = alpha_; for (int j = 0; j < na_; j++) temp_alpha_[na_ * j + j] *= (1.0 + lambda); temp_beta_ = beta_; if (F_->get_verbosity() > 2) { // level: debug F_->ui()->mesg(format_matrix(temp_beta_, 1, na_, "beta")); F_->ui()->mesg(format_matrix(temp_alpha_, na_, na_, "alpha'")); } // Matrix solution (Ax=b) temp_alpha_ * da == temp_beta_ jordan_solve(temp_alpha_, temp_beta_, na_); for (int i = 0; i < na_; i++) // put new a[] into temp_beta_[] temp_beta_[i] = a[i] + temp_beta_[i]; if (F_->get_verbosity() >= 2) output_tried_parameters(temp_beta_); } vector LMfit::get_covariance_matrix(const vector& datas) { update_par_usage(datas); vector alpha(na_*na_, 0.); vector beta(na_); compute_derivatives(F_->mgr.parameters(), datas, alpha, beta); // To avoid singular matrix, put fake values corresponding to unused // parameters. for (int i = 0; i < na_; ++i) if (!par_usage()[i]) { alpha[i*na_ + i] = 1.; } // We may have unused parameters with par_usage_[] set true, // e.g. SplitGaussian with center < min(active x) has hwhm1 unused. // If i'th column/row in alpha are only zeros, we must // do something about it -- standard error is undefined vector undef; for (int i = 0; i < na_; ++i) { bool has_nonzero = false; for (int j = 0; j < na_; j++) if (alpha[na_*i+j] != 0.) { has_nonzero = true; break; } if (!has_nonzero) { undef.push_back(i); alpha[i*na_ + i] = 1.; } } invert_matrix(alpha, na_); v_foreach (int, i, undef) alpha[(*i)*na_ + (*i)] = 0.; #if USE_LONG_DOUBLE return vector(alpha.begin(), alpha.end()); #else return alpha; #endif } vector LMfit::get_standard_errors(const vector& datas) { const vector &pp = F_->mgr.parameters(); realt wssr = compute_wssr(pp, datas, true); int dof = get_dof(datas); // `na_' was set by get_dof() above, from update_par_usage() vector errors(na_); vector alpha = get_covariance_matrix(datas); // `na_' was set by functions above for (int i = 0; i < na_; ++i) errors[i] = sqrt(wssr / dof * alpha[i*na_ + i]); return errors; } } // namespace fityk fityk-1.3.1/fityk/LMfit.h000066400000000000000000000021171302634723100151560ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Simple implementation of the Levenberg-Marquardt method, /// uses Jordan elimination with partial pivoting. #ifndef FITYK_LMFIT_H_ #define FITYK_LMFIT_H_ #include #include "fityk.h" #include "fit.h" namespace fityk { class LMfit : public Fit { public: LMfit(Full* F, const char* name) : Fit(F, name) {} virtual double run_method(std::vector* best_a); // the same methods that were used for all methods up to ver. 1.2.1 // (just for backward compatibility) virtual std::vector get_covariance_matrix(const std::vector& datas); virtual std::vector get_standard_errors(const std::vector& datas); private: std::vector alpha_; // matrix std::vector beta_; // and vector // working arrays in do_iteration() std::vector temp_alpha_, temp_beta_; void prepare_next_parameters(double lambda, const std::vector &a); }; } // namespace fityk #endif fityk-1.3.1/fityk/Makefile.am000066400000000000000000000075531302634723100160370ustar00rootroot00000000000000EXTRA_DIST = swig/fityk_perl.cpp swig/Fityk.pm swig/fityk_ruby.cpp swig/java/ \ swig/fityk.i BUILT_SOURCES = swig/fityk_lua.cpp swig/luarun.h lib_LTLIBRARIES = libfityk.la libfityk_la_LDFLAGS = $(LIBRARY_VERSION_FLAG) -no-undefined libfityk_la_LIBADD = -lxy -lz $(LUA_LIB) libfityk_la_CPPFLAGS = $(LUA_INCLUDE) libfityk_la_SOURCES = logic.cpp view.cpp lexer.cpp eparser.cpp cparser.cpp \ runner.cpp info.cpp common.cpp data.cpp var.cpp mgr.cpp \ tplate.cpp func.cpp udf.cpp bfunc.cpp f_fcjasym.cpp ast.cpp \ vm.cpp transform.cpp settings.cpp ui.cpp ui_api.cpp \ luabridge.cpp GAfit.cpp LMfit.cpp guess.cpp NMfit.cpp \ model.cpp fit.cpp voigt.cpp numfuncs.cpp fityk.cpp \ \ logic.h view.h lexer.h eparser.h cparser.h \ runner.h info.h common.h data.h var.h mgr.h \ tplate.h func.h udf.h bfunc.h f_fcjasym.h ast.h \ vm.h transform.h settings.h ui.h luabridge.h \ GAfit.h LMfit.h guess.h NMfit.h \ model.h fit.h voigt.h numfuncs.h \ swig/fityk_lua.cpp swig/luarun.h \ CMPfit.cpp CMPfit.h cmpfit/mpfit.c cmpfit/mpfit.h if NLOPT_ENABLED libfityk_la_SOURCES += NLfit.cpp NLfit.h endif pkginclude_HEADERS = fityk.h ui_api.h # Undocumented feature: if Lua 5.2 source is unpacked into ./lua52 # and LUA52_FROM_SOURCE=yes liblua is built as part of libfityk. if COMPILE_LUA_SRC nodist_libfityk_la_SOURCES = \ lua52/src/lapi.c \ lua52/src/lcode.c \ lua52/src/lctype.c \ lua52/src/ldebug.c \ lua52/src/ldo.c \ lua52/src/ldump.c \ lua52/src/lfunc.c \ lua52/src/lgc.c \ lua52/src/llex.c \ lua52/src/lmem.c \ lua52/src/lobject.c \ lua52/src/lopcodes.c \ lua52/src/lparser.c \ lua52/src/lstate.c \ lua52/src/lstring.c \ lua52/src/ltable.c \ lua52/src/ltm.c \ lua52/src/lundump.c \ lua52/src/lvm.c \ lua52/src/lzio.c \ lua52/src/lauxlib.c \ lua52/src/lbaselib.c \ lua52/src/lbitlib.c \ lua52/src/lcorolib.c \ lua52/src/ldblib.c \ lua52/src/liolib.c \ lua52/src/lmathlib.c \ lua52/src/loslib.c \ lua52/src/lstrlib.c \ lua52/src/ltablib.c \ lua52/src/loadlib.c \ lua52/src/linit.c endif # --- directory swig/ --- if PYTHON_ENABLED python_PYTHON = $(srcdir)/swig/fityk.py pyexec_LTLIBRARIES = swig/_fityk.la endif swig__fityk_la_SOURCES = swig/fityk_python.cpp swig__fityk_la_CPPFLAGS = $(PYTHON_CPPFLAGS) -I$(srcdir) swig__fityk_la_LDFLAGS = -module -avoid-version -shared -no-undefined swig__fityk_la_LIBADD = libfityk.la $(srcdir)/swig/luarun.h: $(SWIG) -c++ -lua -external-runtime $@ $(srcdir)/swig/fityk_python.cpp: swig/fityk.i fityk.h ui_api.h $(SWIG) -c++ -python -I$(srcdir) -o $@ $< $(srcdir)/swig/fityk.py: $(srcdir)/swig/fityk_python.cpp $(srcdir)/swig/fityk_lua.cpp: swig/fityk.i fityk.h $(SWIG) -c++ -lua -I$(srcdir) -o $@ $< $(srcdir)/swig/fityk_perl.cpp: swig/fityk.i fityk.h $(SWIG) -c++ -perl -I$(srcdir) -o $@ $< $(srcdir)/swig/Fityk.pm: $(srcdir)/swig/fityk_perl.cpp $(srcdir)/swig/fityk_ruby.cpp: swig/fityk.i fityk.h $(SWIG) -c++ -ruby -I$(srcdir) -o $@ $< $(srcdir)/swig/java/fityk_java.cpp: swig/fityk.i fityk.h mkdir -p $(srcdir)/swig/java $(SWIG) -c++ -java -I$(srcdir) -o $@ -package fityk -outdir $(srcdir)/swig/java $< perl: swig/fityk_perl.o mkdir -p swig/perl $(CXX) -shared $< -L./.libs -lfityk -o swig/perl/Fityk.so ruby: swig/fityk_ruby.o mkdir -p swig/ruby $(CXX) -shared $(CXXFLAGS) $(LDFLAGS) $< -L./.libs -lfityk -o swig/ruby/fityk.so java: swig/java/fityk_java.o $(CXX) -shared $(CXXFLAGS) $(LDFLAGS) $< -L./.libs -lfityk -o swig/java/libfitykJ.so # requires perl-ExtUtils-Embed swig/fityk_perl.o: swig/fityk_perl.cpp $(CXX) -fPIC `perl -MExtUtils::Embed -e perl_inc` -I$(srcdir) -o $@ -c $< swig/fityk_ruby.o: swig/fityk_ruby.cpp $(CXX) $(CPPFLAGS) -I$(srcdir) \ -I`ruby -e "require 'rbconfig'; puts Config::CONFIG['archdir']"` \ $(CXXFLAGS) -fPIC -o $@ -c $< swig/java/fityk_java.o: swig/java/fityk_java.cpp mkdir -p swig/java $(CXX) $(CPPFLAGS) -I$(srcdir) \ $(CXXFLAGS) -fno-strict-aliasing -fPIC -o $@ -c $< fityk-1.3.1/fityk/NLfit.cpp000066400000000000000000000065011302634723100155130ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "NLfit.h" #include "logic.h" #include "settings.h" #include "var.h" #if HAVE_LIBNLOPT using namespace std; namespace fityk { NLfit::NLfit(Full* F, const char* name, nlopt_algorithm algorithm) : Fit(F, name), algorithm_(algorithm), opt_(NULL) { } NLfit::~NLfit() { if (opt_ != NULL) nlopt_destroy(opt_); } static double calculate_for_nlopt(unsigned n, const double* x, double* grad, void* f_data) { return static_cast(f_data)->calculate(n, x, grad); } double NLfit::calculate(int n, const double* par, double* grad) { assert(n == na_); vector A(par, par+n); if (F_->get_verbosity() >= 1) output_tried_parameters(A); bool stop = common_termination_criteria(); if (stop) nlopt_force_stop(opt_); double wssr; if (!grad || stop) wssr = compute_wssr(A, fitted_datas_); else wssr = compute_wssr_gradient(A, fitted_datas_, grad); if (F_->get_verbosity() >= 1) F_->ui()->mesg(iteration_info(wssr)); return wssr; } static const char* nlresult_to_string(nlopt_result r) { switch (r) { case NLOPT_FAILURE: return "failure"; case NLOPT_INVALID_ARGS: return "invalid arguments"; case NLOPT_OUT_OF_MEMORY: return "out of memory"; case NLOPT_ROUNDOFF_LIMITED: return "roundoff errors limit progress"; case NLOPT_FORCED_STOP: return "interrupted"; case NLOPT_SUCCESS: return "success"; case NLOPT_STOPVAL_REACHED: return "stop-value reached"; case NLOPT_FTOL_REACHED: return "ftol-value reached"; case NLOPT_XTOL_REACHED: return "xtol-value reached"; case NLOPT_MAXEVAL_REACHED: return "max. evaluation number reached"; case NLOPT_MAXTIME_REACHED: return "max. time reached"; } return NULL; } double NLfit::run_method(vector* best_a) { if (opt_ != NULL && na_ != (int) nlopt_get_dimension(opt_)) { nlopt_destroy(opt_); opt_ = NULL; } if (opt_ == NULL) { opt_ = nlopt_create(algorithm_, na_); nlopt_set_min_objective(opt_, calculate_for_nlopt, this); } // this is also handled in Fit::common_termination_criteria() nlopt_set_maxtime(opt_, F_->get_settings()->max_fitting_time); nlopt_set_maxeval(opt_, max_eval() - 1); // save 1 eval for final calc. nlopt_set_ftol_rel(opt_, F_->get_settings()->ftol_rel); nlopt_set_xtol_rel(opt_, F_->get_settings()->xtol_rel); if (F_->get_settings()->box_constraints) { double *lb = new double[na_]; double *ub = new double[na_]; for (int i = 0; i < na_; ++i) { const RealRange& d = F_->mgr.get_variable(i)->domain; lb[i] = d.lo; ub[i] = d.hi; } nlopt_set_lower_bounds(opt_, lb); nlopt_set_upper_bounds(opt_, ub); delete [] lb; delete [] ub; } double opt_f; double *a = new double[na_]; for (int i = 0; i < na_; ++i) a[i] = a_orig_[i]; nlopt_result r = nlopt_optimize(opt_, a, &opt_f); F_->msg("NLopt says: " + S(nlresult_to_string(r))); best_a->assign(a, a+na_); delete [] a; return opt_f; } } // namespace fityk #endif //HAVE_LIBNLOPT fityk-1.3.1/fityk/NLfit.h000066400000000000000000000016341302634723100151620ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ /// wrapper around NLopt library, http://ab-initio.mit.edu/nlopt/ /// which is a library for nonlinear optimization with a common interface /// for a number of different algorithms. #ifndef FITYK_NLFIT_H_ #define FITYK_NLFIT_H_ #if HAVE_CONFIG_H # include #endif #if HAVE_LIBNLOPT #include #include "fit.h" namespace fityk { class NLfit : public Fit { public: NLfit(Full* F, const char* name, nlopt_algorithm algorithm); ~NLfit(); virtual double run_method(std::vector* best_a); // implementation (must be public to be called inside callback function) double calculate(int n, const double* par, double* grad); private: nlopt_algorithm algorithm_; nlopt_opt opt_; }; } // namespace fityk #endif //HAVE_LIBNLOPT #endif // FITYK_NLFIT_H_ fityk-1.3.1/fityk/NMfit.cpp000066400000000000000000000122171302634723100155150ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "NMfit.h" #include #include #include #include #include "common.h" #include "logic.h" #include "settings.h" using namespace std; namespace fityk { void NMfit::init() { bool move_all = F_->get_settings()->nm_move_all; char distrib = F_->get_settings()->nm_distribution[0]; realt factor = F_->get_settings()->nm_move_factor; // 1. all n+1 vertices are the same Vertex v(a_orig_); vertices = vector (na_ + 1, v); // 2. na_ of na_+1 vertices has one coordinate changed; computing WSSR for (int i = 0; i < na_; ++i) { vertices[i + 1].a[i] = draw_a_from_distribution(i, distrib, factor); if (move_all) { realt d2 = (vertices[i + 1].a[i] - vertices[0].a[i]) / 2; for (vector::iterator j = vertices.begin(); j != vertices.end(); ++j) j->a[i] -= d2; } } for (vector::iterator i = vertices.begin(); i!=vertices.end(); ++i) compute_v (*i); // 3. find_best_worst(); compute_coord_sum(); volume_factor = 1.; } void NMfit::find_best_worst() { // finding best, second best and worst vertex if (vertices[0].wssr < vertices[1].wssr) { worst = vertices.begin() + 1; s_worst = best = vertices.begin(); } else { worst = vertices.begin(); s_worst = best = vertices.begin() + 1; } for (vector::iterator i = vertices.begin(); i!=vertices.end(); ++i){ if (i->wssr < best->wssr) best = i; if (i->wssr > worst->wssr) { s_worst = worst; worst = i; } else if (i->wssr > s_worst->wssr && i != worst) s_worst = i; } } double NMfit::run_method(vector* best_a) { init(); realt convergence = F_->get_settings()->nm_convergence; for (int iter = 0; !termination_criteria(iter, convergence); ++iter) { change_simplex(); find_best_worst(); iteration_plot(best->a, best->wssr); } *best_a = best->a; return best->wssr; } void NMfit::change_simplex() { realt t = try_new_worst (-1.); if (t <= best->wssr) try_new_worst (2.); else if (t >= s_worst->wssr) { realt old = worst->wssr; realt t2 = try_new_worst(0.5); if (t2 >= old) { // than multiple contraction for (vector::iterator i = vertices.begin(); i != vertices.end() ;++i) { if (i == best) continue; for (int j = 0; j < na_; ++j) i->a[j] = (i->a[j] + best->a[j]) / 2; compute_v (*i); volume_factor *= 0.5; } compute_coord_sum(); } } } realt NMfit::try_new_worst(realt f) //extrapolates by a factor f through the face of the simplex across //from the high point, tries it, //and replaces the high point if the new point is better. { Vertex t(na_); realt f1 = (1 - f) / na_; realt f2 = f1 - f; for (int i = 0; i < na_; ++i) t.a[i] = coord_sum[i] * f1 - worst->a[i] * f2; compute_v (t); if (t.wssr < worst->wssr) { for (int i = 0; i < na_; ++i) coord_sum[i] += t.a[i] - worst->a[i]; *worst = t; volume_factor *= f; } return t.wssr; } void NMfit::compute_coord_sum() { coord_sum.resize(na_); fill (coord_sum.begin(), coord_sum.end(), 0.); for (int i = 0; i < na_; ++i) for (vector::iterator j = vertices.begin(); j != vertices.end(); ++j) coord_sum[i] += j->a[i]; } bool NMfit::termination_criteria(int iter, realt convergence) { if (F_->get_verbosity() >= 1) F_->ui()->mesg("#" + S(iter) + " (ev:" + S(evaluations_) + "):" " best:" + S(best->wssr) + " worst:" + S(worst->wssr) + ", " + S(s_worst->wssr) + " [V * |" + S(volume_factor) + "|]"); bool stop = false; if (volume_factor == 1. && iter != 0) { F_->msg ("Simplex got stuck."); stop = true; } volume_factor = 1.; /*DEBUG - BEGIN* string s = "WSSR:"; for (vector::iterator i = vertices.begin(); i!=vertices.end(); ++i) s += " " + S(i->wssr); F_->msg (s); *DEBUG - END*/ //checking stop conditions if (common_termination_criteria()) stop = true; if (is_zero(worst->wssr)) { F_->msg ("All vertices have WSSR < epsilon=" + S(epsilon)); return true; } realt r_diff = 2 * (worst->wssr - best->wssr) / (best->wssr + worst->wssr); if (r_diff < convergence) { F_->msg ("Relative difference between worst and best vertex is only " + S(r_diff) + ". Stop"); stop = true; } return stop; } void NMfit::compute_v(Vertex& v) { assert (!v.a.empty()); v.wssr = compute_wssr(v.a, fitted_datas_); v.computed = true; } } // namespace fityk fityk-1.3.1/fityk/NMfit.h000066400000000000000000000022221302634723100151550ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_NMFIT_H_ #define FITYK_NMFIT_H_ #include #include "common.h" #include "fit.h" namespace fityk { /// Vertex used in Nelder-Mead method struct Vertex { std::vector a; bool computed; realt wssr; Vertex() : a(0), computed(false), wssr(0.) {} Vertex(int n) : a(n), computed(false), wssr(0.) {} Vertex(std::vector& a_) : a(a_), computed(false), wssr(0.) {} }; /// Nelder-Mead simplex method class NMfit : public Fit { public: NMfit(Full* F, const char* name) : Fit(F, name) {} virtual double run_method(std::vector* best_a); private: std::vector vertices; std::vector::iterator best, s_worst /*second worst*/, worst; std::vector coord_sum; realt volume_factor; void init(); void find_best_worst(); void change_simplex(); realt try_new_worst(realt f); void compute_coord_sum(); bool termination_criteria(int iter, realt convergence); void compute_v(Vertex& v); }; } // namespace fityk #endif fityk-1.3.1/fityk/ast.cpp000066400000000000000000001005401302634723100152640ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2005 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "ast.h" #include #include #include #include #include #include #include #include "common.h" #include "voigt.h" #include "lexer.h" #include "eparser.h" using namespace std; namespace fityk { string OpTree::str(const OpTreeFormat& fmt) { if (op < 0) { int v_nr = -op-1; return fmt.vars == NULL || fmt.vars->empty() ? "var"+S(v_nr) : (*fmt.vars)[v_nr]; } switch (op) { case OP_NUMBER: return format1(fmt.num_format, val); case OP_NEG: return "-" + c1->str_b(c1->op >= OP_POW, fmt); case OP_EXP: return "exp(" + c1->str(fmt) + ")"; case OP_ERFC: return "erfc(" + c1->str(fmt) + ")"; case OP_ERF: return "erf(" + c1->str(fmt) + ")"; case OP_SINH: return "sinh(" + c1->str(fmt) + ")"; case OP_COSH: return "cosh(" + c1->str(fmt) + ")"; case OP_TANH: return "tanh("+ c1->str(fmt) + ")"; case OP_SIN: return "sin(" + c1->str(fmt) + ")"; case OP_COS: return "cos(" + c1->str(fmt) + ")"; case OP_TAN: return "tan(" + c1->str(fmt) + ")"; case OP_ASIN: return "asin("+ c1->str(fmt) + ")"; case OP_ACOS: return "acos("+ c1->str(fmt) + ")"; case OP_ATAN: return "atan("+ c1->str(fmt) + ")"; case OP_LGAMMA: return "lgamma("+ c1->str(fmt) + ")"; case OP_DIGAMMA: return "digamma("+ c1->str(fmt) + ")"; case OP_ABS: return "abs(" + c1->str(fmt) + ")"; case OP_LOG10:return "log10("+c1->str(fmt) + ")"; case OP_LN: return "ln(" + c1->str(fmt) + ")"; case OP_SQRT: return "sqrt("+ c1->str(fmt) + ")"; case OP_VOIGT: return "voigt("+ c1->str(fmt) +","+ c2->str(fmt) +")"; case OP_DVOIGT_DX: return "dvoigt_dx("+ c1->str(fmt) + "," + c2->str(fmt) + ")"; case OP_DVOIGT_DY: return "dvoigt_dy("+ c1->str(fmt) + "," + c2->str(fmt) + ")"; case OP_POW: return c1->str_b(c1->op >= OP_POW, fmt) + "^" + c2->str_b(c2->op >= OP_POW, fmt); case OP_ADD: return c1->str(fmt) + "+" + c2->str(fmt); case OP_SUB: return c1->str(fmt) + "-" + c2->str_b(c2->op >= OP_ADD, fmt); case OP_MUL: return c1->str_b(c1->op >= OP_ADD, fmt) + "*" + c2->str_b(c2->op >= OP_ADD, fmt); case OP_DIV: return c1->str_b(c1->op >= OP_ADD, fmt) + "/" + c2->str_b(c2->op >= OP_MUL, fmt); default: assert(0); return ""; } } OpTree* OpTree::clone() const { OpTree *t = new OpTree(val); t->op = op; if (c1) t->c1 = c1->clone(); if (c2) t->c2 = c2->clone(); return t; } //////////////////////////////////////////////////////////////////////////// namespace { OpTree* simplify_terms(OpTree *a); OpTree* do_multiply(OpTree *a, OpTree *b); OpTree* do_neg(OpTree *a) { if (a->op == 0) { realt val = - a->val; delete a; return new OpTree(val); } else if (a->op == OP_NEG) { OpTree *t = a->c1->clone(); delete a; return t; } else return new OpTree(OP_NEG, a); } OpTree* do_add(int op, OpTree *a, OpTree *b) { if (a->op == 0 && b->op == 0) { // p + q realt val = (op == OP_ADD ? a->val + b->val : a->val - b->val); delete a; delete b; return new OpTree(val); } else if (a->op == 0 && is_eq(a->val, 0.)) { // 0 + t delete a; if (op == OP_ADD) return b; else return do_neg(b); } else if (b->op == 0 && is_eq(b->val, 0.)) { // t + 0 delete b; return a; } else if (b->op == OP_NEG) { // t + -u OpTree *t = b->remove_c1(); delete b; return do_add(op == OP_ADD ? OP_SUB : OP_ADD, a, t); } else if ((b->op == OP_MUL || b->op == OP_DIV) && b->c1->op == 0 && b->c1->val < 0) { // t + -p*v b->c1->val = - b->c1->val; return do_add(op == OP_ADD ? OP_SUB : OP_ADD, a, b); } else if (*a == *b) { delete b; if (op == OP_ADD) // t + t return do_multiply(new OpTree(2.), a); else { // t - t delete a; return new OpTree(0.); } } else return new OpTree(op, a, b); } OpTree* do_add(OpTree *a, OpTree *b) { return do_add(OP_ADD, a, b); } OpTree* do_sub(OpTree *a, OpTree *b) { return do_add(OP_SUB, a, b); } OpTree* do_multiply(OpTree *a, OpTree *b) { if (a->op == 0 && b->op == 0) // const * const { realt val = a->val * b->val; delete a; delete b; return new OpTree(val); } else if ((a->op == 0 && is_eq(a->val, 0.)) // 0 * ... || (b->op == 0 && is_eq(b->val, 0.))) // ... * 0 { delete a; delete b; return new OpTree(0.); } else if (a->op == 0 && is_eq(a->val, 1.)) { // 1 * ... delete a; return b; } else if (b->op == 0 && is_eq(b->val, 1.)) { // ... * 1 delete b; return a; } else if (a->op == 0 && is_eq(a->val, -1.)) { // -1 * ... delete a; return do_neg(b); } else if (b->op == 0 && is_eq(b->val, -1.)) { // ... * -1 delete b; return do_neg(a); } // const1 * (const2 / ...) else if (a->op == 0 && b->op == OP_DIV && b->c1->op == 0) { b->c1->val *= a->val; delete a; return b; } else { return new OpTree(OP_MUL, a, b); } } OpTree* do_divide(OpTree *a, OpTree *b) { //no check for division by zero if (a->op == 0 && b->op == 0) { realt val = a->val / b->val; delete a; delete b; return new OpTree(val); } else if (a->op == 0 && is_eq(a->val, 0.)) { delete a; delete b; return new OpTree(0.); } else if (b->op == 0 && is_eq(b->val, 1.)) { delete b; return a; } else { return new OpTree(OP_DIV, a, b); } } OpTree *do_sqr(OpTree *a) { return do_multiply(a, a->clone()); //return new OpTree(OP_MUL, a, a->clone()); } OpTree *do_oneover(OpTree *a) { return do_divide(new OpTree(1.), a); } /* template OpTree* one_arg_func(OpTree *a, T func, int op) { if (a->op == 0) { realt val = func(a->val); delete a; return new OpTree(val); } else return new OpTree(op, simplify_terms(a)); } */ OpTree* do_exp(OpTree *a) { if (a->op == 0) { realt val = exp(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_EXP, simplify_terms(a)); } OpTree* do_erf(OpTree *a) { if (a->op == 0) { realt val = erf(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_ERF, simplify_terms(a)); } OpTree* do_erfc(OpTree *a) { if (a->op == 0) { realt val = erfc(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_ERFC, simplify_terms(a)); } OpTree* do_sqrt(OpTree *a) { if (a->op == 0) { realt val = sqrt(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_SQRT, a); } OpTree* do_log10(OpTree *a) { if (a->op == 0) { realt val = log10(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_LOG10, simplify_terms(a)); } OpTree* do_ln(OpTree *a) { if (a->op == 0) { realt val = log(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_LN, simplify_terms(a)); } OpTree* do_sinh(OpTree *a) { if (a->op == 0) { realt val = sinh(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_SINH, simplify_terms(a)); } OpTree* do_cosh(OpTree *a) { if (a->op == 0) { realt val = cosh(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_COSH, simplify_terms(a)); } OpTree* do_tanh(OpTree *a) { if (a->op == 0) { realt val = tanh(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_TANH, simplify_terms(a)); } OpTree* do_sin(OpTree *a) { if (a->op == 0) { realt val = sin(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_SIN, simplify_terms(a)); } OpTree* do_cos(OpTree *a) { if (a->op == 0) { realt val = cos(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_COS, simplify_terms(a)); } OpTree* do_tan(OpTree *a) { if (a->op == 0) { realt val = tan(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_TAN, simplify_terms(a)); } OpTree* do_atan(OpTree *a) { if (a->op == 0) { realt val = atan(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_ATAN, simplify_terms(a)); } OpTree* do_asin(OpTree *a) { if (a->op == 0) { realt val = asin(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_ASIN, simplify_terms(a)); } OpTree* do_acos(OpTree *a) { if (a->op == 0) { realt val = acos(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_ACOS, simplify_terms(a)); } OpTree* do_lgamma(OpTree *a) { if (a->op == 0) { realt val = boost::math::lgamma(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_LGAMMA, simplify_terms(a)); } OpTree* do_digamma(OpTree *a) { if (a->op == 0) { realt val = boost::math::digamma(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_DIGAMMA, simplify_terms(a)); } OpTree* do_abs(OpTree *a) { if (a->op == 0) { realt val = fabs(a->val); delete a; return new OpTree(val); } else return new OpTree(OP_ABS, simplify_terms(a)); } OpTree* do_pow(OpTree *a, OpTree *b) { if (a->op == 0 && b->op == 0) { realt val = pow(a->val, b->val); delete a; delete b; return new OpTree(val); } else if (a->op == 0 && is_eq(a->val, 0.)) { delete a; delete b; return new OpTree(0.); } else if ((b->op == 0 && is_eq(b->val, 0.)) || (a->op == 0 && is_eq(a->val, 1.))) { delete a; delete b; return new OpTree(1.); } else if (b->op == 0 && is_eq(b->val, 1.)) { delete b; return a; } else if (b->op == 0 && is_eq(b->val, -1.)) { delete b; return do_oneover(a); } else { return new OpTree(OP_POW, a, simplify_terms(b)); } } OpTree* do_voigt(OpTree *a, OpTree *b) { if (a->op == 0 && b->op == 0) { realt val = humlik(a->val, b->val) / sqrt(M_PI); delete a; return new OpTree(val); } else return new OpTree(OP_VOIGT, simplify_terms(a), simplify_terms(b)); } OpTree* do_dvoigt_dx(OpTree *a, OpTree *b) { if (a->op == 0 && b->op == 0) { realt val = humdev_dkdx(a->val, b->val) / sqrt(M_PI); delete a; return new OpTree(val); } else return new OpTree(OP_DVOIGT_DX, simplify_terms(a), simplify_terms(b)); } OpTree* do_dvoigt_dy(OpTree *a, OpTree *b) { if (a->op == 0 && b->op == 0) { realt val = humdev_dkdy(a->val, b->val) / sqrt(M_PI); delete a; return new OpTree(val); } else return new OpTree(OP_DVOIGT_DY, simplify_terms(a), simplify_terms(b)); } //////////////////////////////////////////////////////////////////////////// struct MultFactor { // factor (*t)^(*e) OpTree *t, *e; MultFactor(OpTree *t_, OpTree *e_) : t(t_), e(e_) {} void clear() { delete t; delete e; t=e=0; } }; /// recursively walk though OP_MUL, OP_DIV, OP_NEG, OP_SQRT, OP_POW /// and builds list of nodes with factors, such that tree a is equal to /// (v[0]->t)^(v[0]->e) * (v[1]->t)^(v[1]->e) * ... void get_factors(OpTree *a, OpTree *expo, realt &constant, vector& v) { if (a->op == OP_ADD || a->op == OP_SUB) a = simplify_terms(a); if (a->op == 0 && expo->op == 0) constant *= pow(a->val, expo->val); else if (a->op == OP_MUL) { get_factors(a->c1, expo, constant, v); get_factors(a->c2, expo, constant, v); } else if (a->op == OP_DIV) { get_factors(a->c1, expo, constant, v); OpTree *expo2 = do_neg(expo->clone()); get_factors(a->c2, expo2, constant, v); delete expo2; } else if (a->op == OP_NEG) { get_factors(a->c1, expo, constant, v); get_factors(new OpTree(-1.), expo, constant, v); } else if (a->op == OP_SQRT) { OpTree *expo2 = do_multiply(new OpTree(0.5), expo->clone()); get_factors(a->c1, expo2, constant, v); delete expo2; } else if (a->op == OP_POW) { OpTree *expo2 = do_multiply(a->remove_c2(), expo->clone()); get_factors(a->c1, expo2, constant, v); delete expo2; } else { bool found = false; for (vector::iterator i = v.begin(); i != v.end(); ++i) if (*i->t == *a) { i->e = do_add(i->e, expo->clone()); found = true; break; } if (!found) { v.push_back(MultFactor(a, expo->clone())); return; //don't delete a } } //we are here -- MultFactor(a,...) not created a->c1 = a->c2 = 0; delete a; } OpTree* simplify_factors(OpTree *a) { #ifdef DEBUG_SIMPLIFY cout << "simplify_factors() [<] " << a->str() << endl; #endif vector v; OpTree expo(1.); realt constant = 1; get_factors(a, &expo, constant, v); //deletes a #ifdef DEBUG_SIMPLIFY cout << "simplify_factors(): [.] {" << constant << "} "; for (vector::iterator i = v.begin(); i != v.end(); ++i) cout << "{" << i->t->str() << "|" << i->e->str() << "} "; cout << endl; #endif // tan*cos -> sin; tan/sin -> cos for (vector::iterator i = v.begin(); i != v.end(); ++i) if (i->t && i->t->op == OP_TAN) { for (vector::iterator j = v.begin(); j != v.end(); ++j){ if (j->t && j->t->op == OP_COS && *j->e == *i->e) { i->t->change_op(OP_SIN); j->clear(); } if (j->t && j->t->op == OP_SIN && ((j->e->op==0 && i->e->op==0 && j->e->val==-i->e->val) || (j->e->op==OP_NEG && *j->e->c1 == *i->e) || (i->e->op==OP_NEG && *i->e->c1 == *j->e))) { i->t->change_op(OP_COS); j->clear(); } } } // sin/cos -> tan for (vector::iterator i = v.begin(); i != v.end(); ++i) if (i->t && i->t->op == OP_SIN) { for (vector::iterator j = v.begin(); j != v.end(); ++j){ if (j->t && j->t->op == OP_COS && ((j->e->op==0 && i->e->op==0 && j->e->val==-i->e->val) || (j->e->op==OP_NEG && *j->e->c1 == *i->e) || (i->e->op==OP_NEG && *i->e->c1 == *j->e))) { i->t->change_op(OP_TAN); j->clear(); } } } // -> tree // TODO x^z * y^z -> (x*y)^z (if z != -1,0,1) OpTree *tu = 0, *tb = 0; // preparing expression as (tu / tb) for (vector::iterator i = v.begin(); i != v.end(); ++i) if (i->t) { if ((i->e->op == 0 && i->e->val < 0) || i->e->op == OP_NEG) { OpTree *p = do_pow(i->t, do_neg(i->e)); tb = (tb == 0 ? p : do_multiply(tb, p)); } else { OpTree *p = do_pow(i->t, i->e); tu = (tu == 0 ? p : do_multiply(tu, p)); } } OpTree *constant_t = new OpTree(constant); OpTree *ret = 0; if (tu) { if (tb) ret = do_multiply(constant_t, do_divide(tu, tb)); else //tu && !tb ret = do_multiply(constant_t, tu); } else { if (tb) //!tu && tb ret = do_divide(constant_t, tb); else //!tu && !tb ret = constant_t; } #ifdef DEBUG_SIMPLIFY cout << "simplify_factors() [>] " << ret->str() << endl; #endif return ret; } //////////////////////////////////////////////////////////////////////////// struct MultTerm { OpTree *t; realt k; MultTerm(OpTree *t_, realt k_) : t(t_), k(k_) {} void clear() { delete t; t=0; } }; void get_terms(OpTree *a, realt multiplier, vector &v) { if (a->op == OP_MUL || a->op == OP_DIV || a->op == OP_SQRT || a->op == OP_POW) a = simplify_factors(a); if (a->op == OP_ADD) { // p + q get_terms(a->c1, multiplier, v); get_terms(a->c2, multiplier, v); a->c1 = a->c2 = 0; delete a; } else if (a->op == OP_SUB) { // p - q get_terms(a->c1, multiplier, v); get_terms(a->c2, -multiplier, v); a->c1 = a->c2 = 0; delete a; } else if (a->op == OP_NEG) { // - p get_terms(a->c1, -multiplier, v); a->c1 = a->c2 = 0; delete a; } else if (a->op == OP_MUL && a->c1->op == 0) { // const * p get_terms(a->c2, multiplier*(a->c1->val), v); a->c2 = 0; delete a; } // const / p for const != 1 (to avoid loop) else if (a->op == OP_DIV && a->c1->op == 0 && a->c1->val != 1.) { get_terms(do_oneover(a->c2), multiplier*(a->c1->val), v); a->c2 = 0; delete a; } else { // a can't be splitted for (vector::iterator i = v.begin(); i != v.end(); ++i) { if (a->op == 0 && i->t && i->t->op == 0) {// number (not the first) i->k += multiplier * a->val; delete a; return; } if (i->t && *i->t == *a) { //token already in v i->k += multiplier; delete a; return; } } // we are here -- no first token of its kind if (a->op == 0) { //add number v.push_back(MultTerm(new OpTree(1.), multiplier * a->val)); delete a; } else { // add token v.push_back(MultTerm(a, multiplier)); } } } OpTree* simplify_terms(OpTree *a) { // not handled: // (x+y) * (x-y) == x^2 - y^2 // (x+/-y)^2 == x^2 +/- 2xy + y^2 if (a->op == OP_MUL || a->op == OP_DIV || a->op == OP_SQRT || a->op == OP_POW) return simplify_factors(a); else if (!(a->op == OP_ADD || a->op == OP_SUB || a->op == OP_NEG)) return a; #ifdef DEBUG_SIMPLIFY cout << "simplify_terms() [<] " << a->str() << endl; #endif vector v; get_terms(a, 1., v); //deletes a #ifdef DEBUG_SIMPLIFY cout << "simplify_terms() [.] "; for (vector::iterator i = v.begin(); i != v.end(); ++i) cout << "{" << i->t->str() << "|" << i->k << "} "; cout << endl; #endif // sin^2(x) + cos^2(x) = 1 realt to_add = 0.; for (vector::iterator i = v.begin(); i != v.end(); ++i) if (i->t && i->t->op == OP_POW && i->t->c1->op == OP_SIN && i->t->c2->op == 0 && is_eq(i->t->c2->val, 2.)) for (vector::iterator j = v.begin(); j != v.end(); ++j) if (j->t && j->t->op == OP_POW && j->t->c1->op == OP_COS && j->t->c2->op == 0 && is_eq(j->t->c2->val, 2.)) { realt k = j->k; i->k -= k; j->clear(); to_add += k; } if (to_add) get_terms(new OpTree(1.), to_add, v); // -> tree OpTree *t = 0; for (vector::iterator i = v.begin(); i != v.end(); ++i) if (i->t && !is_eq(i->k, 0)) { if (!t) t = do_multiply(new OpTree(i->k), i->t); else if (i->k > 0) t = do_add(t, do_multiply(new OpTree(i->k), i->t)); else //i->k < 0 t = do_sub(t, do_multiply(new OpTree(-i->k), i->t)); } if (!t) t = new OpTree(0.); #ifdef DEBUG_SIMPLIFY cout << "simplify_terms() [>] " << t->str() << endl; #endif return t; } } // anonymouse namespace //////////////////////////////////////////////////////////////////////////// /// simplify exportable formula, i.e. mathematical function f(x), /// without variables other than x string simplify_formula(string const &formula, const char* num_fmt) { Lexer lex(formula.c_str()); ExpressionParser ep(NULL); // if the formula has not-expanded-functions, like Voigt(2,3,4,5), // it throws SyntaxError try { ep.parse_expr(lex, -1, NULL, NULL, ExpressionParser::kAstMode); } catch (SyntaxError&) { return formula; } vector trees; try { // derivatives are calculated only as a side effect trees = prepare_ast_with_der(ep.vm(), 1); } catch(ExecuteError&) { return formula; } vector vars(1, "x"); OpTreeFormat fmt = { num_fmt, &vars }; string simplified = trees.back()->str(fmt); purge_all_elements(trees); return simplified; } /// debug utility, shows symbolic derivatives of given formula void get_derivatives_str(const char* formula, string& result) { Lexer lex(formula); ExpressionParser ep(NULL); vector vars; ep.parse_expr(lex, -1, NULL, &vars); vector trees = prepare_ast_with_der(ep.vm(), vars.size()); OpTreeFormat fmt = { "%g", &vars }; result += "f(" + join_vector(vars,", ") + ") = " + trees.back()->str(fmt); for (size_t i = 0; i != vars.size(); ++i) result += "\ndf / d " + vars[i] + " = " + trees[i]->str(fmt); purge_all_elements(trees); } /// returns array of trees, /// first n=vars.size() derivatives and the last tree for value static vector calculate_deriv(vector::const_iterator &i, int len, const VMData& vm) { vector results(len + 1, (OpTree*) NULL); --i; assert(i >= vm.code().begin()); if (*i < 0) { --i; assert(i >= vm.code().begin()); assert(VMData::has_idx(*i)); } switch (*i) { case OP_NUMBER: { for (int k = 0; k < len; ++k) results[k] = new OpTree(0.); int negative_idx = *(i+1); int idx = -1 - negative_idx; assert(is_index(idx, vm.numbers())); realt value = vm.numbers()[idx]; results[len] = new OpTree(value); break; } case OP_SYMBOL: { int negative_idx = *(i+1); int idx = -1 - negative_idx; assert(idx <= len); for (int k = 0; k < len; ++k) { realt der_value = (k == idx ? 1. : 0.); results[k] = new OpTree(der_value); } results[len] = new OpTree(NULL, idx); break; } case OP_X: { int n = len - 1; // the rest is the same as in OP_SYMBOL for (int k = 0; k < len; ++k) { realt der_value = (k == n ? 1. : 0.); results[k] = new OpTree(der_value); } results[len] = new OpTree(NULL, n); break; } case OP_SQRT: case OP_EXP: case OP_ERFC: case OP_ERF: case OP_LOG10: case OP_LN: case OP_SINH: case OP_COSH: case OP_TANH: case OP_SIN: case OP_COS: case OP_TAN: case OP_ASIN: case OP_ACOS: case OP_ATAN: case OP_LGAMMA: case OP_ABS: { int op = *i; vector arg = calculate_deriv(i, len, vm); OpTree* (* do_op)(OpTree *) = NULL; OpTree* der = 0; OpTree* larg = arg.back()->clone(); if (op == OP_SQRT) { der = do_divide(new OpTree(0.5), do_sqrt(larg)); do_op = do_sqrt; } else if (op == OP_EXP) { der = do_exp(larg); do_op = do_exp; } else if (op == OP_ERFC) { // d/dz erfc(z) = -2/sqrt(pi) * exp(-z^2) der = do_multiply(do_exp(do_neg(do_sqr(larg))), new OpTree(-2/sqrt(M_PI))); do_op = do_erfc; } else if (op == OP_ERF) { // d/dz erf(z) = 2/sqrt(pi) * exp(-z^2) der = do_multiply(do_exp(do_neg(do_sqr(larg))), new OpTree(2/sqrt(M_PI))); do_op = do_erf; } else if (op == OP_LOG10) { OpTree *ln_10 = do_ln(new OpTree(10.)); der = do_oneover(do_multiply(larg, ln_10)); do_op = do_log10; } else if (op == OP_LN) { der = do_oneover(larg); do_op = do_ln; } else if (op == OP_SINH) { der = do_cosh(larg); do_op = do_sinh; } else if (op == OP_COSH) { der = do_sinh(larg); do_op = do_cosh; } else if (op == OP_TANH) { der = do_oneover(do_sqr(do_cosh(larg))); do_op = do_tanh; } else if (op == OP_SIN) { der = do_cos(larg); do_op = do_sin; } else if (op == OP_COS) { der = do_neg(do_sin(larg)); do_op = do_cos; } else if (op == OP_TAN) { der = do_oneover(do_sqr(do_cos(larg))); do_op = do_tan; } else if (op == OP_ASIN) { OpTree *root_arg = do_sub(new OpTree(1.), do_sqr(larg)); der = do_oneover(do_sqrt(root_arg)); do_op = do_asin; } else if (op == OP_ACOS) { OpTree *root_arg = do_sub(new OpTree(1.), do_sqr(larg)); der = do_divide(new OpTree(-1.), do_sqrt(root_arg)); do_op = do_acos; } else if (op == OP_ATAN) { der = do_oneover(do_add(new OpTree(1.), do_sqr(larg))); do_op = do_atan; } else if (op == OP_LGAMMA) { der = do_digamma(larg); do_op = do_lgamma; } else if (op == OP_ABS) { der = do_divide(do_abs(larg), larg->clone()); do_op = do_abs; } else assert(0); for (int k = 0; k < len; ++k) results[k] = do_multiply(der->clone(), arg[k]); delete der; results[len] = (*do_op)(arg[len]); break; } case OP_VOIGT: { int op = *i; vector right = calculate_deriv(i, len, vm); vector left = calculate_deriv(i, len, vm); assert (op == OP_VOIGT); OpTree *d1 = do_dvoigt_dx(left[len]->clone(), right[len]->clone()); OpTree *d2 = do_dvoigt_dy(left[len]->clone(), right[len]->clone()); for (int k = 0; k < len; ++k) { results[k] = do_add(do_multiply(d1->clone(), left[k]), do_multiply(d2->clone(), right[k])); } results[len] = do_voigt(left[len], right[len]); delete d1; delete d2; break; } case OP_POW: { vector right = calculate_deriv(i, len, vm); vector left = calculate_deriv(i, len, vm); // this special case is needed, because in cases like -2^4 // there was a problem with logarithm in formula below if (left[len]->op == 0 && right[len]->op == 0) { for (int k = 0; k < len; ++k) { assert(left[k]->op == 0 && right[k]->op == 0); delete left[k]; delete right[k]; results[k] = new OpTree(0.); } results[len] = do_pow(left[len], right[len]); } //another special cases like a(x)^n are not handeled separately. //Should they? else { for (int k = 0; k < len; ++k) { OpTree *a = left[len], *b = right[len], *ap = left[k], *bp = right[k]; // b(x) b(x) b(x) a'(x) // (a(x) )' = a(x) (---------- + ln(a(x)) b'(x)) // a(x) OpTree *pow_a_b = do_pow(a->clone(), b->clone()); OpTree *term1 = do_divide(do_multiply(b->clone(), ap), a->clone()); OpTree *term2 = do_multiply(do_ln(a->clone()), bp); results[k] = do_multiply(pow_a_b, do_add(term1, term2)); } results[len] = do_pow(left[len], right[len]); } break; } case OP_NEG: { vector arg = calculate_deriv(i, len, vm); for (int k = 0; k < len+1; ++k) results[k] = do_neg(arg[k]); break; } case OP_MUL: { vector right = calculate_deriv(i, len, vm); vector left = calculate_deriv(i, len, vm); for (int k = 0; k < len; ++k) { // a*b' + a'*b OpTree *a = left[len], *b = right[len], *ap = left[k], *bp = right[k]; results[k] = do_add(do_multiply(a->clone(), bp), do_multiply(ap, b->clone())); } results[len] = do_multiply(left[len], right[len]); break; } case OP_DIV: { vector right = calculate_deriv(i, len, vm); vector left = calculate_deriv(i, len, vm); for (int k = 0; k < len; ++k) { // (a'*b - b'*a) / (b*b) OpTree *a = left[len], *b = right[len], *ap = left[k], *bp = right[k]; OpTree *upper = do_sub(do_multiply(ap, b->clone()), do_multiply(bp, a->clone())); results[k] = do_divide(upper, do_sqr(b->clone())); } results[len] = do_divide(left[len], right[len]); break; } case OP_ADD: { vector right = calculate_deriv(i, len, vm); vector left = calculate_deriv(i, len, vm); for (int k = 0; k < len+1; ++k) results[k] = do_add(left[k], right[k]); break; } case OP_SUB: { vector right = calculate_deriv(i, len, vm); vector left = calculate_deriv(i, len, vm); for (int k = 0; k < len+1; ++k) results[k] = do_sub(left[k], right[k]); break; } /* to be added: case OP_GAMMA: case OP_ROUND: case OP_MOD: case OP_MIN2: case OP_MAX2: case OP_GT: case OP_GE: case OP_LT: case OP_LE: case OP_EQ: case OP_NEQ: case OP_NOT: case OP_OR: case OP_AFTER_OR: case OP_AND: case OP_AFTER_AND: case OP_TERNARY: case OP_TERNARY_MID: case OP_AFTER_TERNARY: */ default: purge_all_elements(results); throw ExecuteError("`" + op2str(*i) + "' is not allowed for " "variables/functions"); } assert(results[0] != NULL); assert(results[len] != NULL); for (int k = 0; k < len+1; ++k) results[k] = simplify_terms(results[k]); //printf("%s\n", results[len]->str().c_str()); return results; } vector prepare_ast_with_der(const VMData& vm, int len) { assert(!vm.code().empty()); const_cast(vm).flip_indices(); vector::const_iterator iter = vm.code().end(); vector r = calculate_deriv(iter, len, vm); assert (iter == vm.code().begin()); const_cast(vm).flip_indices(); return r; } void add_bytecode_from_tree(const OpTree* tree, const vector &symbol_map, VMData& vm) { int op = tree->op; if (op < 0) { size_t n = -op-1; if (n == symbol_map.size()) { vm.append_code(OP_X); } else { assert(is_index(n, symbol_map)); vm.append_code(OP_SYMBOL); vm.append_code(symbol_map[n]); } } else if (op == 0) { vm.append_number(tree->val); } else if (op >= OP_ONE_ARG && op < OP_TWO_ARG) { //one argument add_bytecode_from_tree(tree->c1, symbol_map, vm); vm.append_code(op); } else if (op >= OP_TWO_ARG) { //two arguments add_bytecode_from_tree(tree->c1, symbol_map, vm); add_bytecode_from_tree(tree->c2, symbol_map, vm); vm.append_code(op); } } } // namespace fityk fityk-1.3.1/fityk/ast.h000066400000000000000000000042311302634723100147310ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_AST_H_ #define FITYK_AST_H_ #include #include "vm.h" // opcodes #include "common.h" // DISALLOW_COPY_AND_ASSIGN namespace fityk { struct OpTreeFormat { const char *num_format; const std::vector *vars; }; /// Node in abstract syntax tree (AST) struct OpTree { /// op < 0: variable (n=-op-1) /// op == 0 (== OP_NUMBER): constant /// op > 0: operator /// There is no OP_X in OpTree, x (if there is x) is the last variable int op; OpTree *c1, *c2; realt val; explicit OpTree(realt v) : op(0), c1(0), c2(0), val(v) {} explicit OpTree(void*, int n) : op(-1-n), c1(0), c2(0), val(0.) {} explicit OpTree(int n, OpTree *arg1) : op(n), c1(arg1), c2(0), val(0.) { assert(n >= OP_ONE_ARG && n < OP_TWO_ARG); } explicit OpTree(int n, OpTree *arg1, OpTree *arg2) : op(n), c1(arg1), c2(arg2), val(0.) { assert(n >= OP_TWO_ARG); } ~OpTree() { delete c1; delete c2; } std::string str(const OpTreeFormat& fmt); std::string str_b(bool b, const OpTreeFormat& fmt) { return b ? "(" + str(fmt) + ")" : str(fmt); } OpTree* clone() const; //void swap_args() { assert(c1 && c2); OpTree *t=c1; c1=c2; c2=t; } OpTree* remove_c1() { OpTree *t=c1; c1=0; return t; } OpTree* remove_c2() { OpTree *t=c2; c2=0; return t; } void change_op(int op_) { op=op_; } bool operator==(const OpTree &t) const { return op == t.op && val == t.val && (c1 == t.c1 || (c1 && t.c1 && *c1 == *t.c1)) && (c2 == t.c2 || (c2 && t.c2 && *c2 == *t.c2)); } private: DISALLOW_COPY_AND_ASSIGN(OpTree); }; std::vector prepare_ast_with_der(const VMData& vm, int len); std::string simplify_formula(const std::string &formula, const char* num_fmt); void get_derivatives_str(const char* formula, std::string& result); void add_bytecode_from_tree(const OpTree* tree, const std::vector &symbol_map, VMData& vm); } // namespace fityk #endif fityk-1.3.1/fityk/bfunc.cpp000066400000000000000000001016351302634723100156000ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Built-in function definitions #define BUILDING_LIBFITYK #include "bfunc.h" #include #include "voigt.h" #include "numfuncs.h" using namespace std; using boost::math::lgamma; namespace fityk { void FuncConstant::calculate_value_in_range(vector const&/*xx*/, vector& yy, int first, int last) const { for (int i = first; i < last; ++i) yy[i] += av_[0]; } CALCULATE_DERIV_BEGIN(FuncConstant) (void) x; dy_dv[0] = 1.; dy_dx = 0; CALCULATE_DERIV_END(av_[0]) /////////////////////////////////////////////////////////////////////// CALCULATE_VALUE_BEGIN(FuncLinear) CALCULATE_VALUE_END(av_[0] + x*av_[1]) CALCULATE_DERIV_BEGIN(FuncLinear) dy_dv[0] = 1.; dy_dv[1] = x; dy_dx = av_[1]; CALCULATE_DERIV_END(av_[0] + x*av_[1]) /////////////////////////////////////////////////////////////////////// CALCULATE_VALUE_BEGIN(FuncQuadratic) CALCULATE_VALUE_END(av_[0] + x*av_[1] + x*x*av_[2]) CALCULATE_DERIV_BEGIN(FuncQuadratic) dy_dv[0] = 1.; dy_dv[1] = x; dy_dv[2] = x*x; dy_dx = av_[1] + 2*x*av_[2]; CALCULATE_DERIV_END(av_[0] + x*av_[1] + x*x*av_[2]) /////////////////////////////////////////////////////////////////////// CALCULATE_VALUE_BEGIN(FuncCubic) CALCULATE_VALUE_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3]) CALCULATE_DERIV_BEGIN(FuncCubic) dy_dv[0] = 1.; dy_dv[1] = x; dy_dv[2] = x*x; dy_dv[3] = x*x*x; dy_dx = av_[1] + 2*x*av_[2] + 3*x*x*av_[3]; CALCULATE_DERIV_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3]) /////////////////////////////////////////////////////////////////////// CALCULATE_VALUE_BEGIN(FuncPolynomial4) CALCULATE_VALUE_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3] + x*x*x*x*av_[4]) CALCULATE_DERIV_BEGIN(FuncPolynomial4) dy_dv[0] = 1.; dy_dv[1] = x; dy_dv[2] = x*x; dy_dv[3] = x*x*x; dy_dv[4] = x*x*x*x; dy_dx = av_[1] + 2*x*av_[2] + 3*x*x*av_[3] + 4*x*x*x*av_[4]; CALCULATE_DERIV_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3] + x*x*x*x*av_[4]) /////////////////////////////////////////////////////////////////////// CALCULATE_VALUE_BEGIN(FuncPolynomial5) CALCULATE_VALUE_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3] + x*x*x*x*av_[4] + x*x*x*x*x*av_[5]) CALCULATE_DERIV_BEGIN(FuncPolynomial5) dy_dv[0] = 1.; dy_dv[1] = x; dy_dv[2] = x*x; dy_dv[3] = x*x*x; dy_dv[4] = x*x*x*x; dy_dv[5] = x*x*x*x*x; dy_dx = av_[1] + 2*x*av_[2] + 3*x*x*av_[3] + 4*x*x*x*av_[4] + 5*x*x*x*x*av_[5]; CALCULATE_DERIV_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3] + x*x*x*x*av_[4] + x*x*x*x*x*av_[5]) /////////////////////////////////////////////////////////////////////// CALCULATE_VALUE_BEGIN(FuncPolynomial6) CALCULATE_VALUE_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3] + x*x*x*x*av_[4] + x*x*x*x*x*av_[5] + x*x*x*x*x*x*av_[6]) CALCULATE_DERIV_BEGIN(FuncPolynomial6) dy_dv[0] = 1.; dy_dv[1] = x; dy_dv[2] = x*x; dy_dv[3] = x*x*x; dy_dv[4] = x*x*x*x; dy_dv[5] = x*x*x*x*x; dy_dv[6] = x*x*x*x*x*x; dy_dx = av_[1] + 2*x*av_[2] + 3*x*x*av_[3] + 4*x*x*x*av_[4] + 5*x*x*x*x*av_[5] + 6*x*x*x*x*x*av_[6]; CALCULATE_DERIV_END(av_[0] + x*av_[1] + x*x*av_[2] + x*x*x*av_[3] + x*x*x*x*av_[4] + x*x*x*x*x*av_[5] + x*x*x*x*x*x*av_[6]) /////////////////////////////////////////////////////////////////////// void FuncGaussian::more_precomputations() { if (fabs(av_[2]) < epsilon) av_[2] = epsilon; } CALCULATE_VALUE_BEGIN(FuncGaussian) realt xa1a2 = (x - av_[1]) / av_[2]; realt ex = exp(- M_LN2 * xa1a2 * xa1a2); CALCULATE_VALUE_END(av_[0] * ex) CALCULATE_DERIV_BEGIN(FuncGaussian) realt xa1a2 = (x - av_[1]) / av_[2]; realt ex = exp(- M_LN2 * xa1a2 * xa1a2); dy_dv[0] = ex; realt dcenter = 2 * M_LN2 * av_[0] * ex * xa1a2 / av_[2]; dy_dv[1] = dcenter; dy_dv[2] = dcenter * xa1a2; dy_dx = -dcenter; CALCULATE_DERIV_END(av_[0]*ex) bool FuncGaussian::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { realt w = sqrt(log(fabs(av_[0]/level)) / M_LN2) * av_[2]; left = av_[1] - w; right = av_[1] + w; } return true; } bool FuncGaussian::get_area(realt* a) const { *a = av_[0] * fabs(av_[2]) * sqrt(M_PI / M_LN2); return true; } /////////////////////////////////////////////////////////////////////// void FuncSplitGaussian::more_precomputations() { if (fabs(av_[2]) < epsilon) av_[2] = epsilon; if (fabs(av_[3]) < epsilon) av_[3] = epsilon; } CALCULATE_VALUE_BEGIN(FuncSplitGaussian) realt hwhm = (x < av_[1] ? av_[2] : av_[3]); realt xa1a2 = (x - av_[1]) / hwhm; realt ex = exp(- M_LN2 * xa1a2 * xa1a2); CALCULATE_VALUE_END(av_[0] * ex) CALCULATE_DERIV_BEGIN(FuncSplitGaussian) realt hwhm = (x < av_[1] ? av_[2] : av_[3]); realt xa1a2 = (x - av_[1]) / hwhm; realt ex = exp(- M_LN2 * xa1a2 * xa1a2); dy_dv[0] = ex; realt dcenter = 2 * M_LN2 * av_[0] * ex * xa1a2 / hwhm; dy_dv[1] = dcenter; if (x < av_[1]) { dy_dv[2] = dcenter * xa1a2; dy_dv[3] = 0; } else { dy_dv[2] = 0; dy_dv[3] = dcenter * xa1a2; } dy_dx = -dcenter; CALCULATE_DERIV_END(av_[0]*ex) bool FuncSplitGaussian::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { realt w1 = sqrt (log (fabs(av_[0]/level)) / M_LN2) * av_[2]; realt w2 = sqrt (log (fabs(av_[0]/level)) / M_LN2) * av_[3]; left = av_[1] - w1; right = av_[1] + w2; } return true; } bool FuncSplitGaussian::get_area(realt* a) const { *a = av_[0] * (fabs(av_[2])+fabs(av_[3])) / 2. * sqrt(M_PI/M_LN2); return true; } /////////////////////////////////////////////////////////////////////// void FuncLorentzian::more_precomputations() { if (fabs(av_[2]) < epsilon) av_[2] = epsilon; } CALCULATE_VALUE_BEGIN(FuncLorentzian) realt xa1a2 = (x - av_[1]) / av_[2]; realt inv_denomin = 1. / (1 + xa1a2 * xa1a2); CALCULATE_VALUE_END(av_[0] * inv_denomin) CALCULATE_DERIV_BEGIN(FuncLorentzian) realt xa1a2 = (x - av_[1]) / av_[2]; realt inv_denomin = 1. / (1 + xa1a2 * xa1a2); dy_dv[0] = inv_denomin; realt dcenter = 2 * av_[0] * xa1a2 / av_[2] * inv_denomin * inv_denomin; dy_dv[1] = dcenter; dy_dv[2] = dcenter * xa1a2; dy_dx = -dcenter; CALCULATE_DERIV_END(av_[0] * inv_denomin) bool FuncLorentzian::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { realt w = sqrt(fabs(av_[0]/level) - 1) * av_[2]; left = av_[1] - w; right = av_[1] + w; } return true; } /////////////////////////////////////////////////////////////////////// void FuncPearson7::more_precomputations() { if (fabs(av_[2]) < epsilon) av_[2] = epsilon; if (av_.size() != 5) av_.resize(5); // not checking for av_[3]>0.5 nor even >0 av_[4] = pow(2, 1. / av_[3]) - 1; } CALCULATE_VALUE_BEGIN(FuncPearson7) realt xa1a2 = (x - av_[1]) / av_[2]; realt xa1a2sq = xa1a2 * xa1a2; realt pow_2_1_a3_1 = av_[4]; //pow (2, 1. / a3) - 1; realt denom_base = 1 + xa1a2sq * pow_2_1_a3_1; realt inv_denomin = pow(denom_base, - av_[3]); CALCULATE_VALUE_END(av_[0] * inv_denomin) CALCULATE_DERIV_BEGIN(FuncPearson7) realt xa1a2 = (x - av_[1]) / av_[2]; realt xa1a2sq = xa1a2 * xa1a2; realt pow_2_1_a3_1 = av_[4]; //pow (2, 1. / a3) - 1; realt denom_base = 1 + xa1a2sq * pow_2_1_a3_1; realt inv_denomin = pow(denom_base, - av_[3]); dy_dv[0] = inv_denomin; realt dcenter = 2 * av_[0] * av_[3] * pow_2_1_a3_1 * xa1a2 * inv_denomin / (denom_base * av_[2]); dy_dv[1] = dcenter; dy_dv[2] = dcenter * xa1a2; dy_dv[3] = av_[0] * inv_denomin * (M_LN2 * (pow_2_1_a3_1 + 1) * xa1a2sq / (denom_base * av_[3]) - log(denom_base)); dy_dx = -dcenter; CALCULATE_DERIV_END(av_[0] * inv_denomin) bool FuncPearson7::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { realt t = (pow(fabs(av_[0]/level), 1./av_[3]) - 1) / (pow(2, 1./av_[3]) - 1); realt w = sqrt(t) * av_[2]; left = av_[1] - w; right = av_[1] + w; } return true; } bool FuncPearson7::get_area(realt* a) const { if (av_[3] <= 0.5) return false; realt g = exp(lgamma(av_[3] - 0.5) - lgamma(av_[3])); //in f_val_precomputations(): av_[4] = pow (2, 1. / a3) - 1; *a = av_[0] * 2 * fabs(av_[2]) * sqrt(M_PI) * g / (2 * sqrt(av_[4])); return true; } /////////////////////////////////////////////////////////////////////// void FuncSplitPearson7::more_precomputations() { if (fabs(av_[2]) < epsilon) av_[2] = epsilon; if (fabs(av_[3]) < epsilon) av_[3] = epsilon; if (av_.size() != 8) av_.resize(8); // not checking for av_[3]>0.5 nor even >0 av_[6] = pow(2, 1. / av_[4]) - 1; av_[7] = pow(2, 1. / av_[5]) - 1; } CALCULATE_VALUE_BEGIN(FuncSplitPearson7) int lr = x < av_[1] ? 0 : 1; realt xa1a2 = (x - av_[1]) / av_[2+lr]; realt xa1a2sq = xa1a2 * xa1a2; realt pow_2_1_a3_1 = av_[6+lr]; //pow(2, 1./shape) - 1; realt denom_base = 1 + xa1a2sq * pow_2_1_a3_1; realt inv_denomin = pow(denom_base, - av_[4+lr]); CALCULATE_VALUE_END(av_[0] * inv_denomin) CALCULATE_DERIV_BEGIN(FuncSplitPearson7) int lr = x < av_[1] ? 0 : 1; realt hwhm = av_[2+lr]; realt shape = av_[4+lr]; realt xa1a2 = (x - av_[1]) / hwhm; realt xa1a2sq = xa1a2 * xa1a2; realt pow_2_1_a3_1 = av_[6+lr]; //pow(2, 1./shape) - 1; realt denom_base = 1 + xa1a2sq * pow_2_1_a3_1; realt inv_denomin = pow (denom_base, -shape); dy_dv[0] = inv_denomin; realt dcenter = 2 * av_[0] * shape * pow_2_1_a3_1 * xa1a2 * inv_denomin / (denom_base * hwhm); dy_dv[1] = dcenter; dy_dv[2] = dy_dv[3] = dy_dv[4] = dy_dv[5] = 0; dy_dv[2+lr] = dcenter * xa1a2; dy_dv[4+lr] = av_[0] * inv_denomin * (M_LN2 * (pow_2_1_a3_1 + 1) * xa1a2sq / (denom_base * shape) - log(denom_base)); dy_dx = -dcenter; CALCULATE_DERIV_END(av_[0] * inv_denomin) bool FuncSplitPearson7::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { realt t1 = (pow(fabs(av_[0]/level), 1./av_[4]) - 1) / (pow(2, 1./av_[4]) - 1); realt w1 = sqrt(t1) * av_[2]; realt t2 = (pow(fabs(av_[0]/level), 1./av_[5]) - 1) / (pow(2, 1./av_[5]) - 1); realt w2 = sqrt(t2) * av_[3]; left = av_[1] - w1; right = av_[1] + w2; } return true; } bool FuncSplitPearson7::get_area(realt* a) const { if (av_[4] <= 0.5 || av_[5] <= 0.5) return false; realt g1 = exp(lgamma(av_[4] - 0.5) - lgamma(av_[4])); realt g2 = exp(lgamma(av_[5] - 0.5) - lgamma(av_[5])); *a = av_[0] * fabs(av_[2]) * sqrt(M_PI) * g1 / (2 * sqrt(av_[6])) + av_[0] * fabs(av_[3]) * sqrt(M_PI) * g2 / (2 * sqrt(av_[7])); return true; } /////////////////////////////////////////////////////////////////////// void FuncPseudoVoigt::more_precomputations() { if (fabs(av_[2]) < epsilon) av_[2] = epsilon; } CALCULATE_VALUE_BEGIN(FuncPseudoVoigt) realt xa1a2 = (x - av_[1]) / av_[2]; realt ex = exp(- M_LN2 * xa1a2 * xa1a2); realt lor = 1. / (1 + xa1a2 * xa1a2); realt without_height = (1-av_[3]) * ex + av_[3] * lor; CALCULATE_VALUE_END(av_[0] * without_height) CALCULATE_DERIV_BEGIN(FuncPseudoVoigt) realt xa1a2 = (x - av_[1]) / av_[2]; realt ex = exp(- M_LN2 * xa1a2 * xa1a2); realt lor = 1. / (1 + xa1a2 * xa1a2); realt without_height = (1-av_[3]) * ex + av_[3] * lor; dy_dv[0] = without_height; realt dcenter = 2 * av_[0] * xa1a2 / av_[2] * (av_[3]*lor*lor + (1-av_[3])*M_LN2*ex); dy_dv[1] = dcenter; dy_dv[2] = dcenter * xa1a2; dy_dv[3] = av_[0] * (lor - ex); dy_dx = -dcenter; CALCULATE_DERIV_END(av_[0] * without_height) bool FuncPseudoVoigt::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { // neglecting Gaussian part and adding 4.0 to compensate it realt w = (sqrt (av_[3] * fabs(av_[0]/level) - 1) + 4.) * av_[2]; left = av_[1] - w; right = av_[1] + w; } return true; } bool FuncPseudoVoigt::get_area(realt* a) const { *a = av_[0] * fabs(av_[2]) * ((av_[3] * M_PI) + (1 - av_[3]) * sqrt(M_PI / M_LN2)); return true; } /////////////////////////////////////////////////////////////////////// void FuncVoigt::more_precomputations() { if (av_.size() != 6) av_.resize(6); float k, l, dkdx, dkdy; humdev(0, fabs(av_[3]), k, l, dkdx, dkdy); av_[4] = 1. / k; av_[5] = dkdy / k; if (fabs(av_[2]) < epsilon) av_[2] = epsilon; } CALCULATE_VALUE_BEGIN(FuncVoigt) // humdev/humlik routines require with y (a3 here) parameter >0. float k; realt xa1a2 = (x - av_[1]) / av_[2]; k = humlik(xa1a2, fabs(av_[3])); CALCULATE_VALUE_END(av_[0] * av_[4] * k) CALCULATE_DERIV_BEGIN(FuncVoigt) // humdev/humlik routines require with y (a3 here) parameter >0. // here fabs(av_[3]) is used, and dy_dv[3] is negated if av_[3]<0. float k; realt xa1a2 = (x-av_[1]) / av_[2]; realt a0a4 = av_[0] * av_[4]; float l, dkdx, dkdy; humdev(xa1a2, fabs(av_[3]), k, l, dkdx, dkdy); dy_dv[0] = av_[4] * k; realt dcenter = -a0a4 * dkdx / av_[2]; dy_dv[1] = dcenter; dy_dv[2] = dcenter * xa1a2; dy_dv[3] = a0a4 * (dkdy - k * av_[5]); if (av_[3] < 0) dy_dv[3] = -dy_dv[3]; dy_dx = -dcenter; CALCULATE_DERIV_END(a0a4 * k) bool FuncVoigt::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; realt t = fabs(av_[0]/level); if (t <= 1) { left = right = 0; } else { // I couldn't find ready-to-use approximation of the Voigt inverse. // This estimation is used instead. // width of Lorentzian (exact width when shape -> inf) realt w_l = av_[3] * sqrt(t - 1); // width of Gaussian (exact width when shape=0) realt w_g = sqrt(log(t)); // The sum should do as upper bound of the width at given level. realt w = (w_l + w_g) * av_[2]; left = av_[1] - w; right = av_[1] + w; } return true; } /// estimation according to /// http://en.wikipedia.org/w/index.php?title=Voigt_profile&oldid=115518205 /// fV ~= 0.5346fL + sqrt(0.2166 fL^2 + fG^2) /// /// In original paper, Olivero & Longbothum, 1977, /// http://dx.doi.org/10.1016/0022-4073(77)90161-3 /// this approx. is called "modified Whiting" and is given as: /// alphaV = 1/2 { C1 alphaL + sqrt(C2 alphaL^2 + 4 C3 alphaD^2) } /// where C1=1.0692, C2=0.86639, C3=1.0 /// Which is the same as the first formula (C1/2=0.5346, C2/4=0.2165975). /// /// Voigt parameters used in fityk (gwidth, shape) are equal: /// gwidth = sqrt(2) * sigma /// shape = gamma / (sqrt(2) * sigma) /// where sigma and gamma are defined as in the Wikipedia article. static realt voigt_fwhm(realt gwidth, realt shape) { realt sigma = fabs(gwidth) / M_SQRT2; realt gamma = fabs(gwidth) * shape; realt fG = 2 * sigma * sqrt(2 * M_LN2); realt fL = 2 * gamma; realt fV = 0.5346 * fL + sqrt(0.2165975 * fL * fL + fG * fG); return fV; } bool FuncVoigt::get_fwhm(realt* a) const { *a = voigt_fwhm(av_[2], av_[3]); return true; } bool FuncVoigt::get_area(realt* a) const { *a = av_[0] * fabs(av_[2] * sqrt(M_PI) * av_[4]); return true; } const vector& FuncVoigt::get_other_prop_names() const { static const vector p = vector2(string("GaussianFWHM"), string("LorentzianFWHM")); return p; } bool FuncVoigt::get_other_prop(string const& name, realt* a) const { if (name == "GaussianFWHM") { realt sigma = fabs(av_[2]) / M_SQRT2; *a = 2 * sigma * sqrt(2 * M_LN2); return true; } else if (name == "LorentzianFWHM") { realt gamma = fabs(av_[2]) * av_[3]; *a = 2 * gamma; return true; } else { return false; } } /////////////////////////////////////////////////////////////////////// void FuncVoigtA::more_precomputations() { if (av_.size() != 6) av_.resize(6); av_[4] = 1. / humlik(0, fabs(av_[3])); if (fabs(av_[2]) < epsilon) av_[2] = epsilon; } CALCULATE_VALUE_BEGIN(FuncVoigtA) // humdev/humlik routines require with y (a3 here) parameter >0. float k; realt xa1a2 = (x - av_[1]) / av_[2]; k = humlik(xa1a2, fabs(av_[3])); CALCULATE_VALUE_END(av_[0] / (sqrt(M_PI) * av_[2]) * k) CALCULATE_DERIV_BEGIN(FuncVoigtA) // humdev/humlik routines require with y (a3 here) parameter >0. // here fabs(av_[3]) is used, and dy_dv[3] is negated if av_[3]<0. float k; realt xa1a2 = (x-av_[1]) / av_[2]; realt f = av_[0] / (sqrt(M_PI) * av_[2]); float l, dkdx, dkdy; humdev(xa1a2, fabs(av_[3]), k, l, dkdx, dkdy); dy_dv[0] = k / (sqrt(M_PI) * av_[2]); realt dcenter = -f * dkdx / av_[2]; dy_dv[1] = dcenter; dy_dv[2] = dcenter * xa1a2 - f * k / av_[2]; dy_dv[3] = f * dkdy; if (av_[3] < 0) dy_dv[3] = -dy_dv[3]; dy_dx = -dcenter; CALCULATE_DERIV_END(f * k) bool FuncVoigtA::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { //TODO estimate Voigt's non-zero range return false; } return true; } bool FuncVoigtA::get_fwhm(realt* a) const { *a = voigt_fwhm(av_[2], av_[3]); return true; } bool FuncVoigtA::get_height(realt* a) const { *a = av_[0] / fabs(av_[2] * sqrt(M_PI) * av_[4]); return true; } /////////////////////////////////////////////////////////////////////// void FuncEMG::more_precomputations() { } bool FuncEMG::get_nonzero_range(double/*level*/, realt&/*left*/, realt&/*right*/) const { return false; } // approximation to erfc(x) * exp(x*x) for |x| > 4; // if x < -26.something exp(x*x) in the last line returns inf; // based on "Rational Chebyshev approximations for the error function" // by W.J. Cody, Math. Comp., 1969, 631-638. static double erfcexp_x4(double x) { double ax = fabs(x); assert(ax >= 4.); const double p[4] = { 3.05326634961232344e-1, 3.60344899949804439e-1, 1.25781726111229246e-1, 1.60837851487422766e-2 }; const double q[4] = { 2.56852019228982242, 1.87295284992346047, 5.27905102951428412e-1, 6.05183413124413191e-2 }; double rsq = 1 / (ax * ax); double xnum = 1.63153871373020978e-2 * rsq; double xden = rsq; for (int i = 0; i < 4; ++i) { xnum = (xnum + p[i]) * rsq; xden = (xden + q[i]) * rsq; } double t = rsq * (xnum + 6.58749161529837803e-4) / (xden + 2.33520497626869185e-3); double v = (1/sqrt(M_PI) - t) / ax; return x >= 0 ? v : 2*exp(x*x) - v; } CALCULATE_VALUE_BEGIN(FuncEMG) realt a = av_[0]; realt bx = av_[1] - x; realt c = av_[2]; realt d = av_[3]; realt fact = c*sqrt(M_PI/2)/d; realt erf_arg = (bx/c + c/d) / M_SQRT2; // e_arg == bx/d + c*c/(2*d*d) // erf_arg^2 == bx^2/(2*c^2) + bx/d + c^2/(2*d^2) // e_arg == erf_arg^2 - bx^2/(2*c^2) realt t; // type double cannot handle erfc(x) for x >= 28 if (fabs(erf_arg) < 20) { realt e_arg = bx/d + c*c/(2*d*d); // t = fact * exp(e_arg) * (d >= 0 ? 1-erf(erf_arg) : -1-erf(erf_arg)); t = fact * exp(e_arg) * (d >= 0 ? erfc(erf_arg) : -erfc(-erf_arg)); } else if ((d >= 0 && erf_arg > -26) || (d < 0 && -erf_arg > -26)) { realt h = exp(-bx*bx/(2*c*c)); realt ee = d >= 0 ? erfcexp_x4(erf_arg) : -erfcexp_x4(-erf_arg); t = fact * h * ee; } else t = 0; CALCULATE_VALUE_END(a*t) CALCULATE_DERIV_BEGIN(FuncEMG) realt a = av_[0]; realt bx = av_[1] - x; realt c = av_[2]; realt d = av_[3]; realt fact = c*sqrt(M_PI/2)/d; realt erf_arg = (bx/c + c/d) / M_SQRT2; //== (c*c+b*d-d*x)/(M_SQRT2*c*d); realt ee; if (fabs(erf_arg) < 20) ee = exp(erf_arg*erf_arg) * (d >= 0 ? erfc(erf_arg) : -erfc(-erf_arg)); else if ((d >= 0 && erf_arg > -26) || (d < 0 && -erf_arg > -26)) ee = d >= 0 ? erfcexp_x4(erf_arg) : -erfcexp_x4(-erf_arg); else ee = 0; realt h = exp(-bx*bx/(2*c*c)); realt t = fact * h * ee; dy_dv[0] = t; dy_dv[1] = -a/d * h + a*t/d; dy_dv[2] = -a/(c*d*d) * (h * (c*c - bx*d) - t * (c*c + d*d)); dy_dv[3] = a/(d*d*d) * (h * c*c - t * (c*c + d*d + bx*d)); dy_dx = - dy_dv[1]; CALCULATE_DERIV_END(a*t) bool FuncEMG::get_area(realt* a) const { *a = av_[0]*av_[2]*sqrt(2*M_PI); return true; } /////////////////////////////////////////////////////////////////////// bool FuncDoniachSunjic::get_nonzero_range(double/*level*/, realt&/*left*/, realt&/*right*/) const { return false; } CALCULATE_VALUE_BEGIN(FuncDoniachSunjic) realt h = av_[0]; realt a = av_[1]; realt F = av_[2]; realt xE = x - av_[3]; realt t = h * cos(M_PI*a/2 + (1-a)*atan(xE/F)) / pow(F*F+xE*xE, (1-a)/2); CALCULATE_VALUE_END(t) CALCULATE_DERIV_BEGIN(FuncDoniachSunjic) realt h = av_[0]; realt a = av_[1]; realt F = av_[2]; realt xE = x - av_[3]; realt fe2 = F*F+xE*xE; realt ac = 1-a; realt p = pow(fe2, -ac/2); realt at = atan(xE/F); realt cos_arg = M_PI*a/2 + ac*at; realt co = cos(cos_arg); realt si = sin(cos_arg); realt t = co * p; dy_dv[0] = t; dy_dv[1] = h * p * (co/2 * log(fe2) + (at-M_PI/2) * si); dy_dv[2] = h * ac*p/fe2 * (xE*si - F*co); dy_dv[3] = h * ac*p/fe2 * (xE*co + si*F); dy_dx = -dy_dv[3]; CALCULATE_DERIV_END(h*t) /////////////////////////////////////////////////////////////////////// CALCULATE_VALUE_BEGIN(FuncPielaszekCube) realt height = av_[0]; realt center = av_[1]; realt R = av_[2]; realt s = av_[3]; realt s2 = s*s; realt s4 = s2*s2; realt R2 = R*R; realt q = (x-center); realt q2 = q*q; realt t = height * (-3*R*(-1 - (R2*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2)) * cos(2*(-1.5 + R2/(2.*s2)) * atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*(-0.5 + R2/(2.*s2))* s2); CALCULATE_VALUE_END(t) CALCULATE_DERIV_BEGIN(FuncPielaszekCube) realt height = av_[0]; realt center = av_[1]; realt R = av_[2]; realt s = av_[3]; realt s2 = s*s; realt s3 = s*s2; realt s4 = s2*s2; realt R2 = R*R; realt R4 = R2*R2; realt R3 = R*R2; realt q = (x-center); realt q2 = q*q; realt t = (-3*R*(-1 - (R2*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2)) * cos(2*(-1.5 + R2/(2.*s2)) * atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*(-0.5 + R2/(2.*s2))* s2); realt dcenter = height * ( (3*sqrt(2/M_PI)*R*(-1 - (R2* (-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (q*q2*(-0.5 + R2/(2.*s2))*s2) - (3*R*((R2*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (q*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4) - (R2*((2*q*(1.5 - R2/(2.*s2))* s4* pow(1 + (q2*s4)/R2, 0.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R)))/R2 - (2*(-1.5 + R2/(2.*s2))*s2* pow(1 + (q2*s4)/R2, 0.5 - R2/(2.*s2))* sin(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R)))/R))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*(-0.5 + R2/(2.*s2))* s2)); realt dR = height * ( (3*R2*(-1 - (R2* (-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*pow(-0.5 + R2/(2.*s2),2)* s4) - (3*(-1 - (R2*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*(-0.5 + R2/(2.*s2))* s2) - (3*R*((R3* (-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* pow(-1 + R2/(2.*s2),2)*s4*s2) + (R3*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*pow(-1.5 + R2/(2.*s2),2)* (-1 + R2/(2.*s2))*(s4*s2)) - (R*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4) - (R2*(pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))* ((-2*q2*(1.5 - R2/(2.*s2))* s4)/ (R3* (1 + (q2*s4)/R2)) - (R*log(1 + (q2*s4)/R2))/ s2) + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* ((2*q*(-1.5 + R2/(2.*s2))* s2)/ (R2* (1 + (q2*s4)/R2)) - (2*R*atan((q*s2)/R))/s2)* sin(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*(-0.5 + R2/(2.*s2))* s2)); realt ds = height * ( (-3*R3*(-1 - (R2* (-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*pow(-0.5 + R2/(2.*s2),2)* (s4*s)) + (3*sqrt(2/M_PI)*R* (-1 - (R2*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (q2*(-0.5 + R2/(2.*s2))*s3) - (3*R*(-(R4*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* pow(-1 + R2/(2.*s2),2)*(s4*s3)) - (R4*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*pow(-1.5 + R2/(2.*s2),2)* (-1 + R2/(2.*s2))*(s4*s3)) + (2*R2*(-1 + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*(s4*s)) - (R2*(pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* cos(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))* ((4*q2*(1.5 - R2/(2.*s2))* s3)/ (R2* (1 + (q2*s4)/R2)) + (R2*log(1 + (q2*s4)/R2))/ s3) + pow(1 + (q2*s4)/R2, 1.5 - R2/(2.*s2))* ((-4*q*(-1.5 + R2/(2.*s2))*s)/ (R*(1 + (q2*s4)/R2)) + (2*R2*atan((q*s2)/R))/ s3)* sin(2*(-1.5 + R2/(2.*s2))* atan((q*s2)/R))))/ (2.*q2*(-1.5 + R2/(2.*s2))* (-1 + R2/(2.*s2))*s4)))/ (sqrt(2*M_PI)*q2*(-0.5 + R2/(2.*s2))* s2)); dy_dv[0] = t; dy_dv[1] = -dcenter; dy_dv[2] = dR; dy_dv[3] = ds; dy_dx = dcenter; CALCULATE_DERIV_END(height*t) /////////////////////////////////////////////////////////////////////// // Implemented by Mirko Scholz. The formula is taken from: // Bingemann, D.; Ernsting, N. P. J. Chem. Phys. 1995, 102, 2691–2700. void FuncLogNormal::more_precomputations() { if (av_.size() != 4) av_.resize(4); if (fabs(av_[2]) < epsilon) av_[2] = epsilon; if (fabs(av_[3]) < epsilon) av_[3] = 0.001; } CALCULATE_VALUE_BEGIN(FuncLogNormal) realt a = 2.0 * av_[3] * (x - av_[1]) / av_[2]; realt ex = 0.0; if (a > -1.0) { realt b = log(1 + a) / av_[3]; ex = av_[0] * exp(-M_LN2 * b * b); } CALCULATE_VALUE_END(ex) CALCULATE_DERIV_BEGIN(FuncLogNormal) realt a = 2.0 * av_[3] * (x - av_[1]) / av_[2]; realt ex; if (a > -1.0) { realt b = log(1 + a) / av_[3]; ex = exp(-M_LN2 * b * b); dy_dv[0] = ex; ex *= av_[0]; dy_dv[1] = 4.0*M_LN2/(av_[2]*(a+1))*ex*b; dy_dv[2] = 4.0*(x-av_[1])*M_LN2/(av_[2]*av_[2]*(a+1))*ex*b; dy_dv[3] = ex*(2.0*M_LN2*b*b/av_[3] -4.0*(x-av_[1])*log(a+1)*M_LN2/(av_[2]*av_[3]*av_[3]*(a+1))); dy_dx = -4.0*M_LN2/(av_[2]*(a+1))*ex*b; } else { ex = 0.0; dy_dv[0] = 0.0; dy_dv[1] = 0.0; dy_dv[2] = 0.0; dy_dv[3] = 0.0; dy_dx = 0.0; } CALCULATE_DERIV_END(ex) bool FuncLogNormal::get_nonzero_range(double level, realt &left, realt &right) const { /* untested */ if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { //realt w = sqrt (log (fabs(av_[0]/level)) / M_LN2) * av_[2]; realt w1 = (1-exp(sqrt(log(fabs(av_[0]/level))/M_LN2)*av_[3]))*av_[2] /2.0/av_[3]+av_[1]; realt w0 = (1-exp(-sqrt(log(fabs(av_[0]/level))/M_LN2)*av_[3]))*av_[2] /2.0/av_[3]+av_[1]; if (w1>w0) { left = w0; right = w1; } else { left = w1; right = w0; } } return true; } //cf. eq. 28 of Maroncelli, M.; Fleming, G.R. J. Phys. Chem. 1987, 86, 6221-6239 bool FuncLogNormal::get_fwhm(realt* a) const { *a = av_[2]*sinh(av_[3])/av_[3]; return true; } bool FuncLogNormal::get_area(realt* a) const { *a = av_[0]/sqrt(M_LN2/M_PI) / (2.0/av_[2]) / exp(-av_[3]*av_[3]/4.0/M_LN2); return true; } /////////////////////////////////////////////////////////////////////// // so far all the va functions have parameters x1,y1,x2,y2,... std::string VarArgFunction::get_param(int n) const { if (is_index(n, av_)) return (n % 2 == 0 ? "x" : "y") + S(n/2 + 1); else return ""; } void FuncSpline::more_precomputations() { q_.resize(nv() / 2); for (size_t i = 0; i < q_.size(); ++i) { q_[i].x = av_[2*i]; q_[i].y = av_[2*i+1]; } prepare_spline_interpolation(q_); } CALCULATE_VALUE_BEGIN(FuncSpline) realt t = get_spline_interpolation(q_, x); CALCULATE_VALUE_END(t) CALCULATE_DERIV_BEGIN(FuncSpline) dy_dx = 0; // unused //dy_dv[]; realt t = get_spline_interpolation(q_, x); CALCULATE_DERIV_END(t) /////////////////////////////////////////////////////////////////////// void FuncPolyline::more_precomputations() { q_.resize(nv() / 2); for (size_t i = 0; i < q_.size(); ++i) { q_[i].x = av_[2*i]; q_[i].y = av_[2*i+1]; } } CALCULATE_VALUE_BEGIN(FuncPolyline) realt t = get_linear_interpolation(q_, x); CALCULATE_VALUE_END(t) CALCULATE_DERIV_BEGIN(FuncPolyline) double value; if (q_.empty()) { dy_dx = 0; value = 0.; } else if (q_.size() == 1) { //dy_dv[0] = 0; // 0 -> p_x dy_dv[1] = 1; // 1 -> p_y dy_dx = 0; value = q_[0].y; } else { // value = p0.y + (p1.y - p0.y) / (p1.x - p0.x) * (x - p0.x); vector::iterator pos = get_interpolation_segment(q_, x); double lx = (pos + 1)->x - pos->x; double ly = (pos + 1)->y - pos->y; double d = x - pos->x; double a = ly / lx; size_t npos = pos - q_.begin(); dy_dv[2*npos+0] = a*d/lx - a; // p0.x dy_dv[2*npos+1] = 1 - d/lx; // p0.y dy_dv[2*npos+2] = -a*d/lx; // p1.x dy_dv[2*npos+3] = d/lx; // p1.y dy_dx = a; value = pos->y + a * d; } CALCULATE_DERIV_END(value) /////////////////////////////////////////////////////////////////////// } // namespace fityk fityk-1.3.1/fityk/bfunc.h000066400000000000000000000221161302634723100152410ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_BFUNC_H_ #define FITYK_BFUNC_H_ #include "func.h" #include "numfuncs.h" // PointQ #include "tplate.h" // Tplate::Ptr #include "common.h" // DISALLOW_COPY_AND_ASSIGN #define DECLARE_FUNC_OBLIGATORY_METHODS(NAME, PARENT) \ private:\ DISALLOW_COPY_AND_ASSIGN(Func##NAME); \ public:\ Func##NAME (const Settings* settings, \ const std::string &name, \ Tplate::Ptr tp, \ std::vector const &vars) \ : PARENT(settings, name, tp, vars) {} \ void calculate_value_in_range(std::vector const &xx, \ std::vector &yy, \ int first, int last) const;\ void calculate_value_deriv_in_range(std::vector const &xx, \ std::vector &yy, \ std::vector &dy_da, \ bool in_dx, \ int first, int last) const; ////////////////////////////////////////////////////////////////////////// namespace fityk { class FuncConstant : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Constant, Function) }; class FuncLinear : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Linear, Function) }; class FuncQuadratic : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Quadratic, Function) }; class FuncCubic : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Cubic, Function) }; class FuncPolynomial4 : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Polynomial4, Function) }; class FuncPolynomial5 : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Polynomial5, Function) }; class FuncPolynomial6 : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Polynomial6, Function) }; class FuncGaussian : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Gaussian, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool is_symmetric() const { return true; } bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const { *a = 2 * fabs(av_[2]); return true; } bool get_area(realt* a) const; }; class FuncSplitGaussian : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(SplitGaussian, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const { *a = fabs(av_[2])+fabs(av_[3]); return true; } bool get_area(realt* a) const; }; class FuncLorentzian : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Lorentzian, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool is_symmetric() const { return true; } bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const { *a = 2 * fabs(av_[2]); return true; } bool get_area(realt* a) const { *a = av_[0] * fabs(av_[2]) * M_PI; return true; } }; class FuncPearson7 : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Pearson7, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool is_symmetric() const { return true; } bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const { *a = 2 * fabs(av_[2]); return true; } bool get_area(realt* a) const; }; class FuncSplitPearson7 : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(SplitPearson7, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const { *a = fabs(av_[2])+fabs(av_[3]); return true; } bool get_area(realt* a) const; }; class FuncPseudoVoigt : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(PseudoVoigt, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool is_symmetric() const { return true; } bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const { *a = 2 * fabs(av_[2]); return true; } bool get_area(realt* a) const; }; class FuncVoigt : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(Voigt, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool is_symmetric() const { return true; } bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const; bool get_area(realt* a) const; const std::vector& get_other_prop_names() const; bool get_other_prop(std::string const& name, realt* a) const; }; class FuncVoigtA : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(VoigtA, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool is_symmetric() const { return true; } bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const; bool get_fwhm(realt* a) const; bool get_area(realt* a) const { *a = av_[0]; return true; } }; class FuncEMG : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(EMG, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_area(realt* a) const; }; class FuncDoniachSunjic : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(DoniachSunjic, Function) bool get_nonzero_range(double level, realt &left, realt &right) const; bool get_center(realt* a) const { *a = av_[3]; return true; } }; class FuncPielaszekCube : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(PielaszekCube, Function) bool get_center(realt* a) const { *a = av_[1]; return true; } }; class FuncLogNormal : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(LogNormal, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const; bool get_area(realt* a) const; }; class VarArgFunction : public Function { public: virtual std::string get_param(int n) const; protected: VarArgFunction(const Settings* settings, const std::string &name, Tplate::Ptr tp, const std::vector &vars) : Function(settings, name, tp, vars) {} virtual void init() { center_idx_ = -1; } }; class FuncSpline : public VarArgFunction { DECLARE_FUNC_OBLIGATORY_METHODS(Spline, VarArgFunction) void more_precomputations(); private: mutable std::vector q_; }; class FuncPolyline : public VarArgFunction { DECLARE_FUNC_OBLIGATORY_METHODS(Polyline, VarArgFunction) void more_precomputations(); private: mutable std::vector q_; }; // macros for use in implementations #define CALCULATE_VALUE_BEGIN(NAME) \ void NAME::calculate_value_in_range(vector const &xx, vector &yy,\ int first, int last) const\ {\ for (int i = first; i < last; ++i) {\ realt x = xx[i]; #define CALCULATE_VALUE_END(VAL) \ yy[i] += (VAL);\ }\ } #define CALCULATE_DERIV_BEGIN(NAME) \ void NAME::calculate_value_deriv_in_range(vector const &xx, \ vector &yy, \ vector &dy_da, \ bool in_dx, \ int first, int last) const \ { \ int dyn = dy_da.size() / xx.size(); \ vector dy_dv(nv(), 0.); \ for (int i = first; i < last; ++i) { \ realt x = xx[i]; \ realt dy_dx; #define CALCULATE_DERIV_END(VAL) \ if (!in_dx) { \ yy[i] += (VAL); \ v_foreach (Multi, j, multi_) \ dy_da[dyn*i+j->p] += dy_dv[j->n] * j->mult;\ dy_da[dyn*i+dyn-1] += dy_dx;\ }\ else { \ v_foreach (Multi, j, multi_) \ dy_da[dyn*i+j->p] += dy_da[dyn*i+dyn-1] * dy_dv[j->n]*j->mult;\ } \ } \ } } // namespace fityk #endif fityk-1.3.1/fityk/cmpfit/000077500000000000000000000000001302634723100152535ustar00rootroot00000000000000fityk-1.3.1/fityk/cmpfit/DISCLAIMER000066400000000000000000000060631302634723100166170ustar00rootroot00000000000000 MPFIT: A MINPACK-1 Least Squares Fitting Library in C Original public domain version by B. Garbow, K. Hillstrom, J. More' (Argonne National Laboratory, MINPACK project, March 1980) Copyright (1999) University of Chicago (see below) Tranlation to C Language by S. Moshier (moshier.net) (no restrictions placed on distribution) Enhancements and packaging by C. Markwardt (comparable to IDL fitting routine MPFIT see http://cow.physics.wisc.edu/~craigm/idl/idl.html) Copyright (C) 2003, 2004, 2006, 2007 Craig B. Markwardt This software is provided as is without any warranty whatsoever. Permission to use, copy, modify, and distribute modified or unmodified copies is granted, provided this copyright and disclaimer are included unchanged. Source code derived from MINPACK must have the following disclaimer text provided. =========================================================================== Minpack Copyright Notice (1999) University of Chicago. All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the University of Chicago, as Operator of Argonne National Laboratory. Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4) DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL BE CORRECTED. 5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE, EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE POSSIBILITY OF SUCH LOSS OR DAMAGES. fityk-1.3.1/fityk/cmpfit/README000066400000000000000000000656211302634723100161450ustar00rootroot00000000000000(this directory contains modified copy of cmpfit-1.2, see mpfit.patch) MPFIT: A MINPACK-1 Least Squares Fitting Library in C Original public domain version by B. Garbow, K. Hillstrom, J. More' (Argonne National Laboratory, MINPACK project, March 1980) Tranlation to C Language by S. Moshier (moshier.net) Enhancements, documentation and packaging by C. Markwardt (comparable to IDL fitting routine MPFIT see http://cow.physics.wisc.edu/~craigm/idl/idl.html) Copyright (C) 2003, 2004, 2006, 2007, 2009, 2010 Craig B. Markwardt SUMMARY of CHANGES 16 Feb 2009 - version 1.0 - initial release 18 Feb 2009 - version 1.1 - add 'version' field to 'results' struct 22 Nov 2009 - - allow to compile with C++ compiler - change to memset() instead of nonstandard bzero() - for Microsoft, proprietary equivalent of finite() 04 Oct 2010 - - add static declarations, remove some compiler warnings (reported by Lars Kr. Lundin) 13 Nov 2010 - version 1.2 - additional documentation, cleanup of mpfit.h $Id: README.html,v 1.3 2010/11/13 08:17:15 craigm Exp $ INTRODUCTION MPFIT uses the Levenberg-Marquardt technique to solve the least-squares problem. In its typical use, MPFIT will be used to fit a user-supplied function (the "model") to user-supplied data points (the "data") by adjusting a set of parameters. MPFIT is based upon MINPACK-1 (LMDIF.F) by More' and collaborators. For example, a researcher may think that a set of observed data points is best modelled with a Gaussian curve. A Gaussian curve is parameterized by its mean, standard deviation and normalization. MPFIT will, within certain constraints, find the set of parameters which best fits the data. The fit is "best" in the least-squares sense; that is, the sum of the weighted squared differences between the model and data is minimized. The Levenberg-Marquardt technique is a particular strategy for iteratively searching for the best fit. This particular implementation is drawn from a robust routine called MINPACK-1 (see NETLIB). This version allows upper and lower bounding constraints to be placed on each parameter, or the parameter can be held fixed. The user-supplied function should compute an array of weighted deviations between model and data. In a typical scientific problem the residuals should be weighted so that each deviate has a gaussian sigma of 1.0. If X represents values of the independent variable, Y represents a measurement for each value of X, and ERR represents the error in the measurements, then the deviates could be calculated as follows: for (i=0; ifunct is a C function which computes the residuals using any user data that is required. The number of residuals is specified by the integer m. The nature and properties of user function are described in greater detail below. The user function parameters are passed to mpfit as the array double xall[npar]; where npar is the number of parameters of the user function. It must be the case that m > npar, i.e. there are more data points than free parameters. The user must pass an initial "best guess" of the user parameters to mpfit(), and upon successful return, the xall[] array will contain the "best fit" parameters of the fit (and the original values are overwritten). The user function is responsible to compute an array of generic residuals. Usually these residuals will depend on user-dependent quantities such as measured data or independent variables such "x" when fitting a function of the form y(x). The user should pass these quantities using the optional private_data pointer. If private_data is not used then a null pointer should be passed. Otherwise, it can be any C pointer, typically a pointer to a structure such as this: struct example_private_data { /* EXAMPLE: fitting y(x) */ double *x; /* x - independent variable of model */ double *y; /* y - measured "y" values */ double *y_error; /* y_error - measurement uncertainty in y */ }; The user would be responsible to declare such a structure, and to fill it with pointers to the relevant data arrays before calling mpfit(). mpfit() itself does not inspect or modify the private_data contents, but merely passes it along to the user function The structure pars is optional, and allows the user to specify additional information and constraints about each user function parameter. For example, the user can specify simple bounding constraints. If passed, then pars[] must be dimensioned as, mp_par pars[npar]; where mp_par is a structure defined in mpfit.h. If no special parameter information is necessary, then the user can pass pars == 0. The optional structure config configures how mpfit() behaves, and is described in greater detail below. By passing a null pointer, the user obtains the default behavior. The structure result contains results of the fit, returned by mpfit(). The user should pass a pointer to a structure of type 'mp_result' (which should be zeroed), and upon return, the structure is filled with various diagnostic quantities about the fitting run. These quantities are described in greater detail below. If these diagnostics are not required, then the user may pass a null pointer. USER FUNCTION The user must define a function which computes the appropriate values as specified above. The function must compute the weighted deviations between the model and the data. The user function may also optionally compute explicit derivatives (see below). The user function should be of the following form: int myfunct(int m, int n, double *p, double *deviates, double **derivs, void *private) { int i; /* Compute function deviates */ for (i=0; i= 10 */ memset(&result, 0, sizeof(result)); status = mpfit(myfunct, m, n, p, pars, 0, 0, &result); EXAMPLE 6 - Increasing maximum number of iterations This example changes the maximum number of iterations from its default to 1000. mp_config config; mp_result result; memset(&config, 0, sizeof(config)); config.maxiter = 1000; memset(&result, 0, sizeof(result)); status = mpfit(myfunct, m, n, p, 0, &config, 0, &result); EXAMPLE 7 - Passing private data to user function This example passes "private" data to its user function using the private parameter. It assumes that three variables, x, y, and ey, already exist, and that the user function will know what to do with them. mp_result result; struct mystruct { double *x; double *y; double *ey; }; struct mystruct mydata; mydata.x = x; mydata.y = y; mydata.ey = ey; memset(&result, 0, sizeof(result)); status = mpfit(myfunct, m, n, p, 0, 0, (void *)&mydata, &result); EXAMPLE 8 - Complete example This example shows how to fit sample data to a linear function y = f(x) = a - b*x, where a and b are fitted parameters. There is sample data included within the program. The parameters are initialized to a = 1.0, b = 1.0, and then the fitting occurs. The function residuals; within linfunc(), the value of f(x) is computed. The main routine, main() initializes the variables and calls mpfit(). #include "mpfit.h" #include #include #include /* This is the private data structure which contains the data points and their uncertainties */ struct vars_struct { double *x; double *y; double *ey; }; /* * linear fit function * * m - number of data points * n - number of parameters (2) * p - array of fit parameters * dy - array of residuals to be returned * vars - private data (struct vars_struct *) * * RETURNS: error code (0 = success) */ int linfunc(int m, int n, double *p, double *dy, double **dvec, void *vars) { int i; struct vars_struct *v = (struct vars_struct *) vars; double *x, *y, *ey, f; x = v->x; y = v->y; ey = v->ey; for (i=0; i #include #include #include #include "mpfit.h" /* Forward declarations of functions in this module */ static int mp_fdjac2(mp_func funct, int m, int n, int *ifree, int npar, double *x, double *fvec, double *fjac, int ldfjac, double epsfcn, double *wa, void *priv, int *nfev, double *step, double *dstep, int *dside, int *qulimited, double *ulimit, int *ddebug, double *ddrtol, double *ddatol, double *wa2, double **dvecptr); static void mp_qrfac(int m, int n, double *a, int lda, int pivot, int *ipvt, int lipvt, double *rdiag, double *acnorm, double *wa); static void mp_qrsolv(int n, double *r, int ldr, int *ipvt, double *diag, double *qtb, double *x, double *sdiag, double *wa); static void mp_lmpar(int n, double *r, int ldr, int *ipvt, int *ifree, double *diag, double *qtb, double delta, double *par, double *x, double *sdiag, double *wa1, double *wa2); static double mp_enorm(int n, double *x); static double mp_dmax1(double a, double b); static double mp_dmin1(double a, double b); static int mp_min0(int a, int b); static int mp_covar(int n, double *r, int ldr, int *ipvt, double tol, double *wa); /* Macro to call user function */ #define mp_call(funct, m, n, x, fvec, dvec, priv) (*(funct))(m,n,x,fvec,dvec,priv) /* Macro to safely allocate memory */ #define mp_malloc(dest,type,size) \ dest = (type *) malloc( sizeof(type)*size ); \ if (dest == 0) { \ info = MP_ERR_MEMORY; \ goto CLEANUP; \ } else { \ int _k; \ for (_k=0; _k<(size); _k++) dest[_k] = 0; \ } /* * ********** * * subroutine mpfit * * the purpose of mpfit is to minimize the sum of the squares of * m nonlinear functions in n variables by a modification of * the levenberg-marquardt algorithm. the user must provide a * subroutine which calculates the functions. the jacobian is * then calculated by a finite-difference approximation. * * mp_funct funct - function to be minimized * int m - number of data points * int npar - number of fit parameters * double *xall - array of n initial parameter values * upon return, contains adjusted parameter values * mp_par *pars - array of npar structures specifying constraints; * or 0 (null pointer) for unconstrained fitting * [ see README and mpfit.h for definition & use of mp_par] * mp_config *config - pointer to structure which specifies the * configuration of mpfit(); or 0 (null pointer) * if the default configuration is to be used. * See README and mpfit.h for definition and use * of config. * void *private - any private user data which is to be passed directly * to funct without modification by mpfit(). * mp_result *result - pointer to structure, which upon return, contains * the results of the fit. The user should zero this * structure. If any of the array values are to be * returned, the user should allocate storage for them * and assign the corresponding pointer in *result. * Upon return, *result will be updated, and * any of the non-null arrays will be filled. * * * FORTRAN DOCUMENTATION BELOW * * * the subroutine statement is * * subroutine lmdif(fcn,m,n,x,fvec,ftol,xtol,gtol,maxfev,epsfcn, * diag,mode,factor,nprint,info,nfev,fjac, * ldfjac,ipvt,qtf,wa1,wa2,wa3,wa4) * * where * * fcn is the name of the user-supplied subroutine which * calculates the functions. fcn must be declared * in an external statement in the user calling * program, and should be written as follows. * * subroutine fcn(m,n,x,fvec,iflag) * integer m,n,iflag * double precision x(n),fvec(m) * ---------- * calculate the functions at x and * return this vector in fvec. * ---------- * return * end * * the value of iflag should not be changed by fcn unless * the user wants to terminate execution of lmdif. * in this case set iflag to a negative integer. * * m is a positive integer input variable set to the number * of functions. * * n is a positive integer input variable set to the number * of variables. n must not exceed m. * * x is an array of length n. on input x must contain * an initial estimate of the solution vector. on output x * contains the final estimate of the solution vector. * * fvec is an output array of length m which contains * the functions evaluated at the output x. * * ftol is a nonnegative input variable. termination * occurs when both the actual and predicted relative * reductions in the sum of squares are at most ftol. * therefore, ftol measures the relative error desired * in the sum of squares. * * xtol is a nonnegative input variable. termination * occurs when the relative error between two consecutive * iterates is at most xtol. therefore, xtol measures the * relative error desired in the approximate solution. * * gtol is a nonnegative input variable. termination * occurs when the cosine of the angle between fvec and * any column of the jacobian is at most gtol in absolute * value. therefore, gtol measures the orthogonality * desired between the function vector and the columns * of the jacobian. * * maxfev is a positive integer input variable. termination * occurs when the number of calls to fcn is at least * maxfev by the end of an iteration. * * epsfcn is an input variable used in determining a suitable * step length for the forward-difference approximation. this * approximation assumes that the relative errors in the * functions are of the order of epsfcn. if epsfcn is less * than the machine precision, it is assumed that the relative * errors in the functions are of the order of the machine * precision. * * diag is an array of length n. if mode = 1 (see * below), diag is internally set. if mode = 2, diag * must contain positive entries that serve as * multiplicative scale factors for the variables. * * mode is an integer input variable. if mode = 1, the * variables will be scaled internally. if mode = 2, * the scaling is specified by the input diag. other * values of mode are equivalent to mode = 1. * * factor is a positive input variable used in determining the * initial step bound. this bound is set to the product of * factor and the euclidean norm of diag*x if nonzero, or else * to factor itself. in most cases factor should lie in the * interval (.1,100.). 100. is a generally recommended value. * * nprint is an integer input variable that enables controlled * printing of iterates if it is positive. in this case, * fcn is called with iflag = 0 at the beginning of the first * iteration and every nprint iterations thereafter and * immediately prior to return, with x and fvec available * for printing. if nprint is not positive, no special calls * of fcn with iflag = 0 are made. * * info is an integer output variable. if the user has * terminated execution, info is set to the (negative) * value of iflag. see description of fcn. otherwise, * info is set as follows. * * info = 0 improper input parameters. * * info = 1 both actual and predicted relative reductions * in the sum of squares are at most ftol. * * info = 2 relative error between two consecutive iterates * is at most xtol. * * info = 3 conditions for info = 1 and info = 2 both hold. * * info = 4 the cosine of the angle between fvec and any * column of the jacobian is at most gtol in * absolute value. * * info = 5 number of calls to fcn has reached or * exceeded maxfev. * * info = 6 ftol is too small. no further reduction in * the sum of squares is possible. * * info = 7 xtol is too small. no further improvement in * the approximate solution x is possible. * * info = 8 gtol is too small. fvec is orthogonal to the * columns of the jacobian to machine precision. * * nfev is an integer output variable set to the number of * calls to fcn. * * fjac is an output m by n array. the upper n by n submatrix * of fjac contains an upper triangular matrix r with * diagonal elements of nonincreasing magnitude such that * * t t t * p *(jac *jac)*p = r *r, * * where p is a permutation matrix and jac is the final * calculated jacobian. column j of p is column ipvt(j) * (see below) of the identity matrix. the lower trapezoidal * part of fjac contains information generated during * the computation of r. * * ldfjac is a positive integer input variable not less than m * which specifies the leading dimension of the array fjac. * * ipvt is an integer output array of length n. ipvt * defines a permutation matrix p such that jac*p = q*r, * where jac is the final calculated jacobian, q is * orthogonal (not stored), and r is upper triangular * with diagonal elements of nonincreasing magnitude. * column j of p is column ipvt(j) of the identity matrix. * * qtf is an output array of length n which contains * the first n elements of the vector (q transpose)*fvec. * * wa1, wa2, and wa3 are work arrays of length n. * * wa4 is a work array of length m. * * subprograms called * * user-supplied ...... fcn * * minpack-supplied ... dpmpar,enorm,fdjac2,lmpar,qrfac * * fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * * ********** */ int mpfit(mp_func funct, int m, int npar, double *xall, mp_par *pars, mp_config *config, void *private_data, mp_result *result) { mp_config conf; int i, j, info, iflag, nfree, npegged, iter; int qanylim = 0; int ij,jj,l; double actred,delta,dirder,fnorm,fnorm1,gnorm, orignorm; double par,pnorm,prered,ratio; double sum,temp,temp1,temp2,temp3,xnorm, alpha; static double one = 1.0; static double p1 = 0.1; static double p5 = 0.5; static double p25 = 0.25; static double p75 = 0.75; static double p0001 = 1.0e-4; static double zero = 0.0; int nfev = 0; double *step = 0, *dstep = 0, *llim = 0, *ulim = 0; int *pfixed = 0, *mpside = 0, *ifree = 0, *qllim = 0, *qulim = 0; int *ddebug = 0; double *ddrtol = 0, *ddatol = 0; double *fvec = 0, *qtf = 0; double *x = 0, *xnew = 0, *fjac = 0, *diag = 0; double *wa1 = 0, *wa2 = 0, *wa3 = 0, *wa4 = 0; double **dvecptr = 0; int *ipvt = 0; int ldfjac; /* Default configuration */ conf.ftol = 1e-10; conf.xtol = 1e-10; conf.gtol = 1e-10; conf.stepfactor = 100.0; conf.nprint = 1; conf.epsfcn = MP_MACHEP0; conf.maxiter = 200; conf.douserscale = 0; conf.maxfev = 0; conf.covtol = 1e-14; conf.nofinitecheck = 0; if (config) { /* Transfer any user-specified configurations */ if (config->ftol > 0) conf.ftol = config->ftol; if (config->xtol > 0) conf.xtol = config->xtol; if (config->gtol > 0) conf.gtol = config->gtol; if (config->stepfactor > 0) conf.stepfactor = config->stepfactor; if (config->nprint >= 0) conf.nprint = config->nprint; if (config->epsfcn > 0) conf.epsfcn = config->epsfcn; if (config->maxiter > 0) conf.maxiter = config->maxiter; if (config->maxiter == MP_NO_ITER) conf.maxiter = 0; if (config->douserscale != 0) conf.douserscale = config->douserscale; if (config->covtol > 0) conf.covtol = config->covtol; if (config->nofinitecheck > 0) conf.nofinitecheck = config->nofinitecheck; conf.maxfev = config->maxfev; } info = 0; iflag = 0; nfree = 0; npegged = 0; /* Basic error checking */ if (funct == 0) { return MP_ERR_FUNC; } if ((m <= 0) || (xall == 0)) { return MP_ERR_NPOINTS; } if (npar <= 0) { return MP_ERR_NFREE; } fnorm = -1.0; fnorm1 = -1.0; xnorm = -1.0; delta = 0.0; /* FIXED parameters? */ mp_malloc(pfixed, int, npar); if (pars) for (i=0; i pars[i].limits[1])) ) { info = MP_ERR_INITBOUNDS; goto CLEANUP; } if ( (pars[i].fixed == 0) && pars[i].limited[0] && pars[i].limited[1] && (pars[i].limits[0] >= pars[i].limits[1])) { info = MP_ERR_BOUNDS; goto CLEANUP; } } mp_malloc(qulim, int, nfree); mp_malloc(qllim, int, nfree); mp_malloc(ulim, double, nfree); mp_malloc(llim, double, nfree); for (i=0; i 0)) { ij = j*ldfjac; for (i=0; i= ulim[j])); int dwa1 = fabs(wa1[j]) > MP_MACHEP0; if (lpegged && (wa1[j] < 0)) wa1[j] = 0; if (upegged && (wa1[j] > 0)) wa1[j] = 0; if (dwa1 && qllim[j] && ((x[j] + wa1[j]) < llim[j])) { alpha = mp_dmin1(alpha, (llim[j]-x[j])/wa1[j]); } if (dwa1 && qulim[j] && ((x[j] + wa1[j]) > ulim[j])) { alpha = mp_dmin1(alpha, (ulim[j]-x[j])/wa1[j]); } } /* Scale the resulting vector, advance to the next position */ for (j=0; j= 0) ? (+1) : (-1); sgnl = (llim[j] >= 0) ? (+1) : (-1); ulim1 = ulim[j]*(1-sgnu*MP_MACHEP0) - ((ulim[j] == 0)?(MP_MACHEP0):0); llim1 = llim[j]*(1+sgnl*MP_MACHEP0) + ((llim[j] == 0)?(MP_MACHEP0):0); if (qulim[j] && (wa2[j] >= ulim1)) { wa2[j] = ulim[j]; } if (qllim[j] && (wa2[j] <= llim1)) { wa2[j] = llim[j]; } } } for (j=0; j= zero) { temp = p5; } else { temp = p5*dirder/(dirder + p5*actred); } if (((p1*fnorm1) >= fnorm) || (temp < p1) ) { temp = p1; } delta = temp*mp_dmin1(delta,pnorm/p1); par = par/temp; } else { if ((par == zero) || (ratio >= p75) ) { delta = pnorm/p5; par = p5*par; } } /* * test for successful iteration. */ if (ratio >= p0001) { /* * successful iteration. update x, fvec, and their norms. */ for (j=0; j 0) && (nfev >= conf.maxfev)) { /* Too many function evaluations */ info = MP_MAXITER; } if (iter >= conf.maxiter) { /* Too many iterations */ info = MP_MAXITER; } if ((fabs(actred) <= MP_MACHEP0) && (prered <= MP_MACHEP0) && (p5*ratio <= one) ) { info = MP_FTOL; } if (delta <= MP_MACHEP0*xnorm) { info = MP_XTOL; } if (gnorm <= MP_MACHEP0) { info = MP_GTOL; } if (info != 0) { goto L300; } /* * end of the inner loop. repeat if iteration unsuccessful. */ if (ratio < p0001) goto L200; /* * end of the outer loop. */ goto OUTER_LOOP; L300: /* * termination, either normal or user imposed. */ if (iflag < 0) { info = iflag; } iflag = 0; for (i=0; i 0) && (info > 0)) { iflag = mp_call(funct, m, npar, xall, fvec, 0, private_data); nfev += 1; } /* Compute number of pegged parameters */ npegged = 0; if (pars) for (i=0; icovar || result->xerror)) { mp_covar(nfree, fjac, ldfjac, ipvt, conf.covtol, wa2); if (result->covar) { /* Zero the destination covariance array */ for (j=0; j<(npar*npar); j++) result->covar[j] = 0; /* Transfer the covariance array */ for (j=0; jcovar[ifree[j]*npar+ifree[i]] = fjac[j*ldfjac+i]; } } } if (result->xerror) { for (j=0; jxerror[j] = 0; for (j=0; j 0) result->xerror[ifree[j]] = sqrt(cc); } } } if (result) { strcpy(result->version, MPFIT_VERSION); result->bestnorm = mp_dmax1(fnorm,fnorm1); result->bestnorm *= result->bestnorm; result->orignorm = orignorm; result->status = info; result->niter = iter; result->nfev = nfev; result->npar = npar; result->nfree = nfree; result->npegged = npegged; result->nfunc = m; /* Copy residuals if requested */ if (result->resid) { for (j=0; jresid[j] = fvec[j]; } } CLEANUP: if (fvec) free(fvec); if (qtf) free(qtf); if (x) free(x); if (xnew) free(xnew); if (fjac) free(fjac); if (diag) free(diag); if (wa1) free(wa1); if (wa2) free(wa2); if (wa3) free(wa3); if (wa4) free(wa4); if (ipvt) free(ipvt); if (pfixed) free(pfixed); if (step) free(step); if (dstep) free(dstep); if (mpside) free(mpside); if (ddebug) free(ddebug); if (ddrtol) free(ddrtol); if (ddatol) free(ddatol); if (ifree) free(ifree); if (qllim) free(qllim); if (qulim) free(qulim); if (llim) free(llim); if (ulim) free(ulim); if (dvecptr) free(dvecptr); return info; } /************************fdjac2.c*************************/ static int mp_fdjac2(mp_func funct, int m, int n, int *ifree, int npar, double *x, double *fvec, double *fjac, int ldfjac, double epsfcn, double *wa, void *priv, int *nfev, double *step, double *dstep, int *dside, int *qulimited, double *ulimit, int *ddebug, double *ddrtol, double *ddatol, double *wa2, double **dvec) { /* * ********** * * subroutine fdjac2 * * this subroutine computes a forward-difference approximation * to the m by n jacobian matrix associated with a specified * problem of m functions in n variables. * * the subroutine statement is * * subroutine fdjac2(fcn,m,n,x,fvec,fjac,ldfjac,iflag,epsfcn,wa) * * where * * fcn is the name of the user-supplied subroutine which * calculates the functions. fcn must be declared * in an external statement in the user calling * program, and should be written as follows. * * subroutine fcn(m,n,x,fvec,iflag) * integer m,n,iflag * double precision x(n),fvec(m) * ---------- * calculate the functions at x and * return this vector in fvec. * ---------- * return * end * * the value of iflag should not be changed by fcn unless * the user wants to terminate execution of fdjac2. * in this case set iflag to a negative integer. * * m is a positive integer input variable set to the number * of functions. * * n is a positive integer input variable set to the number * of variables. n must not exceed m. * * x is an input array of length n. * * fvec is an input array of length m which must contain the * functions evaluated at x. * * fjac is an output m by n array which contains the * approximation to the jacobian matrix evaluated at x. * * ldfjac is a positive integer input variable not less than m * which specifies the leading dimension of the array fjac. * * iflag is an integer variable which can be used to terminate * the execution of fdjac2. see description of fcn. * * epsfcn is an input variable used in determining a suitable * step length for the forward-difference approximation. this * approximation assumes that the relative errors in the * functions are of the order of epsfcn. if epsfcn is less * than the machine precision, it is assumed that the relative * errors in the functions are of the order of the machine * precision. * * wa is a work array of length m. * * subprograms called * * user-supplied ...... fcn * * minpack-supplied ... dpmpar * * fortran-supplied ... dabs,dmax1,dsqrt * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * ********** */ int i,j,ij; int iflag = 0; double eps,h,temp; static double zero = 0.0; int has_analytical_deriv = 0, has_numerical_deriv = 0; int has_debug_deriv = 0; temp = mp_dmax1(epsfcn,MP_MACHEP0); eps = sqrt(temp); ij = 0; ldfjac = 0; /* Prevent compiler warning */ if (ldfjac){} /* Prevent compiler warning */ for (j=0; j 0) h = step[ifree[j]]; if (dstep && dstep[ifree[j]] > 0) h = fabs(dstep[ifree[j]]*temp); if (h == zero) h = eps; /* If negative step requested, or we are against the upper limit */ if ((dside && dsidei == -1) || (dside && dsidei == 0 && qulimited && ulimit && qulimited[j] && (temp > (ulimit[j]-h)))) { h = -h; } x[ifree[j]] = temp + h; iflag = mp_call(funct, m, npar, x, wa, 0, priv); if (nfev) *nfev = *nfev + 1; if (iflag < 0 ) goto DONE; x[ifree[j]] = temp; if (dsidei <= 1) { /* COMPUTE THE ONE-SIDED DERIVATIVE */ if (! debug) { /* Non-debug path for speed */ for (i=0; i da + fabs(fjold)*dr))) { printf(" %10d %10.4g %10.4g %10.4g %10.4g %10.4g\n", i, fvec[i], fjold, fjac[ij], fjold-fjac[ij], (fjold == 0)?(0):((fjold-fjac[ij])/fjold)); } } } /* end debugging */ } else { /* dside > 2 */ /* COMPUTE THE TWO-SIDED DERIVATIVE */ for (i=0; i da + fabs(fjold)*dr))) { printf(" %10d %10.4g %10.4g %10.4g %10.4g %10.4g\n", i, fvec[i], fjold, fjac[ij], fjold-fjac[ij], (fjold == 0)?(0):((fjold-fjac[ij])/fjold)); } } } /* end debugging */ } /* if (dside > 2) */ } /* if (has_numerical_derivative) */ if (has_debug_deriv) { printf("FJAC DEBUG END\n"); } DONE: if (iflag < 0) return iflag; return 0; /* * last card of subroutine fdjac2. */ } /************************qrfac.c*************************/ static void mp_qrfac(int m, int n, double *a, int lda, int pivot, int *ipvt, int lipvt, double *rdiag, double *acnorm, double *wa) { /* * ********** * * subroutine qrfac * * this subroutine uses householder transformations with column * pivoting (optional) to compute a qr factorization of the * m by n matrix a. that is, qrfac determines an orthogonal * matrix q, a permutation matrix p, and an upper trapezoidal * matrix r with diagonal elements of nonincreasing magnitude, * such that a*p = q*r. the householder transformation for * column k, k = 1,2,...,min(m,n), is of the form * * t * i - (1/u(k))*u*u * * where u has zeros in the first k-1 positions. the form of * this transformation and the method of pivoting first * appeared in the corresponding linpack subroutine. * * the subroutine statement is * * subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) * * where * * m is a positive integer input variable set to the number * of rows of a. * * n is a positive integer input variable set to the number * of columns of a. * * a is an m by n array. on input a contains the matrix for * which the qr factorization is to be computed. on output * the strict upper trapezoidal part of a contains the strict * upper trapezoidal part of r, and the lower trapezoidal * part of a contains a factored form of q (the non-trivial * elements of the u vectors described above). * * lda is a positive integer input variable not less than m * which specifies the leading dimension of the array a. * * pivot is a logical input variable. if pivot is set true, * then column pivoting is enforced. if pivot is set false, * then no column pivoting is done. * * ipvt is an integer output array of length lipvt. ipvt * defines the permutation matrix p such that a*p = q*r. * column j of p is column ipvt(j) of the identity matrix. * if pivot is false, ipvt is not referenced. * * lipvt is a positive integer input variable. if pivot is false, * then lipvt may be as small as 1. if pivot is true, then * lipvt must be at least n. * * rdiag is an output array of length n which contains the * diagonal elements of r. * * acnorm is an output array of length n which contains the * norms of the corresponding columns of the input matrix a. * if this information is not needed, then acnorm can coincide * with rdiag. * * wa is a work array of length n. if pivot is false, then wa * can coincide with rdiag. * * subprograms called * * minpack-supplied ... dpmpar,enorm * * fortran-supplied ... dmax1,dsqrt,min0 * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * * ********** */ int i,ij,jj,j,jp1,k,kmax,minmn; double ajnorm,sum,temp; static double zero = 0.0; static double one = 1.0; static double p05 = 0.05; lda = 0; /* Prevent compiler warning */ lipvt = 0; /* Prevent compiler warning */ if (lda) {} /* Prevent compiler warning */ if (lipvt) {} /* Prevent compiler warning */ /* * compute the initial column norms and initialize several arrays. */ ij = 0; for (j=0; j rdiag[kmax]) kmax = k; } if (kmax == j) goto L40; ij = m * j; jj = m * kmax; for (i=0; i kp1) { ik = kk + 1; for (i=kp1; i jp1) { ij = jp1 + ldr * j; for (i=jp1; i= 1) { for (k=0; k= 0) { ij = ldr * j; for (i=0; i<=jm1; i++) { wa1[i] -= r[ij]*temp; ij += 1; } } } } for (j=0; j= n) { for (j=0; j= 0) { ij = jj; for (i=0; i<=jm1; i++) { sum += r[ij]*wa1[i]; ij += 1; } } wa1[j] = (wa1[j] - sum)/r[j+ldr*j]; jj += ldr; /* [i+ldr*j] */ } temp = mp_enorm(n,wa1); parl = ((fp/delta)/temp)/temp; } /* * calculate an upper bound, paru, for the zero of the function. */ jj = 0; for (j=0; j zero) parl = mp_dmax1(parl, *par); if (fp < zero) paru = mp_dmin1(paru, *par); /* * compute an improved estimate for par. */ *par = mp_dmax1(parl, *par + parc); /* * end of an iteration. */ goto L150; L220: /* * termination. */ if (iter == 0) *par = zero; /* * last card of subroutine lmpar. */ } /************************enorm.c*************************/ static double mp_enorm(int n, double *x) { /* * ********** * * function enorm * * given an n-vector x, this function calculates the * euclidean norm of x. * * the euclidean norm is computed by accumulating the sum of * squares in three different sums. the sums of squares for the * small and large components are scaled so that no overflows * occur. non-destructive underflows are permitted. underflows * and overflows do not occur in the computation of the unscaled * sum of squares for the intermediate components. * the definitions of small, intermediate and large components * depend on two constants, rdwarf and rgiant. the main * restrictions on these constants are that rdwarf**2 not * underflow and rgiant**2 not overflow. the constants * given here are suitable for every known computer. * * the function statement is * * double precision function enorm(n,x) * * where * * n is a positive integer input variable. * * x is an input array of length n. * * subprograms called * * fortran-supplied ... dabs,dsqrt * * argonne national laboratory. minpack project. march 1980. * burton s. garbow, kenneth e. hillstrom, jorge j. more * * ********** */ int i; double agiant,floatn,s1,s2,s3,xabs,x1max,x3max; double ans, temp; double rdwarf = MP_RDWARF; double rgiant = MP_RGIANT; static double zero = 0.0; static double one = 1.0; s1 = zero; s2 = zero; s3 = zero; x1max = zero; x3max = zero; floatn = n; agiant = rgiant/floatn; for (i=0; i rdwarf) && (xabs < agiant)) { /* * sum for intermediate components. */ s2 += xabs*xabs; continue; } if (xabs > rdwarf) { /* * sum for large components. */ if (xabs > x1max) { temp = x1max/xabs; s1 = one + s1*temp*temp; x1max = xabs; } else { temp = xabs/x1max; s1 += temp*temp; } continue; } /* * sum for small components. */ if (xabs > x3max) { temp = x3max/xabs; s3 = one + s3*temp*temp; x3max = xabs; } else { if (xabs != zero) { temp = xabs/x3max; s3 += temp*temp; } } } /* * calculation of norm. */ if (s1 != zero) { temp = s1 + (s2/x1max)/x1max; ans = x1max*sqrt(temp); return(ans); } if (s2 != zero) { if (s2 >= x3max) temp = s2*(one+(x3max/s2)*(x3max*s3)); else temp = x3max*((s2/x3max)+(x3max*s3)); ans = sqrt(temp); } else { ans = x3max*sqrt(s3); } return(ans); /* * last card of function enorm. */ } /************************lmmisc.c*************************/ static double mp_dmax1(double a, double b) { if (a >= b) return(a); else return(b); } static double mp_dmin1(double a, double b) { if (a <= b) return(a); else return(b); } static int mp_min0(int a, int b) { if (a <= b) return(a); else return(b); } /************************covar.c*************************/ /* c ********** c c subroutine covar c c given an m by n matrix a, the problem is to determine c the covariance matrix corresponding to a, defined as c c t c inverse(a *a) . c c this subroutine completes the solution of the problem c if it is provided with the necessary information from the c qr factorization, with column pivoting, of a. that is, if c a*p = q*r, where p is a permutation matrix, q has orthogonal c columns, and r is an upper triangular matrix with diagonal c elements of nonincreasing magnitude, then covar expects c the full upper triangle of r and the permutation matrix p. c the covariance matrix is then computed as c c t t c p*inverse(r *r)*p . c c if a is nearly rank deficient, it may be desirable to compute c the covariance matrix corresponding to the linearly independent c columns of a. to define the numerical rank of a, covar uses c the tolerance tol. if l is the largest integer such that c c abs(r(l,l)) .gt. tol*abs(r(1,1)) , c c then covar computes the covariance matrix corresponding to c the first l columns of r. for k greater than l, column c and row ipvt(k) of the covariance matrix are set to zero. c c the subroutine statement is c c subroutine covar(n,r,ldr,ipvt,tol,wa) c c where c c n is a positive integer input variable set to the order of r. c c r is an n by n array. on input the full upper triangle must c contain the full upper triangle of the matrix r. on output c r contains the square symmetric covariance matrix. c c ldr is a positive integer input variable not less than n c which specifies the leading dimension of the array r. c c ipvt is an integer input array of length n which defines the c permutation matrix p such that a*p = q*r. column j of p c is column ipvt(j) of the identity matrix. c c tol is a nonnegative input variable used to define the c numerical rank of a in the manner described above. c c wa is a work array of length n. c c subprograms called c c fortran-supplied ... dabs c c argonne national laboratory. minpack project. august 1980. c burton s. garbow, kenneth e. hillstrom, jorge j. more c c ********** */ static int mp_covar(int n, double *r, int ldr, int *ipvt, double tol, double *wa) { int i, ii, j, jj, k, l; int kk, kj, ji, j0, k0, jj0; int sing; double one = 1.0, temp, tolr, zero = 0.0; /* * form the inverse of r in the full upper triangle of r. */ #if 0 for (j=0; j= 0) { for (k=0; k <= l; k++) { k0 = k*ldr; for (j=0; j l); j0 = j*ldr; jj0 = jj*ldr; for (i=0; i<=j; i++) { ji = j0+i; if (sing) r[ji] = zero; ii = ipvt[i]; if (ii > jj) r[jj0+ii] = r[ji]; if (ii < jj) r[ii*ldr+jj] = r[ji]; } wa[jj] = r[j0+j]; } /* * Symmetrize the covariance matrix in r */ for (j=0; j= 199901L #define mpfinite(x) isfinite(x) /* Microsoft C uses _finite(x) instead of finite(x) */ #elif defined(_MSC_VER) && _MSC_VER #include #define mpfinite(x) _finite(x) /* Default is to assume that compiler/library has finite() function */ #else #define mpfinite(x) finite(x) #endif #ifdef __cplusplus } /* extern "C" */ #endif #endif /* MPFIT_H */ fityk-1.3.1/fityk/cmpfit/mpfit.patch000066400000000000000000000016031302634723100174130ustar00rootroot00000000000000--- mpfit.c.orig 2012-10-01 00:30:51.533258108 +0100 +++ mpfit.c 2012-10-01 01:46:42.106809470 +0100 @@ -322,7 +322,7 @@ if (config->stepfactor > 0) conf.stepfactor = config->stepfactor; if (config->nprint >= 0) conf.nprint = config->nprint; if (config->epsfcn > 0) conf.epsfcn = config->epsfcn; - if (config->maxiter > 0) conf.maxiter = config->maxiter; + if (config->maxiter >= 0) conf.maxiter = config->maxiter; if (config->douserscale != 0) conf.douserscale = config->douserscale; if (config->covtol > 0) conf.covtol = config->covtol; if (config->nofinitecheck > 0) conf.nofinitecheck = config->nofinitecheck; @@ -624,7 +624,10 @@ */ if (gnorm <= conf.gtol) info = MP_OK_DIR; if (info != 0) goto L300; - if (conf.maxiter == 0) goto L300; + if (conf.maxiter == 0) { + info = MP_MAXITER; + goto L300; + } /* * rescale if necessary. fityk-1.3.1/fityk/common.cpp000066400000000000000000000065221302634723100157720ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "common.h" #include #include #include #include using namespace std; namespace fityk { const char* fityk_version_line = "# Fityk script. Fityk version: " VERSION; vector range_vector(int l, int u) { vector v(u - l); for (int i = l; i < u; i++) v[i - l] = i; return v; } string time_now() { time_t const t = time(0); return ctime (&t); } bool is_double(const string& s) { char const *c = s.c_str(); char *endptr; strtod(c, &endptr); if (c == endptr) return false; while (isspace(*endptr)) endptr++; return (*endptr == 0); } bool is_int(const string& s) { const char *c = s.c_str(); char *endptr; strtol(c, &endptr, 10); if (c == endptr) return false; while (isspace(*endptr)) endptr++; return (*endptr == 0); } void replace_all(string &s, const string &old, const string &new_) { string::size_type pos = 0; while ((pos = s.find(old, pos)) != string::npos) { s.replace(pos, old.size(), new_); pos += new_.size(); } } /// replaces all words `old_word' in text `str' with `new_word' /// word `foo' is in: "4*foo+1" but not in: "foobar", "_foo", "$foo" void replace_words(string &t, const string &old_word, const string &new_word) { string::size_type pos = 0; while ((pos=t.find(old_word, pos)) != string::npos) { int k = old_word.size(); if ((pos == 0 || !(isalnum(t[pos-1]) || t[pos-1]=='_' || t[pos-1]=='$')) && (pos+k==t.size() || !(isalnum(t[pos+k]) || t[pos+k]=='_'))) { t.replace(pos, k, new_word); pos += new_word.size(); } else pos++; } } /// find matching bracket for (, [ or {, return position in string string::size_type find_matching_bracket(const string& formula, string::size_type left_pos) { if (left_pos == string::npos) return string::npos; assert(left_pos < formula.size()); char opening = formula[left_pos], closing = 0; if (opening == '(') closing = ')'; else if (opening == '[') closing = ']'; else if (opening == '{') closing = '}'; else assert(0); int level = 1; for (size_t p = left_pos+1; p < formula.size() && level > 0; ++p) { if (formula[p] == closing) { if (level == 1) return p; --level; } else if (formula[p] == opening) ++level; } throw ExecuteError("Matching bracket `" + S(closing) + "' not found."); } bool match_glob(const char* name, const char* pattern) { while (*pattern != '\0') { if (*pattern == '*') { if (pattern[1] == '\0') return true; const char *here = name; while (*name != '\0') ++name; while (name != here) { if (match_glob(name, pattern)) return true; --name; } } else { if (*name != *pattern) return false; ++name; } ++pattern; } // if we are here (*pattern == '\0') return *name == '\0'; } } // namespace fityk fityk-1.3.1/fityk/common.h000066400000000000000000000242411302634723100154350ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Various headers and definitions. Included by almost all files. #ifndef FITYK_COMMON_H_ #define FITYK_COMMON_H_ #if HAVE_CONFIG_H # include #endif #ifndef VERSION # define VERSION "unknown" #endif #include #include #include #include "fityk.h" //ExecuteError // MS VC++ has no erf, erfc, trunc, snprintf functions #ifdef _MSC_VER #include using boost::math::erf; using boost::math::erfc; inline double trunc(double a) { return a >= 0 ? floor(a) : ceil(a); } #define snprintf sprintf_s // disable warning about unsafe sprintf #pragma warning( disable : 4996 ) #endif #ifdef NDEBUG #define soft_assert(expr) (void) 0 #else #define soft_assert(expr) \ if (!(expr)) \ fprintf(stderr, "WARNING: failed assertion `%s' in %s:%d\n", \ #expr, __FILE__, __LINE__) #endif //--------------------------------------------------------------------------- // inline helper functions that we keep outside of namespace /// Round real to integer. inline int iround(double d) { return static_cast(floor(d+0.5)); } template std::string format1(const char* fmt, T t) { char buffer[N]; snprintf(buffer, N, fmt, t); buffer[N-1] = '\0'; return std::string(buffer); } /// S() converts to string // generic version - disabled to prevent bugs such as printing pointer address //template inline std::string S(T k) // { return static_cast(std::ostringstream() << k).str(); } inline std::string S(bool b) { return b ? "true" : "false"; } inline std::string S(const char *k) { return std::string(k); } inline std::string S(char k) { return std::string(1, k); } inline std::string S(const std::string& k) { return k; } inline std::string S() { return std::string(); } inline std::string S(int n) { return format1("%d", n); } inline std::string S(long n) { return format1("%ld", n); } inline std::string S(size_t n) { return format1("%lu", (unsigned long) n); } inline std::string S(double d) { return format1("%g", d); } // more exact version of S(); convert double number with 12 significant digits inline std::string eS(double d) { return format1("%.12g", d); } inline std::string S(long double d) { return S((double) d); } /// splits string into tokens, separated by one-character delimitors template std::vector split_string(std::string const &s, T delim) { std::vector v; std::string::size_type start_pos = 0, pos=0; while (pos != std::string::npos) { pos = s.find_first_of(delim, start_pos); v.push_back(std::string(s, start_pos, pos-start_pos)); start_pos = pos+1; } return v; } /// check if vector (first arg) contains given element (second arg) template bool contains_element(T const& vec, T2 const& t) { return (find(vec.begin(), vec.end(), t) != vec.end()); } /// check if string (first arg) contains given substring (second arg) template bool contains_element(std::basic_string const& str, T2 const& t) { return (str.find(t) != std::basic_string::npos); } /// return first index of value, or -1 if not found template int index_of_element(std::vector const& vec, T2 const& t) { typename std::vector::const_iterator p = find(vec.begin(), vec.end(), t); if (p != vec.end()) return p - vec.begin(); else return -1; } /// similar to Python string.startswith() method inline bool startswith(std::string const& s, std::string const& p) { return p.size() <= s.size() && std::string(s, 0, p.size()) == p; } /// similar to Python string.endswith() method inline bool endswith(std::string const& s, std::string const& p) { return p.size() <= s.size() && std::string(s, s.size() - p.size()) == p; } /// similar to Python string.strip() method inline std::string strip_string(std::string const &s) { char const *blank = " \r\n\t"; std::string::size_type first = s.find_first_not_of(blank); if (first == std::string::npos) return std::string(); std::string::size_type last = s.find_last_not_of(blank); if (first == 0 && last == s.size() - 1) return s; else return std::string(s, first, last-first+1); } //--------------------------- V E C T O R -------------------------------- // boost/foreach.hpp includes quite a lot of code. Since only one version // is needed here, let's keep it simple #define v_foreach(type, iter, vec) \ for (vector::const_iterator iter = vec.begin(); iter != vec.end(); ++iter) #define vm_foreach(type, iter, vec) \ for (vector::iterator iter = vec.begin(); iter != vec.end(); ++iter) /// Makes 1-element vector template inline std::vector vector1 (T a) { return std::vector(1, a); } /// Makes 2-element vector template inline std::vector vector2 (T a, T b) { std::vector v = std::vector(2, a); v[1] = b; return v;} /// Make 3-element vector template inline std::vector vector3 (T a, T b, T c) { std::vector v = std::vector(3); v[0]=a; v[1]=b; v[2]=c; return v;} /// Make 4-element vector template inline std::vector vector4 (T a, T b, T c, T d) { std::vector v = std::vector(4); v[0]=a; v[1]=b; v[2]=c; v[3]=d; return v; } /// Make n-element vector, e.g.: vector_of(1)(2)(3)(4)(5) //template //struct vector_of: public std::vector //{ // vector_of(const T& t) { (*this)(t); } // vector_of& operator()(const T& t) { this->push_back(t); return *this; } //}; /// Return 0 <= n < a.size() template inline bool is_index (int idx, std::vector const& v) { return idx >= 0 && idx < static_cast(v.size()); } template inline std::string join(RandomAccessIterator first, RandomAccessIterator last, std::string const& sep) { if (last - first <= 0) return ""; std::string s = S(*first); for (RandomAccessIterator i = first + 1; i != last; ++i) s += sep + S(*i); return s; } template inline std::string join_vector(std::vector const& v, std::string const& sep) { return join(v.begin(), v.end(), sep); } /// delete all objects handled by pointers and clear vector template void purge_all_elements(std::vector &vec) { for (typename std::vector::iterator i=vec.begin(); i!=vec.end(); ++i) delete *i; vec.clear(); } namespace fityk { //-------------------------- N U M E R I C -------------------------------- /// epsilon is used for comparision of real numbers /// defined in settings.cpp; it can be changed in Settings extern FITYK_API double epsilon; inline bool is_eq(double a, double b) { return fabs(a-b) <= epsilon; } inline bool is_neq(double a, double b) { return fabs(a-b) > epsilon; } inline bool is_lt(double a, double b) { return a < b - epsilon; } inline bool is_gt(double a, double b) { return a > b + epsilon; } inline bool is_le(double a, double b) { return a <= b + epsilon; } inline bool is_ge(double a, double b) { return a >= b - epsilon; } inline bool is_zero(double a) { return fabs(a) <= epsilon; } inline bool is_finite(double a) { // to avoid "deprecated finite()" warning on OSX 10.9 we try first isfinite() #if defined(HAVE_ISFINITE) return isfinite(a); #elif defined(HAVE_FINITE) return finite(a); #else return a == a; // this checks only for NaN (better than nothing) #endif } #ifndef M_PI # define M_PI 3.1415926535897932384626433832795029 // pi #endif #ifndef M_LN2 # define M_LN2 0.6931471805599453094172321214581766 // log_e 2 #endif #ifndef M_SQRT2 # define M_SQRT2 1.4142135623730950488016887242096981 // sqrt(2) #endif //--------------------------- S T R I N G -------------------------------- /// True if the string contains only a real number bool is_double (std::string const& s); /// True if the string contains only an integer number bool is_int (std::string const& s); /// replace all occurences of old in string s with new_ FITYK_API void replace_all(std::string &s, std::string const &old, std::string const &new_); void replace_words(std::string &t, std::string const &old_word, std::string const &new_word); std::string::size_type find_matching_bracket(std::string const& formula, std::string::size_type left_pos); /// matches name against pattern containing '*' (wildcard) bool match_glob(const char* name, const char* pattern); // v e c t o r /// Make (u-l)-element vector, filled by numbers: l, l+1, ..., u-1. FITYK_API std::vector range_vector(int l, int u); /// Expression like "i inline int size(std::vector const& v) { return static_cast(v.size()); } //---------------- filename utils ------------------------------------- #if defined(_WIN32) || defined(WIN32) || defined(__NT__) || defined(__WIN32__) || defined(__OS2__) #define PATH_COMPONENT_SEP '\\' #else #define PATH_COMPONENT_SEP '/' #endif inline std::string get_directory(std::string const& filename) { std::string::size_type i = filename.rfind(PATH_COMPONENT_SEP); return i==std::string::npos ? std::string() : std::string(filename, 0, i+1); } //-------------------- M I S C E L A N O U S ------------------------------ // A macro to disallow the copy constructor and operator= functions. // This should be used in the private: declarations for a class. #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&) /// used to put version to script extern FITYK_API const char* fityk_version_line; extern const std::string help_filename; /// Get current date and time as formatted string std::string time_now(); } // namespace fityk #endif fityk-1.3.1/fityk/cparser.cpp000066400000000000000000001074641302634723100161500ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ /// Command parser. #define BUILDING_LIBFITYK #include "cparser.h" #include #include #include #include "lexer.h" #include "eparser.h" #include "settings.h" #include "logic.h" #include "data.h" #include "guess.h" // peak_traits, linear_traits #include "ast.h" // prepare_ast_with_der() #include "tplate.h" using namespace std; namespace fityk { const char *command_list[] = { "debug", "define", "delete", "exec", "fit", "guess", "info", "lua", "plot", "print", "quit", "reset", "set", "sleep", "title", "ui", "undefine", "use", "with", NULL }; const char* info_args[] = { "version", "compiler", "variables", "types", "functions", "dataset_count", "view", "fit_history", "filename", "title", "data", "formula", "gnuplot_formula", "simplified_formula", "simplified_gnuplot_formula", "models", "state", "history_summary", "peaks", "peaks_err", "set", "history", "guess", "fit", "errors", "confidence", "cov", "refs", "prop", NULL }; const char* debug_args[] = { // "%" and "$" mean that any %functions and $variables are accepted as args "parse", "lex", "expr", "der", "rd", "idx", "df", "%", "$", NULL }; const char* commandtype2str(CommandType c) { switch (c) { case kCmdDebug: return "Debug"; case kCmdDefine: return "Define"; case kCmdDelete: return "Delete"; case kCmdDeleteP: return "Delete"; case kCmdExec: return "Exec"; case kCmdFit: return "Fit"; case kCmdGuess: return "Guess"; case kCmdInfo: return "Info"; case kCmdLua: return "Lua"; case kCmdPlot: return "Plot"; case kCmdPrint: return "Print"; case kCmdQuit: return "Quit"; case kCmdReset: return "Reset"; case kCmdSet: return "Set"; case kCmdSleep: return "Sleep"; case kCmdTitle: return "Title"; case kCmdUi: return "Ui"; case kCmdUndef: return "Undef"; case kCmdUse: return "Use"; case kCmdShell: return "Shell"; case kCmdLoad: return "Load"; case kCmdDatasetTr: return "DatasetTr"; case kCmdNameFunc: return "NameFunc"; case kCmdAssignParam: return "AssignParam"; case kCmdNameVar: return "NameVar"; case kCmdChangeModel: return "ChangeModel"; case kCmdPointTr: return "PointTr"; case kCmdAllPointsTr: return "AllPointsTr"; case kCmdResizeP: return "ResizeP"; case kCmdNull: return "Null"; } return NULL; // avoid warning } static Token nop() { Token t; t.type = kTokenNop; return t; } static bool is_command(const Token& token, const char* cmd_base, const char* cmd_suffix) { assert(token.type == kTokenLname); int base_len = strlen(cmd_base); if (strncmp(token.str, cmd_base, base_len) != 0) return false; int left_chars = token.length - base_len; return left_chars == 0 || (left_chars <= (int) strlen(cmd_suffix) && strncmp(token.str + base_len, cmd_suffix, left_chars) == 0); } Parser::Parser(const Full* F) : F_(F), ep_(F) { } Parser::~Parser() { } Token Parser::read_expr(Lexer& lex, ExpressionParser::ParseMode mode) { Token t; t.type = kTokenExpr; t.str = lex.pchar(); ep_.clear_vm(); assert(!st_.datasets.empty()); int ds = st_.datasets[0]; ep_.parse_expr(lex, ds, NULL, NULL, mode); t.length = lex.pchar() - t.str; t.value.d = 0.; return t; } Token Parser::read_and_calc_expr(Lexer& lex) { Token t = read_expr(lex); int ds = st_.datasets[0]; const vector& points = F_->dk.data(ds)->points(); t.value.d = ep_.calculate(0, points); return t; } Token Parser::read_var(Lexer& lex) { Token t; t.type = kTokenEVar; t.str = lex.pchar(); int ds = st_.datasets[0]; ep_.clear_vm(); ep_.parse_expr(lex, ds, NULL, NULL, ExpressionParser::kAstMode); t.value.i = st_.vdlist.size(); st_.vdlist.push_back(ep_.vm()); t.length = lex.pchar() - t.str; return t; } // see the command above Token Parser::read_define_arg(Lexer& lex, const vector& allowed_names, vector *new_names) { Token t; t.type = kTokenExpr; t.str = lex.pchar(); ep_.clear_vm(); ep_.parse_expr(lex, -1, &allowed_names, new_names); t.length = lex.pchar() - t.str; t.value.d = 0.; return t; } // [ '[' [Number] ':' [Number] ']' ] // appends two tokens (kTokenExpr/kTokenNop) to args void Parser::parse_real_range(Lexer& lex, vector& args) { if (lex.peek_token().type == kTokenLSquare) { lex.get_token(); // discard '[' const Token& t = lex.peek_token(); if (t.type == kTokenColon) { args.push_back(nop()); lex.get_token(); // discard ':' } else if (t.type == kTokenRSquare) { // omitted ':', never mind args.push_back(nop()); } else { args.push_back(read_and_calc_expr(lex)); lex.get_expected_token(kTokenColon); // discard ':' } const Token& r = lex.peek_token(); if (r.type == kTokenRSquare) { lex.get_token(); // discard ']' args.push_back(nop()); } else { args.push_back(read_and_calc_expr(lex)); lex.get_expected_token(kTokenRSquare); // discard ']' } } else { args.push_back(nop()); args.push_back(nop()); // we always append two tokens in this function } } // %funcname | [@n.]('F'|'Z') '[' Number ']' // returns: 1 token: Funcname // or 2/3 tokens: Dataset|Nop, "F"|"Z", [expr] void Parser::parse_func_id(Lexer& lex, vector& args, bool accept_fz) { Token t = lex.get_token(); if (t.type == kTokenFuncname) { args.push_back(t); return; } if (t.type == kTokenDataset) { args.push_back(t); lex.get_expected_token(kTokenDot); // discard '.' t = lex.get_token(); } else args.push_back(nop()); if (t.as_string() != "F" && t.as_string() != "Z") lex.throw_syntax_error("expected %function ID"); args.push_back(t); if (accept_fz && lex.peek_token().type != kTokenLSquare) { args.push_back(nop()); return; } lex.get_expected_token(kTokenLSquare); // discard '[' args.push_back(read_and_calc_expr(lex)); lex.get_expected_token(kTokenRSquare); // discard ']' } void Parser::parse_set_args(Lexer& lex, vector& args) { do { Token key = lex.get_expected_token(kTokenLname); lex.get_expected_token(kTokenAssign); // discard '=' SettingsMgr::ValueType t = F_->settings_mgr()->get_value_type(key.as_string()); // exit_on_warning is unused since v. 1.1.1 if (t == SettingsMgr::kNotFound && key.as_string() != "exit_on_warning") lex.throw_syntax_error("no such option: " + key.as_string()); Token value; if (t == SettingsMgr::kString) value = lex.get_expected_token(kTokenString); else if (t == SettingsMgr::kEnum) value = lex.get_expected_token(kTokenLname); else value = read_and_calc_expr(lex); args.push_back(key); args.push_back(value); } while (lex.discard_token_if(kTokenComma)); } class ArgReader { public: ArgReader(Lexer& lex) : lex_(lex) { lex_.get_expected_token(kTokenOpen); flag_ = (lex.get_token_if(kTokenClose).type == kTokenClose ? 0 : 1); } bool next_arg() { if (flag_ == 0) // no args return false; else if (flag_ == 1) { // at the beginning flag_ = 2; return true; } else // now either ',' or ')' return (lex_.get_expected_token(kTokenComma, kTokenClose).type == kTokenComma); } private: Lexer& lex_; int flag_; }; // FuncType "(" [ArgExpr % ","] ")" void Parser::parse_component(Lexer& lex, const vector& lhs_vars, Tplate::Component* c) { Token name = lex.get_expected_token(kTokenCname); c->p = F_->get_tpm()->get_shared_tp(name.as_string()); c->cargs.clear(); ArgReader ar(lex); while (ar.next_arg()) { read_define_arg(lex, lhs_vars, NULL); c->cargs.push_back(ep_.vm()); } if (c->p && c->cargs.size() != c->p->fargs.size()) lex.throw_syntax_error("function " + c->p->name + " should have " + S(c->p->fargs.size()) + " parameters (not " + S(c->cargs.size()) + ")"); } string Parser::read_define_rhs_with_custom_func(Lexer& lex, const Tplate *tp) { vector extra_names; string rhs = read_define_arg(lex, tp->fargs, &extra_names).as_string(); if (lex.peek_token().as_string() == "where") { lex.get_token(); // discard "where" do { string name = lex.get_expected_token(kTokenLname).as_string(); lex.get_expected_token(kTokenAssign); // discard '=' int idx = index_of_element(extra_names, name); if (idx == -1) lex.throw_syntax_error("unused substitution: " + name); extra_names.erase(extra_names.begin() + idx); Token s = read_define_arg(lex, tp->fargs, &extra_names); replace_words(rhs, name, "("+s.as_string()+")"); } while (lex.discard_token_if(kTokenComma)); } v_foreach (string, i, extra_names) { if (*i != "x") lex.throw_syntax_error("unknown argument: " + *i); } return rhs; } void Parser::parse_define_rhs(Lexer& lex, Tplate *tp) { Token t = lex.get_token(); // CompoundFunction, RHS: Component % "+" if (t.type == kTokenCname) { lex.go_back(t); do { Tplate::Component c; parse_component(lex, tp->fargs, &c); tp->components.push_back(c); } while (lex.discard_token_if(kTokenPlus)); tp->create = &create_CompoundFunction; } // SplitFunction, RHS: "x" "<" Arg ? Component : Component else if (t.as_string() == "x" && lex.discard_token_if(kTokenLT)) { tp->components.resize(3); read_define_arg(lex, tp->fargs, NULL); tp->components[0].cargs.push_back(ep_.vm()); lex.get_expected_token(kTokenQMark); // discard '?' parse_component(lex, tp->fargs, &tp->components[1]); lex.get_expected_token(kTokenColon); // discard ':' parse_component(lex, tp->fargs, &tp->components[2]); tp->create = &create_SplitFunction; } // CustomFunction else { lex.go_back(t); string rhs = read_define_rhs_with_custom_func(lex, tp); Lexer lex2(rhs.c_str()); ExpressionParser ep(NULL); ep.parse_expr(lex2, -1, &tp->fargs, NULL, ExpressionParser::kAstMode); tp->op_trees = prepare_ast_with_der(ep.vm(), tp->fargs.size() + 1); tp->create = &create_CustomFunction; } } // Tplate Tplate::Ptr Parser::parse_define_args(Lexer& lex) { boost::shared_ptr tp(new Tplate); // FuncType tp->name = lex.get_expected_token(kTokenCname).as_string(); tp->docs_fragment = NULL; // '(' [(arg_name ['=' default_value]) % ','] ')' ArgReader arg_reader(lex); const vector empty; vector new_vars; while (arg_reader.next_arg()) { string name = lex.get_expected_token(kTokenLname).as_string(); if (name == "x") { if (lex.peek_token().type == kTokenAssign) lex.throw_syntax_error("do not use x at left-hand side."); continue; // ignore this "x" } tp->fargs.push_back(name); string default_value; if (lex.discard_token_if(kTokenAssign)) { Token dv = read_define_arg(lex, empty, &new_vars); if (lex.peek_token().type == kTokenLSquare) { vector dummy_args; parse_real_range(lex, dummy_args); dv.length = lex.pchar() - dv.str; } default_value = dv.as_string(); } else { new_vars.push_back(name); } tp->defvals.push_back(default_value); } tp->traits = 0; v_foreach (string, i, new_vars) if (contains_element(Guess::linear_traits, *i)) { tp->traits |= Tplate::kLinear; break; } v_foreach (string, i, new_vars) if (contains_element(Guess::peak_traits, *i)) { tp->traits |= Tplate::kPeak; break; } v_foreach (string, i, new_vars) if (contains_element(Guess::sigmoid_traits, *i)) { tp->traits |= Tplate::kSigmoid; break; } // '=' lex.get_expected_token(kTokenAssign); // discard '=' const char* start_rhs = lex.pchar(); while (isspace(*start_rhs)) ++start_rhs; parse_define_rhs(lex, tp.get()); tp->rhs = string(start_rhs, lex.pchar()); return tp; } static void parse_ui_args(Lexer& lex, vector& args) { Token key = lex.get_expected_token(kTokenLname); lex.get_expected_token(kTokenAssign); // discard '=' Token value = lex.get_rest_of_cmd(); args.push_back(key); args.push_back(value); } static void parse_undefine_args(Lexer& lex, vector& args) { do { args.push_back(lex.get_expected_token(kTokenCname)); } while (lex.discard_token_if(kTokenComma)); } static void parse_delete_args(Lexer& lex, vector& args) { do { // allow "delete %pd*" or %* or $foo* or $*. Token t = lex.get_glob_token(); if (t.type == kTokenDataset || // @n t.type == kTokenFuncname || // %func t.type == kTokenVarname) // $var args.push_back(t); else if (t.type == kTokenLname && t.as_string() == "file") args.push_back(lex.get_word_token()); else lex.throw_syntax_error("unexpected arg after `delete'"); } while (lex.discard_token_if(kTokenComma)); } static void parse_exec_args(Lexer& lex, vector& args) { if (lex.discard_token_if(kTokenBang)) args.push_back(lex.get_rest_of_line()); else if (lex.peek_token().type == kTokenAssign) { args.push_back(lex.get_token()); args.push_back(lex.get_rest_of_line()); } else args.push_back(lex.get_word_token()); } void Parser::parse_fit_args(Lexer& lex, vector& args) { Token t = lex.get_token(); if (t.type == kTokenLname) { string name = t.as_string(); if (name == "undo" || name == "redo" || name == "clear_history") { args.push_back(t); } else if (name == "history") { args.push_back(t); args.push_back(read_and_calc_expr(lex)); } else lex.throw_syntax_error("unexpected name after `fit'"); } // [n_iter] @n* else if (t.type == kTokenNumber || t.type == kTokenDataset) { args.push_back(t); while (lex.peek_token().type == kTokenDataset) args.push_back(lex.get_token()); } else // no args lex.go_back(t); } // [Funcname '='] Uname ['(' kwarg % ',' ')'] [range] void Parser::parse_guess_args(Lexer& lex, vector& args) { Token t = lex.get_expected_token(kTokenCname, kTokenFuncname); if (t.type == kTokenFuncname) { args.push_back(t); lex.get_expected_token(kTokenAssign); // discard '=' t = lex.get_expected_token(kTokenCname); } else args.push_back(nop()); args.push_back(t); if (lex.peek_token().type == kTokenOpen) { lex.get_expected_token(kTokenOpen); Token t2 = lex.get_token_if(kTokenClose); while (t2.type != kTokenClose) { args.push_back(lex.get_expected_token(kTokenLname)); lex.get_expected_token(kTokenAssign); // discard '=' args.push_back(read_var(lex)); t2 = lex.get_expected_token(kTokenComma, kTokenClose); } } parse_real_range(lex, args); } static void parse_redir(Lexer& lex, vector& args) { if (lex.peek_token().type == kTokenGT || lex.peek_token().type == kTokenAppend) { args.push_back(lex.get_token()); Token f = lex.get_word_token(); if (f.type == kTokenNop) lex.throw_syntax_error("expected filename"); args.push_back(f); } } void Parser::parse_info_args(Lexer& lex, vector& args) { if (lex.peek_token().type == kTokenNop) // no args return; parse_one_info_arg(lex, args); while (lex.discard_token_if(kTokenComma)) parse_one_info_arg(lex, args); parse_redir(lex, args); } void Parser::parse_one_info_arg(Lexer& lex, vector& args) { Token token = lex.get_glob_token(); if (token.type == kTokenLname) { string word = token.as_string(); const char** pos = info_args; while (*pos != NULL && *pos != word) ++pos; if (*pos == NULL) lex.throw_syntax_error("Unknown info argument: " + word); args.push_back(token); if (word == "set") { if (lex.peek_token().type == kTokenLname) args.push_back(lex.get_token()); else args.push_back(nop()); } else if (word == "history" || word == "guess") { parse_real_range(lex, args); } else if (word == "fit" || word == "errors" || word == "cov") { while (lex.peek_token().type == kTokenDataset) args.push_back(lex.get_token()); args.push_back(nop()); // separator } else if (word == "confidence") { while (lex.peek_token().type == kTokenNop) lex.throw_syntax_error("specify level, e.g. confidence 95"); args.push_back(lex.get_expected_token(kTokenNumber)); while (lex.peek_token().type == kTokenDataset) args.push_back(lex.get_token()); args.push_back(nop()); // separator } else if (word == "refs") { args.push_back(lex.get_expected_token(kTokenVarname)); } else if (word == "prop") { args.push_back(lex.get_expected_token(kTokenFuncname)); } } else if (token.type == kTokenCname || token.type == kTokenFuncname || token.type == kTokenVarname) { args.push_back(token); } // handle [@n.]F/Z['['expr']'] else if ((token.type == kTokenUletter && (*token.str == 'F' || *token.str == 'Z')) || token.type == kTokenDataset) { args.push_back(token); if (token.type == kTokenDataset) { lex.get_expected_token(kTokenDot); // discard '.' args.push_back(lex.get_expected_token("F", "Z")); } if (lex.peek_token().type == kTokenLSquare) { lex.get_token(); // discard '[' args.push_back(read_and_calc_expr(lex)); lex.get_expected_token(kTokenRSquare); // discard ']' } } else lex.throw_syntax_error("Unknown info argument: " + token.as_string()); } void Parser::parse_print_args(Lexer& lex, vector& args) { // the first arg means: // ':' -> "all ":" // expr -> "if" expr ":" // nop -> execute once bool once = true; if (lex.peek_token().as_string() == "all") { lex.get_token(); // discard "all" // mark "all" args.push_back(lex.get_expected_token(kTokenColon)); once = false; } else if (lex.peek_token().as_string() == "if") { lex.get_token(); // discard "if" args.push_back(read_expr(lex)); lex.get_expected_token(kTokenColon); // discard ':' once = false; } else args.push_back(nop()); do { if (lex.peek_token().type == kTokenString) args.push_back(lex.get_token()); else if (lex.peek_token().as_string() == "filename" || lex.peek_token().as_string() == "title") args.push_back(lex.get_token()); else { Token t = once ? read_and_calc_expr(lex) : read_expr(lex); args.push_back(t); } } while (lex.discard_token_if(kTokenComma)); parse_redir(lex, args); } CommandType Parser::parse_xysa_args(Lexer& lex, vector& args) { Token t = lex.get_expected_token(kTokenAssign, kTokenLSquare); // X = if (t.type == kTokenAssign) { for (;;) { args.push_back(read_expr(lex)); if (!lex.discard_token_if(kTokenComma)) break; Token a = lex.get_expected_token(kTokenUletter); char d = *a.str; if (d != 'X' && d != 'Y' && d != 'S' && d != 'A') lex.throw_syntax_error("unexpected letter"); args.push_back(a); lex.get_expected_token(kTokenAssign); // discard '=' } return kCmdAllPointsTr; } // X [expr] = else { for (;;) { args.push_back(read_and_calc_expr(lex)); lex.get_expected_token(kTokenRSquare); // discard ']' lex.get_expected_token(kTokenAssign); // discard '=' args.push_back(read_and_calc_expr(lex)); if (!lex.discard_token_if(kTokenComma)) break; Token a = lex.get_expected_token(kTokenUletter); char d = *a.str; if (d != 'X' && d != 'Y' && d != 'S' && d != 'A') lex.throw_syntax_error("unexpected letter"); args.push_back(a); lex.get_expected_token(kTokenLSquare); // discard '[' } return kCmdPointTr; } } void Parser::parse_assign_var(Lexer& lex, vector& args) { if (lex.peek_token().as_string() == "copy") { args.push_back(lex.get_token()); // "copy" lex.get_expected_token(kTokenOpen); // discard '(' if (lex.peek_token().type == kTokenVarname) { args.push_back(lex.get_token()); // $orig } else { parse_func_id(lex, args, false); lex.get_expected_token(kTokenDot); // discard '.' args.push_back(lex.get_expected_token(kTokenLname)); } lex.get_expected_token(kTokenClose); // discard ')' } else { args.push_back(read_var(lex)); } } void Parser::parse_assign_func(Lexer& lex, vector& args) { Token f = lex.get_expected_token(kTokenCname, "copy"); if (f.type == kTokenCname) { // Uname '(' ([Lname '='] v_expr) % ',' ')' args.push_back(f); bool has_kwarg = false; ArgReader arg_reader(lex); while (arg_reader.next_arg()) { Token t = lex.get_token(); if (lex.discard_token_if(kTokenAssign)) { if (t.type != kTokenLname) lex.throw_syntax_error("wrong token before '='"); args.push_back(t); has_kwarg = true; } else { if (has_kwarg) lex.throw_syntax_error("non-keyword arg after keyword arg"); args.push_back(nop()); lex.go_back(t); } args.push_back(read_var(lex)); } } else { // "copy" '(' func_id ')' args.push_back(f); // "copy" lex.get_expected_token(kTokenOpen); // discard '(' parse_func_id(lex, args, false); lex.get_expected_token(kTokenClose); // discard ')' } } void Parser::parse_fz(Lexer& lex, Command &cmd) { Token t = lex.get_token(); // F=..., F+=... // ('='|'+=') (0 | %f | Type(...) | copy(%f) | F | copy(F)) % '+' if (t.type == kTokenAssign || t.type == kTokenAddAssign) { cmd.type = kCmdChangeModel; cmd.args.push_back(t); for (;;) { const Token& p = lex.peek_token(); if (p.type == kTokenCname) { // Type(...) parse_assign_func(lex, cmd.args); } else if (p.as_string() == "0") { // 0 cmd.args.push_back(lex.get_token()); } else if (p.as_string() == "copy") { cmd.args.push_back(lex.get_token()); // "copy" lex.get_expected_token(kTokenOpen); // discard '(' parse_func_id(lex, cmd.args, true); lex.get_expected_token(kTokenClose); // discard ')' } else parse_func_id(lex, cmd.args, true); if (lex.peek_token().type == kTokenPlus) cmd.args.push_back(lex.get_token()); // '+' else break; } } // F.param= ... else if (t.type == kTokenDot) { lex.throw_syntax_error("Illegal syntax, did you mean F[*].par= ?"); } // F[Number]... else if (t.type == kTokenLSquare) { Token tok_idx; if (lex.peek_token().type == kTokenMult) // F[*] tok_idx = lex.get_token(); else // F[expr] tok_idx = read_and_calc_expr(lex); cmd.args.push_back(tok_idx); lex.get_expected_token(kTokenRSquare); // discard ']' Token k = lex.get_expected_token(kTokenAssign, kTokenDot); if (k.type == kTokenAssign) { // F[Number]=... if (tok_idx.type == kTokenMult) lex.throw_syntax_error("Illegal syntax F[*]=..."); cmd.type = kCmdChangeModel; if (lex.peek_token().type == kTokenFuncname) // ...=%func cmd.args.push_back(lex.get_token()); else // ...=Func(...) parse_assign_func(lex, cmd.args); } else { // F[Number].param=... cmd.type = kCmdAssignParam; cmd.args.push_back(lex.get_expected_token(kTokenLname)); lex.get_expected_token(kTokenAssign); // discard '=' cmd.args.push_back(read_var(lex)); } } else lex.throw_syntax_error("unexpected token after F/Z"); } static void add_to_datasets(const Full* F_, vector& datasets, int n) { if (n == Lexer::kAll) for (int j = 0; j != F_->dk.count(); ++j) datasets.push_back(j); else datasets.push_back(n); } bool Parser::parse_statement(Lexer& lex) { st_.datasets.clear(); st_.with_args.clear(); st_.vdlist.clear(); st_.commands.resize(1); st_.commands[0].args.clear(); st_.commands[0].defined_tp.reset(); Token first = lex.peek_token(); if (first.type == kTokenNop) return false; if (first.type == kTokenDataset) { lex.get_token(); Token t = lex.get_token(); if (t.type == kTokenDataset || t.type == kTokenColon) { add_to_datasets(F_, st_.datasets, first.value.i); while (t.type == kTokenDataset) { add_to_datasets(F_, st_.datasets, t.value.i); t = lex.get_expected_token(kTokenDataset, kTokenColon); } } else { lex.go_back(first); } } if (st_.datasets.empty()) st_.datasets.push_back(F_->dk.default_idx()); if (lex.peek_token().type == kTokenLname && is_command(lex.peek_token(), "w","ith")) { lex.get_token(); // discard "with" parse_set_args(lex, st_.with_args); } parse_command(lex, st_.commands[0]); // the check for Nop below is to allows ';' at the end of line while (lex.discard_token_if(kTokenSemicolon) && lex.peek_token().type != kTokenNop) { st_.commands.resize(st_.commands.size() + 1); parse_command(lex, st_.commands.back()); } if (lex.peek_token().type != kTokenNop) lex.throw_syntax_error(S("unexpected token: `") + tokentype2str(lex.peek_token().type) + "'"); return true; } void Parser::parse_command(Lexer& lex, Command& cmd) { cmd.type = kCmdNull; // initial value, will be changed const Token token = lex.get_token(); if (token.type == kTokenLname) { if (is_command(token, "deb","ug")) { cmd.type = kCmdDebug; cmd.args.push_back(lex.get_token()); cmd.args.push_back(lex.get_rest_of_line()); } else if (is_command(token, "def","ine")) { cmd.type = kCmdDefine; cmd.defined_tp = parse_define_args(lex); } else if (is_command(token, "del","ete")) { if (lex.peek_token().type == kTokenOpen) { cmd.type = kCmdDeleteP; lex.get_expected_token(kTokenOpen); // discard '(' cmd.args.push_back(read_expr(lex)); lex.get_expected_token(kTokenClose); // discard ')' } else { cmd.type = kCmdDelete; parse_delete_args(lex, cmd.args); } } else if (is_command(token, "e","xecute")) { cmd.type = kCmdExec; parse_exec_args(lex, cmd.args); } else if (is_command(token, "f","it")) { cmd.type = kCmdFit; parse_fit_args(lex, cmd.args); } else if (is_command(token, "g","uess")) { cmd.type = kCmdGuess; parse_guess_args(lex, cmd.args); } else if (is_command(token, "i","nfo")) { cmd.type = kCmdInfo; parse_info_args(lex, cmd.args); } else if (is_command(token, "l","ua")) { cmd.type = kCmdLua; cmd.args.push_back(lex.get_rest_of_line()); } else if (is_command(token, "pl","ot")) { cmd.type = kCmdPlot; parse_real_range(lex, cmd.args); parse_real_range(lex, cmd.args); while (lex.peek_token().type == kTokenDataset) cmd.args.push_back(lex.get_token()); parse_redir(lex, cmd.args); } else if (is_command(token, "p","rint")) { cmd.type = kCmdPrint; parse_print_args(lex, cmd.args); } else if (is_command(token, "quit","")) { cmd.type = kCmdQuit; // no args } // "s" starts either kCmdSet or kCmdAllPointsTr("s=...") // or kCmdPointTr("s[...]=...") else if (is_command(token, "s","et") && !(token.length == 1 && (lex.peek_token().type == kTokenAssign || lex.peek_token().type == kTokenLSquare))) { cmd.type = kCmdSet; parse_set_args(lex, cmd.args); } else if (is_command(token, "ui","")) { cmd.type = kCmdUi; parse_ui_args(lex, cmd.args); } else if (is_command(token, "undef","ine")) { cmd.type = kCmdUndef; parse_undefine_args(lex, cmd.args); } else if (is_command(token, "reset","")) { cmd.type = kCmdReset; // no args } else if (is_command(token, "sleep","")) { cmd.type = kCmdSleep; Token value = read_and_calc_expr(lex); cmd.args.push_back(value); } else if (is_command(token, "title","")) { // [@n:] "title" '=' cmd.type = kCmdTitle; lex.get_expected_token(kTokenAssign); // discard '=' cmd.args.push_back(lex.get_word_token()); } else if (is_command(token, "use","")) { cmd.type = kCmdUse; cmd.args.push_back(lex.get_expected_token(kTokenDataset)); } else if (token.length == 1 && (*token.str == 'x' || *token.str == 'y' || *token.str == 's' || *token.str == 'a')) { cmd.args.push_back(token); cmd.type = parse_xysa_args(lex, cmd.args); } } else if (token.type == kTokenUletter) { const char c = *token.str; if (c == 'F' || c == 'Z') { cmd.args.push_back(nop()); // dataset cmd.args.push_back(token); // F/Z parse_fz(lex, cmd); } else if (c == 'M') { cmd.type = kCmdResizeP; lex.get_expected_token(kTokenAssign); cmd.args.push_back(read_and_calc_expr(lex)); } else if (c == 'X' || c == 'Y' || c == 'S' || c == 'A') { cmd.args.push_back(token); cmd.type = parse_xysa_args(lex, cmd.args); } else lex.throw_syntax_error("unknown name: " + token.as_string()); } else if (token.type == kTokenAssign) { cmd.type = kCmdLua; cmd.args.push_back(token); cmd.args.push_back(lex.get_rest_of_line()); } else if (token.type == kTokenBang) { cmd.type = kCmdShell; cmd.args.push_back(lex.get_rest_of_line()); } // $var=... else if (token.type == kTokenVarname && lex.peek_token().type == kTokenAssign) { if (token.str[1] == '*') lex.throw_syntax_error("$* cannot be assigned"); cmd.type = kCmdNameVar; cmd.args.push_back(token); lex.get_token(); // discard '=' parse_assign_var(lex, cmd.args); } // %func=... else if (token.type == kTokenFuncname && lex.peek_token().type == kTokenAssign) { if (token.str[1] == '*') lex.throw_syntax_error("%* cannot be assigned"); cmd.type = kCmdNameFunc; cmd.args.push_back(token); lex.get_token(); // discard '=' parse_assign_func(lex, cmd.args); } // %func.param=... else if (token.type == kTokenFuncname && lex.peek_token().type == kTokenDot) { cmd.type = kCmdAssignParam; if (token.str[1] == '*') { cmd.args.push_back(nop()); // see Runner::command_assign_all() cmd.args.push_back(nop()); } cmd.args.push_back(token); lex.get_token(); // discard '.' cmd.args.push_back(lex.get_expected_token(kTokenLname)); lex.get_expected_token(kTokenAssign); // discard '=' cmd.args.push_back(read_var(lex)); } else if (token.type == kTokenDataset && lex.peek_token().type == kTokenDot) { cmd.args.push_back(token); // dataset lex.get_token(); // discard '.' string arg = lex.peek_token().as_string(); if (arg == "F" || arg == "Z") { cmd.args.push_back(lex.get_token()); // F/Z parse_fz(lex, cmd); } else lex.throw_syntax_error("@n. must be followed by F or Z"); } else if (token.type == kTokenDataset && lex.peek_token().type == kTokenLT) { cmd.type = kCmdLoad; cmd.args.push_back(token); lex.get_token(); // discard '<' cmd.args.push_back(lex.get_word_token()); // Normally columns are parsed as a part of filename ('foo.xy:1:2::'), // which is weird, so let's handle also separated 'foo.xy' :1:2:3::. if (lex.peek_token().type == kTokenColon) { cmd.args.push_back(lex.get_word_token()); string cols = Lexer::get_string(cmd.args.back()); if (std::count(cols.begin(), cols.end(), ':') != 4) lex.throw_syntax_error("4 colons required in column spec"); } while (lex.peek_token().type == kTokenLname) cmd.args.push_back(lex.get_token()); } else if (token.type == kTokenDataset && lex.peek_token().type == kTokenAssign) { cmd.type = kCmdDatasetTr; cmd.args.push_back(token); lex.get_token(); // discard '=' cmd.args.push_back(read_expr(lex, ExpressionParser::kDatasetTrMode)); } if (cmd.type == kCmdNull) lex.throw_syntax_error("unexpected token at command beginning"); } bool Parser::check_syntax(const string& str) { try { Lexer lex(str.c_str()); parse_statement(lex); } catch (ExecuteError&) { return false; } catch (SyntaxError&) { // SyntaxError is thrown when resolving %functions and $variables // (in ExpressionParser) fails. return false; } return true; } string Parser::get_statements_repr() const { string r = "datasets: " + join_vector(st_.datasets, " "); if (!st_.with_args.empty()) { r += "\nWith:"; v_foreach (Token, i, st_.with_args) r += "\n\t" + token2str(*i); } v_foreach (Command, i, st_.commands) { r += S("\n") + commandtype2str(i->type); v_foreach (Token, j, i->args) r += "\n\t" + token2str(*j); } return r; } } // namespace fityk fityk-1.3.1/fityk/cparser.h000066400000000000000000000065121302634723100156050ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ /// Command parser. #ifndef FITYK_CPARSER_H_ #define FITYK_CPARSER_H_ #include #include "lexer.h" #include "eparser.h" #include "tplate.h" namespace fityk { enum CommandType { kCmdDebug, kCmdDefine, kCmdDelete, kCmdDeleteP, kCmdExec, kCmdFit, kCmdGuess, kCmdInfo, kCmdLua, kCmdPlot, kCmdPrint, kCmdQuit, kCmdReset, kCmdSet, kCmdSleep, kCmdTitle, kCmdUi, kCmdUndef, kCmdUse, kCmdShell, kCmdLoad, kCmdDatasetTr, kCmdNameFunc, kCmdNameVar, kCmdAssignParam, kCmdChangeModel, kCmdPointTr, kCmdAllPointsTr, kCmdResizeP, kCmdNull }; struct Command { CommandType type; std::vector args; Tplate::Ptr defined_tp; // used to parse the "define" command }; struct Statement { std::vector datasets; std::vector with_args; std::vector commands; std::vector vdlist; }; // NULL-terminated tables, used for tab-expansion. extern const char* command_list[]; extern const char* info_args[]; extern const char* debug_args[]; const char* commandtype2str(CommandType c); class FITYK_API Parser { public: Parser(const Full* F); ~Parser(); // Parses statement. Throws SyntaxError. // Returns false if no tokens are left. bool parse_statement(Lexer& lex); Statement& statement() { return st_; } // Returns true on success. bool check_syntax(const std::string& str); // for debugging only std::string get_statements_repr() const; // these functions are used to parse command fragments from outside void parse_info_args(Lexer& lex, std::vector& args); void parse_print_args(Lexer& lex, std::vector& args); void parse_define_rhs(Lexer& lex, Tplate *tp); std::string read_define_rhs_with_custom_func(Lexer& lex, const Tplate *tp); Tplate::Ptr parse_define_args(Lexer& lex); private: const Full* F_; ExpressionParser ep_; Statement st_; Token read_expr(Lexer& lex, ExpressionParser::ParseMode mode=ExpressionParser::kNormalMode); Token read_and_calc_expr(Lexer& lex); Token read_var(Lexer& lex); Token read_define_arg(Lexer& lex, const std::vector& allowed_names, std::vector *new_names); Token read_default_value(Lexer& lex); void parse_fz(Lexer& lex, Command &cmd); void parse_assign_var(Lexer& lex, std::vector& args); void parse_assign_func(Lexer& lex, std::vector& args); void parse_command(Lexer& lex, Command& cmd); void parse_component(Lexer& lex, const std::vector& lhs_vars, Tplate::Component* c); void parse_set_args(Lexer& lex, std::vector& args); CommandType parse_xysa_args(Lexer& lex, std::vector& args); void parse_real_range(Lexer& lex, std::vector& args); void parse_func_id(Lexer& lex, std::vector& args, bool accept_fz); void parse_guess_args(Lexer& lex, std::vector& args); void parse_one_info_arg(Lexer& lex, std::vector& args); void parse_fit_args(Lexer& lex, std::vector& args); }; } // namespace fityk #endif //FITYK_CPARSER_H_ fityk-1.3.1/fityk/data.cpp000066400000000000000000000344221302634723100154130ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "data.h" #include "common.h" #include "ui.h" #include "numfuncs.h" #include "settings.h" #include "logic.h" #include "model.h" #include #include #include #include #include #include using std::string; using std::vector; #if XYLIB_VERSION < 10500 typedef shared_ptr dataset_shared_ptr; #endif namespace fityk { // filename utils string get_file_basename(const string& path) { string::size_type last_sep = path.rfind(PATH_COMPONENT_SEP); string::size_type last_dot = path.rfind('.'); size_t basename_begin = (last_sep == string::npos ? 0 : last_sep + 1); if (last_dot != string::npos && last_dot > basename_begin) return string(path, basename_begin, last_dot-basename_begin); else return string(path, basename_begin); } Data::Data(BasicContext* ctx, Model *model) : ctx_(ctx), model_(model), x_step_(0.), has_sigma_(false), xps_source_energy_(0.) { } Data::~Data() { model_->destroy(); } string Data::get_info() const { string s; if (p_.empty()) s = "No data points."; else s = S(p_.size()) + " points, " + S(active_.size()) + " active."; if (!spec_.path.empty()) s += "\nFilename: " + spec_.path; if (spec_.x_col != LoadSpec::NN || spec_.y_col != LoadSpec::NN || spec_.sig_col != LoadSpec::NN) s += "\nColumns: " + (spec_.x_col != LoadSpec::NN ? S(spec_.x_col) : S("_")) + ", " + (spec_.y_col != LoadSpec::NN ? S(spec_.y_col) : S("_")); if (spec_.sig_col != LoadSpec::NN) s += ", " + S(spec_.sig_col); if (!title_.empty()) s += "\nData title: " + title_; if (active_.size() != p_.size()) s += "\nActive data range: " + range_as_string(); return s; } // does not clear model void Data::clear() { spec_ = LoadSpec(); title_ = ""; p_.clear(); x_step_ = 0; active_.clear(); has_sigma_ = false; xps_source_energy_ = 0.; } bool Data::completely_empty() const { return is_empty() && get_title().empty() && model()->get_ff().empty() && model()->get_zz().empty(); } void Data::post_load() { if (p_.empty()) return; string inf = S(p_.size()) + " points."; if (!has_sigma_) { string dds = ctx_->get_settings()->default_sigma; if (dds == "sqrt") { for (vector::iterator i = p_.begin(); i < p_.end(); ++i) i->sigma = i->y > 1. ? sqrt (i->y) : 1.; inf += " No explicit std. dev. Set as sqrt(y)"; } else if (dds == "one") { for (vector::iterator i = p_.begin(); i < p_.end(); ++i) i->sigma = 1.; inf += " No explicit std. dev. Set as equal 1."; } else assert(0); } ctx_->msg(inf); update_active_p(); } int Data::load_arrays(const vector &x, const vector &y, const vector &sigma, const string &title) { assert(x.size() == y.size()); assert(sigma.empty() || sigma.size() == y.size()); clear(); title_ = title; p_.resize(y.size()); if (sigma.empty()) for (size_t i = 0; i != y.size(); ++i) p_[i] = Point(x[i], y[i]); else { for (size_t i = 0; i != y.size(); ++i) p_[i] = Point(x[i], y[i], sigma[i]); has_sigma_ = true; } sort_points(); find_step(); post_load(); return p_.size(); } void Data::set_points(const vector &p) { p_ = p; sort_points(); after_transform(); } void Data::revert() { if (spec_.path.empty()) throw ExecuteError("Dataset can't be reverted, it was not loaded " "from file"); string old_title = title_; LoadSpec old_spec = spec_; // this->spec_ should not be passed by ref to load_file() // because path is cleared before being used load_file(old_spec); title_ = old_title; } /* void Data::load_data_sum(const vector& dd, const string& op) { if (dd.empty()) { clear(); return; } // dd can contain this, we can't change p_ or title in-place. string new_filename = dd.size() == 1 ? dd[0]->get_filename() : ""; vector new_p; string new_title; v_foreach (const Data*, i, dd) { new_title += (i == dd.begin() ? "" : " + ") + (*i)->get_title(); new_p.insert(new_p.end(), (*i)->points().begin(), (*i)->points().end()); } sort(new_p.begin(), new_p.end()); if (!new_p.empty() && !op.empty()) apply_operation(new_p, op); // data should be sorted after apply_operation() clear(); title_ = new_title; spec_.path = new_filename; p_ = new_p; has_sigma_ = true; find_step(); post_load(); } */ void Data::add_one_point(realt x, realt y, realt sigma) { Point pt(x, y, sigma); vector::iterator pi = upper_bound(p_.begin(), p_.end(), pt); int idx = pi - p_.begin(); p_.insert(pi, pt); vector::iterator ai = lower_bound(active_.begin(), active_.end(), idx); for (vector::iterator i = ai; i != active_.end(); ++i) *i += 1; active_.insert(upper_bound(active_.begin(), active_.end(), idx), idx); // (fast) x_step_ update if (p_.size() < 2) x_step_ = 0.; else if (p_.size() == 2) x_step_ = p_[1].x - p_[0].x; else if (x_step_ != 0) { //TODO use tiny_relat_diff double max_diff = 1e-4 * fabs(x_step_); if (idx == 0 && fabs((p_[1].x - p_[0].x) - x_step_) < max_diff) ; //nothing, the same step else if (idx == size(p_) - 1 && fabs((p_[idx].x - p_[idx-1].x) - x_step_) < max_diff) ; //nothing, the same step else x_step_ = 0.; } } void Data::update_active_for_one_point(int idx) { vector::iterator a = lower_bound(active_.begin(), active_.end(), idx); bool present = (a < active_.end() && *a == idx); // this function is called only after switching the active flag assert(present != p_[idx].is_active); if (present) active_.erase(a); else active_.insert(a, idx); } // the same as replace_all(options, "_", "-") static string tr_opt(string options) { size_t pos = 0; while ((pos = options.find('_', pos)) != string::npos) { options[pos] = '-'; ++pos; } return options; } int Data::count_blocks(const string& filename, const string& format, const string& options) { try { dataset_shared_ptr xyds(xylib::cached_load_file(filename, format, tr_opt(options))); return xyds->get_block_count(); } catch (const std::runtime_error& e) { throw ExecuteError(e.what()); } } int Data::count_columns(const string& filename, const string& format, const string& options, int first_block) { try { dataset_shared_ptr xyds(xylib::cached_load_file(filename, format, tr_opt(options))); return xyds->get_block(first_block)->get_column_count(); } catch (const std::runtime_error& e) { throw ExecuteError(e.what()); } } void Data::verify_options(const xylib::DataSet* ds, const string& options) { std::string::size_type start_pos = options.find_first_not_of(" \t"); std::string::size_type pos = start_pos; while (pos != std::string::npos) { pos = options.find_first_of(" \t", start_pos); string word = options.substr(start_pos, pos-start_pos); // is_valid_option() is marked as const in since xylib 1.4 if (!const_cast(ds)->is_valid_option(word)) ctx_->ui()->warn("No such option for file type " + string(ds->fi->name) + ": " + word); start_pos = pos+1; } } void Data::load_file(const LoadSpec& spec) { if (spec.path.empty()) return; string block_name; try { string ds_options = tr_opt(spec.options); dataset_shared_ptr xyds( xylib::cached_load_file(spec.path, spec.format, ds_options)); verify_options(xyds.get(), ds_options); clear(); //removing previous file vector bb = spec.blocks.empty() ? vector1(0) : spec.blocks; v_foreach (int, b, bb) { assert(xyds); const xylib::Block* block = xyds->get_block(*b); const xylib::Column& xcol = block->get_column(spec.x_col != LoadSpec::NN ? spec.x_col : 1); const xylib::Column& ycol = block->get_column(spec.y_col != LoadSpec::NN ? spec.y_col : 2); int n = block->get_point_count(); if (n < 5 && bb.size() == 1) ctx_->ui()->warn("Only "+S(n)+" data points found in file."); p_.reserve(p_.size() + n); if (spec.sig_col == LoadSpec::NN) { for (int i = 0; i < n; ++i) { p_.push_back(Point(xcol.get_value(i), ycol.get_value(i))); } } else { const xylib::Column& scol = block->get_column(spec.sig_col); for (int i = 0; i < n; ++i) { p_.push_back(Point(xcol.get_value(i), ycol.get_value(i), scol.get_value(i))); } has_sigma_ = true; } if (xcol.get_step() != 0.) { // column has fixed step x_step_ = xcol.get_step(); if (x_step_ < 0) { reverse(p_.begin(), p_.end()); x_step_ = -x_step_; } } if (!ycol.get_name().empty()) { if (!block_name.empty()) block_name += "/"; block_name += ycol.get_name(); if (!xcol.get_name().empty()) block_name += "(" + xcol.get_name() + ")"; } else if (!block->get_name().empty()) { if (!block_name.empty()) block_name += "/"; block_name += block->get_name(); } if (block->meta.has_key("source energy")) { const string& energy = block->meta.get("source energy"); xps_source_energy_ = strtod(energy.c_str(), NULL); } } } catch (const std::runtime_error& e) { throw ExecuteError(e.what()); } if (!block_name.empty()) title_ = block_name; else { title_ = get_file_basename(spec.path); if (spec.x_col != LoadSpec::NN && spec.y_col != LoadSpec::NN) title_ += ":" + S(spec.x_col) + ":" + S(spec.y_col); } if (x_step_ == 0 || spec.blocks.size() > 1) { sort_points(); find_step(); } spec_ = spec; post_load(); } // std::is_sorted() is added C++0x template bool is_vector_sorted(const vector& v) { if (v.size() <= 1) return true; for (typename vector::const_iterator i = v.begin()+1; i != v.end(); ++i) if (*i < *(i-1)) return false; return true; } void Data::after_transform() { if (!is_vector_sorted(p_)) sort_points(); find_step(); update_active_p(); } void Data::update_active_p() // pre: p_.x sorted // post: active_ sorted { active_.clear(); active_.reserve(p_.size()); for (int i = 0; i < size(p_); i++) if (p_[i].is_active) active_.push_back(i); } //FIXME to remove it or to leave it? string Data::range_as_string() const { if (active_.empty()) { ctx_->ui()->warn("File not loaded or all points inactive."); return "[]"; } vector::const_iterator old_p = p_.begin() + active_[0]; double left = old_p->x; string s = "[" + S (left) + " : "; for (vector::const_iterator i = active_.begin() + 1; i != active_.end(); ++i) { if (p_.begin() + *i != old_p + 1) { double right = old_p->x; left = p_[*i].x; s += S(right) + "] + [" + S(left) + " : "; } old_p = p_.begin() + *i; } double right = old_p->x; s += S(right) + "]"; return s; } ///check for fixed step void Data::find_step() { const double tiny_relat_diff = 1e-4; size_t len = p_.size(); if (len < 2) { x_step_ = 0.; return; } else if (len == 2) { x_step_ = p_[1].x - p_[0].x; return; } // first check for definitely unequal step double s1 = p_[1].x - p_[0].x; double s2 = p_[len-1].x - p_[len-2].x; if (fabs(s2 - s1) > tiny_relat_diff * fabs(s2+s1)) { x_step_ = 0.; return; } double min_step, max_step, step; min_step = max_step = p_[1].x - p_[0].x; for (vector::iterator i = p_.begin() + 2; i < p_.end(); ++i) { step = i->x - (i-1)->x; min_step = std::min (min_step, step); max_step = std::max (max_step, step); } double avg = (max_step + min_step) / 2; if ((max_step - min_step) < tiny_relat_diff * fabs(avg)) x_step_ = avg; else x_step_ = 0.; } void Data::sort_points() { sort(p_.begin(), p_.end()); } std::pair Data::get_index_range(const RealRange& range) const { //pre: p_.x is sorted, active_ is sorted int p1 = lower_bound(p_.begin(), p_.end(), Point(range.lo,0)) - p_.begin(); int p2 = upper_bound(p_.begin(), p_.end(), Point(range.hi,0)) - p_.begin(); int a1 = lower_bound(active_.begin(), active_.end(), p1) - active_.begin(); int a2 = upper_bound(active_.begin(), active_.end(), p2) - active_.begin(); return std::make_pair(a1, a2); } vector::const_iterator Data::get_point_at(double x) const { return lower_bound (p_.begin(), p_.end(), Point(x,0)); } double Data::get_x_min() const { v_foreach (Point, i, p_) if (is_finite(i->x)) return i->x; return 0.; } double Data::get_x_max() const { if (p_.empty()) return 180.; for (vector::const_reverse_iterator i = p_.rbegin(); i != p_.rend(); ++i) if (is_finite(i->x)) return i->x; return 180.; } } // namespace fityk fityk-1.3.1/fityk/data.h000066400000000000000000000074411302634723100150610ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_DATA_H_ #define FITYK_DATA_H_ #include #include #include #include #include "common.h" #include "fityk.h" // struct Point, FITYK_API namespace xylib { class DataSet; } namespace fityk { class BasicContext; class Model; FITYK_API std::string get_file_basename(std::string const& path); /// dataset class FITYK_API Data { public : static int count_blocks(const std::string& filename, const std::string& format, const std::string& options); static int count_columns(const std::string& filename, const std::string& format, const std::string& options, int first_block); Data(BasicContext *ctx, Model *model); ~Data(); std::string get_info() const; void load_file(const LoadSpec& spec); int load_arrays(const std::vector& x, const std::vector& y, const std::vector& sigma, const std::string& title); //void load_data_sum(const std::vector& dd, // const std::string& op); void set_points(const std::vector& p); void clear(); void add_one_point(realt x, realt y, realt sigma); realt get_x(int n) const { return p_[active_[n]].x; } realt get_y(int n) const { return p_[active_[n]].y; } realt get_sigma (int n) const { return p_[active_[n]].sigma; } int get_n() const { return active_.size(); } std::vector get_xx() const; bool is_empty() const { return p_.empty(); } bool completely_empty() const; bool has_any_info() const; double get_x_step() const { return x_step_; } /// 0.0 if not fixed void after_transform(); // update x_step_, active_ std::string range_as_string() const; std::pair get_index_range(const RealRange& range) const; const std::string& get_title() const { return title_; } void set_title(const std::string& title) { title_ = title; } const std::string& get_filename() const { return spec_.path; } void find_step(); void sort_points(); // update active points bookkeeping void update_active_p(); // quick change in active points bookkeeping void update_active_for_one_point(int idx); void append_point() { size_t n = p_.size(); p_.resize(n+1); active_.push_back(n); } // return points at x (if any) or (usually) after it. std::vector::const_iterator get_point_at(double x) const; double get_x_min() const; double get_x_max() const; std::vector const& points() const { return p_; } std::vector& get_mutable_points() { return p_; } int get_given_x() const { return spec_.x_col; } int get_given_y() const { return spec_.y_col; } int get_given_s() const { return spec_.sig_col; } void revert(); Model* model() { return model_; } const Model* model() const { return model_; } double xps_source_energy() const { return xps_source_energy_; } private: const BasicContext* ctx_; Model* const model_; std::string title_; LoadSpec spec_; // given when loading file double x_step_; // 0.0 if not fixed; bool has_sigma_; std::vector p_; std::vector active_; double xps_source_energy_; void post_load(); void verify_options(const xylib::DataSet* ds, const std::string& options); DISALLOW_COPY_AND_ASSIGN(Data); }; inline std::vector Data::get_xx() const { std::vector xx(get_n()); for (size_t j = 0; j < xx.size(); ++j) xx[j] = get_x(j); return xx; } } // namespace fityk #endif fityk-1.3.1/fityk/eparser.cpp000066400000000000000000001112341302634723100161400ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Data expression parser. #define BUILDING_LIBFITYK #include "eparser.h" #include #include #include "lexer.h" #include "common.h" #include "logic.h" #include "data.h" #include "fit.h" // $var.error #include "var.h" // $v #include "func.h" // %f(...) #include "model.h" // F(...) using std::string; using std::vector; using std::min; using std::max; namespace { using namespace fityk; int get_op_priority(int op) { switch (op) { case OP_POW: return 9; case OP_NEG: return 8; case OP_MUL: return 7; case OP_DIV: return 7; case OP_ADD: return 6; case OP_SUB: return 6; case OP_GT: return 5; case OP_GE: return 5; case OP_LT: return 5; case OP_LE: return 5; case OP_EQ: return 5; case OP_NEQ: return 5; case OP_NOT: return 4; case OP_AFTER_AND: return 3; case OP_AFTER_OR: return 2; case OP_TERNARY_MID: return 1; case OP_AFTER_TERNARY: return 1; default: return 0; } } const char* function_name(int op) { switch (op) { // 1-arg functions case OP_SQRT: return "sqrt"; case OP_GAMMA: return "gamma"; case OP_LGAMMA: return "lgamma"; case OP_ERFC: return "erfc"; case OP_ERF: return "erf"; case OP_EXP: return "exp"; case OP_LOG10: return "log10"; case OP_LN: return "ln"; case OP_SINH: return "sinh"; case OP_COSH: return "cosh"; case OP_TANH: return "tanh"; case OP_SIN: return "sin"; case OP_COS: return "cos"; case OP_TAN: return "tan"; case OP_ATAN: return "atan"; case OP_ASIN: return "asin"; case OP_ACOS: return "acos"; case OP_ABS: return "abs"; case OP_ROUND: return "round"; case OP_XINDEX: return "index"; case OP_DT_SUM_SAME_X: return "sum_same_x"; case OP_DT_AVG_SAME_X: return "avg_same_x"; case OP_DT_SHIRLEY_BG: return "shirley_bg"; // 2-args functions case OP_MOD: return "mod"; case OP_MIN2: return "min2"; case OP_MAX2: return "max2"; case OP_VOIGT: return "voigt"; case OP_DVOIGT_DX: return "dvoigt_dx"; case OP_DVOIGT_DY: return "dvoigt_dy"; case OP_RANDNORM: return "randnormal"; case OP_RANDU: return "randuniform"; // Fityk functions case OP_FUNC: return "%function"; case OP_SUM_F: return "F"; case OP_SUM_Z: return "Z"; // "methods" of %f/F/Z case OP_NUMAREA: return "numarea"; case OP_FINDX: return "findx"; case OP_FIND_EXTR: return "extremum"; default: return ""; } } int get_function_narg(int op) { switch (op) { // 1-arg functions case OP_SQRT: case OP_GAMMA: case OP_LGAMMA: case OP_ERFC: case OP_ERF: case OP_EXP: case OP_LOG10: case OP_LN: case OP_SINH: case OP_COSH: case OP_TANH: case OP_SIN: case OP_COS: case OP_TAN: case OP_ATAN: case OP_ASIN: case OP_ACOS: case OP_ABS: case OP_ROUND: case OP_XINDEX: case OP_DT_SUM_SAME_X: case OP_DT_AVG_SAME_X: case OP_DT_SHIRLEY_BG: return 1; // 2-args functions case OP_MOD: case OP_MIN2: case OP_MAX2: case OP_VOIGT: case OP_DVOIGT_DX: case OP_DVOIGT_DY: case OP_RANDNORM: case OP_RANDU: return 2; // Fityk functions case OP_FUNC: case OP_SUM_F: case OP_SUM_Z: return 1; // "methods" of %f/F/Z case OP_NUMAREA: case OP_FINDX: return 3; case OP_FIND_EXTR: return 2; default: return 0; } } bool is_function(int op) { return get_function_narg(op) != 0; } bool is_array_var(int op) { switch (op) { case OP_Px: case OP_Py: case OP_Ps: case OP_Pa: case OP_PX: case OP_PY: case OP_PS: case OP_PA: return true; default: return false; } } class AggregSum : public AggregFunc { protected: virtual void op(double x, int) { v_ += x; } }; class AggregCount : public AggregFunc { protected: virtual void op(double x, int) { if (fabs(x) >= 0.5) v_ += 1; } }; class AggregMin : public AggregFunc { protected: virtual void op(double x, int) { if (counter_ == 1 || x < v_) v_ = x; } }; class AggregMax : public AggregFunc { protected: virtual void op(double x, int) { if (counter_ == 1 || x > v_) v_ = x; } }; class AggregArgMin : public AggregFunc { public: AggregArgMin(const vector& points) : points_(points) {} protected: virtual void op(double x, int n) { if (counter_ == 1 || x < min_) { min_ = x; v_ = points_[n].x; } } private: double min_; const vector& points_; }; class AggregArgMax : public AggregFunc { public: AggregArgMax(const vector& points) : points_(points) {} protected: virtual void op(double x, int n) { if (counter_ == 1 || x > max_) { max_ = x; v_ = points_[n].x; } } private: double max_; const vector& points_; }; class AggregDArea : public AggregFunc { public: AggregDArea(const vector& points) : points_(points) {} protected: virtual void op(double x, int n) { int M = points_.size(); double dx = (points_[min(n+1, M-1)].x - points_[max(n-1, 0)].x) / 2.; v_ += x * dx; } private: const vector& points_; }; class AggregAvg : public AggregFunc { protected: virtual void op(double x, int) { v_ += (x - v_) / counter_; } }; class AggregStdDev : public AggregFunc { public: AggregStdDev() : mean_(0.) {} protected: double mean_; virtual void op(double x, int) { // see: http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance double delta = x - mean_; mean_ += delta / counter_; v_ += delta * (x - mean_); } virtual double value() const { return sqrt(v_ / (counter_ - 1)); } }; class AggregCentile : public AggregFunc { public: AggregCentile() : param_(0.) {} virtual int number_of_parameters() const { return 1; } virtual void add_param(double p) { param_ = p; } protected: virtual void op(double x, int) { values_.push_back(x); } virtual double value() const { if (values_.empty()) return 0; int n = iround(param_ / 100. * values_.size()); n = min(max(n, 0), (int) values_.size() - 1); std::nth_element(values_.begin(), values_.begin() + n, values_.end()); return values_[n]; } private: double param_; mutable vector values_; }; } // anonymous namespace namespace fityk { void ExpressionParser::pop_onto_que() { int op = opstack_.back(); opstack_.pop_back(); vm_.append_code(op); } void ExpressionParser::put_number(double value) { if (expected_ == kOperator) { finished_ = true; return; } //cout << "put_number() " << value << endl; vm_.append_number(value); expected_ = kOperator; } void ExpressionParser::put_unary_op(Op op) { if (expected_ == kOperator) { finished_ = true; return; } opstack_.push_back(op); expected_ = kValue; } void ExpressionParser::put_binary_op(Op op) { if (expected_ != kOperator) { finished_ = true; return; } //cout << "put_binary_op() " << op << endl; int pri = get_op_priority(op); while (!opstack_.empty() && get_op_priority(opstack_.back()) >= pri) pop_onto_que(); opstack_.push_back(op); expected_ = kValue; } void ExpressionParser::put_function(Op op) { //cout << "put_function() " << op << endl; opstack_.push_back(0); // argument counter opstack_.push_back(op); expected_ = kValue; } void ExpressionParser::put_ag_function(Lexer& lex, int ds, AggregFunc& ag) { //cout << "put_ag_function() " << op << endl; lex.get_expected_token(kTokenOpen); // discard '(' ExpressionParser ep(F_); const vector& points = F_->dk.data(ds)->points(); for (int i = 0; i < ag.number_of_parameters(); ++i) { ep.parse_expr(lex, ds); lex.get_expected_token(kTokenComma); ag.add_param(ep.calculate(0, points)); ep.clear_vm(); } ep.parse_expr(lex, ds); Token t = lex.get_expected_token(kTokenClose, "if"); if (t.type == kTokenClose) { for (size_t n = 0; n != points.size(); ++n) { double x = ep.calculate(n, points); ag.put(x, n); } } else { // "if" ExpressionParser cond_p(F_); cond_p.parse_expr(lex, ds); lex.get_expected_token(kTokenClose); // discard ')' for (size_t n = 0; n != points.size(); ++n) { double c = cond_p.calculate(n, points); if (fabs(c) >= 0.5) { double x = ep.calculate(n, points); ag.put(x, n); } } } put_number(ag.value()); } double ExpressionParser::get_value_from(Lexer& lex, int ds, TokenType trailer) { ExpressionParser ep(F_); ep.parse_expr(lex, ds); lex.get_expected_token(trailer); // discard '}' or another token double x = ep.calculate(0, F_->dk.data(ds)->points()); return x; } void ExpressionParser::put_array_var(bool has_index, Op op) { if (has_index) { opstack_.push_back(op); expected_ = kIndex; } else { vm_.append_code(OP_Pn); vm_.append_code(op); expected_ = kOperator; } } void ExpressionParser::put_variable_sth(Lexer& lex, const string& name, bool ast_mode) { if (F_ == NULL) lex.throw_syntax_error("$variables can not be used here"); const Variable *v = F_->mgr.find_variable(name); if (lex.peek_token().type == kTokenDot) { lex.get_token(); // discard '.' lex.get_expected_token("error"); // discard "error" double e = F_->fit_manager()->get_standard_error(v); if (e == -1.) lex.throw_syntax_error("unknown error of $" + v->name + "; it is not simple variable"); put_number(e); } else { if (ast_mode) { int n = F_->mgr.find_variable_nr(name); vm_.append_code(OP_SYMBOL); vm_.append_code(n); expected_ = kOperator; } else put_number(v->value()); } } void ExpressionParser::put_func_sth(Lexer& lex, const string& name, bool ast_mode) { if (F_ == NULL) lex.throw_syntax_error("%functions can not be used here"); if (lex.peek_token().type == kTokenOpen) { int n = F_->mgr.find_function_nr(name); if (n == -1) throw ExecuteError("undefined function: %" + name); // we will put n into code when handling ')' opstack_.push_back(n); put_function(OP_FUNC); } else if (lex.peek_token().type == kTokenDot) { lex.get_token(); // discard '.' Token arg = lex.get_expected_token(kTokenLname, kTokenCname); string word = arg.as_string(); if (arg.type == kTokenCname) { const Function *f = F_->mgr.find_function(name); double val = f->get_param_value(word); put_number(val); } else if (lex.peek_token().type == kTokenOpen) { // method of %function int n = F_->mgr.find_function_nr(name); if (n == -1) throw ExecuteError("undefined function: %" + name); // we will put ds into code when handling ')' opstack_.push_back(n); opstack_.push_back(OP_FUNC); if (word == "numarea") put_function(OP_NUMAREA); else if (word == "findx") put_function(OP_FINDX); else if (word == "extremum") put_function(OP_FIND_EXTR); else lex.throw_syntax_error("unknown method: " + word); } else { // property of %function (= $variable) const Function *f = F_->mgr.find_function(name); string v = f->used_vars().get_name(f->get_param_nr(word)); put_variable_sth(lex, v, ast_mode); } } else lex.throw_syntax_error("expected '.' or '(' after %function"); } void ExpressionParser::put_fz_sth(Lexer& lex, char fz, int ds, bool ast_mode) { if (F_ == NULL || ds < 0) lex.throw_syntax_error("F/Z can not be used here"); if (lex.peek_token().type == kTokenLSquare) { lex.get_token(); // discard '[' ExpressionParser ep(F_); ep.parse_expr(lex, ds); lex.get_expected_token(kTokenRSquare); // discard ']' int idx = iround(ep.calculate()); const string& name = F_->dk.get_model(ds)->get_func_name(fz, idx); put_func_sth(lex, name, ast_mode); } else if (lex.peek_token().type == kTokenOpen) { opstack_.push_back(ds); // we will put ds into code when handling ')' put_function(fz == 'F' ? OP_SUM_F : OP_SUM_Z); } else if (lex.peek_token().type == kTokenDot) { lex.get_token(); // discard '.' string word = lex.get_expected_token(kTokenLname).as_string(); if (lex.peek_token().type != kTokenOpen) lex.throw_syntax_error("F/Z has no .properties, only .methods()"); // we will put ds into code when handling ')' opstack_.push_back(ds); opstack_.push_back(fz == 'F' ? OP_SUM_F : OP_SUM_Z); if (word == "numarea") put_function(OP_NUMAREA); else if (word == "findx") put_function(OP_FINDX); else if (word == "extremum") put_function(OP_FIND_EXTR); else lex.throw_syntax_error("unknown method of F/Z"); } else { lex.throw_syntax_error("unexpected token after F/Z"); } } void ExpressionParser::put_name(Lexer& lex, const string& word, const vector* custom_vars, vector* new_vars, bool ast_mode) { if (word == "pi") { put_number(M_PI); return; } if (word == "true") { put_number(1.); return; } if (word == "false") { put_number(0.); return; } if (ast_mode && word == "x") { vm_.append_code(OP_X); expected_ = kOperator; return; } if (custom_vars != NULL) { int idx = index_of_element(*custom_vars, word); if (idx != -1) { vm_.append_code(OP_SYMBOL); vm_.append_code(idx); expected_ = kOperator; return; } } if (new_vars != NULL) { int idx = index_of_element(*new_vars, word); if (idx == -1) { idx = new_vars->size(); new_vars->push_back(word); } vm_.append_code(OP_SYMBOL); // new_vars is to be appended to custom_vars later int cv_len = custom_vars != NULL ? (int) custom_vars->size() : 0; vm_.append_code(cv_len + idx); expected_ = kOperator; return; } if (custom_vars == NULL && new_vars == NULL && !ast_mode) { // data points bool has_index = (lex.peek_token().type == kTokenLSquare); if (word.size() == 1 && (word[0] == 'x' || word[0] == 'y' || word[0] == 's' || word[0] == 'a' || word[0] == 'n')) { if (word[0] == 'x') put_array_var(has_index, OP_Px); else if (word[0] == 'y') put_array_var(has_index, OP_Py); else if (word[0] == 's') put_array_var(has_index, OP_Ps); else if (word[0] == 'a') put_array_var(has_index, OP_Pa); else if (word[0] == 'n') { vm_.append_code(OP_Pn); expected_ = kOperator; } return; } } lex.throw_syntax_error("unknown name: " + word); } RealRange ExpressionParser::parse_domain(Lexer& lex, int ds) { RealRange range; // default lo/hi values correspond to [:] // read tokens to ':' (discarding ':'), set range.lo lex.get_token(); // discard '[' if (lex.peek_token().type == kTokenColon) { // leave default value for range.lo lex.get_token(); // discard ':' } else if (lex.peek_token().type == kTokenRSquare) { // omitted ':', never mind } else { range.lo = get_value_from(lex, ds, kTokenColon); // discards ':' } // read the rest, set range.hi if (lex.peek_token().type == kTokenRSquare) { lex.get_token(); // discard ']' // leave default value for range.hi } else { range.hi = get_value_from(lex, ds, kTokenRSquare); // discards ']' } return range; } void ExpressionParser::put_tilde_var(Lexer& lex, int ds) { if (expected_ == kOperator) lex.throw_syntax_error("unexpected `~'"); vm_.append_code(OP_TILDE); const Token token = lex.get_token(); double val = 0; if (token.type == kTokenNumber) { val = token.value.d; } else if (token.type == kTokenMinus) { Token num = lex.get_token(); if (num.type != kTokenNumber) lex.throw_syntax_error("expecting number after ~-"); // let's make ~-NUM^NUM illegal to make parsing precedence clear if (lex.peek_token().type == kTokenPower) lex.throw_syntax_error("use ~{-NUM}^NUM instead of ~-NUM^NUM"); val = -num.value.d; } else if (token.type == kTokenLCurly) { val = get_value_from(lex, ds, kTokenRCurly); } else { lex.throw_syntax_error("unexpected token after `~'"); } put_number(val); if (lex.peek_token().type == kTokenLSquare) { RealRange range = parse_domain(lex, ds); vm_.append_number(range.lo); vm_.append_number(range.hi); } else { // artificial mark that there is no domain vm_.append_code(OP_TILDE); } assert(expected_ == kOperator); } void ExpressionParser::pop_until_bracket() { while (!opstack_.empty()) { int op = opstack_.back(); if (op == OP_OPEN_ROUND || op == OP_OPEN_SQUARE || op == OP_TERNARY_MID) break; opstack_.pop_back(); vm_.append_code(op); } } bool ExpressionParser::parse_full(Lexer& lex, int default_ds, const vector *custom_vars) { try { parse_expr(lex, default_ds, custom_vars); } catch (...) { return false; } return lex.peek_token().type == kTokenNop; } // implementation of the shunting-yard algorithm void ExpressionParser::parse_expr(Lexer& lex, int default_ds, const vector *custom_vars, vector *new_vars, ParseMode mode) { opstack_.clear(); finished_ = false; expected_ = kValue; if (F_ != NULL && default_ds >= F_->dk.count()) lex.throw_syntax_error("wrong dataset index"); while (!finished_) { const Token token = lex.get_token(); //cout << "> " << token2str(token) << endl; switch (token.type) { case kTokenNumber: put_number(token.value.d); break; case kTokenLname: { string word = token.as_string(); // "not", "and", "or" can be followed by '(' or not. if (word == "not") put_unary_op(OP_NOT); else if (word == "and") { put_binary_op(OP_AFTER_AND); vm_.append_code(OP_AND); } else if (word == "or") { put_binary_op(OP_AFTER_OR); vm_.append_code(OP_OR); } else if (word == "if") { pop_until_bracket(); if (expected_ == kOperator && opstack_.empty()) finished_ = true; else lex.throw_syntax_error("unexpected `if'"); } else if (lex.peek_token().type == kTokenOpen) { if (expected_ == kOperator) { finished_ = true; break; } // 1-arg functions if (word == "sqrt") put_function(OP_SQRT); else if (word == "gamma") put_function(OP_GAMMA); else if (word == "lgamma") put_function(OP_LGAMMA); else if (word == "erfc") put_function(OP_ERFC); else if (word == "erf") put_function(OP_ERF); else if (word == "exp") put_function(OP_EXP); else if (word == "log10") put_function(OP_LOG10); else if (word == "ln") put_function(OP_LN); else if (word == "sinh") put_function(OP_SINH); else if (word == "cosh") put_function(OP_COSH); else if (word == "tanh") put_function(OP_TANH); else if (word == "sin") put_function(OP_SIN); else if (word == "cos") put_function(OP_COS); else if (word == "tan") put_function(OP_TAN); else if (word == "atan") put_function(OP_ATAN); else if (word == "asin") put_function(OP_ASIN); else if (word == "acos") put_function(OP_ACOS); else if (word == "abs") put_function(OP_ABS); else if (word == "round") put_function(OP_ROUND); else if (word == "index") put_function(OP_XINDEX); // 2-args functions else if (word == "mod") put_function(OP_MOD); else if (word == "min2") put_function(OP_MIN2); else if (word == "max2") put_function(OP_MAX2); else if (word == "voigt") put_function(OP_VOIGT); else if (word == "randnormal") put_function(OP_RANDNORM); else if (word == "randuniform") put_function(OP_RANDU); // aggregate functions else if (word == "sum") { AggregSum ag; put_ag_function(lex, default_ds, ag); } else if (word == "count") { AggregCount ag; put_ag_function(lex, default_ds, ag); } else if (word == "min") { AggregMin ag; put_ag_function(lex, default_ds, ag); } else if (word == "max") { AggregMax ag; put_ag_function(lex, default_ds, ag); } else if (word == "argmin") { AggregArgMin ag(F_->dk.data(default_ds)->points()); put_ag_function(lex, default_ds, ag); } else if (word == "argmax") { AggregArgMax ag(F_->dk.data(default_ds)->points()); put_ag_function(lex, default_ds, ag); } else if (word == "avg") { AggregAvg ag; put_ag_function(lex, default_ds, ag); } else if (word == "stddev") { AggregStdDev ag; put_ag_function(lex, default_ds, ag); } else if (word == "centile") { AggregCentile ag; put_ag_function(lex, default_ds, ag); } else if (word == "darea") { if (F_ == NULL) lex.throw_syntax_error("darea: unknown @dataset"); AggregDArea ag(F_->dk.data(default_ds)->points()); put_ag_function(lex, default_ds, ag); } // dataset functions else if (mode == kDatasetTrMode && word == "sum_same_x") put_function(OP_DT_SUM_SAME_X); else if (mode == kDatasetTrMode && word == "avg_same_x") put_function(OP_DT_AVG_SAME_X); else if (mode == kDatasetTrMode && word == "shirley_bg") put_function(OP_DT_SHIRLEY_BG); else lex.throw_syntax_error("unknown function: " + word); } else { if (expected_ == kOperator) { finished_ = true; break; } put_name(lex, word, custom_vars, new_vars, mode==kAstMode); } break; } case kTokenUletter: { if (expected_ == kOperator) { finished_ = true; break; } bool has_index = (lex.peek_token().type == kTokenLSquare); if (*token.str == 'X') put_array_var(has_index, OP_PX); else if (*token.str == 'Y') put_array_var(has_index, OP_PY); else if (*token.str == 'S') put_array_var(has_index, OP_PS); else if (*token.str == 'A') put_array_var(has_index, OP_PA); else if (*token.str == 'M') { vm_.append_code(OP_PM); expected_ = kOperator; } else if (*token.str == 'F' || *token.str == 'Z') { put_fz_sth(lex, *token.str, default_ds, mode==kAstMode); } else lex.throw_syntax_error("unknown name: "+ token.as_string()); break; } case kTokenDataset: { if (expected_ == kOperator) { finished_ = true; break; } if (lex.peek_token().type == kTokenDot) { lex.get_token(); // discard '.' Token t = lex.get_expected_token(kTokenUletter); if (*t.str == 'F' || *t.str == 'Z') { put_fz_sth(lex, *t.str, token.value.i, mode==kAstMode); } else lex.throw_syntax_error("unknown name: " + token.as_string()); } else { if (mode != kDatasetTrMode) lex.get_expected_token(kTokenDot); int n = token.value.i; if (n == Lexer::kAll || n == Lexer::kNew) lex.throw_syntax_error("@*/@+ not allowed at RHS"); vm_.append_code(OP_DATASET); vm_.append_code(n); expected_ = kOperator; } break; } case kTokenOpen: if (expected_ == kOperator) { finished_ = true; break; } opstack_.push_back(OP_OPEN_ROUND); expected_ = kValue; break; case kTokenLSquare: if (expected_ != kIndex) { finished_ = true; break; } opstack_.push_back(OP_OPEN_SQUARE); expected_ = kValue; break; case kTokenClose: pop_until_bracket(); if (opstack_.empty()) { finished_ = true; break; } else if (opstack_.back() == OP_OPEN_SQUARE) lex.throw_syntax_error("mismatching '[' and ')'"); else if (opstack_.back() == OP_TERNARY_MID) lex.throw_syntax_error("mismatching '?' and ')'"); // if we are here, opstack_.back() == OP_OPEN_ROUND opstack_.pop_back(); // check if this is closing bracket of func() if (!opstack_.empty()) { int top = opstack_.back(); if (is_function(top)) { pop_onto_que(); int n = opstack_.back() + 1; opstack_.pop_back(); int expected_n = get_function_narg(top); if (n != expected_n) lex.throw_syntax_error( S("function ") + function_name(top) + " expects " + S(expected_n) + " arguments, not " + S(n)); if (top==OP_FUNC || top==OP_SUM_F || top==OP_SUM_Z) pop_onto_que(); // pop function index else if (top==OP_NUMAREA || top==OP_FINDX || top==OP_FIND_EXTR) { pop_onto_que(); // pop OP_FUNC/OP_SUM_F/Z pop_onto_que(); // pop function index } } } expected_ = kOperator; break; case kTokenComma: pop_until_bracket(); if (opstack_.empty()) { finished_ = true; break; } else if (opstack_.back() == OP_OPEN_SQUARE) lex.throw_syntax_error("unexpected ',' after '['"); else if (opstack_.back() == OP_TERNARY_MID) lex.throw_syntax_error("unexpected ',' after '?'"); // if we are here, opstack_.back() == OP_OPEN_ROUND else if (opstack_.size() < 3 || !is_function(*(opstack_.end() - 2))) lex.throw_syntax_error("',' outside of function"); else // don't pop OP_OPEN_ROUND from the stack ++ *(opstack_.end() - 3); expected_ = kValue; break; case kTokenRSquare: pop_until_bracket(); if (opstack_.empty()) { finished_ = true; break; } else if (opstack_.back() == OP_OPEN_ROUND) lex.throw_syntax_error("mismatching '(' and ']'"); else if (opstack_.back() == OP_TERNARY_MID) lex.throw_syntax_error("mismatching '?' and ']'"); // if we are here, opstack_.back() == OP_OPEN_SQUARE opstack_.pop_back(); if (opstack_.empty() || !is_array_var(opstack_.back())) lex.throw_syntax_error("[index] can be used only after " "x, y, s, a, X, Y, S or A."); pop_onto_que(); expected_ = kOperator; break; case kTokenNop: finished_ = true; break; case kTokenPower: put_binary_op(OP_POW); break; case kTokenMult: put_binary_op(OP_MUL); break; case kTokenDiv: put_binary_op(OP_DIV); break; case kTokenPlus: if (expected_ == kOperator) put_binary_op(OP_ADD); else {} // do nothing for unary + break; case kTokenMinus: if (expected_ == kOperator) { put_binary_op(OP_SUB); } else if (lex.peek_token().type == kTokenNumber) { // In '-3', '-3+5', '-3*5', 5*-3', etc. '-3' is parsed // as a number. The exception is '-3^5', where '-3' // is parsed as OP_NEG and number, because '^' has higher // precedence than '-' Token num = lex.get_token(); if (lex.peek_token().type != kTokenPower) { put_number(-num.value.d); } else { put_unary_op(OP_NEG); put_number(num.value.d); } } else { put_unary_op(OP_NEG); } break; case kTokenGT: // This token can be outside of the expression. // We handle one special case: '>' followed by string, // to allow "print x, y > 'filename'". if (lex.peek_token().type == kTokenString) finished_ = true; else put_binary_op(OP_GT); break; case kTokenGE: put_binary_op(OP_GE); break; case kTokenLT: put_binary_op(OP_LT); break; case kTokenLE: put_binary_op(OP_LE); break; case kTokenEQ: put_binary_op(OP_EQ); break; case kTokenNE: put_binary_op(OP_NEQ); break; case kTokenQMark: // special case, for handling SplitFunction that has // ... expr "?" TypeName ":" ... // (fixme: why not to throw error here?) if (lex.peek_token().type == kTokenCname) { finished_ = true; break; } put_binary_op(OP_TERNARY_MID); vm_.append_code(OP_TERNARY); break; case kTokenColon: for (;;) { if (opstack_.empty()) { finished_ = true; break; } // pop OP_TERNARY_MID from the stack onto the que int op = opstack_.back(); opstack_.pop_back(); vm_.append_code(op); if (op == OP_TERNARY_MID) break; } if (!finished_) put_binary_op(OP_AFTER_TERNARY); break; case kTokenVarname: put_variable_sth(lex, Lexer::get_string(token), mode==kAstMode); break; case kTokenFuncname: put_func_sth(lex, Lexer::get_string(token), mode==kAstMode); break; case kTokenTilde: put_tilde_var(lex, default_ds); break; case kTokenLCurly: put_number(get_value_from(lex, default_ds, kTokenRCurly)); break; case kTokenString: case kTokenCname: case kTokenBang: case kTokenAppend: case kTokenAddAssign: case kTokenSubAssign: case kTokenDots: case kTokenPlusMinus: case kTokenRCurly: case kTokenAssign: case kTokenSemicolon: case kTokenDot: finished_ = true; break; // these are never return by get_token() case kTokenWord: case kTokenExpr: case kTokenEVar: case kTokenRest: assert(0); break; } if (finished_ && token.type != kTokenNop) lex.go_back(token); } // the expression should not end with operator if (expected_ != kOperator) lex.throw_syntax_error("unexpected token or end of expression"); // no more tokens to read pop_until_bracket(); // there should be no bracket if (!opstack_.empty()) lex.throw_syntax_error("mismatching bracket"); } void ExpressionParser::push_assign_lhs(const Token& t) { Op op; switch (toupper(*t.str)) { case 'X': op = OP_ASSIGN_X; break; case 'Y': op = OP_ASSIGN_Y; break; case 'S': op = OP_ASSIGN_S; break; case 'A': op = OP_ASSIGN_A; break; default: assert(0); } vm_.append_code(op); } } // namespace fityk fityk-1.3.1/fityk/eparser.h000066400000000000000000000067171302634723100156160ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Data expression parser. #ifndef FITYK_EPARSER_H_ #define FITYK_EPARSER_H_ #include #include #include "vm.h" #include "lexer.h" // TokenType, Token, Lexer namespace fityk { /// base class used to implement aggregate functions (sum, min, avg, etc.) class AggregFunc { public: AggregFunc() : counter_(0), v_(0.) {} virtual ~AggregFunc() {} // x - expression value, n - index of the point in Data::p_ void put(double x, int n) { ++counter_; op(x, n); } virtual double value() const { return v_; } virtual int number_of_parameters() const { return 0; } virtual void add_param(double /*p*/) { } protected: int counter_; double v_; virtual void op(double x, int n) = 0; }; /// Expression parser. /// Derived from ExpressionParser only because it is handy to keep both /// in one class. class FITYK_API ExpressionParser : public ExprCalculator { public: enum ExpectedType { kOperator, kValue, kIndex }; enum ParseMode { kNormalMode, kAstMode, kDatasetTrMode }; // if F is NULL, $variables, %functions, etc. are not handled ExpressionParser(const Full* F) : ExprCalculator(F), expected_(kValue), finished_(false) {} /// reset state void clear_vm() { vm_.clear_data(); } /// parse expression void parse_expr(Lexer& lex, int default_ds, const std::vector *custom_vars=NULL, std::vector *new_vars=NULL, ParseMode mode=kNormalMode); // does not throw; returns true if all string is parsed bool parse_full(Lexer& lex, int default_ds, const std::vector *custom_vars=NULL); RealRange parse_domain(Lexer& lex, int ds); /// adds OP_ASSIGN_? to the code void push_assign_lhs(const Token& t); private: // operator stack for the shunting-yard algorithm std::vector opstack_; // expected type of the next token (basic shunting-yard algorithm parses // e.g. two numbers in sequence, like "1 2", ignores the the first one // and doesn't signal error. The expected_ flag is used to stop parsing // such input just after getting token from lexer) ExpectedType expected_; // We set this to true when the next token is not part of the expression. // Exception is not thrown, because ExpressionParser can be used as // sub-parser from Parser. bool finished_; void put_number(double value); void put_unary_op(Op op); void put_binary_op(Op op); void put_function(Op op); void put_ag_function(Lexer& lex, int ds, AggregFunc& ag); double get_value_from(Lexer& lex, int ds, TokenType trailer); void put_array_var(bool has_index, Op op); void put_name(Lexer& lex, const std::string& word, const std::vector* custom_vars, std::vector* new_vars, bool ast_mode); void put_variable_sth(Lexer& lex, const std::string& name, bool ast_mode); void put_func_sth(Lexer& lex, const std::string& name, bool ast_mode); void put_fz_sth(Lexer& lex, char fz, int ds, bool ast_mode); void put_tilde_var(Lexer& lex, int ds); void pop_onto_que(); void pop_until_bracket(); }; } // namespace fityk #endif // FITYK_EPARSER_H_ fityk-1.3.1/fityk/f_fcjasym.cpp000066400000000000000000001261461302634723100164500ustar00rootroot00000000000000// Author: James Hester // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "f_fcjasym.h" using namespace std; namespace fityk { /* Gauss-Legendre coefficients for numerical integration */ const double FuncFCJAsymm::w100[] = { 0.0312554234538633569476425, 0.0312248842548493577323765, 0.0311638356962099067838183, 0.0310723374275665165878102, 0.0309504788504909882340635, 0.0307983790311525904277139, 0.0306161865839804484964594, 0.0304040795264548200165079, 0.0301622651051691449190687, 0.0298909795933328309168368, 0.0295904880599126425117545, 0.0292610841106382766201190, 0.0289030896011252031348762, 0.0285168543223950979909368, 0.0281027556591011733176483, 0.0276611982207923882942042, 0.0271926134465768801364916, 0.0266974591835709626603847, 0.0261762192395456763423087, 0.0256294029102081160756420, 0.0250575444815795897037642, 0.0244612027079570527199750, 0.0238409602659682059625604, 0.0231974231852541216224889, 0.0225312202563362727017970, 0.0218430024162473863139537, 0.0211334421125276415426723, 0.0204032326462094327668389, 0.0196530874944353058653815, 0.0188837396133749045529412, 0.0180959407221281166643908, 0.0172904605683235824393442, 0.0164680861761452126431050, 0.0156296210775460027239369, 0.0147758845274413017688800, 0.0139077107037187726879541, 0.0130259478929715422855586, 0.0121314576629794974077448, 0.0112251140231859771172216, 0.0103078025748689695857821, 0.0093804196536944579514182, 0.0084438714696689714026208, 0.0074990732554647115788287, 0.0065469484508453227641521, 0.0055884280038655151572119, 0.0046244500634221193510958, 0.0036559612013263751823425, 0.0026839253715534824194396, 0.0017093926535181052395294, 0.0007346344905056717304063}; const double FuncFCJAsymm::x100[] = { 0.0156289844215430828722167, 0.0468716824215916316149239, 0.0780685828134366366948174, 0.1091892035800611150034260, 0.1402031372361139732075146, 0.1710800805386032748875324, 0.2017898640957359972360489, 0.2323024818449739696495100, 0.2625881203715034791689293, 0.2926171880384719647375559, 0.3223603439005291517224766, 0.3517885263724217209723438, 0.3808729816246299567633625, 0.4095852916783015425288684, 0.4378974021720315131089780, 0.4657816497733580422492166, 0.4932107892081909335693088, 0.5201580198817630566468157, 0.5465970120650941674679943, 0.5725019326213811913168704, 0.5978474702471787212648065, 0.6226088602037077716041908, 0.6467619085141292798326303, 0.6702830156031410158025870, 0.6931491993558019659486479, 0.7153381175730564464599671, 0.7368280898020207055124277, 0.7575981185197071760356680, 0.7776279096494954756275514, 0.7968978923903144763895729, 0.8153892383391762543939888, 0.8330838798884008235429158, 0.8499645278795912842933626, 0.8660146884971646234107400, 0.8812186793850184155733168, 0.8955616449707269866985210, 0.9090295709825296904671263, 0.9216092981453339526669513, 0.9332885350430795459243337, 0.9440558701362559779627747, 0.9539007829254917428493369, 0.9628136542558155272936593, 0.9707857757637063319308979, 0.9778093584869182885537811, 0.9838775407060570154961002, 0.9889843952429917480044187, 0.9931249370374434596520099, 0.9962951347331251491861317, 0.9984919506395958184001634, 0.9997137267734412336782285}; const double FuncFCJAsymm::x1024[] = { 0.0015332313560626384065387, 0.0045996796509132604743248, 0.0076660846940754867627839, 0.0107324176515422803327458, 0.0137986496899844401539048, 0.0168647519770217265449962, 0.0199306956814939776907024, 0.0229964519737322146859283, 0.0260619920258297325581921, 0.0291272870119131747190088, 0.0321923081084135882953009, 0.0352570264943374577920498, 0.0383214133515377145376052, 0.0413854398649847193632977, 0.0444490772230372159692514, 0.0475122966177132524285687, 0.0505750692449610682823599, 0.0536373663049299446784129, 0.0566991590022410150066456, 0.0597604185462580334848567, 0.0628211161513580991486838, 0.0658812230372023327000985, 0.0689407104290065036692117, 0.0719995495578116053446277, 0.0750577116607543749280791, 0.0781151679813377563695878, 0.0811718897697013033399379, 0.0842278482828915197978074, 0.0872830147851321356094940, 0.0903373605480943146797811, 0.0933908568511667930531222, 0.0964434749817259444449839, 0.0994951862354057706638682, 0.1025459619163678143852404, 0.1055957733375709917393206, 0.1086445918210413421754502, 0.1116923886981416930665228, 0.1147391353098412365177689, 0.1177848030069850158450139, 0.1208293631505633191883714, 0.1238727871119809777282145, 0.1269150462733265659711591, 0.1299561120276415015747167, 0.1329959557791890421802183, 0.1360345489437231767245806, 0.1390718629487574087024745, 0.1421078692338334288514767, 0.1451425392507896747338214, 0.1481758444640297746894331, 0.1512077563507908736360111, 0.1542382464014118381930443, 0.1572672861196013386077717, 0.1602948470227058049622614, 0.1633209006419772551419632, 0.1663454185228409920472972, 0.1693683722251631675310675, 0.1723897333235182105457458, 0.1754094734074561169859457, 0.1784275640817695987127083, 0.1814439769667610892475458, 0.1844586836985096036255346, 0.1874716559291374498981239, 0.1904828653270767897777182, 0.1934922835773360459175133, 0.1964998823817661533215037, 0.1995056334593266523810493, 0.2025095085463516210358758, 0.2055114793968154435588961, 0.2085115177825984134657778, 0.2115095954937521680517391, 0.2145056843387649520596422, 0.2174997561448267079850562, 0.2204917827580939905255947, 0.2234817360439547026834844, 0.2264695878872926510320010, 0.2294553101927519176581055, 0.2324388748850010462953415, 0.2354202539089970401627982, 0.2383994192302491690277166, 0.2413763428350825830111093, 0.2443509967309017306575811, 0.2473233529464535787923793, 0.2502933835320906316905658, 0.2532610605600337470850902, 0.2562263561246347465424530, 0.2591892423426388177365829, 0.2621496913534467061535080, 0.2651076753193766937613805, 0.2680631664259263621824189, 0.2710161368820341379053566, 0.2739665589203406170790369, 0.2769144047974496674298651, 0.2798596467941893048479266, 0.2828022572158723421886958, 0.2857422083925568078394062, 0.2886794726793061316013119, 0.2916140224564490954412652, 0.2945458301298395466682397, 0.2974748681311158710926665, 0.3004011089179602237287060, 0.3033245249743575146018584, 0.3062450888108541472266190, 0.3091627729648165073212094, 0.3120775500006891993287636, 0.3149893925102530283167230, 0.3178982731128827248285835, 0.3208041644558044102645582, 0.3237070392143528003701590, 0.3266068700922281444141618, 0.3295036298217528976399056, 0.3323972911641281245763845, 0.3352878269096896307981228, 0.3381752098781638207253743, 0.3410594129189232790587667, 0.3439404089112420734451077, 0.3468181707645507759736923, 0.3496926714186912011050938, 0.3525638838441708576370887, 0.3554317810424171123150528, 0.3582963360460310626968790, 0.3611575219190411168852009, 0.3640153117571562777424605, 0.3668696786880191292071420, 0.3697205958714585223322883, 0.3725680364997419586702471, 0.3754119737978276686304337, 0.3782523810236163824397703, 0.3810892314682027913383487, 0.3839224984561266966457784, 0.3867521553456238443366159, 0.3895781755288764427662286, 0.3924005324322633611914264, 0.3952191995166100067331951, 0.3980341502774378774318886, 0.4008453582452137890482864, 0.4036527969855987732669841, 0.4064564400996966449616823, 0.4092562612243022361850445, 0.4120522340321492945489319, 0.4148443322321580436639788, 0.4176325295696824033106488, 0.4204167998267568670171117, 0.4231971168223430347225035, 0.4259734544125757982073747, 0.4287457864910091769763965, 0.4315140869888618022816824, 0.4342783298752620469783905, 0.4370384891574927989076034, 0.4397945388812358755048319, 0.4425464531308160773358662, 0.4452942060294448782650898, 0.4480377717394637499647905, 0.4507771244625871184774399, 0.4535122384401449505463744, 0.4562430879533249674337895, 0.4589696473234144839484647, 0.4616918909120418704091584, 0.4644097931214176352731591, 0.4671233283945751261630457, 0.4698324712156108470282980, 0.4725371961099243891820077, 0.4752374776444579739565725, 0.4779332904279356047259052, 0.4806246091111018260453658, 0.4833114083869600876643171, 0.4859936629910107111699206, 0.4886713477014884570245255, 0.4913444373395996897627612, 0.4940129067697591391182235, 0.4966767308998262548534419, 0.4993358846813411530706387, 0.5019903431097601517846292, 0.5046400812246908935430768, 0.5072850741101270528831987, 0.5099252968946826264179220, 0.5125607247518258033484145, 0.5151913329001124142038603, 0.5178170966034189556133159, 0.5204379911711751889184691, 0.5230539919585963104401304, 0.5256650743669146912153147, 0.5282712138436111840258187, 0.5308723858826459955432696, 0.5334685660246891214197081, 0.5360597298573503421568799, 0.5386458530154087775915395, 0.5412269111810419978382210, 0.5438028800840546885350993, 0.5463737355021068682427603, 0.5489394532609416558499039, 0.5515000092346125858442412, 0.5540553793457104693110943, 0.5566055395655897985264809, 0.5591504659145946930157566, 0.5616901344622843849532002, 0.5642245213276582417822586, 0.5667536026793803239405196, 0.5692773547360034755778519, 0.5717957537661929461605442, 0.5743087760889495408586850, 0.5768163980738322976184566, 0.5793185961411806888254667, 0.5818153467623363454697137, 0.5843066264598643017272666, 0.5867924118077737578782574, 0.5892726794317383594853053, 0.5917474060093159907610475, 0.5942165682701680800580147, 0.5966801429962784154186793, 0.5991381070221714681281111, 0.6015904372351302222163013, 0.6040371105754135078618616, 0.6064781040364728366534687, 0.6089133946651687366701116, 0.6113429595619865853458987, 0.6137667758812519380899084, 0.6161848208313453506363029, 0.6185970716749166931046915, 0.6210035057290989537555048, 0.6234041003657215304299416, 0.6257988330115230076688675, 0.6281876811483634175098794, 0.6305706223134359819666081, 0.6329476340994783351992008, 0.6353186941549832233898213, 0.6376837801844086803419153, 0.6400428699483876768269192, 0.6423959412639372417070377, 0.6447429720046670528676835, 0.6470839401009874959981582, 0.6494188235403171892641570, 0.6517476003672899719207013, 0.6540702486839613549191454, 0.6563867466500144315669620, 0.6586970724829652463040876, 0.6610012044583676196647058, 0.6632991209100174274984589, 0.6655908002301563325302097, 0.6678762208696749663426270, 0.6701553613383155598710345, 0.6724282002048740205051479, 0.6746947160974014538975312, 0.6769548877034051285838219, 0.6792086937700488815250166, 0.6814561131043529626873631, 0.6836971245733933167806834, 0.6859317071045003002812397, 0.6881598396854568318705713, 0.6903815013646959744270519, 0.6925966712514979467122689, 0.6948053285161865628996815, 0.6970074523903250980984011, 0.6992030221669115780303307, 0.7013920172005734910243170, 0.7035744169077619204963997, 0.7057502007669450960906928, 0.7079193483188013616608982, 0.7100818391664115582779368, 0.7122376529754508204546805, 0.7143867694743797837842896, 0.7165291684546352021941915, 0.7186648297708199730232898, 0.7207937333408925681355609, 0.7229158591463558692887801, 0.7250311872324454059827217, 0.7271396977083169940167956, 0.7292413707472337729927181, 0.7313361865867526410034676, 0.7334241255289100847554419, 0.7355051679404074033764222, 0.7375792942527953241676460, 0.7396464849626580085640129, 0.7417067206317964465721772, 0.7437599818874112379620360, 0.7458062494222847584928838, 0.7478455039949627094612890, 0.7498777264299350488635483, 0.7519028976178163024713854, 0.7539209985155252531253957, 0.7559320101464640065565832, 0.7579359136006964320521972, 0.7599326900351259762879594, 0.7619223206736728486546595, 0.7639047868074505764130149, 0.7658800697949419280166093, 0.7678481510621742029486694, 0.7698090121028938864243967, 0.7717626344787406673165402, 0.7737089998194208176678866, 0.7756480898228799321603470, 0.7775798862554750259163361, 0.7795043709521459890141759, 0.7814215258165863961053031, 0.7833313328214136695271245, 0.7852337740083385943114429, 0.7871288314883341834944720, 0.7890164874418038921405657, 0.7908967241187491784979139, 0.7927695238389364107105941, 0.7946348689920631175175217, 0.7964927420379235813750136, 0.7983431255065737724458586, 0.8001860019984956219039900, 0.8020213541847606330100649, 0.8038491648071928284194859, 0.8056694166785310321906380, 0.8074820926825904849673728, 0.8092871757744237908160400, 0.8110846489804811942036542, 0.8128744953987701856100790, 0.8146566981990144342734272, 0.8164312406228120465742028, 0.8181981059837931485700490, 0.8199572776677767911993239, 0.8217087391329271766780945, 0.8234524739099092046215225, 0.8251884656020433364270094, 0.8269166978854597764628854, 0.8286371545092519686128428, 0.8303498192956294067327593, 0.8320546761400697575830038, 0.8337517090114702948057846, 0.8354409019522986425235764, 0.8371222390787428271411563, 0.8387957045808606359402829, 0.8404612827227282810625704, 0.8421189578425883674826439, 0.8437687143529971635802028, 0.8454105367409711729261812, 0.8470444095681330059047621, 0.8486703174708565497995875, 0.8502882451604114359791023, 0.8518981774231068028225812, 0.8535000991204343530350070, 0.8550939951892107040056078, 0.8566798506417190298715048, 0.8582576505658499939545848, 0.8598273801252419702463831, 0.8613890245594205526224495, 0.8629425691839373504743648, 0.8644879993905080694542896, 0.8660253006471498760336444, 0.8675544584983180445842596, 0.8690754585650418856970762, 0.8705882865450599544602407, 0.8720929282129545374252050, 0.8735893694202854169962281, 0.8750775960957229119854680, 0.8765575942451801930826613, 0.8780293499519448719952049, 0.8794928493768098630212838, 0.8809480787582035158255322, 0.8823950244123190181935674, 0.8838336727332430675485994, 0.8852640101930838100201983, 0.8866860233420980458621863, 0.8880996988088177000235219, 0.8895050233001755566829532, 0.8909019836016302565651375, 0.8922905665772905558628607, 0.8936707591700388455969280, 0.8950425484016539302522575, 0.8964059213729330645356690, 0.8977608652638132471078410, 0.8991073673334917701488930, 0.9004454149205460236240486, 0.9017749954430525531228459, 0.9030960963987053701523781, 0.9044087053649335137720782, 0.9057128099990178624646022, 0.9070083980382071951444166, 0.9082954572998335002127549, 0.9095739756814265315746820, 0.9108439411608276105410847, 0.9121053417963026725455006, 0.9133581657266545576127977, 0.9146024011713345435238301, 0.9158380364305531206273175, 0.9170650598853900072573273, 0.9182834599979034047218800, 0.9194932253112384908353520, 0.9206943444497351509745089, 0.9218868061190349456451742, 0.9230705991061873135537215, 0.9242457122797550091847637, 0.9254121345899187738936182, 0.9265698550685812395293315, 0.9277188628294700636112689, 0.9288591470682402950895005, 0.9299906970625759697264543, 0.9311135021722909341445515, 0.9322275518394288975917975, 0.9333328355883627104845635, 0.9344293430258928687940732, 0.9355170638413452433503852, 0.9365959878066680331449597, 0.9376661047765279417201973, 0.9387274046884055757416456, 0.9397798775626900648558921, 0.9408235135027729019444869, 0.9418583026951410028915762, 0.9428842354094689849902736, 0.9439013019987106631201510, 0.9449094928991897628355911, 0.9459087986306898495121205, 0.9468992097965434727052183, 0.9478807170837205248834878, 0.9488533112629158137054760, 0.9498169831886358470168335, 0.9507717237992848297519245, 0.9517175241172498719314184, 0.9526543752489854069548347, 0.9535822683850968193944507, 0.9545011948004232815044368, 0.9554111458541197976665483, 0.9563121129897384560011695, 0.9572040877353088863799924, 0.9580870617034179240840996, 0.9589610265912884783587268, 0.9598259741808576051234879, 0.9606818963388537831043733, 0.9615287850168733926613630, 0.9623666322514563965930439, 0.9631954301641612222071790, 0.9640151709616388439537466, 0.9648258469357060659245549, 0.9656274504634180035311332, 0.9664199740071397636802195, 0.9672034101146173227737943, 0.9679777514190476018682591, 0.9687429906391477383350273, 0.9694991205792235533724866, 0.9702461341292372147270016, 0.9709840242648740939883669, 0.9717127840476088178328839, 0.9724324066247705125950353, 0.9731428852296072415565604, 0.9738442131813496343496072, 0.9745363838852737078785517, 0.9752193908327628781730396, 0.9758932276013691625928266, 0.9765578878548735718130775, 0.9772133653433456910269459, 0.9778596539032024498104955, 0.9784967474572660801033674, 0.9791246400148212617670490, 0.9797433256716714551911835, 0.9803527986101944204270933, 0.9809530530993969223366037, 0.9815440834949686212533729, 0.9821258842393351486632952, 0.9826984498617103674201996, 0.9832617749781478160230522, 0.9838158542915913364912672, 0.9843606825919248853856025, 0.9848962547560215275335618, 0.9854225657477916120303537, 0.9859396106182301300994116, 0.9864473845054632544104222, 0.9869458826347940594679517, 0.9874351003187474227003598, 0.9879150329571141058970610, 0.9883856760369940166627304, 0.9888470251328386495802522, 0.9892990759064927068006818, 0.9897418241072348978090276, 0.9901752655718179181502248, 0.9905993962245076069415402, 0.9910142120771212830473891, 0.9914197092290652598522332, 0.9918158838673715386394944, 0.9922027322667336806727008, 0.9925802507895418581838653, 0.9929484358859170846092543, 0.9933072840937446245820355, 0.9936567920387065844051246, 0.9939969564343136839997662, 0.9943277740819362116746914, 0.9946492418708341635125525, 0.9949613567781865697596566, 0.9952641158691200113800912, 0.9955575162967363309635588, 0.9958415553021395435525955, 0.9961162302144619548145649, 0.9963815384508894965215124, 0.9966374775166862927999356, 0.9968840450052184754903082, 0.9971212385979772738362093, 0.9973490560646014135491635, 0.9975674952628988745188845, 0.9977765541388680773265018, 0.9979762307267185998745420, 0.9981665231488915727109186, 0.9983474296160799746514418, 0.9985189484272491654281575, 0.9986810779696581776171579, 0.9988338167188825964389443, 0.9989771632388403756649803, 0.9991111161818228462260355, 0.9992356742885348165163858, 0.9993508363881507486653971, 0.9994566013984000492749057, 0.9995529683257070064969677, 0.9996399362654382464576482, 0.9997175044023747284307007, 0.9997856720116889628341744, 0.9998444384611711916084367, 0.9998938032169419878731474, 0.9999337658606177711221103, 0.9999643261538894550943330, 0.9999854843850284447675914, 0.9999972450545584403516182}; const double FuncFCJAsymm::w1024[]= {0.0030664603092439082115513, 0.0030664314747171934849726, 0.0030663738059349007324470, 0.0030662873034393008056861, 0.0030661719680437936084028, 0.0030660278008329004477528, 0.0030658548031622538363679, 0.0030656529766585847450783, 0.0030654223232197073064431, 0.0030651628450145009692318, 0.0030648745444828901040266, 0.0030645574243358210601357, 0.0030642114875552366740338, 0.0030638367373940482295700, 0.0030634331773761048702058, 0.0030630008112961604635720, 0.0030625396432198379186545, 0.0030620496774835909559465, 0.0030615309186946633309249, 0.0030609833717310455112352, 0.0030604070417414288079918, 0.0030598019341451569616257, 0.0030591680546321751827342, 0.0030585054091629766484119, 0.0030578140039685464545661, 0.0030570938455503030247440, 0.0030563449406800369760227, 0.0030555672963998474425352, 0.0030547609200220758572342, 0.0030539258191292371925135, 0.0030530620015739486603347, 0.0030521694754788558725307, 0.0030512482492365564619779, 0.0030502983315095211653578, 0.0030493197312300123682482, 0.0030483124576000001133114, 0.0030472765200910755723677, 0.0030462119284443619831693, 0.0030451186926704230517109, 0.0030439968230491688209395, 0.0030428463301297590067471, 0.0030416672247305038021562, 0.0030404595179387621506312, 0.0030392232211108374894710, 0.0030379583458718709642643, 0.0030366649041157321154111, 0.0030353429080049070377385, 0.0030339923699703840142628, 0.0030326133027115366251721, 0.0030312057191960043331307, 0.0030297696326595705460252, 0.0030283050566060381583022, 0.0030268120048071025720655, 0.0030252904913022221991274, 0.0030237405303984864452325, 0.0030221621366704811776946, 0.0030205553249601516777118, 0.0030189201103766630786495, 0.0030172565082962582916016, 0.0030155645343621134195681, 0.0030138442044841906616068, 0.0030120955348390887083441, 0.0030103185418698906302495, 0.0030085132422860092601062, 0.0030066796530630300711306, 0.0030048177914425515522176, 0.0030029276749320230818149, 0.0030010093213045803019478, 0.0029990627485988779939449, 0.0029970879751189204574353, 0.0029950850194338893942123, 0.0029930539003779692985814, 0.0029909946370501703558363, 0.0029889072488141488505262, 0.0029867917552980250862041, 0.0029846481763941988183689, 0.0029824765322591622023349, 0.0029802768433133102577897, 0.0029780491302407488518214, 0.0029757934139891002022209, 0.0029735097157693059028890, 0.0029711980570554274731990, 0.0029688584595844444331918, 0.0029664909453560499065010, 0.0029640955366324437529314, 0.0029616722559381232326340, 0.0029592211260596712038487, 0.0029567421700455418562030, 0.0029542354112058439815854, 0.0029517008731121217846274, 0.0029491385795971332348581, 0.0029465485547546259626151, 0.0029439308229391107008170, 0.0029412854087656322747309, 0.0029386123371095381418860, 0.0029359116331062444843108, 0.0029331833221509998552933, 0.0029304274298986463828860, 0.0029276439822633785324025, 0.0029248330054184994301727, 0.0029219945257961747508486, 0.0029191285700871841705750, 0.0029162351652406703883623, 0.0029133143384638857180205, 0.0029103661172219362530391, 0.0029073905292375236068160, 0.0029043876024906842306667, 0.0029013573652185263120627, 0.0028982998459149642555740, 0.0028952150733304507490135, 0.0028921030764717064173001, 0.0028889638846014470665859, 0.0028857975272381085212091, 0.0028826040341555690560623, 0.0028793834353828694269858, 0.0028761357612039305018167, 0.0028728610421572684947521, 0.0028695593090357078067012, 0.0028662305928860914743281, 0.0028628749250089892305081, 0.0028594923369584031789413, 0.0028560828605414710856927, 0.0028526465278181672904478, 0.0028491833711010012402964, 0.0028456934229547136488796, 0.0028421767161959702837564, 0.0028386332838930533848701, 0.0028350631593655507170153, 0.0028314663761840422592303, 0.0028278429681697845340603, 0.0028241929693943925796601, 0.0028205164141795195677262, 0.0028168133370965340702726, 0.0028130837729661949782821, 0.0028093277568583240752928, 0.0028055453240914762689974, 0.0028017365102326074839556, 0.0027979013510967402185435, 0.0027940398827466267692845, 0.0027901521414924101257281, 0.0027862381638912825390663, 0.0027822979867471417676962, 0.0027783316471102450029635, 0.0027743391822768604783394, 0.0027703206297889167653083, 0.0027662760274336497592617, 0.0027622054132432473587211, 0.0027581088254944918412282, 0.0027539863027083999392661, 0.0027498378836498606195970, 0.0027456636073272705694208, 0.0027414635129921673927833, 0.0027372376401388605206822, 0.0027329860285040598383428, 0.0027287087180665020331547, 0.0027244057490465746667821, 0.0027200771619059379749851, 0.0027157229973471443987056, 0.0027113432963132558499974, 0.0027069380999874587163979, 0.0027025074497926766073634, 0.0026980513873911808464073, 0.0026935699546841987126055, 0.0026890631938115194351518, 0.0026845311471510979446691, 0.0026799738573186563850015, 0.0026753913671672833892344, 0.0026707837197870311237119, 0.0026661509585045101038391, 0.0026614931268824817854798, 0.0026568102687194489357814, 0.0026521024280492437872770, 0.0026473696491406139791397, 0.0026426119764968062894804, 0.0026378294548551481626046, 0.0026330221291866270351630, 0.0026281900446954674651512, 0.0026233332468187060677353, 0.0026184517812257642618999, 0.0026135456938180188319369, 0.0026086150307283703078113, 0.0026036598383208091684657, 0.0025986801631899798721388, 0.0025936760521607427178014, 0.0025886475522877335418257, 0.0025835947108549212540321, 0.0025785175753751632172710, 0.0025734161935897584747222, 0.0025682906134679988291122, 0.0025631408832067177780710, 0.0025579670512298373098703, 0.0025527691661879125638030, 0.0025475472769576743594882, 0.0025423014326415695994010, 0.0025370316825672995489502, 0.0025317380762873559984451, 0.0025264206635785553113127, 0.0025210794944415703629476, 0.0025157146191004603745948, 0.0025103260880021986466869, 0.0025049139518161981960773, 0.0024994782614338353016280, 0.0024940190679679709626349, 0.0024885364227524702745874, 0.0024830303773417197267843, 0.0024775009835101424263432, 0.0024719482932517112531633, 0.0024663723587794599504176, 0.0024607732325249921551741, 0.0024551509671379883737605, 0.0024495056154857109065099, 0.0024438372306525067265426, 0.0024381458659393083172574, 0.0024324315748631324732279, 0.0024266944111565770692147, 0.0024209344287673158020275, 0.0024151516818575909099866, 0.0024093462248037038747545, 0.0024035181121955041103265, 0.0023976673988358756439882, 0.0023917941397402217940673, 0.0023858983901359478493246, 0.0023799802054619417548485, 0.0023740396413680528093376, 0.0023680767537145683786720, 0.0023620915985716886306938, 0.0023560842322189992961374, 0.0023500547111449424606655, 0.0023440030920462853929883, 0.0023379294318275874140606, 0.0023318337876006648123684, 0.0023257162166840538103394, 0.0023195767766024715869239, 0.0023134155250862753614165, 0.0023072325200709195436049, 0.0023010278196964109553481, 0.0022948014823067621287099, 0.0022885535664494426857857, 0.0022822841308748288053830, 0.0022759932345356507817318, 0.0022696809365864386804193, 0.0022633472963829660967620, 0.0022569923734816920218464, 0.0022506162276392008214839, 0.0022442189188116403333494, 0.0022378005071541580875846, 0.0022313610530203356561684, 0.0022249006169616211363732, 0.0022184192597267597736437, 0.0022119170422612227292520, 0.0022053940257066339981005, 0.0021988502714001954820607, 0.0021922858408741102242558, 0.0021857007958550038097087, 0.0021790951982633439377969, 0.0021724691102128581719720, 0.0021658225940099498722195, 0.0021591557121531123157498, 0.0021524685273323410114303, 0.0021457611024285442134846, 0.0021390335005129516400021, 0.0021322857848465214018174, 0.0021255180188793451473363, 0.0021187302662500514289029, 0.0021119225907852072963166, 0.0021050950564987181231273, 0.0020982477275912256713511, 0.0020913806684495044002679, 0.0020844939436458560249764, 0.0020775876179375023304007, 0.0020706617562659762464561, 0.0020637164237565111901030, 0.0020567516857174286800274, 0.0020497676076395242297101, 0.0020427642551954515246552, 0.0020357416942391048895728, 0.0020286999908050000513193, 0.0020216392111076532034194, 0.0020145594215409583780096, 0.0020074606886775631310555, 0.0020003430792682425467160, 0.0019932066602412715667394, 0.0019860514987017956507927, 0.0019788776619311997736447, 0.0019716852173864757651327, 0.0019644742326995879988655, 0.0019572447756768374356240, 0.0019499969142982240274419, 0.0019427307167168074883601, 0.0019354462512580664378677, 0.0019281435864192559230531, 0.0019208227908687633255086, 0.0019134839334454626590447, 0.0019061270831580672642844, 0.0018987523091844809062265, 0.0018913596808711472808775, 0.0018839492677323979370705, 0.0018765211394497986196010, 0.0018690753658714940398285, 0.0018616120170115510799024, 0.0018541311630493004367905, 0.0018466328743286767122991, 0.0018391172213575569552912, 0.0018315842748070976623218, 0.0018240341055110702429247, 0.0018164667844651949558009, 0.0018088823828264733221690, 0.0018012809719125190225581, 0.0017936626232008872833327, 0.0017860274083284027592567, 0.0017783753990904859184165, 0.0017707066674404779358362, 0.0017630212854889641021349, 0.0017553193255030957535871, 0.0017476008599059107299616, 0.0017398659612756523665312, 0.0017321147023450870266539, 0.0017243471560008201813452, 0.0017165633952826110422716, 0.0017087634933826857546100, 0.0017009475236450491562317, 0.0016931155595647951096823, 0.0016852676747874154134422, 0.0016774039431081072989678, 0.0016695244384710795200224, 0.0016616292349688570408253, 0.0016537184068415843295541, 0.0016457920284763272637533, 0.0016378501744063736542136, 0.0016298929193105323938983, 0.0016219203380124312385075, 0.0016139325054798132252838, 0.0016059294968238317366751, 0.0015979113872983442154825, 0.0015898782522992045381361, 0.0015818301673635540527516, 0.0015737672081691112886347, 0.0015656894505334603439125, 0.0015575969704133379579831, 0.0015494898439039192754876, 0.0015413681472381023085203, 0.0015332319567857911038062, 0.0015250813490531776215856, 0.0015169164006820223329593, 0.0015087371884489335424584, 0.0015005437892646454426166, 0.0014923362801732949073323, 0.0014841147383516970308228, 0.0014758792411086194189814, 0.0014676298658840552399621, 0.0014593666902484950408286, 0.0014510897919021973371136, 0.0014427992486744579821480, 0.0014344951385228783230315, 0.0014261775395326321501237, 0.0014178465299157314469528, 0.0014095021880102909474427, 0.0014011445922797915073771, 0.0013927738213123422970256, 0.0013843899538199418218713, 0.0013759930686377377783877, 0.0013675832447232857518263, 0.0013591605611558067629844, 0.0013507250971354436709363, 0.0013422769319825164387192, 0.0013338161451367762689788, 0.0013253428161566586165863, 0.0013168570247185350852537, 0.0013083588506159642151809, 0.0012998483737589411687807, 0.0012913256741731463215379, 0.0012827908319991927650686, 0.0012742439274918727294554, 0.0012656850410194029319476, 0.0012571142530626688591208, 0.0012485316442144679896043, 0.0012399372951787519644928, 0.0012313312867698677125706, 0.0012227136999117975374834, 0.0012140846156373981740056, 0.0012054441150876388205601, 0.0011967922795108381551550, 0.0011881291902619003419159, 0.0011794549288015500353964, 0.0011707695766955663898644, 0.0011620732156140160807669, 0.0011533659273304853455891, 0.0011446477937213110513287, 0.0011359188967648107958214, 0.0011271793185405120501566, 0.0011184291412283803494364, 0.0011096684471080465391373, 0.0011008973185580330843445, 0.0010921158380549794491381, 0.0010833240881728665534171, 0.0010745221515822403144596, 0.0010657101110494342805238, 0.0010568880494357913638046, 0.0010480560496968846800697, 0.0010392141948817375023057, 0.0010303625681320423357186, 0.0010215012526813791214350, 0.0010126303318544325762649, 0.0010037498890662086758941, 0.0009948600078212502888805, 0.0009859607717128519688418, 0.0009770522644222739122264, 0.0009681345697179550890732, 0.0009592077714547255541688, 0.0009502719535730179460261, 0.0009413272000980781811114, 0.0009323735951391753507612, 0.0009234112228888108282347, 0.0009144401676219265933610, 0.0009054605136951127822476, 0.0008964723455458144695262, 0.0008874757476915376906225, 0.0008784708047290547115472, 0.0008694576013336085537138, 0.0008604362222581167813022, 0.0008514067523323745586954, 0.0008423692764622569855308, 0.0008333238796289207169173, 0.0008242706468880048763834, 0.0008152096633688312691343, 0.0008061410142736039032099, 0.0007970647848766078261514, 0.0007879810605234072847989, 0.0007788899266300432158601, 0.0007697914686822300749096, 0.0007606857722345520114971, 0.0007515729229096583980656, 0.0007424530063974587204051, 0.0007333261084543168373926, 0.0007241923149022446178008, 0.0007150517116280949619884, 0.0007059043845827542163241, 0.0006967504197803339882351, 0.0006875899032973623698204, 0.0006784229212719745780188, 0.0006692495599031030193850, 0.0006600699054496667875923, 0.0006508840442297606018626, 0.0006416920626198431946113, 0.0006324940470539251567018, 0.0006232900840227562488244, 0.0006140802600730121876541, 0.0006048646618064809156059, 0.0005956433758792483631993, 0.0005864164890008837132649, 0.0005771840879336241764943, 0.0005679462594915592881427, 0.0005587030905398147360662, 0.0005494546679937357307118, 0.0005402010788180699282026, 0.0005309424100261499182844, 0.0005216787486790752896494, 0.0005124101818848942860548, 0.0005031367967977850677401, 0.0004938586806172365939677, 0.0004845759205872291441124, 0.0004752886039954144966810, 0.0004659968181722957880391, 0.0004567006504904070755681, 0.0004474001883634926336095, 0.0004380955192456860150653, 0.0004287867306306889171352, 0.0004194739100509498966958, 0.0004101571450768429896514, 0.0004008365233158462997325, 0.0003915121324117206363681, 0.0003821840600436882993131, 0.0003728523939256121308821, 0.0003635172218051749865499, 0.0003541786314630598135175, 0.0003448367107121305776064, 0.0003354915473966143456333, 0.0003261432293912849189248, 0.0003167918446006485317858, 0.0003074374809581322877037, 0.0002980802264252762217455, 0.0002887201689909301727620, 0.0002793573966704570567274, 0.0002699919975049447012834, 0.0002606240595604292032823, 0.0002512536709271339139118, 0.0002418809197187298044384, 0.0002325058940716253739001, 0.0002231286821442978268308, 0.0002137493721166826096154, 0.0002043680521896465790359, 0.0001949848105845827899210, 0.0001855997355431850062940, 0.0001762129153274925249194, 0.0001668244382203495280013, 0.0001574343925265138930609, 0.0001480428665748079976500, 0.0001386499487219861751244, 0.0001292557273595155266326, 0.0001198602909254695827354, 0.0001104637279257437565603, 0.0001010661269730276014588, 0.0000916675768613669107254, 0.0000822681667164572752810, 0.0000728679863190274661367, 0.0000634671268598044229933, 0.0000540656828939400071988, 0.0000446637581285753393838, 0.0000352614859871986975067, 0.0000258591246764618586716, 0.0000164577275798968681068, 0.0000070700764101825898713}; /////////////////////////////////////////////////////////////////////// /* The FCJAsymm peakshape is that described in Finger, Cox and Jephcoat (1994) J. Appl. Cryst. vol 27, pp 892-900. */ realt FuncFCJAsymm::dfunc_int(realt twopsi, realt twotheta) const { /* The integral of the FCJ weight function: 0.5(asin((2 cos (twotheta)^2 + 2 sin(twopsi)-2)/|2 sin twopsi - 2|sin(twotheta)) - asin((2 cos (twotheta)^2 - 2 sin(twopsi)-2)/|2 sin twopsi + 2|sin(twotheta)) ) Twotheta and twopsi are in radians. We note that the limit as twopsi -> twotheta is pi/2. Note that callers will need to apply the 1/(2_hl) factor found in the FCJ paper. */ if(twopsi == 0) return 0.0; if(fabs(twopsi - twotheta)<1e-8) return M_PI/2.0; realt stwopsi = sin(twopsi); realt stwoth = sin(twotheta); realt ctwoth = cos(twotheta); return 0.5 * (asin((2.0*ctwoth*ctwoth + 2*stwopsi -2)/(abs(2*stwopsi-2)*stwoth)) - asin((2.0*ctwoth*ctwoth - 2*stwopsi -2)/(abs(2*stwopsi+2)*stwoth))); } static double sq(double a) { return a*a; } void FuncFCJAsymm::more_precomputations() { denom=0.0; radians = M_PI/180.0; cent_rad = av_[1]*radians; realt hfunc_neg, hfunc_pos; // If either of the below give a cosine greater than one, set to 0 // Handle extrema by setting twopsimin to appropriate limit twopsimin = 0.0; if (cent_rad > M_PI/2) twopsimin = M_PI; realt cospsimin = cos(cent_rad)*sqrt(sq(av_[4]+av_[5]) + 1.0); if(fabs(cospsimin)<1.0) twopsimin = acos(cospsimin); twopsiinfl = 0.0; realt cospsiinfl = cos(cent_rad)*sqrt(sq(av_[4]-av_[5]) + 1.0); if(fabs(cospsiinfl)<1.0) twopsiinfl = acos(cospsiinfl); if(av_[4] == 0 && av_[5] == 0) denom = 1.0; else { /* The denominator for the FCJ expression can be calculated analytically. We define it in terms of the integral of the weight function, dfunc_int: denom = 2* min(h_l,s_l) * (pi/2 - dfunc_int (twopsiinfl,twotheta)) + h_l * (v-u) + s_l * (v-u) - (extra_int (twopsiinfl,twotheta) - extra_int (twopsimin,twotheta)) where v = 1/(2h_l) * dfunc_int(twopsiinfl,twotheta) and u = 1/2h_l * dfunc_int(twopsimin,twotheta). extra_int is the integral of 1/cos(psi). */ realt u = 0.5*dfunc_int(twopsimin,cent_rad)/av_[4]; realt v = 0.5*dfunc_int(twopsiinfl,cent_rad)/av_[4]; denom_unscaled = 2.0 * min(av_[5],av_[4]) * (M_PI/(4.0*av_[4]) - v) + (av_[4] + av_[5])* (v - u) - (1.0/(2*av_[4]))*0.5*(log(fabs(sin(twopsiinfl) + 1)) - log(fabs(sin(twopsiinfl)-1)) - log(fabs(sin(twopsimin) + 1)) + log(fabs(sin(twopsimin)-1))); denom = denom_unscaled * 2.0/fabs(cent_rad-twopsimin); //Scale to [-1,1] interval of G-L integration // The following two factors are the analytic derivatives of the integral of D with respect to // h_l and s_l. realt uu = dfunc_int(twopsiinfl,cent_rad); realt vv = dfunc_int(twopsimin,cent_rad); df_dh_factor = (1.0/(2*av_[4]))*(uu - vv) - (1.0/av_[4])*denom_unscaled; if (av_[4] fabs(cos(twopsiinfl))) { weight_neg[pt] = av_[4] + av_[5] - hfunc_neg; } else { weight_neg[pt] = 2 * min(av_[4],av_[5]); } //Weights for positive half of G-L interval weight_neg[pt] = weight_neg[pt]/(2.0*av_[4]*hfunc_neg*abs(cos(delta_n_neg[pt]))); if(fabs(cos(delta_n_pos[pt])) > fabs(cos(twopsiinfl))) { weight_pos[pt] = av_[4] + av_[5] - hfunc_pos; } else { weight_pos[pt] = 2 * min(av_[4],av_[5]); } weight_pos[pt] = weight_pos[pt]/(2.0*av_[4]*hfunc_pos*abs(cos(delta_n_pos[pt]))); // Apply Gauss-Legendre weights weight_pos[pt]*=w1024[pt]; weight_neg[pt]*=w1024[pt]; } } } bool FuncFCJAsymm::get_nonzero_range(double level, realt &left, realt &right) const { if (level == 0) return false; else if (fabs(level) >= fabs(av_[0])) left = right = 0; else { // As for Pseudo-Voigt, allow 4 half-widths for Gaussian realt pvw = av_[2]*(sqrt(fabs(av_[0]/(level*M_PI*av_[2])-1))+4.); //halfwidths for Lorenzian // The first non-zero point occurs when the convoluting PV reaches twopsimin. The // last value occurs when the convoluting PV moves completely past the centre if(av_[1] < 90) { left = twopsimin*180/M_PI - pvw; right = av_[1] + pvw; } else { left = av_[1] - pvw; right = twopsimin*180/M_PI + pvw; } } return true; } //Pseudo-Voigt with scaling factors as used in crystallography. realt FuncFCJAsymm::fcj_psv(realt x, realt location, realt fwhm, realt mixing) const { realt xa1a2 = (location - x) / fwhm; realt ex = exp(- 4.0 * M_LN2 * xa1a2 * xa1a2); ex *= sqrt(4.0*M_LN2/M_PI)/fwhm; realt lor = 2. / (M_PI * fwhm * (1 + 4* xa1a2 * xa1a2)); return (1-mixing) * ex + mixing * lor; } CALCULATE_VALUE_BEGIN(FuncFCJAsymm) realt numer = 0.0; realt fwhm_rad = av_[2]*2*M_PI/180.0; // Fityk uses hwhm, we use fwhm if((av_[4]==0 && av_[5]==0) || cent_rad==M_PI/2) { // Plain PseudoVoigt numer = fcj_psv(x*radians,cent_rad,fwhm_rad, av_[3]); } else { //do the sum over 1024 Gauss-Legendre points for(int pt=0; pt < 512; pt++) { /* Note that the Pseudo-Voight equation for this calculation is that used in powder diffraction, where the coefficients are chosen to give matching width parameters, i.e. only one width parameter is necessary and the width is expressed in degrees (which means a normalised height in degrees */ // negative and positive sides realt psvval = 0.0; psvval = fcj_psv(delta_n_neg[pt],x*radians,fwhm_rad,av_[3]); numer += weight_neg[pt] * psvval; psvval = fcj_psv(delta_n_pos[pt],x*radians,fwhm_rad,av_[3]); numer += weight_pos[pt] * psvval; } } //Radians scale below to make up for fwhm_rad in denominator of PV function CALCULATE_VALUE_END(av_[0]*M_PI/180 * numer/denom) CALCULATE_DERIV_BEGIN(FuncFCJAsymm) realt fwhm_rad = av_[2]*2*M_PI/180.0; realt numer = 0.0; realt hfunc_neg=0.0,hfunc_pos=0.0; //FCJ hfunc for neg, pos regions of G-L integration realt sumWdGdh = 0.0; // derivative with respect to H/L realt sumWdGds = 0.0; // derivative with respect to S/L realt sumWdRdG = 0.0; // sum w_i * dR/dgamma * W(delta,twotheta)/H realt sumWdRde = 0.0 ;// as above with dR/deta realt sumWdRdt = 0.0; // as above with dR/d2theta //do the sum over 1024 points // parameters are height,centre,hwhm,eta (mixing),H/L,S/L // 0 1 2 3 4 5 for(int pt=0; pt < 512; pt++) { for(int side=0;side < 2; side++) { realt xa1a2 = 0.0; if(side == 0) xa1a2 = (x*radians - delta_n_neg[pt]) / fwhm_rad; else xa1a2 = (x*radians - delta_n_pos[pt]) / fwhm_rad ; realt facta = -4.0 * M_LN2 * xa1a2 ; realt ex = exp(facta * xa1a2); ex *= sqrt(4.0*M_LN2/M_PI)/fwhm_rad; realt lor = 2. / (M_PI * fwhm_rad *(1 + 4* xa1a2 * xa1a2)); realt without_height = (1-av_[3]) * ex + av_[3] * lor; realt psvval = av_[0] * without_height; if(side == 0) { numer += weight_neg[pt] * psvval; hfunc_neg = 1/(2.0*av_[4]*sqrt(sq(cos(delta_n_neg[pt]))/sq(cos(cent_rad))-1)); } else if(side == 1) { //So hfunc nonzero numer += weight_pos[pt] * psvval; hfunc_pos = 1.0/(2.0*av_[4]*sqrt(sq(cos(delta_n_pos[pt]))/sq(cos(cent_rad))-1)); } // pseudo-voigt derivatives: first fwhm. The parameter is expressed in // degrees, but our calculations use radians,so we remember to scale at the end. realt dRdg = ex/fwhm_rad * (-1.0 + -2.0*facta*xa1a2); //gaussian part:checked dRdg = av_[0] * ((1-av_[3])* dRdg + av_[3]*(-1.0*lor/fwhm_rad + 16*xa1a2*xa1a2/(M_PI*(fwhm_rad*fwhm_rad))*1.0/sq(1.0+4*xa1a2*xa1a2))); realt dRde = av_[0] * (lor - ex); //with respect to mixing realt dRdtt = -1.0* av_[0] * ((1.0-av_[3])*2.0*ex*facta/fwhm_rad - av_[3]*lor*8*xa1a2/(fwhm_rad*(1+4*xa1a2*xa1a2))); if(side==0) { /* We know that d(FCJ)/d(param) = sum w[i]*dR/d(param) * W/H(delta) */ sumWdRdG += weight_neg[pt] * dRdg; sumWdRde += weight_neg[pt] * dRde; sumWdRdt += weight_neg[pt] * dRdtt; } else { sumWdRdG += weight_pos[pt] * dRdg; sumWdRde += weight_pos[pt] * dRde; sumWdRdt += weight_pos[pt] * dRdtt; } /* The derivative for h_l includes the convolution of dfunc with PV only up to twopsiinfl when s_l < h_l as it is zero above this limit, and likewise for s_l when h_l < s_l. To save program bytes, we keep the same G-L interval and therefore quadrature points. This is defensible as it is equivalent to including the zero valued points in the integration. The derivative for peak "centre" given here ignores the contribution from changes in the weighting function, as it is not possible to numerically integrate the derivative of dfunc that appears in the full expression. It seems to work. */ realt angpt = 0; realt dconvol = 0; if (side == 1) { angpt = cos(delta_n_pos[pt]); dconvol = w1024[pt] * psvval * hfunc_pos / abs(angpt); } else { angpt = cos(delta_n_neg[pt]); dconvol = w1024[pt] * psvval * hfunc_neg / abs(angpt); } if(fabs(angpt) > fabs(cos(twopsiinfl))){ //further from centre than psi_infl sumWdGdh += dconvol; sumWdGds += dconvol; } if(fabs(angpt) < fabs(cos(twopsiinfl))) { //closer to centre than psi_infl if (av_[5] < av_[4]) { // H_L is larger sumWdGds += 2.0* dconvol; } else { // S_L is larger sumWdGdh += 2.0 * dconvol; } } } } // Note that we must scale any numerically integrated terms back to the correct interval // This scale factor cancels for numer/denom, but not for e.g. numer/denom^2 dy_dv[0] = M_PI/180 * numer/(av_[0]*denom); // height derivative(note numer contains height) dy_dv[1] = M_PI*M_PI/(180*180) * sumWdRdt/denom; // peak position in degrees dy_dv[2] = 2*M_PI*M_PI/(180*180) * sumWdRdG/denom; // fwhm/2 is hwhm, in degrees dy_dv[3] = M_PI/180 * sumWdRde/denom; // mixing dy_dv[4] = M_PI/180 * (sumWdGdh/denom - 1.0/av_[4] * numer/denom - df_dh_factor*numer/(denom_unscaled*denom)); // h_l dy_dv[5] = M_PI/180* (sumWdGds/denom - df_ds_factor * numer/(denom*denom_unscaled)); // s_l dy_dx = -1.0*dy_dv[1]; CALCULATE_DERIV_END(M_PI/180 * numer/denom) } // namespace fityk fityk-1.3.1/fityk/f_fcjasym.h000066400000000000000000000034171302634723100161100ustar00rootroot00000000000000// Author: James Hester // Licence: GNU General Public License ver. 2+ // peak shape in Finger, Cox and Jephcoat model, J. Appl. Cryst. (1994) 27, 892 // with some improvements to the original FCJ code's approach to derivative // calculations, see: // J. R. Hester, Improved asymmetric peak parameter refinement, // J. Appl. Cryst. (2013) 46, 1219-1220 // http://dx.doi.org/10.1107/S0021889813016233 // and http://dx.doi.org/10.1107/S0021889813016233/ks5355sup4.txt #ifndef FITYK_F_FCJASYM_H_ #define FITYK_F_FCJASYM_H_ #include "bfunc.h" namespace fityk { class FuncFCJAsymm : public Function { DECLARE_FUNC_OBLIGATORY_METHODS(FCJAsymm, Function) void more_precomputations(); bool get_nonzero_range(double level, realt &left, realt &right) const; bool get_center(realt* a) const { *a = av_[1]; return true; } bool get_height(realt* a) const { *a = av_[0]; return true; } bool get_fwhm(realt* a) const { *a = 2 * fabs(av_[2]); return true; } private: realt dfunc_int(realt angle1, realt angle2) const; realt fcj_psv(realt x, realt location, realt fwhm, realt mixing) const; static const double x100[]; static const double w100[]; static const double x1024[]; static const double w1024[]; realt twopsiinfl; realt twopsimin; realt cent_rad; realt radians; realt delta_n_neg[512]; //same number of points as x1024 and w1024 realt delta_n_pos[512]; realt weight_neg[512]; realt weight_pos[512]; realt denom; //denominator constant for given parameters realt denom_unscaled; //denominator for x-axis in radians realt df_ds_factor; //derivative with respect to denominator realt df_dh_factor; //derivative with respect to denominator }; } // namespace fityk #endif fityk-1.3.1/fityk/fit.cpp000066400000000000000000000533511302634723100152660ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "fit.h" #include #include // Valgrind may not like the way boost::math::erfc_inv is initialized, see // https://svn.boost.org/trac/boost/ticket/10005 // If you get: // terminate called after throwing an instance of // 'boost::exception_detail::clone_impl< // boost::exception_detail::error_info_injector >' // what(): Error in function boost::math::erfc_inv(e, e): Overflow Error // try this ugly workaround. #ifdef VALGRIND_WORKAROUND #include #undef LDBL_MAX_10_EXP // not very correct, but seems harmless - LDBL_MAX_10_EXP is not used much #define LDBL_MAX_10_EXP 799 #include #endif #include #include "logic.h" #include "model.h" #include "data.h" #include "ui.h" #include "numfuncs.h" #include "settings.h" #include "var.h" #include "LMfit.h" #include "CMPfit.h" #include "GAfit.h" #include "NMfit.h" #include "NLfit.h" using namespace std; namespace fityk { int count_points(const vector& datas) { int n = 0; v_foreach (Data*, i, datas) n += (*i)->get_n(); return n; } Fit::Fit(Full *F, const string& m) : name(m), F_(F), evaluations_(0), na_(0), last_refresh_time_(0) { } /// dof = degrees of freedom = (number of points - number of parameters) int Fit::get_dof(const vector& datas) { update_par_usage(datas); int used_parameters = count(par_usage_.begin(), par_usage_.end(), true); return count_points(datas) - used_parameters; } string Fit::get_goodness_info(const vector& datas) { const SettingsMgr *sm = F_->settings_mgr(); const vector& pp = F_->mgr.parameters(); int dof = get_dof(datas); //update_par_usage(datas); realt wssr = compute_wssr(pp, datas, true); return "WSSR=" + sm->format_double(wssr) + " DoF=" + S(dof) + " WSSR/DoF=" + sm->format_double(wssr/dof) + " SSR=" + sm->format_double(compute_wssr(pp, datas, false)) + " R2=" + sm->format_double(compute_r_squared(pp, datas)); } vector Fit::get_covariance_matrix(const vector& datas) { update_par_usage(datas); return MPfit(F_, "").get_covariance_matrix(datas); } vector Fit::get_standard_errors(const vector& datas) { update_par_usage(datas); return MPfit(F_, "").get_standard_errors(datas); } vector Fit::get_confidence_limits(const vector& datas, double level_percent) { vector v = get_standard_errors(datas); int dof = get_dof(datas); double level = 1. - level_percent / 100.; // If Fityk run under valgrind gives // Error in function boost::math::erfc_inv(e, e): Overflow Error // see VALGRIND_WORKAROUND above. boost::math::students_t dist(dof); double t = boost::math::quantile(boost::math::complement(dist, level/2)); vm_foreach (double, i, v) *i *= t; return v; } string Fit::get_cov_info(const vector& datas) { string s; const SettingsMgr *sm = F_->settings_mgr(); vector alpha = get_covariance_matrix(datas); s += "\nCovariance matrix\n "; for (int i = 0; i < na_; ++i) if (par_usage_[i]) s += "\t$" + F_->mgr.gpos_to_var(i)->name; for (int i = 0; i < na_; ++i) { if (par_usage_[i]) { s += "\n$" + F_->mgr.gpos_to_var(i)->name; for (int j = 0; j < na_; ++j) { if (par_usage_[j]) s += "\t" + sm->format_double(alpha[na_*i + j]); } } } return s; } int Fit::compute_deviates(const vector &A, double *deviates) { ++evaluations_; F_->mgr.use_external_parameters(A); //that's the only side-effect int ntot = 0; v_foreach (Data*, i, fitted_datas_) ntot += compute_deviates_for_data(*i, deviates + ntot); return ntot; } //static int Fit::compute_deviates_for_data(const Data* data, double *deviates) { int n = data->get_n(); vector xx = data->get_xx(); vector yy(n, 0.); data->model()->compute_model(xx, yy); for (int j = 0; j < n; ++j) deviates[j] = (data->get_y(j) - yy[j]) / data->get_sigma(j); return n; } realt Fit::compute_wssr(const vector &A, const vector& datas, bool weigthed) { realt wssr = 0; F_->mgr.use_external_parameters(A); //that's the only side-effect v_foreach (Data*, i, datas) { wssr += compute_wssr_for_data(*i, weigthed); } ++evaluations_; return wssr; } //static realt Fit::compute_wssr_for_data(const Data* data, bool weigthed) { int n = data->get_n(); vector xx = data->get_xx(); vector yy(n, 0.); data->model()->compute_model(xx, yy); // using long double, because it does not effect (much) the efficiency // and notably increases the accuracy of WSSR. // If better accuracy is needed, Kahan summation algorithm could be used. long double wssr = 0; for (int j = 0; j < n; j++) { realt dy = data->get_y(j) - yy[j]; if (weigthed) dy /= data->get_sigma(j); wssr += dy * dy; } return wssr; } // R^2 for multiple datasets is calculated with separate mean y for each dataset realt Fit::compute_r_squared(const vector &A, const vector& datas) { realt sum_err = 0, sum_tot = 0, se = 0, st = 0; F_->mgr.use_external_parameters(A); v_foreach (Data*, i, datas) { compute_r_squared_for_data(*i, &se, &st); sum_err += se; sum_tot += st; } return 1 - (sum_err / sum_tot); } //static realt Fit::compute_r_squared_for_data(const Data* data, realt* sum_err, realt* sum_tot) { int n = data->get_n(); vector xx = data->get_xx(); vector yy(n, 0.); data->model()->compute_model(xx, yy); realt ysum = 0; realt ss_err = 0; // Sum of squares of dist. between fitted curve and data for (int j = 0; j < n; j++) { ysum += data->get_y(j) ; realt dy = data->get_y(j) - yy[j]; ss_err += dy * dy ; } realt mean = ysum / n; realt ss_tot = 0; // Sum of squares of distances between mean and data for (int j = 0; j < n; j++) { realt dy = data->get_y(j) - mean; ss_tot += dy * dy; } if (sum_err != NULL) *sum_err = ss_err; if (sum_tot != NULL) *sum_tot = ss_tot; // R^2, formula from // http://en.wikipedia.org/wiki/Coefficient_of_determination return 1 - (ss_err / ss_tot); } //results in alpha and beta void Fit::compute_derivatives(const vector &A, const vector& datas, vector& alpha, vector& beta) { assert (size(A) == na_ && size(alpha) == na_ * na_ && size(beta) == na_); fill(alpha.begin(), alpha.end(), 0.0); fill(beta.begin(), beta.end(), 0.0); F_->mgr.use_external_parameters(A); v_foreach (Data*, i, datas) { compute_derivatives_for(*i, alpha, beta); } // filling second half of alpha[] for (int j = 1; j < na_; j++) for (int k = 0; k < j; k++) alpha[na_ * k + j] = alpha[na_ * j + k]; } //results in alpha and beta //it computes only half of alpha matrix void Fit::compute_derivatives_for(const Data* data, vector& alpha, vector& beta) { // Iterating over points is tiled to limit memory usage. It's also a little // faster than a single loop over all points for large number of points. const int kMaxTileSize = 1024; vector dy_da; for (int tstart = 0; tstart < data->get_n(); tstart += kMaxTileSize) { const int dyn = na_+1; int tsize = min(data->get_n() - tstart, kMaxTileSize); vector xx(tsize); for (int j = 0; j != tsize; ++j) xx[j] = data->get_x(tstart+j); vector yy(tsize, 0.); dy_da.resize(tsize*dyn); fill(dy_da.begin(), dy_da.end(), 0.); data->model()->compute_model_with_derivs(xx, yy, dy_da); for (int i = 0; i != tsize; ++i) { realt inv_sig = 1.0 / data->get_sigma(tstart+i); realt dy_sig = (data->get_y(tstart+i) - yy[i]) * inv_sig; vector::iterator t = dy_da.begin() + i*dyn; // The program spends here a lot of time. // Testing on GCC 4.8 with -O3 on x64 i7 processor: // the first loop (j) is faster when iterating upward, // and the other one (k) is faster downward. // Removing par_usage_ only slows down this loop (!?). for (int j = 0; j != na_; ++j) { if (par_usage_[j] && *(t+j) != 0) { *(t+j) *= inv_sig; for (int k = j; k != -1; --k) //half of alpha[] alpha[na_ * j + k] += *(t+j) * *(t+k); beta[j] += dy_sig * *(t+j); } } } } } // similar to compute_derivatives(), but adjusted for MPFIT interface void Fit::compute_derivatives_mp(const vector &A, const vector& datas, double **derivs, double *deviates) { ++evaluations_; F_->mgr.use_external_parameters(A); int ntot = 0; v_foreach (Data*, i, datas) { ntot += compute_derivatives_mp_for(*i, ntot, derivs, deviates); } } int Fit::compute_derivatives_mp_for(const Data* data, int offset, double **derivs, double *deviates) { int n = data->get_n(); vector xx = data->get_xx(); vector yy(n, 0.); const int dyn = na_+1; vector dy_da(n*dyn, 0.); data->model()->compute_model_with_derivs(xx, yy, dy_da); for (int i = 0; i != n; ++i) deviates[offset+i] = (data->get_y(i) - yy[i]) / data->get_sigma(i); for (int j = 0; j != na_; ++j) if (derivs[j] != NULL) for (int i = 0; i != n; ++i) derivs[j][offset+i] = -dy_da[i*dyn+j] / data->get_sigma(i); return n; } // similar to compute_derivatives(), but adjusted for NLopt interface realt Fit::compute_wssr_gradient(const vector &A, const vector& datas, double *grad) { assert(size(A) == na_); ++evaluations_; F_->mgr.use_external_parameters(A); realt wssr = 0.; fill(grad, grad+na_, 0.0); v_foreach (Data*, i, datas) wssr += compute_wssr_gradient_for(*i, grad); return wssr; } realt Fit::compute_wssr_gradient_for(const Data* data, double *grad) { realt wssr = 0; int n = data->get_n(); vector xx = data->get_xx(); vector yy(n, 0.); const int dyn = na_+1; vector dy_da(n*dyn, 0.); data->model()->compute_model_with_derivs(xx, yy, dy_da); for (int i = 0; i != n; i++) { realt sig = data->get_sigma(i); realt dy_sig = (data->get_y(i) - yy[i]) / sig; wssr += dy_sig * dy_sig; for (int j = 0; j != na_; ++j) //if (par_usage_[j]) grad[j] += -2 * dy_sig * dy_da[i*dyn+j] / sig; } return wssr; } realt Fit::draw_a_from_distribution(int gpos, char distribution, realt mult) { assert (gpos >= 0 && gpos < na_); if (!par_usage_[gpos]) return a_orig_[gpos]; realt dv = 0; switch (distribution) { case 'g': dv = rand_gauss(); break; case 'l': dv = rand_cauchy(); break; case 'b': dv = rand_bool() ? -1 : 1; break; default: // 'u' - uniform dv = rand_1_1(); break; } return F_->mgr.variation_of_a(gpos, dv * mult); } class ComputeUI { public: ComputeUI(UserInterface *ui) : ui_(ui) { ui->hint_ui("busy", "1"); } ~ComputeUI() { ui_->hint_ui("busy", ""); } private: UserInterface *ui_; }; /// initialize and run fitting procedure for not more than max_eval evaluations void Fit::fit(int max_eval, const vector& datas) { // initialization start_time_ = clock(); last_refresh_time_ = time(0); ComputeUI compute_ui(F_->ui()); update_par_usage(datas); fitted_datas_ = datas; a_orig_ = F_->mgr.parameters(); F_->fit_manager()->push_param_history(a_orig_); evaluations_ = 0; fityk::user_interrupt = 0; max_eval_ = (max_eval > 0 ? max_eval : F_->get_settings()->max_wssr_evaluations); int nu = count(par_usage_.begin(), par_usage_.end(), true); F_->msg("Fitting " + S(nu) + " (of " + S(na_) + ") parameters to " + S(count_points(datas)) + " points ..."); initial_wssr_ = compute_wssr(a_orig_, fitted_datas_); best_shown_wssr_ = initial_wssr_; const SettingsMgr *sm = F_->settings_mgr(); if (F_->get_verbosity() >= 1) F_->ui()->mesg("Method: " + name + ". Initial WSSR=" + sm->format_double(initial_wssr_)); // here the work is done vector best_a; realt wssr = run_method(&best_a); // finalization F_->msg(name + ": " + S(evaluations_) + " evaluations, " + format1("%.2f", elapsed()) + " s. of CPU time."); if (wssr < initial_wssr_) { F_->fit_manager()->push_param_history(best_a); F_->mgr.put_new_parameters(best_a); double percent_change = (wssr - initial_wssr_) / initial_wssr_ * 100.; F_->msg("WSSR: " + sm->format_double(wssr) + " (" + S(percent_change) + "%)"); } else { F_->msg("Better fit NOT found (WSSR = " + sm->format_double(wssr) + ", was " + sm->format_double(initial_wssr_) + ")." "\nParameters NOT changed"); F_->mgr.use_external_parameters(a_orig_); if (F_->get_settings()->fit_replot) F_->ui()->draw_plot(UserInterface::kRepaintImmediately); } } // sets na_ and par_usage_ based on F_->mgr and datas void Fit::update_par_usage(const vector& datas) { if (F_->mgr.parameters().empty()) throw ExecuteError("there are no fittable parameters."); if (datas.empty()) throw ExecuteError("No datasets to fit."); na_ = F_->mgr.parameters().size(); par_usage_ = vector(na_, false); for (int idx = 0; idx < na_; ++idx) { int var_idx = F_->mgr.gpos_to_vpos(idx); v_foreach (Data*, i, datas) { if ((*i)->model()->is_dependent_on_var(var_idx)) { par_usage_[idx] = true; break; //go to next idx } } } if (count(par_usage_.begin(), par_usage_.end(), true) == 0) throw ExecuteError("No parametrized functions are used in the model."); } /// checks termination criteria common for all fitting methods bool Fit::common_termination_criteria() const { bool stop = false; if (fityk::user_interrupt) { F_->msg ("Fitting stopped manually."); stop = true; } double max_time = F_->get_settings()->max_fitting_time; if (max_time > 0 && elapsed() >= max_time) { F_->msg("Maximum processor time exceeded."); stop = true; } if (max_eval_ > 0 && evaluations_ >= max_eval_) { F_->msg("Maximum evaluations number reached."); stop = true; } return stop; } void Fit::iteration_plot(const vector &A, realt wssr) { int p = F_->get_settings()->refresh_period; if (p < 0 || (p > 0 && time(0) - last_refresh_time_ < p)) return; if (F_->get_settings()->fit_replot) { F_->mgr.use_external_parameters(A); F_->ui()->draw_plot(UserInterface::kRepaintImmediately); } F_->msg(iteration_info(wssr) + " CPU time: " + format1("%.2f", elapsed()) + "s."); F_->ui()->hint_ui("yield", ""); last_refresh_time_ = time(0); } void Fit::output_tried_parameters(const vector& a) { const SettingsMgr *sm = F_->settings_mgr(); string s = "Trying ( "; s.reserve(s.size() + a.size() * 12); // rough guess v_foreach (realt, j, a) s += sm->format_double(*j) + (j+1 == a.end() ? " )" : ", "); F_->ui()->mesg(s); } double Fit::elapsed() const { return (clock() - start_time_) / (double) CLOCKS_PER_SEC; } string Fit::iteration_info(realt wssr) { const SettingsMgr *sm = F_->settings_mgr(); double last_change = (best_shown_wssr_ - wssr) / best_shown_wssr_ * 100; double total_change = (initial_wssr_ - wssr) / initial_wssr_ * 100; string first_char = " "; if (wssr < best_shown_wssr_) { best_shown_wssr_ = wssr; first_char = "*"; } return first_char + " eval: " + S(evaluations_) + "/" + (max_eval_ > 0 ? S(max_eval_) : string("oo")) + " WSSR=" + sm->format_double(wssr) + format1(" (%+.3g%%,", last_change) + format1(" total %+.3g%%)", total_change) + format1(" CPU: %.2fs.", elapsed()); } //------------------------------------------------------------------- // keep sync with to FitManager ctor const char* FitManager::method_list[][3] = { { "levenberg_marquardt", "Lev-Mar (own)", "Levenberg-Marquardt" }, { "mpfit", "Lev-Mar (from MPFIT)", "Levenberg-Marquardt" }, #if HAVE_LIBNLOPT { "nlopt_nm", "Nelder-Mead (from NLopt)","Nelder-Mead Simplex" }, { "nlopt_lbfgs", "BFGS (from NLopt)", "L-BFGS" }, { "nlopt_var2", "VAR2 (from NLopt)", "shifted limited-memory variable-metric" }, { "nlopt_praxis", "PRAXIS (from NLopt)", "principal-axis method" }, { "nlopt_bobyqa", "BOBYQA (from NLopt)", "Bound Optimization BY Quadratic Approx." }, { "nlopt_sbplx", "Sbplx (from NLopt)", "(based on Subplex)" }, //{ "nlopt_crs2", "CRS2 (from NLopt)", "Controlled Random Search" }, //{ "nlopt_slsqp", "SLSQP (from NLopt)", "sequential quadratic programming" }, //{ "nlopt_mma", "MMA (from NLopt)", "Method of Moving Asymptotes" }, //{ "nlopt_cobyla", "COBYLA (from NLopt)", // "Constrained Optimization BY Linear Approx." }, #endif { "nelder_mead_simplex", "Nelder-Mead Simplex", "(own implementation)" }, { "genetic_algorithms", "Genetic Algorithm", "(not really maintained)" }, { NULL, NULL } }; FitManager::FitManager(Full *F_) : ParameterHistoryMgr(F_), dirty_error_cache_(true) { // these methods correspond to method_list[] methods_.push_back(new LMfit(F_, next_method())); methods_.push_back(new MPfit(F_, next_method())); #if HAVE_LIBNLOPT methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_NELDERMEAD)); methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_LBFGS)); methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_VAR2)); methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_PRAXIS)); methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_BOBYQA)); methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_SBPLX)); //methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_MMA)); //methods_.push_back(new NLfit(F_, next_method(), NLOPT_LD_SLSQP)); //methods_.push_back(new NLfit(F_, next_method(), NLOPT_LN_COBYLA)); //methods_.push_back(new NLfit(F_, next_method(), NLOPT_GN_CRS2_LM)); #endif methods_.push_back(new NMfit(F_, next_method())); methods_.push_back(new GAfit(F_, next_method())); } FitManager::~FitManager() { purge_all_elements(methods_); } Fit* FitManager::get_method(const string& name) const { v_foreach(Fit*, i, methods_) if ((*i)->name == name) return *i; throw ExecuteError("fitting method `" + name + "' not available."); return NULL; // avoid compiler warning } double FitManager::get_standard_error(const Variable* var) const { if (!var->is_simple()) return -1.; // value signaling unknown standard error if (dirty_error_cache_ || errors_cache_.size() != F_->mgr.parameters().size()) { errors_cache_ = F_->get_fit()->get_standard_errors(F_->dk.datas()); } return errors_cache_[var->gpos()]; } /// loads vector of parameters from the history /// "relative" is used for undo/redo commands /// if history is not empty and current parameters are different from /// the ones pointed by param_hist_ptr_ (but have the same size), /// load_param_history(-1, true), i.e undo, will load the parameters /// pointed by param_hist_ptr_ void ParameterHistoryMgr::load_param_history(int item_nr, bool relative) { if (item_nr == -1 && relative && !param_history_.empty() && //undo param_history_[param_hist_ptr_] != F_->mgr.parameters()) item_nr = 0; // load parameters from param_hist_ptr_ if (relative) item_nr += param_hist_ptr_; else if (item_nr < 0) item_nr += param_history_.size(); if (item_nr < 0 || item_nr >= size(param_history_)) throw ExecuteError("There is no parameter history item #" + S(item_nr) + "."); F_->mgr.put_new_parameters(param_history_[item_nr]); param_hist_ptr_ = item_nr; } bool ParameterHistoryMgr::can_undo() const { return !param_history_.empty() && (param_hist_ptr_ > 0 || param_history_[0] != F_->mgr.parameters()); } bool ParameterHistoryMgr::push_param_history(const vector& aa) { param_hist_ptr_ = param_history_.size() - 1; if (param_history_.empty() || param_history_.back() != aa) { param_history_.push_back(aa); ++param_hist_ptr_; return true; } else return false; } string ParameterHistoryMgr::param_history_info() const { string s = "Parameter history contains " + S(param_history_.size()) + " items."; if (!param_history_.empty()) s += " Now at #" + S(param_hist_ptr_); return s; } } // namespace fityk fityk-1.3.1/fityk/fit.h000066400000000000000000000136111302634723100147260ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_FIT_H_ #define FITYK_FIT_H_ #include #include #include #include "common.h" namespace fityk { class Data; class Full; class Variable; int count_points(const std::vector& datas); /// interface of fitting method and implementation of common functions class FITYK_API Fit { public: const std::string name; Fit(Full *F, const std::string& m); virtual ~Fit() {} void fit(int max_iter, const std::vector& datas); std::string get_goodness_info(const std::vector& datas); int get_dof(const std::vector& datas); std::string get_cov_info(const std::vector& datas); virtual std::vector get_covariance_matrix(const std::vector& datas); virtual std::vector get_standard_errors(const std::vector& datas); std::vector get_confidence_limits(const std::vector& datas, double level_percent); //const std::vector& get_last_dm() const { return fitted_datas_; } static realt compute_wssr_for_data (const Data* data, bool weigthed); static int compute_deviates_for_data(const Data* data, double *deviates); // called from GUI realt compute_wssr(const std::vector &A, const std::vector& datas, bool weigthed=true); // calculate objective function and its gradient (derivatives) // pre: update_par_usage() realt compute_wssr_gradient(const std::vector &A, const std::vector& datas, double *grad); static realt compute_r_squared_for_data(const Data* data, realt* sum_err, realt* sum_tot); realt compute_r_squared(const std::vector &A, const std::vector& datas); bool is_param_used(int n) const { return par_usage_[n]; } protected: Full *F_; std::vector fitted_datas_; int evaluations_; // zeroed in fit() initialization, ++'ed in other places realt initial_wssr_; // set (only) at the beginning of fit() std::vector a_orig_; int na_; ///number of fitted parameters, equal to par_usage_.size() // getters, see the comments below for the variables int max_eval() const { return max_eval_; } const std::vector& par_usage() const { return par_usage_; } virtual double run_method(std::vector* best_a) = 0; std::string iteration_info(realt wssr); // changes best_shown_wssr_ bool common_termination_criteria() const; void compute_derivatives(const std::vector &A, const std::vector& datas, std::vector& alpha, std::vector& beta); void compute_derivatives_mp(const std::vector &A, const std::vector& datas, double **derivs, double *deviates); int compute_deviates(const std::vector &A, double *deviates); realt draw_a_from_distribution(int gpos, char distribution = 'u', realt mult = 1.); void iteration_plot(const std::vector &A, realt wssr); void output_tried_parameters(const std::vector& a); void update_par_usage(const std::vector& datas); private: int max_eval_; // it is set before calling run_method() time_t last_refresh_time_; clock_t start_time_; std::vector par_usage_; realt best_shown_wssr_; // for iteration_info() double elapsed() const; // CPU time elapsed since the start of fit() // compute_*_for() does the same as compute_*() but for one dataset void compute_derivatives_for(const Data *data, std::vector& alpha, std::vector& beta); int compute_derivatives_mp_for(const Data* data, int offset, double **derivs, double *deviates); realt compute_wssr_gradient_for(const Data* data, double *grad); }; /// handles parameter history class FITYK_API ParameterHistoryMgr { public: ParameterHistoryMgr(Full *F) : F_(F), param_hist_ptr_(0) {} bool push_param_history(const std::vector& aa); void clear_param_history() { param_history_.clear(); param_hist_ptr_ = 0; } int get_param_history_size() const { return param_history_.size(); } void load_param_history(int item_nr, bool relative); bool has_param_history_rel_item(int rel_nr) const { return is_index(param_hist_ptr_ + rel_nr, param_history_); } bool can_undo() const; std::string param_history_info() const; const std::vector& get_item(int n) const {return param_history_[n];} int get_active_nr() const { return param_hist_ptr_; } protected: Full *F_; private: std::vector > param_history_; /// old parameter vectors int param_hist_ptr_; /// points to the current/last parameter vector }; /// gives access to fitting methods, enables swithing between them /// also stores parameter history class FITYK_API FitManager : public ParameterHistoryMgr { public: static const char* method_list[][3]; FitManager(Full *F_); ~FitManager(); Fit* get_method(const std::string& name) const; const std::vector& methods() const { return methods_; } double get_standard_error(const Variable* var) const; void outdated_error_cache() { dirty_error_cache_ = true; } private: std::vector methods_; mutable std::vector errors_cache_; bool dirty_error_cache_; const char* next_method() { return method_list[methods_.size()][0]; } DISALLOW_COPY_AND_ASSIGN(FitManager); }; } // namespace fityk #endif fityk-1.3.1/fityk/fityk.cpp000066400000000000000000000340301302634723100156230ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// implementation of libfityk public API #define BUILDING_LIBFITYK #define FITYK_DECLARE_C_API #include "fityk.h" #include #include #include "common.h" #include "ui.h" #include "logic.h" #include "data.h" #include "model.h" #include "fit.h" #include "func.h" #include "info.h" #include "settings.h" using namespace std; #define CATCH_EXECUTE_ERROR \ catch (ExecuteError& e) { \ last_error_ = string("ExecuteError: ") + e.what(); \ if (throws_) \ throw; \ } #define CATCH_SYNTAX_ERROR \ catch (SyntaxError& e) { \ last_error_ = string("SyntaxError: ") + e.what(); \ if (throws_) \ throw; \ } // not thread-safe, but let's keep it simple static FILE* message_sink_ = NULL; namespace { using namespace fityk; void write_message_to_file(UserInterface::Style style, string const& s) { if (message_sink_ && style != UserInterface::kInput) fprintf(message_sink_, "%s\n", s.c_str()); } realt get_wssr_or_ssr(const Full* priv, int dataset, bool weigthed) { if (dataset == ALL_DATASETS) { realt result = 0; for (int i = 0; i < priv->dk.count(); ++i) result += Fit::compute_wssr_for_data(priv->dk.data(i), weigthed); return result; } else { return Fit::compute_wssr_for_data(priv->dk.data(dataset), weigthed); } } vector get_datasets_(Full* priv, int dataset) { vector dd; if (dataset == ALL_DATASETS) { for (int i = 0; i < priv->dk.count(); ++i) dd.push_back(priv->dk.data(i)); } else { dd.push_back(priv->dk.data(dataset)); } return dd; } int hd(Full* priv, int dataset) { return dataset == DEFAULT_DATASET ? priv->dk.default_idx() : dataset; } } // anonymous namespace namespace fityk { string RealRange::str() const { string s; if (!lo_inf() || !hi_inf()) s = " [" + (lo_inf() ? string() : eS(lo)) + ":" + (hi_inf() ? string() : eS(hi)) + "]"; return s; } Point::Point() : x(0), y(0), sigma(1), is_active(true) {} Point::Point(realt x_, realt y_) : x(x_), y(y_), sigma(1), is_active(true) {} Point::Point(realt x_, realt y_, realt sigma_) : x(x_), y(y_), sigma(sigma_), is_active(true) {} string Point::str() const { return "(" + S(x) + "; " + S(y) + "; " + S(sigma) + (is_active ? ")*" : ") "); } struct FitykInternalData { bool owns; UiApi::t_show_message_callback* old_message_callback; }; Fityk::Fityk() : throws_(true), p_(new FitykInternalData) { priv_ = new Full; p_->owns = true; p_->old_message_callback = NULL; } Fityk::Fityk(Full* F) : throws_(true), p_(new FitykInternalData) { priv_ = F; p_->owns = false; p_->old_message_callback = NULL; } Fityk::~Fityk() { if (p_->owns) delete priv_; delete p_; } void Fityk::execute(string const& s) throw(SyntaxError, ExecuteError, ExitRequestedException) { try { priv_->parse_and_execute_line(s); } CATCH_SYNTAX_ERROR CATCH_EXECUTE_ERROR } string Fityk::get_info(string const& s, int dataset) throw(SyntaxError, ExecuteError) { try { string result; parse_and_eval_info(priv_, s, hd(priv_, dataset), result); return result; } CATCH_SYNTAX_ERROR CATCH_EXECUTE_ERROR return ""; } realt Fityk::calculate_expr(string const& s, int dataset) throw(SyntaxError, ExecuteError) { try { Lexer lex(s.c_str()); ExpressionParser ep(priv_); int d = hd(priv_, dataset); ep.parse_expr(lex, d); return ep.calculate(0, priv_->dk.data(d)->points()); } CATCH_SYNTAX_ERROR CATCH_EXECUTE_ERROR return 0.; } int Fityk::get_dataset_count() const { return priv_->dk.count(); } int Fityk::get_default_dataset() const { return priv_->dk.default_idx(); } int Fityk::get_parameter_count() const { return priv_->mgr.parameters().size(); } const vector& Fityk::all_parameters() const { return priv_->mgr.parameters(); } vector Fityk::all_variables() const { const vector& variables = priv_->mgr.variables(); return vector(variables.begin(), variables.end()); } vector Fityk::all_functions() const { const vector& functions = priv_->mgr.functions(); return vector(functions.begin(), functions.end()); } const Func* Fityk::get_function(const std::string& name) const { if (name.empty()) return NULL; int n = priv_->mgr.find_function_nr(name[0] == '%' ? name.substr(1) : name); if (n == -1) return NULL; return priv_->mgr.functions()[n]; } vector Fityk::get_components(int dataset, char fz) throw(ExecuteError) { const Model *model = priv_->dk.get_model(hd(priv_, dataset)); const vector& indexes = model->get_fz(fz).idx; const vector& functions = priv_->mgr.functions(); vector ret(indexes.size()); for (size_t i = 0; i != indexes.size(); ++i) ret[i] = functions[indexes[i]]; return ret; } realt Fityk::get_model_value(realt x, int dataset) throw(ExecuteError) { try { return priv_->dk.get_model(hd(priv_, dataset))->value(x); } CATCH_EXECUTE_ERROR return 0.; } vector Fityk::get_model_vector(vector const& x, int dataset) throw(ExecuteError) { vector xx(x); vector yy(x.size(), 0.); try { priv_->dk.get_model(hd(priv_, dataset))->compute_model(xx, yy); } CATCH_EXECUTE_ERROR return yy; } const Var* Fityk::get_variable(string const& name) throw(ExecuteError) { try { string vname; if (name.empty()) throw ExecuteError("get_variable() called with empty name"); else if (name[0] == '$') vname = string(name, 1); else if (name[0] == '%' && name.find('.') < name.size() - 1) { string::size_type pos = name.find('.'); Function const* f = priv_->mgr.find_function(name.substr(1, pos-1)); string pname = name.substr(pos+1); vname = f->used_vars().get_name(f->get_param_nr(pname)); } else vname = name; return priv_->mgr.find_variable(vname); } CATCH_EXECUTE_ERROR return NULL; // avoid compiler warning } double Fityk::get_view_boundary(char side) { switch (side) { case 'L': return priv_->view.left(); case 'R': return priv_->view.right(); case 'T': return priv_->view.top(); case 'B': return priv_->view.bottom(); default: return 0.; } } void Fityk::load(LoadSpec const& spec, int dataset) throw(ExecuteError) { if (dataset == DEFAULT_DATASET) dataset = priv_->dk.default_idx(); try { bool new_dataset = (dataset < 0); priv_->dk.do_import_dataset(new_dataset, dataset, spec, priv_, priv_->mgr); } CATCH_EXECUTE_ERROR } void Fityk::load_data(int dataset, vector const& x, vector const& y, vector const& sigma, string const& title) throw(ExecuteError) { try { priv_->dk.data(dataset)->load_arrays(x, y, sigma, title); } CATCH_EXECUTE_ERROR } void Fityk::add_point(realt x, realt y, realt sigma, int dataset) throw(ExecuteError) { try { priv_->dk.data(hd(priv_, dataset))->add_one_point(x, y, sigma); } CATCH_EXECUTE_ERROR } vector const& Fityk::get_data(int dataset) throw(ExecuteError) { static const vector empty; try { return priv_->dk.data(hd(priv_, dataset))->points(); } CATCH_EXECUTE_ERROR return empty; } void Fityk::redir_messages(FILE *stream) { if (stream) { UiApi::t_show_message_callback* old = priv_->ui()->connect_show_message(write_message_to_file); if (old != write_message_to_file) p_->old_message_callback = old; } else { // note: if redir_messages() is used for the first time, // p_->old_message_callback is NULL and the output is just disabled p_->old_message_callback = priv_->ui()->connect_show_message(p_->old_message_callback); } message_sink_ = stream; } void Fityk::set_option_as_string(const string& opt, const string& val) throw(ExecuteError) { priv_->mutable_settings_mgr()->set_as_string(opt, val); } void Fityk::set_option_as_number(const string& opt, double val) throw(ExecuteError) { priv_->mutable_settings_mgr()->set_as_number(opt, val); } string Fityk::get_option_as_string(const string& opt) const throw(ExecuteError) { return priv_->settings_mgr()->get_as_string(opt, /*quote_str=*/false); } double Fityk::get_option_as_number(const string& opt) const throw(ExecuteError) { return priv_->settings_mgr()->get_as_number(opt); } void Fityk::out(string const& s) const { priv_->ui()->output_message(UserInterface::kNormal, s); } string Fityk::input(string const& prompt) { return priv_->ui()->get_input_from_user(prompt); } realt Fityk::get_wssr(int dataset) throw(ExecuteError) { try { return get_wssr_or_ssr(priv_, dataset, true); } CATCH_EXECUTE_ERROR return 0.; } realt Fityk::get_ssr(int dataset) throw(ExecuteError) { try { return get_wssr_or_ssr(priv_, dataset, false); } CATCH_EXECUTE_ERROR return 0.; } realt Fityk::get_rsquared(int dataset) throw(ExecuteError) { try { if (dataset == ALL_DATASETS) { realt result = 0; for (int i = 0; i < priv_->dk.count(); ++i) result += Fit::compute_r_squared_for_data(priv_->dk.data(i), NULL, NULL); return result; } else { return Fit::compute_r_squared_for_data(priv_->dk.data(dataset), NULL, NULL); } } CATCH_EXECUTE_ERROR return 0.; } int Fityk::get_dof(int dataset) throw(ExecuteError) { try { return priv_->get_fit()->get_dof(get_datasets_(priv_, dataset)); } CATCH_EXECUTE_ERROR return 0; } vector > Fityk::get_covariance_matrix(int dataset) throw(ExecuteError) { try { vector dss = get_datasets_(priv_, dataset); vector c = priv_->get_fit()->get_covariance_matrix(dss); //reshape size_t na = priv_->mgr.parameters().size(); assert(c.size() == na * na); vector > r(na); for (size_t i = 0; i != na; ++i) r[i] = vector(c.begin() + i*na, c.begin() + i*(na+1)); return r; } CATCH_EXECUTE_ERROR return vector >(); } realt* Fityk::get_covariance_matrix_as_array(int dataset) { try { vector dss = get_datasets_(priv_, dataset); vector c = priv_->get_fit()->get_covariance_matrix(dss); realt* array = (realt*) malloc(c.size() * sizeof(realt)); if (array != NULL) for (size_t i = 0; i != c.size(); ++i) array[i] = c[i]; return array; } CATCH_EXECUTE_ERROR return NULL; } UiApi* Fityk::get_ui_api() { return priv_->ui(); } void Fityk::process_cmd_line_arg(const string& arg) { priv_->process_cmd_line_arg(arg); } } //namespace fityk // C API, not recommended for use in C++ and other languages using fityk::Fityk; extern "C" { Fityk* fityk_create() { Fityk *f = new Fityk; f->set_throws(false); return f; } void fityk_delete(Fityk *f) { delete f; } bool fityk_execute(Fityk *f, const char* command) { try { f->execute(command); } catch(ExitRequestedException) { return false; } return true; } void fityk_load_data(Fityk *f, int dataset, double *x, double *y, double *sigma, int num, const char* title) { f->load_data(dataset, vector(x, x+num), vector(y, y+num), vector(sigma, sigma+num), title); } const char* fityk_last_error(const Fityk *f) { if (f->last_error().empty()) return NULL; return f->last_error().c_str(); } void fityk_clear_last_error(Fityk *f) { f->clear_last_error(); } char* fityk_get_info(Fityk *f, const char *s, int dataset) { const string info = f->get_info(s, dataset); char* ret = (char*) malloc(info.size() + 1); strcpy(ret, info.c_str()); return ret; } realt fityk_calculate_expr(Fityk *f, const char* s, int dataset) { return f->calculate_expr(s, dataset); } int fityk_get_dataset_count(const Fityk *f) { return f->get_dataset_count(); } int fityk_get_parameter_count(const Fityk* f) { return f->get_parameter_count(); } const Point* fityk_get_data_point(Fityk *f, int dataset, int index) { const vector& data = f->get_data(dataset); if (index >= 0 && (size_t) index < data.size()) return &data[index]; else return NULL; } realt fityk_get_model_value(Fityk *f, realt x, int dataset) { return f->get_model_value(x, dataset); } realt fityk_get_wssr(Fityk *f, int dataset) { return f->get_wssr(dataset); } realt fityk_get_ssr(Fityk *f, int dataset) { return f->get_ssr(dataset); } realt fityk_get_rsquared(Fityk *f, int dataset) { return f->get_rsquared(dataset); } int fityk_get_dof(Fityk *f, int dataset) { return f->get_dof(dataset); } realt* fityk_get_covariance_matrix(Fityk *f, int dataset) { return f->get_covariance_matrix_as_array(dataset); } } // extern "C" fityk-1.3.1/fityk/fityk.h000066400000000000000000000322501302634723100152720ustar00rootroot00000000000000/* This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr * Licence: GNU General Public License ver. 2+ */ #ifndef FITYK_FITYK_H_ #define FITYK_FITYK_H_ /* set precision used for storing data and fitting functions */ #define USE_LONG_DOUBLE 0 #if USE_LONG_DOUBLE typedef long double realt; # define REALT_LENGTH_MOD "L" #else typedef double realt; # define REALT_LENGTH_MOD "" #endif /* FITYK_API marks classes and functions visible in Windows DLL */ #if defined(_WIN32) && (defined(LIBFITYK_DLL) || defined(DLL_EXPORT)) # if defined(BUILDING_LIBFITYK) # define FITYK_API __declspec(dllexport) # else # define FITYK_API __declspec(dllimport) # endif #else # if __GNUC__-0 >= 4 # define FITYK_API __attribute__ ((visibility ("default"))) # else # define FITYK_API # endif #endif #ifdef __cplusplus #include #include #include #include #include namespace fityk { // C++ exception specifications are used by SWIG bindings. // They are deprecated (in this form) in C++-11. #ifdef _MSC_VER #pragma warning( disable : 4290 ) // C++ exception specification ignored... #endif #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated" #endif /// Public C++ API of libfityk: class Fityk and helpers. /// /// Minimal examples of using libfityk in C++, Python, Lua and Perl are in /// samples/hello.* files. class Full; class UiApi; struct FitykInternalData; /// exception thrown at run-time (when executing parsed command) struct FITYK_API ExecuteError : public std::runtime_error { ExecuteError(const std::string& msg) : runtime_error(msg) {} }; /// syntax error exception struct FITYK_API SyntaxError : public std::invalid_argument { SyntaxError(const std::string& msg="") : invalid_argument(msg) {} }; /// exception thrown to finish the program (on command "quit") struct FITYK_API ExitRequestedException : std::exception { }; /// used for variable domain and for plot borders struct FITYK_API RealRange { double lo, hi; RealRange() : lo(-HUGE_VAL), hi(HUGE_VAL) {} RealRange(double low, double high) : lo(low), hi(high) {} bool lo_inf() const { return lo == -HUGE_VAL; } bool hi_inf() const { return hi == HUGE_VAL; } std::string str() const; }; /// represents $variable /// (public API has only a subset of members) class FITYK_API Var { public: const std::string name; RealRange domain; realt value() const { return value_; } int gpos() const { return gpos_; } bool is_simple() const { return gpos_ != -1; } protected: Var(const std::string &name_, int gpos) : name(name_), gpos_(gpos) {} ~Var() {} int gpos_; /// see description of this class in var.h realt value_; }; /// represents %function /// (public API has only a subset of members) class FITYK_API Func { public: const std::string name; virtual ~Func() {} virtual const std::string& get_template_name() const = 0; virtual std::string get_param(int n) const = 0; virtual const std::string& var_name(const std::string& param) const throw(ExecuteError) = 0; virtual realt get_param_value(const std::string& param) const throw(ExecuteError) = 0; virtual realt value_at(realt x) const = 0; protected: Func(const std::string name_) : name(name_) {} }; /// special dataset magic numbers used only in this API enum { /// all datasets, used to get statistics for all datasets together ALL_DATASETS=-1, /// default dataset (as set by the 'use' command) DEFAULT_DATASET=-2 }; /// data point struct FITYK_API Point { realt x, y, sigma; bool is_active; Point(); Point(realt x_, realt y_); Point(realt x_, realt y_, realt sigma_); std::string str() const; bool operator< (Point const& q) const { return x < q.x; } }; /// the only use of this struct is as an argument to Fityk::load() struct FITYK_API LoadSpec { enum { NN = -10000 }; // not given, default value std::string path; // utf8 (ascii is valid utf8) std::vector blocks; int x_col; int y_col; int sig_col; std::string format; std::string options; LoadSpec() : x_col(NN), y_col(NN), sig_col(NN) {} explicit LoadSpec(std::string const& p) : path(p), x_col(NN), y_col(NN), sig_col(NN) {} }; /// the public API to libfityk class FITYK_API Fityk { public: Fityk(); Fityk(Full* F); ~Fityk(); /// @name execute fityk commands or change data // @{ /// execute command; throws exception on error void execute(std::string const& s) throw(SyntaxError, ExecuteError, ExitRequestedException); /// load data from file (path should be ascii or utf8, col=0 is index) void load(LoadSpec const& spec, int dataset=DEFAULT_DATASET) throw(ExecuteError); void load(std::string const& path, int dataset=DEFAULT_DATASET) throw(ExecuteError) { load(LoadSpec(path), dataset); } /// load data from arrays void load_data(int dataset, std::vector const& x, std::vector const& y, std::vector const& sigma, std::string const& title="") throw(ExecuteError); /// add one data point to dataset void add_point(realt x, realt y, realt sigma, int dataset=DEFAULT_DATASET) throw(ExecuteError); // @} /// @name (alternative to exceptions) handling of program errors // @{ /// If set to false, does not throw exceptions. Default: true. void set_throws(bool state) { throws_ = state; } /// Return error handling mode: true if exceptions are thrown. bool get_throws() const { return throws_; } ///\brief Returns a string with last error or an empty string. /// Useful after calling set_throws(false). See also: clear_last_error(). std::string const& last_error() const { return last_error_; } /// Clear last error message. See also: last_error(). void clear_last_error() { last_error_.clear(); } // @} /// @name settings // @{ void set_option_as_string(const std::string& opt, const std::string& val) throw(ExecuteError); void set_option_as_number(const std::string& opt, double val) throw(ExecuteError); std::string get_option_as_string(const std::string& opt) const throw(ExecuteError); double get_option_as_number(const std::string& opt) const throw(ExecuteError); // @} /// @name input/output // @{ /// redirect output to file or stdout/stderr; called with NULL reverts /// previous call(s). /// Internally uses UiApi::set_show_message(). /// Bugs: can't be used with more than one Fityk instance at the same time. void redir_messages(std::FILE *stream); /// print string in the output of GUI/CLI (useful for embedded Lua) void out(std::string const& s) const; /// query user (useful for embedded Lua) /// If the prompt contains string "[y/n]" the GUI shows Yes/No buttons. std::string input(std::string const& prompt); // @} /// @name get data and informations // @{ /// return output of the info command std::string get_info(std::string const& s, int dataset=DEFAULT_DATASET) throw(SyntaxError, ExecuteError); /// return expression value, similarly to the print command realt calculate_expr(std::string const& s, int dataset=DEFAULT_DATASET) throw(SyntaxError, ExecuteError); //(planned) /// returns dataset titles //std::vector all_datasets() const; //or returns a new class, public API to Data (like Func and Var) //std::vector all_datasets() const; /// returns number of datasets n, always n >= 1 int get_dataset_count() const; /// returns dataset set by the "use" command int get_default_dataset() const; /// get data points std::vector const& get_data(int dataset=DEFAULT_DATASET) throw(ExecuteError); /// returns number of simple-variables (parameters that can be fitted) int get_parameter_count() const; /// returns global array of parameters (values of simple-variables) const std::vector& all_parameters() const; /// returns all $variables std::vector all_variables() const; /// returns variable $name const Var* get_variable(std::string const& name) throw(ExecuteError); /// returns all %functions std::vector all_functions() const; /// returns function with given name ("%" in the name is optional) const Func* get_function(const std::string& name) const; /// returns %functions used in dataset std::vector get_components(int dataset=DEFAULT_DATASET, char fz='F') throw(ExecuteError); /// returns the value of the model for a given dataset at x realt get_model_value(realt x, int dataset=DEFAULT_DATASET) throw(ExecuteError); /// multiple point version of the get_model_value() std::vector get_model_vector(std::vector const& x, int dataset=DEFAULT_DATASET) throw(ExecuteError); /// get coordinates of rectangle set by the plot command /// side is one of L(eft), R(ight), T(op), B(ottom) double get_view_boundary(char side); // @} /// @name get fit statistics // @{ /// get WSSR for given dataset or for all datasets realt get_wssr(int dataset=ALL_DATASETS) throw(ExecuteError); /// get SSR for given dataset or for all datasets realt get_ssr(int dataset=ALL_DATASETS) throw(ExecuteError); /// get R-squared for given dataset or for all datasets realt get_rsquared(int dataset=ALL_DATASETS) throw(ExecuteError); /// get number of degrees-of-freedom for given dataset or for all datasets int get_dof(int dataset=ALL_DATASETS) throw(ExecuteError); /// get covariance matrix (for given dataset or for all datasets) std::vector > get_covariance_matrix(int dataset=ALL_DATASETS) throw(ExecuteError); // @} /// UiApi contains functions used by CLI and may be used to implement /// another user interface. UiApi* get_ui_api(); void process_cmd_line_arg(const std::string& arg); // implementation details (for internal use) Full* priv() { return priv_; } // access to private API realt* get_covariance_matrix_as_array(int dataset); private: Full *priv_; bool throws_; std::string last_error_; FitykInternalData *p_; // members hidden for the sake of API stability // disallow copy and assign Fityk(const Fityk&); void operator=(const Fityk&); }; } // namespace fityk #ifdef __clang__ #pragma clang diagnostic pop #endif #else /* !__cplusplus */ /* C API. * Functions below correspond to member functions of class Fityk. * To check for errors use fityk_last_error(). * bool and Point here should be ABI-compatible with C++ bool and fityk::Point. */ #define bool _Bool typedef struct Fityk_ Fityk; typedef struct { realt x, y, sigma; bool is_active; } Point; #endif /* __cplusplus */ #if !defined(__cplusplus) || defined(FITYK_DECLARE_C_API) #ifdef __cplusplus extern "C" { using fityk::Point; using fityk::Fityk; #endif FITYK_API Fityk* fityk_create(); FITYK_API void fityk_delete(Fityk *f); /* returns false on ExitRequestedException */ FITYK_API bool fityk_execute(Fityk *f, const char* command); FITYK_API void fityk_load_data(Fityk *f, int dataset, double *x, double *y, double *sigma, int num, const char* title); /* returns NULL if no error happened since fityk_clear_last_error() */ FITYK_API const char* fityk_last_error(const Fityk *f); FITYK_API void fityk_clear_last_error(Fityk *f); /* caller is responsible to free() returned string */ FITYK_API char* fityk_get_info(Fityk *f, const char *s, int dataset); FITYK_API realt fityk_calculate_expr(Fityk *f, const char* s, int dataset); FITYK_API int fityk_get_dataset_count(const Fityk *f); FITYK_API int fityk_get_parameter_count(const Fityk* f); /* get data point, returns NULL if index is out of range */ FITYK_API const Point* fityk_get_data_point(Fityk *f, int dataset, int index); FITYK_API realt fityk_get_model_value(Fityk *f, realt x, int dataset); FITYK_API realt fityk_get_wssr(Fityk *f, int dataset); FITYK_API realt fityk_get_ssr(Fityk *f, int dataset); FITYK_API realt fityk_get_rsquared(Fityk *f, int dataset); FITYK_API int fityk_get_dof(Fityk *f, int dataset); /* returns matrix in array, which caller is responsible to free(); */ /* length of the array is parameter_count^2 */ FITYK_API realt* fityk_get_covariance_matrix(Fityk *f, int dataset); #ifdef __cplusplus } // extern "C" #endif #endif #endif /* FITYK_FITYK_H_ */ fityk-1.3.1/fityk/func.cpp000066400000000000000000000161261302634723100154360ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "func.h" #include "common.h" #include "bfunc.h" #include "settings.h" #include "udf.h" using namespace std; namespace fityk { vector Function::bufx_(1); vector Function::bufy_(1); Function::Function(const Settings* settings, const string &name_, const Tplate::Ptr tp, const vector &vars) : Func(name_), used_vars_(vars), settings_(settings), tp_(tp), av_(vars.size()), center_idx_(-1) { } void Function::init() { center_idx_ = index_of_element(tp_->fargs, "center"); if (center_idx_ == -1 && (tp_->traits & Tplate::kSigmoid)) center_idx_ = index_of_element(tp_->fargs, "xmid"); if (av_.size() != tp_->fargs.size()) throw ExecuteError("Function " + tp_->name + " requires " + S(tp_->fargs.size()) + " argument(s), got " + S(av_.size()) + "."); } void Function::do_precomputations(const vector &variables) { //precondition: recalculate() for all variables multi_.clear(); for (int i = 0; i < used_vars_.get_count(); ++i) { const Variable *v = variables[used_vars_.get_idx(i)]; av_[i] = v->value(); v_foreach (Variable::ParMult, j, v->recursive_derivatives()) multi_.push_back(Multi(i, *j)); } this->more_precomputations(); } void Function::erased_parameter(int k) { vm_foreach (Multi, i, multi_) if (i->p > k) -- i->p; } void Function::calculate_value(const vector &x, vector &y) const { realt left, right; double cut_level = settings_->function_cutoff; if (cut_level != 0. && get_nonzero_range(cut_level, left, right)) { int first = lower_bound(x.begin(), x.end(), left) - x.begin(); int last = upper_bound(x.begin(), x.end(), right) - x.begin(); this->calculate_value_in_range(x, y, first, last); } else this->calculate_value_in_range(x, y, 0, x.size()); } realt Function::calculate_value(realt x) const { bufx_[0] = x; bufy_[0] = 0.; calculate_value_in_range(bufx_, bufy_, 0, 1); return bufy_[0]; } void Function::calculate_value_deriv(const vector &x, vector &y, vector &dy_da, bool in_dx) const { realt left, right; double cut_level = settings_->function_cutoff; if (cut_level != 0. && get_nonzero_range(cut_level, left, right)) { int first = lower_bound(x.begin(), x.end(), left) - x.begin(); int last = upper_bound(x.begin(), x.end(), right) - x.begin(); this->calculate_value_deriv_in_range(x, y, dy_da, in_dx, first, last); } else this->calculate_value_deriv_in_range(x, y, dy_da, in_dx, 0, x.size()); } int Function::max_param_pos() const { int n = 0; v_foreach (Multi, j, multi_) n = max(j->p + 1, n); return n; } bool Function::get_center(realt* a) const { if (center_idx_ != -1) { *a = av_[center_idx_]; return true; } return false; } bool Function::get_ibreadth(realt* a) const { realt area, height; if (this->get_area(&area) && this->get_height(&height)) { *a = height != 0. ? area / height : 0.; return true; } return false; } /// return sth like: %f = Linear($foo, $_2) string Function::get_basic_assignment() const { string r = "%" + name + " = " + tp_->name + "("; v_foreach (string, i, used_vars_.names()) r += (i == used_vars_.names().begin() ? "$" : ", $") + *i; r += ")"; return r; } /// return sth like: %f = Linear(a0=$foo, a1=~3.5) string Function::get_current_assignment(const vector &variables, const vector ¶meters) const { vector vs; for (int i = 0; i < used_vars_.get_count(); ++i) { const Variable* v = variables[used_vars_.get_idx(i)]; string t = get_param(i) + "=" + (v->is_simple() ? v->get_formula(parameters) : "$" + v->name); vs.push_back(t); } return "%" + name + " = " + tp_->name + "(" + join_vector(vs, ", ") + ")"; } void Function::replace_symbols_with_values(string &t, const char* num_fmt) const { for (size_t i = 0; i < tp_->fargs.size(); ++i) { const string& symbol = tp_->fargs[i]; string value = format1(num_fmt, av_[i]); // like replace_words(t,symbol,value) but adds () in a^n for a<0 string::size_type pos = 0; while ((pos=t.find(symbol, pos)) != string::npos) { int k = symbol.size(); if ((pos == 0 || !(isalnum(t[pos-1]) || t[pos-1]=='_' || t[pos-1]=='$')) && (pos+k==t.size() || !(isalnum(t[pos+k]) || t[pos+k]=='_'))) { string new_word = value; // rare special case if (pos+k < t.size() && t[pos+k] == '^' && av_[i] < 0) new_word = "("+value+")"; t.replace(pos, k, new_word); pos += new_word.size(); } else pos++; } } } string Function::get_current_formula(const string& x, const char* num_fmt) const { string t; if (contains_element(tp_->rhs, '#')) { t = tp_->name + "("; for (int i = 0; i != nv(); ++i) { string value = format1(num_fmt, av_[i]); t += value; t += (i+1 < nv() ? ", " : ")"); } } else { t = tp_->rhs; replace_symbols_with_values(t, num_fmt); } replace_words(t, "x", x); return t; } int Function::get_param_nr(const string& param) const { int n = index_of_element(tp_->fargs, param); if (n == -1) throw ExecuteError("%" + name + " has no parameter `" + param + "'"); return n; } realt Function::get_param_value(const string& param) const throw(ExecuteError) { realt a; if (!param.empty() && islower(param[0])) return av_[get_param_nr(param)]; else if (param == "Center" && get_center(&a)) { return a; } else if (param == "Height" && get_height(&a)) { return a; } else if (param == "FWHM" && get_fwhm(&a)) { return a; } else if (param == "Area" && get_area(&a)) { return a; } else if (param == "IB" && get_ibreadth(&a)) { return a; } else if (get_other_prop(param, &a)) { return a; } else throw ExecuteError("%" + name + " (" + tp_->name + ") has no parameter `" + param + "'"); } realt Function::numarea(realt x1, realt x2, int nsteps) const { if (nsteps <= 1) return 0.; realt xmin = min(x1, x2); realt xmax = max(x1, x2); realt h = (xmax - xmin) / (nsteps-1); vector xx(nsteps), yy(nsteps); for (int i = 0; i < nsteps; ++i) xx[i] = xmin + i*h; calculate_value(xx, yy); realt a = (yy[0] + yy[nsteps-1]) / 2.; for (int i = 1; i < nsteps-1; ++i) a += yy[i]; return a*h; } } // namespace fityk fityk-1.3.1/fityk/func.h000066400000000000000000000126661302634723100151100ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_FUNC_H_ #define FITYK_FUNC_H_ #include "tplate.h" #include "var.h" namespace fityk { struct Settings; class FITYK_API Function : public Func { public: struct Multi { int p; int n; realt mult; Multi(int n_, const Variable::ParMult& pm) : p(pm.p), n(n_), mult(pm.mult) {} }; Function(const Settings* settings, const std::string &name_, const Tplate::Ptr tp, const std::vector &vars); virtual ~Function() {} virtual void init(); const Tplate::Ptr& tp() const { return tp_; } /// number of variables int nv() const {return tp_->fargs.empty() ? av_.size() : tp_->fargs.size();} /// calculate value at x[i] and _add_ the result to y[i] (for each i) virtual void calculate_value_in_range(const std::vector &x, std::vector &y, int first, int last) const = 0; void calculate_value(const std::vector &x, std::vector &y) const; realt calculate_value(realt x) const; /// wrapper around array version virtual void calculate_value_deriv_in_range(const std::vector &x, std::vector &y, std::vector &dy_da, bool in_dx, int first, int last) const = 0; void calculate_value_deriv(const std::vector &x, std::vector &y, std::vector &dy_da, bool in_dx=false) const; void do_precomputations(const std::vector &variables); virtual void more_precomputations() {} void erased_parameter(int k); virtual bool get_nonzero_range(double /*level*/, realt& /*left*/, realt& /*right*/) const { return false; } virtual bool is_symmetric() const { return false; } virtual bool get_center(realt* a) const; virtual bool get_height(realt* /*a*/) const { return false; } virtual bool get_fwhm(realt* /*a*/) const { return false; } virtual bool get_area(realt* /*a*/) const { return false; } /// integral width := area / height bool get_ibreadth(realt* a) const; /// get list of other properties (e.g. like Lorentzian-FWHM of Voigt) virtual const std::vector& get_other_prop_names() const { static const std::vector empty; return empty; } /// if defined, returns true and sets second parameter to the value virtual bool get_other_prop(const std::string&, realt*) const { return 0; } const std::vector& av() const { return av_; } std::string get_basic_assignment() const; std::string get_current_assignment(const std::vector &variables, const std::vector ¶meters) const; virtual std::string get_current_formula(const std::string& x, const char* num_fmt) const; // VarArgFunction overrides this defintion (that's why value is returned) virtual std::string get_param(int n) const { return is_index(n, tp_->fargs) ? tp_->fargs[n] : std::string(); } int get_param_nr(const std::string& param) const; // C++ exception specifications are used by SWIG bindings. // They are deprecated (in this form) in C++-11. #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated" #endif virtual realt get_param_value(const std::string& param) const throw(ExecuteError); // exc. spec. is used by SWIG realt numarea(realt x1, realt x2, int nsteps) const; virtual std::string get_bytecode() const { return "No bytecode"; } virtual void update_var_indices(const std::vector& variables) { used_vars_.update_indices(variables); } void set_param_name(int n, const std::string &new_p) { used_vars_.set_name(n, new_p); } const IndexedVars& used_vars() const { return used_vars_; } // implementation of members of Func virtual const std::string& get_template_name() const { return tp_->name; } virtual const std::string& var_name(const std::string& param) const throw(ExecuteError) // exc. spec. is used by SWIG { return used_vars_.get_name(get_param_nr(param)); } #ifdef __clang__ #pragma clang diagnostic pop #endif virtual realt value_at(realt x) const { return calculate_value(x); } int max_param_pos() const; realt calculate_value_and_deriv(realt x, std::vector &dy_da) const { bufx_[0] = x, bufy_[0] = 0.; calculate_value_deriv_in_range(bufx_, bufy_, dy_da, false, 0, 1); return bufy_[0]; } protected: void replace_symbols_with_values(std::string &t, const char* num_fmt) const; IndexedVars used_vars_; const Settings* settings_; Tplate::Ptr tp_; /// current values of arguments, /// the vector can be extended by derived classes to store temporary values std::vector av_; std::vector multi_; int center_idx_; private: static std::vector bufx_; static std::vector bufy_; }; } // namespace fityk #endif fityk-1.3.1/fityk/guess.cpp000066400000000000000000000134141302634723100156260ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "guess.h" #include #include #include "common.h" #include "data.h" #include "model.h" #include "settings.h" using namespace std; namespace fityk { const vector Guess::linear_traits = vector3(S("slope"), S("intercept"), S("avgy")); const vector Guess::peak_traits = vector4(S("center"), S("height"), S("hwhm"), S("area")); const vector Guess::sigmoid_traits = vector4(S("lower"), S("upper"), S("xmid"), S("wsig")); void Guess::set_data(const Data* data, const RealRange& range, int ignore_idx) { pair point_indexes = data->get_index_range(range); int len = point_indexes.second - point_indexes.first; assert(len >= 0); if (len == 0) throw ExecuteError("guess: empty range"); xx_.resize(len); for (int j = 0; j != len; ++j) xx_[j] = data->get_x(point_indexes.first + j); if (settings_->guess_uses_weights) { sigma_.resize(len); for (int j = 0; j != len; ++j) sigma_[j] = data->get_sigma(point_indexes.first + j); } yy_.clear(); // just in case yy_.resize(len, 0.); data->model()->compute_model(xx_, yy_, ignore_idx); for (int j = 0; j != len; ++j) yy_[j] = data->get_y(point_indexes.first + j) - yy_[j]; } double Guess::find_hwhm(int pos, double* area) const { const double hm = 0.5 * yy_[pos]; const int n = 3; int left_pos = 0; int right_pos = yy_.size() - 1; // first we search the width of the left side of the peak int counter = 0; for (int i = pos; i > 0; --i) { if (yy_[i] > hm) { if (counter > 0) // previous point had y < hm --counter; // compensate it, it was only fluctuation } else { ++counter; // we found a point below `hm', but we need to find `n' points // below `hm' to be sure that it's not a fluctuation if (counter == n) { left_pos = i + counter; break; } } } // do the same for the right side counter = 0; for (int i = pos; i < right_pos; i++) { if (yy_[i] > hm) { if (counter > 0) counter--; } else { counter++; if (counter == n) { // +1 here is intentionally asymmetric with the left side right_pos = i - counter + 1; break; } } } if (area) { *area = 0; for (int i = left_pos; i < right_pos; ++i) *area += (xx_[i+1] - xx_[i]) * (yy_[i] + yy_[i+1]) / 2; } double hwhm = (xx_[right_pos] - xx_[left_pos]) / 2.; return max(hwhm, epsilon); } // outputs vector with: center, height, hwhm, area // returns values corresponding to peak_traits vector Guess::estimate_peak_parameters() const { // find the highest point, which must be higher than the previous point // and not lower than the next one (-> it cannot be the first/last point) int pos = -1; if (!sigma_.empty()) { for (int i = 1; i < (int) yy_.size() - 1; ++i) { int t = (pos == -1 ? i-1 : pos); if (sigma_[t] * yy_[i] > sigma_[i] * yy_[t] && sigma_[i+1] * yy_[i] >= sigma_[i] * yy_[i+1]) pos = i; } } else { for (int i = 1; i < (int) yy_.size() - 1; ++i) { int t = (pos == -1 ? i-1 : pos); if (yy_[i] > yy_[t] && yy_[i] >= yy_[i+1]) pos = i; } } if (pos == -1) throw ExecuteError("Peak outside of the range."); double height = yy_[pos] * settings_->height_correction; double center = xx_[pos]; double area; double hwhm = find_hwhm(pos, &area) * settings_->width_correction; return vector4(center, height, hwhm, area); } vector Guess::estimate_linear_parameters() const { double sx = 0, sy = 0, sxx = 0, /*syy = 0,*/ sxy = 0; int n = yy_.size(); for (int i = 0; i != n; ++i) { double x = xx_[i]; double y = yy_[i]; sx += x; sy += y; sxx += x*x; //syy += y*y; sxy += x*y; } double slope = (n * sxy - sx * sy) / (n * sxx - sx * sx); double intercept = (sy - slope * sx) / n; double avgy = sy / n; return vector3(slope, intercept, avgy); } // ad-hoc arbitrary procedure to guess initial sigmoid parameters, // with no theoretical justification vector Guess::estimate_sigmoid_parameters() const { double lower; double upper; vector ycopy = yy_; // ignoring 20% lowest and 20% highest points sort(ycopy.begin(), ycopy.end()); if (ycopy.size() < 10) { lower = ycopy.front(); upper = ycopy.back(); } else { lower = ycopy[ycopy.size()/5]; upper = ycopy[ycopy.size()*4/5]; } // fitting ax+b to linearized sigmoid double sx = 0, sy = 0, sxx = 0, sxy = 0; int n = 0; for (size_t i = 0; i != yy_.size(); ++i) { if (yy_[i] <= lower || yy_[i] >= upper) continue; double x = xx_[i]; // normalizing: y -> (y - lower) / (upper - lower); // and y -> -log(1/y-1); double y = -log((upper - lower) / (yy_[i] - lower) - 1.); sx += x; sy += y; sxx += x*x; sxy += x*y; ++n; } double a = (n * sxy - sx * sy) / (n * sxx - sx * sx); double b = (sy - a * sx) / n; //double xmid = (xx_.front() + xx_.back()) / 2.; double xmid = -b/a; //double wsig = (xx_.back() - xx_.front()) / 10.; double wsig = 1/a; return vector4(lower, upper, xmid, wsig); } } // namespace fityk fityk-1.3.1/fityk/guess.h000066400000000000000000000026471302634723100153010ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_GUESS_H_ #define FITYK_GUESS_H_ #include #include #include "fityk.h" // realt, FITYK_API namespace fityk { class Data; struct Settings; /// guessing initial parameters of functions class FITYK_API Guess { public: static const std::vector linear_traits; static const std::vector peak_traits; static const std::vector sigmoid_traits; Guess(Settings const *settings) : settings_(settings) {} /// Use data points with indexes from lb to rb-1, /// substract the current model from the data, (optionally) with exception /// of function that has index `ignore_idx'. /// This exception is used in "Guess %f = ..." if %f is already defined. void set_data(const Data* data, const RealRange& range, int ignore_idx); /// returns values corresponding to linear_traits std::vector estimate_linear_parameters() const; /// returns values corresponding to peak_traits std::vector estimate_peak_parameters() const; /// returns values corresponding to sigmoid_traits std::vector estimate_sigmoid_parameters() const; private: Settings const* settings_; std::vector xx_, yy_, sigma_; double find_hwhm(int pos, double *area) const; }; } // namespace fityk #endif fityk-1.3.1/fityk/info.cpp000066400000000000000000000700431302634723100154340ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ /// Functions to execute commands: info, debug, print. #define BUILDING_LIBFITYK #include "info.h" #include #include #include #include #include //get_version() #include // BOOST_VERSION extern "C" { #ifndef DISABLE_LUA # include // LUA_RELEASE #else # define LUA_RELEASE "disabled" #endif } // is included from common.h #if HAVE_LIBNLOPT # include #endif #include "logic.h" #include "func.h" #include "tplate.h" #include "data.h" #include "fit.h" #include "ast.h" #include "model.h" #include "guess.h" #include "cparser.h" #include "eparser.h" #include "lexer.h" #include "ui.h" #include "runner.h" // args2range using namespace std; namespace fityk { const char* embedded_lua_version() { #ifdef LUA_RELEASE // LUA_RELEASE was added in Lua 5.1.1 return LUA_RELEASE; #else return LUA_VERSION; #endif } // get standard formula and make it parsable by the gnuplot program string& gnuplotize_formula(string& formula) { replace_all(formula, "^", "**"); replace_words(formula, "ln", "log"); // avoid integer division (1/2 == 0) size_t pos = 0; size_t len = formula.length(); while ((pos = formula.find('/', pos)) != string::npos) { pos = formula.find_first_not_of(' ', pos+1); if (pos == string::npos || !isdigit(formula[pos])) continue; while (pos < len && isdigit(formula[pos])) ++pos; if (pos == formula.length() || formula[pos] != '.') formula.insert(pos, "."); } return formula; } void models_as_script(const Full* F, string& r, bool commented_defines) { r += "# ------------ (un)defines ------------"; TplateMgr default_tpm; Parser parser(F); // CommandExecutor.parser() could be used default_tpm.add_builtin_types(&parser); v_foreach (Tplate::Ptr, i, default_tpm.tpvec()) { const Tplate* t = F->get_tpm()->get_tp((*i)->name); if (t == NULL || t->as_formula() != (*i)->as_formula()) r += "\nundefine " + (*i)->name; } v_foreach (Tplate::Ptr, i, F->get_tpm()->tpvec()) { string formula = (*i)->as_formula(); const Tplate* t = default_tpm.get_tp((*i)->name); if (t == NULL || t->as_formula() != formula) r += "\ndefine " + formula; else if (commented_defines) r += "\n# define " + formula; } r += "\n\n# ------------ variables and functions ------------"; // The script must not trigger ModelManager::remove_unreferred() // or ModelManager::auto_remove_functions() until all references // are reproduced. v_foreach (Variable*, i, F->mgr.variables()) r += "\n$" + (*i)->name +" = "+ (*i)->get_formula(F->mgr.parameters()); r += "\n"; v_foreach (Function*, i, F->mgr.functions()) r +="\n" + (*i)->get_basic_assignment(); r += "\n\n# ------------ models ------------"; for (int i = 0; i != F->dk.count(); ++i) { const Model* model = F->dk.get_model(i); const vector& ff = model->get_ff().names; if (!ff.empty()) r += "\n@" + S(i) + ": F = %" + join_vector(ff, " + %"); vector const& zz = model->get_zz().names; if (!zz.empty()) r += "\n@" + S(i) + ": Z = %" + join_vector(zz, " + %"); } } string build_info() { #if HAVE_LIBNLOPT int nl_ver[3]; nlopt_version(&nl_ver[0], &nl_ver[1], &nl_ver[2]); #endif return "Build system type: " #ifdef CONFIGURE_BUILD CONFIGURE_BUILD #else "UNKNOWN" #endif "\nConfigured with: " #ifdef CONFIGURE_ARGS CONFIGURE_ARGS #else "UNKNOWN" #endif "\nCompiler: " #if defined(__GNUC__) "GCC" #elif defined(_MSC_VER) "MSVC++" #else "UNKNOWN" #endif #ifdef __VERSION__ " " __VERSION__ #endif "\nWith libraries: " "\nBoost " + S(BOOST_VERSION / 100000) + "." + S(BOOST_VERSION / 100 % 1000) + "." + S(BOOST_VERSION % 100) + "\nxylib " + xylib_get_version() + "\n" + embedded_lua_version() #if HAVE_LIBNLOPT + "\nNLopt " + S(nl_ver[0]) + "." + S(nl_ver[1]) + "." + S(nl_ver[2]) #endif ; } namespace { string get_variable_info(const Full* F, const Variable* v) { string s = "$" + v->name + " = " + v->get_formula(F->mgr.parameters()) + " = " + F->settings_mgr()->format_double(v->value()) + v->domain.str(); if (ModelManager::is_auto(v->name)) s += " [auto]"; return s; } void info_functions(const Full* F, const string& name, string& result) { if (!contains_element(name, '*')) { const Function *f = F->mgr.find_function(name); result += f->get_basic_assignment(); } else { v_foreach (Function*, i, F->mgr.functions()) if (match_glob((*i)->name.c_str(), name.c_str())) result += (result.empty() ? "" : "\n") + (*i)->get_basic_assignment(); } } void info_variables(const Full* F, const string& name, string& result) { if (!contains_element(name, '*')) { const Variable* var = F->mgr.find_variable(name); result += get_variable_info(F, var); } else { v_foreach (Variable*, i, F->mgr.variables()) if (match_glob((*i)->name.c_str(), name.c_str())) result += (result.empty() ? "" : "\n") + get_variable_info(F, *i); } } void info_func_type(const Full* F, const string& functype, string& result) { const Tplate* tp = F->get_tpm()->get_tp(functype); if (tp == NULL) result += "undefined"; else { result += tp->as_formula(); if (!tp->op_trees.empty()) { vector args = tp->fargs; args.push_back("x"); const char* num_format = F->get_settings()->numeric_format.c_str(); OpTreeFormat fmt = { num_format, &args }; result += "\n = " + tp->op_trees.back()->str(fmt); } } } string info_func_props(const Full* F, const string& name) { const Function* f = F->mgr.find_function(name); string s = f->tp()->as_formula(); for (int i = 0; i < f->used_vars().get_count(); ++i) { Variable const* v = F->mgr.get_variable(f->used_vars().get_idx(i)); s += "\n" + f->get_param(i) + " = " + get_variable_info(F, v); } realt a; const vector& fargs = f->tp()->fargs;; if (f->get_center(&a) && !contains_element(fargs, string("center"))) s += "\nCenter: " + S(a); if (f->get_height(&a) && !contains_element(fargs, string("height"))) s += "\nHeight: " + S(a); if (f->get_fwhm(&a) && !contains_element(fargs, string("fwhm"))) s += "\nFWHM: " + S(a); if (f->get_area(&a) && !contains_element(fargs, string("area"))) s += "\nArea: " + S(a); v_foreach (string, i, f->get_other_prop_names()) { f->get_other_prop(*i, &a); s += "\n" + *i + ": " + S(a); } return s; } void info_history(const Full* F, const Token& t1, const Token& t2, string& result) { const vector& cmds = F->ui()->cmds(); int from = 0, to = cmds.size(); if (t1.type == kTokenExpr) { from = iround(t1.value.d); if (from < 0) from += cmds.size(); } if (t2.type == kTokenExpr) { to = iround(t2.value.d); if (to < 0) to += cmds.size(); } if (from < 0 || to > (int) cmds.size()) throw ExecuteError("wrong history range"); for (int i = from; i < to; ++i) result += cmds[i].str() + "\n"; } void info_guess(const Full* F, int ds, const RealRange& range, string& result) { if (range.lo >= range.hi) result += "invalid range"; else { Guess g(F->get_settings()); g.set_data(F->dk.data(ds), range, -1); vector lin_v = g.estimate_linear_parameters(); for (int i = 0; i != 3; ++i) result += (i != 0 ? ", " : "") + Guess::linear_traits[i] + ": " + S(lin_v[i]); result += "\n"; vector peak_v = g.estimate_peak_parameters(); for (int i = 0; i != 4; ++i) result += (i != 0 ? ", " : "") + Guess::peak_traits[i] + ": " + S(peak_v[i]); result += "\n"; vector s_v = g.estimate_sigmoid_parameters(); for (int i = 0; i != 3; ++i) result += (i != 0 ? ", " : "") + Guess::sigmoid_traits[i] + ": " + S(s_v[i]); } } void save_state(const Full* F, string& r) { if (!r.empty()) r += "\n"; r += fityk_version_line + S(". Created: ") + time_now(); r += "\nset verbosity = -1 #the rest of the file is not shown"; r += "\nset autoplot = 0"; r += "\nreset"; r += "\n# ------------ settings ------------"; // do not set autoplot and verbosity here vector e = F->settings_mgr()->get_key_list(""); v_foreach(string, i, e) { if (*i == "autoplot" || *i == "verbosity") continue; string v = F->settings_mgr()->get_as_string(*i); if (*i == "cwd" && v == "''") // avoid this: set cwd='' continue; r += "\nset " + *i + " = " + v; } r += "\n"; r += "\n# ------------ datasets ------------"; for (int i = 0; i != F->dk.count(); ++i) { const Data* data = F->dk.data(i); if (i != 0) r += "\n@+ = 0"; r += "\nuse @" + S(i); r += "\ntitle = '" + data->get_title() + "'"; int m = data->points().size(); r += "\nM=" + S(m); r += "\nX=" + eS(data->get_x_max()) + "# =max(x), prevents sorting."; for (int j = 0; j != m; ++j) { const Point& p = data->points()[j]; string idx = "[" + S(j) + "]="; r += "\nX" + idx + eS(p.x) + ", Y" + idx + eS(p.y) + ", S" + idx + eS(p.sigma) + ", A" + idx + (p.is_active ? "1" : "0"); } r += "\n"; } r += "\n\n"; models_as_script(F, r, true); r += "\n"; r += F->ui()->ui_state_as_script(); r += "\n"; r += "\nplot " + F->view.str(); r += "\nuse @" + S(F->dk.default_idx()); r += "\nset autoplot = " + F->settings_mgr()->get_as_string("autoplot"); r += "\nset verbosity = " + F->settings_mgr()->get_as_string("verbosity"); } static string format_error_info(const Full* F, const vector& errors) { string s; const SettingsMgr *sm = F->settings_mgr(); const vector& pp = F->mgr.parameters(); assert(pp.size() == errors.size()); const Fit* fit = F->get_fit(); for (size_t i = 0; i != errors.size(); ++i) { if (fit->is_param_used(i)) { double err = errors[i]; s += "\n$" + F->mgr.gpos_to_var(i)->name + " = " + sm->format_double(pp[i]) + " +- " + (err == 0. ? string("??") : sm->format_double(err)); } } return s; } int eval_one_info_arg(const Full* F, int ds, const vector& args, int n, string& result) { int ret = 0; if (args[n].type == kTokenLname) { const string word = args[n].as_string(); // no args if (word == "version") result += "Fityk " VERSION; else if (word == "compiler") result += build_info(); else if (word == "variables") for (size_t i = 0; i < F->mgr.variables().size(); ++i) result += (i > 0 ? " $" : "$") + F->mgr.get_variable(i)->name; else if (word == "types") v_foreach (Tplate::Ptr, i, F->get_tpm()->tpvec()) result += (*i)->name + " "; else if (word == "functions") for (size_t i = 0; i < F->mgr.functions().size(); ++i) result += (i > 0 ? " %" : "%") + F->mgr.get_function(i)->name; else if (word == "dataset_count") result += S(F->dk.count()); else if (word == "view") result += F->view.str(); else if (word == "fit_history") result += F->fit_manager()->param_history_info(); else if (word == "filename") { result += F->dk.data(ds)->get_filename(); } else if (word == "title") { result += F->dk.data(ds)->get_title(); } else if (word == "data") { result += F->dk.data(ds)->get_info(); } else if (word == "formula") { const char* fmt = F->get_settings()->numeric_format.c_str(); result += F->dk.get_model(ds)->get_formula(false, fmt, false); } else if (word == "gnuplot_formula") { const char* fmt = F->get_settings()->numeric_format.c_str(); string formula = F->dk.get_model(ds)->get_formula(false, fmt,false); result += gnuplotize_formula(formula); } else if (word == "simplified_formula") { const char* fmt = F->get_settings()->numeric_format.c_str(); result += F->dk.get_model(ds)->get_formula(true, fmt, false); } else if (word == "simplified_gnuplot_formula") { const char* fmt = F->get_settings()->numeric_format.c_str(); string formula = F->dk.get_model(ds)->get_formula(true, fmt, false); result += gnuplotize_formula(formula); } else if (word == "models") { models_as_script(F, result, false); } else if (word == "state") { save_state(F, result); } else if (word == "peaks") { vector no_errors; // empty vec -> no errors result += F->dk.get_model(ds)->get_peak_parameters(no_errors); } else if (word == "peaks_err") { //FIXME: assumes the dataset was fitted separately Data* data = const_cast(F->dk.data(ds)); vector datas(1, data); vector errors = F->get_fit()->get_standard_errors(datas); result += F->dk.get_model(ds)->get_peak_parameters(errors); } else if (word == "history_summary") result += F->ui()->get_history_summary(); else if (word == "set") { if (args[n+1].type == kTokenLname) { string key = args[n+1].as_string(); result += F->settings_mgr()->get_as_string(key) + "\ntype: " + F->settings_mgr()->get_type_desc(key); } else { result += "Available options:"; vector e = F->settings_mgr()->get_key_list(""); v_foreach(string, i, e) result += "\n " + *i + " <" + F->settings_mgr()->get_type_desc(*i) + "> = " + F->settings_mgr()->get_as_string(*i); } ++ret; } // optional range else if (word == "history") { info_history(F, args[n+1], args[n+2], result); ret += 2; } else if (word == "guess") { RealRange range = args2range(args[n+1], args[n+2]); info_guess(F, ds, range, result); ret += 2; } // optionally takes datasets as args else if (word == "fit" || word == "errors" || word == "cov" || word == "confidence") { double level = 0.; if (word == "confidence") { level = args[n+1].value.d; if (level <= 0 || level >= 100) throw ExecuteError("confidence level outside of (0,100)"); ++n; ++ret; } vector v; while (args[n+1].type == kTokenDataset) { token_to_data(const_cast(F), args[n+1], v); ++n; ++ret; } assert(args[n+1].type == kTokenNop); // separator ++ret; if (v.empty()) { Data* data = const_cast(F->dk.data(ds)); v.push_back(data); } if (word == "fit") result += F->get_fit()->get_goodness_info(v); else if (word == "errors") { result += "Standard errors:"; vector errors = F->get_fit()->get_standard_errors(v); result += format_error_info(F, errors); } else if (word == "confidence") { result += S(level) + "% confidence intervals:"; vector limits = F->get_fit()->get_confidence_limits(v, level); result += format_error_info(F, limits); } else //if (word == "cov") result += F->get_fit()->get_cov_info(v); } // one arg: $var else if (word == "refs") { string name = Lexer::get_string(args[n+1]); vector refs = F->mgr.get_variable_references(name); result += join_vector(refs, ", "); ++ret; } // one arg: %func else if (word == "prop") { string name = Lexer::get_string(args[n+1]); result += info_func_props(F, name); ++ret; } } // FuncType else if (args[n].type == kTokenCname) info_func_type(F, args[n].as_string(), result); // %func else if (args[n].type == kTokenFuncname) info_functions(F, Lexer::get_string(args[n]), result); // $var else if (args[n].type == kTokenVarname) info_variables(F, Lexer::get_string(args[n]), result); // handle [@n.]F/Z['['expr']'] else if ((args[n].type == kTokenUletter && (*args[n].str == 'F' || *args[n].str == 'Z')) || args[n].type == kTokenDataset) { int k = ds; if (args[n].type == kTokenDataset) { k = args[n].value.i; ++n; ++ret; } const Model* model = F->dk.get_model(k); char fz = *args[n].str; if (is_index(n+1, args) && args[n+1].type == kTokenExpr) { ++ret; int idx = iround(args[n+1].value.d); const string& name = model->get_func_name(fz, idx); const Function *f = F->mgr.find_function(name); result += f->get_basic_assignment(); } else { const vector& names = model->get_fz(fz).names; if (!names.empty()) result += "%" + join_vector(names, " + %"); } } ++ret; return ret; } void eval_one_print_arg(const Full* F, int ds, const Token& t, string& result) { if (t.type == kTokenString) result += Lexer::get_string(t); else if (t.type == kTokenExpr) result += F->settings_mgr()->format_double(t.value.d); else if (t.as_string() == "filename") result += F->dk.data(ds)->get_filename(); else if (t.as_string() == "title") result += F->dk.data(ds)->get_title(); else assert(0); } int eval_print_args(const Full* F, int ds, const vector& args, int len, string& result) { // args: condition (expr|string|"filename"|"title")+ string sep = " "; if (args[0].type == kTokenNop) { for (int n = 1; n < len; ++n) { if (n != 1) result += sep; eval_one_print_arg(F, ds, args[n], result); } } else { vector expr_parsers(args.size() + 1, F); for (int i = 0; i < len; ++i) if (args[i].type == kTokenExpr) { Lexer lex(args[i].str); expr_parsers[i].parse_expr(lex, ds); } const vector& points = F->dk.data(ds)->points(); for (int k = 0; k != (int) points.size(); ++k) { if (args[0].type == kTokenExpr) { double cond = expr_parsers[0].calculate(k, points); if (fabs(cond) < 0.5) continue; } if (!result.empty()) result += "\n"; for (int n = 1; n < len; ++n) { if (n != 1) result += sep; if (args[n].type == kTokenExpr) { double value = expr_parsers[n].calculate(k, points); result += F->settings_mgr()->format_double(value); } else eval_one_print_arg(F, ds, args[n], result); } } } return len; } } // anonymous namespace int eval_info_args(const Full* F, int ds, const vector& args, int len, string& result) { int n = 0; while (n < len) { if (!result.empty()) result += "\n"; n += eval_one_info_arg(F, ds, args, n, result); } if (len == 0) { // special case result += "Available arguments:\n"; const char** arg = info_args; while (*arg != NULL) { result += *arg + S(" "); ++arg; } result += "%* $* AnyFunctionT"; } return n; } void command_redirectable(const Full* F, int ds, CommandType cmd, const vector& args) { string info; int len = args.size(); bool redir = (len >= 2 && (args[len-2].type == kTokenGT || args[len-2].type == kTokenAppend)); int n_args = redir ? len - 2 : len; if (cmd == kCmdInfo) eval_info_args(F, ds, args, n_args, info); else // cmd == kCmdPrint eval_print_args(F, ds, args, n_args, info); if (!redir) { // no redirection to file int max_screen_info_length = 2048; int more = (int) info.length() - max_screen_info_length; if (more > 0) { info.resize(max_screen_info_length); info += "\n[... " + S(more) + " characters more...]"; } F->ui()->mesg(info); } else { assert(args.back().type == kTokenWord || args.back().type == kTokenString); string filename = Lexer::get_string(args.back()); const char* mode = args[len-2].type == kTokenGT ? "w" : "a"; FILE *f = fopen(filename.c_str(), mode); if (!f) throw ExecuteError("Can't open file: " + filename); fprintf(f, "%s\n", info.c_str()); fclose(f); } } void command_debug(const Full* F, int ds, const Token& key, const Token& rest) { // args: any-token rest-of-line string r; string word = key.as_string(); if (word == "parse") { Parser parser(const_cast(F)); try { Lexer lex(rest.str); while (parser.parse_statement(lex)) r += parser.get_statements_repr(); } catch (SyntaxError& e) { r += string("ERR: ") + e.what(); } } else if (word == "lex") { Lexer lex(rest.str); for (Token t = lex.get_token(); t.type != kTokenNop; t =lex.get_token()) r += token2str(t) + "\n"; } else if (word == "expr") { // Possible options: dt|ast, new. Example: debug expr ast new a*x^2 Lexer lex(rest.str); try { ExpressionParser parser(F); ExpressionParser::ParseMode mode = ExpressionParser::kNormalMode; if (lex.peek_token().as_string() == "ast") { mode = ExpressionParser::kAstMode; lex.get_token(); } else if (lex.peek_token().as_string() == "dt") { mode = ExpressionParser::kDatasetTrMode; lex.get_token(); } vector *new_names = NULL; vector names; if (lex.peek_token().as_string() == "new") { new_names = &names; lex.get_token(); } parser.parse_expr(lex, -1, NULL, new_names, mode); r += vm2str(parser.vm()); if (new_names != NULL) r += "\nnew names: " + join_vector(*new_names, ", "); } catch (SyntaxError& e) { r += "ERROR at " + S(lex.scanned_chars()) + ": " + e.what(); } if (lex.peek_token().type != kTokenNop) r += "\nnext token: " + token2str(lex.peek_token()); } else if (word == "der") { get_derivatives_str(rest.str, r); } // show values of derivatives for all variables else if (word == "rd") { v_foreach(Variable*, v, F->mgr.variables()) { r += "$" + (*v)->name + ": "; v_foreach (Variable::ParMult, i, (*v)->recursive_derivatives()) r += "p" + S(i->p) + "=$" + F->mgr.gpos_to_var(i->p)->name + " *" + S(i->mult) + " "; r += "\n"; } } // show used_vars from VariableUser else if (word == "idx") { for (size_t i = 0; i != F->mgr.functions().size(); ++i) { const Function *f = F->mgr.get_function(i); r += S(i) + ": %" + f->name + ": "; const IndexedVars& uv = f->used_vars(); for (int j = 0; j != uv.get_count(); ++j) r += uv.get_name(j) + "/" + S(uv.get_idx(j)) + " "; r += "\n"; } for (size_t i = 0; i != F->mgr.variables().size(); ++i) { const Variable *v = F->mgr.get_variable(i); r += S(i) + ": $" + v->name + ": "; const IndexedVars& uv = v->used_vars(); for (int j = 0; j != uv.get_count(); ++j) r += uv.get_name(j) + "/" + S(uv.get_idx(j)) + " "; r += "\n"; } } // compares numeric and symbolic derivatives else if (word == "df") { Lexer lex(rest.str); ExpressionParser ep(F); ep.parse_expr(lex, ds); realt x = ep.calculate(); const Model* model = F->dk.get_model(ds); realt y; vector symb = model->get_symbolic_derivatives(x, &y); vector num = model->get_numeric_derivatives(x, 1e4*epsilon); assert (symb.size() == num.size()); int n = symb.size() - 1; r += "F(" + S(x) + ")=" + S(model->value(x)) + "=" + S(y); r += "\nusing h=1e4*epsilon=" + S(1e4*epsilon); for (int i = 0; i < n; ++i) { if (is_neq(symb[i], 0) || is_neq(num[i], 0)) r += "\ndF / d$" + F->mgr.gpos_to_var(i)->name + " = (symb.) " + S(symb[i]) + " = (num.) " + S(num[i]); } r += "\ndF / dx = (symb.) " + S(symb[n]) + " = (num.) " + S(num[n]); } // show %function's bytecode else if (key.type == kTokenFuncname) { const Function* f = F->mgr.find_function(Lexer::get_string(key)); r += f->get_bytecode(); } // show derivatives of $variable else if (key.type == kTokenVarname) { const Variable* v = F->mgr.find_variable(Lexer::get_string(key)); vector vn; v_foreach (string, i, v->used_vars().names()) vn.push_back("$" + *i); for (int i = 0; i < v->used_vars().get_count(); ++i) { const char* num_format = F->get_settings()->numeric_format.c_str(); OpTreeFormat fmt = { num_format, &vn }; string formula = v->get_op_trees()[i]->str(fmt); double value = v->get_derivative(i); if (i != 0) r += "\n"; r += "d($" + v->name + ")/d($" + v->used_vars().get_name(i) + "): " + formula + " == " + F->settings_mgr()->format_double(value); } } // tests the match_glob() else if (word == "glob") { Lexer lex(rest.str); string pattern = lex.get_word_token().as_string(); Token t; while ((t = lex.get_word_token()).type != kTokenNop) { string s = t.as_string(); if (match_glob(s.c_str(), pattern.c_str())) r += s + " "; } } else r += "unexpected arg: " + word + "\nShould be one of: " + join(debug_args, debug_args+9, " "); F->ui()->mesg(r); } void parse_and_eval_info(Full *F, const string& s, int dataset, string& result) { Lexer lex(s.c_str()); Parser parser(F); parser.statement().datasets.push_back(dataset); vector args; parser.parse_info_args(lex, args); if (lex.peek_token().type != kTokenNop) lex.throw_syntax_error("unexpected argument"); eval_info_args(F, dataset, args, args.size(), result); } } // namespace fityk fityk-1.3.1/fityk/info.h000066400000000000000000000022031302634723100150720ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ #ifndef FITYK_INFO_H_ #define FITYK_INFO_H_ #include #include #include "lexer.h" // Token #include "cparser.h" // CommandType namespace fityk { FITYK_API std::string build_info(); FITYK_API const char* embedded_lua_version(); /// appends output of the "info" command to the result int eval_info_args(const Full* F, int ds, const std::vector& args, int len, std::string& result); /// handles commands info and print void command_redirectable(Full const* F, int ds, CommandType cmd, const std::vector& args); void command_debug(const Full* F, int ds, const Token& key, const Token&rest); FITYK_API void parse_and_eval_info(Full *F, const std::string& s, int dataset, std::string& result); FITYK_API std::string& gnuplotize_formula(std::string& formula); FITYK_API void models_as_script(const Full* F, std::string& r, bool commented_defines); } // namespace fityk #endif // FITYK_INFO_H_ fityk-1.3.1/fityk/lexer.cpp000066400000000000000000000316061302634723100156220ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Lexical analyser. Takes C string and yields tokens. #define BUILDING_LIBFITYK #include "lexer.h" #include #include #include #include #include "fityk.h" // SyntaxError #include "common.h" // S() using namespace std; namespace fityk { string Lexer::get_string(const Token& token) { switch (token.type) { case kTokenString: return string(token.str+1, token.length - 2); case kTokenVarname: return string(token.str+1, token.length - 1); case kTokenFuncname: return string(token.str+1, token.length - 1); default: //assert(!"Unexpected token in get_string()"); return token.as_string(); } } const char* tokentype2str(TokenType tt) { switch (tt) { case kTokenLname: return "lower_case_name"; case kTokenCname: return "CamelCaseName"; case kTokenUletter: return "Upper-case-letter"; case kTokenString: return "'quoted-string'"; case kTokenVarname: return "$variable_name"; case kTokenFuncname: return "%func_name"; case kTokenNumber: return "number"; case kTokenDataset: return "@dataset"; case kTokenWord: return "word"; case kTokenExpr: return "expr"; case kTokenEVar: return "var-expr"; case kTokenRest: return "rest-of-line"; case kTokenLE: return "<="; case kTokenGE: return ">="; case kTokenNE: return "!="; case kTokenEQ: return "=="; case kTokenAppend: return ">>"; case kTokenDots: return ".."; case kTokenPlusMinus: return "+-"; case kTokenAddAssign: return "+="; case kTokenSubAssign: return "-="; case kTokenOpen: return "("; case kTokenClose: return ")"; case kTokenLSquare: return "["; case kTokenRSquare: return "]"; case kTokenLCurly: return "{"; case kTokenRCurly: return "}"; case kTokenPlus: return "+"; case kTokenMinus: return "-"; case kTokenMult: return "*"; case kTokenDiv: return "/"; case kTokenPower: return "^"; case kTokenLT: return "<"; case kTokenGT: return ">"; case kTokenAssign: return "="; case kTokenComma: return ","; case kTokenSemicolon: return ";"; case kTokenDot: return "."; case kTokenColon: return ":"; case kTokenTilde: return "~"; case kTokenQMark: return "?"; case kTokenBang: return "!"; case kTokenNop: return "Nop"; } return NULL; // avoid compiler warning } string token2str(const Token& token) { string s = tokentype2str(token.type); switch (token.type) { case kTokenString: case kTokenVarname: case kTokenFuncname: case kTokenLname: case kTokenCname: case kTokenUletter: case kTokenWord: case kTokenRest: return s + " \"" + token.as_string() + "\""; case kTokenExpr: return s + " \"" + token.as_string() + "\" ("+S(token.value.d)+")"; case kTokenEVar: return s + " \"" + token.as_string() + "\""; case kTokenNumber: return s + " " + S(token.value.d); case kTokenDataset: if (token.value.i == Lexer::kAll) return s + " '*'"; else if (token.value.i == Lexer::kNew) return s + " '+'"; else return s + " " + S(token.value.i); default: return s; } } void Lexer::read_token(bool allow_glob) { tok_.str = cur_; while (isspace(*tok_.str)) ++tok_.str; const char* ptr = tok_.str; switch (*ptr) { case '\0': case '#': tok_.type = kTokenNop; break; case '\'': { tok_.type = kTokenString; const char* end = strchr(ptr + 1, '\''); if (end == NULL) throw SyntaxError("unfinished string"); ptr = end + 1; break; } case '>': ++ptr; if (*ptr == '=') { tok_.type = kTokenGE; ++ptr; } else if (*ptr == '>') { tok_.type = kTokenAppend; ++ptr; } else tok_.type = kTokenGT; break; case '<': ++ptr; if (*ptr == '=') { tok_.type = kTokenLE; ++ptr; } else if (*ptr == '>') { tok_.type = kTokenNE; ++ptr; } else tok_.type = kTokenLT; break; case '=': ++ptr; if (*ptr == '=') { tok_.type = kTokenEQ; ++ptr; } else tok_.type = kTokenAssign; break; case '+': ++ptr; if (*ptr == '-') { tok_.type = kTokenPlusMinus; ++ptr; } else if (*ptr == '=') { tok_.type = kTokenAddAssign; ++ptr; } else tok_.type = kTokenPlus; break; case '-': ++ptr; if (*ptr == '=') { tok_.type = kTokenSubAssign; ++ptr; } else tok_.type = kTokenMinus; break; case '!': ++ptr; if (*ptr == '=') { tok_.type = kTokenNE; ++ptr; } else tok_.type = kTokenBang; break; case '.': ++ptr; if (isdigit(*ptr)) { char* endptr; tok_.value.d = strtod(ptr-1, &endptr); ptr = endptr; tok_.type = kTokenNumber; } else if (*ptr == '.') { ++ptr; if (*ptr == '.') // 3rd dot ++ptr; tok_.type = kTokenDots; } else tok_.type = kTokenDot; break; case '@': ++ptr; tok_.type = kTokenDataset; if (*ptr == '*') { tok_.value.i = kAll; ++ptr; } else if (*ptr == '+') { tok_.value.i = kNew; ++ptr; } else if (isdigit(*ptr)) { char *endptr; tok_.value.i = strtol(ptr, &endptr, 10); ptr = endptr; } else throw SyntaxError("unexpected character after '@'"); break; case '$': ++ptr; // allow_glob decides if the '*' is read ("delete $p*") // or not ("$c=$a*$b"). Always read "$*" (it's not ambigous and // we do't want error when peeking) if (! (isalpha(*ptr) || *ptr == '_' || *ptr == '*')) throw SyntaxError("unexpected character after '$'"); ++ptr; tok_.type = kTokenVarname; while (isalnum(*ptr) || *ptr == '_' || (allow_glob && *ptr == '*')) ++ptr; break; case '%': ++ptr; // the same rules as in the case of '$' if (! (isalpha(*ptr) || *ptr == '_' || *ptr == '*')) throw SyntaxError("unexpected character after '%'"); ++ptr; tok_.type = kTokenFuncname; while (isalnum(*ptr) || *ptr == '_' || (allow_glob && *ptr == '*')) ++ptr; break; case '(': tok_.type = kTokenOpen; ++ptr; break; case ')': tok_.type = kTokenClose; ++ptr; break; case '[': tok_.type = kTokenLSquare; ++ptr; break; case ']': tok_.type = kTokenRSquare; ++ptr; break; case '{': tok_.type = kTokenLCurly; ++ptr; break; case '}': tok_.type = kTokenRCurly; ++ptr; break; case '*': tok_.type = kTokenMult; ++ptr; break; case '/': tok_.type = kTokenDiv; ++ptr; break; case '^': tok_.type = kTokenPower; ++ptr; break; case ',': tok_.type = kTokenComma; ++ptr; break; case ';': tok_.type = kTokenSemicolon; ++ptr; break; case ':': tok_.type = kTokenColon; ++ptr; break; case '~': tok_.type = kTokenTilde; ++ptr; break; case '?': tok_.type = kTokenQMark; ++ptr; break; default: if (isdigit(*ptr)) { char* endptr; tok_.value.d = strtod(ptr, &endptr); ptr = endptr; tok_.type = kTokenNumber; } else if (isupper(*ptr)) { ++ptr; if (isalnum(*ptr)) { while (isalnum(*ptr)) ++ptr; tok_.type = kTokenCname; } else tok_.type = kTokenUletter; } else if (isalpha(*ptr) || *ptr == '_') { while (isalnum(*ptr) || *ptr == '_') ++ptr; tok_.type = kTokenLname; } else throw SyntaxError("unexpected character: " + string(ptr, 1)); } tok_.length = ptr - tok_.str; cur_ = ptr; } Token Lexer::get_token() { if (!peeked_) read_token(); peeked_ = false; return tok_; } const Token& Lexer::peek_token() { if (!peeked_) read_token(); peeked_ = true; return tok_; } void Lexer::go_back(const Token& token) { cur_ = token.str; peeked_ = false; } Token Lexer::get_glob_token() { if (peeked_) { // un-peek cur_ = tok_.str; peeked_ = false; } read_token(true); return tok_; } Token Lexer::get_word_token() { Token t = get_token(); if (t.type == kTokenString || t.type == kTokenNop) return t; while (*cur_ != '\0' && !isspace(*cur_) && *cur_ != ';' && *cur_ != '#') ++cur_; t.type = kTokenWord; t.length = cur_ - t.str; return t; } Token Lexer::get_rest_of_cmd() { Token t = get_token(); if (t.type == kTokenString || t.type == kTokenNop) return t; while (*cur_ != '\0' && *cur_ != ';' && *cur_ != '#') ++cur_; t.type = kTokenRest; t.length = cur_ - t.str; return t; } Token Lexer::get_rest_of_line() { // avoid calling here read_token() because it may throw exception Token t; t.type = kTokenRest; while (isspace(*cur_)) ++cur_; t.str = peeked_ ? tok_.str : cur_; peeked_ = false; while (*cur_ != '\0') ++cur_; t.length = cur_ - t.str; return t; } Token Lexer::get_expected_token(const string& raw) { TokenType p = peek_token().type; string s = peek_token().as_string(); if (s != raw) { string msg = "expected `" + raw + "'"; throw_syntax_error(p == kTokenNop ? msg : msg + " instead of `" + s + "'"); } return get_token(); } Token Lexer::get_expected_token(TokenType tt) { TokenType p = peek_token().type; if (p != tt) { string msg = S("expected ") + tokentype2str(tt); throw_syntax_error(p == kTokenNop ? msg : msg + " instead of " + tokentype2str(p)); } return get_token(); } Token Lexer::get_expected_token(TokenType tt1, TokenType tt2) { TokenType p = peek_token().type; if (p != tt1 && p != tt2) { string msg = S("expected ") + tokentype2str(tt1) + " or " + tokentype2str(tt2); throw_syntax_error(p == kTokenNop ? msg : msg + " instead of " + tokentype2str(p)); } return get_token(); } Token Lexer::get_expected_token(TokenType tt, const string& raw) { TokenType p = peek_token().type; string s = peek_token().as_string(); if (p != tt && s != raw) { string msg = S("expected ") + tokentype2str(tt) + " or `" + raw + "'"; throw_syntax_error(p == kTokenNop ? msg : msg + " instead of `" + s + "'"); } return get_token(); } Token Lexer::get_expected_token(const string& raw1, const string& raw2) { TokenType p = peek_token().type; string s = peek_token().as_string(); if (s != raw1 && s != raw2) { string msg = "expected `" + raw1 + "' or `" + raw2 + "'"; throw_syntax_error(p == kTokenNop ? msg : msg + " instead of `" + s + "'"); } return get_token(); } Token Lexer::get_token_if(TokenType tt) { if (peek_token().type == tt) return get_token(); else { Token token; token.type = kTokenNop; token.str = cur_; token.length = 0; return token; } } void Lexer::throw_syntax_error(const string& msg) { int pos = cur_ - input_; string s = S(pos); if (pos >= 10) s += ", near `" + string(cur_ - 10, cur_) + "'"; throw SyntaxError("at " + s + ": " + msg); } } // namespace fityk fityk-1.3.1/fityk/lexer.h000066400000000000000000000105171302634723100152650ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Lexical analyser. Takes characters and yields tokens. #ifndef FITYK_LEXER_H_ #define FITYK_LEXER_H_ #include namespace fityk { class VMData; #ifdef _WIN32 // On Windows TokenType is a constant in _TOKEN_INFORMATION_CLASS in Winnt.h #define TokenType FitykTokenType #endif enum TokenType { // textual tokens kTokenLname, // (Lowercase | '_') {Lowercase | Digit | '_'} kTokenCname, // Uppercase (Alpha | Digit) {Alpha | Digit} kTokenUletter, // single uppercase letter kTokenString, // 'string' kTokenVarname, // $variable kTokenFuncname, // %function // special tokens: // returned only by get_word_token(), not by get_token() kTokenWord, // expression as string, never returned by Lexer, used only in Parser kTokenExpr, // variable or expression meant to create a new variable, // never returned by Lexer, used only in Parser kTokenEVar, // it can be returned by get_rest_of_line() kTokenRest, // tokens with `value' set kTokenNumber, // number (value.d) kTokenDataset, // @n, @*, @+ (value.i) // 2-char tokens kTokenLE, kTokenGE, // <= >= kTokenNE, // != or <> kTokenEQ, // == kTokenAppend, // >> kTokenDots, // .. kTokenPlusMinus, // +- kTokenAddAssign, kTokenSubAssign, // += -= // single-char tokens: ( ) [ ] { } + - * / ^ < > = ; , : . ~ ? kTokenOpen, kTokenClose, // ( ) kTokenLSquare, kTokenRSquare, // [ ] kTokenLCurly, kTokenRCurly, // { } kTokenPlus, kTokenMinus, // + - kTokenMult, kTokenDiv, // * / kTokenPower, // ^ kTokenLT, kTokenGT, // < > kTokenAssign, // = kTokenComma, kTokenSemicolon, // , ; kTokenDot, // . kTokenColon, // : kTokenTilde, // ~ kTokenQMark, // ? kTokenBang, // ! kTokenNop // end of line (returned by Lexer) or placeholder (in Parser) }; const char* tokentype2str(TokenType tt); // with 64-bit alignment sizeof(Token) is 24 struct Token { const char* str; // position in the string TokenType type; short length; // raw string length (e.g. 3 for 'a') union { int i; double d; } value; // get string associated with the token. std::string as_string() const { return std::string(str, length); } }; class Lexer { public: // dataset special values enum { kAll = -1, kNew = -2 }; // get string associated with the token. Works only with: // kTokenLname, kTokenCname, kTokenUletter, // kTokenString, kTokenVarname, kTokenFuncname. static std::string get_string(const Token& token); Lexer(const char* input) : input_(input), cur_(input), peeked_(false), tok_() {} Token get_token(); // look ahead and read the next token without removing it const Token& peek_token(); Token get_expected_token(TokenType tt); Token get_expected_token(const std::string& raw); Token get_expected_token(TokenType tt1, TokenType tt2); Token get_expected_token(TokenType tt, const std::string& raw); Token get_expected_token(const std::string& raw1, const std::string& raw2); // if the next token is of type `tt' get it, otherwise return kTokenNop Token get_token_if(TokenType tt); bool discard_token_if(TokenType tt) { return get_token_if(tt).type != kTokenNop; } // Unlike get_token(), allow '*' in $variables and %functions. Token get_glob_token(); // Used mostly for filenames. Reads a quoted string or a sequence // of non-blank and non-[;#] characters as a word. // Returns kTokenWord, kTokenString or kTokenNop. Token get_word_token(); // Reads the same as get_word_token() plus blanks. Returns kTokenRest Token get_rest_of_cmd(); // Reads rest of the line and returns kTokenRest Token get_rest_of_line(); void go_back(const Token& token); void throw_syntax_error(const std::string& msg=""); const char* pchar() const { return peeked_ ? tok_.str : cur_; } int scanned_chars() const { return pchar() - input_; } private: void read_token(bool allow_glob=false); const char* const input_; // used for diagnostic messages only const char* cur_; bool peeked_; Token tok_; }; std::string token2str(const Token& token); } // namespace fityk #endif // FITYK_LEXER_H_ fityk-1.3.1/fityk/logic.cpp000066400000000000000000000204541302634723100155770ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "logic.h" #include #include #include #include #include "common.h" #include "data.h" #include "model.h" #include "ui.h" #include "fit.h" #include "settings.h" #include "mgr.h" #include "tplate.h" #include "var.h" #include "luabridge.h" #include "lexer.h" // Lexer::kNew #include "cparser.h" #include "runner.h" using namespace std; namespace fityk { Full::Full() : mgr(this), view(&dk) { // reading numbers won't work with decimal points different than '.' setlocale(LC_NUMERIC, "C"); cmd_executor_ = new CommandExecutor(this); ui_ = new UserInterface(this, cmd_executor_); lua_bridge_ = new LuaBridge(this); initialize(); } Full::~Full() { destroy(); delete lua_bridge_; delete ui_; delete cmd_executor_; } // initializations common for ctor and reset() void Full::initialize() { fit_manager_ = new FitManager(this); // Settings ctor is using FitManager settings_mgr_ = new SettingsMgr(this); tplate_mgr_ = new TplateMgr; tplate_mgr_->add_builtin_types(cmd_executor_->parser()); view = View(&dk); ui_->mark_plot_dirty(); dk.append(new Data(this, mgr.create_model())); dk.set_default_idx(0); settings_mgr_->do_srand(); } // cleaning common for dtor and reset() void Full::destroy() { dk.clear(); mgr.do_reset(); delete fit_manager_; delete settings_mgr_; delete tplate_mgr_; } // reset everything but UserInterface (and related settings) void Full::reset() { int verbosity = get_settings()->verbosity; bool autoplot = get_settings()->autoplot; destroy(); initialize(); if (verbosity != get_settings()->verbosity) settings_mgr_->set_as_number("verbosity", verbosity); if (autoplot != get_settings()->autoplot) settings_mgr_->set_as_number("autoplot", autoplot); } void DataKeeper::remove(int d) { index_check(d); if (datas_.size() == 1) { datas_[0]->model()->clear(); datas_[0]->clear(); } else { delete datas_[d]; datas_.erase(datas_.begin() + d); } } Fit* Full::get_fit() const { string method_name = get_settings()->fitting_method; return fit_manager()->get_method(method_name); } namespace { int atoi_all(string const& s) { char *endptr; int n = strtol(s.c_str(), &endptr, 10); if (*endptr != 0) throw ExecuteError("integral number expected, got: " + s); return n; } // e.g.: "1,3..5,7" -> 1,3,4,5,7 // "4" -> 4 // "2,1" -> 2,1 vector parse_int_range(string const& s, int maximum) { vector values; vector t = split_string(s, ","); v_foreach (string, i, t) { string::size_type dots = i->find(".."); if (dots == string::npos) { int n = atoi_all(*i); values.push_back(n); } else { int m = atoi_all(i->substr(0, dots)); string n_ = i->substr(dots+2); int n = n_.empty() ? maximum : atoi_all(i->substr(dots+2)); if (m < 0) m += maximum; if (n < 0) n += maximum; if (m < 0 || n < 0) throw ExecuteError("Negative number found in range: " + s); if (m <= n) for (int j = m; j <= n; ++j) values.push_back(j); else for (int j = m; j >= n; --j) values.push_back(j); } } return values; } } //anonymous namespace void DataKeeper::import_dataset(int slot, const string& data_path, const string& format, const string& options, BasicContext* ctx, ModelManager &mgr) { const bool new_dataset = (slot == Lexer::kNew); // split "data_path" (e.g. "foo.dat:1:2,3::") into filename // and colon-separated indices int count_colons = ::count(data_path.begin(), data_path.end(), ':'); LoadSpec spec; vector indices[3]; if (count_colons >= 4) { // take filename string::size_type fn_end = string::npos; for (int i = 0; i < 4; ++i) fn_end = data_path.rfind(':', fn_end - 1); spec.path = data_path.substr(0, fn_end); // blocks string::size_type end_pos = data_path.size(); string::size_type bpos = data_path.rfind(':', end_pos - 1); string::size_type blen = end_pos - bpos - 1; if (blen > 0) { int block_count = Data::count_blocks(spec.path, format, options); string range = data_path.substr(bpos+1, blen); spec.blocks = parse_int_range(range, block_count-1); } end_pos = bpos; int first_block = spec.blocks.empty() ? 0 : spec.blocks[0]; int col_count = Data::count_columns(spec.path, format, options, first_block); for (int i = 2; i >= 0; --i) { string::size_type pos = data_path.rfind(':', end_pos - 1); string::size_type len = end_pos - pos - 1; if (len > 0) { string range = data_path.substr(pos+1, len); indices[i] = parse_int_range(range, col_count); } end_pos = pos; } assert(fn_end == end_pos); } else { spec.path = data_path; } if (indices[0].size() > 1) throw ExecuteError("Only one column x can be specified"); if (indices[2].size() > 1) throw ExecuteError("Only one column sigma can be specified"); if (indices[1].size() > 1 && !new_dataset) throw ExecuteError("Multiple y columns can be specified only with @+"); if (!indices[0].empty()) spec.x_col = indices[0][0]; if (!indices[2].empty()) spec.sig_col = indices[2][0]; spec.format = format; spec.options = options; if (indices[1].empty()) indices[1].push_back(LoadSpec::NN); for (size_t i = 0; i < indices[1].size(); ++i) { spec.y_col = indices[1][i]; do_import_dataset(new_dataset, slot, spec, ctx, mgr); } } void DataKeeper::do_import_dataset(bool new_dataset, int slot, const LoadSpec& spec, BasicContext* ctx, ModelManager &mgr) { Data *d; auto_ptr auto_d; if (!new_dataset) d = data(slot); else if (count() == 1 && data(0)->completely_empty()) // reusable slot 0 d = data(0); else { // new slot auto_d.reset(new Data(ctx, mgr.create_model())); d = auto_d.get(); } d->load_file(spec); if (auto_d.get()) append(auto_d.release()); } void Full::outdated_plot() { ui_->mark_plot_dirty(); fit_manager_->outdated_error_cache(); } bool Full::are_independent(std::vector dd) const { for (size_t i = 0; i != mgr.variables().size(); ++i) if (mgr.get_variable(i)->is_simple()) { bool dep = false; v_foreach(Data*, d, dd) if ((*d)->model()->is_dependent_on_var(i)) { if (dep) return false; dep = true; } } return true; } static bool is_fityk_script(string filename) { const char *magic = "# Fityk"; FILE *f = fopen(filename.c_str(), "rb"); if (!f) return false; if (endswith(filename, ".fit") || endswith(filename, ".fityk") || endswith(filename, ".fit.gz") || endswith(filename, ".fityk.gz")) { fclose(f); return true; } const int magic_len = strlen(magic); char buffer[32]; char *ret = fgets(buffer, magic_len, f); fclose(f); return ret && !strncmp(magic, buffer, magic_len); } void Full::process_cmd_line_arg(const string& arg) { if (startswith(arg, "=->")) ui()->exec_and_log(string(arg, 3)); else if (endswith(arg, ".lua")) lua_bridge()->exec_lua_script(arg); else if (is_fityk_script(arg)) ui()->exec_fityk_script(arg); else { ui()->exec_and_log("@+ <'" + arg + "'"); } } bool Full::check_syntax(const string& str) { return cmd_executor_->parser()->check_syntax(str); } void Full::parse_and_execute_line(const string& str) { return cmd_executor_->raw_execute_line(str); } } // namespace fityk fityk-1.3.1/fityk/logic.h000066400000000000000000000102621302634723100152400ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_LOGIC_H_ #define FITYK_LOGIC_H_ #include #include "mgr.h" #include "ui.h" //UserInterface #include "view.h" #include "settings.h" #include "data.h" // Data.model() namespace fityk { class FitManager; class Fit; class TplateMgr; class LuaBridge; class CommandExecutor; class FITYK_API DataKeeper { public: DataKeeper() : default_idx_(0) {} void append(Data *data) { datas_.push_back(data); } void remove(int d); void clear() { purge_all_elements(datas_); } const std::vector& datas() const { return datas_; } int count() const { return datas_.size(); } Data* data(int n) { index_check(n); return datas_[n]; } const Data* data(int n) const { index_check(n); return datas_[n]; } const Model* get_model(int n) const { return data(n)->model(); } Model *get_mutable_model(int n) { return data(n)->model(); } int default_idx() const { return default_idx_; } void set_default_idx(int n) { index_check(n); default_idx_ = n; } /// import dataset (or multiple datasets, in special cases) void import_dataset(int slot, const std::string& data_path, const std::string& format, const std::string& options, BasicContext* ctx, ModelManager &mgr); void do_import_dataset(bool new_dataset, int slot, const LoadSpec& spec, BasicContext* ctx, ModelManager &mgr); private: int default_idx_; std::vector datas_; /// verify that n is the valid number for get_data() and return n void index_check(int n) const { if (!is_index(n, datas_)) throw ExecuteError("No such dataset: @" + S(n)); } }; /// A restricted interface to class Full. Provides read-only access to /// settings and access to UserInterface, primarily for printing messages. class FITYK_API BasicContext { public: const UserInterface* ui() const { return ui_; } UserInterface* ui() { return ui_; } // short names for popular calls int get_verbosity() const { return get_settings()->verbosity; } void msg(const std::string &s) const { if (get_verbosity() >= 0) ui_->mesg(s); } const SettingsMgr* settings_mgr() const { return settings_mgr_; } const Settings* get_settings() const { return &settings_mgr_->m(); } protected: SettingsMgr* settings_mgr_; UserInterface* ui_; }; /// Full context. /// Contains everything in libfityk except public API. class FITYK_API Full : public BasicContext { public: // for simplicity, these members are public and accessed directly ModelManager mgr; DataKeeper dk; View view; Full(); ~Full(); /// reset everything but UserInterface (and related settings) void reset(); SettingsMgr* mutable_settings_mgr() { return settings_mgr_; } const FitManager* fit_manager() const { return fit_manager_; } FitManager* fit_manager() { return fit_manager_; } Fit* get_fit() const; const TplateMgr* get_tpm() const { return tplate_mgr_; } TplateMgr* get_tpm() { return tplate_mgr_; } LuaBridge* lua_bridge() { return lua_bridge_; } /// called after changes that (possibly) need to be reflected in the plot /// (IOW when plot needs to be updated). This function is also used /// to mark cache of parameter errors as outdated. void outdated_plot(); // check if given models share common parameters bool are_independent(std::vector dd) const; // interprets command-line argument as data or script file or as command void process_cmd_line_arg(const std::string& arg); /// return true if the syntax is correct bool check_syntax(const std::string& str); void parse_and_execute_line(const std::string& str); private: // these members, as well as settings_mgr_ and ui_, are used via getters FitManager* fit_manager_; TplateMgr* tplate_mgr_; LuaBridge* lua_bridge_; CommandExecutor* cmd_executor_; // these two are used in ctor, dtor and reset() void initialize(); void destroy(); DISALLOW_COPY_AND_ASSIGN(Full); }; } // namespace fityk #endif fityk-1.3.1/fityk/luabridge.cpp000066400000000000000000000147211302634723100164400ustar00rootroot00000000000000 #define BUILDING_LIBFITYK #include "luabridge.h" #include "logic.h" #include "ui.h" #ifndef DISABLE_LUA extern "C" { #include #include #include #include "swig/luarun.h" // the SWIG external runtime extern int luaopen_fityk(lua_State *L); // the SWIG wrappered library } using namespace std; // based on luaB_print from lbaselib.c static int fityk_lua_print(lua_State* L) { using fityk::UserInterface; string str; int n = lua_gettop(L); // number of arguments lua_getglobal(L, "tostring"); for (int i=1; i<=n; i++) { lua_pushvalue(L, -1); // `tostring' function lua_pushvalue(L, i); // i'th arg lua_call(L, 1, 1); // calls tostring(arg_i) const char *s = lua_tostring(L, -1); // get result if (s == NULL) return luaL_error(L, "cannot convert argument to string"); if (i > 1) str += "\t"; str += s; lua_pop(L, 1); // pop result } UserInterface *ui = (UserInterface*) lua_touserdata(L, lua_upvalueindex(1)); ui->output_message(UserInterface::kNormal, str); return 0; } // it may rely on implementation details of Lua // SWIG-wrapped vector is indexed from 0. Return (n, vec[n]) starting from n=0. static int lua_vector_iterator(lua_State* L) { assert(lua_isuserdata(L,1)); // in SWIG everything is wrapped as userdata int idx = lua_isnil(L, -1) ? 0 : (int) lua_tonumber(L, -1) + 1; // no lua_len() in 5.1, let's call size() directly lua_getfield(L, 1, "size"); lua_pushvalue(L, 1); // arg: vector as userdata lua_call(L, 1, 1); // call vector<>::size(this) int size = (int) lua_tonumber(L, -1); if (idx >= size) { lua_settop(L, 0); return 0; } lua_settop(L, 1); lua_pushnumber(L, idx); // index, to be returned lua_pushvalue(L, -1); // the same index, to access value lua_gettable(L, 1); // value, to be returned lua_remove(L, 1); return 2; } namespace fityk { LuaBridge::LuaBridge(Full *F) : ctx_(F) { L_ = luaL_newstate(); luaL_openlibs(L_); luaopen_fityk(L_); // SWIG-generated luaopen_fityk() leaves two tables on the stack, // clear the stack lua_settop(L_, 0); // make vectors also iterators over elements const char* vectors[] = { "FuncVector", "VarVector", "PointVector", "RealVector" }; for (int i = 0; i < 4; ++i) { SWIG_Lua_get_class_metatable(L_, vectors[i]); SWIG_Lua_add_function(L_, "__call", lua_vector_iterator); lua_pop(L_, 1); } // define F swig_type_info *type_info = SWIG_TypeQuery(L_, "fityk::Fityk *"); assert(type_info != NULL); int owned = 1; Fityk *f = new Fityk(F); SWIG_NewPointerObj(L_, f, type_info, owned); lua_setglobal(L_, "F"); // redefine print UserInterface *ui = ctx_->ui(); lua_pushlightuserdata(L_, ui); lua_pushcclosure(L_, fityk_lua_print, 1); lua_setglobal(L_, "print"); // Python-like string formatting with % operator, based on // http://lua-users.org/wiki/StringInterpolation const char *lua_init_str = "getmetatable('').__mod = function(a, b)\n" " if not b then return a\n" " elseif type(b) == 'table' then return string.format(a, " #if LUA_VERSION_NUM >= 502 "table." #endif "unpack(b))\n" " else return string.format(a, b)\n" " end\n" "end\n"; int status = luaL_dostring(L_, lua_init_str); if (status != 0) // just in case, should not happen handle_lua_error(); } LuaBridge::~LuaBridge() { if (L_ != NULL) lua_close(L_); } void LuaBridge::exec_lua_script(const string& str) { // pass filename in arg[0], like in the Lua stand-alone interpreter lua_createtable(L_, 1, 0); lua_pushstring(L_, str.c_str()); lua_rawseti(L_, -2, 0); lua_setglobal(L_, "arg"); int status = luaL_dofile(L_, str.c_str()); if (status != 0) handle_lua_error(); } // for use in GUI EditorDlg bool LuaBridge::is_lua_line_incomplete(const char* str) { int status = luaL_loadstring(L_, str); if (status == LUA_ERRSYNTAX) { size_t lmsg; const char *msg = lua_tolstring(L_, -1, &lmsg); #if LUA_VERSION_NUM <= 501 if (lmsg >= 7 && strcmp(msg + lmsg - 7, "''") == 0) #else if (lmsg >= 5 && strcmp(msg + lmsg - 5, "") == 0) #endif { lua_pop(L_, 1); return true; } } lua_pop(L_, 1); return false; } void LuaBridge::exec_lua_string(const string& str) { int status = luaL_dostring(L_, str.c_str()); if (status == 0 && lua_gettop(L_) > 0) { // print returned values luaL_checkstack(L_, LUA_MINSTACK, "too many results to print"); lua_getglobal(L_, "print"); lua_insert(L_, 1); status = lua_pcall(L_, lua_gettop(L_)-1, 0, 0); } if (status != 0) // LUA_OK(=0) was added in Lua 5.2 handle_lua_error(); } void LuaBridge::exec_lua_output(const string& str) { int status = luaL_dostring(L_, ("return "+str).c_str()); if (status == 0) { int n = lua_gettop(L_); // number of args lua_getglobal(L_, "tostring"); for (int i = 1; i <= n; ++i) { lua_pushvalue(L_, -1); // tostring() lua_pushvalue(L_, i); // value lua_call(L_, 1, 1); const char *s = lua_tolstring(L_, -1, NULL); if (s == NULL) // luaL_error() long-jumps or throws and doesn't return luaL_error(L_, "cannot covert value to string"); UserInterface::Status r = ctx_->ui()->execute_line(s); if (r != UserInterface::kStatusOk && ctx_->get_settings()->on_error[0] != 'n'/*nothing*/) break; lua_pop(L_, 1); // pop tostring result } lua_settop(L_, 0); } if (status != 0) // LUA_OK(=0) was added in Lua 5.2 handle_lua_error(); } void LuaBridge::handle_lua_error() { const char *msg = lua_tostring(L_, -1); ctx_->ui()->warn("Lua Error:\n" + S(msg ? msg : "(non-string error)")); lua_pop(L_, 1); } } // namespace fityk #else // DISABLE_LUA namespace fityk { LuaBridge::LuaBridge(Full*) {} LuaBridge::~LuaBridge() {} void LuaBridge::close_lua() {} void LuaBridge::exec_lua_string(const std::string&) {} void LuaBridge::exec_lua_script(const std::string&) {} void LuaBridge::exec_lua_output(const std::string&) {} bool LuaBridge::is_lua_line_incomplete(const char*) { return true; } } #endif // DISABLE_LUA fityk-1.3.1/fityk/luabridge.h000066400000000000000000000013751302634723100161060ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_LUABRIDGE_H_ #define FITYK_LUABRIDGE_H_ #include "common.h" struct lua_State; namespace fityk { class Full; class BasicContext; class FITYK_API LuaBridge { public: LuaBridge(Full *F); ~LuaBridge(); void close_lua(); void exec_lua_string(const std::string& str); void exec_lua_script(const std::string& str); void exec_lua_output(const std::string& str); bool is_lua_line_incomplete(const char* str); //lua_State* state() { return L_ }; private: lua_State *L_; BasicContext* ctx_; void handle_lua_error(); DISALLOW_COPY_AND_ASSIGN(LuaBridge); }; } // namespace fityk #endif fityk-1.3.1/fityk/mgr.cpp000066400000000000000000000520561302634723100152720ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "mgr.h" #include #include #include #include #include "common.h" #include "var.h" #include "ast.h" #include "tplate.h" #include "func.h" #include "model.h" #include "settings.h" #include "logic.h" using namespace std; namespace fityk { ModelManager::ModelManager(const BasicContext* ctx) : ctx_(ctx), var_autoname_counter_(0), func_autoname_counter_(0) { assert(ctx != NULL); } ModelManager::~ModelManager() { purge_all_elements(functions_); purge_all_elements(variables_); } Model* ModelManager::create_model() { Model *m = new Model(ctx_, *this); models_.push_back(m); return m; } void ModelManager::delete_model(Model *m) { vector::iterator k = find(models_.begin(), models_.end(), m); assert (k != models_.end()); delete *k; models_.erase(k); } void ModelManager::sort_variables() { for (vector::iterator i = variables_.begin(); i != variables_.end(); ++i) (*i)->set_var_idx(variables_); int pos = 0; while (pos < size(variables_)) { int M = variables_[pos]->used_vars().get_max_idx(); if (M > pos) { swap(variables_[pos], variables_[M]); for (vector::iterator i = variables_.begin(); i != variables_.end(); ++i) (*i)->set_var_idx(variables_); } else ++pos; } } /* /// takes expression string and: /// if the string refers to existing variable -- returns its name /// otherwise -- creates a new variable and returns its name string ModelManager::get_or_make_variable(const VMData* vd) { int ret; if (vd->index != -1) { ret = vd->index; } else { ret = next_var_name(); assign_variable(ret, func); } assert(is_index(ret, variables_)); return ret; } */ Variable* make_compound_variable(const string &name, VMData* vd, const vector& all_variables) { //printf("make_compound_variable: %s\n", vm2str(*vd).c_str()); if (vd->has_op(OP_X)) throw ExecuteError("variable can't depend on x."); // re-index variables vector used_vars; vm_foreach (int, i, vd->get_mutable_code()) { if (*i == OP_SYMBOL) { ++i; const string& vname = all_variables[*i]->name; int idx = index_of_element(used_vars, vname); if (idx == -1) { idx = used_vars.size(); used_vars.push_back(vname); } *i = idx; } else if (VMData::has_idx(*i)) ++i; } vector op_trees = prepare_ast_with_der(*vd, used_vars.size()); return new Variable(name, used_vars, op_trees); } void ModelManager::eval_tilde(vector::iterator op, vector& code, const vector& nums) { assert(*op == OP_TILDE); // the first two ops are overwritten *op = OP_SYMBOL; ++op; assert(*op == OP_NUMBER); *op = variables_.size(); ++op; // the rest of ops is to be deleted after reading double value = nums[*op]; Variable *tilde_var = new Variable(next_var_name(), parameters_.size()); if (*(op+1) == OP_TILDE) { // TILDE,NUMBER,N1,TILDE -> SYMBOL,N2 code.erase(op, op+2); } else { // TILDE,NUMBER,N1,NUMBER,N2,NUMBER,N3 -> SYMBOL,N4 assert(*(op+1) == OP_NUMBER); tilde_var->domain.lo = nums[*(op+2)]; assert(*(op+3) == OP_NUMBER); tilde_var->domain.hi = nums[*(op+4)]; code.erase(op, op+5); } parameters_.push_back(value); variables_.push_back(tilde_var); } int ModelManager::make_variable(const string &name, VMData* vd) { assert(!name.empty()); const std::vector& code = vd->code(); const vector& nums = vd->numbers(); // simple variable [OP_TILDE OP_NUMBER idx OP_TILDE] or // [OP_TILDE OP_NUMBER idx OP_NUMBER idx OP_NUMBER idx] if (code.size() >= 4 && code[0] == OP_TILDE && code[1] == OP_NUMBER && code.size() == (code[3] == OP_TILDE ? 4 : 7)) { realt val = nums[code[2]]; // avoid changing order of parameters in case of "$var = ~1.23" int old_pos = find_variable_nr(name); Variable *var; if (old_pos != -1 && variables_[old_pos]->is_simple()) { int gpos = variables_[old_pos]->gpos(); // variable at old_pos will be deleted soon parameters_[gpos] = val; var = variables_[old_pos]; } else { old_pos = -1; var = new Variable(name, parameters_.size()); } bool old_domain = true; if (code.size() == 7) { var->domain = RealRange(nums[code[4]], nums[code[6]]); old_domain = false; } if (old_pos == -1) { parameters_.push_back(val); return add_variable(var, old_domain); } else { return old_pos; } } // compound variable else { // OP_TILDE -> new variable vector& mcode = vd->get_mutable_code(); for (vector::iterator op = mcode.begin(); op < mcode.end(); ++op) { if (*op == OP_TILDE) { eval_tilde(op, mcode, nums); ++op; } else if (VMData::has_idx(*op)) ++op; } Variable *var = make_compound_variable(name, vd, variables_); return add_variable(var, true); } } bool ModelManager::is_variable_referred(int i, string *first_referrer) { // A variable can be referred only by variables with larger index. for (int j = i+1; j < size(variables_); ++j) { if (variables_[j]->used_vars().has_idx(i)) { if (first_referrer) *first_referrer = "$" + variables_[j]->name; return true; } } for (vector::iterator j = functions_.begin(); j != functions_.end(); ++j) { if ((*j)->used_vars().has_idx(i)) { if (first_referrer) *first_referrer = "%" + (*j)->name; return true; } } return false; } vector ModelManager::get_variable_references(const string &name) const { int idx = find_variable_nr(name); vector refs; v_foreach (Variable*, i, variables_) if ((*i)->used_vars().has_idx(idx)) refs.push_back("$" + (*i)->name); v_foreach (Function*, i, functions_) for (int j = 0; j < (*i)->used_vars().get_count(); ++j) if ((*i)->used_vars().get_idx(j) == idx) refs.push_back("%" + (*i)->name + "." + (*i)->get_param(j)); return refs; } // set indices corresponding to variable names in all functions and variables void ModelManager::reindex_all() { for (vector::iterator i = variables_.begin(); i != variables_.end(); ++i) (*i)->set_var_idx(variables_); for (vector::iterator i = functions_.begin(); i != functions_.end(); ++i) { (*i)->update_var_indices(variables_); } } void ModelManager::remove_unreferred() { // remove auto-delete marked variables, which are not referred by others for (int i = variables_.size()-1; i >= 0; --i) if (is_auto(variables_[i]->name) && !is_variable_referred(i)) { delete variables_[i]; variables_.erase(variables_.begin() + i); } // re-index all functions and variables (in any case) reindex_all(); // remove unreferred parameters for (int i = size(parameters_)-1; i >= 0; --i) { bool del=true; for (int j = 0; j < size(variables_); ++j) if (variables_[j]->gpos() == i) { del=false; break; } if (del) { parameters_.erase(parameters_.begin() + i); // take care about parameter indices in variables and functions for (vector::iterator j = variables_.begin(); j != variables_.end(); ++j) (*j)->erased_parameter(i); for (vector::iterator j = functions_.begin(); j != functions_.end(); ++j) (*j)->erased_parameter(i); } } } /// puts Variable into `variables_' vector, checking dependencies int ModelManager::add_variable(Variable* new_var, bool old_domain) { auto_ptr var(new_var); var->set_var_idx(variables_); int pos = find_variable_nr(var->name); if (pos == -1) { pos = variables_.size(); variables_.push_back(var.release()); } else { if (var->used_vars().depends_on(pos, variables_)) { //check for loops throw ExecuteError("loop in dependencies of $" + var->name); } // Keep domain from old variable. It doesn't matter in most cases, // but in "$a={$a}; $a=~{$a}" keep original domain if (old_domain) var->domain = variables_[pos]->domain; delete variables_[pos]; variables_[pos] = var.release(); if (variables_[pos]->used_vars().get_max_idx() > pos) sort_variables(); remove_unreferred(); } return pos; } int ModelManager::copy_and_add_variable(const string& newname, const Variable* orig, const map& varmap) { Variable *var; if (orig->is_simple()) { realt val = orig->value(); parameters_.push_back(val); int gpos = parameters_.size() - 1; var = new Variable(newname, gpos); } else { vector vars; for (int i = 0; i != orig->used_vars().get_count(); ++i) { int v_idx = orig->used_vars().get_idx(i); assert(varmap.count(v_idx)); vars.push_back(varmap.find(v_idx)->second); } vector new_op_trees; v_foreach (OpTree*, i, orig->get_op_trees()) new_op_trees.push_back((*i)->clone()); var = new Variable(newname, vars, new_op_trees); } var->domain = orig->domain; return add_variable(var, false); } int ModelManager::assign_var_copy(const string &name, const string &orig) { assert(!name.empty()); const Variable* ov = find_variable(orig); map var_copies; for (int i = 0; i < size(variables_); ++i) { if (ov->used_vars().depends_on(i, variables_)) { const Variable* var_orig = variables_[i]; string newname = name_var_copy(var_orig); copy_and_add_variable(newname, var_orig, var_copies); var_copies[i] = newname; } } return copy_and_add_variable(name, ov, var_copies); } // names can contains '*' wildcards void ModelManager::delete_variables(const vector &names) { if (names.empty()) return; set nn; // find indices of variables_, expanding wildcards v_foreach (string, i, names) { if (i->find('*') == string::npos) { int k = find_variable_nr(*i); if (k == -1) throw ExecuteError("undefined variable: $" + *i); nn.insert(k); } else for (size_t j = 0; j != variables_.size(); ++j) if (match_glob(variables_[j]->name.c_str(), i->c_str())) nn.insert(j); } // Delete variables_. The descending index order is required to make // is_variable_referred() and variables_.erase() work properly. for (set::const_reverse_iterator i = nn.rbegin(); i != nn.rend(); ++i){ // Check for dependencies. string first_referrer; if (is_variable_referred(*i, &first_referrer)) { reindex_all(); remove_unreferred(); // post-delete throw ExecuteError("can't delete $" + get_variable(*i)->name + " because " + first_referrer + " depends on it."); } delete variables_[*i]; variables_.erase(variables_.begin() + *i); } // post-delete reindex_all(); remove_unreferred(); } void ModelManager::delete_funcs(const vector& names) { if (names.empty()) return; set nn; // find indices of functions, expanding wildcards v_foreach (string, i, names) { if (i->find('*') == string::npos) { int k = find_function_nr(*i); if (k == -1) throw ExecuteError("undefined function: %" + *i); nn.insert(k); } else for (size_t j = 0; j != functions_.size(); ++j) if (match_glob(functions_[j]->name.c_str(), i->c_str())) nn.insert(j); } // Delete functions. The descending index order is needed by .erase(). for (set::const_reverse_iterator i = nn.rbegin(); i != nn.rend(); ++i){ delete functions_[*i]; functions_.erase(functions_.begin() + *i); } // post-delete remove_unreferred(); update_indices_in_models(); } bool ModelManager::is_function_referred(int n) const { v_foreach (Model*, i, models_) { if (contains_element((*i)->get_ff().idx, n) || contains_element((*i)->get_zz().idx, n)) return true; } return false; } // post: call update_indices_in_models() void ModelManager::auto_remove_functions() { int func_size = functions_.size(); for (int i = func_size - 1; i >= 0; --i) if (is_auto(functions_[i]->name) && !is_function_referred(i)) { delete functions_[i]; functions_.erase(functions_.begin() + i); } if (func_size != size(functions_)) { remove_unreferred(); } } int ModelManager::find_function_nr(const string &name) const { for (int i = 0; i < size(functions_); ++i) if (functions_[i]->name == name) return i; return -1; } const Function* ModelManager::find_function(const string &name) const { int n = find_function_nr(name); if (n == -1) throw ExecuteError("undefined function: %" + name); return functions_[n]; } int ModelManager::find_variable_nr(const string &name) const { for (int i = 0; i < size(variables_); ++i) if (variables_[i]->name == name) return i; return -1; } const Variable* ModelManager::find_variable(const string &name) const { int n = find_variable_nr(name); if (n == -1) throw ExecuteError("undefined variable: $" + name); return variables_[n]; } int ModelManager::gpos_to_vpos(int gpos) const { assert(gpos >= 0 && gpos < size(parameters_)); for (size_t i = 0; i < variables_.size(); ++i) if (variables_[i]->gpos() == gpos) return i; assert(0); return 0; } void ModelManager::use_parameters() { use_external_parameters(parameters_); } void ModelManager::use_external_parameters(const vector &ext_param) { vm_foreach (Variable*, i, variables_) (*i)->recalculate(variables_, ext_param); vm_foreach (Function*, i, functions_) (*i)->do_precomputations(variables_); } void ModelManager::put_new_parameters(const vector &aa) { for (size_t i = 0; i < min(aa.size(), parameters_.size()); ++i) parameters_[i] = aa[i]; use_parameters(); } void ModelManager::set_domain(int n, const RealRange& domain) { variables_[n]->domain = domain; } int ModelManager::assign_func(const string &name, Tplate::Ptr tp, vector &args) { assert(tp); vector varnames; vm_foreach (VMData*, j, args) { int idx = (*j)->single_symbol() ? (*j)->code()[1] : make_variable(next_var_name(), *j); varnames.push_back(variables_[idx]->name); } Function *func = (*tp->create)(ctx_->get_settings(), name, tp, varnames); func->init(); return add_func(func); } int ModelManager::assign_func_copy(const string &name, const string &orig) { assert(!name.empty()); const Function* of = find_function(orig); map var_copies; for (int i = 0; i < size(variables_); ++i) { if (of->used_vars().depends_on(i, variables_)) { const Variable* var_orig = variables_[i]; string newname = name_var_copy(var_orig); copy_and_add_variable(newname, var_orig, var_copies); var_copies[i] = newname; } } vector varnames; for (int i = 0; i != of->used_vars().get_count(); ++i) { int v_idx = of->used_vars().get_idx(i); assert(var_copies.count(v_idx)); varnames.push_back(var_copies[v_idx]); } Tplate::Ptr tp = of->tp(); Function* func = (*tp->create)(ctx_->get_settings(), name, tp, varnames); func->init(); return add_func(func); } int ModelManager::add_func(Function* func) { func->update_var_indices(variables_); // if there is already function with the same name -- replace int nr = find_function_nr(func->name); if (nr != -1) { delete functions_[nr]; functions_[nr] = func; remove_unreferred(); ctx_->msg("%" + func->name + " replaced."); } else { nr = functions_.size(); functions_.push_back(func); ctx_->msg("%" + func->name + " created."); } return nr; } string ModelManager::name_var_copy(const Variable* v) { if (v->name[0] == '_') return next_var_name(); //for other names append "01" or increase the last two digits in name int vs = v->name.size(); int appendix = 0; string core = v->name; if (vs > 2 && is_int(string(v->name, vs-2, 2))) { // foo02 appendix = atoi(v->name.c_str()+vs-2); core.resize(vs-2); } while (true) { ++appendix; string new_varname = core + S(appendix/10) + S(appendix%10); if (find_variable_nr(new_varname) == -1) return new_varname; } } void ModelManager::substitute_func_param(const string &name, const string ¶m, VMData* vd) { int nr = find_function_nr(name); if (nr == -1) throw ExecuteError("undefined function: %" + name); Function* k = functions_[nr]; int v_idx = vd->single_symbol() ? vd->code()[1] : make_variable(next_var_name(), vd); k->set_param_name(k->get_param_nr(param), variables_[v_idx]->name); k->update_var_indices(variables_); remove_unreferred(); } realt ModelManager::variation_of_a(int n, realt variat) const { assert (0 <= n && n < size(parameters())); const Variable* v = get_variable(n); double lo = v->domain.lo, hi = v->domain.hi; double percent = ctx_->get_settings()->domain_percent; if (v->domain.lo_inf()) lo = v->value() * (1 - 0.01 * percent); if (v->domain.hi_inf()) hi = v->value() * (1 + 0.01 * percent); // return lower bound for variat=-1 and upper bound for variat=1 return lo + 0.5 * (variat + 1) * (hi - lo); } string ModelManager::next_var_name() { while (1) { string t = "_" + S(++var_autoname_counter_); if (find_variable_nr(t) == -1) return t; } } string ModelManager::next_func_name() { while (1) { string t = "_" + S(++func_autoname_counter_); if (find_function_nr(t) == -1) return t; } } void ModelManager::do_reset() { purge_all_elements(functions_); purge_all_elements(variables_); var_autoname_counter_ = 0; func_autoname_counter_ = 0; parameters_.clear(); //don't delete models, they should unregister itself update_indices_in_models(); } void ModelManager::update_indices(FunctionSum& sum) { sum.idx.clear(); size_t i = 0; while (i < sum.names.size()) { int k = find_function_nr(sum.names[i]); if (k == -1) sum.names.erase(sum.names.begin() + i); else { sum.idx.push_back(k); ++i; } } } void ModelManager::update_indices_in_models() { for (vector::iterator i = models_.begin(); i != models_.end(); ++i){ update_indices((*i)->get_ff()); update_indices((*i)->get_zz()); } } vector ModelManager::share_par_cmd(const string& par, bool share) { vector cmds; const string varname = "_" + par; string val_str; int nr = find_variable_nr(varname); if (share) { vector values; v_foreach (Function*, i, functions_) { int idx = index_of_element((*i)->tp()->fargs, par); if (idx != -1) values.push_back((*i)->av()[idx]); } if (values.empty()) return cmds; if (nr == -1) { sort(values.begin(), values.end()); double median = values[(values.size()-1)/2]; cmds.push_back("$" + varname + " = ~" + S(median)); } val_str = "$" + varname; } else { // undoing if (nr == -1) return cmds; val_str = get_variable(nr)->get_formula(parameters()); // varname (_hwhm or _shape) will be auto-deleted } cmds.push_back("%*." + par + " = " + val_str); return cmds; } } // namespace fityk fityk-1.3.1/fityk/mgr.h000066400000000000000000000111041302634723100147240ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_MGR_H_ #define FITYK_MGR_H_ #include #include "fityk.h" #include "tplate.h" // Tplate::Ptr namespace fityk { class Variable; class Function; class BasicContext; class Model; struct FunctionSum; /// keeps all functions and variables class FITYK_API ModelManager { public: static bool is_auto(const std::string& name) { return !name.empty() && name[0] == '_'; } ModelManager(const BasicContext* ctx); ~ModelManager(); Model* create_model(); void delete_model(Model *m); //int assign_variable(const std::string &name, const std::string &rhs); int assign_var_copy(const std::string &name, const std::string &orig); int make_variable(const std::string &name, VMData* vd); void delete_variables(const std::vector &name); /// returns -1 if not found or idx in variables if found int find_variable_nr(const std::string &name) const; const Variable* find_variable(const std::string &name) const; int gpos_to_vpos(int gpos) const; const Variable* gpos_to_var(int gpos) const { return variables_[gpos_to_vpos(gpos)]; } /// remove unreffered variables and parameters void remove_unreferred(); /// remove unreffered functions void auto_remove_functions(); bool is_function_referred(int n) const; // returns the global array of parameters const std::vector& parameters() const { return parameters_; } const std::vector& variables() const { return variables_; } const Variable* get_variable(int n) const { return variables_[n]; } //Variable* get_variable(int n) { return variables_[n]; } void set_domain(int n, const RealRange& domain); /// returns index of the new function in functions_ int assign_func(const std::string &name, Tplate::Ptr tp, std::vector &args); /// returns index of the new function in functions_ int assign_func_copy(const std::string &name, const std::string &orig); void substitute_func_param(const std::string &name, const std::string ¶m, VMData* vd); void delete_funcs(const std::vector &names); ///returns -1 if not found or idx in functions_ if found int find_function_nr(const std::string &name) const; const Function* find_function(const std::string &name) const; const std::vector& functions() const { return functions_; } const Function* get_function(int n) const { return functions_[n]; } /// calculate value and derivatives of all variables; /// do precomputations for all functions void use_parameters(); void use_external_parameters(const std::vector &ext_param); void put_new_parameters(const std::vector &aa); realt variation_of_a(int n, realt variat) const; std::vector get_variable_references(const std::string &name) const; void update_indices_in_models(); void do_reset(); std::vector share_par_cmd(const std::string& par, bool share); std::string next_var_name(); ///generate name for "anonymous" variable std::string next_func_name(); ///generate name for "anonymous" function private: const BasicContext* ctx_; std::vector models_; std::vector parameters_; /// sorted, a doesn't depend on b if idx(a)>idx(b) std::vector variables_; std::vector functions_; int var_autoname_counter_; ///for names for "anonymous" variables int func_autoname_counter_; ///for names for "anonymous" functions int add_variable(Variable* new_var, bool old_domain); void sort_variables(); int copy_and_add_variable(const std::string& name, const Variable* orig, const std::map& varmap); int add_func(Function* func); //std::string get_or_make_variable(const std::string& func); bool is_variable_referred(int i, std::string *first_referrer = NULL); void reindex_all(); std::string name_var_copy(const Variable* v); void update_indices(FunctionSum& sum); void eval_tilde(std::vector::iterator op, std::vector& code, const std::vector& nums); }; // used in mgr.cpp and udf.cpp Variable* make_compound_variable(const std::string &name, VMData* vd, const std::vector& all_variables); } // namespace fityk #endif fityk-1.3.1/fityk/model.cpp000066400000000000000000000171421302634723100156020ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "model.h" #include #include #include #include "common.h" #include "func.h" #include "var.h" #include "mgr.h" #include "logic.h" #include "ast.h" using namespace std; namespace fityk { void Model::destroy() { mgr_.delete_model(this); } void Model::clear() { if (ff_.names.empty() && zz_.names.empty()) return; ff_.names.clear(); ff_.idx.clear(); zz_.names.clear(); zz_.idx.clear(); //mgr_.auto_remove_functions(); //mgr.update_indices_in_models(); //F_->outdated_plot(); } /// checks if this model depends on the variable with index idx bool Model::is_dependent_on_var(int idx) const { const vector& vv = mgr_.variables(); v_foreach (int, i, ff_.idx) if (mgr_.get_function(*i)->used_vars().depends_on(idx, vv)) return true; v_foreach (int, i, zz_.idx) if (mgr_.get_function(*i)->used_vars().depends_on(idx, vv)) return true; return false; } realt Model::value(realt x) const { x += zero_shift(x); realt y = 0; v_foreach (int, i, ff_.idx) y += mgr_.get_function(*i)->calculate_value(x); return y; } realt Model::zero_shift(realt x) const { realt z = 0; v_foreach (int, i, zz_.idx) z += mgr_.get_function(*i)->calculate_value(x); return z; } void Model::compute_model(vector &x, vector &y, int ignore_func) const { // add x-correction to x v_foreach (int, i, zz_.idx) mgr_.get_function(*i)->calculate_value(x, x); // add y-value to y v_foreach (int, i, ff_.idx) if (*i != ignore_func) mgr_.get_function(*i)->calculate_value(x, y); } // returns y values in y, x is changed in place to x+Z, // derivatives are returned in dy_da as a matrix: // [ dy/da_1 (x_1) dy/da_2 (x_1) ... dy/da_na (x_1) dy/dx (x_1) ] // [ dy/da_1 (x_2) dy/da_2 (x_2) ... dy/da_na (x_2) dy/dx (x_2) ] // [ ... ] // [ dy/da_1 (x_n) dy/da_2 (x_n) ... dy/da_na (x_n) dy/dx (x_n) ] void Model::compute_model_with_derivs(vector &x, vector &y, vector &dy_da) const { assert(y.size() == x.size()); if (x.empty()) return; fill (dy_da.begin(), dy_da.end(), 0); // add x-correction to x v_foreach (int, i, zz_.idx) mgr_.get_function(*i)->calculate_value(x, x); // calculate value and derivatives v_foreach (int, i, ff_.idx) mgr_.get_function(*i)->calculate_value_deriv(x, y, dy_da, false); v_foreach (int, i, zz_.idx) mgr_.get_function(*i)->calculate_value_deriv(x, y, dy_da, true); } realt Model::calculate_value_and_deriv(realt x, vector &dy_da) const { vector bufx(1, x), bufy(1, 0); compute_model_with_derivs(bufx, bufy, dy_da); return bufy[0]; } vector Model::get_symbolic_derivatives(realt x, realt *y) const { int n = mgr_.parameters().size(); vector dy_da(n+1); // last item is dy/dx vector xx(1, x); vector yy(1); compute_model_with_derivs(xx, yy, dy_da); if (y != NULL) *y = yy[0]; return dy_da; } vector Model::get_numeric_derivatives(realt x, realt numerical_h) const { vector av_numder = mgr_.parameters(); int n = av_numder.size(); vector dy_da(n+1); const double small_number = 1e-10; //it only prevents h==0 for (int k = 0; k < n; k++) { realt acopy = av_numder[k]; realt h = max(fabs(acopy), small_number) * numerical_h; av_numder[k] -= h; mgr_.use_external_parameters(av_numder); realt y_aless = value(x); av_numder[k] = acopy + h; mgr_.use_external_parameters(av_numder); realt y_amore = value(x); dy_da[k] = (y_amore - y_aless) / (2 * h); av_numder[k] = acopy; } mgr_.use_parameters(); realt h = max(fabs(x), small_number) * numerical_h; dy_da[n] = (value(x+h) - value(x-h)) / (2 * h); return dy_da; } realt Model::approx_max(realt x_min, realt x_max) const { mgr_.use_parameters(); realt x = x_min; realt y_max = value(x); vector xx; v_foreach (int, i, ff_.idx) { realt ctr; if (mgr_.get_function(*i)->get_center(&ctr) && x_min < ctr && ctr < x_max) xx.push_back(ctr); } xx.push_back(x_max); sort(xx.begin(), xx.end()); v_foreach (realt, i, xx) { realt x_between = (x + *i)/2.; x = *i; realt y = max(value(x_between), value(x)); if (y > y_max) y_max = y; } return y_max; } string Model::get_peak_parameters(const vector& errors) const { string s; const SettingsMgr *sm = ctx_->settings_mgr(); s += "# PeakType\tCenter\tHeight\tArea\tFWHM\tparameters...\n"; v_foreach (int, i, ff_.idx) { const Function* p = mgr_.get_function(*i); s += "%" + p->name + " " + p->tp()->name; realt a; if (p->get_center(&a)) s += "\t" + sm->format_double(a); else s += "\tx"; if (p->get_height(&a)) s += "\t" + sm->format_double(a); else s += "\tx"; if (p->get_area(&a)) s += "\t" + sm->format_double(a); else s += "\tx"; if (p->get_fwhm(&a)) s += "\t" + sm->format_double(a); else s += "\tx"; s += "\t"; for (int j = 0; j < p->used_vars().get_count(); ++j) { s += " " + sm->format_double(p->av()[j]); if (!errors.empty()) { const Variable* var = mgr_.get_variable(p->used_vars().get_idx(j)); if (var->is_simple()) { double err = errors[var->gpos()]; s += " +/- " + sm->format_double(err); } else s += " +/- ?"; } } s += "\n"; } return s; } string Model::get_formula(bool simplify, const char* num_fmt, bool extra_breaks) const { if (ff_.names.empty()) return "0"; string shift; v_foreach (int, i, zz_.idx) { string expr = mgr_.get_function(*i)->get_current_formula("x", num_fmt); shift += "+" + (simplify ? simplify_formula(expr, num_fmt) : expr); } string x = "x"; if (!shift.empty()) x = "(x" + shift + ")"; string formula; v_foreach (int, i, ff_.idx) { string expr = mgr_.get_function(*i)->get_current_formula(x, num_fmt); if (i != ff_.idx.begin()) formula += (extra_breaks ? " +\n" : " + "); formula += (simplify ? simplify_formula(expr, num_fmt) : expr); } return formula; } const string& Model::get_func_name(char c, int idx) const { const vector& names = get_fz(c).names; if (idx < 0) idx += names.size(); if (!is_index(idx, names)) throw ExecuteError("wrong [index]: " + S(idx)); return names[idx]; } realt Model::numarea(realt x1, realt x2, int nsteps) const { x1 += zero_shift(x1); x2 += zero_shift(x2); realt a = 0; v_foreach (int, i, ff_.idx) a += mgr_.get_function(*i)->numarea(x1, x2, nsteps); return a; } int Model::max_param_pos() const { int n = 0; v_foreach (int, i, ff_.idx) n = max(mgr_.get_function(*i)->max_param_pos(), n); v_foreach (int, i, zz_.idx) n = max(mgr_.get_function(*i)->max_param_pos(), n); return n; } } // namespace fityk fityk-1.3.1/fityk/model.h000066400000000000000000000056261302634723100152530ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_SUM_H_ #define FITYK_SUM_H_ #include #include #include #include "fityk.h" #include "common.h" // DISALLOW_COPY_AND_ASSIGN namespace fityk { class ModelManager; class BasicContext; struct FunctionSum { /// names of functions in F/Z, i.e. names of the component functions std::vector names; /// indices corresponding to the names in names std::vector idx; bool empty() const { return names.empty(); } }; /// This class contains description of curve which we are trying to fit /// to data. This curve is described simply by listing names of functions /// in F and in Z (Z contains x-corrections) class FITYK_API Model { public: void destroy(); void clear(); /// calculate model (single point) realt value(realt x) const; /// calculate model (multiple points) without derivatives /// the option to ignore one function in F is useful for "guessing". void compute_model(std::vector &x, std::vector &y, int ignore_func=-1) const; /// calculate model (multiple points) with derivatives void compute_model_with_derivs(std::vector &x, std::vector &y, std::vector &dy_da) const; /// estimate max. value in given range (probe at peak centers and between) realt approx_max(realt x_min, realt x_max) const; std::string get_formula(bool simplify, const char *num_fmt, bool extra_breaks) const; std::string get_peak_parameters(const std::vector& errors) const; std::vector get_symbolic_derivatives(realt x, realt *y) const; std::vector get_numeric_derivatives(realt x, realt numerical_h)const; realt zero_shift(realt x) const; // ff_ and zz_ getters const FunctionSum& get_ff() const { return ff_; } FunctionSum& get_ff() { return ff_; } const FunctionSum& get_zz() const { return zz_; } FunctionSum& get_zz() { return zz_; } const FunctionSum& get_fz(char c) const { return (c == 'F' ? ff_ : zz_); } FunctionSum& get_fz(char c) { return (c == 'F' ? ff_ : zz_); } // throws SyntaxError if index `idx' is wrong const std::string& get_func_name(char c, int idx) const; realt numarea(realt x1, realt x2, int nsteps) const; bool is_dependent_on_var(int idx) const; int max_param_pos() const; realt calculate_value_and_deriv(realt x, std::vector &dy_da) const; private: const BasicContext* ctx_; ModelManager &mgr_; FunctionSum ff_, zz_; // can be created/deleted only from ModelManager friend class ModelManager; Model(const BasicContext *ctx, ModelManager &mgr) : ctx_(ctx), mgr_(mgr) {} ~Model() {} DISALLOW_COPY_AND_ASSIGN(Model); }; } // namespace fityk #endif fityk-1.3.1/fityk/numfuncs.cpp000066400000000000000000000234131302634723100163360ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "numfuncs.h" #include #include #include #include "common.h" using namespace std; namespace fityk { /// Returns position pos in sorted vector of points: points *pos and *(pos+1) /// can be used for interpolation of a value at x. /// Optimized for sequential calls with slowly increasing x's. template typename vector::iterator get_interpolation_segment(vector &bb, double x) { static size_t hint = 0; assert (size(bb) > 1); // when outside of the range, use the first or the last segment if (x <= bb[1].x) { hint = 0; return bb.begin(); } if (x >= bb.back().x) return bb.end() - 2; if (hint >= bb.size()) hint = 0; // check if hinted position is good typename vector::iterator pos = bb.begin() + hint; if (pos->x <= x) { //pos->x <= x and x < bb.back().x and bb is sorted => pos < bb.end()-1 if (x <= (pos+1)->x) { return pos; // nope, try the next position } if (pos+2 == bb.end() || x <= (pos+2)->x) { ++hint; return pos+1; } } // nope, use general search pos = lower_bound(bb.begin(), bb.end(), T(x, 0)) - 1; //printf("DEBUG: get_interpolation_segment %zu -> %zu / %zu (%g)\n", // hint, size_t(pos-bb.begin()), bb.size(), x); hint = pos - bb.begin(); return pos; } // explicit instantiation for use in bfunc.cpp in FuncPolyline template vector::iterator get_interpolation_segment(vector &bb, double x); void prepare_spline_interpolation (vector &bb) { //first wroten for bb interpolation, then generalized const int n = bb.size(); if (n == 0) return; //find d2y/dx2 and put it in .q bb[0].q = 0; //natural spline vector u(n); for (int k = 1; k <= n-2; k++) { PointQ *b = &bb[k]; double sig = (b->x - (b-1)->x) / ((b+1)->x - (b-1)->x); double t = sig * (b-1)->q + 2.; b->q = (sig - 1.) / t; u[k] = ((b+1)->y - b->y) / ((b+1)->x - b->x) - (b->y - (b-1)->y) / (b->x - (b - 1)->x); u[k] = (6. * u[k] / ((b+1)->x - (b-1)->x) - sig * u[k-1]) / t; } bb.back().q = 0; for (int k = n-2; k >= 0; k--) { PointQ *b = &bb[k]; b->q = b->q * (b+1)->q + u[k]; } } double get_spline_interpolation(vector &bb, double x) { if (bb.empty()) return 0.; if (bb.size() == 1) return bb[0].y; vector::iterator pos = get_interpolation_segment(bb, x); // based on Numerical Recipes www.nr.com double h = (pos+1)->x - pos->x; double a = ((pos+1)->x - x) / h; double b = (x - pos->x) / h; double t = a * pos->y + b * (pos+1)->y + ((a * a * a - a) * pos->q + (b * b * b - b) * (pos+1)->q) * (h * h) / 6.; return t; } template double get_linear_interpolation_(vector &bb, double x) { if (bb.empty()) return 0.; if (bb.size() == 1) return bb[0].y; typename vector::iterator pos = get_interpolation_segment(bb, x); double a = ((pos + 1)->y - pos->y) / ((pos + 1)->x - pos->x); return pos->y + a * (x - pos->x); } double get_linear_interpolation(vector &bb, double x) { return get_linear_interpolation_(bb, x); } double get_linear_interpolation(vector &bb, double x) { return get_linear_interpolation_(bb, x); } // random number utilities static const double TINY = 1e-12; //only for rand_gauss() and rand_cauchy() /// normal distribution, mean=0, variance=1 double rand_gauss() { static bool is_saved = false; static double saved; if (!is_saved) { double rsq, x1, x2; while(1) { x1 = rand_1_1(); x2 = rand_1_1(); rsq = x1 * x1 + x2 * x2; if (rsq >= TINY && rsq < 1) break; } double f = sqrt(-2. * log(rsq) / rsq); saved = x1 * f; is_saved = true; return x2 * f; } else { is_saved = false; return saved; } } double rand_cauchy() { while (1) { double x1 = rand_1_1(); double x2 = rand_1_1(); double rsq = x1 * x1 + x2 * x2; if (rsq >= TINY && rsq < 1 && fabs(x1) >= TINY) return (x2 / x1); } } // matrix is in vec, m rows, n columns string format_matrix(const vector& vec, int m, int n, const char *mname) { assert (size(vec) == m * n); soft_assert(!vec.empty()); string h = S(mname) + "={ "; if (m == 1) { // vector for (int i = 0; i < n; i++) h += S(vec[i]) + (i < n - 1 ? ", " : " }") ; } else { //matrix string blanks(strlen(mname) + 1, ' '); for (int j = 0; j < m; j++){ if (j > 0) h += blanks + " "; for (int i = 0; i < n; i++) h += S(vec[j * n + i]) + ", "; h += "\n"; } h += blanks + "}"; } return h; } /// This function solves a set of linear algebraic equations using /// Gauss-Jordan elimination with partial pivoting. /// /// A * x = b /// /// A is n x n matrix, realt A[n*n] /// b is vector b[n], /// Function returns vector x[] in b[], and 1-matrix in A[]. /// return value: true=OK, false=singular matrix /// with special exception: /// if i'th row, i'th column and i'th element in b all contains zeros, /// it's just ignored, void jordan_solve(vector& A, vector& b, int n) { assert (size(A) == n*n && size(b) == n); for (int i = 0; i < n; i++) { // looking for a pivot element int maxnr = -1; realt amax = 0; for (int j = i; j < n; j++) if (fabs (A[n*j+i]) > amax) { maxnr = j; amax = fabs (A[n * j + i]); } // handle singular matrix if (maxnr == -1) { // i-th column has only zeros. // If it's the same about i-th row, and b[i]==0, let x[i]==0. for (int j = i; j < n; j++) if (A[n * i + j] || b[i]) { // printf("%s\n", format_matrix(A, n, n, "A")); printf("%s\n", format_matrix(b, 1, n, "b").c_str()); throw ExecuteError("Trying to reverse singular matrix." " Column " + S(i) + " is zeroed."); } continue; // x[i]=b[i], b[i]==0 } // interchanging rows if (maxnr != i) { for (int j = i; j < n; j++) swap (A[n*maxnr+j], A[n*i+j]); swap (b[i], b[maxnr]); } // divide by a_ii -- to get a_ii=1 realt c = 1.0 / A[i*n+i]; for (int j = i; j < n; j++) A[i*n+j] *= c; b[i] *= c; // subtract -- to zero all remaining elements of this row for (int k = 0; k < n; k++) if (k != i) { realt d = A[k * n + i]; for (int j = i; j < n; j++) A[k * n + j] -= A[i * n + j] * d; b[k] -= b[i] * d; } } } /// Invert matrix using Gauss-Jordan elimination with partial pivoting, /// based on http://www.isical.ac.in/~arnabc/matalgop1.pdf /// A - matrix n x n; returns A^(-1) in A void invert_matrix(vector&A, int n) { assert(size(A) == n*n); vector row_swaps(n); for (int i = 0; i != n; ++i) { // looking for a pivot element int maxnr = -1; realt amax = 0; for (int j = i; j != n; ++j) if (fabs(A[j*n+i]) > amax) { maxnr = j; amax = fabs(A[j*n+i]); } row_swaps[i] = maxnr; // handle singular matrix if (maxnr == -1) { // As a special exception we allow singular matrix if both // i-th column and i-th row are completely zeroed. // Such row and column are ignored and unchanged. // (Pivoting doesn't move such column+row.) // Actually this exception is not be necessary. for (int j = i; j != n; ++j) if (A[i*n+j] != 0.) { // changed wording from jordan_solve() - to tell them apart throw ExecuteError("Singular matrix cannot be reversed." " (zeroed column " + S(i) + ")."); } continue; } // interchanging rows if (maxnr != i) { for (int j = 0; j != n; j++) swap(A[maxnr*n+j], A[i*n+j]); } realt inv_piv = 1. / A[i*n+i]; for (int k = 0; k != n; ++k) if (k != i) { realt d = A[k*n+i] * inv_piv; for (int j = 0; j != n; ++j) { if (j == i) A[k*n+j] = -d; else A[k*n+j] -= A[i*n+j] * d; } } for (int j = 0; j != n; ++j) A[i*n+j] *= inv_piv; A[i*n+i] = inv_piv; } // apply the swaps in reverse order - row swap becomes a column swap for (int i = n-1; i >= 0; --i) { int p = row_swaps[i]; if (p != -1 && p != i) for (int j = 0; j != n; ++j) swap(A[j*n+p], A[j*n+i]); } } void SimplePolylineConvex::push_point(PointD const& p) { if (vertices_.size() < 2 || is_left(*(vertices_.end() - 2), *(vertices_.end() - 1), p)) vertices_.push_back(p); else { // the middle point (the last one currently in vertices_) is not convex // remove it and check again the last three points vertices_.pop_back(); push_point(p); } } } // namespace fityk fityk-1.3.1/fityk/numfuncs.h000066400000000000000000000133751302634723100160110ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_NUMFUNCS_H_ #define FITYK_NUMFUNCS_H_ #include #include "fityk.h" #include "common.h" // S namespace fityk { /// Point used for linear interpolation and polyline convex hull algorithm. struct PointD { double x, y; PointD() {} PointD(double x_, double y_) : x(x_), y(y_) {} bool operator< (const PointD& b) const { return x < b.x; } }; /// Point used for spline/polyline interpolation. /// The q parameter is used for cubic spline computation. struct PointQ { double x, y; double q; /* q is used for spline */ PointQ() {} PointQ(double x_, double y_) : x(x_), y(y_) {} bool operator< (const PointQ& b) const { return x < b.x; } }; /// must be run before computing value of cubic spline in point x /// results are written in PointQ::q /// based on Numerical Recipes www.nr.com FITYK_API void prepare_spline_interpolation (std::vector &bb); // instantiated for T = PointQ, PointD template typename std::vector::iterator get_interpolation_segment(std::vector &bb, double x); FITYK_API double get_spline_interpolation(std::vector &bb, double x); FITYK_API double get_linear_interpolation(std::vector &bb, double x); FITYK_API double get_linear_interpolation(std::vector &bb, double x); // random number utilities inline double rand_1_1() { return 2.0 * rand() / RAND_MAX - 1.; } inline double rand_0_1() { return static_cast(rand()) / RAND_MAX; } inline double rand_uniform(double a, double b) { return a + rand_0_1()*(b-a); } inline bool rand_bool() { return rand() < RAND_MAX / 2; } double rand_gauss(); double rand_cauchy(); // very simple matrix utils void jordan_solve(std::vector& A, std::vector& b, int n); FITYK_API void invert_matrix(std::vector&A, int n); // format (for printing) matrix m x n stored in vec. `mname' is name/comment. std::string format_matrix(const std::vector& vec, int m, int n, const char *mname); // Simple Polyline Convex Hull Algorithms // takes as input a sequence of points (x,y), with increasing x coord (added // in push_point()) and returns points of convex hull (get_vertices()) class FITYK_API SimplePolylineConvex { public: void push_point(double x, double y) { push_point(PointD(x, y)); } void push_point(PointD const& p); std::vector const& get_vertices() const { return vertices_; } // test if point p2 left of the line through p0 and p1 static bool is_left(PointD const& p0, PointD const& p1, PointD const& p2) { return (p1.x - p0.x)*(p2.y - p0.y) > (p2.x - p0.x)*(p1.y - p0.y); } private: std::vector vertices_; }; /// search x in [x1, x2] for which %f(x)==val, /// x1, x2, val: f(x1) <= val <= f(x2) or f(x2) <= val <= f(x1) /// bisection + Newton-Raphson template realt find_x_with_value(T *func, realt x1, realt x2, realt val) { const int max_iter = 1000; std::vector dy_da(func->max_param_pos() + 1, 0); // we don't need derivatives here, but to make it simpler.. realt y1 = func->calculate_value_and_deriv(x1, dy_da) - val; realt y2 = func->calculate_value_and_deriv(x2, dy_da) - val; if ((y1 > 0 && y2 > 0) || (y1 < 0 && y2 < 0)) throw ExecuteError("Value " + S(val) + " is not bracketed by " + S(x1) + "(" + S(y1+val) + ") and " + S(x2) + "(" + S(y2+val) + ")."); if (y1 == 0) return x1; if (y2 == 0) return x2; if (y1 > 0) std::swap(x1, x2); realt t = (x1 + x2) / 2.; for (int i = 0; i < max_iter; ++i) { //check if converged if (is_eq(x1, x2)) return (x1+x2) / 2.; // calculate f and df dy_da.back() = 0; realt f = func->calculate_value_and_deriv(t, dy_da) - val; realt df = dy_da.back(); // narrow the range if (f == 0.) return t; else if (f < 0) x1 = t; else // f > 0 x2 = t; // select new guess point realt dx = -f/df * 1.02; // 1.02 is to jump to the other side of point if ((t+dx > x2 && t+dx > x1) || (t+dx < x2 && t+dx < x1) // outside || i % 20 == 19) { // precaution //bisection t = (x1 + x2) / 2.; } else { t += dx; } } throw ExecuteError("The search has not converged."); } /// finds root of derivative, using bisection method template realt find_extremum(T *func, realt x1, realt x2) { const int max_iter = 1000; std::vector dy_da(func->max_param_pos() + 1, 0); // calculate df dy_da.back() = 0; func->calculate_value_and_deriv(x1, dy_da); realt y1 = dy_da.back(); dy_da.back() = 0; func->calculate_value_and_deriv(x2, dy_da); realt y2 = dy_da.back(); if ((y1 > 0 && y2 > 0) || (y1 < 0 && y2 < 0)) throw ExecuteError("Derivatives at " + S(x1) + " and " + S(x2) + " have the same sign."); if (y1 == 0) return x1; if (y2 == 0) return x2; if (y1 > 0) std::swap(x1, x2); for (int i = 0; i < max_iter; ++i) { realt t = (x1 + x2) / 2.; // calculate df dy_da.back() = 0; func->calculate_value_and_deriv(t, dy_da); realt df = dy_da.back(); // narrow the range if (df == 0.) return t; else if (df < 0) x1 = t; else // df > 0 x2 = t; //check if converged if (is_eq(x1, x2)) return (x1+x2) / 2.; } throw ExecuteError("The search has not converged."); } } // namespace fityk #endif fityk-1.3.1/fityk/root/000077500000000000000000000000001302634723100147545ustar00rootroot00000000000000fityk-1.3.1/fityk/root/LICENSE000066400000000000000000000635701302634723100157740ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, 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 this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), 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 distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey 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 library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! fityk-1.3.1/fityk/root/README.md000066400000000000000000000002771302634723100162410ustar00rootroot00000000000000 This directory contains code extracted from [ROOT](https://root.cern.ch/), available under the LGPL 2.1 (see the LICENSE file in this directory or https://root.cern.ch/license for details). fityk-1.3.1/fityk/root/background.cpp000066400000000000000000001247301302634723100176060ustar00rootroot00000000000000// @(#)root/spectrum:$Id$ // Author: Miroslav Morhac 27/05/99 /************************************************************************* * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ // Modified by Cristiano Fontana 17/11/2016 // Eliminated the dependency on ROOT #include #include #include "background.hpp" //////////////////////////////////////////////////////////////////////////////// /// This function calculates background spectrum from source spectrum. /// The result is placed in the vector pointed by spectrum pointer. /// The goal is to separate the useful information (peaks) from useless /// information (background). /// /// - method is based on Sensitive Nonlinear Iterative Peak (SNIP) clipping /// algorithm. /// - new value in the channel "i" is calculated /// /// \f[ /// v_p(i) = min \left\{ v_{p-1}(i)^{\frac{\left[v_{p-1}(i+p)+v_{p-1}(i-p)\right]}{2}} \right\} /// \f] /// /// where p = 1, 2, ..., numberIterations. In fact it represents second order /// difference filter (-1,2,-1). /// /// One can also change the /// direction of the change of the clipping window, the order of the clipping /// filter, to include smoothing, to set width of smoothing window and to include /// the estimation of Compton edges. On successful completion it returns 0. On /// error it returns pointer to the string describing error. /// /// #### Parameters: /// /// - spectrum: vector of source spectrum /// - numberIterations: maximal width of clipping window, /// - direction: direction of change of clipping window. /// Possible values: kBackIncreasingWindow, kBackDecreasingWindow /// - filterOrder: order of clipping filter. /// Possible values: kBackOrder2, kBackOrder4, kBackOrder6, kBackOrder8 /// - smoothing: logical variable whether the smoothing operation in the /// estimation of background will be included. /// Possible values: kFALSE, kTRUE /// - smoothWindow: width of smoothing window. /// Possible values: kBackSmoothing3, kBackSmoothing5, kBackSmoothing7, /// kBackSmoothing9, kBackSmoothing11, kBackSmoothing13, kBackSmoothing15. /// - compton: logical variable whether the estimation of Compton edge will be /// included. Possible values: kFALSE, kTRUE. /// /// #### Return: /// /// A vector with the estimated background. /// /// #### References: /// /// 1. C. G Ryan et al.: SNIP, a statistics-sensitive background treatment for the /// quantitative analysis of PIXE spectra in geoscience applications. NIM, B34 /// (1988), 396-402. /// /// 2. M. Morhac;, J. Kliman, V. Matouoek, M. Veselsky, I. Turzo: /// Background elimination methods for multidimensional gamma-ray spectra. NIM, /// A401 (1997) 113-132. /// /// 3. D. D. Burgess, R. J. Tervo: Background estimation for gamma-ray /// spectroscopy. NIM 214 (1983), 431-434. /// /// ## Examples from the ROOT documentation /// /// ### Example 1 script Background_incr.c: /// /// \image html TSpectrum_Background_incr.jpg Fig. 1 Example of the estimation of background for number of iterations=6. Original spectrum is shown in black color, estimated background in red color. /// /// #### Script: /// /// ~~~ {.cpp} /// // Example to illustrate the background estimator (class TSpectrum). /// // To execute this example, do /// // root > .x Background_incr.C /// /// #include /// /// void Background_incr() { /// Int_t i; /// Double_t nbins = 256; /// Double_t xmin = 0; /// Double_t xmax = nbins; /// Double_t * source = new Double_t[nbins]; /// TH1F *back = new TH1F("back","",nbins,xmin,xmax); /// TH1F *d = new TH1F("d","",nbins,xmin,xmax); /// TFile *f = new TFile("spectra/TSpectrum.root"); /// back=(TH1F*) f->Get("back1;1"); /// TCanvas *Background = gROOT->GetListOfCanvases()->FindObject("Background"); /// if (!Background) Background = /// new TCanvas("Background", /// "Estimation of background with increasing window", /// 10,10,1000,700); /// back->Draw("L"); /// TSpectrum *s = new TSpectrum(); /// for (i = 0; i < nbins; i++) source[i]=back->GetBinContent(i + 1); /// s->Background(source,nbins,6,kBackIncreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d->SetBinContent(i + 1,source[i]); /// d->SetLineColor(kRed); /// d->Draw("SAME L"); /// } /// ~~~ /// /// ### Example 2 script Background_decr.c: /// /// In Fig. 1. one can notice that at the edges of the peaks the estimated /// background goes under the peaks. An alternative approach is to decrease the /// clipping window from a given value numberIterations to the value of one, which /// is presented in this example. /// /// \image html TSpectrum_Background_decr.jpg Fig. 2 Example of the estimation of background for numberIterations=6 using decreasing clipping window algorithm. Original spectrum is shown in black color, estimated background in red color. /// /// #### Script: /// /// ~~~ {.cpp} /// // Example to illustrate the background estimator (class TSpectrum). /// // To execute this example, do /// // root > .x Background_decr.C /// /// #include /// /// void Background_decr() { /// Int_t i; /// Double_t nbins = 256; /// Double_t xmin = 0; /// Double_t xmax = nbins; /// Double_t * source = new Double_t[nbins]; /// TH1F *back = new TH1F("back","",nbins,xmin,xmax); /// TH1F *d = new TH1F("d","",nbins,xmin,xmax); /// TFile *f = new TFile("spectra/TSpectrum.root"); /// back=(TH1F*) f->Get("back1;1"); /// TCanvas *Background = gROOT->GetListOfCanvases()->FindObject("Background"); /// if (!Background) Background = /// new TCanvas("Background","Estimation of background with decreasing window", /// 10,10,1000,700); /// back->Draw("L"); /// TSpectrum *s = new TSpectrum(); /// for (i = 0; i < nbins; i++) source[i]=back->GetBinContent(i + 1); /// s->Background(source,nbins,6,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d->SetBinContent(i + 1,source[i]); /// d->SetLineColor(kRed); /// d->Draw("SAME L"); /// } /// ~~~ /// /// ### Example 3 script Background_width.c: /// /// The question is how to choose the width of the clipping window, i.e., /// numberIterations parameter. The influence of this parameter on the estimated /// background is illustrated in Fig. 3. /// /// \image html TSpectrum_Background_width.jpg Fig. 3 Example of the influence of clipping window width on the estimated background for numberIterations=4 (red line), 6 (blue line) 8 (green line) using decreasing clipping window algorithm. /// /// in general one should set this parameter so that the value /// 2*numberIterations+1 was greater than the widths of preserved objects (peaks). /// /// #### Script: /// /// ~~~ {.cpp} /// // Example to illustrate the influence of the clipping window width on the /// // estimated background. To execute this example, do: /// // root > .x Background_width.C /// /// #include /// /// void Background_width() { /// Int_t i; /// Double_t nbins = 256; /// Double_t xmin = 0; /// Double_t xmax = nbins; /// Double_t * source = new Double_t[nbins]; /// TH1F *h = new TH1F("h","",nbins,xmin,xmax); /// TH1F *d1 = new TH1F("d1","",nbins,xmin,xmax); /// TH1F *d2 = new TH1F("d2","",nbins,xmin,xmax); /// TH1F *d3 = new TH1F("d3","",nbins,xmin,xmax); /// TFile *f = new TFile("spectra/TSpectrum.root"); /// h=(TH1F*) f->Get("back1;1"); /// TCanvas *background = gROOT->GetListOfCanvases()->FindObject("background"); /// if (!background) background = new TCanvas("background", /// "Influence of clipping window width on the estimated background", /// 10,10,1000,700); /// h->Draw("L"); /// TSpectrum *s = new TSpectrum(); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,4,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d1->SetBinContent(i + 1,source[i]); /// d1->SetLineColor(kRed); /// d1->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,6,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d2->SetBinContent(i + 1,source[i]); /// d2->SetLineColor(kBlue); /// d2->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,8,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d3->SetBinContent(i + 1,source[i]); /// d3->SetLineColor(kGreen); /// d3->Draw("SAME L"); /// } /// ~~~ /// /// ### Example 4 script Background_width2.c: /// /// another example for very complex spectrum is given in Fig. 4. /// /// \image html TSpectrum_Background_width2.jpg Fig. 4 Example of the influence of clipping window width on the estimated background for numberIterations=10 (red line), 20 (blue line), 30 (green line) and 40 (magenta line) using decreasing clipping window algorithm. /// /// #### Script: /// /// ~~~ {.cpp} /// // Example to illustrate the influence of the clipping window width on the /// // estimated background. To execute this example, do: /// // root > .x Background_width2.C /// /// #include /// /// void Background_width2() { /// Int_t i; /// Double_t nbins = 4096; /// Double_t xmin = 0; /// Double_t xmax = 4096; /// Double_t * source = new Double_t[nbins]; /// TH1F *h = new TH1F("h","",nbins,xmin,xmax); /// TH1F *d1 = new TH1F("d1","",nbins,xmin,xmax); /// TH1F *d2 = new TH1F("d2","",nbins,xmin,xmax); /// TH1F *d3 = new TH1F("d3","",nbins,xmin,xmax); /// TH1F *d4 = new TH1F("d4","",nbins,xmin,xmax); /// TFile *f = new TFile("spectra/TSpectrum.root"); /// h=(TH1F*) f->Get("back2;1"); /// TCanvas *background = gROOT->GetListOfCanvases()->FindObject("background"); /// if (!background) background = new TCanvas("background", /// "Influence of clipping window width on the estimated background", /// 10,10,1000,700); /// h->SetAxisRange(0,1000); /// h->SetMaximum(20000); /// h->Draw("L"); /// TSpectrum *s = new TSpectrum(); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,10,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d1->SetBinContent(i + 1,source[i]); /// d1->SetLineColor(kRed); /// d1->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,20,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d2->SetBinContent(i + 1,source[i]); /// d2->SetLineColor(kBlue); /// d2->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,30,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d3->SetBinContent(i + 1,source[i]); /// d3->SetLineColor(kGreen); /// d3->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,10,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d4->SetBinContent(i + 1,source[i]); /// d4->SetLineColor(kMagenta); /// d4->Draw("SAME L"); /// } /// ~~~ /// /// ### Example 5 script Background_order.c: /// /// Second order difference filter removes linear (quasi-linear) background and /// preserves symmetrical peaks. However if the shape of the background is more /// complex one can employ higher-order clipping filters (see example in Fig. 5) /// /// \image html TSpectrum_Background_order.jpg Fig. 5 Example of the influence of clipping filter difference order on the estimated background for fNnumberIterations=40, 2-nd order red line, 4-th order blue line, 6-th order green line and 8-th order magenta line, and using decreasing clipping window algorithm. /// /// #### Script: /// /// ~~~ {.cpp} /// // Example to illustrate the influence of the clipping filter difference order /// // on the estimated background. To execute this example, do /// // root > .x Background_order.C /// /// #include /// /// void Background_order() { /// Int_t i; /// Double_t nbins = 4096; /// Double_t xmin = 0; /// Double_t xmax = 4096; /// Double_t * source = new Double_t[nbins]; /// TH1F *h = new TH1F("h","",nbins,xmin,xmax); /// TH1F *d1 = new TH1F("d1","",nbins,xmin,xmax); /// TH1F *d2 = new TH1F("d2","",nbins,xmin,xmax); /// TH1F *d3 = new TH1F("d3","",nbins,xmin,xmax); /// TH1F *d4 = new TH1F("d4","",nbins,xmin,xmax); /// TFile *f = new TFile("spectra/TSpectrum.root"); /// h=(TH1F*) f->Get("back2;1"); /// TCanvas *background = gROOT->GetListOfCanvases()->FindObject("background"); /// if (!background) background = new TCanvas("background", /// "Influence of clipping filter difference order on the estimated background", /// 10,10,1000,700); /// h->SetAxisRange(1220,1460); /// h->SetMaximum(11000); /// h->Draw("L"); /// TSpectrum *s = new TSpectrum(); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,40,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d1->SetBinContent(i + 1,source[i]); /// d1->SetLineColor(kRed); /// d1->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,40,kBackDecreasingWindow,kBackOrder4,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d2->SetBinContent(i + 1,source[i]); /// d2->SetLineColor(kBlue); /// d2->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,40,kBackDecreasingWindow,kBackOrder6,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d3->SetBinContent(i + 1,source[i]); /// d3->SetLineColor(kGreen); /// d3->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,40,kBackDecreasingWindow,kBackOrder8,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d4->SetBinContent(i + 1,source[i]); /// d4->SetLineColor(kMagenta); /// d4->Draw("SAME L"); /// } /// ~~~ /// /// ### Example 6 script Background_smooth.c: /// /// The estimate of the background can be influenced by noise present in the /// spectrum. We proposed the algorithm of the background estimate with /// simultaneous smoothing. In the original algorithm without smoothing, the /// estimated background snatches the lower spikes in the noise. Consequently, /// the areas of peaks are biased by this error. /// /// \image html TSpectrum_Background_smooth1.jpg Fig. 7 Principle of background estimation algorithm with simultaneous smoothing. /// \image html TSpectrum_Background_smooth2.jpg Fig. 8 Illustration of non-smoothing (red line) and smoothing algorithm of background estimation (blue line). /// /// #### Script: /// /// ~~~ {.cpp} /// // Example to illustrate the background estimator (class TSpectrum) including /// // Compton edges. To execute this example, do: /// // root > .x Background_smooth.C /// /// #include /// /// void Background_smooth() { /// Int_t i; /// Double_t nbins = 4096; /// Double_t xmin = 0; /// Double_t xmax = nbins; /// Double_t * source = new Double_t[nbins]; /// TH1F *h = new TH1F("h","",nbins,xmin,xmax); /// TH1F *d1 = new TH1F("d1","",nbins,xmin,xmax); /// TH1F *d2 = new TH1F("d2","",nbins,xmin,xmax); /// TFile *f = new TFile("spectra/TSpectrum.root"); /// h=(TH1F*) f->Get("back4;1"); /// TCanvas *background = gROOT->GetListOfCanvases()->FindObject("background"); /// if (!background) background = new TCanvas("background", /// "Estimation of background with noise",10,10,1000,700); /// h->SetAxisRange(3460,3830); /// h->Draw("L"); /// TSpectrum *s = new TSpectrum(); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,6,kBackDecreasingWindow,kBackOrder2,kFALSE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d1->SetBinContent(i + 1,source[i]); /// d1->SetLineColor(kRed); /// d1->Draw("SAME L"); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,6,kBackDecreasingWindow,kBackOrder2,kTRUE, /// kBackSmoothing3,kFALSE); /// for (i = 0; i < nbins; i++) d2->SetBinContent(i + 1,source[i]); /// d2->SetLineColor(kBlue); /// d2->Draw("SAME L"); /// } /// ~~~ /// /// ### Example 8 script Background_compton.c: /// /// Sometimes it is necessary to include also the Compton edges into the estimate of /// the background. In Fig. 8 we present the example of the synthetic spectrum /// with Compton edges. The background was estimated using the 8-th order filter /// with the estimation of the Compton edges using decreasing /// clipping window algorithm (numberIterations=10) with smoothing /// (smoothingWindow=5). /// /// \image html TSpectrum_Background_compton.jpg Fig. 8 Example of the estimate of the background with Compton edges (red line) for numberIterations=10, 8-th order difference filter, using decreasing clipping window algorithm and smoothing (smoothingWindow=5). /// /// #### Script: /// /// ~~~ {.cpp} /// // Example to illustrate the background estimator (class TSpectrum) including /// // Compton edges. To execute this example, do: /// // root > .x Background_compton.C /// /// #include /// /// void Background_compton() { /// Int_t i; /// Double_t nbins = 512; /// Double_t xmin = 0; /// Double_t xmax = nbins; /// Double_t * source = new Double_t[nbins]; /// TH1F *h = new TH1F("h","",nbins,xmin,xmax); /// TH1F *d1 = new TH1F("d1","",nbins,xmin,xmax); /// TFile *f = new TFile("spectra/TSpectrum.root"); /// h=(TH1F*) f->Get("back3;1"); /// TCanvas *background = gROOT->GetListOfCanvases()->FindObject("background"); /// if (!background) background = new TCanvas("background", /// "Estimation of background with Compton edges under peaks",10,10,1000,700); /// h->Draw("L"); /// TSpectrum *s = new TSpectrum(); /// for (i = 0; i < nbins; i++) source[i]=h->GetBinContent(i + 1); /// s->Background(source,nbins,10,kBackDecreasingWindow,kBackOrder8,kTRUE, /// kBackSmoothing5,,kTRUE); /// for (i = 0; i < nbins; i++) d1->SetBinContent(i + 1,source[i]); /// d1->SetLineColor(kRed); /// d1->Draw("SAME L"); /// } /// ~~~ std::vector background::background(std::vector spectrum, int numberIterations, int direction, int filterOrder, bool smoothing, int smoothWindow, bool compton) { int i, j, w, bw, b1, b2, priz; double a, b, c, d, e, yb1, yb2, ai, av, men, b4, c4, d4, e4, b6, c6, d6, e6, f6, g6, b8, c8, d8, e8, f8, g8, h8, i8; const unsigned int ssize = spectrum.size(); if (ssize <= 0) throw "Wrong Parameters"; if (numberIterations < 1) throw "Width of Clipping Window Must Be Positive"; if (ssize < 2 * numberIterations + 1) throw "Too Large Clipping Window"; if (smoothing == true && smoothWindow != kBackSmoothing3 && smoothWindow != kBackSmoothing5 && smoothWindow != kBackSmoothing7 && smoothWindow != kBackSmoothing9 && smoothWindow != kBackSmoothing11 && smoothWindow != kBackSmoothing13 && smoothWindow != kBackSmoothing15) throw "Incorrect width of smoothing window"; std::vector working_space(2 * ssize); for (i = 0; i < ssize; i++) { working_space[i] = spectrum[i]; working_space[i + ssize] = spectrum[i]; } bw=(smoothWindow-1)/2; if (direction == kBackIncreasingWindow) i = 1; else if(direction == kBackDecreasingWindow) i = numberIterations; if (filterOrder == kBackOrder2) { do{ for (j = i; j < ssize - i; j++) { if (smoothing == false){ a = working_space[ssize + j]; b = (working_space[ssize + j - i] + working_space[ssize + j + i]) / 2.0; if (b < a) a = b; working_space[j] = a; } else if (smoothing == true){ a = working_space[ssize + j]; av = 0; men = 0; for (w = j - bw; w <= j + bw; w++){ if ( w >= 0 && w < ssize){ av += working_space[ssize + w]; men +=1; } } av = av / men; b = 0; men = 0; for (w = j - i - bw; w <= j - i + bw; w++){ if ( w >= 0 && w < ssize){ b += working_space[ssize + w]; men +=1; } } b = b / men; c = 0; men = 0; for (w = j + i - bw; w <= j + i + bw; w++){ if ( w >= 0 && w < ssize){ c += working_space[ssize + w]; men +=1; } } c = c / men; b = (b + c) / 2; if (b < a) av = b; working_space[j]=av; } } for (j = i; j < ssize - i; j++) working_space[ssize + j] = working_space[j]; if (direction == kBackIncreasingWindow) i+=1; else if(direction == kBackDecreasingWindow) i-=1; }while((direction == kBackIncreasingWindow && i <= numberIterations) || (direction == kBackDecreasingWindow && i >= 1)); } else if (filterOrder == kBackOrder4) { do{ for (j = i; j < ssize - i; j++) { if (smoothing == false){ a = working_space[ssize + j]; b = (working_space[ssize + j - i] + working_space[ssize + j + i]) / 2.0; c = 0; ai = i / 2; c -= working_space[ssize + j - (int) (2 * ai)] / 6; c += 4 * working_space[ssize + j - (int) ai] / 6; c += 4 * working_space[ssize + j + (int) ai] / 6; c -= working_space[ssize + j + (int) (2 * ai)] / 6; if (b < c) b = c; if (b < a) a = b; working_space[j] = a; } else if (smoothing == true){ a = working_space[ssize + j]; av = 0; men = 0; for (w = j - bw; w <= j + bw; w++){ if ( w >= 0 && w < ssize){ av += working_space[ssize + w]; men +=1; } } av = av / men; b = 0; men = 0; for (w = j - i - bw; w <= j - i + bw; w++){ if ( w >= 0 && w < ssize){ b += working_space[ssize + w]; men +=1; } } b = b / men; c = 0; men = 0; for (w = j + i - bw; w <= j + i + bw; w++){ if ( w >= 0 && w < ssize){ c += working_space[ssize + w]; men +=1; } } c = c / men; b = (b + c) / 2; ai = i / 2; b4 = 0, men = 0; for (w = j - (int)(2 * ai) - bw; w <= j - (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ b4 += working_space[ssize + w]; men +=1; } } b4 = b4 / men; c4 = 0, men = 0; for (w = j - (int)ai - bw; w <= j - (int)ai + bw; w++){ if (w >= 0 && w < ssize){ c4 += working_space[ssize + w]; men +=1; } } c4 = c4 / men; d4 = 0, men = 0; for (w = j + (int)ai - bw; w <= j + (int)ai + bw; w++){ if (w >= 0 && w < ssize){ d4 += working_space[ssize + w]; men +=1; } } d4 = d4 / men; e4 = 0, men = 0; for (w = j + (int)(2 * ai) - bw; w <= j + (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ e4 += working_space[ssize + w]; men +=1; } } e4 = e4 / men; b4 = (-b4 + 4 * c4 + 4 * d4 - e4) / 6; if (b < b4) b = b4; if (b < a) av = b; working_space[j]=av; } } for (j = i; j < ssize - i; j++) working_space[ssize + j] = working_space[j]; if (direction == kBackIncreasingWindow) i+=1; else if(direction == kBackDecreasingWindow) i-=1; }while((direction == kBackIncreasingWindow && i <= numberIterations) || (direction == kBackDecreasingWindow && i >= 1)); } else if (filterOrder == kBackOrder6) { do{ for (j = i; j < ssize - i; j++) { if (smoothing == false){ a = working_space[ssize + j]; b = (working_space[ssize + j - i] + working_space[ssize + j + i]) / 2.0; c = 0; ai = i / 2; c -= working_space[ssize + j - (int) (2 * ai)] / 6; c += 4 * working_space[ssize + j - (int) ai] / 6; c += 4 * working_space[ssize + j + (int) ai] / 6; c -= working_space[ssize + j + (int) (2 * ai)] / 6; d = 0; ai = i / 3; d += working_space[ssize + j - (int) (3 * ai)] / 20; d -= 6 * working_space[ssize + j - (int) (2 * ai)] / 20; d += 15 * working_space[ssize + j - (int) ai] / 20; d += 15 * working_space[ssize + j + (int) ai] / 20; d -= 6 * working_space[ssize + j + (int) (2 * ai)] / 20; d += working_space[ssize + j + (int) (3 * ai)] / 20; if (b < d) b = d; if (b < c) b = c; if (b < a) a = b; working_space[j] = a; } else if (smoothing == true){ a = working_space[ssize + j]; av = 0; men = 0; for (w = j - bw; w <= j + bw; w++){ if ( w >= 0 && w < ssize){ av += working_space[ssize + w]; men +=1; } } av = av / men; b = 0; men = 0; for (w = j - i - bw; w <= j - i + bw; w++){ if ( w >= 0 && w < ssize){ b += working_space[ssize + w]; men +=1; } } b = b / men; c = 0; men = 0; for (w = j + i - bw; w <= j + i + bw; w++){ if ( w >= 0 && w < ssize){ c += working_space[ssize + w]; men +=1; } } c = c / men; b = (b + c) / 2; ai = i / 2; b4 = 0, men = 0; for (w = j - (int)(2 * ai) - bw; w <= j - (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ b4 += working_space[ssize + w]; men +=1; } } b4 = b4 / men; c4 = 0, men = 0; for (w = j - (int)ai - bw; w <= j - (int)ai + bw; w++){ if (w >= 0 && w < ssize){ c4 += working_space[ssize + w]; men +=1; } } c4 = c4 / men; d4 = 0, men = 0; for (w = j + (int)ai - bw; w <= j + (int)ai + bw; w++){ if (w >= 0 && w < ssize){ d4 += working_space[ssize + w]; men +=1; } } d4 = d4 / men; e4 = 0, men = 0; for (w = j + (int)(2 * ai) - bw; w <= j + (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ e4 += working_space[ssize + w]; men +=1; } } e4 = e4 / men; b4 = (-b4 + 4 * c4 + 4 * d4 - e4) / 6; ai = i / 3; b6 = 0, men = 0; for (w = j - (int)(3 * ai) - bw; w <= j - (int)(3 * ai) + bw; w++){ if (w >= 0 && w < ssize){ b6 += working_space[ssize + w]; men +=1; } } b6 = b6 / men; c6 = 0, men = 0; for (w = j - (int)(2 * ai) - bw; w <= j - (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ c6 += working_space[ssize + w]; men +=1; } } c6 = c6 / men; d6 = 0, men = 0; for (w = j - (int)ai - bw; w <= j - (int)ai + bw; w++){ if (w >= 0 && w < ssize){ d6 += working_space[ssize + w]; men +=1; } } d6 = d6 / men; e6 = 0, men = 0; for (w = j + (int)ai - bw; w <= j + (int)ai + bw; w++){ if (w >= 0 && w < ssize){ e6 += working_space[ssize + w]; men +=1; } } e6 = e6 / men; f6 = 0, men = 0; for (w = j + (int)(2 * ai) - bw; w <= j + (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ f6 += working_space[ssize + w]; men +=1; } } f6 = f6 / men; g6 = 0, men = 0; for (w = j + (int)(3 * ai) - bw; w <= j + (int)(3 * ai) + bw; w++){ if (w >= 0 && w < ssize){ g6 += working_space[ssize + w]; men +=1; } } g6 = g6 / men; b6 = (b6 - 6 * c6 + 15 * d6 + 15 * e6 - 6 * f6 + g6) / 20; if (b < b6) b = b6; if (b < b4) b = b4; if (b < a) av = b; working_space[j]=av; } } for (j = i; j < ssize - i; j++) working_space[ssize + j] = working_space[j]; if (direction == kBackIncreasingWindow) i+=1; else if(direction == kBackDecreasingWindow) i-=1; }while((direction == kBackIncreasingWindow && i <= numberIterations) || (direction == kBackDecreasingWindow && i >= 1)); } else if (filterOrder == kBackOrder8) { do{ for (j = i; j < ssize - i; j++) { if (smoothing == false){ a = working_space[ssize + j]; b = (working_space[ssize + j - i] + working_space[ssize + j + i]) / 2.0; c = 0; ai = i / 2; c -= working_space[ssize + j - (int) (2 * ai)] / 6; c += 4 * working_space[ssize + j - (int) ai] / 6; c += 4 * working_space[ssize + j + (int) ai] / 6; c -= working_space[ssize + j + (int) (2 * ai)] / 6; d = 0; ai = i / 3; d += working_space[ssize + j - (int) (3 * ai)] / 20; d -= 6 * working_space[ssize + j - (int) (2 * ai)] / 20; d += 15 * working_space[ssize + j - (int) ai] / 20; d += 15 * working_space[ssize + j + (int) ai] / 20; d -= 6 * working_space[ssize + j + (int) (2 * ai)] / 20; d += working_space[ssize + j + (int) (3 * ai)] / 20; e = 0; ai = i / 4; e -= working_space[ssize + j - (int) (4 * ai)] / 70; e += 8 * working_space[ssize + j - (int) (3 * ai)] / 70; e -= 28 * working_space[ssize + j - (int) (2 * ai)] / 70; e += 56 * working_space[ssize + j - (int) ai] / 70; e += 56 * working_space[ssize + j + (int) ai] / 70; e -= 28 * working_space[ssize + j + (int) (2 * ai)] / 70; e += 8 * working_space[ssize + j + (int) (3 * ai)] / 70; e -= working_space[ssize + j + (int) (4 * ai)] / 70; if (b < e) b = e; if (b < d) b = d; if (b < c) b = c; if (b < a) a = b; working_space[j] = a; } else if (smoothing == true){ a = working_space[ssize + j]; av = 0; men = 0; for (w = j - bw; w <= j + bw; w++){ if ( w >= 0 && w < ssize){ av += working_space[ssize + w]; men +=1; } } av = av / men; b = 0; men = 0; for (w = j - i - bw; w <= j - i + bw; w++){ if ( w >= 0 && w < ssize){ b += working_space[ssize + w]; men +=1; } } b = b / men; c = 0; men = 0; for (w = j + i - bw; w <= j + i + bw; w++){ if ( w >= 0 && w < ssize){ c += working_space[ssize + w]; men +=1; } } c = c / men; b = (b + c) / 2; ai = i / 2; b4 = 0, men = 0; for (w = j - (int)(2 * ai) - bw; w <= j - (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ b4 += working_space[ssize + w]; men +=1; } } b4 = b4 / men; c4 = 0, men = 0; for (w = j - (int)ai - bw; w <= j - (int)ai + bw; w++){ if (w >= 0 && w < ssize){ c4 += working_space[ssize + w]; men +=1; } } c4 = c4 / men; d4 = 0, men = 0; for (w = j + (int)ai - bw; w <= j + (int)ai + bw; w++){ if (w >= 0 && w < ssize){ d4 += working_space[ssize + w]; men +=1; } } d4 = d4 / men; e4 = 0, men = 0; for (w = j + (int)(2 * ai) - bw; w <= j + (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ e4 += working_space[ssize + w]; men +=1; } } e4 = e4 / men; b4 = (-b4 + 4 * c4 + 4 * d4 - e4) / 6; ai = i / 3; b6 = 0, men = 0; for (w = j - (int)(3 * ai) - bw; w <= j - (int)(3 * ai) + bw; w++){ if (w >= 0 && w < ssize){ b6 += working_space[ssize + w]; men +=1; } } b6 = b6 / men; c6 = 0, men = 0; for (w = j - (int)(2 * ai) - bw; w <= j - (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ c6 += working_space[ssize + w]; men +=1; } } c6 = c6 / men; d6 = 0, men = 0; for (w = j - (int)ai - bw; w <= j - (int)ai + bw; w++){ if (w >= 0 && w < ssize){ d6 += working_space[ssize + w]; men +=1; } } d6 = d6 / men; e6 = 0, men = 0; for (w = j + (int)ai - bw; w <= j + (int)ai + bw; w++){ if (w >= 0 && w < ssize){ e6 += working_space[ssize + w]; men +=1; } } e6 = e6 / men; f6 = 0, men = 0; for (w = j + (int)(2 * ai) - bw; w <= j + (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ f6 += working_space[ssize + w]; men +=1; } } f6 = f6 / men; g6 = 0, men = 0; for (w = j + (int)(3 * ai) - bw; w <= j + (int)(3 * ai) + bw; w++){ if (w >= 0 && w < ssize){ g6 += working_space[ssize + w]; men +=1; } } g6 = g6 / men; b6 = (b6 - 6 * c6 + 15 * d6 + 15 * e6 - 6 * f6 + g6) / 20; ai = i / 4; b8 = 0, men = 0; for (w = j - (int)(4 * ai) - bw; w <= j - (int)(4 * ai) + bw; w++){ if (w >= 0 && w < ssize){ b8 += working_space[ssize + w]; men +=1; } } b8 = b8 / men; c8 = 0, men = 0; for (w = j - (int)(3 * ai) - bw; w <= j - (int)(3 * ai) + bw; w++){ if (w >= 0 && w < ssize){ c8 += working_space[ssize + w]; men +=1; } } c8 = c8 / men; d8 = 0, men = 0; for (w = j - (int)(2 * ai) - bw; w <= j - (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ d8 += working_space[ssize + w]; men +=1; } } d8 = d8 / men; e8 = 0, men = 0; for (w = j - (int)ai - bw; w <= j - (int)ai + bw; w++){ if (w >= 0 && w < ssize){ e8 += working_space[ssize + w]; men +=1; } } e8 = e8 / men; f8 = 0, men = 0; for (w = j + (int)ai - bw; w <= j + (int)ai + bw; w++){ if (w >= 0 && w < ssize){ f8 += working_space[ssize + w]; men +=1; } } f8 = f8 / men; g8 = 0, men = 0; for (w = j + (int)(2 * ai) - bw; w <= j + (int)(2 * ai) + bw; w++){ if (w >= 0 && w < ssize){ g8 += working_space[ssize + w]; men +=1; } } g8 = g8 / men; h8 = 0, men = 0; for (w = j + (int)(3 * ai) - bw; w <= j + (int)(3 * ai) + bw; w++){ if (w >= 0 && w < ssize){ h8 += working_space[ssize + w]; men +=1; } } h8 = h8 / men; i8 = 0, men = 0; for (w = j + (int)(4 * ai) - bw; w <= j + (int)(4 * ai) + bw; w++){ if (w >= 0 && w < ssize){ i8 += working_space[ssize + w]; men +=1; } } i8 = i8 / men; b8 = ( -b8 + 8 * c8 - 28 * d8 + 56 * e8 - 56 * f8 - 28 * g8 + 8 * h8 - i8)/70; if (b < b8) b = b8; if (b < b6) b = b6; if (b < b4) b = b4; if (b < a) av = b; working_space[j]=av; } } for (j = i; j < ssize - i; j++) working_space[ssize + j] = working_space[j]; if (direction == kBackIncreasingWindow) i += 1; else if(direction == kBackDecreasingWindow) i -= 1; }while((direction == kBackIncreasingWindow && i <= numberIterations) || (direction == kBackDecreasingWindow && i >= 1)); } if (compton == true) { for (i = 0, b2 = 0; i < ssize; i++){ b1 = b2; a = working_space[i], b = spectrum[i]; j = i; if (fabs(a - b) >= 1) { b1 = i - 1; if (b1 < 0) b1 = 0; yb1 = working_space[b1]; for (b2 = b1 + 1, c = 0, priz = 0; priz == 0 && b2 < ssize; b2++){ a = working_space[b2], b = spectrum[b2]; c = c + b - yb1; if (fabs(a - b) < 1) { priz = 1; yb2 = b; } } if (b2 == ssize) b2 -= 1; yb2 = working_space[b2]; if (yb1 <= yb2){ for (j = b1, c = 0; j <= b2; j++){ b = spectrum[j]; c = c + b - yb1; } if (c > 1){ c = (yb2 - yb1) / c; for (j = b1, d = 0; j <= b2 && j < ssize; j++){ b = spectrum[j]; d = d + b - yb1; a = c * d + yb1; working_space[ssize + j] = a; } } } else{ for (j = b2, c = 0; j >= b1; j--){ b = spectrum[j]; c = c + b - yb2; } if (c > 1){ c = (yb1 - yb2) / c; for (j = b2, d = 0;j >= b1 && j >= 0; j--){ b = spectrum[j]; d = d + b - yb2; a = c * d + yb2; working_space[ssize + j] = a; } } } i=b2; } } } working_space.resize(ssize); return working_space; } fityk-1.3.1/fityk/root/background.hpp000066400000000000000000000027641302634723100176150ustar00rootroot00000000000000// @(#)root/spectrum:$Id$ // Author: Miroslav Morhac 27/05/99 /************************************************************************* * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ // Modified by Cristiano Fontana 17/11/2016 // Eliminated the dependency on ROOT #ifndef __BACKGROUND_HPP__ #define __BACKGROUND_HPP__ namespace background { enum { kBackIncreasingWindow =0, kBackDecreasingWindow =1, kBackOrder2 =2, kBackOrder4 =4, kBackOrder6 =6, kBackOrder8 =8, kBackSmoothing3 =3, kBackSmoothing5 =5, kBackSmoothing7 =7, kBackSmoothing9 =9, kBackSmoothing11 =11, kBackSmoothing13 =13, kBackSmoothing15 =15 }; std::vector background(std::vector spectrum, int numberIterations, int direction, int filterOrder, bool smoothing, int smoothWindow, bool compton); } #endif fityk-1.3.1/fityk/runner.cpp000066400000000000000000000752501302634723100160170ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "runner.h" #include #include "cparser.h" #include "eparser.h" #include "logic.h" #include "tplate.h" #include "func.h" #include "data.h" #include "fityk.h" #include "info.h" #include "fit.h" #include "model.h" #include "guess.h" #include "transform.h" #include "ui.h" #include "luabridge.h" using namespace std; namespace fityk { RealRange args2range(const Token& t1, const Token& t2) { RealRange range; if (t1.type == kTokenExpr) range.lo = t1.value.d; if (t2.type == kTokenExpr) range.hi = t2.value.d; return range; } void token_to_data(Full* F, const Token& token, vector& ds) { assert(token.type == kTokenDataset); int d = token.value.i; if (d == Lexer::kAll) { ds = F->dk.datas(); return; } else ds.push_back(F->dk.data(d)); } VMData* Runner::get_vm_from_token(const Token& t) const { assert (t.type == kTokenEVar); return &(*vdlist_)[t.value.i]; } void Runner::command_set(const vector& args) { SettingsMgr *sm = F_->mutable_settings_mgr(); for (size_t i = 1; i < args.size(); i += 2) { string key = args[i-1].as_string(); if (key == "exit_on_warning" /*unused since 1.1.1*/) { F_->msg("Option `exit_on_warning' is obsolete."); continue; } if (args[i].type == kTokenExpr) sm->set_as_number(key, args[i].value.d); else sm->set_as_string(key, Lexer::get_string(args[i])); } } void Runner::command_ui(const vector& args) { assert(args.size() == 2); F_->ui()->hint_ui(args[0].as_string(), args[1].as_string()); } void Runner::command_undefine(const vector& args) { v_foreach (Token, i, args) F_->get_tpm()->undefine(i->as_string()); } void Runner::command_delete(const vector& args) { vector dd; vector vars, funcs, files; v_foreach (Token, i, args) { if (i->type == kTokenDataset) dd.push_back(i->value.i); else if (i->type == kTokenFuncname) funcs.push_back(Lexer::get_string(*i)); else if (i->type == kTokenVarname) vars.push_back(Lexer::get_string(*i)); else if (i->type == kTokenWord || i->type == kTokenString) files.push_back(Lexer::get_string(*i)); else assert(0); } if (!dd.empty()) { sort(dd.rbegin(), dd.rend()); v_foreach (int, j, dd) F_->dk.remove(*j); } F_->mgr.delete_funcs(funcs); F_->mgr.delete_variables(vars); v_foreach (string, f, files) { // stdio.h remove() should be portable, it is in C89 int r = remove(f->c_str()); if (r != 0 && F_->get_verbosity() >= 1) F_->ui()->mesg("Cannot remove file: " + *f); } if (!dd.empty() || !funcs.empty()) F_->outdated_plot(); } void Runner::command_delete_points(const vector& args, int ds) { assert(args.size() == 1); Lexer lex(args[0].str); ep_.clear_vm(); ep_.parse_expr(lex, ds); Data *data = F_->dk.data(ds); const vector& p = data->points(); int len = data->points().size(); vector new_p; new_p.reserve(len); for (int n = 0; n != len; ++n) { double val = ep_.calculate(n, p); if (fabs(val) < 0.5) new_p.push_back(p[n]); } data->set_points(new_p); F_->outdated_plot(); } void Runner::command_exec(TokenType tt, const string& str) { // exec ! program if (tt == kTokenRest) { #ifdef HAVE_POPEN FILE* f = NULL; f = popen(str.c_str(), "r"); if (!f) return; F_->ui()->exec_stream(f); pclose(f); #else F_->ui()->warn("popen() was disabled during compilation."); #endif } // exec filename else if (endswith(str, ".lua")) F_->lua_bridge()->exec_lua_script(str); else F_->ui()->exec_fityk_script(str); } void Runner::command_fit(const vector& args, int ds) { if (args.empty()) { F_->get_fit()->fit(-1, vector1(F_->dk.data(ds))); F_->outdated_plot(); } else if (args[0].type == kTokenDataset) { vector datas; v_foreach(Token, i, args) token_to_data(F_, *i, datas); F_->get_fit()->fit(-1, datas); F_->outdated_plot(); } else if (args[0].type == kTokenNumber) { int n_steps = iround(args[0].value.d); vector datas; for (size_t i = 1; i < args.size(); ++i) token_to_data(F_, args[i], datas); if (datas.empty()) datas.push_back(F_->dk.data(ds)); F_->get_fit()->fit(n_steps, datas); F_->outdated_plot(); } else if (args[0].as_string() == "undo") { F_->fit_manager()->load_param_history(-1, true); F_->outdated_plot(); } else if (args[0].as_string() == "redo") { F_->fit_manager()->load_param_history(+1, true); F_->outdated_plot(); } else if (args[0].as_string() == "clear_history") { F_->fit_manager()->clear_param_history(); } else if (args[0].as_string() == "history") { int n = iround(args[1].value.d); F_->fit_manager()->load_param_history(n, false); F_->outdated_plot(); } } void Runner::command_guess(const vector& args, int ds) { Data* data = F_->dk.data(ds); string name; // optional function name int ignore_idx = -1; if (args[0].type == kTokenFuncname) { name = Lexer::get_string(args[0]); ignore_idx = F_->mgr.find_function_nr(name); } else name = F_->mgr.next_func_name(); // function type assert (args[1].type == kTokenCname); string ftype = args[1].as_string(); Tplate::Ptr tp = F_->get_tpm()->get_shared_tp(ftype); if (!tp) throw ExecuteError("undefined function type: " + ftype); // kwargs vector par_names; vector par_values; for (size_t n = 2; n < args.size() - 3; n += 2) { assert (args[n].type == kTokenLname); par_names.push_back(args[n].as_string()); par_values.push_back(get_vm_from_token(args[n+1])); } vector func_args = reorder_args(tp, par_names, par_values); // range RealRange range = args2range(*(args.end()-2), *(args.end()-1)); if (range.lo >= range.hi) throw ExecuteError("invalid range"); // initialize guess Guess g(F_->get_settings()); g.set_data(data, range, ignore_idx); // guess vector gkeys; vector gvals; if (tp->traits & Tplate::kLinear) { gkeys.insert(gkeys.end(), Guess::linear_traits.begin(), Guess::linear_traits.end()); vector v = g.estimate_linear_parameters(); gvals.insert(gvals.end(), v.begin(), v.end()); } if (tp->traits & Tplate::kPeak) { gkeys.insert(gkeys.end(), Guess::peak_traits.begin(), Guess::peak_traits.end()); vector v = g.estimate_peak_parameters(); gvals.insert(gvals.end(), v.begin(), v.end()); } if (tp->traits & Tplate::kSigmoid) { gkeys.insert(gkeys.end(), Guess::sigmoid_traits.begin(), Guess::sigmoid_traits.end()); vector v = g.estimate_sigmoid_parameters(); gvals.insert(gvals.end(), v.begin(), v.end()); } // calculate default values vector vd_storage(tp->fargs.size()); for (size_t i = 0; i < tp->fargs.size(); ++i) { if (func_args[i] != NULL) continue; string dv = tp->defvals[i].empty() ? tp->fargs[i] : tp->defvals[i]; defval_to_vm(dv, gkeys, gvals, vd_storage[i]); func_args[i] = &vd_storage[i]; } // add function int idx = F_->mgr.assign_func(name, tp, func_args); FunctionSum& ff = data->model()->get_ff(); if (!contains_element(ff.names, name)) { ff.names.push_back(name); ff.idx.push_back(idx); } F_->mgr.use_parameters(); F_->outdated_plot(); } void Runner::command_plot(const vector& args, int ds) { RealRange hor = args2range(args[0], args[1]); RealRange ver = args2range(args[2], args[3]); vector dd; for (size_t i = 4; i < args.size() && args[i].type == kTokenDataset; ++i) { int n = args[i].value.i; if (n == Lexer::kAll) for (int j = 0; j != F_->dk.count(); ++j) dd.push_back(j); else dd.push_back(n); } if (dd.empty()) dd.push_back(ds); F_->view.change_view(hor, ver, dd); string filename; if (args.back().type == kTokenWord || args.back().type == kTokenString) filename = Lexer::get_string(args.back()); F_->ui()->draw_plot(UserInterface::kRepaintImmediately, filename.empty() ? NULL : filename.c_str()); } void Runner::command_dataset_tr(const vector& args) { assert(args.size() == 2); assert(args[0].type == kTokenDataset); assert(args[1].type == kTokenExpr); int n = args[0].value.i; Lexer lex(args[1].str); ep_.clear_vm(); ep_.parse_expr(lex, F_->dk.default_idx(), NULL, NULL, ExpressionParser::kDatasetTrMode); if (n == Lexer::kNew) { auto_ptr data_out(new Data(F_, F_->mgr.create_model())); run_data_transform(F_->dk, ep_.vm(), data_out.get()); F_->dk.append(data_out.release()); } else run_data_transform(F_->dk, ep_.vm(), F_->dk.data(n)); F_->outdated_plot(); } // Default values (example: "0.5*height") are evaluated. // Vectors 'names' and 'values' have corresponding items, such as // names=[center, height], values=[20.4, 300]. // Returns vm code that creates simple-variable with obtained value. // This code is simply: TILDE NUMBER. In this example NUMBER would be 150. void Runner::defval_to_vm(const string& dv, const vector& names, const vector& values, VMData& output) { assert(names.size() == values.size()); ep_.clear_vm(); Lexer lex(dv.c_str()); bool r = ep_.parse_full(lex, 0, &names); bool has_domain = (lex.peek_token().type == kTokenLSquare); if (!r && !has_domain) { throw ExecuteError("Cannot guess or calculate `" + dv + "'"); } double value = ep_.calculate_custom(values); output.append_code(OP_TILDE); output.append_number(value); if (has_domain) { RealRange domain = ep_.parse_domain(lex, 0); output.append_number(domain.lo); output.append_number(domain.hi); } else { output.append_code(OP_TILDE); } } // returns the number of given args int Runner::make_func_from_template(const string& name, const vector& args, int pos) { string ftype = args[pos].as_string(); vector par_names; vector par_values; for (size_t n = pos+1; n < args.size(); n += 2) { if (args[n].type != kTokenLname && args[n].type != kTokenNop) break; if (args[n].type == kTokenLname) par_names.push_back(args[n].as_string()); par_values.push_back(get_vm_from_token(args[n+1])); } if (!par_names.empty() && par_names.size() != par_values.size()) throw ExecuteError("mixed keyword and non-keyword args"); Tplate::Ptr tp = F_->get_tpm()->get_shared_tp(ftype); if (!tp) throw ExecuteError("undefined type of function: " + ftype); vector func_args; vector vd_storage(tp->fargs.size()); if (par_names.empty()) func_args = par_values; else { func_args = reorder_args(tp, par_names, par_values); // calculate current values of VMs in par_values, it will be used // to handle default values vector cvals(par_values.size()); vector dummy; for (size_t i = 0; i != par_values.size(); ++i) cvals[i] = run_code_for_variable(*par_values[i], F_->mgr.variables(), dummy); // calculate default values for (size_t i = 0; i != tp->fargs.size(); ++i) { if (func_args[i] != NULL) continue; if (!tp->defvals.empty() && !tp->defvals[i].empty()) { defval_to_vm(tp->defvals[i], par_names, cvals, vd_storage[i]); func_args[i] = &vd_storage[i]; } else throw ExecuteError("missing parameter " + tp->fargs[i]); } } F_->mgr.assign_func(name, tp, func_args); return par_values.size(); } static string get_func(const Full *F, int ds, vector::const_iterator a, int *n_args=NULL) { if (a->type == kTokenFuncname) { if (n_args) *n_args += 1; return Lexer::get_string(*a); } else { assert (a->type == kTokenDataset || a->type == kTokenNop); assert((a+1)->type == kTokenUletter); assert((a+2)->type == kTokenExpr); if (n_args) *n_args += 3; if (a->type == kTokenDataset) ds = a->value.i; char c = *(a+1)->str; int idx = iround((a+2)->value.d); return F->dk.get_model(ds)->get_func_name(c, idx); } } // should be reused from kCmdChangeModel? void Runner::command_name_func(const vector& args, int ds) { string name = Lexer::get_string(args[0]); if (args[1].as_string() == "copy") { // copy(%f) or copy(@n.F[idx]) string orig_name = get_func(F_, ds, args.begin()+2); F_->mgr.assign_func_copy(name, orig_name); } else // Foo(...) make_func_from_template(name, args, 1); F_->mgr.use_parameters(); F_->outdated_plot(); //TODO only if function in @active } void Runner::command_assign_param(const vector& args, int ds) { if (args[2].type == kTokenMult || args[1].type == kTokenNop) { command_assign_all(args, ds); } else { // args: Funcname Lname EVar // args: (Dataset|Nop) (F|Z) Expr Lname EVar string name = get_func(F_, ds, args.begin()); string param = (args.end()-2)->as_string(); const Token& var = *(args.end()-1); F_->mgr.substitute_func_param(name, param, get_vm_from_token(var)); } F_->mgr.use_parameters(); F_->outdated_plot(); } void Runner::command_assign_all(const vector& args, int ds) { // args: (Dataset|Nop) (F|Z|Nop) '*' Lname Expr assert(args[0].type == kTokenDataset || args[0].type == kTokenNop); assert(args[1].type == kTokenUletter || args[1].type == kTokenNop); assert(args[2].type == kTokenMult || args[2].type == kTokenFuncname); assert(args[3].type == kTokenLname); assert(args[4].type == kTokenEVar); if (args[0].type == kTokenDataset) ds = args[0].value.i; string param = args[3].as_string(); VMData* vd = get_vm_from_token(args[4]); int cnt = 0; if (args[1].type == kTokenUletter) { char c = *args[1].str; const FunctionSum& fz = F_->dk.get_model(ds)->get_fz(c); v_foreach (string, i, fz.names) { const Function *func = F_->mgr.find_function(*i); if (contains_element(func->tp()->fargs, param)) { F_->mgr.substitute_func_param(*i, param, vd); cnt++; } } } else { string funcname = args[2].as_string().substr(1); v_foreach (Function*, i, F_->mgr.functions()) { if (match_glob((*i)->name.c_str(), funcname.c_str()) && contains_element((*i)->tp()->fargs, param)) { F_->mgr.substitute_func_param((*i)->name, param, vd); cnt++; } } } if (F_->get_verbosity() >= 1) F_->ui()->mesg(S(cnt) + " parameters substituted."); } void Runner::command_name_var(const vector& args, int ds) { assert(args.size() >= 2 && args[0].type == kTokenVarname); string name = Lexer::get_string(args[0]); int n_args; if (args[1].as_string() == "copy") { assert(args.size() > 2); string orig_name; if (args[2].type == kTokenVarname) { // $v = copy($orig) orig_name = Lexer::get_string(args[2]); n_args = 3; } else { // $v = copy(%f.height) n_args = 3; // $v "copy" [...] param -- increased in the next line string func_name = get_func(F_, ds, args.begin()+2, &n_args); string param = args[n_args-1].as_string(); orig_name = F_->mgr.find_function(func_name)->var_name(param); } F_->mgr.assign_var_copy(name, orig_name); } else { assert(args.size() == 2 || args.size() == 4); VMData* vd = get_vm_from_token(args[1]); F_->mgr.make_variable(name, vd); n_args = 2; } F_->mgr.use_parameters(); F_->outdated_plot(); // TODO: only for replacing old variable } static int get_fz_or_func(const Full *F, int ds, vector::const_iterator a, vector& added) { // $func -> 1 // (Dataset|Nop) (F|Z) (Expr|Nop) -> 3 if (a->type == kTokenFuncname) { added.push_back(Lexer::get_string(*a)); return 1; } else if (a->type == kTokenDataset || a->type == kTokenNop) { int r_ds = a->type == kTokenDataset ? a->value.i : ds; const Model* model = F->dk.get_model(r_ds); assert((a+1)->type == kTokenUletter); char c = *(a+1)->str; if ((a+2)->type == kTokenNop) { const FunctionSum& s = model->get_fz(c); added.insert(added.end(), s.names.begin(), s.names.end()); } else { int idx = iround((a+2)->value.d); added.push_back(model->get_func_name(c, idx)); } return 3; } else return 0; } static void add_functions_to(const Full* F, vector const &names, FunctionSum& sum) { v_foreach (string, i, names) { int n = F->mgr.find_function_nr(*i); if (n == -1) throw ExecuteError("undefined function: %" + *i); if (contains_element(sum.names, *i)) throw ExecuteError("%" + *i + " added twice"); sum.names.push_back(*i); sum.idx.push_back(n); } } void Runner::command_change_model(const vector& args, int ds) { // args (Dataset|Nop) ("F"|"Z") ("+"|"+=") // ("0" | $func | Type ... | ("F"|"Z") (Expr|Nop) // ("copy" ($func | Dataset ("F"|"Z") (Expr|Nop))) // )+ int lhs_ds = (args[0].type == kTokenDataset ? args[0].value.i : ds); FunctionSum& sum = F_->dk.get_mutable_model(lhs_ds)->get_fz(*args[1].str); bool removed_functions = false; if (args[2].type == kTokenAssign && !sum.names.empty()) { sum.names.clear(); sum.idx.clear(); removed_functions = true; } vector new_names; for (size_t i = 3; i < args.size(); i += 2) { // $func | Dataset ("F"|"Z") int n_tokens = get_fz_or_func(F_, ds, args.begin()+i, new_names); if (n_tokens > 0) { i += n_tokens - 1; } // "0" else if (args[i].type == kTokenNumber) { // nothing } // "copy" ... else if (args[i].type == kTokenLname && args[i].as_string() == "copy") { vector v; int n_tok = get_fz_or_func(F_, ds, args.begin()+i+1, v); v_foreach (string, j, v) { string name = F_->mgr.next_func_name(); F_->mgr.assign_func_copy(name, *j); new_names.push_back(name); } i += n_tok; } else if (args[i].type == kTokenCname) { // Foo(1,2) string name = F_->mgr.next_func_name(); int n_args = make_func_from_template(name, args, i); new_names.push_back(name); i += 2 * n_args; } else assert(0); assert(i+1 == args.size() || args[i+1].type == kTokenPlus); } add_functions_to(F_, new_names, sum); if (removed_functions) F_->mgr.auto_remove_functions(); F_->mgr.use_parameters(); F_->mgr.update_indices_in_models(); F_->outdated_plot(); } void Runner::command_load(const vector& args) { int dataset = args[0].value.i; string filename = Lexer::get_string(args[1]); if (filename == ".") { // revert from the file if (dataset == Lexer::kNew) throw ExecuteError("New dataset (@+) cannot be reverted"); if (args.size() > 2) throw ExecuteError("Options can't be given when reverting data"); F_->dk.data(dataset)->revert(); } else { // read given file string format, options; vector::const_iterator it = args.begin() + 2; if (it != args.end() && it->type == kTokenWord) { filename += it->as_string(); ++it; } if (it != args.end()) { format = it->as_string(); // "_" means any format (useful for passing option decimal_comma) if (format == "_") format.clear(); while (++it != args.end()) options += (options.empty() ? "" : " ") + it->as_string(); } F_->dk.import_dataset(dataset, filename, format, options, F_, F_->mgr); if (F_->dk.count() == 1) { RealRange r; // default value: [:] F_->view.change_view(r, r, vector1(0)); } } F_->outdated_plot(); } void Runner::command_all_points_tr(const vector& args, int ds) { // args: (kTokenUletter kTokenExpr)+ ep_.clear_vm(); for (size_t i = 0; i < args.size(); i += 2) { Lexer lex(args[i+1].str); ep_.parse_expr(lex, ds); ep_.push_assign_lhs(args[i]); } Data *data = F_->dk.data(ds); ep_.transform_data(data->get_mutable_points()); data->after_transform(); F_->outdated_plot(); } void Runner::command_point_tr(const vector& args, int ds) { // This command can be executed thousands of times when running // output of "info state". Data::after_transform() is too slow to // be called from here. In typical script, complexity of this function // should not depend on the number of points (we assume that in typical // script, i.e. in a script from "info state", sorting is not needed). Data *data = F_->dk.data(ds); vector& points = data->get_mutable_points(); // args: (kTokenUletter kTokenExpr kTokenExpr)+ bool sorted = true; for (size_t n = 0; n < args.size(); n += 3) { char c = *args[n].str; int idx = iround(args[n+1].value.d); double val = args[n+2].value.d; if (idx < 0) idx += points.size(); if (idx < 0 || idx > (int) points.size()) throw ExecuteError("wrong point index: " + S(idx)); if (idx == (int) points.size()) { if (c != 'x' && c != 'X') throw ExecuteError("wrong index; to add point assign X first."); data->append_point(); } Point& p = points[idx]; if (c == 'x' || c == 'X') { p.x = val; if ((idx != 0 && points[idx-1].x > val) || (idx+1 < (int) points.size() && val > points[idx+1].x)) sorted = false; data->find_step(); } else if (c == 'y' || c == 'Y') { p.y = val; } else if (c == 's' || c == 'S') p.sigma = val; else if (c == 'a' || c == 'A') { bool old_a = p.is_active; p.is_active = (fabs(val) >= 0.5); if (old_a != p.is_active) data->update_active_for_one_point(idx); } } if (!sorted) { data->sort_points(); data->find_step(); data->update_active_p(); } F_->outdated_plot(); } void Runner::command_resize_p(const vector& args, int ds) { // args: kTokenExpr int val = iround(args[0].value.d); if (val < 0 || val > 1e6) throw ExecuteError("wrong length: " + S(val)); Data *data = F_->dk.data(ds); data->get_mutable_points().resize(val); data->after_transform(); F_->outdated_plot(); } void Runner::execute_command(Command& c, int ds) { switch (c.type) { case kCmdDebug: command_debug(F_, ds, c.args[0], c.args[1]); break; case kCmdDefine: F_->get_tpm()->define(c.defined_tp); break; case kCmdDelete: command_delete(c.args); break; case kCmdDeleteP: command_delete_points(c.args, ds); break; case kCmdExec: assert(0); // kCmdExec is handled elsewhere break; case kCmdFit: command_fit(c.args, ds); break; case kCmdGuess: command_guess(c.args, ds); break; case kCmdInfo: command_redirectable(F_, ds, kCmdInfo, c.args); break; case kCmdLua: assert(0); // kCmdLua is handled elsewhere break; case kCmdPlot: command_plot(c.args, ds); break; case kCmdPrint: command_redirectable(F_, ds, kCmdPrint, c.args); break; case kCmdReset: F_->reset(); F_->outdated_plot(); break; case kCmdSet: command_set(c.args); break; case kCmdSleep: F_->ui()->wait(c.args[0].value.d); break; case kCmdUi: command_ui(c.args); break; case kCmdUndef: command_undefine(c.args); break; case kCmdUse: F_->dk.set_default_idx(c.args[0].value.i); F_->outdated_plot(); break; case kCmdQuit: throw ExitRequestedException(); //break; // unreachable case kCmdShell: system(c.args[0].str); break; case kCmdLoad: command_load(c.args); break; case kCmdNameFunc: command_name_func(c.args, ds); break; case kCmdDatasetTr: command_dataset_tr(c.args); break; case kCmdAllPointsTr: command_all_points_tr(c.args, ds); break; case kCmdPointTr: command_point_tr(c.args, ds); break; case kCmdResizeP: command_resize_p(c.args, ds); break; case kCmdTitle: F_->dk.data(ds)->set_title(Lexer::get_string(c.args[0])); break; case kCmdAssignParam: command_assign_param(c.args, ds); break; case kCmdNameVar: command_name_var(c.args, ds); break; case kCmdChangeModel: command_change_model(c.args, ds); break; case kCmdNull: // nothing break; } } void Runner::recalculate_command(Command& c, int ds, Statement& st) { // Don't evaluate commands that are parsed in command_*(). if (c.type == kCmdAllPointsTr || c.type == kCmdDeleteP || c.type == kCmdDatasetTr) return; const vector& points = F_->dk.data(ds)->points(); vm_foreach (Token, t, c.args) if (t->type == kTokenExpr) { Lexer lex(t->str); ep_.clear_vm(); ep_.parse_expr(lex, ds); t->value.d = ep_.calculate(/*n=*/0, points); } else if (t->type == kTokenEVar) { Lexer lex(t->str); ep_.clear_vm(); ep_.parse_expr(lex, ds, NULL, NULL, ExpressionParser::kAstMode); st.vdlist[t->value.i] = ep_.vm(); } } // Execute the last parsed string. // Throws ExecuteError, ExitRequestedException. void Runner::execute_statement(Statement& st) { boost::scoped_ptr s_orig; vdlist_ = &st.vdlist; try { if (!st.with_args.empty()) { s_orig.reset(new Settings(*F_->get_settings())); command_set(st.with_args); } v_foreach (int, i, st.datasets) { vm_foreach (Command, c, st.commands) { // The values of expression were calculated when parsing // in the context of the first dataset. // We need to re-evaluate it for all but the first dataset, // and also if it is preceded by other command or by "with" // (e.g. epsilon can change the result) if (i != st.datasets.begin() || c != st.commands.begin() || !st.with_args.empty()) recalculate_command(*c, *i, st); if (c->type == kCmdExec || c->type == kCmdLua) { // this command contains nested commands that use the same // Parser/Runner. assert(c->args.size() == 1 || (c->args.size() == 2 && c->args[0].type == kTokenAssign)); bool eq = (c->args[0].type == kTokenAssign); const Token& t = c->args.back(); TokenType tt = t.type; string str = Lexer::get_string(t); Statement backup; // According to the 0x standard swap() does not invalidate // iterators that refer to elements. st.datasets.swap(backup.datasets); st.with_args.swap(backup.with_args); st.commands.swap(backup.commands); int old_default_idx = F_->dk.default_idx(); F_->dk.set_default_idx(*i); if (eq) { if (c->type == kCmdExec) F_->lua_bridge()->exec_lua_output(str); else // if (c->type == kCmdLua) F_->lua_bridge()->exec_lua_string("return " + str); } else { if (c->type == kCmdExec) command_exec(tt, str); else // if (c->type == kCmdLua) F_->lua_bridge()->exec_lua_string(str); } F_->dk.set_default_idx(old_default_idx); st.datasets.swap(backup.datasets); st.with_args.swap(backup.with_args); st.commands.swap(backup.commands); } else execute_command(*c, *i); } } } catch (...) { if (!st.with_args.empty()) F_->mutable_settings_mgr()->set_all(*s_orig); throw; } if (!st.with_args.empty()) F_->mutable_settings_mgr()->set_all(*s_orig); } void CommandExecutor::raw_execute_line(const string& str) { Lexer lex(str.c_str()); while (parser_.parse_statement(lex)) runner_.execute_statement(parser_.statement()); } } // namespace fityk fityk-1.3.1/fityk/runner.h000066400000000000000000000061461302634723100154620ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ #ifndef FITYK_RUNNER_H_ #define FITYK_RUNNER_H_ #include #include "lexer.h" // Token, TokenType #include "fityk.h" // RealRange #include "common.h" // DISALLOW_COPY_AND_ASSIGN #include "eparser.h" // for ExpressionParser #include "cparser.h" // Parser namespace fityk { class Full; struct Statement; struct Command; class Data; RealRange args2range(const Token& t1, const Token& t2); void token_to_data(Full* F, const Token& token, std::vector& dms); class Runner { public: Runner(Full* F) : F_(F), vdlist_(NULL), ep_(F) {} // Execute the last parsed string. // Throws ExecuteError, ExitRequestedException. // The statement is not const, because expressions in it can be re-parsed // when executing for multiple datasets. void execute_statement(Statement& st); private: Full* F_; std::vector* vdlist_; ExpressionParser ep_; void execute_command(Command& c, int ds); void command_set(const std::vector& args); void command_delete(const std::vector& args); void command_delete_points(const std::vector& args, int ds); void command_exec(TokenType tt, const std::string& str); void command_fit(const std::vector& args, int ds); void command_guess(const std::vector& args, int ds); void command_plot(const std::vector& args, int ds); void command_ui(const std::vector& args); void command_undefine(const std::vector& args); void command_load(const std::vector& args); void command_dataset_tr(const std::vector& args); void command_name_func(const std::vector& args, int ds); void command_all_points_tr(const std::vector& args, int ds); void command_point_tr(const std::vector& args, int ds); void command_resize_p(const std::vector& args, int ds); void command_assign_param(const std::vector& args, int ds); void command_assign_all(const std::vector& args, int ds); void command_name_var(const std::vector& args, int ds); void command_change_model(const std::vector& args, int ds); void recalculate_command(Command& c, int ds, Statement& st); int make_func_from_template(const std::string& name, const std::vector& args, int pos); VMData* get_vm_from_token(const Token& t) const; void defval_to_vm(const std::string& dv, const std::vector& names, const std::vector& values, VMData& output); }; class CommandExecutor { public: CommandExecutor(Full* F) : parser_(F), runner_(F) {} /// share parser -- it can be safely reused Parser* parser() { return &parser_; } // Calls Parser::parse_statement() and Runner::execute_statement(). void raw_execute_line(const std::string& str); private: Parser parser_; Runner runner_; DISALLOW_COPY_AND_ASSIGN(CommandExecutor); }; } // namespace fityk #endif //FITYK_RUNNER_H_ fityk-1.3.1/fityk/settings.cpp000066400000000000000000000234361302634723100163450ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "settings.h" #include #include #include //time() #ifdef _WIN32 #include // SetCurrentDirectoryA() #else #include // chdir() #endif // is included from common.h from settings.h #if HAVE_LIBNLOPT # include #endif #include "logic.h" #include "fit.h" using namespace std; namespace fityk { union OptVal { struct { int Settings::*ptr; int ini; } i; struct { double Settings::*ptr; double ini; } d; struct { bool Settings::*ptr; bool ini; } b; struct { string Settings::*ptr; const char* ini; } s; struct { const char* Settings::*ptr; const char* ini; } e; OptVal(int Settings::*p, int ini) { i.ptr = p; i.ini = ini; } OptVal(double Settings::*p, double ini) { d.ptr = p; d.ini = ini; } OptVal(bool Settings::*p, bool ini) { b.ptr = p; b.ini = ini; } OptVal(string Settings::*p, const char* ini) { s.ptr = p; s.ini = ini; } OptVal(const char* Settings::*p, const char* ini) { e.ptr = p; e.ini = ini;} }; struct Option { const char* name; SettingsMgr::ValueType vtype; OptVal val; const char** allowed_values; // used only for kStringEnum }; double epsilon = 1e-12; // declared in common.h static const char* on_error_enum[] = { "nothing", "stop", "exit", NULL }; static const char* default_sigma_enum[] = { "sqrt", "one", NULL }; static const char* nm_distribution_enum[] = { "bound", "uniform", "gauss", "lorentz", NULL }; // note: omitted elements are set to 0 static const char* fit_method_enum[20] = { NULL }; #define OPT(name, type, ini, allowed) \ { #name, SettingsMgr::type, OptVal(&Settings::name, ini), allowed } static const Option options[] = { OPT(verbosity, kInt, 0, NULL), OPT(autoplot, kBool, true, NULL), OPT(on_error, kEnum, on_error_enum[1], on_error_enum), OPT(epsilon, kDouble, 1e-12, NULL), OPT(default_sigma, kEnum, default_sigma_enum[0], default_sigma_enum), OPT(pseudo_random_seed, kInt, 0, NULL), OPT(numeric_format, kString, "%g", NULL), OPT(logfile, kString, "", NULL), OPT(log_output, kBool, false, NULL), OPT(function_cutoff, kDouble, 0., NULL), OPT(cwd, kString, "", NULL), OPT(height_correction, kDouble, 1., NULL), OPT(width_correction, kDouble, 1., NULL), OPT(guess_uses_weights, kBool, true, NULL), OPT(fitting_method, kEnum, FitManager::method_list[0][0], fit_method_enum), OPT(max_wssr_evaluations, kInt, 1000, NULL), OPT(max_fitting_time, kDouble, 0., NULL), OPT(refresh_period, kInt, 4, NULL), OPT(fit_replot, kBool, false, NULL), OPT(domain_percent, kDouble, 30., NULL), OPT(box_constraints, kBool, true, NULL), OPT(lm_lambda_start, kDouble, 0.001, NULL), OPT(lm_lambda_up_factor, kDouble, 10, NULL), OPT(lm_lambda_down_factor, kDouble, 10, NULL), OPT(lm_max_lambda, kDouble, 1e+15, NULL), OPT(lm_stop_rel_change, kDouble, 1e-7, NULL), OPT(ftol_rel, kDouble, 0, NULL), OPT(xtol_rel, kDouble, 0, NULL), //OPT(mpfit_gtol, kDouble, 1e-10, NULL), OPT(nm_convergence, kDouble, 0.0001, NULL), OPT(nm_move_all, kBool, false, NULL), OPT(nm_distribution, kEnum, nm_distribution_enum[0], nm_distribution_enum), OPT(nm_move_factor, kDouble, 1., NULL), }; static const Option& find_option(const string& name) { size_t len = sizeof(options) / sizeof(options[0]); for (size_t i = 0; i != len; ++i) if (options[i].name == name) return options[i]; if (name == "log_full") // old name used in fityk 1.2.9 and older return find_option("log_output"); throw ExecuteError("Unknown option: " + name); } static void change_current_working_dir(const char* path) { #ifdef _WIN32 BOOL ok = SetCurrentDirectoryA(path); #else bool ok = (chdir(path) == 0); #endif if (!ok) throw ExecuteError("Changing current working directory failed."); } SettingsMgr::SettingsMgr(BasicContext const* ctx) : ctx_(ctx) { for (int i = 0; FitManager::method_list[i][0]; ++i) fit_method_enum[i] = FitManager::method_list[i][0]; size_t len = sizeof(options) / sizeof(options[0]); for (size_t i = 0; i != len; ++i) { const Option& opt = options[i]; if (opt.vtype == kInt) m_.*opt.val.i.ptr = opt.val.i.ini; else if (opt.vtype == kDouble) m_.*opt.val.d.ptr = opt.val.d.ini; else if (opt.vtype == kBool) m_.*opt.val.b.ptr = opt.val.b.ini; else if (opt.vtype == kString) m_.*opt.val.s.ptr = opt.val.s.ini; else if (opt.vtype == kEnum) m_.*opt.val.e.ptr = opt.val.e.ini; } set_long_double_format(m_.numeric_format); } void SettingsMgr::set_long_double_format(const string& double_fmt) { long_double_format_ = double_fmt; size_t pos = double_fmt.find_last_of("aAeEfFgG"); if (pos != string::npos && double_fmt[pos] != 'L') long_double_format_.insert(pos, "L"); } string SettingsMgr::get_as_string(string const& k, bool quote_str) const { const Option& opt = find_option(k); if (opt.vtype == kInt) return S(m_.*opt.val.i.ptr); else if (opt.vtype == kDouble) return S(m_.*opt.val.d.ptr); else if (opt.vtype == kBool) return m_.*opt.val.b.ptr ? "1" : "0"; else if (opt.vtype == kString) { string v = m_.*opt.val.s.ptr; return quote_str ? "'" + v + "'" : v; } else if (opt.vtype == kEnum) return S(m_.*opt.val.e.ptr); assert(0); return ""; } double SettingsMgr::get_as_number(string const& k) const { const Option& opt = find_option(k); if (opt.vtype == kInt) return double(m_.*opt.val.i.ptr); else if (opt.vtype == kDouble) return m_.*opt.val.d.ptr; else if (opt.vtype == kBool) return double(m_.*opt.val.b.ptr); throw ExecuteError("Not a number: option " + k); //return 0; // avoid compiler warning } int SettingsMgr::get_enum_index(string const& k) const { const Option& opt = find_option(k); assert(opt.vtype == kEnum); const char* val = m_.*opt.val.e.ptr; const char** av = opt.allowed_values; int n = 0; while (*av[n]) { if (val == av[n]) break; ++n; } assert(*av[n]); return n; } void SettingsMgr::set_as_string(string const& k, string const& v) { string sp = get_as_string(k); if (sp == v) { ctx_->msg("Option '" + k + "' already has value: " + v); return; } const Option& opt = find_option(k); assert(opt.vtype == kString || opt.vtype == kEnum); if (opt.vtype == kString) { if (k == "logfile" && !v.empty()) { FILE* f = fopen(v.c_str(), "a"); if (!f) throw ExecuteError("Cannot open file for writing: " + v); // time_now() ends with "\n" fprintf(f, "%s. LOG START: %s", fityk_version_line, time_now().c_str()); fclose(f); } else if (k == "numeric_format") { if (count(v.begin(), v.end(), '%') != 1) throw ExecuteError("Exactly one `%' expected, e.g. '%.9g'"); set_long_double_format(v); } else if (k == "cwd") { change_current_working_dir(v.c_str()); } m_.*opt.val.s.ptr = v; } else { // if (opt.vtype == kEnum) const char **ptr = opt.allowed_values; while (*ptr) { if (*ptr == v) { m_.*opt.val.e.ptr = *ptr; return; } ++ptr; } throw ExecuteError("`" + v + "' is not a valid value for `" + k + "'"); } } void SettingsMgr::set_as_number(string const& k, double d) { string sp = get_as_string(k); if (sp == S(d)) { ctx_->msg("Option '" + k + "' already has value: " + sp); return; } const Option& opt = find_option(k); assert(opt.vtype == kInt || opt.vtype == kDouble || opt.vtype == kBool); if (opt.vtype == kInt) { m_.*opt.val.i.ptr = iround(d); if (k == "pseudo_random_seed") do_srand(); } else if (opt.vtype == kDouble) { if (k == "epsilon") { if (d <= 0.) throw ExecuteError("Value of epsilon must be positive."); epsilon = d; } m_.*opt.val.d.ptr = d; } else // if (opt.vtype == kBool) m_.*opt.val.b.ptr = (fabs(d) >= 0.5); } SettingsMgr::ValueType SettingsMgr::get_value_type(const string& k) { try { return find_option(k).vtype; } catch (ExecuteError&) { return kNotFound; } } string SettingsMgr::get_type_desc(const string& k) { const Option& opt = find_option(k); switch (opt.vtype) { case kInt: return "integer number"; case kDouble: return "real number"; case kBool: return "boolean (0/1)"; case kString: return "'string'"; case kEnum: { const char **ptr = opt.allowed_values; string s = "one of: " + S(*ptr); while (*++ptr) s += S(", ") + *ptr; return s; } case kNotFound: assert(0); } return ""; } vector SettingsMgr::get_key_list(const string& start) { vector v; size_t len = sizeof(options) / sizeof(options[0]); for (size_t i = 0; i != len; ++i) if (startswith(options[i].name, start)) v.push_back(options[i].name); sort(v.begin(), v.end()); return v; } const char** SettingsMgr::get_allowed_values(const std::string& k) { return find_option(k).allowed_values; } void SettingsMgr::do_srand() { int seed = m_.pseudo_random_seed == 0 ? (int) time(NULL) : m_.pseudo_random_seed; srand(seed); #if HAVE_LIBNLOPT nlopt_srand(seed); #endif } } // namespace fityk fityk-1.3.1/fityk/settings.h000066400000000000000000000063121302634723100160040ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_SETTINGS_H_ #define FITYK_SETTINGS_H_ #include "common.h" namespace fityk { class BasicContext; // settings that can be changed using the set command struct FITYK_API Settings { // general int verbosity; bool autoplot; const char* on_error; double epsilon; // for now, there is also global epsilon const char* default_sigma; int pseudo_random_seed; std::string numeric_format; std::string logfile; bool log_output; double function_cutoff; std::string cwd; // current working directory // guess double height_correction; double width_correction; bool guess_uses_weights; // fitting const char* fitting_method; int max_wssr_evaluations; double max_fitting_time; int refresh_period; bool fit_replot; double domain_percent; bool box_constraints; // fitting - LM double lm_lambda_start; double lm_lambda_up_factor; double lm_lambda_down_factor; double lm_max_lambda; double lm_stop_rel_change; // fitting - MPFIT & NLopt double ftol_rel; double xtol_rel; //double mpfit_gtol; // fitting - NM double nm_convergence; bool nm_move_all; const char* nm_distribution; double nm_move_factor; }; /// Wraps struct Settings class FITYK_API SettingsMgr { public: enum ValueType { kInt, kDouble, kBool, kString, kEnum, kNotFound // used as a return value from get_value_type() }; SettingsMgr(BasicContext const* ctx); /// get all option keys that start with given string static std::vector get_key_list (const std::string& start); /// returns NULL-terminated list of values for kEnum type, NULL otherwise static const char** get_allowed_values(const std::string& k); /// return value type of the option static ValueType get_value_type(const std::string& k); /// get text information about type of option k static std::string get_type_desc(const std::string& k); // getters const Settings& m() const { return m_; } /// get value of option as string std::string get_as_string(const std::string& k, bool quote_str=true) const; /// get value of option as number double get_as_number(const std::string& k) const; /// get kEnum index int get_enum_index(const std::string& k) const; // setters void set_as_string(const std::string& k, const std::string& v); void set_as_number(const std::string& k, double v); void set_all(const Settings& s) { m_ = s; epsilon = s.epsilon; } // utilities that use settings void do_srand(); std::string format_double(double d) const { return format1(m_.numeric_format.c_str(), d); } std::string format_double(long double d) const { return format1(long_double_format_.c_str(), d); } private: const BasicContext* ctx_; // used for msg() Settings m_; std::string long_double_format_; void set_long_double_format(const std::string& double_fmt); DISALLOW_COPY_AND_ASSIGN(SettingsMgr); }; } // namespace fityk #endif fityk-1.3.1/fityk/swig/000077500000000000000000000000001302634723100147425ustar00rootroot00000000000000fityk-1.3.1/fityk/swig/fityk.i000066400000000000000000000141651302634723100162510ustar00rootroot00000000000000// This file is part of fityk program. // Licence: GNU General Public License version 2 // tests for bindings are in the samples/ directory %{ // suppress a number of clang warnings from SWIG-generated code #ifdef __clang__ #pragma clang diagnostic ignored "-Wused-but-marked-unused" #pragma clang diagnostic ignored "-Wmissing-variable-declarations" #pragma clang diagnostic ignored "-Wunreachable-code" #pragma clang diagnostic ignored "-Wmissing-prototypes" #pragma clang diagnostic ignored "-Wshadow" #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #pragma clang diagnostic ignored "-Wconditional-uninitialized" #endif %} #if defined(SWIGPERL) // Perl has convention of capitalized module names %module Fityk #elif defined(SWIGJAVA) // module name fityk creates filename conflicts with Fityk class // on case-insensitive filesystems %module FitykModule #else %module fityk #endif %feature("autodoc", "1"); %{ #define BUILDING_LIBFITYK #include "fityk.h" %} %include "std_string.i" %include "std_vector.i" %include "std_except.i" #ifdef SWIGLUA %extend std::vector { int __len(void*) { return self->size(); } } #endif namespace std { %template(PointVector) vector; /* temporarily realt is replaced by double as a workaround of SWIG bug. * It's likely the same bug as in: * http://article.gmane.org/gmane.comp.programming.swig.devel/21772 */ //%template(RealVector) vector; %template(RealVector) vector; %template(VarVector) vector; %template(FuncVector) vector; } // implementation, not api %ignore get_ftk; %ignore get_covariance_matrix_as_array; #if defined(SWIGLUA) || defined(SWIGJAVA) namespace std { class runtime_error : public exception { public: explicit runtime_error (const string& what_arg); }; class invalid_argument : public exception { public: explicit invalid_argument (const string& what_arg); }; } #endif #if defined(SWIGPYTHON) || defined(SWIGLUA) %extend fityk::Point { std::string __str__() { return $self->str(); } } %extend fityk::Func { std::string __str__() { return "name + ">"; } } %extend fityk::Var { std::string __str__() { return "name + ">"; } } #endif #if defined(SWIGPYTHON) %extend fityk::SyntaxError { const char* __str__() { return $self->what(); } } %extend fityk::ExecuteError { const char* __str__() { return $self->what(); } } %include "file.i" #elif defined(SWIGLUA) %typemap(throws) fityk::ExecuteError { lua_pushstring(L,$1.what()); SWIG_fail; } %typemap(throws) fityk::SyntaxError { lua_pushstring(L,$1.what()); SWIG_fail; } %typemap(in) FILE * { FILE **f; if (lua_isnil(L, $input)) $1=NULL; else { f = (FILE **)luaL_checkudata(L, $input, "FILE*"); if (*f == NULL) luaL_error(L, "attempt to use a closed file"); $1=*f; } } #elif defined(SWIGPERL) %typemap(in) FILE * { if (!SvTRUE($input)) $1=NULL; else $1 = PerlIO_exportFILE(IoIFP(sv_2io($input)), NULL); } %typemap(throws) fityk::ExecuteError { std::string msg = std::string("Runtime error: ") + $1.what() + "\n "; croak(msg.c_str()); } %typemap(throws) fityk::SyntaxError { std::string msg = std::string("Syntax error: ") + $1.what() + "\n "; croak(msg.c_str()); } #elif defined(SWIGRUBY) %extend fityk::Point { std::string to_s() { return $self->str(); } } %extend fityk::SyntaxError { const char* to_s() { return $self->what(); } } %extend fityk::ExecuteError { const char* to_s() { return $self->what(); } } %include "file.i" #elif defined(SWIGJAVA) %rename(isLesser) operator<; #else #warning \ fityk.i supports Python, Perl, Ruby and Lua.\ If you use another language, please let me know - wojdyr@gmail.com #endif #if !defined(SWIGJAVA) %apply FILE* { std::FILE* }; #endif /* ui_api.h is wrapped only by Python now, let me know if you'd like to use * it from another language. */ #if defined(SWIGPYTHON) namespace std { %template(StringVector) vector; } %typemap(check) PyObject *pyfunc { if (!PyCallable_Check($1)) SWIG_exception(SWIG_TypeError,"Expected function."); } /* we had problem with user_interrupt, see https://github.com/swig/swig/issues/629 */ %apply int { std::sig_atomic_t }; #define FITYK_API // empirical workaround that makes SWIG 2.0.8 work %{ using fityk::Fityk; // empirical workaround that makes SWIG 2.0.8 work #include "ui_api.h" PyObject *_py_show_message_func = NULL; static void PythonShowMessageCallBack(fityk::UiApi::Style style, std::string const& s) { PyObject *arglist = Py_BuildValue("(is)", style, s.c_str()); PyEval_CallObject(_py_show_message_func, arglist); Py_DECREF(arglist); } PyObject *_py_draw_plot_func = NULL; static void PythonDrawPlotCallBack(fityk::UiApi::RepaintMode mode, const char* /*filename*/) { PyObject *arglist = Py_BuildValue("(i)", mode); PyEval_CallObject(_py_draw_plot_func, arglist); Py_DECREF(arglist); } %} %extend fityk::UiApi { void connect_show_message_py(PyObject *pyfunc) { if (_py_show_message_func != NULL) Py_DECREF(_py_show_message_func); _py_show_message_func = pyfunc; self->connect_show_message(PythonShowMessageCallBack); Py_INCREF(pyfunc); } void connect_draw_plot_py(PyObject *pyfunc) { if (_py_draw_plot_func != NULL) Py_DECREF(_py_draw_plot_func); _py_draw_plot_func = pyfunc; self->connect_draw_plot(PythonDrawPlotCallBack); Py_INCREF(pyfunc); } } %include "ui_api.h" #else %ignore get_ui_api; #endif %include "fityk.h" fityk-1.3.1/fityk/tplate.cpp000066400000000000000000000264451302634723100160010ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "tplate.h" #include // for assert #include "common.h" #include "func.h" #include "udf.h" #include "bfunc.h" #include "f_fcjasym.h" #include "lexer.h" #include "cparser.h" #include "eparser.h" #include "guess.h" using namespace std; namespace fityk { string Tplate::as_formula() const { string r = name + "("; for (size_t i = 0; i != fargs.size(); ++i) { if (i != 0) r += ", "; r += fargs[i]; if (!defvals[i].empty()) r += "=" + defvals[i]; } r += ") = " + rhs; return r; } bool Tplate::is_coded() const { return create != create_CompoundFunction && create != create_SplitFunction && create != create_CustomFunction && create != NULL; // return false for empty Tplate } vector Tplate::get_missing_default_values() const { vector gkeys; if (traits & kLinear) gkeys.insert(gkeys.end(), Guess::linear_traits.begin(), Guess::linear_traits.end()); if (traits & kPeak) gkeys.insert(gkeys.end(), Guess::peak_traits.begin(), Guess::peak_traits.end()); if (traits & kSigmoid) gkeys.insert(gkeys.end(), Guess::sigmoid_traits.begin(), Guess::sigmoid_traits.end()); ExpressionParser ep(NULL); vector missing; for (size_t i = 0; i < fargs.size(); ++i) { string dv = defvals[i].empty() ? fargs[i] : defvals[i]; ep.clear_vm(); Lexer lex(dv.c_str()); ep.parse_expr(lex, 0, &gkeys, &missing); } return missing; } #define FACTORY_FUNC(NAME) \ Function* create_##NAME(const Settings* settings, const std::string& name, \ Tplate::Ptr tp, const std::vector& vars) \ { return new NAME(settings, name, tp, vars); } static FACTORY_FUNC(FuncConstant) static FACTORY_FUNC(FuncLinear) static FACTORY_FUNC(FuncQuadratic) static FACTORY_FUNC(FuncCubic) static FACTORY_FUNC(FuncPolynomial4) static FACTORY_FUNC(FuncPolynomial5) static FACTORY_FUNC(FuncPolynomial6) static FACTORY_FUNC(FuncGaussian) static FACTORY_FUNC(FuncSplitGaussian) static FACTORY_FUNC(FuncLorentzian) static FACTORY_FUNC(FuncPearson7) static FACTORY_FUNC(FuncSplitPearson7) static FACTORY_FUNC(FuncPseudoVoigt) static FACTORY_FUNC(FuncVoigt) static FACTORY_FUNC(FuncVoigtA) static FACTORY_FUNC(FuncEMG) static FACTORY_FUNC(FuncDoniachSunjic) static FACTORY_FUNC(FuncPielaszekCube) static FACTORY_FUNC(FuncLogNormal) static FACTORY_FUNC(FuncSpline) static FACTORY_FUNC(FuncPolyline) static FACTORY_FUNC(FuncFCJAsymm) FACTORY_FUNC(CustomFunction) FACTORY_FUNC(CompoundFunction) FACTORY_FUNC(SplitFunction) void TplateMgr::add(const char* name, const char* cs_fargs, // comma-separated parameters const char* cs_dv, // comma-separated default values const char* rhs, int traits, Tplate::create_type create, Parser* parser, bool documented) { Tplate* tp = new Tplate; tp->name = name; if (cs_fargs[0] != '\0') { tp->fargs = split_string(cs_fargs, ','); tp->defvals = split_string(cs_dv, ','); } tp->rhs = rhs; tp->traits = traits; tp->create = create; tp->docs_fragment = documented ? name : NULL; assert(tp->fargs.size() == tp->defvals.size()); tpvec_.push_back(Tplate::Ptr(tp)); if (parser) { Lexer lex(rhs); parser->parse_define_rhs(lex, tp); } } void TplateMgr::add_builtin_types(Parser* p) { tpvec_.reserve(32); //------------------- coded in bfunc.cpp --------------------- add("Constant", "a", "avgy", "a", Tplate::kLinear, &create_FuncConstant); add("Linear", "a0,a1", "intercept,slope", "a0 + a1 * x", Tplate::kLinear, &create_FuncLinear); add("Quadratic", "a0,a1,a2", "intercept,slope,0", "a0 + a1*x + a2*x^2", Tplate::kLinear, &create_FuncQuadratic); add("Cubic", "a0,a1,a2,a3", "intercept,slope,0,0", "a0 + a1*x + a2*x^2 + a3*x^3", Tplate::kLinear, &create_FuncCubic); add("Polynomial4", "a0,a1,a2,a3,a4", "intercept,slope,0,0,0", "a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4", Tplate::kLinear, &create_FuncPolynomial4); add("Polynomial5", "a0,a1,a2,a3,a4,a5", "intercept,slope,0,0,0,0", "a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5", Tplate::kLinear, &create_FuncPolynomial5, NULL, true); add("Polynomial6", "a0,a1,a2,a3,a4,a5,a6", "intercept,slope,0,0,0,0,0", "a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5 + a6*x^6", Tplate::kLinear, &create_FuncPolynomial6); add("Gaussian", "height,center,hwhm", ",,", "height*exp(-ln(2)*((x-center)/hwhm)^2)", Tplate::kPeak, &create_FuncGaussian, NULL, true); add("SplitGaussian", "height,center,hwhm1,hwhm2", ",,hwhm,hwhm", "x

components[0].cargs.size() == 3); assert(tpvec_.back()->components[0].cargs[1].code().size() == 2); add("Pearson7A", "area,center,hwhm,shape", ",,,2", "Pearson7(area/(hwhm*exp(lgamma(shape-0.5)-lgamma(shape))" "*sqrt(pi/(2^(1/shape)-1))), " "center, hwhm, shape)", Tplate::kPeak, &create_CompoundFunction, p, true); add("PseudoVoigtA", "area,center,hwhm,shape", ",,,0.5[0:1]", "GaussianA(area*(1-shape), center, hwhm)" " + LorentzianA(area*shape, center, hwhm)", Tplate::kPeak, &create_CompoundFunction, p, true); add("Sigmoid", "lower,upper,xmid,wsig", ",,,", "lower + (upper-lower)/(1+exp((xmid-x)/wsig))", Tplate::kSigmoid, &create_CustomFunction, p, true); add("SplitLorentzian", "height,center,hwhm1,hwhm2", ",,hwhm,hwhm", "x < center ? Lorentzian(height, center, hwhm1)" " : Lorentzian(height, center, hwhm2)", Tplate::kPeak, &create_SplitFunction, p, true); add("SplitPseudoVoigt", "height,center,hwhm1,hwhm2,shape1,shape2", ",,hwhm,hwhm,0.5[0:1],0.5[0:1]", "x < center ? PseudoVoigt(height, center, hwhm1, shape1)" " : PseudoVoigt(height, center, hwhm2, shape2)", Tplate::kPeak, &create_SplitFunction, p, true); add("SplitVoigt", "height,center,gwidth1,gwidth2,shape1,shape2", ",,hwhm*0.8,hwhm*0.8,0.1[0:1],0.1[0:1]", "x < center ? Voigt(height, center, gwidth1, shape1)" " : Voigt(height, center, gwidth2, shape2)", Tplate::kPeak, &create_SplitFunction, p, true); } void TplateMgr::define(Tplate::Ptr tp) { if (get_tp(tp->name) != NULL) throw ExecuteError(tp->name + " is already defined. (undefine it first)"); tpvec_.push_back(tp); } void TplateMgr::undefine(string const &type) { vector::iterator iter; for (iter = tpvec_.begin(); iter != tpvec_.end(); ++iter) if ((*iter)->name == type) break; if (iter == tpvec_.end()) throw ExecuteError(type + " is not defined"); if (iter->use_count() > 1) throw ExecuteError(type + " is currently used (" + S(iter->use_count() - 1) + ")."); tpvec_.erase(iter); } const Tplate* TplateMgr::get_tp(string const &type) const { v_foreach (Tplate::Ptr, i, tpvec_) if ((*i)->name == type) return i->get(); return NULL; } Tplate::Ptr TplateMgr::get_shared_tp(string const &type) const { v_foreach (Tplate::Ptr, i, tpvec_) if ((*i)->name == type) return *i; return Tplate::Ptr(); } vector reorder_args(Tplate::Ptr tp, const vector &keys, const vector &values) { assert (keys.size() == values.size()); int n = tp->fargs.size(); vector vv(n, (VMData*) NULL); for (int i = 0; i < n; ++i) { int idx = index_of_element(keys, tp->fargs[i]); if (idx != -1) vv[i] = values[idx]; } return vv; } } // namespace fityk fityk-1.3.1/fityk/tplate.h000066400000000000000000000062761302634723100154460ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_TPLATE_H_ #define FITYK_TPLATE_H_ #include #include #include #include "common.h" // DISALLOW_COPY_AND_ASSIGN #include "vm.h" // VMData namespace fityk { struct Settings; class Function; class Parser; struct OpTree; /// template -- function type, like Gaussian(height, center, hwhm) = ..., /// which can be used to create %functions by binding $variables to template's /// parameters. struct FITYK_API Tplate { typedef boost::shared_ptr Ptr; typedef Function* (*create_type)(const Settings*, const std::string&, Ptr, const std::vector&); struct Component { Ptr p; std::vector cargs; }; enum Kind { kLinear = 1, kPeak = 2, kSigmoid = 4 }; std::string name; std::vector fargs; std::vector defvals; std::string rhs; // used in info only, not in calculations int traits; // 0 or combination of kLinear, kPeak and kSigmoid create_type create; std::vector components; // CompoundFunction, SplitFunction std::vector op_trees; // CustomFunction const char* docs_fragment; std::string as_formula() const; bool is_coded() const; std::vector get_missing_default_values() const; }; // takes keyword args and returns positional args for given function. // Used when we get Gaussian(center=1,whatever=2,height=3,hwhm=4) // instead of Gaussian(3,1,4) std::vector reorder_args(Tplate::Ptr, const std::vector &keys, const std::vector &values); /// template manager class FITYK_API TplateMgr { public: TplateMgr() {} // initialization void add_builtin_types(Parser* p); /// stores the formula void define(Tplate::Ptr tp); /// removes the definition void undefine(const std::string& name); /// returns NULL if not found const Tplate* get_tp(const std::string& name) const; Tplate::Ptr get_shared_tp(const std::string& name) const; const std::vector& tpvec() const { return tpvec_; } private: std::vector tpvec_; void add(const char* name, const char* cs_fargs, const char* cs_dv, const char* rhs, int traits, Tplate::create_type create, Parser* parser=NULL, bool documented=false); DISALLOW_COPY_AND_ASSIGN(TplateMgr); }; // create_* functions defined by macro in tplate.cpp, also used in cparser.cpp Function* create_CompoundFunction(const Settings* s, const std::string& name, Tplate::Ptr tp, const std::vector& vars); Function* create_SplitFunction(const Settings* s, const std::string& name, Tplate::Ptr tp, const std::vector& vars); Function* create_CustomFunction(const Settings* s, const std::string& name, Tplate::Ptr tp, const std::vector& vars); } // namespace fityk #endif // FITYK_TPLATE_H_ fityk-1.3.1/fityk/transform.cpp000066400000000000000000000177211302634723100165200ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// virtual machine for dataset transformations (@n = ...) #define BUILDING_LIBFITYK #include "transform.h" #include "logic.h" #include "data.h" using namespace std; namespace { using namespace fityk; struct DtStackItem { bool is_num; realt num; vector points; string title; }; realt find_extrapolated_y(vector const& pp, realt x) { if (pp.empty()) return 0; else if (x <= pp.front().x) return pp.front().y; else if (x >= pp.back().x) return pp.back().y; vector::const_iterator i = lower_bound(pp.begin(), pp.end(), Point(x, 0)); assert (i > pp.begin() && i < pp.end()); if (is_eq(x, i->x)) return i->y; else return (i-1)->y + (i->y - (i-1)->y) * (i->x - x) / (i->x - (i-1)->x); } void merge_same_x(vector &pp, bool avg) { int count_same = 1; double x0 = 0; // 0 is assigned only to avoid compiler warnings for (int i = pp.size() - 2; i >= 0; --i) { if (count_same == 1) x0 = pp[i+1].x; if (is_eq(pp[i].x, x0)) { pp[i].x += pp[i+1].x; pp[i].y += pp[i+1].y; pp[i].sigma += pp[i+1].sigma; pp[i].is_active = pp[i].is_active || pp[i+1].is_active; pp.erase(pp.begin() + i+1); count_same++; if (i > 0) continue; else i = -1; // to change pp[0] } if (count_same > 1) { pp[i+1].x /= count_same; if (avg) { pp[i+1].y /= count_same; pp[i+1].sigma /= count_same; } count_same = 1; } } } void shirley_bg(vector &pp) { const int max_iter = 50; const double max_rdiff = 1e-6; const int n = pp.size(); double ya = pp[0].y; // lowest bg double yb = pp[n-1].y; // highest bg double dy = yb - ya; vector B(n, ya); vector PA(n, 0.); double old_A = 0; for (int iter = 0; iter < max_iter; ++iter) { vector Y(n); for (int i = 0; i < n; ++i) Y[i] = pp[i].y - B[i]; for (int i = 1; i < n; ++i) PA[i] = PA[i-1] + (Y[i] + Y[i-1]) / 2 * (pp[i].x - pp[i-1].x); double rel_diff = old_A != 0. ? fabs(PA[n-1] - old_A) / old_A : 1.; if (rel_diff < max_rdiff) break; old_A = PA[n-1]; for (int i = 0; i < n; ++i) B[i] = ya + dy / PA[n-1] * PA[i]; } for (int i = 0; i < n; ++i) pp[i].y = B[i]; } } // anonymous namespace namespace fityk { /// executes VM code and stores results in dataset `data_out' void run_data_transform(const DataKeeper& dk, const VMData& vm, Data* data_out) { DtStackItem stack[6]; DtStackItem* stackPtr = stack - 1; // will be ++'ed first v_foreach (int, i, vm.code()) { switch (*i) { case OP_NUMBER: stackPtr += 1; if (stackPtr - stack >= 6) throw ExecuteError("stack overflow"); ++i; stackPtr->is_num = true; stackPtr->num = vm.numbers()[*i]; break; case OP_DATASET: stackPtr += 1; if (stackPtr - stack >= 6) throw ExecuteError("stack overflow"); stackPtr->is_num = false; ++i; stackPtr->points = dk.data(*i)->points(); stackPtr->title = dk.data(*i)->get_title(); if (stackPtr->title.empty()) stackPtr->title = "nt"; // no title break; case OP_NEG: if (stackPtr->is_num) stackPtr->num = -stackPtr->num; else { vm_foreach (Point, j, stackPtr->points) j->y = -j->y; stackPtr->title = "-" + stackPtr->title; } break; case OP_ADD: stackPtr -= 1; if (stackPtr->is_num && (stackPtr+1)->is_num) stackPtr->num += (stackPtr+1)->num; else if (!stackPtr->is_num && !(stackPtr+1)->is_num) { vm_foreach (Point, j, stackPtr->points) j->y += find_extrapolated_y((stackPtr+1)->points, j->x); stackPtr->title += "+" + (stackPtr+1)->title; } else throw ExecuteError("adding number and dataset"); break; case OP_SUB: stackPtr -= 1; if (stackPtr->is_num && (stackPtr+1)->is_num) stackPtr->num -= (stackPtr+1)->num; else if (!stackPtr->is_num && !(stackPtr+1)->is_num) { vm_foreach (Point, j, stackPtr->points) j->y -= find_extrapolated_y((stackPtr+1)->points, j->x); stackPtr->title += "-" + (stackPtr+1)->title; } else throw ExecuteError("substracting number and dataset"); break; case OP_MUL: stackPtr -= 1; if (stackPtr->is_num && (stackPtr+1)->is_num) stackPtr->num *= (stackPtr+1)->num; else if (!stackPtr->is_num && !(stackPtr+1)->is_num) { throw ExecuteError("multiplying two datasets"); } else if (!stackPtr->is_num && (stackPtr+1)->is_num) { realt mult = (stackPtr+1)->num; vm_foreach (Point, j, stackPtr->points) j->y *= mult; stackPtr->title += "*" + S(mult); } else if (stackPtr->is_num && !(stackPtr+1)->is_num) { realt mult = stackPtr->num; stackPtr->points.swap((stackPtr+1)->points); stackPtr->is_num = false; vm_foreach (Point, j, stackPtr->points) j->y *= mult; stackPtr->title = S(mult) + "*" + (stackPtr+1)->title; } break; case OP_DT_SUM_SAME_X: if (stackPtr->is_num) throw ExecuteError(op2str(*i) + " is defined only for @n"); merge_same_x(stackPtr->points, false); break; case OP_DT_AVG_SAME_X: if (stackPtr->is_num) throw ExecuteError(op2str(*i) + " is defined only for @n"); merge_same_x(stackPtr->points, true); break; case OP_DT_SHIRLEY_BG: if (stackPtr->is_num) throw ExecuteError(op2str(*i) + " is defined only for @n"); shirley_bg(stackPtr->points); break; case OP_AND: // do nothing break; case OP_AFTER_AND: stackPtr -= 1; if (stackPtr->is_num || (stackPtr+1)->is_num) throw ExecuteError("expected @n on both sides of `and'"); stackPtr->points.insert(stackPtr->points.end(), (stackPtr+1)->points.begin(), (stackPtr+1)->points.end()); sort(stackPtr->points.begin(), stackPtr->points.end()); stackPtr->title += "&" + (stackPtr+1)->title; break; default: throw ExecuteError("op " + op2str(*i) + " is not allowed in dataset transformations."); } } assert(stackPtr == stack); if (!stackPtr->is_num) { data_out->set_points(stackPtr->points); data_out->set_title(stackPtr->title); } else if (stackPtr->num == 0.) data_out->clear(); else throw ExecuteError("dataset or 0 expected on RHS"); } } // namespace fityk fityk-1.3.1/fityk/transform.h000066400000000000000000000006621302634723100161610ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// virtual machine for dataset transformations (@n = ...) #ifndef FITYK_TRANSFORM_H_ #define FITYK_TRANSFORM_H_ #include "vm.h" namespace fityk { class Data; class DataKeeper; void run_data_transform(const DataKeeper& dk, const VMData& vm, Data* data_out); } // namespace fityk #endif // FITYK_TRANSFORM_H_ fityk-1.3.1/fityk/udf.cpp000066400000000000000000000334361302634723100152640ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "udf.h" #include "ast.h" #include "lexer.h" #include "cparser.h" using namespace std; namespace fityk { static Function* init_component(const string& func_name, const Tplate::Component& c, vector& variables, const Settings* settings) { assert(c.p); vector varnames; v_foreach (VMData, j, c.cargs) { string var_name; if (j->single_symbol()) { int idx = j->code()[1]; var_name = variables[idx]->name; } else { var_name = "_i" + S(variables.size() + 1); VMData vm = *j; if (vm.has_op(OP_TILDE)) throw ExecuteError("unexpected `~' in UDF"); Variable *v = make_compound_variable(var_name, &vm, variables); v->set_var_idx(variables); variables.push_back(v); } varnames.push_back(var_name); } Function *func = (*c.p->create)(settings, func_name, c.p, varnames); func->init(); func->update_var_indices(variables); return func; } CompoundFunction::CompoundFunction(const Settings* settings, const string &name, const Tplate::Ptr tp, const vector &vars) : Function(settings, name, tp, vars) { } CompoundFunction::~CompoundFunction() { purge_all_elements(intern_functions_); purge_all_elements(intern_variables_); } void CompoundFunction::init() { Function::init(); // add mirror-variables for (int j = 0; j != nv(); ++j) { Variable* var = new Variable(used_vars_.get_name(j), -2); intern_variables_.push_back(var); } v_foreach (Tplate::Component, i, tp_->components) { string func_name = "_i" + S(intern_functions_.size() + 1); Function *func = init_component(func_name, *i, intern_variables_, settings_); intern_functions_.push_back(func); } } void CompoundFunction::update_var_indices(vector const& variables) { Function::update_var_indices(variables); for (int i = 0; i < nv(); ++i) { const Variable* orig = variables[used_vars_.get_idx(i)]; intern_variables_[i]->set_original(orig); } } void CompoundFunction::more_precomputations() { vm_foreach (Variable*, i, intern_variables_) (*i)->recalculate(intern_variables_, vector()); vm_foreach (Function*, i, intern_functions_) (*i)->do_precomputations(intern_variables_); } void CompoundFunction::calculate_value_in_range(const vector &xx, vector &yy, int first, int last) const { v_foreach (Function*, i, intern_functions_) (*i)->calculate_value_in_range(xx, yy, first, last); } void CompoundFunction::calculate_value_deriv_in_range(const vector &xx, vector &yy, vector &dy_da, bool in_dx, int first, int last) const { v_foreach (Function*, i, intern_functions_) (*i)->calculate_value_deriv_in_range(xx, yy, dy_da, in_dx, first, last); } string CompoundFunction::get_current_formula(const string& x, const char *num_fmt) const { string t; v_foreach (Function*, i, intern_functions_) { if (!t.empty()) t += "+"; t += (*i)->get_current_formula(x, num_fmt); } return t; } bool CompoundFunction::is_symmetric() const { realt ctr; if (!get_center(&ctr)) return false; v_foreach (Function*, i, intern_functions_) if (!(*i)->is_symmetric()) return false; return true; } bool CompoundFunction::get_center(realt* a) const { if (Function::get_center(a)) return true; vector const& ff = intern_functions_; bool r = ff[0]->get_center(a); if (!r) return false; for (size_t i = 1; i < ff.size(); ++i) { realt b; r = ff[i]->get_center(&b); if (!r || is_neq(*a, b)) return false; } return true; } /// if consists of >1 functions and centers are in the same place /// height is a sum of heights bool CompoundFunction::get_height(realt* a) const { vector const& ff = intern_functions_; if (ff.size() == 1) return ff[0]->get_height(a); realt ctr; if (!get_center(&ctr)) return false; realt sum = 0; for (size_t i = 0; i < ff.size(); ++i) { if (!ff[i]->get_height(a)) return false; sum += *a; } *a = sum; return true; } bool CompoundFunction::get_fwhm(realt* a) const { vector const& ff = intern_functions_; if (ff.size() == 1) return ff[0]->get_fwhm(a); return false; } bool CompoundFunction::get_area(realt* a) const { vector const& ff = intern_functions_; realt sum = 0; for (size_t i = 0; i < ff.size(); ++i) if (ff[i]->get_area(a)) sum += *a; else return false; *a = sum; return true; } bool CompoundFunction::get_nonzero_range(double level, realt& left, realt& right) const { vector const& ff = intern_functions_; if (ff.size() == 1) return ff[0]->get_nonzero_range(level, left, right); else return false; } /////////////////////////////////////////////////////////////////////// CustomFunction::CustomFunction(const Settings* settings, const string &name, const Tplate::Ptr tp, const vector &vars) : Function(settings, name, tp, vars), // don't use nv() here, it's not set until init() derivatives_(vars.size()+1), value_offset_(0) { } CustomFunction::~CustomFunction() { } void CustomFunction::update_var_indices(const vector& variables) { Function::update_var_indices(variables); assert(used_vars().get_count() + 2 == (int) tp_->op_trees.size()); // we put function's parameter index rather than variable index after // OP_SYMBOL, it is handled in this way in more_precomputations() vector symbol_map = range_vector(0, used_vars().get_count()); vm_.clear_data(); int n = tp_->op_trees.size() - 1; for (int i = 0; i < n; ++i) { add_bytecode_from_tree(tp_->op_trees[i], symbol_map, vm_); vm_.append_code(OP_PUT_DERIV); vm_.append_code(i); } value_offset_ = vm_.code().size(); add_bytecode_from_tree(tp_->op_trees.back(), symbol_map, vm_); } void CustomFunction::more_precomputations() { substituted_vm_ = vm_; substituted_vm_.replace_symbols(av_); } void CustomFunction::calculate_value_in_range(const vector &xx, vector &yy, int first, int last) const { for (int i = first; i < last; ++i) yy[i] += run_code_for_custom_func_value(substituted_vm_, xx[i], value_offset_); } void CustomFunction::calculate_value_deriv_in_range(const vector &xx, vector &yy, vector &dy_da, bool in_dx, int first, int last) const { int dyn = dy_da.size() / xx.size(); for (int i = first; i < last; ++i) { realt y = run_code_for_custom_func(substituted_vm_, xx[i],derivatives_); if (!in_dx) { yy[i] += y; v_foreach (Multi, j, multi_) dy_da[dyn*i+j->p] += derivatives_[j->n] * j->mult; dy_da[dyn*i+dyn-1] += derivatives_.back(); } else { v_foreach (Multi, j, multi_) dy_da[dyn*i+j->p] += dy_da[dyn*i+dyn-1] * derivatives_[j->n] * j->mult; } } } string CustomFunction::get_bytecode() const { const VMData& s = substituted_vm_; vector der_code(s.code().begin(), s.code().begin() + value_offset_); vector val_code(s.code().begin() + value_offset_, s.code().end()); return "code with symbols: " + vm2str(vm_) + "\nderivatives: " + vm2str(der_code, s.numbers()) + "\nvalue: " + vm2str(val_code, s.numbers()); } string CustomFunction::get_current_formula(const string& x, const char *num_fmt) const { Lexer lex(tp_->rhs.c_str()); string s = Parser(NULL).read_define_rhs_with_custom_func(lex, tp_.get()); replace_symbols_with_values(s, num_fmt); replace_words(s, "x", x); return s; } /////////////////////////////////////////////////////////////////////// SplitFunction::SplitFunction(const Settings* settings, const string &name, const Tplate::Ptr tp, const vector &vars) : Function(settings, name, tp, vars), left_(NULL), right_(NULL) { } SplitFunction::~SplitFunction() { delete left_; delete right_; purge_all_elements(intern_variables_); } void SplitFunction::init() { Function::init(); // add mirror-variables for (int j = 0; j != nv(); ++j) { Variable* var = new Variable(used_vars_.get_name(j), -2); intern_variables_.push_back(var); } left_ = init_component("l", tp_->components[1], intern_variables_, settings_); right_ = init_component("r", tp_->components[2], intern_variables_, settings_); VMData vm = tp_->components[0].cargs[0]; if (vm.has_op(OP_TILDE)) throw ExecuteError("unexpected `~' in condition in UDF"); Variable *v = make_compound_variable("split", &vm, intern_variables_); v->set_var_idx(intern_variables_); intern_variables_.push_back(v); } void SplitFunction::update_var_indices(vector const& variables) { Function::update_var_indices(variables); for (int i = 0; i < nv(); ++i) { const Variable* orig = variables[used_vars_.get_idx(i)]; intern_variables_[i]->set_original(orig); } } void SplitFunction::more_precomputations() { vm_foreach (Variable*, i, intern_variables_) (*i)->recalculate(intern_variables_, vector()); left_->do_precomputations(intern_variables_); right_->do_precomputations(intern_variables_); } void SplitFunction::calculate_value_in_range(const vector &xx, vector &yy, int first, int last) const { realt xsplit = intern_variables_.back()->value(); int t = lower_bound(xx.begin(), xx.end(), xsplit) - xx.begin(); left_->calculate_value_in_range(xx, yy, first, t); right_->calculate_value_in_range(xx, yy, t, last); } void SplitFunction::calculate_value_deriv_in_range(const vector &xx, vector &yy, vector &dy_da, bool in_dx, int first, int last) const { realt xsplit = intern_variables_.back()->value(); int t = lower_bound(xx.begin(), xx.end(), xsplit) - xx.begin(); left_-> calculate_value_deriv_in_range(xx, yy, dy_da, in_dx, first, t); right_-> calculate_value_deriv_in_range(xx, yy, dy_da, in_dx, t, last); } string SplitFunction::get_current_formula(const string& x, const char* num_fmt) const { realt xsplit = intern_variables_.back()->value(); return "x < " + S(xsplit) + " ? " + left_->get_current_formula(x, num_fmt) + " : " + right_->get_current_formula(x, num_fmt); } bool SplitFunction::get_height(realt* a) const { realt h2; return left_->get_height(a) && right_->get_height(&h2) && is_eq(*a, h2); } bool SplitFunction::get_center(realt* a) const { if (Function::get_center(a)) return true; realt c2; return left_->get_center(a) && right_->get_center(&c2) && is_eq(*a, c2); } bool SplitFunction::get_fwhm(realt* a) const { realt c1, c2; realt xsplit = intern_variables_.back()->value(); bool two_halves = left_->is_symmetric() && right_->is_symmetric() && left_->get_center(&c1) && is_eq(c1, xsplit) && right_->get_center(&c2) && is_eq(c2, xsplit); realt fwhm1, fwhm2; if (two_halves && left_->get_fwhm(&fwhm1) && right_->get_fwhm(&fwhm2)) { *a = (fwhm1 + fwhm2) / 2.; return true; } else return false; } bool SplitFunction::get_area(realt* a) const { realt c1, c2; realt xsplit = intern_variables_.back()->value(); bool two_halves = left_->is_symmetric() && right_->is_symmetric() && left_->get_center(&c1) && is_eq(c1, xsplit) && right_->get_center(&c2) && is_eq(c2, xsplit); realt area1, area2; if (two_halves && left_->get_area(&area1) && right_->get_area(&area2)) { *a = (area1 + area2) / 2.; return true; } else return false; } bool SplitFunction::get_nonzero_range(double level, realt& left, realt& right) const { realt dummy; return left_->get_nonzero_range(level, left, dummy) && right_->get_nonzero_range(level, dummy, right); } } // namespace fityk fityk-1.3.1/fityk/udf.h000066400000000000000000000112521302634723100147210ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_UDF_H_ #define FITYK_UDF_H_ #include "func.h" #include "mgr.h" #include "common.h" namespace fityk { /// Function which definition is based on other function(s) class CompoundFunction: public Function { public: CompoundFunction(const Settings* settings, const std::string &name, Tplate::Ptr tp, const std::vector &vars); ~CompoundFunction(); virtual void init(); void more_precomputations(); void calculate_value_in_range(const std::vector &xx, std::vector &yy, int first, int last) const; void calculate_value_deriv_in_range(const std::vector &xx, std::vector &yy, std::vector &dy_da, bool in_dx, int first, int last) const; std::string get_current_formula(const std::string& x, const char *num_fmt) const; bool is_symmetric() const; bool get_center(realt* a) const; bool get_height(realt* a) const; bool get_fwhm(realt* a) const; bool get_area(realt* a) const; bool get_nonzero_range(double level, realt& left, realt& right) const; void update_var_indices(const std::vector& variables); protected: std::vector intern_variables_; std::vector intern_functions_; private: DISALLOW_COPY_AND_ASSIGN(CompoundFunction); }; ////////////////////////////////////////////////////////////////////////// /// User Defined Function, formula taken from user input class CustomFunction: public Function { public: CustomFunction(const Settings* settings, const std::string &name, const Tplate::Ptr tp, const std::vector &vars); ~CustomFunction(); void more_precomputations(); void calculate_value_in_range(std::vector const &xx, std::vector &yy, int first, int last) const; void calculate_value_deriv_in_range(std::vector const &xx, std::vector &yy, std::vector &dy_da, bool in_dx, int first, int last) const; std::string get_current_formula(const std::string& x, const char *num_fmt) const; void update_var_indices(std::vector const& variables); std::string get_bytecode() const; private: // used locally in calculate_value_deriv_in_range(), // declared as a member only as optimization, to avoid allocations mutable std::vector derivatives_; VMData vm_; VMData substituted_vm_; // made by substituting symbols with numbers in vm_ int value_offset_; DISALLOW_COPY_AND_ASSIGN(CustomFunction); }; ////////////////////////////////////////////////////////////////////////// /// split function, defined using "x < expr ? Func1(...) : Func2(...) class SplitFunction: public Function { public: SplitFunction(const Settings* settings, const std::string &name, Tplate::Ptr tp, const std::vector &vars); ~SplitFunction(); void init(); void more_precomputations(); void calculate_value_in_range(const std::vector &xx, std::vector &yy, int first, int last) const; void calculate_value_deriv_in_range(std::vector const &xx, std::vector &yy, std::vector &dy_da, bool in_dx, int first, int last) const; std::string get_current_formula(const std::string& x, const char *num_fmt) const; bool get_center(realt* a) const; bool get_height(realt* a) const; bool get_fwhm(realt* a) const; bool get_area(realt* a) const; bool get_nonzero_range(double level, realt& left, realt& right) const; void update_var_indices(const std::vector& variables); private: std::vector intern_variables_; Function *left_, *right_; DISALLOW_COPY_AND_ASSIGN(SplitFunction); }; } // namespace fityk #endif fityk-1.3.1/fityk/ui.cpp000066400000000000000000000237621302634723100151240ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "ui.h" #include #include #include #include #include #include #ifdef _WIN32 # include #else # include #endif #include "settings.h" #include "logic.h" #include "runner.h" // CommandExecutor using namespace std; namespace fityk { // utils for reading FILE #if !HAVE_GETLINE // simple replacement for GNU getline() (returns int, not ssize_t) static int our_getline(char **lineptr, size_t *n, FILE *stream) { int c; int counter = 0; while ((c = getc (stream)) != EOF) { if (counter >= (int) *n - 1) { *n = 2 * (*n) + 80; *lineptr = (char *) realloc (*lineptr, *n); if (lineptr == NULL) return -1; } (*lineptr)[counter] = c; ++counter; if (c == '\n') break; } if (counter == 0) return -1; (*lineptr)[counter] = '\0'; return counter; } #endif //!HAVE_GETLINE // the same as our_getline(), but works with gzFile instead of FILE static int gzipped_getline(char **lineptr, size_t *n, gzFile stream) { int c; int counter = 0; while ((c = gzgetc (stream)) != EOF) { if (counter >= (int) *n - 1) { *n = 2 * (*n) + 80; *lineptr = (char *) realloc (*lineptr, *n); if (lineptr == NULL) return -1; } (*lineptr)[counter] = c; ++counter; if (c == '\n') break; } if (counter == 0) return -1; (*lineptr)[counter] = '\0'; return counter; } // buffer for reading lines from file, with minimalistic interface class LineReader { public: LineReader() : len_(160), buf_((char*) malloc(len_)) {} ~LineReader() { free(buf_); } char* next(FILE *fp) { #if HAVE_GETLINE return return_buf(getline(&buf_, &len_, fp)); #else // if GNU getline() is not available, use very simple replacement return return_buf(our_getline(&buf_, &len_, fp)); #endif } char* gz_next(gzFile gz_stream) { return return_buf(gzipped_getline(&buf_, &len_, gz_stream)); } private: size_t len_; char* buf_; char* return_buf(int n) { if (n > 0 && buf_[n-1] == '\n') buf_[n-1] = '\0'; return n == -1 ? NULL : buf_; } }; string UserInterface::Cmd::str() const { switch (status) { case UiApi::kStatusOk: return cmd; case UiApi::kStatusExecuteError: return cmd + " #>Runtime Error"; case UiApi::kStatusSyntaxError: return cmd + " #>Syntax Error"; } return ""; // avoid compiler warnings } string UserInterface::get_history_summary() const { string s = S(cmd_count_) + " commands since the start of the program,"; if (cmd_count_ == size(cmds_)) s += " of which:"; else s += "\nin last " + S(cmds_.size()) + " commands:"; int n_ok = 0, n_execute_error = 0, n_syntax_error = 0; for (vector::const_iterator i = cmds_.begin(); i != cmds_.end(); ++i) if (i->status == UiApi::kStatusOk) ++n_ok; else if (i->status == UiApi::kStatusExecuteError) ++n_execute_error; else if (i->status == UiApi::kStatusSyntaxError) ++n_syntax_error; s += "\n " + S(n_ok) + " executed successfully" + "\n " + S(n_execute_error) + " finished with execute error" + "\n " + S(n_syntax_error) + " with syntax error"; return s; } UserInterface::UserInterface(BasicContext* ctx, CommandExecutor* ce) : ctx_(ctx), cmd_executor_(ce), cmd_count_(0), dirty_plot_(false) { } UiApi::Status UserInterface::exec_and_log(const string& c) { if (strip_string(c).empty()) return UiApi::kStatusOk; // we want to log the input before the output if (!ctx_->get_settings()->logfile.empty()) { FILE* f = fopen(ctx_->get_settings()->logfile.c_str(), "a"); if (f) { fprintf(f, "%s\n", c.c_str()); fclose(f); } } UiApi::Status r = execute_line_via_callback(c); cmds_.push_back(Cmd(c, r)); ++cmd_count_; return r; } UiApi::Status UserInterface::execute_line(const string& str) { UiApi::Status status = UiApi::kStatusOk; try { cmd_executor_->raw_execute_line(str); } catch (SyntaxError &e) { warn(string("Syntax error: ") + e.what()); status = UiApi::kStatusSyntaxError; } // ExecuteError and xylib::FormatError and xylib::RunTimeError // are derived from std::runtime_error catch (runtime_error &e) { warn(string("Error: ") + e.what()); status = UiApi::kStatusExecuteError; } if (dirty_plot_ && ctx_->get_settings()->autoplot) draw_plot(UiApi::kRepaint); return status; } void UserInterface::output_message(Style style, const string& s) const { show_message(style, s); if (!ctx_->get_settings()->logfile.empty() && ctx_->get_settings()->log_output) { FILE* f = fopen(ctx_->get_settings()->logfile.c_str(), "a"); if (f) { // insert "# " at the beginning of string and before every new line fprintf(f, "# "); for (const char *p = s.c_str(); *p; p++) { fputc(*p, f); if (*p == '\n') fprintf(f, "# "); } fprintf(f, "\n"); fclose(f); } } if (style == kWarning && ctx_->get_settings()->on_error[0] == 'e'/*exit*/) { show_message(kNormal, "Warning -> exiting program."); throw ExitRequestedException(); } } class FileOpener { public: virtual ~FileOpener() {} virtual bool open(const char* fn) = 0; virtual char* read_line() = 0; protected: LineReader reader; }; class NormalFileOpener : public FileOpener { public: NormalFileOpener() : f_(NULL) {} virtual ~NormalFileOpener() { if (f_) fclose(f_); } virtual bool open(const char* fn) { f_=fopen(fn, "r"); return f_!=NULL; } virtual char* read_line() { return reader.next(f_); } private: FILE *f_; }; class GzipFileOpener : public FileOpener { public: GzipFileOpener() : f_(NULL) {} virtual ~GzipFileOpener() { if (f_) gzclose(f_); } virtual bool open(const char* fn) { f_=gzopen(fn, "rb"); return f_!=NULL; } virtual char* read_line() { return reader.gz_next(f_); } private: gzFile f_; }; void UserInterface::exec_fityk_script(const string& filename) { user_interrupt = false; boost::scoped_ptr opener; if (endswith(filename, ".gz")) opener.reset(new GzipFileOpener); else opener.reset(new NormalFileOpener); if (!opener->open(filename.c_str())) { warn("Can't open file: " + filename); return; } int line_index = 0; char *line; string s; while ((line = opener->read_line()) != NULL) { ++line_index; if (line[0] == '\0') continue; if (ctx_->get_verbosity() >= 0) show_message (kQuoted, S(line_index) + "> " + line); s += line; if (*(s.end() - 1) == '\\') { s.resize(s.size()-1); continue; } if (s.find("_SCRIPT_DIR_/") != string::npos) { string dir = get_directory(filename); replace_all(s, "_EXECUTED_SCRIPT_DIR_/", dir); // old magic string replace_all(s, "_SCRIPT_DIR_/", dir); // new magic string } Status r = execute_line(s); if (r != kStatusOk && ctx_->get_settings()->on_error[0] != 'n' /*nothing*/) break; if (user_interrupt) { mesg("Script stopped by signal INT."); break; } s.clear(); } if (line == NULL && !s.empty()) throw SyntaxError("unfinished line"); } void UserInterface::exec_stream(FILE *fp) { LineReader reader; char *line; string s; while ((line = reader.next(fp)) != NULL) { if (ctx_->get_verbosity() >= 0) show_message(kQuoted, string("> ") + line); s += line; if (*(s.end() - 1) == '\\') { s.resize(s.size()-1); continue; } Status r = execute_line(s); if (r != kStatusOk) break; s.clear(); } if (line == NULL && !s.empty()) throw SyntaxError("unfinished line"); } void UserInterface::exec_string_as_script(const char* s) { const char* start = s; for (;;) { const char* end = start; while (*end != '\0' && *end != '\n') ++end; while (isspace(*(end-1)) && end > start) --end; if (end > start) { // skip blank lines string line(start, end); if (!ctx_->get_settings()->logfile.empty()) { FILE* f = fopen(ctx_->get_settings()->logfile.c_str(), "a"); if (f) { fprintf(f, " %s\n", line.c_str()); fclose(f); } } if (ctx_->get_verbosity() >= 0) show_message(kQuoted, "> " + line); Status r = execute_line(line); if (r != kStatusOk) break; } if (*end == '\0') break; start = end + 1; } } void UserInterface::draw_plot(RepaintMode mode, const char* filename) { if (draw_plot_callback_) (*draw_plot_callback_)(mode, filename); if (filename == NULL) dirty_plot_ = false; } UiApi::Status UserInterface::execute_line_via_callback(const string& s) { return exec_command_callback_ ? (*exec_command_callback_)(s) : execute_line(s); } void UserInterface::wait(float seconds) const { #ifdef _WIN32 Sleep(iround(seconds*1e3)); #else //!_WIN32 seconds = fabs(seconds); timespec ts; ts.tv_sec = static_cast(seconds); ts.tv_nsec = static_cast((seconds - ts.tv_sec) * 1e9); nanosleep(&ts, NULL); #endif //_WIN32 } } // namespace fityk fityk-1.3.1/fityk/ui.h000066400000000000000000000055671302634723100145740ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_UI_H_ #define FITYK_UI_H_ #include "common.h" #include "ui_api.h" namespace fityk { class BasicContext; class CommandExecutor; /// commands, messages and plot refreshing /// it has callbacks that can be set by user interface class FITYK_API UserInterface : public UiApi { public: static const int max_cmd = 4096; struct FITYK_API Cmd { std::string cmd; UiApi::Status status; Cmd(const std::string& c, UiApi::Status s) : cmd(c), status(s) {} std::string str() const; }; UserInterface(BasicContext* ctx, CommandExecutor* ce); /// Redraw the plot. void draw_plot(RepaintMode mode, const char* filename=NULL); void mark_plot_dirty() { dirty_plot_ = true; } /// Calls the show_message(), logs the message to file if logging is on, /// handles option on_error=exit. void output_message(Style style, const std::string& s) const; /// Send warning void warn(std::string const &s) const { output_message(kWarning, s); } /// Send implicitely requested message void mesg(std::string const &s) const { output_message(kNormal, s); } /// Excute commands from file, i.e. run a script (.fit). void exec_fityk_script(const std::string& filename); void exec_stream(FILE *fp); void exec_string_as_script(const char* s); // logs the command and calls execute_line_via_callback() UiApi::Status exec_and_log(const std::string& c); // Calls raw_execute_line(), catches exceptions and returns status code. UiApi::Status execute_line(const std::string& str); void hint_ui(const std::string& key, const std::string& value) { if (hint_ui_callback_) (*hint_ui_callback_)(key, value); } std::string get_input_from_user(const std::string& prompt) { return user_input_callback_ ? (*user_input_callback_)(prompt) : std::string(); } std::string ui_state_as_script() const { return ui_state_callback_ ? (*ui_state_callback_)() : std::string(); } /// wait doing nothing for given number of seconds (can be fractional). void wait(float seconds) const; const std::vector& cmds() const { return cmds_; } std::string get_history_summary() const; private: BasicContext* ctx_; CommandExecutor* cmd_executor_; int cmd_count_; //!=cmds_.size() if max_cmd was exceeded std::vector cmds_; bool dirty_plot_; /// show message to user void show_message(Style style, const std::string& s) const { if (show_message_callback_) (*show_message_callback_)(style, s); } // It can finish the program (eg. if s=="quit"). UiApi::Status execute_line_via_callback(const std::string& s); DISALLOW_COPY_AND_ASSIGN(UserInterface); }; } // namespace fityk #endif fityk-1.3.1/fityk/ui_api.cpp000066400000000000000000000171311302634723100157460ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2012 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "ui_api.h" #include #include #include // for isspace #include "cparser.h" #include "mgr.h" #include "logic.h" #include "func.h" using namespace std; namespace { using namespace fityk; // assumes that array ends with NULL. void add_c_string_array(const char **array, const char* text, vector &entries) { for (const char** p = array; *p != NULL; ++p) if (strncmp(*p, text, strlen(text)) == 0) entries.push_back(*p); } void type_completions(Full *F, const char *text, vector &entries) { v_foreach (Tplate::Ptr, i, F->get_tpm()->tpvec()) if (strncmp((*i)->name.c_str(), text, strlen(text)) == 0) entries.push_back((*i)->name); } bool starts_with_command(const char *cmd, int n, const char* head, const char* tail) { int hlen = strlen(head); if (strncmp(head, cmd, hlen) != 0) return false; for (int i = 0; hlen + i < n; ++i) if (isspace(cmd[hlen+i])) return i == 0 || strncmp(cmd+hlen, tail, i) == 0; return false; } } // namespace namespace fityk { const char* config_dirname() { return ".fityk"; } const char* startup_commands_filename() { return "init"; } volatile std::sig_atomic_t user_interrupt = 0; static void simple_show_message(UiApi::Style style, const string& s) { if (style == UiApi::kWarning) printf("\a"); printf("%s\n", s.c_str()); fflush(stdout); } static string simple_user_input(const string& prompt) { printf("%s ", prompt.c_str()); fflush(stdout); char s[100]; char *ret = fgets(s, 100, stdin); return ret ? strip_string(s) : ""; } UiApi::UiApi() : show_message_callback_(simple_show_message), draw_plot_callback_(NULL), exec_command_callback_(NULL), hint_ui_callback_(NULL), user_input_callback_(simple_user_input), ui_state_callback_(NULL) { } UiApi::t_draw_plot_callback* UiApi::connect_draw_plot(UiApi::t_draw_plot_callback *func) { UiApi::t_draw_plot_callback *old = draw_plot_callback_; draw_plot_callback_ = func; return old; } UiApi::t_show_message_callback* UiApi::connect_show_message(UiApi::t_show_message_callback *func) { UiApi::t_show_message_callback *old = show_message_callback_; show_message_callback_ = func; return old; } UiApi::t_exec_command_callback* UiApi::connect_exec_command(UiApi::t_exec_command_callback *func) { UiApi::t_exec_command_callback *old = exec_command_callback_; exec_command_callback_ = func; return old; } UiApi::t_hint_ui_callback* UiApi::connect_hint_ui(UiApi::t_hint_ui_callback *func) { UiApi::t_hint_ui_callback *old = hint_ui_callback_; hint_ui_callback_ = func; return old; } UiApi::t_user_input_callback* UiApi::connect_user_input(UiApi::t_user_input_callback *func) { UiApi::t_user_input_callback *old = user_input_callback_; user_input_callback_ = func; return old; } UiApi::t_ui_state_callback* UiApi::connect_ui_state(UiApi::t_ui_state_callback *func) { UiApi::t_ui_state_callback *old = ui_state_callback_; ui_state_callback_ = func; return old; } vector complete_fityk_line(Fityk *F, const char* line_buffer, int start, int end, const char *text) { vector entries; Full *priv = F->priv(); //find start of the command, and skip blanks int cmd_start = start; while (cmd_start > 0 && line_buffer[cmd_start-1] != ';') --cmd_start; while (isspace(line_buffer[cmd_start])) ++cmd_start; // skip "@m @n:" if (line_buffer[cmd_start] == '@') { int t = cmd_start + 1; while (t < start && line_buffer[t] != '.') { if (line_buffer[t] == ':') { cmd_start = t+1; while (isspace(line_buffer[cmd_start])) ++cmd_start; break; } ++t; } } //command if (cmd_start == start) { add_c_string_array(command_list, text, entries); return entries; } const char *ptr = line_buffer+cmd_start; const char* prev_nonblank = line_buffer + start - 1; while (prev_nonblank > line_buffer && isspace(*prev_nonblank)) --prev_nonblank; if (*prev_nonblank == '>' || *prev_nonblank == '<') // special value that requests rl_filename_completion_function entries.push_back(""); //check if it is after set command or after with else if (starts_with_command(ptr, start - cmd_start, "s","et") || starts_with_command(ptr, start - cmd_start, "w","ith")) { while (*ptr && !isspace(*ptr)) ++ptr; ++ptr; const char *has_eq = NULL; for (const char *i = ptr; i <= line_buffer+end; ++i) { if (*i == '=') has_eq = i; else if (*i == ',') { ptr = i+1; has_eq = NULL; } } if (!has_eq) entries = priv->settings_mgr()->get_key_list(text); else { string key = strip_string(string(ptr, has_eq)); try { const char** allowed_values = priv->settings_mgr()->get_allowed_values(key); if (allowed_values != NULL) add_c_string_array(allowed_values, text, entries); } catch (ExecuteError&) {} // unknown option } } // FunctionType completion else if (starts_with_command(ptr, start - cmd_start, "g","uess")) { type_completions(priv, text, entries); } // FunctionType or "guess" completion else if (cmd_start <= start-3 && line_buffer[cmd_start] == '%' && strchr(line_buffer+cmd_start, '=') && !strchr(line_buffer+cmd_start, '(')) { type_completions(priv, text, entries); if (strncmp("guess", text, strlen(text)) == 0) entries.push_back("guess"); } // %function completion else if (text[0] == '%') { v_foreach (Function*, i, priv->mgr.functions()) if (!strncmp((*i)->name.c_str(), text+1, strlen(text+1))) entries.push_back("%" + (*i)->name); } // $variable completion else if (start > 0 && line_buffer[start-1] == '$') { v_foreach (Variable*, i, priv->mgr.variables()) if (!strncmp ((*i)->name.c_str(), text, strlen(text))) entries.push_back((*i)->name); } // info completion else if (starts_with_command(ptr, start - cmd_start, "i","nfo")) { // info set int arg_start = cmd_start; while (!isspace(line_buffer[arg_start])) ++arg_start; while (isspace(line_buffer[arg_start])) ++arg_start; const char* arg_ptr = line_buffer + arg_start; if (starts_with_command(arg_ptr, start - arg_start, "set","")) entries = priv->settings_mgr()->get_key_list(text); else { type_completions(priv, text, entries); add_c_string_array(info_args, text, entries); } } // debug completion else if (starts_with_command(ptr, start - cmd_start, "debug","")) { add_c_string_array(debug_args, text, entries); } // filename completion after exec else if (starts_with_command(ptr, start - cmd_start, "e","xecute")) // special value that requests rl_filename_completion_function entries.push_back(""); return entries; // true = done } } // namespace fityk fityk-1.3.1/fityk/ui_api.h000066400000000000000000000066561302634723100154250ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2012 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ #ifndef FITYK_UI_API_H_ #define FITYK_UI_API_H_ #include // sig_atomic_t #include #include #include "fityk.h" // FITYK_API namespace fityk { // this is API needed mostly to implement own user interface to libfityk. class FITYK_API UiApi { public: /// 4 styles are supported by output_message() enum Style { kNormal, kWarning, kQuoted, kInput }; /// modes supported by draw_plot() enum RepaintMode { kRepaint, // repaint can be delayed kRepaintImmediately // repaint immediately }; /// command status enum Status { kStatusOk, kStatusExecuteError, kStatusSyntaxError }; UiApi(); virtual ~UiApi() {} /// in addition to executing command, log it if logging option is set virtual Status exec_and_log(const std::string& c) = 0; /// Excute commands from file, i.e. run a script (.fit). virtual void exec_fityk_script(const std::string& filename) = 0; // Callbacks. connect_*() returns old callback. // Callback for plotting. typedef void t_draw_plot_callback(RepaintMode mode, const char* filename); t_draw_plot_callback* connect_draw_plot(t_draw_plot_callback *func); // Callback for text output. Initially, a callback suitable for CLI // is connected (messages go to stdout). typedef void t_show_message_callback(Style style, const std::string& s); t_show_message_callback* connect_show_message(t_show_message_callback *func); // If set, this callback is used instead of execute_line(s) function. typedef Status t_exec_command_callback(const std::string &s); t_exec_command_callback* connect_exec_command(t_exec_command_callback *func); // This callback is called with arg=0 before time-consuming computation, // after the computation with arg=1, // and periodically during computations with arg=-1. typedef void t_hint_ui_callback(const std::string& key, const std::string& value); t_hint_ui_callback* connect_hint_ui(t_hint_ui_callback *func); // Callback for querying user. typedef std::string t_user_input_callback(const std::string& prompt); t_user_input_callback* connect_user_input(t_user_input_callback *func); // Callback for ui state typedef std::string t_ui_state_callback(); t_ui_state_callback* connect_ui_state(t_ui_state_callback *func); protected: t_show_message_callback *show_message_callback_; t_draw_plot_callback *draw_plot_callback_; t_exec_command_callback *exec_command_callback_; t_hint_ui_callback *hint_ui_callback_; t_user_input_callback *user_input_callback_; t_ui_state_callback *ui_state_callback_; }; /// Helper for readline tab-completion. /// Returns completions of the word `text' in the context of line_buffer, /// or a single empty string if filename completion is to be used instead. FITYK_API std::vector complete_fityk_line(Fityk *F, const char* line_buffer, int start, int end, const char *text); FITYK_API const char* startup_commands_filename(); // "init" FITYK_API const char* config_dirname(); // ".fityk" /// flag that is set to interrupt fitting (it is checked after each iteration) extern volatile FITYK_API std::sig_atomic_t user_interrupt; } // namespace fityk #endif // FITYK_UI_API_H_ fityk-1.3.1/fityk/var.cpp000066400000000000000000000105311302634723100152650ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "var.h" #include "common.h" #include "ast.h" #include #include using namespace std; namespace fityk { /// checks if *this depends (directly or indirectly) on variable with index idx bool IndexedVars::depends_on(int idx, vector const &variables) const { v_foreach (int, i, indices_) if (*i == idx || variables[*i]->used_vars().depends_on(idx, variables)) return true; return false; } void IndexedVars::update_indices(vector const &variables) { const int n = names_.size(); indices_.resize(n); for (int v = 0; v < n; ++v) { bool found = false; for (int i = 0; i < size(variables); ++i) { if (names_[v] == variables[i]->name) { indices_[v] = i; found = true; break; } } if (!found) throw ExecuteError("Undefined variable: $" + names_[v]); } } int IndexedVars::get_max_idx() const { if (indices_.empty()) return -1; else return *max_element(indices_.begin(), indices_.end()); } //////////////////////////////////////////////////////////////////////////// // ctor for simple variables and mirror variables Variable::Variable(string const &name_, int gpos) : Var(name_, gpos), original_(NULL) { assert(!name_.empty()); if (gpos_ != -2) { ParMult pm; pm.p = gpos_; pm.mult = 1; recursive_derivatives_.push_back(pm); } } // ctor for compound variables Variable::Variable(string const &name_, vector const &vars, vector const &op_trees) : Var(name_, -1), used_vars_(vars), derivatives_(vars.size()), op_trees_(op_trees), original_(NULL) { assert(!name_.empty()); } Variable::~Variable() { purge_all_elements(op_trees_); } void Variable::set_var_idx(vector const& variables) { used_vars_.update_indices(variables); if (gpos_ == -1) { /// (re-)create bytecode, required after update_indices() assert(used_vars_.indices().size() + 1 == op_trees_.size()); vm_.clear_data(); int n = op_trees_.size() - 1; for (int i = 0; i < n; ++i) { add_bytecode_from_tree(op_trees_[i], used_vars_.indices(), vm_); vm_.append_code(OP_PUT_DERIV); vm_.append_code(i); } add_bytecode_from_tree(op_trees_.back(), used_vars_.indices(), vm_); //printf("Variable::set_var_idx: %s\n", vm2str(vm_).c_str()); } } string Variable::get_formula(vector const ¶meters) const { assert(gpos_ >= -1); vector vn; v_foreach (string, i, used_vars_.names()) vn.push_back("$" + *i); const char* num_format = "%.12g"; OpTreeFormat fmt = { num_format, &vn }; return gpos_ == -1 ? get_op_trees().back()->str(fmt) : "~" + eS(parameters[gpos_]); } void Variable::recalculate(vector const &variables, vector const ¶meters) { if (gpos_ >= 0) { assert (gpos_ < (int) parameters.size()); value_ = parameters[gpos_]; assert(derivatives_.empty()); } else if (gpos_ == -1) { value_ = run_code_for_variable(vm_, variables, derivatives_); recursive_derivatives_.clear(); for (int i = 0; i < size(derivatives_); ++i) { Variable *v = variables[used_vars_.get_idx(i)]; v_foreach (ParMult, j, v->recursive_derivatives()) { recursive_derivatives_.push_back(*j); recursive_derivatives_.back().mult *= derivatives_[i]; } } } else if (gpos_ == -2) { if (original_) { value_ = original_->value_; recursive_derivatives_ = original_->recursive_derivatives_; } } else assert(0); } void Variable::erased_parameter(int k) { if (gpos_ != -1 && gpos_ > k) --gpos_; for (vector::iterator i = recursive_derivatives_.begin(); i != recursive_derivatives_.end(); ++i) if (i->p > k) -- i->p; } bool Variable::is_constant() const { return gpos_ == -1 && op_trees_.back()->op == 0; } } // namespace fityk fityk-1.3.1/fityk/var.h000066400000000000000000000072331302634723100147370ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_VAR_H_ #define FITYK_VAR_H_ #include #include "common.h" #include "vm.h" namespace fityk { struct OpTree; class Variable; class FITYK_API IndexedVars { public: IndexedVars() {} IndexedVars(const std::vector &vars) : names_(vars) {} const std::vector& names() const { return names_; } const std::vector& indices() const { return indices_; } int get_count() const { return names_.size(); } const std::string& get_name(int n) const { assert(is_index(n, names_)); return names_[n]; } int get_idx(int n) const { assert(is_index(n, indices_)); return indices_[n]; } int get_max_idx() const; bool has_idx(int idx) const { return contains_element(indices_, idx); } bool depends_on(int idx, const std::vector &variables) const; std::string get_debug_idx_info() const; void set_name(int n, const std::string &new_p) { assert(is_index(n, names_)); names_[n] = new_p; } void update_indices(const std::vector& variables); private: // variable names std::vector names_; // corresponding indices; set after initialization (in outer class) // and modified after variable removal or change std::vector indices_; DISALLOW_COPY_AND_ASSIGN(IndexedVars); }; /// the variable can be one of: /// * simple-variable; gpos_ is its index in the global array of parameters, /// * compound-variable; gpos_ == -1, /// * mirror-variable; gpos_ == -2 (such variable is copied, not recalculated) /// /// The value and derivatives of compound-variable are calculated in this way: /// - string is parsed by eparser to VMData representation, /// and then it is transformed to AST (struct OpTree), calculating derivates /// at the same time (calculate_deriv()). /// - set_var_idx() finds positions of variables in variables vector /// (references to variables are kept using names) and creates bytecode /// (VMData, again) that will be used to calculate value and derivatives. /// - recalculate() calculates (using run_code_for_variable()) value /// and derivatives for current parameter value class FITYK_API Variable : public Var { public: struct ParMult { int p; realt mult; }; Variable(const std::string &name_, int gpos); Variable(const std::string &name_, const std::vector &vars, const std::vector &op_trees); ~Variable(); bool is_constant() const; std::string get_formula(const std::vector ¶meters) const; void recalculate(const std::vector &variables, const std::vector ¶meters); void erased_parameter(int k); bool is_visible() const { return true; } //for future use void set_var_idx(const std::vector &variables); const std::vector& recursive_derivatives() const { return recursive_derivatives_; } std::vector const& get_op_trees() const { return op_trees_; } void set_original(const Variable* orig) { assert(gpos_ == -2); original_ = orig; } realt get_derivative(int n) const { return derivatives_[n]; } const IndexedVars& used_vars() const { return used_vars_; } private: IndexedVars used_vars_; std::vector derivatives_; std::vector recursive_derivatives_; std::vector op_trees_; VMData vm_; Variable const* original_; }; } // namespace fityk #endif // FITYK_VAR_H_ fityk-1.3.1/fityk/view.cpp000066400000000000000000000126071302634723100154550ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #define BUILDING_LIBFITYK #include "view.h" #include "common.h" #include "data.h" #include "model.h" #include "logic.h" using namespace std; namespace fityk { const double View::relative_x_margin = 1./20.; const double View::relative_y_margin = 1./20.; string View::str() const { char buffer[128]; sprintf(buffer, "[%.12g:%.12g] [%.12g:%.12g]", hor.lo, hor.hi, ver.lo, ver.hi); return string(buffer); } void View::change_view(const RealRange& hor_r, const RealRange& ver_r, const vector& datasets) { assert(!datasets.empty()); hor = hor_r; ver = ver_r; // For the first dataset in `dataset' (@n, it doesn't contain @*) both // data points and models are considered. // For the next ones only data points. vector datas(datasets.size()); for (size_t i = 0; i != datasets.size(); ++i) datas[i] = dk_->data(datasets[i]); vector models(1, datas[0]->model()); if (hor.lo_inf() || hor.hi_inf()) { double x_min=0, x_max=0; get_x_range(datas, x_min, x_max); if (x_min == x_max) { x_min -= 0.1; x_max += 0.1; } if (log_x_) { x_min = max(epsilon, x_min); // 'max' is intentional x_max = max(epsilon, x_max); double margin = log(x_max / x_min) * relative_x_margin; if (hor.lo_inf()) hor.lo = exp(log(x_min) - margin); if (hor.hi_inf()) hor.hi = exp(log(x_max) + margin); } else { double margin = (x_max - x_min) * relative_x_margin; if (hor.lo_inf()) hor.lo = x_min - margin; if (hor.hi_inf()) hor.hi = x_max + margin; } } if (ver.lo_inf() || ver.hi_inf()) { double y_min=0, y_max=0; get_y_range(datas, models, y_min, y_max); if (y_min == y_max) { y_min -= 0.1; y_max += 0.1; } if (log_y_) { y_min = max(epsilon, y_min); // 'max' is intentional y_max = max(epsilon, y_max); double margin = log(y_max / y_min) * relative_y_margin; if (ver.lo_inf()) ver.lo = exp(log(y_min) - margin); if (ver.hi_inf()) ver.hi = exp(log(y_max) + margin); } else { double margin = (y_max - y_min) * relative_y_margin; if (ver.lo_inf()) ver.lo = y_min - margin; if (ver.hi_inf()) ver.hi = y_max + margin; } } } void View::get_x_range(vector datas, double &x_min, double &x_max) { if (datas.empty()) throw ExecuteError("Can't find x-y axes ranges for plot"); x_min = datas.front()->get_x_min(); x_max = datas.front()->get_x_max(); for (vector::const_iterator i = datas.begin() + 1; i != datas.end(); ++i) { x_min = min(x_min, (*i)->get_x_min()); x_max = max(x_max, (*i)->get_x_max()); } } void View::get_y_range(vector datas, vector models, double &y_min, double &y_max) { if (datas.empty()) throw ExecuteError("Can't find x-y axes ranges for plot"); bool min_max_set = false; v_foreach (Data const*, i, datas) { vector::const_iterator f = (*i)->get_point_at(hor.lo); vector::const_iterator l = (*i)->get_point_at(hor.hi); //first we are searching for minimal and max. y in active points for (vector::const_iterator j = f; j < l; ++j) { if (j->is_active && is_finite(j->y)) { if (min_max_set) { if (j->y > y_max) y_max = j->y; if (j->y < y_min) y_min = j->y; } else { y_min = y_max= j->y; min_max_set = true; } } } } if (!min_max_set || y_min == y_max) { //none or 1 active point, so now we // search for min. and max. y in all points v_foreach (Data const*, i, datas) { vector::const_iterator f = (*i)->get_point_at(hor.lo); vector::const_iterator l = (*i)->get_point_at(hor.hi); for (vector::const_iterator j = f; j < l; ++j) { if (!is_finite(j->y)) continue; // min_max_set = true; if (j->y > y_max) y_max = j->y; if (j->y < y_min) y_min = j->y; } } } v_foreach (Model const*, i, models) { Model const* model = *i; if (model->get_ff().empty()) continue; // estimated model maximum double model_y_max = model->approx_max(hor.lo, hor.hi); if (model_y_max > y_max) y_max = model_y_max; if (model_y_max < y_min) y_min = model_y_max; } // include or not include zero if (!log_y_ && y0_factor_ > 0) { double dy = y_max - y_min; if (y_min > 0 && y0_factor_ * dy > y_max) y_min = 0; else if (y_max < 0 && y0_factor_ * dy > fabs(y_min)) y_max = 0; } } } // namespace fityk fityk-1.3.1/fityk/view.h000066400000000000000000000037351302634723100151240ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_VIEW_H_ #define FITYK_VIEW_H_ #include #include #include "fityk.h"// for RealRange, FITYK_API namespace fityk { class Data; class Model; class DataKeeper; struct FITYK_API Rect { RealRange hor, ver; Rect(double l, double r, double b, double t) { hor.lo = l; hor.hi = r; ver.lo = b; ver.hi = t; } double left() const { return hor.lo; } double right() const { return hor.hi; } double bottom() const { return ver.lo; } double top() const { return ver.hi; } double width() const { return hor.hi - hor.lo; } double height() const { return ver.hi - ver.lo; } }; /// manages view, i.e. x and y range visible currently to the user /// user can set view in `plot' command, using string like "[20:][-100:1000]" /// If the visible range is to be fitted to data/model, given datasets are used. class FITYK_API View: public Rect { public: static const double relative_x_margin; static const double relative_y_margin; View(const DataKeeper* dk) : Rect(0, 180., -50, 1e3), dk_(dk), log_x_(false), log_y_(false), y0_factor_(10.) {} std::string str() const; /// fit specified edges to the data range void change_view(const RealRange& hor_r, const RealRange& ver_r, const std::vector& datasets); void set_log_scale(bool log_x, bool log_y) { log_x_=log_x; log_y_=log_y; } double y0_factor() const { return y0_factor_; } void set_y0_factor(double f) { y0_factor_ = f; } private: const DataKeeper* dk_; bool log_x_, log_y_; double y0_factor_; void get_x_range(std::vector datas, double &x_min, double &x_max); void get_y_range(std::vector datas, std::vector models, double &y_min, double &y_max); }; } // namespace fityk #endif fityk-1.3.1/fityk/vm.cpp000066400000000000000000000572511302634723100151310ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// virtual machine - calculates expressions using by executing bytecode #define BUILDING_LIBFITYK #include "vm.h" #include #include #include "common.h" #include "voigt.h" #include "numfuncs.h" #include "logic.h" #include "func.h" // %f(...) #include "model.h" // F(...) using namespace std; namespace { using namespace fityk; vector::const_iterator skip_code(vector::const_iterator i, int start_op, int finish_op) { //TODO: it doesn't work correctly now, because both op's and indices // are positive and mixed int counter = 1; while (counter) { ++i; if (*i == finish_op) counter--; else if (*i == start_op) counter++; else if (VMData::has_idx(*i)) ++i; } return i; } template realt get_var_with_idx(realt idx, vector const& points, T Point::*t) { if (points.empty()) return 0.; else if (idx <= 0) return points[0].*t; else if (idx >= points.size() - 1) return points.back().*t; else if (is_eq(idx, iround(idx))) return points[iround(idx)].*t; else { int flo = int(floor(idx)); realt fra = idx - flo; return (1-fra) * realt(points[flo].*t) + fra * realt(points[flo+1].*t); } } /// returns floating-point "index" of x in sorted vec of points realt find_idx_in_sorted(vector const& pp, realt x) { if (pp.empty()) return 0; else if (x <= pp.front().x) return 0; else if (x >= pp.back().x) return pp.size() - 1; vector::const_iterator i = lower_bound(pp.begin(), pp.end(), Point(x, 0)); assert (i > pp.begin() && i < pp.end()); if (is_eq(x, i->x)) return i - pp.begin(); else return i - pp.begin() - (i->x - x) / (i->x - (i-1)->x); } } // anonymous namespace namespace fityk { /// debuging utility #define OP_(x) \ case OP_##x: return #x; string op2str(int op) { switch (static_cast(op)) { OP_(NUMBER) OP_(SYMBOL) OP_(X) OP_(PUT_DERIV) OP_(NEG) OP_(EXP) OP_(ERFC) OP_(ERF) OP_(SIN) OP_(COS) OP_(TAN) OP_(SINH) OP_(COSH) OP_(TANH) OP_(ABS) OP_(ROUND) OP_(ATAN) OP_(ASIN) OP_(ACOS) OP_(LOG10) OP_(LN) OP_(SQRT) OP_(POW) OP_(GAMMA) OP_(LGAMMA) OP_(DIGAMMA) OP_(VOIGT) OP_(DVOIGT_DX) OP_(DVOIGT_DY) OP_(XINDEX) OP_(ADD) OP_(SUB) OP_(MUL) OP_(DIV) OP_(MOD) OP_(MIN2) OP_(MAX2) OP_(RANDNORM) OP_(RANDU) OP_(PX) OP_(PY) OP_(PS) OP_(PA) OP_(Px) OP_(Py) OP_(Ps) OP_(Pa) OP_(Pn) OP_(PM) OP_(OR) OP_(AFTER_OR) OP_(AND) OP_(AFTER_AND) OP_(NOT) OP_(TERNARY) OP_(TERNARY_MID) OP_(AFTER_TERNARY) OP_(GT) OP_(GE) OP_(LT) OP_(LE) OP_(EQ) OP_(NEQ) OP_(ASSIGN_X) OP_(ASSIGN_Y) OP_(ASSIGN_S) OP_(ASSIGN_A) OP_(FUNC) OP_(SUM_F) OP_(SUM_Z) OP_(NUMAREA) OP_(FINDX) OP_(FIND_EXTR) OP_(TILDE) OP_(DATASET) OP_(DT_SUM_SAME_X) OP_(DT_AVG_SAME_X) OP_(DT_SHIRLEY_BG) OP_(OPEN_ROUND) OP_(OPEN_SQUARE) } return S(op); // unreachable (if all OPs are listed above) } #undef OP_ string vm2str(vector const& code, vector const& data) { string s; for (vector::const_iterator i = code.begin(); i < code.end(); ++i) { s += op2str(*i); if (*i == OP_NUMBER) { ++i; assert (*i >= 0 && *i < size(data)); s += "[" + S(*i) + "](" + S(data[*i]) + ")"; } else if (VMData::has_idx(*i)) { ++i; s += "[" + S(*i) + "]"; } s += " "; } return s; } void VMData::append_number(realt d) { append_code(OP_NUMBER); int number_pos = numbers_.size(); append_code(number_pos); numbers_.push_back(d); } void VMData::replace_symbols(const vector& vv) { for (vector::iterator op = code_.begin(); op < code_.end(); ++op) { if (*op == OP_SYMBOL) { *op = OP_NUMBER; ++op; realt value = vv[*op]; vector::iterator x = find(numbers_.begin(), numbers_.end(), value); if (x != numbers_.end()) *op = x - numbers_.begin(); else { *op = numbers_.size(); numbers_.push_back(value); } } else if (has_idx(*op)) ++op; } } /// switches between non-negative and negative indices (a -> -1-a), /// the point of having negative indices is to avoid conflicts with opcodes. /// The same transformation is used in OpTree. void VMData::flip_indices() { for (vector::iterator i = code_.begin(); i < code_.end(); ++i) if (has_idx(*i)) { ++i; *i = -1 - *i; } } bool VMData::has_op(int op) const { for (vector::const_iterator i = code_.begin(); i < code_.end(); ++i) { if (*i == op) return true; if (has_idx(*i)) ++i; } return false; } inline realt as_bool(realt d) { return fabs(d) < 0.5 ? 0 : 1; } #define STACK_OFFSET_CHANGE(ch) stackPtr+=(ch) inline void run_const_op(const Full* F, const std::vector& numbers, vector::const_iterator& i, realt*& stackPtr, const int n, const vector& old_points, const vector& new_points) { switch (*i) { //unary-operators case OP_NEG: *stackPtr = - *stackPtr; break; case OP_SQRT: *stackPtr = sqrt(*stackPtr); break; case OP_GAMMA: *stackPtr = boost::math::tgamma(*stackPtr); break; case OP_LGAMMA: *stackPtr = boost::math::lgamma(*stackPtr); break; case OP_DIGAMMA: *stackPtr = boost::math::digamma(*stackPtr); break; case OP_EXP: *stackPtr = exp(*stackPtr); break; case OP_ERFC: *stackPtr = erfc(*stackPtr); break; case OP_ERF: *stackPtr = erf(*stackPtr); break; case OP_LOG10: *stackPtr = log10(*stackPtr); break; case OP_LN: *stackPtr = log(*stackPtr); break; case OP_SIN: *stackPtr = sin(*stackPtr); break; case OP_COS: *stackPtr = cos(*stackPtr); break; case OP_TAN: *stackPtr = tan(*stackPtr); break; case OP_SINH: *stackPtr = sinh(*stackPtr); break; case OP_COSH: *stackPtr = cosh(*stackPtr); break; case OP_TANH: *stackPtr = tanh(*stackPtr); break; case OP_ATAN: *stackPtr = atan(*stackPtr); break; case OP_ASIN: *stackPtr = asin(*stackPtr); break; case OP_ACOS: *stackPtr = acos(*stackPtr); break; case OP_ABS: *stackPtr = fabs(*stackPtr); break; case OP_ROUND: *stackPtr = floor(*stackPtr + 0.5); break; case OP_XINDEX: *stackPtr = find_idx_in_sorted(old_points, *stackPtr); break; #ifndef STANDALONE_DATATRANS case OP_FUNC: i++; *stackPtr = F->mgr.get_function(*i)->calculate_value(*stackPtr); break; case OP_SUM_F: i++; *stackPtr = F->dk.get_model(*i)->value(*stackPtr); break; case OP_SUM_Z: i++; *stackPtr = F->dk.get_model(*i)->zero_shift(*stackPtr); break; case OP_NUMAREA: i += 2; STACK_OFFSET_CHANGE(-2); if (*(i-1) == OP_FUNC) { *stackPtr = F->mgr.get_function(*i)->numarea(*stackPtr, *(stackPtr+1), iround(*(stackPtr+2))); } else if (*(i-1) == OP_SUM_F) { *stackPtr = F->dk.get_model(*i)->numarea(*stackPtr, *(stackPtr+1), iround(*(stackPtr+2))); } else // OP_SUM_Z throw ExecuteError("Z.numarea() is not implemented. " "Does anyone need it?"); break; case OP_FINDX: i += 2; STACK_OFFSET_CHANGE(-2); if (*(i-1) == OP_FUNC) { *stackPtr = find_x_with_value(F->mgr.get_function(*i), *stackPtr, *(stackPtr+1), *(stackPtr+2)); } else if (*(i-1) == OP_SUM_F) { *stackPtr = find_x_with_value(F->dk.get_model(*i), *stackPtr, *(stackPtr+1), *(stackPtr+2)); } else // OP_SUM_Z throw ExecuteError("Z.findx() is not implemented. " "Does anyone need it?"); break; case OP_FIND_EXTR: i += 2; STACK_OFFSET_CHANGE(-1); if (*(i-1) == OP_FUNC) { *stackPtr = find_extremum(F->mgr.get_function(*i), *stackPtr, *(stackPtr+1)); } else if (*(i-1) == OP_SUM_F) { *stackPtr = find_extremum(F->dk.get_model(*i), *stackPtr, *(stackPtr+1)); } else // OP_SUM_Z throw ExecuteError("Z.extremum() is not implemented. " "Does anyone need it?"); break; #endif //not STANDALONE_DATATRANS //binary-operators case OP_MIN2: STACK_OFFSET_CHANGE(-1); *stackPtr = min(*stackPtr, *(stackPtr+1)); break; case OP_MAX2: STACK_OFFSET_CHANGE(-1); *stackPtr = max(*stackPtr, *(stackPtr+1)); break; case OP_RANDU: STACK_OFFSET_CHANGE(-1); *stackPtr = rand_uniform(*stackPtr, *(stackPtr+1)); break; case OP_RANDNORM: STACK_OFFSET_CHANGE(-1); *stackPtr += rand_gauss() * *(stackPtr+1); break; case OP_ADD: STACK_OFFSET_CHANGE(-1); *stackPtr += *(stackPtr+1); break; case OP_SUB: STACK_OFFSET_CHANGE(-1); *stackPtr -= *(stackPtr+1); break; case OP_MUL: STACK_OFFSET_CHANGE(-1); *stackPtr *= *(stackPtr+1); break; case OP_DIV: STACK_OFFSET_CHANGE(-1); *stackPtr /= *(stackPtr+1); break; case OP_MOD: STACK_OFFSET_CHANGE(-1); *stackPtr -= floor(*stackPtr / *(stackPtr+1)) * *(stackPtr+1); break; case OP_POW: STACK_OFFSET_CHANGE(-1); *stackPtr = pow(*stackPtr, *(stackPtr+1)); break; case OP_VOIGT: STACK_OFFSET_CHANGE(-1); *stackPtr = humlik(*stackPtr, *(stackPtr+1)) / sqrt(M_PI); break; case OP_DVOIGT_DX: STACK_OFFSET_CHANGE(-1); *stackPtr = humdev_dkdx(*stackPtr, *(stackPtr+1)) / sqrt(M_PI); break; case OP_DVOIGT_DY: STACK_OFFSET_CHANGE(-1); *stackPtr = humdev_dkdy(*stackPtr, *(stackPtr+1)) / sqrt(M_PI); break; // comparisions case OP_LT: STACK_OFFSET_CHANGE(-1); *stackPtr = is_lt(*stackPtr, *(stackPtr+1)); break; case OP_GT: STACK_OFFSET_CHANGE(-1); *stackPtr = is_gt(*stackPtr, *(stackPtr+1)); break; case OP_LE: STACK_OFFSET_CHANGE(-1); *stackPtr = is_le(*stackPtr, *(stackPtr+1)); break; case OP_GE: STACK_OFFSET_CHANGE(-1); *stackPtr = is_ge(*stackPtr, *(stackPtr+1)); break; case OP_EQ: STACK_OFFSET_CHANGE(-1); *stackPtr = is_eq(*stackPtr, *(stackPtr+1)); break; case OP_NEQ: STACK_OFFSET_CHANGE(-1); *stackPtr = is_neq(*stackPtr, *(stackPtr+1)); break; // putting-number-to-stack-operators case OP_NUMBER: STACK_OFFSET_CHANGE(+1); i++; *stackPtr = numbers[*i]; break; case OP_Pn: STACK_OFFSET_CHANGE(+1); *stackPtr = static_cast(n); break; case OP_PM: STACK_OFFSET_CHANGE(+1); *stackPtr = static_cast(old_points.size()); break; case OP_Px: *stackPtr = get_var_with_idx(*stackPtr, old_points, &Point::x); break; case OP_Py: *stackPtr = get_var_with_idx(*stackPtr, old_points, &Point::y); break; case OP_Ps: *stackPtr = get_var_with_idx(*stackPtr, old_points, &Point::sigma); break; case OP_Pa: *stackPtr = as_bool(get_var_with_idx(*stackPtr, old_points, &Point::is_active)); break; case OP_PX: *stackPtr = get_var_with_idx(*stackPtr, new_points, &Point::x); break; case OP_PY: *stackPtr = get_var_with_idx(*stackPtr, new_points, &Point::y); break; case OP_PS: *stackPtr = get_var_with_idx(*stackPtr, new_points, &Point::sigma); break; case OP_PA: *stackPtr = as_bool(get_var_with_idx(*stackPtr, new_points, &Point::is_active)); break; // logical; can skip part of VM code ! case OP_NOT: *stackPtr = is_eq(*stackPtr, 0.); break; case OP_AND: if (is_neq(*stackPtr, 0)) //return second stackPtr--; else // return first i = skip_code(i, OP_AND, OP_AFTER_AND); break; case OP_OR: if (is_neq(*stackPtr, 0)) //return first i = skip_code(i, OP_OR, OP_AFTER_OR); else // return second stackPtr--; break; case OP_TERNARY: if (! *stackPtr) i = skip_code(i, OP_TERNARY, OP_TERNARY_MID); stackPtr--; break; case OP_TERNARY_MID: //if we are here, condition was true. Skip. i = skip_code(i, OP_TERNARY_MID, OP_AFTER_TERNARY); break; case OP_AFTER_AND: //do nothing case OP_AFTER_OR: case OP_AFTER_TERNARY: case OP_TILDE: break; case OP_DATASET: throw ExecuteError("@n can not be used in this context"); //break; // unreachable default: //cerr << "Unknown operator in VM code: " << *i << endl; assert(0); } } inline void run_mutab_op(const Full* F, const std::vector& numbers, vector::const_iterator& i, realt*& stackPtr, const int n, const vector& old_points, vector& new_points) { //cerr << "op " << dt_op(*i) << endl; switch (*i) { //assignment-operators case OP_ASSIGN_X: new_points[n].x = *stackPtr; STACK_OFFSET_CHANGE(-1); break; case OP_ASSIGN_Y: new_points[n].y = *stackPtr; STACK_OFFSET_CHANGE(-1); break; case OP_ASSIGN_S: new_points[n].sigma = *stackPtr; STACK_OFFSET_CHANGE(-1); break; case OP_ASSIGN_A: new_points[n].is_active = is_neq(*stackPtr, 0.); STACK_OFFSET_CHANGE(-1); break; default: run_const_op(F, numbers, i, stackPtr, n, old_points, new_points); } } inline void run_func_op(const vector& numbers, vector::const_iterator &i, realt*& stackPtr) { switch (*i) { //unary operators case OP_NEG: *stackPtr = - *stackPtr; break; case OP_SQRT: *stackPtr = sqrt(*stackPtr); break; case OP_EXP: *stackPtr = exp(*stackPtr); break; case OP_ERFC: *stackPtr = erfc(*stackPtr); break; case OP_ERF: *stackPtr = erf(*stackPtr); break; case OP_LOG10: *stackPtr = log10(*stackPtr); break; case OP_LN: *stackPtr = log(*stackPtr); break; case OP_SINH: *stackPtr = sinh(*stackPtr); break; case OP_COSH: *stackPtr = cosh(*stackPtr); break; case OP_TANH: *stackPtr = tanh(*stackPtr); break; case OP_SIN: *stackPtr = sin(*stackPtr); break; case OP_COS: *stackPtr = cos(*stackPtr); break; case OP_TAN: *stackPtr = tan(*stackPtr); break; case OP_ATAN: *stackPtr = atan(*stackPtr); break; case OP_ASIN: *stackPtr = asin(*stackPtr); break; case OP_ACOS: *stackPtr = acos(*stackPtr); break; case OP_LGAMMA: *stackPtr = boost::math::lgamma(*stackPtr); break; case OP_DIGAMMA: *stackPtr = boost::math::digamma(*stackPtr); break; case OP_ABS: *stackPtr = fabs(*stackPtr); break; //binary operators case OP_ADD: STACK_OFFSET_CHANGE(-1); *stackPtr += *(stackPtr+1); break; case OP_SUB: STACK_OFFSET_CHANGE(-1); *stackPtr -= *(stackPtr+1); break; case OP_MUL: STACK_OFFSET_CHANGE(-1); *stackPtr *= *(stackPtr+1); break; case OP_DIV: STACK_OFFSET_CHANGE(-1); *stackPtr /= *(stackPtr+1); break; case OP_POW: STACK_OFFSET_CHANGE(-1); *stackPtr = pow(*stackPtr, *(stackPtr+1)); break; case OP_VOIGT: STACK_OFFSET_CHANGE(-1); *stackPtr = humlik(*stackPtr, *(stackPtr+1)) / sqrt(M_PI); break; case OP_DVOIGT_DX: STACK_OFFSET_CHANGE(-1); *stackPtr = humdev_dkdx(*stackPtr, *(stackPtr+1)) / sqrt(M_PI); break; case OP_DVOIGT_DY: STACK_OFFSET_CHANGE(-1); *stackPtr = humdev_dkdy(*stackPtr, *(stackPtr+1)) / sqrt(M_PI); break; // putting-number-to-stack-operators // stack overflow not checked case OP_NUMBER: STACK_OFFSET_CHANGE(+1); i++; // OP_NUMBER opcode is always followed by index *stackPtr = numbers[*i]; break; case OP_TILDE: // used for default values in Runner::make_func_from_template() break; default: throw ExecuteError("op " + op2str(*i) + " is not allowed for variables and functions"); } } void ExprCalculator::transform_data(vector& points) { if (points.empty()) return; realt stack[16]; realt* stackPtr = stack - 1; // will be ++'ed first vector new_points = points; // do the time-consuming overflow checking only for the first point v_foreach (int, i, vm_.code()) { run_mutab_op(F_, vm_.numbers(), i, stackPtr, 0, points, new_points); if (stackPtr - stack >= 16) throw ExecuteError("stack overflow"); } assert(stackPtr == stack - 1); // ASSIGN_ op must be at the end // the same for the rest of points, but without checks for (int n = 1; n != size(points); ++n) v_foreach (int, i, vm_.code()) run_mutab_op(F_, vm_.numbers(), i, stackPtr, n, points, new_points); points.swap(new_points); } realt ExprCalculator::calculate(int n, const vector& points) const { realt stack[16]; realt* stackPtr = stack - 1; // will be ++'ed first v_foreach (int, i, vm_.code()) { run_const_op(F_, vm_.numbers(), i, stackPtr, n, points, points); if (stackPtr - stack >= 16) throw ExecuteError("stack overflow"); } //cerr << "stackPtr: " << stackPtr - stack << endl; assert(stackPtr == stack); // no ASSIGN_ at the end return stack[0]; } realt ExprCalculator::calculate_custom(const vector& custom_val) const { realt stack[16]; realt* stackPtr = stack - 1; // will be ++'ed first const vector dummy; v_foreach (int, i, vm_.code()) { if (*i == OP_SYMBOL) { STACK_OFFSET_CHANGE(+1); ++i; if (is_index(*i, custom_val)) *stackPtr = custom_val[*i]; else throw ExecuteError("[internal] variable mismatch"); } else run_const_op(F_, vm_.numbers(), i, stackPtr, 0, dummy, dummy); if (stackPtr - stack >= 16) throw ExecuteError("stack overflow"); } assert(stackPtr == stack); // no ASSIGN_ at the end return stack[0]; } /// executes VM code, sets derivatives and returns value realt run_code_for_variable(const VMData& vm, const vector &variables, vector &derivatives) { realt stack[16]; realt* stackPtr = stack - 1; // will be ++'ed first v_foreach (int, i, vm.code()) { if (*i == OP_SYMBOL) { STACK_OFFSET_CHANGE(+1); ++i; // skip the next one *stackPtr = variables[*i]->value(); } else if (*i == OP_PUT_DERIV) { ++i; // the OP_PUT_DERIV opcode is followed by a number n, // the derivative is calculated with respect to n'th variable assert(*i < (int) derivatives.size()); derivatives[*i] = *stackPtr; STACK_OFFSET_CHANGE(-1); } else run_func_op(vm.numbers(), i, stackPtr); } assert(stackPtr == stack); return stack[0]; } realt run_code_for_custom_func(const VMData& vm, realt x, vector &derivatives) { realt stack[16]; realt* stackPtr = stack - 1; // will be ++'ed first v_foreach (int, i, vm.code()) { if (*i == OP_X) { STACK_OFFSET_CHANGE(+1); *stackPtr = x; } else if (*i == OP_PUT_DERIV) { ++i; // the OP_PUT_DERIV opcode is followed by a number n, // the derivative is calculated with respect to n'th variable assert(*i < (int) derivatives.size()); derivatives[*i] = *stackPtr; STACK_OFFSET_CHANGE(-1); } else run_func_op(vm.numbers(), i, stackPtr); } assert(stackPtr == stack); return stack[0]; } realt run_code_for_custom_func_value(const VMData& vm, realt x, int code_offset) { realt stack[16]; realt* stackPtr = stack - 1; // will be ++'ed first for (vector::const_iterator i = vm.code().begin() + code_offset; i != vm.code().end(); ++i) { if (*i == OP_X) { STACK_OFFSET_CHANGE(+1); *stackPtr = x; } else run_func_op(vm.numbers(), i, stackPtr); } assert(stackPtr == stack); return stack[0]; } } // namespace fityk fityk-1.3.1/fityk/vm.h000066400000000000000000000110511302634723100145620ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// virtual machine - calculates expressions using by executing bytecode #ifndef FITYK_VM_H_ #define FITYK_VM_H_ #include "fityk.h" // struct Point, realt namespace fityk { class Full; class Variable; /// operators used in VM code enum Op { // constant OP_NUMBER, // Custom symbol that has associated numeric value. // Like OP_NUMBER, OP_SYMBOL is followed by index, // but the value is stored externally. OP_SYMBOL, // ops used only in calc.cpp OP_X, OP_PUT_DERIV, // functions R -> R OP_ONE_ARG, OP_NEG = OP_ONE_ARG, OP_EXP, OP_ERFC, OP_ERF, OP_SIN, OP_COS, OP_TAN, OP_SINH, OP_COSH, OP_TANH, OP_ASIN, OP_ACOS, OP_ATAN, OP_LOG10, OP_LN, OP_SQRT, OP_GAMMA, OP_LGAMMA, OP_DIGAMMA, OP_ABS, OP_ROUND, // functions (R, R) -> R OP_TWO_ARG, OP_POW = OP_TWO_ARG, OP_MUL, OP_DIV, OP_ADD, OP_SUB, OP_VOIGT, OP_DVOIGT_DX, OP_DVOIGT_DY, OP_MOD, OP_MIN2, OP_MAX2, OP_RANDNORM, OP_RANDU, // comparisons (R, R) -> 0/1 OP_GT, OP_GE, OP_LT, OP_LE, OP_EQ, OP_NEQ, // boolean // R -> 0/1 OP_NOT, // evaluate first arg and either discard it or skip the second expression OP_OR, OP_AFTER_OR, OP_AND, OP_AFTER_AND, // evaluate condition and one of two expressions OP_TERNARY, OP_TERNARY_MID, OP_AFTER_TERNARY, // functions (R, points) -> R OP_XINDEX, // properties of points OP_PX, OP_PY, OP_PS, OP_PA, OP_Px, OP_Py, OP_Ps, OP_Pa, OP_Pn, OP_PM, // changing points OP_ASSIGN_X, OP_ASSIGN_Y, OP_ASSIGN_S, OP_ASSIGN_A, // Fityk function-objects OP_FUNC, OP_SUM_F, OP_SUM_Z, // (model, R, ...) -> R OP_NUMAREA, OP_FINDX, OP_FIND_EXTR, OP_TILDE, // ... // used only in dataset transformations (@n=...) OP_DATASET, // followed by number OP_DT_SUM_SAME_X, OP_DT_AVG_SAME_X, OP_DT_SHIRLEY_BG, // these two are not VM operators, but are handy to have here, // they and are used in implementation of shunting yard algorithm OP_OPEN_ROUND, OP_OPEN_SQUARE }; /// handles VM (virtual machine) data and provides low-level access to it class FITYK_API VMData { public: static bool has_idx(int op) { return op == OP_NUMBER || op == OP_SYMBOL || op == OP_PUT_DERIV || op == OP_DATASET; } const std::vector& code() const { return code_; } const std::vector& numbers() const { return numbers_; } void append_code(int op) { code_.push_back(op); } void append_number(realt d); void clear_data() { code_.clear(); numbers_.clear(); } void replace_symbols(const std::vector& vv); void flip_indices(); bool single_symbol() const {return code_.size()==2 && code_[0]==OP_SYMBOL;} bool has_op(int op) const; std::vector& get_mutable_code() { return code_; } private: std::vector code_; // VM code std::vector numbers_; // VM data (numeric values) }; std::string op2str(int op); std::string vm2str(const std::vector& code, const std::vector& data); inline std::string vm2str(const VMData& vm) { return vm2str(vm.code(), vm.numbers()); } class FITYK_API ExprCalculator { public: ExprCalculator(const Full* F) : F_(F) {} /// calculate value of expression that may depend on dataset realt calculate(int n, const std::vector& points) const; /// calculate value of expression that does not depend on dataset realt calculate() const { return calculate(0, std::vector()); } /// calculate value of expression that was parsed with custom_vars set, /// the values in custom_val should correspond to names in custom_vars realt calculate_custom(const std::vector& custom_val) const; /// transform data (X=..., Y=..., S=..., A=...) void transform_data(std::vector& points); const VMData& vm() const { return vm_; } protected: const Full* F_; VMData vm_; }; realt run_code_for_variable(const VMData& vm, const std::vector &variables, std::vector &derivatives); realt run_code_for_custom_func(const VMData& vm, realt x, std::vector &derivatives); realt run_code_for_custom_func_value(const VMData& vm, realt x, int code_offset); } // namespace fityk #endif // FITYK_VM_H_ fityk-1.3.1/fityk/voigt.cpp000066400000000000000000000400041302634723100156230ustar00rootroot00000000000000 // fastest_humlik.for and humdev.for - from Bob Wells Voigt Function Page // http://www.atm.ox.ac.uk/user/wells/voigt.html // Translated to C++ with f2c program and modified by M.W. // It can be slower than original, I haven't compared the speed. #define BUILDING_LIBFITYK #include "voigt.h" #include /// Calculates the Faddeeva function /// and partial derivatives of the Voigt function for y>=0 /// (from http://www.atm.ox.ac.uk/user/wells/voigt.html) /// arguments: /// x, y - Faddeeva/Voigt function arguments /// k - voigt -- output /// l - Imaginary part -- output /// dkdx - dVoigt/dx -- output /// dkdy - dVoigt/dy -- output void humdev(const float x, const float y, float &k, float &l, float &dkdx, float &dkdy) { static const float c[6] = { 1.0117281f, -0.75197147f, 0.012557727f, 0.010022008f, -2.4206814e-4f, 5.0084806e-7f }; static const float s[6] = { 1.393237f, 0.23115241f, -0.15535147f, 0.0062183662f, 9.1908299e-5f, -6.2752596e-7f }; static const float t[6] = { 0.31424038f, 0.94778839f, 1.5976826f, 2.2795071f, 3.020637f, 3.8897249f }; static const float rrtpi = 0.56418958f; // 1/SQRT(pi) static const double drtpi = 0.5641895835477563f; // 1/SQRT(pi) static float a0, b1, c0, c2, d0, d1, d2, e0, e2, e4, f1, f3, f5, g0, g2, g4, g6, h0, h2, h4, h6, p0, p2, p4, p6, p8, q1, q3, q5, q7, r0, r2, w0, w2, w4, z0, z2, z4, z6, z8, mf[6], pf[6], mq[6], mt[6], pq[6], pt[6], xm[6], ym[6], xp[6], yp[6]; static float old_y = -1.f; static bool rgb, rgc, rgd; static float yq, xlima, xlimb, xlimc, xlim4; if (y != old_y) { old_y = y; rgb = true, rgc = true, rgd = true; yq = y * y; xlima = 146.7f - y; xlimb = 24.f - y; xlimc = 7.4f - y; xlim4 = y * 18.1f + 1.65f; } float abx = fabs(x); float xq = abx * abx; if (abx > xlima) { // Region A float d = (float)1. / (xq + yq); d1 = d * rrtpi; k = d1 * y; l = d1 * x; d1 *= d; dkdx = -d1 * (y + y) * x; dkdy = d1 * (xq - yq); } else if (abx > xlimb) { // Region B if (rgb) { rgb = false; a0 = yq + .5f; b1 = yq - .5f; d0 = a0 * a0; d2 = b1 + b1; c0 = yq * (1.f - d2) + 1.5f; c2 = a0 + a0; r0 = yq * (.25f - yq * (yq + .5f)) + .125f; r2 = yq * (yq + 5.f) + .25f; } float d = 1.f / (d0 + xq * (d2 + xq)); d1 = d * rrtpi; k = d1 * (a0 + xq) * y; l = d1 * (b1 + xq) * x; d1 *= d; dkdx = d1 * x * y * (c0 - (c2 + xq) * (xq + xq)); dkdy = d1 * (r0 - xq * (r2 - xq * (b1 + xq))); } else { if (abx > xlimc) { // Region C if (rgc) { rgc = false; h0 = yq * (yq * (yq * (yq + (float)6.) + (float)10.5) + (float)4.5) + (float).5625; h2 = yq * (yq * (yq * (float)4. + (float)6.) + (float)9.) - (float)4.5; h4 = (float)10.5 - yq * ((float)6. - yq * (float)6.); h6 = yq * (float)4. - (float)6.; w0 = yq * (yq * (yq * (float)7. + (float)27.5) + (float) 24.25) + (float)1.875; w2 = yq * (yq * (float)15. + (float)3.) + (float)5.25; w4 = yq * (float)9. - (float)4.5; f1 = yq * (yq * (yq + (float)4.5) + (float)5.25) - (float) 1.875; f3 = (float)8.25 - yq * ((float)1. - yq * (float)3.); f5 = yq * (float)3. - (float)5.5; e0 = y * (yq * (yq * (yq + (float)5.5) + (float)8.25) + (float)1.875); e2 = y * (yq * (yq * (float)3. + (float)1.) + (float) 5.25); e4 = y * (float).75 * h6; g0 = y * (yq * (yq * (yq * (float)8. + (float)36.) + (float)42.) + (float)9.); g2 = y * (yq * (yq * (float)24. + (float)24.) + (float)18.); g4 = y * (yq * (float)24. - (float)12.); g6 = y * (float)8.; } float u = e0 + xq * (e2 + xq * (e4 + xq * y)); float d = (float)1. / (h0 + xq * (h2 + xq * (h4 + xq * (h6 + xq)))); k = d * rrtpi * u; l = d * rrtpi * x * (f1 + xq * (f3 + xq * (f5 + xq))); float dudy = w0 + xq * (w2 + xq * (w4 + xq)); float dvdy = g0 + xq * (g2 + xq * (g4 + xq * g6)); dkdy = d * rrtpi * (dudy - d * u * dvdy); } else if (abx < (float).85) { // Region D if (rgd) { rgd = false; z0 = y * (y * (y * (y * (y * (y * (y * (y * (y * (y + (float)13.3988) + (float)88.26741) + (float) 369.1989) + (float)1074.409) + (float)2256.981) + (float)3447.629) + (float)3764.966) + (float) 2802.87) + (float)1280.829) + (float)272.1014; z2 = y * (y * (y * (y * (y * (y * (y * (y * (float)5. + (float)53.59518) + (float)266.2987) + (float)793.4273) + (float)1549.675) + (float)2037.31) + (float)1758.336) + (float)902.3066) + (float)211.678; z4 = y * (y * (y * (y * (y * (y * (float)10. + (float)80.39278) + (float)269.2916) + (float) 479.2576) + (float)497.3014) + (float)308.1852) + (float)78.86585; z6 = y * (y * (y * (y * (float)10. + (float)53.59518) + (float)92.75679) + (float)55.02933) + (float)22.03523; z8 = y * (y * (float)5. + (float)13.3988) + (float)1.49646; p0 = y * (y * (y * (y * (y * (y * (y * (y * (y * (float).3183291 + (float)4.264678) + (float) 27.93941) + (float)115.3772) + (float)328.2151) + (float)662.8097) + (float)946.897) + (float) 919.4955) + (float)549.3954) + (float)153.5168; p2 = y * (y * (y * (y * (y * (y * (y * (float) 1.2733163 + (float)12.79458) + (float)56.81652) + (float)139.4665) + (float)189.773) + (float) 124.5975) - (float)1.322256) - (float)34.16955; p4 = y * (y * (y * (y * (y * (float)1.9099744 + ( float)12.79568) + (float)29.81482) + (float) 24.01655) + (float)10.46332) + (float)2.584042; p6 = y * (y * (y * (float)1.273316 + (float)4.266322) + (float).9377051) - (float).07272979; p8 = y * (float).3183291 + (float)5.480304e-4; q1 = y * (y * (y * (y * (y * (y * (y * (y * ( float).3183291 + (float)4.26413) + (float)27.6294) + (float)111.0528) + (float)301.3208) + (float) 557.5178) + (float)685.8378) + (float)508.2585) + (float)173.2355; q3 = y * (y * (y * (y * (y * (y * (float)1.273316 + (float)12.79239) + (float)55.8865) + (float) 130.8905) + (float)160.4013) + (float)100.7375) + (float)18.97431; q5 = y * (y * (y * (y * (float)1.909974 + (float) 12.79239) + (float)28.8848) + (float)19.83766) + (float)7.985877; q7 = y * (y * (float)1.273316 + (float)4.26413) + (float).6276985; } float u = (p0 + xq * (p2 + xq * (p4 + xq * (p6 + xq * p8)))) * 1.7724538f; float d = 1.f / (z0 + xq * (z2 + xq * (z4 + xq * (z6 + xq * (z8 + xq))))); k = d * u; l = d * 1.7724538f * x * (q1 + xq * (q3 + xq * (q5 + xq * (q7 + xq * .3183291f)))); dkdy = 2 * ((double) x * (double) l + (double) y * (double) k - drtpi); } else { // Use CPF12 float ypy0 = y + 1.5f; float ypy0q = ypy0 * ypy0; k = (float)0.; l = (float)0.; for (int j = 0; j <= 5; ++j) { mt[j] = x - t[j]; mq[j] = mt[j] * mt[j]; mf[j] = (float)1. / (mq[j] + ypy0q); xm[j] = mf[j] * mt[j]; ym[j] = mf[j] * ypy0; pt[j] = x + t[j]; pq[j] = pt[j] * pt[j]; pf[j] = (float)1. / (pq[j] + ypy0q); xp[j] = pf[j] * pt[j]; yp[j] = pf[j] * ypy0; l += c[j] * (xm[j] + xp[j]) + s[j] * (ym[j] - yp[j]); } if (abx <= xlim4) { // Humlicek CPF12 Region I float yf1 = ypy0 + ypy0; float yf2 = ypy0q + ypy0q; dkdy = (float)0.; for (int j = 0; j <= 5; ++j) { float mfq = mf[j] * mf[j]; float pfq = pf[j] * pf[j]; k += c[j] * (ym[j] + yp[j]) - s[j] * (xm[j] - xp[j]); dkdy += c[j] * (mf[j] + pf[j] - yf2 * (mfq + pfq)) + s[j] * yf1 * (mt[j] * mfq - pt[j] * pfq); } } else { // Humlicek CPF12 Region II float yp2y0 = y + (float)3.; for (int j = 0; j <= 5; ++j) { k += (c[j] * (mq[j] * mf[j] - ym[j] * 1.5f) + s[j] * yp2y0 * xm[j]) / (mq[j] + 2.25f) + (c[j] * (pq[j] * pf[j] - yp[j] * 1.5f) - s[j] * yp2y0 * xp[j]) / (pq[j] + 2.25f); } k = y * k + exp(-xq); dkdy = 2 * ((double) x * (double) l + (double) y * (double) k - drtpi); } } dkdx = 2 * ((double) y * (double) l - (double) x * (double) k); } } // ======================================================================== /// Calculates the Faddeeva function with relative error less than 10^(-4). /// (from http://www.atm.ox.ac.uk/user/wells/voigt.html) /// arguments: /// x, y - Faddeeva/Voigt function arguments /// return value -- voigt float humlik(const float x, const float y) { static const float c[6] = { 1.0117281f, -0.75197147f, 0.012557727f, 0.010022008f, -2.4206814e-4f, 5.0084806e-7f }; static const float s[6] = { 1.393237f, 0.23115241f, -0.15535147f, 0.0062183662f, 9.1908299e-5f, -6.2752596e-7f }; static const float t[6] = { 0.31424038f, 0.94778839f, 1.5976826f, 2.2795071f, 3.020637f, 3.8897249f }; const float rrtpi = 0.56418958f; // 1/SQRT(pi) static float a0, d0, d2, e0, e2, e4, h0, h2, h4, h6, p0, p2, p4, p6, p8, z0, z2, z4, z6, z8; static float mf[6], pf[6], mq[6], pq[6], xm[6], ym[6], xp[6], yp[6]; static float old_y = -1.f; static bool rg1, rg2, rg3; static float xlim0, xlim1, xlim2, xlim3, xlim4; static float yq, yrrtpi; if (y != old_y) { old_y = y; yq = y * y; yrrtpi = y * rrtpi; rg1 = true, rg2 = true, rg3 = true; if (y < 70.55) { xlim0 = sqrt(y * (40.f - y * 3.6f) + 15100.f); xlim1 = (y >= 8.425 ? 0.f : sqrt(164.f - y * (y * 1.8f + 4.3f))); xlim2 = 6.8f - y; xlim3 = y * 2.4f; xlim4 = y * 18.1f + 1.65f; if (y <= 1e-6) xlim2 = xlim1 = xlim0; } } float abx = fabs(x); float xq = abx * abx; if (abx >= xlim0 || y >= 70.55) // Region 0 algorithm return yrrtpi / (xq + yq); else if (abx >= xlim1) { // Humlicek W4 Region 1 if (rg1) { // First point in Region 1 rg1 = false; a0 = yq + 0.5f; //Region 1 y-dependents d0 = a0 * a0; d2 = yq + yq - 1.f; } return rrtpi / (d0 + xq * (d2 + xq)) * y * (a0 + xq); } else if (abx > xlim2) { // Humlicek W4 Region 2 if (rg2) { //First point in Region 2 rg2 = false; // Region 2 y-dependents h0 = yq * (yq * (yq * (yq + 6.f) + 10.5f) + 4.5f) + 0.5625f; h2 = yq * (yq * (yq * 4.f + 6.f) + 9.f) - 4.5f; h4 = 10.5f - yq * (6.f - yq * 6.f); h6 = yq * 4.f - 6.f; e0 = yq * (yq * (yq + 5.5f) + 8.25f) + 1.875f; e2 = yq * (yq * 3.f + 1.f) + 5.25f; e4 = h6 * 0.75f; } return rrtpi / (h0 + xq * (h2 + xq * (h4 + xq * (h6 + xq)))) * y * (e0 + xq * (e2 + xq * (e4 + xq))); } else if (abx < xlim3) { // Humlicek W4 Region 3 if (rg3) { // First point in Region 3 rg3 = false; //Region 3 y-dependents z0 = y * (y * (y * (y * (y * (y * (y * (y * (y * (y + 13.3988f) + 88.26741f) + 369.1989f) + 1074.409f) + 2256.981f) + 3447.629f) + 3764.966f) + 2802.87f) + 1280.829f) + 272.1014f; z2 = y * (y * (y * (y * (y * (y * (y * (y * 5.f + 53.59518f) + 266.2987f) + 793.4273f) + 1549.675f) + 2037.31f) + 1758.336f) + 902.3066f) + 211.678f; z4 = y * (y * (y * (y * (y * (y * 10.f + 80.39278f) + 269.2916f) + 479.2576f) + 497.3014f) + 308.1852f) + 78.86585f; z6 = y * (y * (y * (y * 10.f + 53.59518f) + 92.75679f) + 55.02933f) + 22.03523f; z8 = y * (y * 5.f + 13.3988f) + 1.49646f; p0 = y * (y * (y * (y * (y * (y * (y * (y * (y * 0.3183291f + 4.264678f) + 27.93941f) + 115.3772f) + 328.2151f) + 662.8097f) + 946.897f) + 919.4955f) + 549.3954f) + 153.5168f; p2 = y * (y * (y * (y * (y * (y * (y * 1.2733163f + 12.79458f) + 56.81652f) + 139.4665f) + 189.773f) + 124.5975f) - 1.322256f) - 34.16955f; p4 = y * (y * (y * (y * (y * 1.9099744f + 12.79568f) + 29.81482f) + 24.01655f) + 10.46332f) + 2.584042f; p6 = y * (y * (y * 1.273316f + 4.266322f) + 0.9377051f) - 0.07272979f; p8 = y * .3183291f + 5.480304e-4f; } return 1.7724538f / (z0 + xq * (z2 + xq * (z4 + xq * (z6 + xq * (z8 + xq))))) * (p0 + xq * (p2 + xq * (p4 + xq * (p6 + xq * p8)))); } else { // Humlicek CPF12 algorithm float ypy0 = y + 1.5f; float ypy0q = ypy0 * ypy0; for (int j = 0; j <= 5; ++j) { float d = x - t[j]; mq[j] = d * d; mf[j] = 1.f / (mq[j] + ypy0q); xm[j] = mf[j] * d; ym[j] = mf[j] * ypy0; d = x + t[j]; pq[j] = d * d; pf[j] = 1.f / (pq[j] + ypy0q); xp[j] = pf[j] * d; yp[j] = pf[j] * ypy0; } float k = 0.f; if (abx <= xlim4) // Humlicek CPF12 Region I for (int j = 0; j <= 5; ++j) k += c[j] * (ym[j]+yp[j]) - s[j] * (xm[j]-xp[j]); else { // Humlicek CPF12 Region II float yf = y + 3.f; for (int j = 0; j <= 5; ++j) k += (c[j] * (mq[j] * mf[j] - ym[j] * 1.5f) + s[j] * yf * xm[j]) / (mq[j] + 2.25f) + (c[j] * (pq[j] * pf[j] - yp[j] * 1.5f) - s[j] * yf * xp[j]) / (pq[j] + 2.25f); k = y * k + exp(-xq); } return k; } } fityk-1.3.1/fityk/voigt.h000066400000000000000000000022761302634723100153010ustar00rootroot00000000000000 /// calculates the Faddeeva function /// and partial derivatives of the Voigt function for y>=0 /// (from http://www.atm.ox.ac.uk/user/wells/voigt.html) void humdev(const float x, const float y, float &k, float &l, float &dkdx, float &dkdy); // arguments: // x, y - Faddeeva/Voigt function arguments // k - voigt -- output // l - Imaginary part -- output // dkdx - dVoigt/dx -- output // dkdy - dVoigt/dy -- output /// calculates the Faddeeva function with relative error less than 10^(-4). /// (from http://www.atm.ox.ac.uk/user/wells/voigt.html) float humlik(const float x, const float y); // arguments: // x, y - Faddeeva/Voigt function arguments // return value -- voigt /// wrapper around humdev(), return dk/dx. Can be slow. inline float humdev_dkdx(const float x, const float y) { float k, l, dkdx, dkdy; humdev(x, y, k, l, dkdx, dkdy); return dkdx; } /// wrapper around humdev(), return dk/dy. Can be slow. inline float humdev_dkdy(const float x, const float y) { float k, l, dkdx, dkdy; humdev(x, y, k, l, dkdx, dkdy); return dkdy; } fityk-1.3.1/m4/000077500000000000000000000000001302634723100131635ustar00rootroot00000000000000fityk-1.3.1/m4/ax_cxx_have_isfinite.m4000066400000000000000000000015731302634723100176220ustar00rootroot00000000000000dnl test from https://svn.code.sf.net/p/cppunit/code/trunk/cppunit/config/ax_cxx_have_isfinite.m4 dnl with changed to (no std:: added) dnl --- dnl @synopsis AX_CXX_HAVE_ISFINITE dnl dnl If isfinite() is available to the C++ compiler: dnl define HAVE_ISFINITE dnl add "-lm" to LIBS dnl AC_DEFUN([AX_CXX_HAVE_ISFINITE], [ax_cxx_have_isfinite_save_LIBS=$LIBS LIBS="$LIBS -lm" AC_CACHE_CHECK(for isfinite, ax_cv_cxx_have_isfinite, [AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[int f = isfinite( 3 );]])], [ax_cv_cxx_have_isfinite=yes], [ax_cv_cxx_have_isfinite=no]) AC_LANG_RESTORE]) if test "$ax_cv_cxx_have_isfinite" = yes; then AC_DEFINE([HAVE_ISFINITE],1,[define if compiler has isfinite]) else LIBS=$ax_cxx_have_isfinite_save_LIBS fi ]) fityk-1.3.1/m4/ax_lib_readline.m4000066400000000000000000000074461302634723100165410ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_lib_readline.html # =========================================================================== # # SYNOPSIS # # AX_LIB_READLINE # # DESCRIPTION # # Searches for a readline compatible library. If found, defines # `HAVE_LIBREADLINE'. If the found library has the `add_history' function, # sets also `HAVE_READLINE_HISTORY'. Also checks for the locations of the # necessary include files and sets `HAVE_READLINE_H' or # `HAVE_READLINE_READLINE_H' and `HAVE_READLINE_HISTORY_H' or # 'HAVE_HISTORY_H' if the corresponding include files exists. # # The libraries that may be readline compatible are `libedit', # `libeditline' and `libreadline'. Sometimes we need to link a termcap # library for readline to work, this macro tests these cases too by trying # to link with `libtermcap', `libcurses' or `libncurses' before giving up. # # Here is an example of how to use the information provided by this macro # to perform the necessary includes or declarations in a C file: # # #ifdef HAVE_LIBREADLINE # # if defined(HAVE_READLINE_READLINE_H) # # include # # elif defined(HAVE_READLINE_H) # # include # # else /* !defined(HAVE_READLINE_H) */ # extern char *readline (); # # endif /* !defined(HAVE_READLINE_H) */ # char *cmdline = NULL; # #else /* !defined(HAVE_READLINE_READLINE_H) */ # /* no readline */ # #endif /* HAVE_LIBREADLINE */ # # #ifdef HAVE_READLINE_HISTORY # # if defined(HAVE_READLINE_HISTORY_H) # # include # # elif defined(HAVE_HISTORY_H) # # include # # else /* !defined(HAVE_HISTORY_H) */ # extern void add_history (); # extern int write_history (); # extern int read_history (); # # endif /* defined(HAVE_READLINE_HISTORY_H) */ # /* no history */ # #endif /* HAVE_READLINE_HISTORY */ # # LICENSE # # Copyright (c) 2008 Ville Laurikari # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. #serial 6 AU_ALIAS([VL_LIB_READLINE], [AX_LIB_READLINE]) AC_DEFUN([AX_LIB_READLINE], [ AC_CACHE_CHECK([for a readline compatible library], ax_cv_lib_readline, [ ORIG_LIBS="$LIBS" for readline_lib in readline edit editline; do for termcap_lib in "" termcap curses ncurses; do if test -z "$termcap_lib"; then TRY_LIB="-l$readline_lib" else TRY_LIB="-l$readline_lib -l$termcap_lib" fi LIBS="$ORIG_LIBS $TRY_LIB" AC_TRY_LINK_FUNC(readline, ax_cv_lib_readline="$TRY_LIB") if test -n "$ax_cv_lib_readline"; then break fi done if test -n "$ax_cv_lib_readline"; then break fi done if test -z "$ax_cv_lib_readline"; then ax_cv_lib_readline="no" fi LIBS="$ORIG_LIBS" ]) if test "$ax_cv_lib_readline" != "no"; then LIBS="$LIBS $ax_cv_lib_readline" AC_DEFINE(HAVE_LIBREADLINE, 1, [Define if you have a readline compatible library]) AC_CHECK_HEADERS(readline.h readline/readline.h) AC_CACHE_CHECK([whether readline supports history], ax_cv_lib_readline_history, [ ax_cv_lib_readline_history="no" AC_TRY_LINK_FUNC(add_history, ax_cv_lib_readline_history="yes") ]) if test "$ax_cv_lib_readline_history" = "yes"; then AC_DEFINE(HAVE_READLINE_HISTORY, 1, [Define if your readline library has \`add_history']) AC_CHECK_HEADERS(history.h readline/history.h) fi fi ])dnl fityk-1.3.1/m4/ax_lua.m4000066400000000000000000000636011302634723100147040ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_lua.html # =========================================================================== # # SYNOPSIS # # AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # # DESCRIPTION # # Detect a Lua interpreter, optionally specifying a minimum and maximum # version number. Set up important Lua paths, such as the directories in # which to install scripts and modules (shared libraries). # # Also detect Lua headers and libraries. The Lua version contained in the # header is checked to match the Lua interpreter version exactly. When # searching for Lua libraries, the version number is used as a suffix. # This is done with the goal of supporting multiple Lua installs (5.1, # 5.2, and 5.3 side-by-side). # # A note on compatibility with previous versions: This file has been # mostly rewritten for serial 18. Most developers should be able to use # these macros without needing to modify configure.ac. Care has been taken # to preserve each macro's behavior, but there are some differences: # # 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as # AX_PROG_LUA with no arguments. # # 2) AX_LUA_HEADERS now checks that the version number defined in lua.h # matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore # unnecessary, so it is deprecated and does not expand to anything. # # 3) The configure flag --with-lua-suffix no longer exists; the user # should instead specify the LUA precious variable on the command line. # See the AX_PROG_LUA description for details. # # Please read the macro descriptions below for more information. # # This file was inspired by Andrew Dalke's and James Henstridge's # python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4 # (serial 17). Basically, this file is a mash-up of those two files. I # like to think it combines the best of the two! # # AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua # paths. Adds precious variable LUA, which may contain the path of the Lua # interpreter. If LUA is blank, the user's path is searched for an # suitable interpreter. # # If MINIMUM-VERSION is supplied, then only Lua interpreters with a # version number greater or equal to MINIMUM-VERSION will be accepted. If # TOO-BIG-VERSION is also supplied, then only Lua interpreters with a # version number greater or equal to MINIMUM-VERSION and less than # TOO-BIG-VERSION will be accepted. # # The Lua version number, LUA_VERSION, is found from the interpreter, and # substituted. LUA_PLATFORM is also found, but not currently supported (no # standard representation). # # Finally, the macro finds four paths: # # luadir Directory to install Lua scripts. # pkgluadir $luadir/$PACKAGE # luaexecdir Directory to install Lua modules. # pkgluaexecdir $luaexecdir/$PACKAGE # # These paths are found based on $prefix, $exec_prefix, Lua's # package.path, and package.cpath. The first path of package.path # beginning with $prefix is selected as luadir. The first path of # package.cpath beginning with $exec_prefix is used as luaexecdir. This # should work on all reasonable Lua installations. If a path cannot be # determined, a default path is used. Of course, the user can override # these later when invoking make. # # luadir Default: $prefix/share/lua/$LUA_VERSION # luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION # # These directories can be used by Automake as install destinations. The # variable name minus 'dir' needs to be used as a prefix to the # appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES. # # If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is # performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT- # FOUND is blank, then it will default to printing an error. To prevent # the default behavior, give ':' as an action. # # AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be # expanded before this macro. Adds precious variable LUA_INCLUDE, which # may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If # LUA_INCLUDE is blank, then this macro will attempt to find suitable # flags. # # LUA_INCLUDE can be used by Automake to compile Lua modules or # executables with embedded interpreters. The *_CPPFLAGS variables should # be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE). # # This macro searches for the header lua.h (and others). The search is # performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE. # If the search is unsuccessful, then some common directories are tried. # If the headers are then found, then LUA_INCLUDE is set accordingly. # # The paths automatically searched are: # # * /usr/include/luaX.Y # * /usr/include/lua/X.Y # * /usr/include/luaXY # * /usr/local/include/luaX.Y # * /usr/local/include/lua-X.Y # * /usr/local/include/lua/X.Y # * /usr/local/include/luaXY # # (Where X.Y is the Lua version number, e.g. 5.1.) # # The Lua version number found in the headers is always checked to match # the Lua interpreter's version number. Lua headers with mismatched # version numbers are not accepted. # # If headers are found, then ACTION-IF-FOUND is performed, otherwise # ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then # it will default to printing an error. To prevent the default behavior, # set the action to ':'. # # AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be # expanded before this macro. Adds precious variable LUA_LIB, which may # contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank, # then this macro will attempt to find suitable flags. # # LUA_LIB can be used by Automake to link Lua modules or executables with # embedded interpreters. The *_LIBADD and *_LDADD variables should be used # for this purpose, e.g. mymod_LIBADD = $(LUA_LIB). # # This macro searches for the Lua library. More technically, it searches # for a library containing the function lua_load. The search is performed # with a combination of LIBS, LIBRARY_PATH, and LUA_LIB. # # If the search determines that some linker flags are missing, then those # flags will be added to LUA_LIB. # # If libraries are found, then ACTION-IF-FOUND is performed, otherwise # ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then # it will default to printing an error. To prevent the default behavior, # set the action to ':'. # # AX_LUA_READLINE: Search for readline headers and libraries. Requires the # AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the # Autoconf Archive. # # If a readline compatible library is found, then ACTION-IF-FOUND is # performed, otherwise ACTION-IF-NOT-FOUND is performed. # # LICENSE # # Copyright (c) 2015 Reuben Thomas # Copyright (c) 2014 Tim Perkins # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 39 dnl ========================================================================= dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION], dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_PROG_LUA], [ dnl Check for required tools. AC_REQUIRE([AC_PROG_GREP]) AC_REQUIRE([AC_PROG_SED]) dnl Make LUA a precious variable. AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1]) dnl Find a Lua interpreter. m4_define_default([_AX_LUA_INTERPRETER_LIST], [lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50]) m4_if([$1], [], [ dnl No version check is needed. Find any Lua interpreter. AS_IF([test "x$LUA" = 'x'], [AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])]) ax_display_LUA='lua' AS_IF([test "x$LUA" != 'x:'], [ dnl At least check if this is a Lua interpreter. AC_MSG_CHECKING([if $LUA is a Lua interpreter]) _AX_LUA_CHK_IS_INTRP([$LUA], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([not a Lua interpreter]) ]) ]) ], [ dnl A version check is needed. AS_IF([test "x$LUA" != 'x'], [ dnl Check if this is a Lua interpreter. AC_MSG_CHECKING([if $LUA is a Lua interpreter]) _AX_LUA_CHK_IS_INTRP([$LUA], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([not a Lua interpreter]) ]) dnl Check the version. m4_if([$2], [], [_ax_check_text="whether $LUA version >= $1"], [_ax_check_text="whether $LUA version >= $1, < $2"]) AC_MSG_CHECKING([$_ax_check_text]) _AX_LUA_CHK_VER([$LUA], [$1], [$2], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([version is out of range for specified LUA])]) ax_display_LUA=$LUA ], [ dnl Try each interpreter until we find one that satisfies VERSION. m4_if([$2], [], [_ax_check_text="for a Lua interpreter with version >= $1"], [_ax_check_text="for a Lua interpreter with version >= $1, < $2"]) AC_CACHE_CHECK([$_ax_check_text], [ax_cv_pathless_LUA], [ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do test "x$ax_cv_pathless_LUA" = 'xnone' && break _AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue]) _AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break]) done ]) dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA. AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'], [LUA=':'], [AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])]) ax_display_LUA=$ax_cv_pathless_LUA ]) ]) AS_IF([test "x$LUA" = 'x:'], [ dnl Run any user-specified action, or abort. m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])]) ], [ dnl Query Lua for its version number. AC_CACHE_CHECK([for $ax_display_LUA version], [ax_cv_lua_version], [ dnl Get the interpreter version in X.Y format. This should work for dnl interpreters version 5.0 and beyond. ax_cv_lua_version=[`$LUA -e ' -- return a version number in X.Y format local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)") print(ver)'`] ]) AS_IF([test "x$ax_cv_lua_version" = 'x'], [AC_MSG_ERROR([invalid Lua version number])]) AC_SUBST([LUA_VERSION], [$ax_cv_lua_version]) AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`]) dnl The following check is not supported: dnl At times (like when building shared libraries) you may want to know dnl which OS platform Lua thinks this is. AC_CACHE_CHECK([for $ax_display_LUA platform], [ax_cv_lua_platform], [ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]]) AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct dnl variables so they can be overridden if need be. However, the general dnl consensus is that you shouldn't need this ability. AC_SUBST([LUA_PREFIX], ['${prefix}']) AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}']) dnl Lua provides no way to query the script directory, and instead dnl provides LUA_PATH. However, we should be able to make a safe educated dnl guess. If the built-in search path contains a directory which is dnl prefixed by $prefix, then we can store scripts there. The first dnl matching path will be used. AC_CACHE_CHECK([for $ax_display_LUA script directory], [ax_cv_lua_luadir], [ AS_IF([test "x$prefix" = 'xNONE'], [ax_lua_prefix=$ac_default_prefix], [ax_lua_prefix=$prefix]) dnl Initialize to the default path. ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION" dnl Try to find a path with the prefix. _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script]) AS_IF([test "x$ax_lua_prefixed_path" != 'x'], [ dnl Fix the prefix. _ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'` ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \ $SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"` ]) ]) AC_SUBST([luadir], [$ax_cv_lua_luadir]) AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE]) dnl Lua provides no way to query the module directory, and instead dnl provides LUA_PATH. However, we should be able to make a safe educated dnl guess. If the built-in search path contains a directory which is dnl prefixed by $exec_prefix, then we can store modules there. The first dnl matching path will be used. AC_CACHE_CHECK([for $ax_display_LUA module directory], [ax_cv_lua_luaexecdir], [ AS_IF([test "x$exec_prefix" = 'xNONE'], [ax_lua_exec_prefix=$ax_lua_prefix], [ax_lua_exec_prefix=$exec_prefix]) dnl Initialize to the default path. ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION" dnl Try to find a path with the prefix. _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_exec_prefix], [module]) AS_IF([test "x$ax_lua_prefixed_path" != 'x'], [ dnl Fix the prefix. _ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'` ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \ $SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"` ]) ]) AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir]) AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE]) dnl Run any user specified action. $3 ]) ]) dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA. AC_DEFUN([AX_WITH_LUA], [ AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]]) AX_PROG_LUA ]) dnl ========================================================================= dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl ========================================================================= AC_DEFUN([_AX_LUA_CHK_IS_INTRP], [ dnl A minimal Lua factorial to prove this is an interpreter. This should work dnl for Lua interpreters version 5.0 and beyond. _ax_lua_factorial=[`$1 2>/dev/null -e ' -- a simple factorial function fact (n) if n == 0 then return 1 else return n * fact(n-1) end end print("fact(5) is " .. fact(5))'`] AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'], [$2], [$3]) ]) dnl ========================================================================= dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION], dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl ========================================================================= AC_DEFUN([_AX_LUA_CHK_VER], [ dnl Check that the Lua version is within the bounds. Only the major and minor dnl version numbers are considered. This should work for Lua interpreters dnl version 5.0 and beyond. _ax_lua_good_version=[`$1 -e ' -- a script to compare versions function verstr2num(verstr) local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)") if majorver and minorver then return tonumber(majorver) * 100 + tonumber(minorver) end end local minver = verstr2num("$2") local _, _, trimver = string.find(_VERSION, "^Lua (.*)") local ver = verstr2num(trimver) local maxver = verstr2num("$3") or 1e9 if minver <= ver and ver < maxver then print("yes") else print("no") end'`] AS_IF([test "x$_ax_lua_good_version" = "xyes"], [$4], [$5]) ]) dnl ========================================================================= dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR) dnl ========================================================================= AC_DEFUN([_AX_LUA_FND_PRFX_PTH], [ dnl Get the script or module directory by querying the Lua interpreter, dnl filtering on the given prefix, and selecting the shallowest path. If no dnl path is found matching the prefix, the result will be an empty string. dnl The third argument determines the type of search, it can be 'script' or dnl 'module'. Supplying 'script' will perform the search with package.path dnl and LUA_PATH, and supplying 'module' will search with package.cpath and dnl LUA_CPATH. This is done for compatibility with Lua 5.0. ax_lua_prefixed_path=[`$1 -e ' -- get the path based on search type local searchtype = "$3" local paths = "" if searchtype == "script" then paths = (package and package.path) or LUA_PATH elseif searchtype == "module" then paths = (package and package.cpath) or LUA_CPATH end -- search for the prefix local prefix = "'$2'" local minpath = "" local mindepth = 1e9 string.gsub(paths, "(@<:@^;@:>@+)", function (path) path = string.gsub(path, "%?.*$", "") path = string.gsub(path, "/@<:@^/@:>@*$", "") if string.find(path, prefix) then local depth = string.len(string.gsub(path, "@<:@^/@:>@", "")) if depth < mindepth then minpath = path mindepth = depth end end end) print(minpath)'`] ]) dnl ========================================================================= dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_LUA_HEADERS], [ dnl Check for LUA_VERSION. AC_MSG_CHECKING([if LUA_VERSION is defined]) AS_IF([test "x$LUA_VERSION" != 'x'], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION]) ]) dnl Make LUA_INCLUDE a precious variable. AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1]) dnl Some default directories to search. LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'` m4_define_default([_AX_LUA_INCLUDE_LIST], [ /usr/include/lua$LUA_VERSION \ /usr/include/lua-$LUA_VERSION \ /usr/include/lua/$LUA_VERSION \ /usr/include/lua$LUA_SHORT_VERSION \ /usr/local/include/lua$LUA_VERSION \ /usr/local/include/lua-$LUA_VERSION \ /usr/local/include/lua/$LUA_VERSION \ /usr/local/include/lua$LUA_SHORT_VERSION \ ]) dnl Try to find the headers. _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h]) CPPFLAGS=$_ax_lua_saved_cppflags dnl Try some other directories if LUA_INCLUDE was not set. AS_IF([test "x$LUA_INCLUDE" = 'x' && test "x$ac_cv_header_lua_h" != 'xyes'], [ dnl Try some common include paths. for _ax_include_path in _AX_LUA_INCLUDE_LIST; do test ! -d "$_ax_include_path" && continue AC_MSG_CHECKING([for Lua headers in]) AC_MSG_RESULT([$_ax_include_path]) AS_UNSET([ac_cv_header_lua_h]) AS_UNSET([ac_cv_header_lualib_h]) AS_UNSET([ac_cv_header_lauxlib_h]) AS_UNSET([ac_cv_header_luaconf_h]) _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS -I$_ax_include_path" AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h]) CPPFLAGS=$_ax_lua_saved_cppflags AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'], [ LUA_INCLUDE="-I$_ax_include_path" break ]) done ]) AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'], [ dnl Make a program to print LUA_VERSION defined in the header. dnl TODO It would be really nice if we could do this without compiling a dnl program, then it would work when cross compiling. But I'm not sure how dnl to do this reliably. For now, assume versions match when cross compiling. AS_IF([test "x$cross_compiling" != 'xyes'], [ AC_CACHE_CHECK([for Lua header version], [ax_cv_lua_header_version], [ _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" AC_RUN_IFELSE( [ AC_LANG_SOURCE([[ #include #include #include int main(int argc, char ** argv) { if(argc > 1) printf("%s", LUA_VERSION); exit(EXIT_SUCCESS); } ]]) ], [ ax_cv_lua_header_version=`./conftest$EXEEXT p | \ $SED -n "s|^Lua \(@<:@0-9@:>@\{1,\}\.@<:@0-9@:>@\{1,\}\).\{0,\}|\1|p"` ], [ax_cv_lua_header_version='unknown']) CPPFLAGS=$_ax_lua_saved_cppflags ]) dnl Compare this to the previously found LUA_VERSION. AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION]) AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"], [ AC_MSG_RESULT([yes]) ax_header_version_match='yes' ], [ AC_MSG_RESULT([no]) ax_header_version_match='no' ]) ], [ AC_MSG_WARN([cross compiling so assuming header version number matches]) ax_header_version_match='yes' ]) ]) dnl Was LUA_INCLUDE specified? AS_IF([test "x$ax_header_version_match" != 'xyes' && test "x$LUA_INCLUDE" != 'x'], [AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])]) dnl Test the final result and run user code. AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1], [m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])]) ]) dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS. AC_DEFUN([AX_LUA_HEADERS_VERSION], [ AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]]) ]) dnl ========================================================================= dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_LUA_LIBS], [ dnl TODO Should this macro also check various -L flags? dnl Check for LUA_VERSION. AC_MSG_CHECKING([if LUA_VERSION is defined]) AS_IF([test "x$LUA_VERSION" != 'x'], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION]) ]) dnl Make LUA_LIB a precious variable. AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1]) AS_IF([test "x$LUA_LIB" != 'x'], [ dnl Check that LUA_LIBS works. _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" AC_SEARCH_LIBS([lua_load], [], [_ax_found_lua_libs='yes'], [_ax_found_lua_libs='no']) LIBS=$_ax_lua_saved_libs dnl Check the result. AS_IF([test "x$_ax_found_lua_libs" != 'xyes'], [AC_MSG_ERROR([cannot find libs for specified LUA_LIB])]) ], [ dnl First search for extra libs. _ax_lua_extra_libs='' _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" AC_SEARCH_LIBS([exp], [m]) AC_SEARCH_LIBS([dlopen], [dl]) LIBS=$_ax_lua_saved_libs AS_IF([test "x$ac_cv_search_exp" != 'xno' && test "x$ac_cv_search_exp" != 'xnone required'], [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"]) AS_IF([test "x$ac_cv_search_dlopen" != 'xno' && test "x$ac_cv_search_dlopen" != 'xnone required'], [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"]) dnl Try to find the Lua libs. _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" AC_SEARCH_LIBS([lua_load], [ lua$LUA_VERSION \ lua$LUA_SHORT_VERSION \ lua-$LUA_VERSION \ lua-$LUA_SHORT_VERSION \ lua \ ], [_ax_found_lua_libs='yes'], [_ax_found_lua_libs='no'], [$_ax_lua_extra_libs]) LIBS=$_ax_lua_saved_libs AS_IF([test "x$ac_cv_search_lua_load" != 'xno' && test "x$ac_cv_search_lua_load" != 'xnone required'], [LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"]) ]) dnl Test the result and run user code. AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1], [m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])]) ]) dnl ========================================================================= dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_LUA_READLINE], [ AX_LIB_READLINE AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' && test "x$ac_cv_header_readline_history_h" != 'x'], [ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS" $1 ], [$2]) ]) fityk-1.3.1/m4/ax_pkg_swig.m4000066400000000000000000000151571302634723100157400ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html # =========================================================================== # # SYNOPSIS # # AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found]) # # DESCRIPTION # # This macro searches for a SWIG installation on your system. If found, # then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is # found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd. # # You can use the optional first argument to check if the version of the # available SWIG is greater than or equal to the value of the argument. It # should have the format: N[.N[.N]] (N is a number between 0 and 999. Only # the first N is mandatory.) If the version argument is given (e.g. # 1.3.17), AX_PKG_SWIG checks that the swig package is this version number # or higher. # # As usual, action-if-found is executed if SWIG is found, otherwise # action-if-not-found is executed. # # In configure.in, use as: # # AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ]) # AX_SWIG_ENABLE_CXX # AX_SWIG_MULTI_MODULE_SUPPORT # AX_SWIG_PYTHON # # LICENSE # # Copyright (c) 2008 Sebastian Huber # Copyright (c) 2008 Alan W. Irwin # Copyright (c) 2008 Rafael Laboissiere # Copyright (c) 2008 Andrew Collier # Copyright (c) 2011 Murray Cumming # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 12 AC_DEFUN([AX_PKG_SWIG],[ # Find path to the "swig" executable. AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0]) if test -z "$SWIG" ; then m4_ifval([$3],[$3],[:]) elif test -n "$1" ; then AC_MSG_CHECKING([SWIG version]) [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] AC_MSG_RESULT([$swig_version]) if test -n "$swig_version" ; then # Calculate the required version number components [required=$1] [required_major=`echo $required | sed 's/[^0-9].*//'`] if test -z "$required_major" ; then [required_major=0] fi [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] [required_minor=`echo $required | sed 's/[^0-9].*//'`] if test -z "$required_minor" ; then [required_minor=0] fi [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] [required_patch=`echo $required | sed 's/[^0-9].*//'`] if test -z "$required_patch" ; then [required_patch=0] fi # Calculate the available version number components [available=$swig_version] [available_major=`echo $available | sed 's/[^0-9].*//'`] if test -z "$available_major" ; then [available_major=0] fi [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] [available_minor=`echo $available | sed 's/[^0-9].*//'`] if test -z "$available_minor" ; then [available_minor=0] fi [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] [available_patch=`echo $available | sed 's/[^0-9].*//'`] if test -z "$available_patch" ; then [available_patch=0] fi # Convert the version tuple into a single number for easier comparison. # Using base 100 should be safe since SWIG internally uses BCD values # to encode its version number. required_swig_vernum=`expr $required_major \* 10000 \ \+ $required_minor \* 100 \+ $required_patch` available_swig_vernum=`expr $available_major \* 10000 \ \+ $available_minor \* 100 \+ $available_patch` if test $available_swig_vernum -lt $required_swig_vernum; then AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.]) SWIG='' m4_ifval([$3],[$3],[]) else AC_MSG_CHECKING([for SWIG library]) SWIG_LIB=`$SWIG -swiglib` AC_MSG_RESULT([$SWIG_LIB]) m4_ifval([$2],[$2],[]) fi else AC_MSG_WARN([cannot determine SWIG version]) SWIG='' m4_ifval([$3],[$3],[]) fi fi AC_SUBST([SWIG_LIB]) ]) fityk-1.3.1/m4/ax_python_devel.m4000066400000000000000000000257321302634723100166260ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_python_devel.html # =========================================================================== # # SYNOPSIS # # AX_PYTHON_DEVEL([version]) # # DESCRIPTION # # Note: Defines as a precious variable "PYTHON_VERSION". Don't override it # in your configure.ac. # # This macro checks for Python and tries to get the include path to # 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LIBS) output # variables. It also exports $(PYTHON_EXTRA_LIBS) and # $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. # # You can search for some particular version of Python by passing a # parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please # note that you *have* to pass also an operator along with the version to # match, and pay special attention to the single quotes surrounding the # version number. Don't use "PYTHON_VERSION" for this: that environment # variable is declared as precious and thus reserved for the end-user. # # This macro should work for all versions of Python >= 2.1.0. As an end # user, you can disable the check for the python version by setting the # PYTHON_NOVERSIONCHECK environment variable to something else than the # empty string. # # If you need to use this macro for an older Python version, please # contact the authors. We're always open for feedback. # # LICENSE # # Copyright (c) 2009 Sebastian Huber # Copyright (c) 2009 Alan W. Irwin # Copyright (c) 2009 Rafael Laboissiere # Copyright (c) 2009 Andrew Collier # Copyright (c) 2009 Matteo Settenvini # Copyright (c) 2009 Horst Knorr # Copyright (c) 2013 Daniel Mullner # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 18 AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) AC_DEFUN([AX_PYTHON_DEVEL],[ # # Allow the use of a (user set) custom python version # AC_ARG_VAR([PYTHON_VERSION],[The installed Python version to use, for example '2.3'. This string will be appended to the Python interpreter canonical name.]) AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) if test -z "$PYTHON"; then AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) PYTHON_VERSION="" fi # # Check for a version of Python >= 2.1.0 # AC_MSG_CHECKING([for a version of Python >= '2.1.0']) ac_supports_python_ver=`$PYTHON -c "import sys; \ ver = sys.version.split ()[[0]]; \ print (ver >= '2.1.0')"` if test "$ac_supports_python_ver" != "True"; then if test -z "$PYTHON_NOVERSIONCHECK"; then AC_MSG_RESULT([no]) AC_MSG_FAILURE([ This version of the AC@&t@_PYTHON_DEVEL macro doesn't work properly with versions of Python before 2.1.0. You may need to re-run configure, setting the variables PYTHON_CPPFLAGS, PYTHON_LIBS, PYTHON_SITE_PKG, PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. Moreover, to disable this check, set PYTHON_NOVERSIONCHECK to something else than an empty string. ]) else AC_MSG_RESULT([skip at user request]) fi else AC_MSG_RESULT([yes]) fi # # if the macro parameter ``version'' is set, honour it # if test -n "$1"; then AC_MSG_CHECKING([for a version of Python $1]) ac_supports_python_ver=`$PYTHON -c "import sys; \ ver = sys.version.split ()[[0]]; \ print (ver $1)"` if test "$ac_supports_python_ver" = "True"; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) AC_MSG_ERROR([this package requires Python $1. If you have it installed, but it isn't the default Python interpreter in your system path, please pass the PYTHON_VERSION variable to configure. See ``configure --help'' for reference. ]) PYTHON_VERSION="" fi fi # # Check if you have distutils, else fail # AC_MSG_CHECKING([for the distutils Python package]) ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` if test -z "$ac_distutils_result"; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) AC_MSG_ERROR([cannot import Python module "distutils". Please check your Python installation. The error was: $ac_distutils_result]) PYTHON_VERSION="" fi # # Check for Python include path # AC_MSG_CHECKING([for Python include path]) if test -z "$PYTHON_CPPFLAGS"; then python_path=`$PYTHON -c "import distutils.sysconfig; \ print (distutils.sysconfig.get_python_inc ());"` plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ print (distutils.sysconfig.get_python_inc (plat_specific=1));"` if test -n "${python_path}"; then if test "${plat_python_path}" != "${python_path}"; then python_path="-I$python_path -I$plat_python_path" else python_path="-I$python_path" fi fi PYTHON_CPPFLAGS=$python_path fi AC_MSG_RESULT([$PYTHON_CPPFLAGS]) AC_SUBST([PYTHON_CPPFLAGS]) # # Check for Python library path # AC_MSG_CHECKING([for Python library path]) if test -z "$PYTHON_LIBS"; then # (makes two attempts to ensure we've got a version number # from the interpreter) ac_python_version=`cat<]], [[Py_Initialize();]]) ],[pythonexists=yes],[pythonexists=no]) AC_LANG_POP([C]) # turn back to default flags CPPFLAGS="$ac_save_CPPFLAGS" LIBS="$ac_save_LIBS" LDFLAGS="$ac_save_LDFLAGS" AC_MSG_RESULT([$pythonexists]) if test ! "x$pythonexists" = "xyes"; then AC_MSG_FAILURE([ Could not link test program to Python. Maybe the main Python library has been installed in some non-standard library path. If so, pass it to configure, via the LIBS environment variable. Example: ./configure LIBS="-L/usr/non-standard-path/python/lib" ============================================================================ ERROR! You probably have to install the development version of the Python package for your distribution. The exact name of this package varies among them. ============================================================================ ]) PYTHON_VERSION="" fi # # all done! # ]) fityk-1.3.1/m4/wxwin.m4000066400000000000000000001171611302634723100146100ustar00rootroot00000000000000dnl --------------------------------------------------------------------------- dnl Author: wxWidgets development team, dnl Francesco Montorsi, dnl Bob McCown (Mac-testing) dnl Creation date: 24/11/2001 dnl --------------------------------------------------------------------------- dnl =========================================================================== dnl Table of Contents of this macro file: dnl ------------------------------------- dnl dnl SECTION A: wxWidgets main macros dnl - WX_CONFIG_OPTIONS dnl - WX_CONFIG_CHECK dnl - WXRC_CHECK dnl - WX_STANDARD_OPTIONS dnl - WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS dnl - WX_DETECT_STANDARD_OPTION_VALUES dnl dnl SECTION B: wxWidgets-related utilities dnl - WX_LIKE_LIBNAME dnl - WX_ARG_ENABLE_YESNOAUTO dnl - WX_ARG_WITH_YESNOAUTO dnl dnl SECTION C: messages to the user dnl - WX_STANDARD_OPTIONS_SUMMARY_MSG dnl - WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN dnl - WX_STANDARD_OPTIONS_SUMMARY_MSG_END dnl - WX_BOOLOPT_SUMMARY dnl dnl The special "WX_DEBUG_CONFIGURE" variable can be set to 1 to enable extra dnl debug output on stdout from these macros. dnl =========================================================================== dnl --------------------------------------------------------------------------- dnl Macros for wxWidgets detection. Typically used in configure.in as: dnl dnl AC_ARG_ENABLE(...) dnl AC_ARG_WITH(...) dnl ... dnl WX_CONFIG_OPTIONS dnl ... dnl ... dnl WX_CONFIG_CHECK([2.6.0], [wxWin=1]) dnl if test "$wxWin" != 1; then dnl AC_MSG_ERROR([ dnl wxWidgets must be installed on your system dnl but wx-config script couldn't be found. dnl dnl Please check that wx-config is in path, the directory dnl where wxWidgets libraries are installed (returned by dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or dnl equivalent variable and wxWidgets version is 2.3.4 or above. dnl ]) dnl fi dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" dnl dnl LIBS="$LIBS $WX_LIBS" dnl dnl If you want to support standard --enable-debug/unicode/shared options, you dnl may do the following: dnl dnl ... dnl AC_CANONICAL_SYSTEM dnl dnl # define configure options dnl WX_CONFIG_OPTIONS dnl WX_STANDARD_OPTIONS([debug,unicode,shared,toolkit,wxshared]) dnl dnl # basic configure checks dnl ... dnl dnl # we want to always have DEBUG==WX_DEBUG and UNICODE==WX_UNICODE dnl WX_DEBUG=$DEBUG dnl WX_UNICODE=$UNICODE dnl dnl WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS dnl WX_CONFIG_CHECK([2.8.0], [wxWin=1],,[html,core,net,base],[$WXCONFIG_FLAGS]) dnl WX_DETECT_STANDARD_OPTION_VALUES dnl dnl # write the output files dnl AC_CONFIG_FILES([Makefile ...]) dnl AC_OUTPUT dnl dnl # optional: just to show a message to the user dnl WX_STANDARD_OPTIONS_SUMMARY_MSG dnl dnl --------------------------------------------------------------------------- dnl --------------------------------------------------------------------------- dnl WX_CONFIG_OPTIONS dnl dnl adds support for --wx-prefix, --wx-exec-prefix, --with-wxdir and dnl --wx-config command line options dnl --------------------------------------------------------------------------- AC_DEFUN([WX_CONFIG_OPTIONS], [ AC_ARG_WITH(wxdir, [ --with-wxdir=PATH Use uninstalled version of wxWidgets in PATH], [ wx_config_name="$withval/wx-config" wx_config_args="--inplace"]) AC_ARG_WITH(wx-config, [ --with-wx-config=CONFIG wx-config script to use (optional)], wx_config_name="$withval" ) AC_ARG_WITH(wx-prefix, [ --with-wx-prefix=PREFIX Prefix where wxWidgets is installed (optional)], wx_config_prefix="$withval", wx_config_prefix="") AC_ARG_WITH(wx-exec-prefix, [ --with-wx-exec-prefix=PREFIX Exec prefix where wxWidgets is installed (optional)], wx_config_exec_prefix="$withval", wx_config_exec_prefix="") ]) dnl Helper macro for checking if wx version is at least $1.$2.$3, set's dnl wx_ver_ok=yes if it is: AC_DEFUN([_WX_PRIVATE_CHECK_VERSION], [ wx_ver_ok="" if test "x$WX_VERSION" != x ; then if test $wx_config_major_version -gt $1; then wx_ver_ok=yes else if test $wx_config_major_version -eq $1; then if test $wx_config_minor_version -gt $2; then wx_ver_ok=yes else if test $wx_config_minor_version -eq $2; then if test $wx_config_micro_version -ge $3; then wx_ver_ok=yes fi fi fi fi fi fi ]) dnl --------------------------------------------------------------------------- dnl WX_CONFIG_CHECK(VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND dnl [, WX-LIBS [, ADDITIONAL-WX-CONFIG-FLAGS]]]]) dnl dnl Test for wxWidgets, and define WX_C*FLAGS, WX_LIBS and WX_LIBS_STATIC dnl (the latter is for static linking against wxWidgets). Set WX_CONFIG_NAME dnl environment variable to override the default name of the wx-config script dnl to use. Set WX_CONFIG_PATH to specify the full path to wx-config - in this dnl case the macro won't even waste time on tests for its existence. dnl dnl Optional WX-LIBS argument contains comma- or space-separated list of dnl wxWidgets libraries to link against. If it is not specified then WX_LIBS dnl and WX_LIBS_STATIC will contain flags to link with all of the core dnl wxWidgets libraries. dnl dnl Optional ADDITIONAL-WX-CONFIG-FLAGS argument is appended to wx-config dnl invocation command in present. It can be used to fine-tune lookup of dnl best wxWidgets build available. dnl dnl Example use: dnl WX_CONFIG_CHECK([2.6.0], [wxWin=1], [wxWin=0], [html,core,net] dnl [--unicode --debug]) dnl --------------------------------------------------------------------------- dnl dnl Get the cflags and libraries from the wx-config script dnl AC_DEFUN([WX_CONFIG_CHECK], [ dnl do we have wx-config name: it can be wx-config or wxd-config or ... if test x${WX_CONFIG_NAME+set} != xset ; then WX_CONFIG_NAME=wx-config fi if test "x$wx_config_name" != x ; then WX_CONFIG_NAME="$wx_config_name" fi dnl deal with optional prefixes if test x$wx_config_exec_prefix != x ; then wx_config_args="$wx_config_args --exec-prefix=$wx_config_exec_prefix" WX_LOOKUP_PATH="$wx_config_exec_prefix/bin" fi if test x$wx_config_prefix != x ; then wx_config_args="$wx_config_args --prefix=$wx_config_prefix" WX_LOOKUP_PATH="$WX_LOOKUP_PATH:$wx_config_prefix/bin" fi if test "$cross_compiling" = "yes"; then wx_config_args="$wx_config_args --host=$host_alias" fi dnl don't search the PATH if WX_CONFIG_NAME is absolute filename if test -x "$WX_CONFIG_NAME" ; then AC_MSG_CHECKING(for wx-config) WX_CONFIG_PATH="$WX_CONFIG_NAME" AC_MSG_RESULT($WX_CONFIG_PATH) else AC_PATH_PROG(WX_CONFIG_PATH, $WX_CONFIG_NAME, no, "$WX_LOOKUP_PATH:$PATH") fi if test "$WX_CONFIG_PATH" != "no" ; then WX_VERSION="" min_wx_version=ifelse([$1], ,2.2.1,$1) if test -z "$5" ; then AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version]) else AC_MSG_CHECKING([for wxWidgets version >= $min_wx_version ($5)]) fi dnl don't add the libraries ($4) to this variable as this would result in dnl an error when it's used with --version below WX_CONFIG_WITH_ARGS="$WX_CONFIG_PATH $wx_config_args $5" WX_VERSION=`$WX_CONFIG_WITH_ARGS --version 2>/dev/null` wx_config_major_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` wx_config_minor_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` wx_config_micro_version=`echo $WX_VERSION | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` wx_requested_major_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` wx_requested_minor_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` wx_requested_micro_version=`echo $min_wx_version | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` _WX_PRIVATE_CHECK_VERSION([$wx_requested_major_version], [$wx_requested_minor_version], [$wx_requested_micro_version]) if test -n "$wx_ver_ok"; then AC_MSG_RESULT(yes (version $WX_VERSION)) WX_LIBS=`$WX_CONFIG_WITH_ARGS --libs $4` dnl is this even still appropriate? --static is a real option now dnl and WX_CONFIG_WITH_ARGS is likely to contain it if that is dnl what the user actually wants, making this redundant at best. dnl For now keep it in case anyone actually used it in the past. AC_MSG_CHECKING([for wxWidgets static library]) WX_LIBS_STATIC=`$WX_CONFIG_WITH_ARGS --static --libs $4 2>/dev/null` if test "x$WX_LIBS_STATIC" = "x"; then AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) fi dnl starting with version 2.2.6 wx-config has --cppflags argument wx_has_cppflags="" if test $wx_config_major_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -gt 2; then wx_has_cppflags=yes else if test $wx_config_minor_version -eq 2; then if test $wx_config_micro_version -ge 6; then wx_has_cppflags=yes fi fi fi fi fi dnl starting with version 2.7.0 wx-config has --rescomp option wx_has_rescomp="" if test $wx_config_major_version -gt 2; then wx_has_rescomp=yes else if test $wx_config_major_version -eq 2; then if test $wx_config_minor_version -ge 7; then wx_has_rescomp=yes fi fi fi if test "x$wx_has_rescomp" = x ; then dnl cannot give any useful info for resource compiler WX_RESCOMP= else WX_RESCOMP=`$WX_CONFIG_WITH_ARGS --rescomp` fi if test "x$wx_has_cppflags" = x ; then dnl no choice but to define all flags like CFLAGS WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags $4` WX_CPPFLAGS=$WX_CFLAGS WX_CXXFLAGS=$WX_CFLAGS WX_CFLAGS_ONLY=$WX_CFLAGS WX_CXXFLAGS_ONLY=$WX_CFLAGS else dnl we have CPPFLAGS included in CFLAGS included in CXXFLAGS WX_CPPFLAGS=`$WX_CONFIG_WITH_ARGS --cppflags $4` WX_CXXFLAGS=`$WX_CONFIG_WITH_ARGS --cxxflags $4` WX_CFLAGS=`$WX_CONFIG_WITH_ARGS --cflags $4` WX_CFLAGS_ONLY=`echo $WX_CFLAGS | sed "s@^$WX_CPPFLAGS *@@"` WX_CXXFLAGS_ONLY=`echo $WX_CXXFLAGS | sed "s@^$WX_CFLAGS *@@"` fi ifelse([$2], , :, [$2]) else if test "x$WX_VERSION" = x; then dnl no wx-config at all AC_MSG_RESULT(no) else AC_MSG_RESULT(no (version $WX_VERSION is not new enough)) fi WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" if test ! -z "$5"; then wx_error_message=" The configuration you asked for $PACKAGE_NAME requires a wxWidgets build with the following settings: $5 but such build is not available. To see the wxWidgets builds available on this system, please use 'wx-config --list' command. To use the default build, returned by 'wx-config --selected-config', use the options with their 'auto' default values." fi wx_error_message=" The requested wxWidgets build couldn't be found. $wx_error_message If you still get this error, then check that 'wx-config' is in path, the directory where wxWidgets libraries are installed (returned by 'wx-config --libs' command) is in LD_LIBRARY_PATH or equivalent variable and wxWidgets version is $1 or above." ifelse([$3], , AC_MSG_ERROR([$wx_error_message]), [$3]) fi else WX_CFLAGS="" WX_CPPFLAGS="" WX_CXXFLAGS="" WX_LIBS="" WX_LIBS_STATIC="" WX_RESCOMP="" ifelse([$3], , :, [$3]) fi AC_SUBST(WX_CPPFLAGS) AC_SUBST(WX_CFLAGS) AC_SUBST(WX_CXXFLAGS) AC_SUBST(WX_CFLAGS_ONLY) AC_SUBST(WX_CXXFLAGS_ONLY) AC_SUBST(WX_LIBS) AC_SUBST(WX_LIBS_STATIC) AC_SUBST(WX_VERSION) AC_SUBST(WX_RESCOMP) dnl need to export also WX_VERSION_MINOR and WX_VERSION_MAJOR symbols dnl to support wxpresets bakefiles (we export also WX_VERSION_MICRO for completeness): WX_VERSION_MAJOR="$wx_config_major_version" WX_VERSION_MINOR="$wx_config_minor_version" WX_VERSION_MICRO="$wx_config_micro_version" AC_SUBST(WX_VERSION_MAJOR) AC_SUBST(WX_VERSION_MINOR) AC_SUBST(WX_VERSION_MICRO) ]) dnl --------------------------------------------------------------------------- dnl Get information on the wxrc program for making C++, Python and xrs dnl resource files. dnl dnl AC_ARG_ENABLE(...) dnl AC_ARG_WITH(...) dnl ... dnl WX_CONFIG_OPTIONS dnl ... dnl WX_CONFIG_CHECK(2.6.0, wxWin=1) dnl if test "$wxWin" != 1; then dnl AC_MSG_ERROR([ dnl wxWidgets must be installed on your system dnl but wx-config script couldn't be found. dnl dnl Please check that wx-config is in path, the directory dnl where wxWidgets libraries are installed (returned by dnl 'wx-config --libs' command) is in LD_LIBRARY_PATH or dnl equivalent variable and wxWidgets version is 2.6.0 or above. dnl ]) dnl fi dnl dnl WXRC_CHECK([HAVE_WXRC=1], [HAVE_WXRC=0]) dnl if test "x$HAVE_WXRC" != x1; then dnl AC_MSG_ERROR([ dnl The wxrc program was not installed or not found. dnl dnl Please check the wxWidgets installation. dnl ]) dnl fi dnl dnl CPPFLAGS="$CPPFLAGS $WX_CPPFLAGS" dnl CXXFLAGS="$CXXFLAGS $WX_CXXFLAGS_ONLY" dnl CFLAGS="$CFLAGS $WX_CFLAGS_ONLY" dnl dnl LDFLAGS="$LDFLAGS $WX_LIBS" dnl --------------------------------------------------------------------------- dnl --------------------------------------------------------------------------- dnl WXRC_CHECK([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) dnl dnl Test for wxWidgets' wxrc program for creating either C++, Python or XRS dnl resources. The variable WXRC will be set and substituted in the configure dnl script and Makefiles. dnl dnl Example use: dnl WXRC_CHECK([wxrc=1], [wxrc=0]) dnl --------------------------------------------------------------------------- dnl dnl wxrc program from the wx-config script dnl AC_DEFUN([WXRC_CHECK], [ AC_ARG_VAR([WXRC], [Path to wxWidget's wxrc resource compiler]) if test "x$WX_CONFIG_NAME" = x; then AC_MSG_ERROR([The wxrc tests must run after wxWidgets test.]) else AC_MSG_CHECKING([for wxrc]) if test "x$WXRC" = x ; then dnl wx-config --utility is a new addition to wxWidgets: _WX_PRIVATE_CHECK_VERSION(2,5,3) if test -n "$wx_ver_ok"; then WXRC=`$WX_CONFIG_WITH_ARGS --utility=wxrc` fi fi if test "x$WXRC" = x ; then AC_MSG_RESULT([not found]) ifelse([$2], , :, [$2]) else AC_MSG_RESULT([$WXRC]) ifelse([$1], , :, [$1]) fi AC_SUBST(WXRC) fi ]) dnl --------------------------------------------------------------------------- dnl WX_LIKE_LIBNAME([output-var] [prefix], [name]) dnl dnl Sets the "output-var" variable to the name of a library named with same dnl wxWidgets rule. dnl E.g. for output-var=='lib', name=='test', prefix='mine', sets dnl the $lib variable to: dnl 'mine_gtk2ud_test-2.8' dnl if WX_PORT=gtk2, WX_UNICODE=1, WX_DEBUG=1 and WX_RELEASE=28 dnl --------------------------------------------------------------------------- AC_DEFUN([WX_LIKE_LIBNAME], [ wx_temp="$2""_""$WX_PORT" dnl add the [u][d] string if test "$WX_UNICODE" = "1"; then wx_temp="$wx_temp""u" fi if test "$WX_DEBUG" = "1"; then wx_temp="$wx_temp""d" fi dnl complete the name of the lib wx_temp="$wx_temp""_""$3""-$WX_VERSION_MAJOR.$WX_VERSION_MINOR" dnl save it in the user's variable $1=$wx_temp ]) dnl --------------------------------------------------------------------------- dnl WX_ARG_ENABLE_YESNOAUTO/WX_ARG_WITH_YESNOAUTO dnl dnl Two little custom macros which define the ENABLE/WITH configure arguments. dnl Macro arguments: dnl $1 = the name of the --enable / --with feature dnl $2 = the name of the variable associated dnl $3 = the description of that feature dnl $4 = the default value for that feature dnl $5 = additional action to do in case option is given with "yes" value dnl --------------------------------------------------------------------------- AC_DEFUN([WX_ARG_ENABLE_YESNOAUTO], [AC_ARG_ENABLE($1, AC_HELP_STRING([--enable-$1], [$3 (default is $4)]), [], [enableval="$4"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --enable-$1 option]) if test "$enableval" = "yes" ; then AC_MSG_RESULT([yes]) $2=1 $5 elif test "$enableval" = "no" ; then AC_MSG_RESULT([no]) $2=0 elif test "$enableval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) $2="auto" else AC_MSG_ERROR([ Unrecognized option value (allowed values: yes, no, auto) ]) fi ]) AC_DEFUN([WX_ARG_WITH_YESNOAUTO], [AC_ARG_WITH($1, AC_HELP_STRING([--with-$1], [$3 (default is $4)]), [], [withval="$4"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --with-$1 option]) if test "$withval" = "yes" ; then AC_MSG_RESULT([yes]) $2=1 $5 dnl NB: by default we don't allow --with-$1=no option dnl since it does not make much sense ! elif test "$6" = "1" -a "$withval" = "no" ; then AC_MSG_RESULT([no]) $2=0 elif test "$withval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) $2="auto" else AC_MSG_ERROR([ Unrecognized option value (allowed values: yes, auto) ]) fi ]) dnl --------------------------------------------------------------------------- dnl WX_STANDARD_OPTIONS([options-to-add]) dnl dnl Adds to the configure script one or more of the following options: dnl --enable-[debug|unicode|shared|wxshared|wxdebug] dnl --with-[gtk|msw|motif|x11|mac|dfb] dnl --with-wxversion dnl Then checks for their presence and eventually set the DEBUG, UNICODE, SHARED, dnl PORT, WX_SHARED, WX_DEBUG, variables to one of the "yes", "no", "auto" values. dnl dnl Note that e.g. UNICODE != WX_UNICODE; the first is the value of the dnl --enable-unicode option (in boolean format) while the second indicates dnl if wxWidgets was built in Unicode mode (and still is in boolean format). dnl --------------------------------------------------------------------------- AC_DEFUN([WX_STANDARD_OPTIONS], [ dnl the following lines will expand to WX_ARG_ENABLE_YESNOAUTO calls if and only if dnl the $1 argument contains respectively the debug,unicode or shared options. dnl be careful here not to set debug flag if only "wxdebug" was specified ifelse(regexp([$1], [\bdebug]), [-1],, [WX_ARG_ENABLE_YESNOAUTO([debug], [DEBUG], [Build in debug mode], [auto])]) ifelse(index([$1], [unicode]), [-1],, [WX_ARG_ENABLE_YESNOAUTO([unicode], [UNICODE], [Build in Unicode mode], [auto])]) ifelse(regexp([$1], [\bshared]), [-1],, [WX_ARG_ENABLE_YESNOAUTO([shared], [SHARED], [Build as shared library], [auto])]) dnl WX_ARG_WITH_YESNOAUTO cannot be used for --with-toolkit since it's an option dnl which must be able to accept the auto|gtk1|gtk2|msw|... values ifelse(index([$1], [toolkit]), [-1],, [ AC_ARG_WITH([toolkit], AC_HELP_STRING([--with-toolkit], [Build against a specific wxWidgets toolkit (default is auto)]), [], [withval="auto"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --with-toolkit option]) if test "$withval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) TOOLKIT="auto" else TOOLKIT="$withval" dnl PORT must be one of the allowed values if test "$TOOLKIT" != "gtk1" -a "$TOOLKIT" != "gtk2" -a \ "$TOOLKIT" != "msw" -a "$TOOLKIT" != "motif" -a \ "$TOOLKIT" != "osx_carbon" -a "$TOOLKIT" != "osx_cocoa" -a \ "$TOOLKIT" != "dfb" -a "$TOOLKIT" != "x11"; then AC_MSG_ERROR([ Unrecognized option value (allowed values: auto, gtk1, gtk2, msw, motif, osx_carbon, osx_cocoa, dfb, x11) ]) fi AC_MSG_RESULT([$TOOLKIT]) fi ]) dnl ****** IMPORTANT ******* dnl Unlike for the UNICODE setting, you can build your program in dnl shared mode against a static build of wxWidgets. Thus we have the dnl following option which allows these mixtures. E.g. dnl dnl ./configure --disable-shared --with-wxshared dnl dnl will build your library in static mode against the first available dnl shared build of wxWidgets. dnl dnl Note that's not possible to do the viceversa: dnl dnl ./configure --enable-shared --without-wxshared dnl dnl Doing so you would try to build your library in shared mode against a static dnl build of wxWidgets. This is not possible (you would mix PIC and non PIC code) ! dnl A check for this combination of options is in WX_DETECT_STANDARD_OPTION_VALUES dnl (where we know what 'auto' should be expanded to). dnl dnl If you try to build something in ANSI mode against a UNICODE build dnl of wxWidgets or in RELEASE mode against a DEBUG build of wxWidgets, dnl then at best you'll get ton of linking errors ! dnl ************************ ifelse(index([$1], [wxshared]), [-1],, [ WX_ARG_WITH_YESNOAUTO( [wxshared], [WX_SHARED], [Force building against a shared build of wxWidgets, even if --disable-shared is given], [auto], [], [1]) ]) dnl Just like for SHARED and WX_SHARED it may happen that some adventurous dnl peoples will want to mix a wxWidgets release build with a debug build of dnl his app/lib. So, we have both DEBUG and WX_DEBUG variables. ifelse(index([$1], [wxdebug]), [-1],, [ WX_ARG_WITH_YESNOAUTO( [wxdebug], [WX_DEBUG], [Force building against a debug build of wxWidgets, even if --disable-debug is given], [auto], [], [1]) ]) dnl WX_ARG_WITH_YESNOAUTO cannot be used for --with-wxversion since it's an option dnl which accepts the "auto|2.6|2.7|2.8|2.9|3.0" etc etc values ifelse(index([$1], [wxversion]), [-1],, [ AC_ARG_WITH([wxversion], AC_HELP_STRING([--with-wxversion], [Build against a specific version of wxWidgets (default is auto)]), [], [withval="auto"]) dnl Show a message to the user about this option AC_MSG_CHECKING([for the --with-wxversion option]) if test "$withval" = "auto" ; then AC_MSG_RESULT([will be automatically detected]) WX_RELEASE="auto" else wx_requested_major_version=`echo $withval | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).*/\1/'` wx_requested_minor_version=`echo $withval | \ sed 's/\([[0-9]]*\).\([[0-9]]*\).*/\2/'` dnl both vars above must be exactly 1 digit if test "${#wx_requested_major_version}" != "1" -o \ "${#wx_requested_minor_version}" != "1" ; then AC_MSG_ERROR([ Unrecognized option value (allowed values: auto, 2.6, 2.7, 2.8, 2.9, 3.0) ]) fi WX_RELEASE="$wx_requested_major_version"".""$wx_requested_minor_version" AC_MSG_RESULT([$WX_RELEASE]) fi ]) if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] DEBUG: $DEBUG, WX_DEBUG: $WX_DEBUG" echo "[[dbg]] UNICODE: $UNICODE, WX_UNICODE: $WX_UNICODE" echo "[[dbg]] SHARED: $SHARED, WX_SHARED: $WX_SHARED" echo "[[dbg]] TOOLKIT: $TOOLKIT, WX_TOOLKIT: $WX_TOOLKIT" echo "[[dbg]] VERSION: $VERSION, WX_RELEASE: $WX_RELEASE" fi ]) dnl --------------------------------------------------------------------------- dnl WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS dnl dnl Sets the WXCONFIG_FLAGS string using the SHARED,DEBUG,UNICODE variable values dnl which are different from "auto". dnl Thus this macro needs to be called only once all options have been set. dnl --------------------------------------------------------------------------- AC_DEFUN([WX_CONVERT_STANDARD_OPTIONS_TO_WXCONFIG_FLAGS], [ if test "$WX_SHARED" = "1" ; then WXCONFIG_FLAGS="--static=no " elif test "$WX_SHARED" = "0" ; then WXCONFIG_FLAGS="--static=yes " fi if test "$WX_DEBUG" = "1" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--debug=yes " elif test "$WX_DEBUG" = "0" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--debug=no " fi dnl The user should have set WX_UNICODE=UNICODE if test "$WX_UNICODE" = "1" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--unicode=yes " elif test "$WX_UNICODE" = "0" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--unicode=no " fi if test "$TOOLKIT" != "auto" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--toolkit=$TOOLKIT " fi if test "$WX_RELEASE" != "auto" ; then WXCONFIG_FLAGS="$WXCONFIG_FLAGS""--version=$WX_RELEASE " fi dnl strip out the last space of the string WXCONFIG_FLAGS=${WXCONFIG_FLAGS% } if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] WXCONFIG_FLAGS: $WXCONFIG_FLAGS" fi ]) dnl --------------------------------------------------------------------------- dnl _WX_SELECTEDCONFIG_CHECKFOR([RESULTVAR], [STRING], [MSG] dnl [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) dnl dnl Outputs the given MSG. Then searches the given STRING in the wxWidgets dnl additional CPP flags and put the result of the search in WX_$RESULTVAR dnl also adding the "yes" or "no" message result to MSG. dnl --------------------------------------------------------------------------- AC_DEFUN([_WX_SELECTEDCONFIG_CHECKFOR], [ if test "$$1" = "auto" ; then dnl The user does not have particular preferences for this option; dnl so we will detect the wxWidgets relative build setting and use it AC_MSG_CHECKING([$3]) dnl set WX_$1 variable to 1 if the $WX_SELECTEDCONFIG contains the $2 dnl string or to 0 otherwise. dnl NOTE: 'expr match STRING REGEXP' cannot be used since on Mac it dnl doesn't work; we use 'expr STRING : REGEXP' instead WX_$1=$(expr "$WX_SELECTEDCONFIG" : ".*$2.*") if test "$WX_$1" != "0"; then WX_$1=1 AC_MSG_RESULT([yes]) ifelse([$4], , :, [$4]) else WX_$1=0 AC_MSG_RESULT([no]) ifelse([$5], , :, [$5]) fi else dnl Use the setting given by the user WX_$1=$$1 fi ]) dnl --------------------------------------------------------------------------- dnl WX_DETECT_STANDARD_OPTION_VALUES dnl dnl Detects the values of the following variables: dnl 1) WX_RELEASE dnl 2) WX_UNICODE dnl 3) WX_DEBUG dnl 4) WX_SHARED (and also WX_STATIC) dnl 5) WX_PORT dnl from the previously selected wxWidgets build; this macro in fact must be dnl called *after* calling the WX_CONFIG_CHECK macro. dnl dnl Note that the WX_VERSION_MAJOR, WX_VERSION_MINOR symbols are already set dnl by WX_CONFIG_CHECK macro dnl --------------------------------------------------------------------------- AC_DEFUN([WX_DETECT_STANDARD_OPTION_VALUES], [ dnl IMPORTANT: WX_VERSION contains all three major.minor.micro digits, dnl while WX_RELEASE only the major.minor ones. WX_RELEASE="$WX_VERSION_MAJOR""$WX_VERSION_MINOR" if test $WX_RELEASE -lt 26 ; then AC_MSG_ERROR([ Cannot detect the wxWidgets configuration for the selected wxWidgets build since its version is $WX_VERSION < 2.6.0; please install a newer version of wxWidgets. ]) fi dnl The wx-config we are using understands the "--selected_config" dnl option which returns an easy-parseable string ! WX_SELECTEDCONFIG=$($WX_CONFIG_WITH_ARGS --selected_config) if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] Using wx-config --selected-config" echo "[[dbg]] WX_SELECTEDCONFIG: $WX_SELECTEDCONFIG" fi dnl we could test directly for WX_SHARED with a line like: dnl _WX_SELECTEDCONFIG_CHECKFOR([SHARED], [shared], dnl [if wxWidgets was built in SHARED mode]) dnl but wx-config --selected-config DOES NOT outputs the 'shared' dnl word when wx was built in shared mode; it rather outputs the dnl 'static' word when built in static mode. if test $WX_SHARED = "1"; then STATIC=0 elif test $WX_SHARED = "0"; then STATIC=1 elif test $WX_SHARED = "auto"; then STATIC="auto" fi dnl Now set the WX_UNICODE, WX_DEBUG, WX_STATIC variables _WX_SELECTEDCONFIG_CHECKFOR([UNICODE], [unicode], [if wxWidgets was built with UNICODE enabled]) _WX_SELECTEDCONFIG_CHECKFOR([DEBUG], [debug], [if wxWidgets was built in DEBUG mode]) _WX_SELECTEDCONFIG_CHECKFOR([STATIC], [static], [if wxWidgets was built in STATIC mode]) dnl init WX_SHARED from WX_STATIC if test "$WX_STATIC" != "0"; then WX_SHARED=0 else WX_SHARED=1 fi AC_SUBST(WX_UNICODE) AC_SUBST(WX_DEBUG) AC_SUBST(WX_SHARED) dnl detect the WX_PORT to use if test "$TOOLKIT" = "auto" ; then dnl The user does not have particular preferences for this option; dnl so we will detect the wxWidgets relative build setting and use it AC_MSG_CHECKING([which wxWidgets toolkit was selected]) WX_GTKPORT1=$(expr "$WX_SELECTEDCONFIG" : ".*gtk1.*") WX_GTKPORT2=$(expr "$WX_SELECTEDCONFIG" : ".*gtk2.*") WX_MSWPORT=$(expr "$WX_SELECTEDCONFIG" : ".*msw.*") WX_MOTIFPORT=$(expr "$WX_SELECTEDCONFIG" : ".*motif.*") WX_OSXCOCOAPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_cocoa.*") WX_OSXCARBONPORT=$(expr "$WX_SELECTEDCONFIG" : ".*osx_carbon.*") WX_X11PORT=$(expr "$WX_SELECTEDCONFIG" : ".*x11.*") WX_DFBPORT=$(expr "$WX_SELECTEDCONFIG" : ".*dfb.*") WX_PORT="unknown" if test "$WX_GTKPORT1" != "0"; then WX_PORT="gtk1"; fi if test "$WX_GTKPORT2" != "0"; then WX_PORT="gtk2"; fi if test "$WX_MSWPORT" != "0"; then WX_PORT="msw"; fi if test "$WX_MOTIFPORT" != "0"; then WX_PORT="motif"; fi if test "$WX_OSXCOCOAPORT" != "0"; then WX_PORT="osx_cocoa"; fi if test "$WX_OSXCARBONPORT" != "0"; then WX_PORT="osx_carbon"; fi if test "$WX_X11PORT" != "0"; then WX_PORT="x11"; fi if test "$WX_DFBPORT" != "0"; then WX_PORT="dfb"; fi dnl NOTE: backward-compatible check for wx2.8; in wx2.9 the mac dnl ports are called 'osx_cocoa' and 'osx_carbon' (see above) WX_MACPORT=$(expr "$WX_SELECTEDCONFIG" : ".*mac.*") if test "$WX_MACPORT" != "0"; then WX_PORT="mac"; fi dnl check at least one of the WX_*PORT has been set ! if test "$WX_PORT" = "unknown" ; then AC_MSG_ERROR([ Cannot detect the currently installed wxWidgets port ! Please check your 'wx-config --cxxflags'... ]) fi AC_MSG_RESULT([$WX_PORT]) else dnl Use the setting given by the user if test -z "$TOOLKIT" ; then WX_PORT=$TOOLKIT else dnl try with PORT WX_PORT=$PORT fi fi AC_SUBST(WX_PORT) if test "$WX_DEBUG_CONFIGURE" = "1"; then echo "[[dbg]] Values of all WX_* options after final detection:" echo "[[dbg]] WX_DEBUG: $WX_DEBUG" echo "[[dbg]] WX_UNICODE: $WX_UNICODE" echo "[[dbg]] WX_SHARED: $WX_SHARED" echo "[[dbg]] WX_RELEASE: $WX_RELEASE" echo "[[dbg]] WX_PORT: $WX_PORT" fi dnl Avoid problem described in the WX_STANDARD_OPTIONS which happens when dnl the user gives the options: dnl ./configure --enable-shared --without-wxshared dnl or just do dnl ./configure --enable-shared dnl but there is only a static build of wxWidgets available. if test "$WX_SHARED" = "0" -a "$SHARED" = "1"; then AC_MSG_ERROR([ Cannot build shared library against a static build of wxWidgets ! This error happens because the wxWidgets build which was selected has been detected as static while you asked to build $PACKAGE_NAME as shared library and this is not possible. Use the '--disable-shared' option to build $PACKAGE_NAME as static library or '--with-wxshared' to use wxWidgets as shared library. ]) fi dnl now we can finally update the DEBUG,UNICODE,SHARED options dnl to their final values if they were set to 'auto' if test "$DEBUG" = "auto"; then DEBUG=$WX_DEBUG fi if test "$UNICODE" = "auto"; then UNICODE=$WX_UNICODE fi if test "$SHARED" = "auto"; then SHARED=$WX_SHARED fi if test "$TOOLKIT" = "auto"; then TOOLKIT=$WX_PORT fi dnl in case the user needs a BUILD=debug/release var... if test "$DEBUG" = "1"; then BUILD="debug" elif test "$DEBUG" = "0" -o "$DEBUG" = ""; then BUILD="release" fi dnl respect the DEBUG variable adding the optimize/debug flags dnl NOTE: the CXXFLAGS are merged together with the CPPFLAGS so we dnl don't need to set them, too if test "$DEBUG" = "1"; then CXXFLAGS="$CXXFLAGS -g -O0" CFLAGS="$CFLAGS -g -O0" else CXXFLAGS="$CXXFLAGS -O2" CFLAGS="$CFLAGS -O2" fi ]) dnl --------------------------------------------------------------------------- dnl WX_BOOLOPT_SUMMARY([name of the boolean variable to show summary for], dnl [what to print when var is 1], dnl [what to print when var is 0]) dnl dnl Prints $2 when variable $1 == 1 and prints $3 when variable $1 == 0. dnl This macro mainly exists just to make configure.ac scripts more readable. dnl dnl NOTE: you need to use the [" my message"] syntax for 2nd and 3rd arguments dnl if you want that m4 avoid to throw away the spaces prefixed to the dnl argument value. dnl --------------------------------------------------------------------------- AC_DEFUN([WX_BOOLOPT_SUMMARY], [ if test "x$$1" = "x1" ; then echo $2 elif test "x$$1" = "x0" ; then echo $3 else echo "$1 is $$1" fi ]) dnl --------------------------------------------------------------------------- dnl WX_STANDARD_OPTIONS_SUMMARY_MSG dnl dnl Shows a summary message to the user about the WX_* variable contents. dnl This macro is used typically at the end of the configure script. dnl --------------------------------------------------------------------------- AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG], [ echo echo " The wxWidgets build which will be used by $PACKAGE_NAME $PACKAGE_VERSION" echo " has the following settings:" WX_BOOLOPT_SUMMARY([WX_DEBUG], [" - DEBUG build"], [" - RELEASE build"]) WX_BOOLOPT_SUMMARY([WX_UNICODE], [" - UNICODE mode"], [" - ANSI mode"]) WX_BOOLOPT_SUMMARY([WX_SHARED], [" - SHARED mode"], [" - STATIC mode"]) echo " - VERSION: $WX_VERSION" echo " - PORT: $WX_PORT" ]) dnl --------------------------------------------------------------------------- dnl WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN, WX_STANDARD_OPTIONS_SUMMARY_MSG_END dnl dnl Like WX_STANDARD_OPTIONS_SUMMARY_MSG macro but these two macros also gives info dnl about the configuration of the package which used the wxpresets. dnl dnl Typical usage: dnl WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN dnl echo " - Package setting 1: $SETTING1" dnl echo " - Package setting 2: $SETTING1" dnl ... dnl WX_STANDARD_OPTIONS_SUMMARY_MSG_END dnl dnl --------------------------------------------------------------------------- AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG_BEGIN], [ echo echo " ----------------------------------------------------------------" echo " Configuration for $PACKAGE_NAME $PACKAGE_VERSION successfully completed." echo " Summary of main configuration settings for $PACKAGE_NAME:" WX_BOOLOPT_SUMMARY([DEBUG], [" - DEBUG build"], [" - RELEASE build"]) WX_BOOLOPT_SUMMARY([UNICODE], [" - UNICODE mode"], [" - ANSI mode"]) WX_BOOLOPT_SUMMARY([SHARED], [" - SHARED mode"], [" - STATIC mode"]) ]) AC_DEFUN([WX_STANDARD_OPTIONS_SUMMARY_MSG_END], [ WX_STANDARD_OPTIONS_SUMMARY_MSG echo echo " Now, just run make." echo " ----------------------------------------------------------------" echo ]) dnl --------------------------------------------------------------------------- dnl Deprecated macro wrappers dnl --------------------------------------------------------------------------- AC_DEFUN([AM_OPTIONS_WXCONFIG], [WX_CONFIG_OPTIONS]) AC_DEFUN([AM_PATH_WXCONFIG], [ WX_CONFIG_CHECK([$1],[$2],[$3],[$4],[$5]) ]) AC_DEFUN([AM_PATH_WXRC], [WXRC_CHECK([$1],[$2])]) fityk-1.3.1/release.sh000077500000000000000000000077201302634723100146300ustar00rootroot00000000000000#!/bin/bash version=1.3.1 MINGW_DIR=mingw-build win_setup_filename=$MINGW_DIR/all_files/Output/fityk-$version-setup.exe tarball_filename=fityk-$version.tar.bz2 if [ $# -eq 0 ]; then echo Version in this script is set to $version echo usage: $0 step_nr echo steps: echo a. update autotools files and m4 scripts from autoconf-archive echo 0. prepare new version and increase version number echo 1. run tests under valgrind echo "2. cd doc && make && make pdf" echo 3. make tarball: make dist-bzip2 echo 4. compile windows version and make installer echo 5. https://build.opensuse.org/project/show?project=home%3Awojdyr echo 8. "git tag -a v$version -m 'version $version'; git push --tags" echo 9. put docs on www exit fi echo echo Step $1 of the release procedure... echo echo -n '===>' if [ $1 = "a" ]; then echo update m4 scripts from autoconf-archive... ac_scripts="ax_lua.m4 ax_python_devel.m4 ax_lib_readline.m4 ax_pkg_swig.m4" for i in $ac_scripts; do curl "http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/$i" -o m4/$i done rm -r m4/libtool.m4 m4/lt* build-aux/* aclocal.m4 autoreconf -ifv elif [ $1 -eq 0 ]; then echo now the version in this script is: $version echo configure.ac: grep AC_INIT configure.ac echo doc/conf.py: grep 'version =' doc/conf.py echo doc/index.rst: grep 'Version ' doc/index.rst echo NEWS: head -4 NEWS | grep version echo elif [ $1 -eq 1 ]; then echo run tests and samples under valgrind... make check LOG_COMPILER="valgrind --error-exitcode=1" || exit valgrind --trace-children=yes --log-file=valgrind.log make check-scripts grep 'ERROR SUMMARY:' valgrind.log wxgui/fityk ../samples/nacl01.fit wxgui/fityk ../samples/SiC_Zn.fit elif [ $1 -eq 2 ]; then cd doc && make && make pdf elif [ $1 -eq 3 ]; then echo make tarball make dist-bzip2 #cd builds/ #make daily elif [ $1 -eq 4 ]; then echo Building MS Windows version in $MINGW_DIR unset GREP_OPTIONS # http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16259 set -e MDIR=$HOME/local/mingw32 BOOST_DIR=$HOME/local/src/boost_1_50_0 [ -d "$MINGW_DIR" ] || mkdir -p $MINGW_DIR cd "$MINGW_DIR" if ! [ -e Makefile ]; then ../configure --host=i686-w64-mingw32 \ CPPFLAGS="-I$BOOST_DIR -I$MDIR/include" \ CFLAGS="-O3" CXXFLAGS="-O3" \ LDFLAGS="-s -fno-keep-inline-dllexport -L$MDIR/lib" \ LUA52_FROM_SOURCE=yes \ --without-readline --with-wx-config=$MDIR/bin/wx-config \ --disable-static --enable-shared --enable-nlopt fi make -j2 || exit outdir=all_files mkdir -p $outdir/samples $outdir/fityk cp fityk.iss ../fityk.url ../COPYING ../TODO ../NEWS $outdir/ cp -r ../doc/html/ $outdir/ cp ../samples/*.fit ../samples/*.dat ../samples/*.lua \ ../samples/README $outdir/samples/ cp wxgui/.libs/*.exe cli/.libs/cfityk.exe \ fityk/.libs/libfityk-*.dll \ $MDIR/bin/libxy-*.dll $MDIR/bin/xyconv.exe $MDIR/bin/xyconvert.exe \ $MDIR/bin/libnlopt*.dll \ $MDIR/lib/wxbase30u_gcc_custom.dll \ $MDIR/lib/wxmsw30u_adv_gcc_custom.dll \ $MDIR/lib/wxmsw30u_core_gcc_custom.dll \ $MDIR/lib/wxmsw30u_stc_gcc_custom.dll \ $outdir/fityk/ #MINGW_DLL_DIR=/usr/i686-w64-mingw32/sys-root/mingw/bin #MINGW_DLL_DIR2=$MINGW_DLL_DIR MINGW_DLL_DIR=/usr/i686-w64-mingw32/lib MINGW_DLL_DIR2=/usr/lib/gcc/i686-w64-mingw32/5.3-win32 cp $MINGW_DLL_DIR/libwinpthread-1.dll \ $MINGW_DLL_DIR2/libgcc_s_sjlj-1.dll \ $MINGW_DLL_DIR2/libstdc++-6.dll \ $MINGW_DLL_DIR/zlib1.dll \ $outdir/fityk/ i686-w64-mingw32-strip $outdir/fityk/* echo everything is in: `pwd`/$outdir elif [ $1 -eq 9 ]; then #echo putting docs on www #echo destination: $WEB cd doc/ make all pdf echo "now upload PDF manual..." #echo "sending PDF manual..." #scp latex/fityk-manual.pdf $WEB/ #echo sending html #scp -r html/* $WEB/ #echo generating doxygen docs... #cd ../doxygen/ #doxygen #echo sending doxygen docs... #scp -r html/ $WEB/doxygen/ #cd .. else echo unexpected step number: $1 fi fityk-1.3.1/samples/000077500000000000000000000000001302634723100143075ustar00rootroot00000000000000fityk-1.3.1/samples/README000066400000000000000000000007351302634723100151740ustar00rootroot00000000000000 This directory contains small samples of data and scripts that are used to test the program. nacl01 - 'Hello world' sample SiC_Zn - Powder pattern sample read-shockley - fitting a single user-defined function enso - fitting sines and cosines (data from Southern Oscillation Index) test_syntax - testing the command parser, just a set of random commands hello.* - minimal examples of using libfityk from various languages cfityk.py - equivalent of cfityk written in Python fityk-1.3.1/samples/SiC_Zn.dat000066400000000000000000001051611302634723100161320ustar00rootroot0000000000000020.0 49 20.02 39 20.04 31 20.06 42 20.08 44 20.1 26 20.12 43 20.14 44 20.16 26 20.18 41 20.2 32 20.22 43 20.24 34 20.26 49 20.28 40 20.3 34 20.32 49 20.34 48 20.36 37 20.38 48 20.4 47 20.42 46 20.44 41 20.46 35 20.48 48 20.5 29 20.52 53 20.54 36 20.56 47 20.58 49 20.6 56 20.62 40 20.64 31 20.66 52 20.68 31 20.7 41 20.72 43 20.74 36 20.76 32 20.78 37 20.8 44 20.82 40 20.84 34 20.86 33 20.88 44 20.9 38 20.92 44 20.94 38 20.96 49 20.98 37 21.0 46 21.02 40 21.04 38 21.06 49 21.08 37 21.1 44 21.12 30 21.14 51 21.16 31 21.18 51 21.2 36 21.22 44 21.24 47 21.26 42 21.28 47 21.3 32 21.32 36 21.34 46 21.36 56 21.38 36 21.4 29 21.42 32 21.44 44 21.46 55 21.48 32 21.5 42 21.52 46 21.54 26 21.56 33 21.58 33 21.6 40 21.62 49 21.64 44 21.66 34 21.68 35 21.7 43 21.72 38 21.74 55 21.76 37 21.78 25 21.8 45 21.82 46 21.84 44 21.86 27 21.88 51 21.9 37 21.92 34 21.94 29 21.96 39 21.98 44 22.0 36 22.02 40 22.04 39 22.06 48 22.08 25 22.1 28 22.12 20 22.14 45 22.16 38 22.18 53 22.2 33 22.22 33 22.24 38 22.26 32 22.28 40 22.3 31 22.32 35 22.34 43 22.36 37 22.38 33 22.4 34 22.42 39 22.44 33 22.46 45 22.48 30 22.5 47 22.52 33 22.54 41 22.56 32 22.58 39 22.6 38 22.62 35 22.64 31 22.66 36 22.68 41 22.7 45 22.72 40 22.74 30 22.76 25 22.78 23 22.8 31 22.82 40 22.84 36 22.86 32 22.88 40 22.9 33 22.92 30 22.94 28 22.96 42 22.98 30 23.0 35 23.02 26 23.04 33 23.06 45 23.08 28 23.1 36 23.12 40 23.14 20 23.16 42 23.18 24 23.2 42 23.22 37 23.24 33 23.26 28 23.28 29 23.3 35 23.32 32 23.34 40 23.36 30 23.38 28 23.4 45 23.42 28 23.44 35 23.46 30 23.48 35 23.5 33 23.52 24 23.54 29 23.56 31 23.58 36 23.6 28 23.62 34 23.64 40 23.66 36 23.68 29 23.7 42 23.72 37 23.74 35 23.76 32 23.78 40 23.8 29 23.82 35 23.84 33 23.86 36 23.88 34 23.9 36 23.92 36 23.94 45 23.96 32 23.98 31 24.0 35 24.02 42 24.04 34 24.06 31 24.08 35 24.1 36 24.12 26 24.14 39 24.16 27 24.18 31 24.2 37 24.22 35 24.24 25 24.26 27 24.28 33 24.3 31 24.32 36 24.34 34 24.36 28 24.38 38 24.4 22 24.42 30 24.44 33 24.46 32 24.48 34 24.5 25 24.52 37 24.54 25 24.56 37 24.58 30 24.6 28 24.62 37 24.64 31 24.66 42 24.68 20 24.7 30 24.72 41 24.74 37 24.76 32 24.78 24 24.8 25 24.82 31 24.84 37 24.86 32 24.88 32 24.9 43 24.92 38 24.94 32 24.96 29 24.98 25 25.0 29 25.02 42 25.04 41 25.06 26 25.08 27 25.1 32 25.12 32 25.14 23 25.16 24 25.18 32 25.2 24 25.22 29 25.24 26 25.26 32 25.28 35 25.3 29 25.32 35 25.34 40 25.36 30 25.38 28 25.4 37 25.42 36 25.44 33 25.46 41 25.48 26 25.5 39 25.52 26 25.54 32 25.56 27 25.58 37 25.6 34 25.62 33 25.64 29 25.66 37 25.68 24 25.7 37 25.72 31 25.74 24 25.76 21 25.78 30 25.8 39 25.82 25 25.84 32 25.86 28 25.88 25 25.9 32 25.92 30 25.94 32 25.96 27 25.98 26 26.0 37 26.02 26 26.04 38 26.06 32 26.08 26 26.1 33 26.12 35 26.14 28 26.16 31 26.18 33 26.2 32 26.22 35 26.24 33 26.26 34 26.28 26 26.3 27 26.32 19 26.34 27 26.36 33 26.38 30 26.4 35 26.42 32 26.44 22 26.46 22 26.48 37 26.5 30 26.52 26 26.54 24 26.56 27 26.58 39 26.6 27 26.62 33 26.64 31 26.66 35 26.68 40 26.7 41 26.72 47 26.74 46 26.76 52 26.78 54 26.8 58 26.82 47 26.84 44 26.86 41 26.88 29 26.9 25 26.92 36 26.94 31 26.96 28 26.98 34 27.0 31 27.02 24 27.04 19 27.06 25 27.08 26 27.1 28 27.12 26 27.14 30 27.16 31 27.18 24 27.2 26 27.22 21 27.24 26 27.26 30 27.28 22 27.3 29 27.32 34 27.34 21 27.36 20 27.38 28 27.4 35 27.42 29 27.44 25 27.46 28 27.48 25 27.5 30 27.52 36 27.54 27 27.56 32 27.58 22 27.6 35 27.62 28 27.64 30 27.66 27 27.68 26 27.7 23 27.72 29 27.74 30 27.76 22 27.78 26 27.8 26 27.82 30 27.84 31 27.86 17 27.88 27 27.9 26 27.92 26 27.94 31 27.96 20 27.98 25 28.0 25 28.02 23 28.04 17 28.06 34 28.08 38 28.1 30 28.12 26 28.14 28 28.16 13 28.18 26 28.2 21 28.22 30 28.24 26 28.26 24 28.28 17 28.3 27 28.32 28 28.34 27 28.36 24 28.38 20 28.4 26 28.42 34 28.44 35 28.46 32 28.48 33 28.5 31 28.52 25 28.54 24 28.56 28 28.58 34 28.6 25 28.62 26 28.64 18 28.66 32 28.68 28 28.7 20 28.72 29 28.74 17 28.76 26 28.78 24 28.8 30 28.82 20 28.84 33 28.86 26 28.88 29 28.9 20 28.92 26 28.94 22 28.96 26 28.98 30 29.0 24 29.02 22 29.04 29 29.06 28 29.08 35 29.1 18 29.12 27 29.14 34 29.16 21 29.18 31 29.2 26 29.22 28 29.24 23 29.26 31 29.28 16 29.3 26 29.32 20 29.34 30 29.36 22 29.38 28 29.4 20 29.42 41 29.44 27 29.46 19 29.48 26 29.5 24 29.52 27 29.54 31 29.56 25 29.58 25 29.6 29 29.62 27 29.64 32 29.66 32 29.68 28 29.7 41 29.72 26 29.74 30 29.76 25 29.78 19 29.8 28 29.82 24 29.84 34 29.86 21 29.88 25 29.9 25 29.92 17 29.94 22 29.96 30 29.98 26 30.0 34 30.02 32 30.04 18 30.06 35 30.08 23 30.1 28 30.12 28 30.14 24 30.16 43 30.18 24 30.2 30 30.22 25 30.24 19 30.26 23 30.28 28 30.3 30 30.32 24 30.34 28 30.36 31 30.38 20 30.4 29 30.42 21 30.44 26 30.46 18 30.48 21 30.5 17 30.52 27 30.54 24 30.56 28 30.58 31 30.6 16 30.62 39 30.64 16 30.66 22 30.68 33 30.7 25 30.72 21 30.74 28 30.76 27 30.78 26 30.8 29 30.82 26 30.84 18 30.86 24 30.88 20 30.9 32 30.92 27 30.94 23 30.96 19 30.98 23 31.0 31 31.02 30 31.04 16 31.06 29 31.08 20 31.1 29 31.12 19 31.14 25 31.16 30 31.18 23 31.2 20 31.22 26 31.24 29 31.26 25 31.28 36 31.3 25 31.32 25 31.34 37 31.36 38 31.38 27 31.4 28 31.42 26 31.44 19 31.46 21 31.48 36 31.5 22 31.52 34 31.54 33 31.56 25 31.58 19 31.6 22 31.62 31 31.64 28 31.66 28 31.68 35 31.7 32 31.72 33 31.74 27 31.76 32 31.78 36 31.8 28 31.82 25 31.84 38 31.86 21 31.88 22 31.9 24 31.92 31 31.94 25 31.96 25 31.98 32 32.0 28 32.02 27 32.04 27 32.06 25 32.08 25 32.1 27 32.12 25 32.14 28 32.16 23 32.18 36 32.2 22 32.22 26 32.24 18 32.26 30 32.28 35 32.3 34 32.32 36 32.34 35 32.36 25 32.38 25 32.4 29 32.42 33 32.44 36 32.46 26 32.48 40 32.5 28 32.52 31 32.54 21 32.56 25 32.58 33 32.6 25 32.62 28 32.64 37 32.66 32 32.68 31 32.7 38 32.72 26 32.74 28 32.76 39 32.78 35 32.8 29 32.82 39 32.84 16 32.86 29 32.88 41 32.9 31 32.92 34 32.94 25 32.96 32 32.98 32 33.0 41 33.02 35 33.04 25 33.06 28 33.08 36 33.1 28 33.12 38 33.14 26 33.16 37 33.18 37 33.2 28 33.22 37 33.24 27 33.26 28 33.28 34 33.3 40 33.32 31 33.34 29 33.36 45 33.38 29 33.4 45 33.42 39 33.44 41 33.46 41 33.48 47 33.5 32 33.52 34 33.54 49 33.56 47 33.58 43 33.6 32 33.62 42 33.64 38 33.66 43 33.68 40 33.7 39 33.72 45 33.74 50 33.76 48 33.78 54 33.8 51 33.82 52 33.84 44 33.86 38 33.88 58 33.9 49 33.92 44 33.94 38 33.96 57 33.98 45 34.0 47 34.02 43 34.04 51 34.06 53 34.08 57 34.1 40 34.12 52 34.14 41 34.16 48 34.18 51 34.2 64 34.22 60 34.24 49 34.26 51 34.28 56 34.3 51 34.32 55 34.34 61 34.36 47 34.38 52 34.4 67 34.42 64 34.44 49 34.46 41 34.48 51 34.5 50 34.52 45 34.54 45 34.56 55 34.58 71 34.6 62 34.62 64 34.64 57 34.66 60 34.68 53 34.7 58 34.72 62 34.74 50 34.76 71 34.78 74 34.8 61 34.82 70 34.84 84 34.86 74 34.88 84 34.9 80 34.92 58 34.94 75 34.96 78 34.98 73 35.0 82 35.02 74 35.04 67 35.06 88 35.08 89 35.1 72 35.12 66 35.14 75 35.16 80 35.18 98 35.2 87 35.22 99 35.24 88 35.26 108 35.28 100 35.3 107 35.32 117 35.34 91 35.36 112 35.38 117 35.4 122 35.42 102 35.44 135 35.46 130 35.48 131 35.5 146 35.52 167 35.54 153 35.56 161 35.58 163 35.6 141 35.62 161 35.64 133 35.66 155 35.68 163 35.7 167 35.72 133 35.74 171 35.76 172 35.78 142 35.8 158 35.82 139 35.84 127 35.86 149 35.88 145 35.9 120 35.92 148 35.94 141 35.96 142 35.98 141 36.0 156 36.02 122 36.04 142 36.06 138 36.08 169 36.1 147 36.12 151 36.14 154 36.16 137 36.18 167 36.2 165 36.22 160 36.24 182 36.26 206 36.28 233 36.3 209 36.32 250 36.34 266 36.36 283 36.38 291 36.4 310 36.42 254 36.44 280 36.46 254 36.48 281 36.5 275 36.52 249 36.54 257 36.56 239 36.58 240 36.6 238 36.62 212 36.64 201 36.66 172 36.68 173 36.7 169 36.72 159 36.74 137 36.76 144 36.78 153 36.8 137 36.82 121 36.84 94 36.86 117 36.88 116 36.9 130 36.92 92 36.94 104 36.96 96 36.98 103 37.0 84 37.02 86 37.04 89 37.06 81 37.08 85 37.1 68 37.12 66 37.14 75 37.16 68 37.18 66 37.2 60 37.22 72 37.24 89 37.26 54 37.28 63 37.3 69 37.32 75 37.34 64 37.36 66 37.38 63 37.4 65 37.42 62 37.44 63 37.46 59 37.48 58 37.5 69 37.52 50 37.54 48 37.56 52 37.58 62 37.6 52 37.62 48 37.64 52 37.66 59 37.68 71 37.7 59 37.72 52 37.74 58 37.76 69 37.78 46 37.8 45 37.82 58 37.84 58 37.86 48 37.88 49 37.9 52 37.92 62 37.94 53 37.96 49 37.98 43 38.0 54 38.02 50 38.04 59 38.06 52 38.08 57 38.1 42 38.12 48 38.14 41 38.16 63 38.18 51 38.2 67 38.22 64 38.24 51 38.26 62 38.28 54 38.3 57 38.32 63 38.34 56 38.36 60 38.38 60 38.4 62 38.42 69 38.44 53 38.46 76 38.48 72 38.5 63 38.52 59 38.54 72 38.56 75 38.58 83 38.6 91 38.62 86 38.64 96 38.66 96 38.68 94 38.7 95 38.72 131 38.74 147 38.76 122 38.78 155 38.8 177 38.82 174 38.84 218 38.86 214 38.88 228 38.9 218 38.92 232 38.94 248 38.96 233 38.98 232 39.0 217 39.02 187 39.04 178 39.06 167 39.08 167 39.1 115 39.12 125 39.14 113 39.16 108 39.18 113 39.2 101 39.22 72 39.24 83 39.26 80 39.28 71 39.3 79 39.32 55 39.34 65 39.36 72 39.38 71 39.4 66 39.42 61 39.44 68 39.46 55 39.48 63 39.5 52 39.52 63 39.54 42 39.56 61 39.58 58 39.6 51 39.62 61 39.64 53 39.66 46 39.68 42 39.7 53 39.72 54 39.74 55 39.76 44 39.78 53 39.8 40 39.82 42 39.84 51 39.86 53 39.88 47 39.9 55 39.92 54 39.94 51 39.96 47 39.98 55 40.0 58 40.02 36 40.04 45 40.06 39 40.08 33 40.1 48 40.12 41 40.14 50 40.16 51 40.18 41 40.2 49 40.22 53 40.24 54 40.26 51 40.28 53 40.3 50 40.32 45 40.34 54 40.36 48 40.38 52 40.4 42 40.42 37 40.44 43 40.46 61 40.48 36 40.5 39 40.52 57 40.54 53 40.56 44 40.58 52 40.6 35 40.62 44 40.64 60 40.66 50 40.68 41 40.7 44 40.72 45 40.74 53 40.76 44 40.78 57 40.8 34 40.82 49 40.84 47 40.86 58 40.88 37 40.9 51 40.92 41 40.94 62 40.96 45 40.98 47 41.0 47 41.02 46 41.04 54 41.06 43 41.08 57 41.1 55 41.12 55 41.14 35 41.16 39 41.18 49 41.2 51 41.22 50 41.24 71 41.26 50 41.28 49 41.3 48 41.32 50 41.34 45 41.36 41 41.38 50 41.4 65 41.42 59 41.44 51 41.46 58 41.48 67 41.5 53 41.52 58 41.54 58 41.56 56 41.58 50 41.6 66 41.62 67 41.64 62 41.66 63 41.68 63 41.7 54 41.72 64 41.74 52 41.76 58 41.78 62 41.8 57 41.82 65 41.84 65 41.86 52 41.88 49 41.9 47 41.92 61 41.94 60 41.96 56 41.98 49 42.0 76 42.02 59 42.04 45 42.06 67 42.08 67 42.1 64 42.12 64 42.14 72 42.16 75 42.18 60 42.2 75 42.22 71 42.24 75 42.26 87 42.28 73 42.3 82 42.32 65 42.34 77 42.36 87 42.38 97 42.4 80 42.42 82 42.44 100 42.46 91 42.48 85 42.5 89 42.52 102 42.54 121 42.56 112 42.58 113 42.6 123 42.62 124 42.64 117 42.66 125 42.68 152 42.7 141 42.72 141 42.74 171 42.76 181 42.78 172 42.8 181 42.82 180 42.84 238 42.86 200 42.88 248 42.9 292 42.92 295 42.94 307 42.96 362 42.98 406 43.0 461 43.02 491 43.04 524 43.06 626 43.08 607 43.1 733 43.12 786 43.14 854 43.16 900 43.18 893 43.2 926 43.22 907 43.24 858 43.26 836 43.28 772 43.3 731 43.32 702 43.34 622 43.36 549 43.38 462 43.4 398 43.42 404 43.44 347 43.46 294 43.48 277 43.5 251 43.52 231 43.54 224 43.56 212 43.58 202 43.6 166 43.62 136 43.64 152 43.66 146 43.68 131 43.7 136 43.72 121 43.74 107 43.76 118 43.78 99 43.8 99 43.82 95 43.84 74 43.86 77 43.88 82 43.9 75 43.92 91 43.94 69 43.96 64 43.98 59 44.0 48 44.02 52 44.04 53 44.06 63 44.08 66 44.1 58 44.12 47 44.14 62 44.16 53 44.18 55 44.2 58 44.22 63 44.24 54 44.26 36 44.28 51 44.3 47 44.32 51 44.34 49 44.36 43 44.38 47 44.4 38 44.42 41 44.44 56 44.46 35 44.48 42 44.5 44 44.52 46 44.54 49 44.56 47 44.58 42 44.6 44 44.62 42 44.64 42 44.66 31 44.68 32 44.7 39 44.72 33 44.74 42 44.76 21 44.78 27 44.8 34 44.82 36 44.84 23 44.86 37 44.88 36 44.9 29 44.92 30 44.94 24 44.96 41 44.98 29 45.0 33 45.02 32 45.04 37 45.06 23 45.08 29 45.1 45 45.12 21 45.14 22 45.16 35 45.18 24 45.2 27 45.22 30 45.24 36 45.26 23 45.28 27 45.3 22 45.32 33 45.34 23 45.36 23 45.38 28 45.4 28 45.42 38 45.44 37 45.46 23 45.48 22 45.5 36 45.52 36 45.54 17 45.56 30 45.58 28 45.6 25 45.62 25 45.64 24 45.66 34 45.68 31 45.7 23 45.72 33 45.74 32 45.76 21 45.78 30 45.8 27 45.82 30 45.84 24 45.86 28 45.88 25 45.9 17 45.92 31 45.94 22 45.96 13 45.98 29 46.0 28 46.02 21 46.04 22 46.06 22 46.08 24 46.1 25 46.12 37 46.14 18 46.16 25 46.18 24 46.2 18 46.22 29 46.24 33 46.26 20 46.28 25 46.3 29 46.32 26 46.34 24 46.36 23 46.38 19 46.4 19 46.42 19 46.44 28 46.46 26 46.48 18 46.5 27 46.52 28 46.54 28 46.56 21 46.58 23 46.6 21 46.62 22 46.64 19 46.66 28 46.68 30 46.7 26 46.72 18 46.74 25 46.76 23 46.78 20 46.8 28 46.82 19 46.84 22 46.86 21 46.88 20 46.9 30 46.92 22 46.94 26 46.96 18 46.98 29 47.0 30 47.02 38 47.04 25 47.06 29 47.08 22 47.1 15 47.12 21 47.14 24 47.16 27 47.18 18 47.2 15 47.22 21 47.24 26 47.26 25 47.28 22 47.3 24 47.32 21 47.34 20 47.36 20 47.38 21 47.4 22 47.42 19 47.44 19 47.46 22 47.48 33 47.5 16 47.52 30 47.54 22 47.56 18 47.58 21 47.6 26 47.62 31 47.64 21 47.66 17 47.68 18 47.7 18 47.72 22 47.74 16 47.76 28 47.78 16 47.8 19 47.82 18 47.84 17 47.86 16 47.88 27 47.9 21 47.92 21 47.94 21 47.96 26 47.98 15 48.0 17 48.02 32 48.04 24 48.06 20 48.08 14 48.1 23 48.12 24 48.14 24 48.16 13 48.18 22 48.2 15 48.22 19 48.24 24 48.26 21 48.28 18 48.3 14 48.32 30 48.34 30 48.36 17 48.38 27 48.4 13 48.42 19 48.44 24 48.46 17 48.48 25 48.5 18 48.52 21 48.54 18 48.56 23 48.58 12 48.6 17 48.62 29 48.64 18 48.66 18 48.68 22 48.7 16 48.72 20 48.74 17 48.76 18 48.78 12 48.8 17 48.82 19 48.84 30 48.86 26 48.88 13 48.9 21 48.92 15 48.94 18 48.96 18 48.98 23 49.0 23 49.02 19 49.04 20 49.06 19 49.08 16 49.1 22 49.12 19 49.14 20 49.16 23 49.18 21 49.2 20 49.22 19 49.24 19 49.26 22 49.28 16 49.3 20 49.32 22 49.34 22 49.36 20 49.38 20 49.4 32 49.42 22 49.44 23 49.46 20 49.48 16 49.5 20 49.52 20 49.54 19 49.56 18 49.58 17 49.6 17 49.62 24 49.64 24 49.66 20 49.68 14 49.7 24 49.72 18 49.74 13 49.76 14 49.78 16 49.8 23 49.82 15 49.84 26 49.86 18 49.88 21 49.9 16 49.92 18 49.94 18 49.96 16 49.98 18 50.0 18 50.02 16 50.04 24 50.06 15 50.08 27 50.1 27 50.12 18 50.14 16 50.16 16 50.18 23 50.2 21 50.22 23 50.24 24 50.26 17 50.28 15 50.3 22 50.32 17 50.34 15 50.36 19 50.38 22 50.4 22 50.42 25 50.44 21 50.46 16 50.48 14 50.5 18 50.52 18 50.54 18 50.56 22 50.58 27 50.6 17 50.62 15 50.64 15 50.66 22 50.68 12 50.7 5 50.72 23 50.74 24 50.76 14 50.78 17 50.8 20 50.82 16 50.84 21 50.86 23 50.88 15 50.9 17 50.92 17 50.94 18 50.96 33 50.98 13 51.0 25 51.02 12 51.04 15 51.06 18 51.08 18 51.1 16 51.12 14 51.14 11 51.16 24 51.18 19 51.2 16 51.22 18 51.24 18 51.26 14 51.28 30 51.3 19 51.32 13 51.34 18 51.36 16 51.38 18 51.4 22 51.42 15 51.44 20 51.46 18 51.48 25 51.5 19 51.52 21 51.54 20 51.56 18 51.58 24 51.6 15 51.62 15 51.64 13 51.66 9 51.68 18 51.7 16 51.72 13 51.74 12 51.76 20 51.78 14 51.8 17 51.82 18 51.84 18 51.86 17 51.88 27 51.9 12 51.92 20 51.94 18 51.96 23 51.98 22 52.0 15 52.02 14 52.04 24 52.06 19 52.08 10 52.1 20 52.12 30 52.14 18 52.16 22 52.18 24 52.2 22 52.22 21 52.24 21 52.26 23 52.28 25 52.3 22 52.32 22 52.34 17 52.36 17 52.38 13 52.4 24 52.42 17 52.44 14 52.46 20 52.48 24 52.5 21 52.52 23 52.54 23 52.56 16 52.58 30 52.6 11 52.62 19 52.64 18 52.66 22 52.68 21 52.7 26 52.72 20 52.74 18 52.76 25 52.78 24 52.8 26 52.82 25 52.84 24 52.86 16 52.88 18 52.9 31 52.92 21 52.94 26 52.96 18 52.98 28 53.0 22 53.02 24 53.04 18 53.06 25 53.08 24 53.1 27 53.12 19 53.14 23 53.16 15 53.18 26 53.2 22 53.22 23 53.24 28 53.26 24 53.28 15 53.3 29 53.32 25 53.34 17 53.36 30 53.38 24 53.4 22 53.42 23 53.44 17 53.46 33 53.48 21 53.5 20 53.52 36 53.54 26 53.56 29 53.58 24 53.6 30 53.62 31 53.64 18 53.66 26 53.68 30 53.7 22 53.72 26 53.74 23 53.76 24 53.78 32 53.8 28 53.82 33 53.84 24 53.86 32 53.88 38 53.9 36 53.92 35 53.94 36 53.96 33 53.98 30 54.0 41 54.02 43 54.04 50 54.06 45 54.08 47 54.1 63 54.12 49 54.14 61 54.16 76 54.18 60 54.2 89 54.22 89 54.24 103 54.26 92 54.28 88 54.3 100 54.32 118 54.34 132 54.36 131 54.38 120 54.4 113 54.42 140 54.44 103 54.46 122 54.48 103 54.5 88 54.52 106 54.54 64 54.56 101 54.58 80 54.6 94 54.62 90 54.64 72 54.66 66 54.68 61 54.7 47 54.72 49 54.74 49 54.76 49 54.78 46 54.8 47 54.82 48 54.84 60 54.86 35 54.88 34 54.9 37 54.92 40 54.94 45 54.96 31 54.98 30 55.0 25 55.02 32 55.04 25 55.06 42 55.08 31 55.1 24 55.12 35 55.14 27 55.16 37 55.18 28 55.2 25 55.22 30 55.24 26 55.26 26 55.28 17 55.3 17 55.32 21 55.34 19 55.36 34 55.38 23 55.4 28 55.42 28 55.44 18 55.46 22 55.48 26 55.5 28 55.52 28 55.54 21 55.56 23 55.58 32 55.6 22 55.62 32 55.64 30 55.66 24 55.68 33 55.7 17 55.72 25 55.74 21 55.76 19 55.78 12 55.8 26 55.82 27 55.84 22 55.86 16 55.88 18 55.9 27 55.92 26 55.94 16 55.96 18 55.98 20 56.0 17 56.02 23 56.04 26 56.06 23 56.08 22 56.1 15 56.12 20 56.14 19 56.16 29 56.18 24 56.2 24 56.22 25 56.24 28 56.26 21 56.28 17 56.3 24 56.32 15 56.34 17 56.36 16 56.38 14 56.4 25 56.42 19 56.44 18 56.46 24 56.48 19 56.5 14 56.52 24 56.54 25 56.56 28 56.58 18 56.6 16 56.62 21 56.64 20 56.66 25 56.68 20 56.7 24 56.72 28 56.74 27 56.76 26 56.78 22 56.8 20 56.82 26 56.84 26 56.86 15 56.88 18 56.9 14 56.92 16 56.94 13 56.96 21 56.98 26 57.0 31 57.02 22 57.04 14 57.06 26 57.08 27 57.1 23 57.12 20 57.14 19 57.16 18 57.18 26 57.2 15 57.22 32 57.24 24 57.26 25 57.28 24 57.3 25 57.32 25 57.34 19 57.36 30 57.38 22 57.4 22 57.42 24 57.44 24 57.46 18 57.48 20 57.5 18 57.52 18 57.54 25 57.56 19 57.58 20 57.6 17 57.62 24 57.64 20 57.66 22 57.68 23 57.7 22 57.72 23 57.74 26 57.76 27 57.78 27 57.8 23 57.82 26 57.84 18 57.86 16 57.88 19 57.9 25 57.92 25 57.94 21 57.96 22 57.98 28 58.0 16 58.02 27 58.04 22 58.06 17 58.08 27 58.1 19 58.12 20 58.14 16 58.16 23 58.18 19 58.2 29 58.22 22 58.24 26 58.26 30 58.28 36 58.3 31 58.32 29 58.34 25 58.36 28 58.38 18 58.4 30 58.42 24 58.44 29 58.46 28 58.48 27 58.5 33 58.52 32 58.54 25 58.56 25 58.58 23 58.6 28 58.62 22 58.64 25 58.66 26 58.68 28 58.7 25 58.72 23 58.74 36 58.76 22 58.78 24 58.8 20 58.82 26 58.84 21 58.86 34 58.88 40 58.9 22 58.92 27 58.94 29 58.96 31 58.98 32 59.0 28 59.02 30 59.04 31 59.06 33 59.08 27 59.1 24 59.12 31 59.14 37 59.16 31 59.18 37 59.2 32 59.22 31 59.24 31 59.26 37 59.28 45 59.3 40 59.32 38 59.34 40 59.36 37 59.38 28 59.4 36 59.42 26 59.44 39 59.46 40 59.48 37 59.5 55 59.52 39 59.54 40 59.56 42 59.58 36 59.6 51 59.62 43 59.64 55 59.66 51 59.68 45 59.7 53 59.72 73 59.74 61 59.76 52 59.78 55 59.8 59 59.82 62 59.84 62 59.86 65 59.88 64 59.9 73 59.92 63 59.94 55 59.96 70 59.98 55 60.0 67 60.02 70 60.04 77 60.06 77 60.08 52 60.1 63 60.12 66 60.14 45 60.16 68 60.18 53 60.2 58 60.22 72 60.24 50 60.26 57 60.28 56 60.3 54 60.32 61 60.34 46 60.36 36 60.38 45 60.4 40 60.42 45 60.44 40 60.46 40 60.48 49 60.5 38 60.52 34 60.54 40 60.56 42 60.58 44 60.6 35 60.62 32 60.64 47 60.66 27 60.68 42 60.7 38 60.72 39 60.74 38 60.76 39 60.78 31 60.8 35 60.82 40 60.84 34 60.86 34 60.88 25 60.9 25 60.92 31 60.94 31 60.96 37 60.98 32 61.0 35 61.02 30 61.04 38 61.06 27 61.08 29 61.1 36 61.12 31 61.14 31 61.16 26 61.18 29 61.2 29 61.22 42 61.24 31 61.26 37 61.28 39 61.3 36 61.32 24 61.34 26 61.36 34 61.38 27 61.4 34 61.42 24 61.44 26 61.46 29 61.48 25 61.5 25 61.52 20 61.54 31 61.56 32 61.58 19 61.6 29 61.62 22 61.64 33 61.66 27 61.68 33 61.7 34 61.72 21 61.74 31 61.76 29 61.78 22 61.8 18 61.82 24 61.84 24 61.86 27 61.88 26 61.9 26 61.92 22 61.94 25 61.96 30 61.98 20 62.0 18 62.02 30 62.04 32 62.06 24 62.08 29 62.1 25 62.12 19 62.14 24 62.16 18 62.18 28 62.2 20 62.22 28 62.24 24 62.26 13 62.28 24 62.3 23 62.32 28 62.34 38 62.36 27 62.38 20 62.4 17 62.42 21 62.44 19 62.46 33 62.48 19 62.5 28 62.52 24 62.54 18 62.56 25 62.58 19 62.6 26 62.62 22 62.64 33 62.66 18 62.68 22 62.7 25 62.72 15 62.74 22 62.76 25 62.78 21 62.8 25 62.82 23 62.84 19 62.86 32 62.88 23 62.9 34 62.92 24 62.94 23 62.96 29 62.98 17 63.0 14 63.02 16 63.04 21 63.06 29 63.08 22 63.1 22 63.12 23 63.14 28 63.16 14 63.18 26 63.2 24 63.22 19 63.24 22 63.26 17 63.28 24 63.3 24 63.32 22 63.34 18 63.36 16 63.38 19 63.4 23 63.42 32 63.44 18 63.46 24 63.48 23 63.5 23 63.52 16 63.54 18 63.56 24 63.58 23 63.6 25 63.62 23 63.64 18 63.66 21 63.68 12 63.7 26 63.72 26 63.74 23 63.76 21 63.78 23 63.8 15 63.82 21 63.84 29 63.86 19 63.88 28 63.9 28 63.92 27 63.94 20 63.96 21 63.98 25 64.0 33 64.02 29 64.04 24 64.06 26 64.08 24 64.1 28 64.12 19 64.14 17 64.16 19 64.18 18 64.2 15 64.22 23 64.24 25 64.26 15 64.28 19 64.3 31 64.32 23 64.34 22 64.36 27 64.38 22 64.4 24 64.42 29 64.44 27 64.46 20 64.48 26 64.5 20 64.52 19 64.54 27 64.56 18 64.58 16 64.6 28 64.62 18 64.64 16 64.66 35 64.68 20 64.7 28 64.72 26 64.74 24 64.76 22 64.78 18 64.8 21 64.82 24 64.84 26 64.86 15 64.88 21 64.9 18 64.92 17 64.94 25 64.96 27 64.98 23 65.0 28 65.02 19 65.04 23 65.06 17 65.08 28 65.1 19 65.12 13 65.14 28 65.16 25 65.18 13 65.2 17 65.22 19 65.24 20 65.26 25 65.28 18 65.3 19 65.32 18 65.34 22 65.36 24 65.38 19 65.4 17 65.42 18 65.44 17 65.46 24 65.48 17 65.5 24 65.52 17 65.54 21 65.56 16 65.58 26 65.6 21 65.62 15 65.64 19 65.66 23 65.68 21 65.7 24 65.72 24 65.74 17 65.76 19 65.78 27 65.8 28 65.82 20 65.84 11 65.86 23 65.88 15 65.9 19 65.92 17 65.94 26 65.96 17 65.98 26 66.0 19 66.02 19 66.04 22 66.06 26 66.08 20 66.1 27 66.12 23 66.14 26 66.16 24 66.18 21 66.2 30 66.22 18 66.24 16 66.26 17 66.28 20 66.3 15 66.32 23 66.34 33 66.36 24 66.38 27 66.4 20 66.42 23 66.44 22 66.46 12 66.48 14 66.5 19 66.52 33 66.54 21 66.56 27 66.58 27 66.6 21 66.62 23 66.64 21 66.66 19 66.68 23 66.7 25 66.72 27 66.74 25 66.76 21 66.78 26 66.8 23 66.82 24 66.84 22 66.86 37 66.88 23 66.9 18 66.92 24 66.94 21 66.96 18 66.98 25 67.0 22 67.02 20 67.04 22 67.06 26 67.08 24 67.1 21 67.12 16 67.14 22 67.16 22 67.18 19 67.2 32 67.22 27 67.24 21 67.26 27 67.28 25 67.3 19 67.32 25 67.34 20 67.36 25 67.38 26 67.4 26 67.42 33 67.44 13 67.46 26 67.48 28 67.5 26 67.52 32 67.54 19 67.56 20 67.58 22 67.6 19 67.62 23 67.64 19 67.66 27 67.68 23 67.7 18 67.72 18 67.74 29 67.76 24 67.78 15 67.8 23 67.82 19 67.84 17 67.86 25 67.88 20 67.9 27 67.92 30 67.94 23 67.96 24 67.98 21 68.0 25 68.02 32 68.04 31 68.06 31 68.08 28 68.1 28 68.12 20 68.14 33 68.16 21 68.18 23 68.2 21 68.22 25 68.24 17 68.26 18 68.28 29 68.3 29 68.32 27 68.34 18 68.36 31 68.38 29 68.4 36 68.42 30 68.44 29 68.46 33 68.48 20 68.5 31 68.52 33 68.54 24 68.56 25 68.58 26 68.6 25 68.62 22 68.64 26 68.66 27 68.68 32 68.7 19 68.72 26 68.74 35 68.76 26 68.78 20 68.8 16 68.82 20 68.84 20 68.86 28 68.88 27 68.9 28 68.92 31 68.94 20 68.96 27 68.98 31 69.0 31 69.02 26 69.04 26 69.06 38 69.08 39 69.1 35 69.12 36 69.14 30 69.16 35 69.18 38 69.2 30 69.22 36 69.24 23 69.26 41 69.28 28 69.3 40 69.32 39 69.34 29 69.36 40 69.38 38 69.4 54 69.42 38 69.44 35 69.46 31 69.48 39 69.5 27 69.52 35 69.54 42 69.56 41 69.58 56 69.6 40 69.62 32 69.64 39 69.66 48 69.68 44 69.7 49 69.72 43 69.74 51 69.76 46 69.78 50 69.8 43 69.82 77 69.84 59 69.86 71 69.88 71 69.9 58 69.92 73 69.94 75 69.96 81 69.98 114 70.0 105 70.02 98 70.04 105 70.06 122 70.08 116 70.1 115 70.12 113 70.14 153 70.16 125 70.18 154 70.2 139 70.22 143 70.24 163 70.26 133 70.28 183 70.3 143 70.32 153 70.34 176 70.36 171 70.38 157 70.4 177 70.42 165 70.44 163 70.46 182 70.48 184 70.5 170 70.52 162 70.54 155 70.56 154 70.58 145 70.6 136 70.62 143 70.64 148 70.66 143 70.68 136 70.7 111 70.72 109 70.74 129 70.76 97 70.78 101 70.8 89 70.82 100 70.84 97 70.86 67 70.88 72 70.9 65 70.92 73 70.94 76 70.96 65 70.98 67 71.0 62 71.02 70 71.04 61 71.06 52 71.08 53 71.1 57 71.12 43 71.14 49 71.16 47 71.18 74 71.2 56 71.22 49 71.24 61 71.26 63 71.28 54 71.3 58 71.32 56 71.34 78 71.36 61 71.38 50 71.4 51 71.42 49 71.44 62 71.46 74 71.48 56 71.5 52 71.52 55 71.54 70 71.56 59 71.58 68 71.6 69 71.62 63 71.64 74 71.66 79 71.68 66 71.7 61 71.72 62 71.74 55 71.76 54 71.78 65 71.8 71 71.82 50 71.84 50 71.86 55 71.88 53 71.9 64 71.92 50 71.94 59 71.96 47 71.98 55 72.0 49 72.02 61 72.04 50 72.06 50 72.08 46 72.1 48 72.12 48 72.14 43 72.16 42 72.18 61 72.2 60 72.22 44 72.24 41 72.26 34 72.28 46 72.3 38 72.32 47 72.34 48 72.36 50 72.38 47 72.4 47 72.42 32 72.44 38 72.46 45 72.48 40 72.5 39 72.52 26 72.54 52 72.56 37 72.58 50 72.6 26 72.62 55 72.64 43 72.66 34 72.68 43 72.7 34 72.72 29 72.74 29 72.76 44 72.78 25 72.8 39 72.82 42 72.84 26 72.86 28 72.88 31 72.9 36 72.92 35 72.94 33 72.96 34 72.98 37 73.0 29 73.02 44 73.04 35 73.06 30 73.08 32 73.1 28 73.12 39 73.14 32 73.16 32 73.18 26 73.2 27 73.22 26 73.24 41 73.26 21 73.28 33 73.3 22 73.32 33 73.34 25 73.36 21 73.38 33 73.4 33 73.42 30 73.44 22 73.46 22 73.48 26 73.5 24 73.52 28 73.54 29 73.56 41 73.58 27 73.6 26 73.62 29 73.64 26 73.66 22 73.68 30 73.7 33 73.72 24 73.74 34 73.76 32 73.78 19 73.8 29 73.82 26 73.84 18 73.86 29 73.88 22 73.9 19 73.92 20 73.94 31 73.96 24 73.98 16 74.0 39 74.02 29 74.04 31 74.06 30 74.08 31 74.1 21 74.12 30 74.14 30 74.16 16 74.18 38 74.2 21 74.22 28 74.24 25 74.26 35 74.28 26 74.3 36 74.32 17 74.34 18 74.36 30 74.38 31 74.4 30 74.42 32 74.44 25 74.46 30 74.48 25 74.5 23 74.52 26 74.54 25 74.56 38 74.58 27 74.6 33 74.62 26 74.64 25 74.66 22 74.68 18 74.7 35 74.72 27 74.74 40 74.76 25 74.78 29 74.8 27 74.82 31 74.84 35 74.86 22 74.88 21 74.9 23 74.92 40 74.94 26 74.96 31 74.98 27 75.0 33 75.02 29 75.04 31 75.06 29 75.08 21 75.1 26 75.12 21 75.14 29 75.16 40 75.18 20 75.2 26 75.22 18 75.24 28 75.26 21 75.28 27 75.3 34 75.32 29 75.34 45 75.36 39 75.38 29 75.4 24 75.42 26 75.44 35 75.46 21 75.48 36 75.5 28 75.52 29 75.54 27 75.56 30 75.58 18 75.6 26 75.62 33 75.64 21 75.66 23 75.68 20 75.7 30 75.72 25 75.74 24 75.76 33 75.78 26 75.8 27 75.82 20 75.84 35 75.86 28 75.88 24 75.9 28 75.92 38 75.94 26 75.96 23 75.98 24 76.0 24 76.02 21 76.04 23 76.06 20 76.08 25 76.1 23 76.12 28 76.14 23 76.16 27 76.18 27 76.2 30 76.22 21 76.24 22 76.26 26 76.28 26 76.3 26 76.32 29 76.34 25 76.36 30 76.38 28 76.4 28 76.42 27 76.44 21 76.46 19 76.48 19 76.5 27 76.52 27 76.54 28 76.56 30 76.58 27 76.6 20 76.62 25 76.64 23 76.66 22 76.68 28 76.7 30 76.72 30 76.74 25 76.76 35 76.78 31 76.8 22 76.82 22 76.84 23 76.86 28 76.88 25 76.9 33 76.92 28 76.94 29 76.96 33 76.98 40 77.0 26 77.02 27 77.04 27 77.06 28 77.08 25 77.1 31 77.12 28 77.14 26 77.16 21 77.18 35 77.2 31 77.22 37 77.24 27 77.26 40 77.28 24 77.3 18 77.32 28 77.34 30 77.36 29 77.38 29 77.4 26 77.42 26 77.44 26 77.46 32 77.48 28 77.5 32 77.52 39 77.54 30 77.56 23 77.58 18 77.6 34 77.62 27 77.64 30 77.66 30 77.68 27 77.7 41 77.72 32 77.74 33 77.76 26 77.78 22 77.8 27 77.82 18 77.84 22 77.86 25 77.88 38 77.9 26 77.92 26 77.94 28 77.96 28 77.98 29 78.0 19 78.02 24 78.04 19 78.06 27 78.08 18 78.1 31 78.12 29 78.14 21 78.16 18 78.18 25 78.2 39 78.22 22 78.24 23 78.26 17 78.28 22 78.3 24 78.32 33 78.34 26 78.36 25 78.38 23 78.4 23 78.42 24 78.44 28 78.46 24 78.48 24 78.5 27 78.52 31 78.54 14 78.56 25 78.58 20 78.6 20 78.62 34 78.64 26 78.66 25 78.68 22 78.7 25 78.72 30 78.74 20 78.76 20 78.78 24 78.8 26 78.82 24 78.84 16 78.86 25 78.88 24 78.9 20 78.92 24 78.94 16 78.96 26 78.98 21 79.0 19 79.02 28 79.04 26 79.06 25 79.08 26 79.1 22 79.12 24 79.14 26 79.16 22 79.18 29 79.2 15 79.22 25 79.24 26 79.26 18 79.28 27 79.3 12 79.32 24 79.34 30 79.36 26 79.38 17 79.4 16 79.42 23 79.44 25 79.46 21 79.48 16 79.5 22 79.52 27 79.54 29 79.56 22 79.58 20 79.6 16 79.62 30 79.64 31 79.66 29 79.68 28 79.7 16 79.72 20 79.74 29 79.76 22 79.78 26 79.8 22 79.82 29 79.84 23 79.86 17 79.88 21 79.9 31 79.92 20 79.94 31 79.96 20 79.98 20 80.0 27 80.02 29 80.04 32 80.06 27 80.08 23 80.1 29 80.12 23 80.14 28 80.16 16 80.18 21 80.2 17 80.22 16 80.24 26 80.26 25 80.28 21 80.3 19 80.32 21 80.34 34 80.36 24 80.38 23 80.4 30 80.42 24 80.44 29 80.46 20 80.48 23 80.5 19 80.52 26 80.54 24 80.56 24 80.58 28 80.6 36 80.62 28 80.64 24 80.66 26 80.68 20 80.7 27 80.72 28 80.74 20 80.76 22 80.78 17 80.8 30 80.82 29 80.84 21 80.86 19 80.88 23 80.9 24 80.92 27 80.94 33 80.96 28 80.98 34 81.0 22 81.02 23 81.04 25 81.06 29 81.08 30 81.1 26 81.12 36 81.14 26 81.16 28 81.18 21 81.2 33 81.22 26 81.24 37 81.26 23 81.28 33 81.3 44 81.32 41 81.34 40 81.36 44 81.38 53 81.4 41 81.42 37 81.44 45 81.46 39 81.48 44 81.5 38 81.52 57 81.54 39 81.56 40 81.58 43 81.6 43 81.62 56 81.64 51 81.66 59 81.68 52 81.7 41 81.72 57 81.74 53 81.76 71 81.78 65 81.8 69 81.82 72 81.84 71 81.86 85 81.88 73 81.9 89 81.92 76 81.94 91 81.96 103 81.98 106 82.0 96 82.02 93 82.04 125 82.06 110 82.08 106 82.1 109 82.12 118 82.14 101 82.16 102 82.18 88 82.2 98 82.22 81 82.24 76 82.26 82 82.28 65 82.3 75 82.32 62 82.34 65 82.36 51 82.38 64 82.4 58 82.42 65 82.44 46 82.46 46 82.48 48 82.5 50 82.52 48 82.54 46 82.56 54 82.58 41 82.6 43 82.62 44 82.64 35 82.66 32 82.68 37 82.7 24 82.72 35 82.74 31 82.76 38 82.78 25 82.8 28 82.82 32 82.84 32 82.86 22 82.88 24 82.9 29 82.92 31 82.94 22 82.96 42 82.98 31 83.0 31 83.02 25 83.04 30 83.06 28 83.08 26 83.1 23 83.12 20 83.14 27 83.16 29 83.18 28 83.2 28 83.22 28 83.24 34 83.26 35 83.28 27 83.3 23 83.32 32 83.34 39 83.36 33 83.38 35 83.4 41 83.42 38 83.44 36 83.46 35 83.48 19 83.5 38 83.52 31 83.54 37 83.56 26 83.58 39 83.6 35 83.62 44 83.64 33 83.66 35 83.68 32 83.7 30 83.72 34 83.74 37 83.76 31 83.78 38 83.8 31 83.82 26 83.84 36 83.86 27 83.88 32 83.9 23 83.92 34 83.94 33 83.96 24 83.98 34 84.0 26 84.02 23 84.04 17 84.06 26 84.08 31 84.1 24 84.12 21 84.14 29 84.16 22 84.18 14 84.2 36 84.22 19 84.24 21 84.26 23 84.28 34 84.3 30 84.32 24 84.34 23 84.36 20 84.38 25 84.4 14 84.42 19 84.44 21 84.46 26 84.48 31 84.5 17 84.52 22 84.54 28 84.56 32 84.58 18 84.6 19 84.62 28 84.64 23 84.66 25 84.68 30 84.7 19 84.72 27 84.74 17 84.76 28 84.78 24 84.8 25 84.82 21 84.84 23 84.86 21 84.88 25 84.9 24 84.92 26 84.94 19 84.96 26 84.98 27 85.0 28 85.02 32 85.04 26 85.06 29 85.08 21 85.1 32 85.12 29 85.14 25 85.16 23 85.18 22 85.2 28 85.22 23 85.24 22 85.26 27 85.28 25 85.3 35 85.32 32 85.34 19 85.36 26 85.38 21 85.4 22 85.42 24 85.44 31 85.46 37 85.48 26 85.5 28 85.52 34 85.54 30 85.56 24 85.58 28 85.6 28 85.62 38 85.64 29 85.66 31 85.68 25 85.7 21 85.72 34 85.74 39 85.76 25 85.78 36 85.8 26 85.82 32 85.84 27 85.86 39 85.88 34 85.9 38 85.92 37 85.94 47 85.96 34 85.98 32 86.0 58 86.02 49 86.04 46 86.06 52 86.08 48 86.1 39 86.12 58 86.14 47 86.16 57 86.18 54 86.2 61 86.22 63 86.24 70 86.26 66 86.28 71 86.3 73 86.32 61 86.34 63 86.36 73 86.38 70 86.4 81 86.42 77 86.44 85 86.46 78 86.48 72 86.5 57 86.52 83 86.54 60 86.56 84 86.58 69 86.6 61 86.62 56 86.64 57 86.66 58 86.68 52 86.7 39 86.72 44 86.74 55 86.76 36 86.78 39 86.8 39 86.82 46 86.84 47 86.86 34 86.88 43 86.9 37 86.92 39 86.94 31 86.96 36 86.98 31 87.0 30 87.02 35 87.04 38 87.06 21 87.08 30 87.1 29 87.12 37 87.14 25 87.16 34 87.18 27 87.2 30 87.22 24 87.24 26 87.26 33 87.28 19 87.3 27 87.32 29 87.34 23 87.36 23 87.38 30 87.4 22 87.42 23 87.44 23 87.46 21 87.48 22 87.5 26 87.52 33 87.54 18 87.56 35 87.58 24 87.6 21 87.62 29 87.64 18 87.66 24 87.68 27 87.7 34 87.72 27 87.74 23 87.76 26 87.78 28 87.8 26 87.82 23 87.84 25 87.86 20 87.88 30 87.9 27 87.92 26 87.94 20 87.96 13 87.98 27 88.0 18 88.02 25 88.04 21 88.06 22 88.08 22 88.1 25 88.12 35 88.14 24 88.16 22 88.18 23 88.2 28 88.22 27 88.24 27 88.26 29 88.28 29 88.3 25 88.32 21 88.34 14 88.36 27 88.38 20 88.4 22 88.42 27 88.44 14 88.46 30 88.48 28 88.5 27 88.52 25 88.54 28 88.56 22 88.58 25 88.6 23 88.62 25 88.64 21 88.66 21 88.68 17 88.7 21 88.72 16 88.74 14 88.76 32 88.78 17 88.8 18 88.82 23 88.84 22 88.86 25 88.88 21 88.9 25 88.92 32 88.94 28 88.96 24 88.98 30 89.0 34 89.02 24 89.04 25 89.06 21 89.08 19 89.1 29 89.12 33 89.14 30 89.16 23 89.18 21 89.2 27 89.22 26 89.24 29 89.26 28 89.28 31 89.3 25 89.32 26 89.34 26 89.36 20 89.38 24 89.4 20 89.42 19 89.44 22 89.46 22 89.48 27 89.5 26 89.52 25 89.54 22 89.56 15 89.58 26 89.6 27 89.62 31 89.64 30 89.66 29 89.68 31 89.7 19 89.72 36 89.74 35 89.76 24 89.78 22 89.8 26 89.82 27 89.84 21 89.86 29 89.88 32 89.9 24 89.92 28 89.94 36 89.96 32 89.98 34 90.0 25 90.02 31 90.04 31 90.06 37 90.08 29 90.1 41 90.12 34 90.14 29 90.16 35 90.18 29 90.2 39 90.22 30 90.24 35 90.26 34 90.28 32 90.3 35 90.32 26 90.34 27 90.36 29 90.38 30 90.4 31 90.42 31 90.44 28 90.46 41 90.48 35 90.5 28 90.52 32 90.54 30 90.56 28 90.58 29 90.6 29 90.62 32 90.64 23 90.66 40 90.68 33 90.7 37 90.72 30 90.74 21 90.76 33 90.78 25 90.8 28 90.82 36 90.84 38 90.86 28 90.88 25 90.9 24 90.92 23 90.94 28 90.96 27 90.98 15 91.0 19 91.02 22 91.04 18 91.06 26 91.08 21 91.1 25 91.12 26 91.14 27 91.16 20 91.18 25 91.2 25 91.22 29 91.24 30 91.26 20 91.28 27 91.3 20 91.32 23 91.34 25 91.36 29 91.38 27 91.4 18 91.42 25 91.44 24 91.46 19 91.48 26 91.5 28 91.52 21 91.54 22 91.56 33 91.58 26 91.6 19 91.62 23 91.64 25 91.66 30 91.68 24 91.7 33 91.72 22 91.74 27 91.76 29 91.78 18 91.8 21 91.82 27 91.84 26 91.86 20 91.88 39 91.9 18 91.92 30 91.94 20 91.96 23 91.98 20 92.0 16 92.02 18 92.04 20 92.06 27 92.08 20 92.1 21 92.12 21 92.14 29 92.16 26 92.18 31 92.2 24 92.22 26 92.24 19 92.26 21 92.28 24 92.3 30 92.32 29 92.34 26 92.36 27 92.38 29 92.4 23 92.42 19 92.44 20 92.46 30 92.48 24 92.5 28 92.52 15 92.54 26 92.56 26 92.58 19 92.6 20 92.62 13 92.64 30 92.66 17 92.68 15 92.7 20 92.72 21 92.74 23 92.76 22 92.78 23 92.8 26 92.82 18 92.84 25 92.86 22 92.88 25 92.9 28 92.92 25 92.94 20 92.96 27 92.98 31 93.0 29 93.02 23 93.04 22 93.06 15 93.08 19 93.1 29 93.12 27 93.14 24 93.16 21 93.18 21 93.2 21 93.22 22 93.24 18 93.26 18 93.28 20 93.3 17 93.32 25 93.34 29 93.36 27 93.38 25 93.4 21 93.42 21 93.44 28 93.46 21 93.48 22 93.5 22 93.52 22 93.54 20 93.56 17 93.58 29 93.6 19 93.62 27 93.64 27 93.66 11 93.68 18 93.7 21 93.72 30 93.74 27 93.76 23 93.78 25 93.8 28 93.82 25 93.84 35 93.86 22 93.88 24 93.9 27 93.92 14 93.94 29 93.96 26 93.98 27 94.0 15 94.02 19 94.04 23 94.06 25 94.08 27 94.1 23 94.12 28 94.14 17 94.16 24 94.18 23 94.2 31 94.22 19 94.24 28 94.26 28 94.28 21 94.3 22 94.32 24 94.34 33 94.36 36 94.38 31 94.4 25 94.42 25 94.44 18 94.46 25 94.48 42 94.5 33 94.52 33 94.54 36 94.56 31 94.58 22 94.6 28 94.62 23 94.64 45 94.66 29 94.68 30 94.7 39 94.72 39 94.74 36 94.76 43 94.78 31 94.8 42 94.82 46 94.84 31 94.86 29 94.88 32 94.9 21 94.92 35 94.94 40 94.96 25 94.98 38 95.0 28 95.02 30 95.04 27 95.06 37 95.08 37 95.1 26 95.12 30 95.14 37 95.16 34 95.18 29 95.2 20 95.22 27 95.24 32 95.26 29 95.28 27 95.3 36 95.32 28 95.34 25 95.36 23 95.38 31 95.4 25 95.42 26 95.44 22 95.46 20 95.48 20 95.5 18 95.52 25 95.54 26 95.56 19 95.58 28 95.6 23 95.62 16 95.64 26 95.66 25 95.68 26 95.7 22 95.72 25 95.74 19 95.76 26 95.78 19 95.8 32 95.82 31 95.84 21 95.86 28 95.88 18 95.9 19 95.92 17 95.94 27 95.96 30 95.98 19 96.0 19 96.02 19 96.04 21 96.06 26 96.08 18 96.1 22 96.12 21 96.14 20 96.16 29 96.18 27 96.2 25 96.22 22 96.24 28 96.26 21 96.28 21 96.3 23 96.32 28 96.34 26 96.36 28 96.38 21 96.4 21 96.42 15 96.44 30 96.46 21 96.48 27 96.5 35 96.52 22 96.54 29 96.56 29 96.58 26 96.6 25 96.62 22 96.64 25 96.66 23 96.68 27 96.7 27 96.72 38 96.74 24 96.76 24 96.78 30 96.8 18 96.82 24 96.84 23 96.86 22 96.88 20 96.9 15 96.92 12 96.94 13 96.96 29 96.98 26 97.0 24 97.02 23 97.04 23 97.06 21 97.08 14 97.1 25 97.12 27 97.14 24 97.16 29 97.18 23 97.2 20 97.22 21 97.24 18 97.26 21 97.28 43 97.3 29 97.32 17 97.34 20 97.36 21 97.38 25 97.4 17 97.42 26 97.44 23 97.46 27 97.48 16 97.5 26 97.52 23 97.54 28 97.56 17 97.58 21 97.6 22 97.62 20 97.64 15 97.66 31 97.68 19 97.7 25 97.72 25 97.74 19 97.76 27 97.78 20 97.8 19 97.82 23 97.84 21 97.86 31 97.88 23 97.9 25 97.92 23 97.94 27 97.96 24 97.98 17 98.0 19 98.02 20 98.04 22 98.06 19 98.08 22 98.1 18 98.12 18 98.14 36 98.16 17 98.18 23 98.2 30 98.22 21 98.24 18 98.26 21 98.28 26 98.3 19 98.32 29 98.34 30 98.36 24 98.38 28 98.4 22 98.42 25 98.44 23 98.46 28 98.48 25 98.5 13 98.52 30 98.54 38 98.56 14 98.58 22 98.6 25 98.62 22 98.64 17 98.66 28 98.68 23 98.7 18 98.72 27 98.74 25 98.76 23 98.78 20 98.8 25 98.82 29 98.84 38 98.86 25 98.88 28 98.9 21 98.92 27 98.94 19 98.96 23 98.98 19 99.0 28 99.02 23 99.04 30 99.06 27 99.08 32 99.1 27 99.12 18 99.14 22 99.16 29 99.18 30 99.2 27 99.22 30 99.24 25 99.26 26 99.28 25 99.3 25 99.32 21 99.34 31 99.36 20 99.38 19 99.4 22 99.42 32 99.44 26 99.46 23 99.48 31 99.5 22 99.52 25 99.54 23 99.56 23 99.58 31 99.6 30 99.62 22 99.64 25 99.66 14 99.68 21 99.7 23 99.72 26 99.74 28 99.76 19 99.78 26 99.8 28 99.82 24 99.84 34 99.86 22 99.88 31 99.9 28 99.92 29 99.94 30 99.96 35 99.98 34 100.0 29 fityk-1.3.1/samples/SiC_Zn.fit000066400000000000000000000070001302634723100161350ustar00rootroot00000000000000# Fityk 1.1.2 ## This script shows the Pawley method for powder pattern which can be called ## a multi-peak fitting, with equality constraints. # Load data file from directory of this script (SiC+Zn data) @0 < '_SCRIPT_DIR_/SiC_Zn.dat' # the background was obtained by clicking on the plot in the "background mode" %bg0 = Spline(20.4823,43.3474, 28.004,24.3128, 31.4412,23.6984, 33.7911,36.0138, 38.6477,30.5403, 49.9335,17.263, 65.1888,17.968, 79.5965,22.1979, 98.9835,23.6079) Y = y - %bg0(x) A = 31 < x and x < 90 # only data with 2theta in (31, 90) are active # The wavelength is known and we do not want to fit it. # If you would like to fit wavelength, put '~' before the number. $lambda = 1.54051 # Cu Ka1 # initial lattice parameters $sic_a = ~4.35 #cubic SiC $zn_a = ~2.67; $zn_c = ~4.924 #hexagonal Zn # the peak positions are given by the following formulae: #1/d = sqrt(h^2 + k^2 + l^2) / a # for cubic phase #1/d = sqrt(4./3. * (h^2 + k^2 + h*k) / a^2 + l^2 / c^2) # for hexagonal phase #peak_center = 2 * asin((1/d) / 2 * lambda) [in RAD, must be converted to DEG] ## All initial peak width and heights are the same (0.2 and 200, respectively). # peak hkl=(220) of SiC $c_sic220 = 360/pi * asin(sqrt(2^2+2^2+0) / $sic_a / 2 * $lambda) %sic220 = PseudoVoigt(center=$c_sic220, hwhm=~0.2, height=~200) # Zn (002) $c_zn002 = 360/pi * asin(sqrt(4/3 * (0+0+0*0) / $zn_a^2 + 2^2/$zn_c^2 ) / 2 * $lambda) %zn002 = PseudoVoigt(center=$c_zn002, hwhm=~0.2, height=~200) # SiC (111) $c_sic111 = 360/pi * asin(sqrt(1^2+1^2+1^2) / $sic_a / 2 * $lambda) %sic111 = PseudoVoigt(center=$c_sic111, hwhm=~0.2, height=~200) # Zn (100) $c_zn100 = 360/pi * asin(sqrt(4/3 * (1^2+0+1*0) / $zn_a^2 + 0/$zn_c^2 ) / 2 * $lambda) %zn100 = PseudoVoigt(center=$c_zn100, hwhm=~0.2, height=~200) # Zn (101) $c_zn101 = 360/pi * asin(sqrt(4/3 * (1^2+0+1*0) / $zn_a^2 + 1^2/$zn_c^2 ) / 2 * $lambda) %zn101 = PseudoVoigt(center=$c_zn101, hwhm=~0.2, height=~200) # Zn (102) $c_zn102 = 360/pi * asin(sqrt(4/3 * (1^2+0+1*0) / $zn_a^2 + 2^2/$zn_c^2 ) / 2 * $lambda) %zn102 = PseudoVoigt(center=$c_zn102, hwhm=~0.2, height=~200) F = %sic220 + %zn002 + %sic111 + %zn100 + %zn101 + %zn102 # after adding a few peaks it can be a good idea to fit it, # to get a better approximation of the lattice parameters fit 10 # Zn (103) $c_zn103 = 360/pi * asin(sqrt(4/3 * (1^2+0+1*0) / $zn_a^2 + 3^2/$zn_c^2 ) / 2 * $lambda) %zn103 = PseudoVoigt(center=$c_zn103, hwhm=~0.2, height=~200) # Zn (110) $c_zn110 = 360/pi * asin(sqrt(4/3 * (1^2+1^2+1*1) / $zn_a^2 + 0^2/$zn_c^2 ) / 2 * $lambda) %zn110 = PseudoVoigt(center=$c_zn110, hwhm=~0.2, height=~200) # Zn (112) $c_zn112 = 360/pi * asin(sqrt(4/3 * (1^2+1^2+1*1) / $zn_a^2 + 2^2/$zn_c^2 ) / 2 * $lambda) %zn112 = PseudoVoigt(center=$c_zn112, hwhm=~0.2, height=~200) # Zn (200) $c_zn200 = 360/pi * asin(sqrt(4/3 * (2^2+0^2+2*0) / $zn_a^2 + 0^2/$zn_c^2 ) / 2 * $lambda) %zn200 = PseudoVoigt(center=$c_zn200, hwhm=~0.2, height=~200) # constraints: this small peak will have the same width and shape as %zn112 %zn200.shape = %zn112.shape %zn200.hwhm = %zn112.hwhm # Zn (201) $c_zn201 = 360/pi * asin(sqrt(4/3 * (2^2+0^2+2*0) / $zn_a^2 + 1^2/$zn_c^2 ) / 2 * $lambda) %zn201 = PseudoVoigt(center=$c_zn201, hwhm=~0.2, height=~200) # SiC (311) $c_sic311 = 360/pi * asin(sqrt(3^2+1^2+1^2) / $sic_a / 2 * $lambda) %sic311 = PseudoVoigt(center=$c_sic311, hwhm=~0.2, height=~200) # add these functions to the model F += %zn103 + %zn110 + %zn112 + %zn200 + %zn201 + %sic311 # add zero-shift Z = Constant(~0.) # fit # least-squares fitting fityk-1.3.1/samples/cfityk.py000077500000000000000000000130131302634723100161530ustar00rootroot00000000000000#!/usr/bin/env python """ Equivalent of cfityk in Python. """ import os import sys try: import readline except ImportError: readline = None import atexit import signal from optparse import OptionParser import subprocess import bisect import functools import fityk _PROMPT = "=-> " _PROMPT2 = "... " _gnuplot = None # Python 3.2 has math.isfinite() def finite(x): return x == x def interrupt_handler(signum, frame): sys.stderr.write("\n(^C interrupts long calculations, use ^D to exit)\n") fityk.cvar.user_interrupt = True def read_line(): try: line = raw_input(_PROMPT) except EOFError: raise fityk.ExitRequestedException() while line.endswith("\\"): cont = raw_input(_PROMPT2) line = line[:-1] + cont return line def get_filename_completions(text): head, tail = os.path.split(text) dirname = head or os.getcwd() try: return [os.path.join(head, f) for f in os.listdir(dirname) if f.startswith(tail)] except: return [] class Completer: def __init__(self, ftk): self.ftk = ftk self.clist = None def complete(self, text, state): if state == 0: self.clist = fityk.complete_fityk_line(self.ftk, readline.get_line_buffer(), readline.get_begidx(), readline.get_endidx(), text) if len(self.clist) == 1 and self.clist[0] == "": self.clist = get_filename_completions(text) if state < len(self.clist): return self.clist[state] else: return None def main(): config_dir = os.path.join(os.path.expanduser("~"), fityk.config_dirname()) if readline: histfile = os.path.join(config_dir, "history") if hasattr(readline, "read_history_file"): try: readline.read_history_file(histfile) except IOError: pass atexit.register(readline.write_history_file, histfile) signal.signal(signal.SIGINT, interrupt_handler) parser = OptionParser("Usage: %prog [-h] [-V] [-c ]" " [script or data file...]") parser.add_option("-V", "--version", action="store_true", help="output version information and exit") parser.add_option("-c", "--cmd", action="append", default=[], help="script passed in as string") parser.add_option("-I", "--no-init", action="store_true", help="don't process $HOME/.fityk/init file") parser.add_option("-q", "--quit", action="store_true", help="don't enter interactive shell") (options, args) = parser.parse_args() f = fityk.Fityk() ui = f.get_ui_api() ui.connect_draw_plot_py(functools.partial(plot_in_gnuplot, f)) if options.version: print("cfityk.py %s" % f.get_info("version").split()[-1]) return if not options.no_init: init_file = os.path.join(config_dir, fityk.startup_commands_filename()) if os.path.exists(init_file): sys.stderr.write(" -- init file: %s --\n" % init_file) ui.exec_fityk_script(init_file) sys.stderr.write(" -- end of init file --\n") if readline: readline.parse_and_bind("tab: complete") readline.set_completer_delims(" \t\n\"\\'`@$><=;|&{(:") # default+":" completer = Completer(f) readline.set_completer(completer.complete) try: for s in options.cmd: ui.exec_and_log(s) for arg in args: f.process_cmd_line_arg(arg) if not options.quit: while True: line = read_line() ui.exec_and_log(line) print("") except fityk.ExitRequestedException: sys.stderr.write("\nbye...\n") def plot_in_gnuplot(f, mode): global _gnuplot # _gnuplot is False -- failed to open # _gnuplot is None -- not initialized if _gnuplot is False: return # plot only the active dataset and model dm_number = f.get_default_dataset() points = f.get_data(dm_number) left_x = f.get_view_boundary('L') right_x = f.get_view_boundary('R') begin = bisect.bisect_left(points, fityk.Point(left_x,0)) end = bisect.bisect_right(points, fityk.Point(right_x,0)) has_points = (begin != end) if _gnuplot is None and has_points: try: _gnuplot = subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE) except OSError: _gnuplot = False sys.stderr.write("WARNING: Failed to open gnuplot.\n") if not _gnuplot: return # send "plot ..." through the pipe to gnuplot plot_string = ("plot %s '-' title \"data\", '-' title \"sum\" with line\n" % f.get_info("view")) _gnuplot.stdin.write(plot_string) # data if has_points: for p in points[begin:end]: if p.is_active and finite(p.x) and finite(p.y): _gnuplot.stdin.write("%f %f\n" % (p.x, p.y)) else: _gnuplot.stdin.write("0.0 0.0\n") _gnuplot.stdin.write("e\n") # gnuplot needs 'e' at the end of data # model if has_points: for p in points[begin:end]: if p.is_active and finite(p.x): y = f.get_model_value(p.x, dm_number) if finite(y): _gnuplot.stdin.write("%f %f\n" % (p.x, y)) else: _gnuplot.stdin.write("0.0 0.0\n") _gnuplot.stdin.write("e\n") if __name__ == '__main__': main() fityk-1.3.1/samples/enso.dat000066400000000000000000000014121302634723100157430ustar00rootroot0000000000000012.9 11.3 10.6 11.2 10.9 7.5 7.7 11.7 12.9 14.3 10.9 13.7 17.1 14.0 15.3 8.5 5.7 5.5 7.6 8.6 7.3 7.6 12.7 11.0 12.7 12.9 13.0 10.9 10.4 10.2 8.0 10.9 13.6 10.5 9.2 12.4 12.7 13.3 10.1 7.8 4.8 3.0 2.5 6.3 9.7 11.6 8.6 12.4 10.5 13.3 10.4 8.1 3.7 10.7 5.1 10.4 10.9 11.7 11.4 13.7 14.1 14.0 12.5 6.3 9.6 11.7 5.0 10.8 12.7 10.8 11.8 12.6 15.7 12.6 14.8 7.8 7.1 11.2 8.1 6.4 5.2 12.0 10.2 12.7 10.2 14.7 12.2 7.1 5.7 6.7 3.9 8.5 8.3 10.8 16.7 12.6 12.5 12.5 9.8 7.2 4.1 10.6 10.1 10.1 11.9 13.6 16.3 17.6 15.5 16.0 15.2 11.2 14.3 14.5 8.5 12.0 12.7 11.3 14.5 15.1 10.4 11.5 13.4 7.5 0.6 0.3 5.5 5.0 4.6 8.2 9.9 9.2 12.5 10.9 9.9 8.9 7.6 9.5 8.4 10.7 13.6 13.7 13.7 16.5 16.8 17.1 15.4 9.5 6.1 10.1 9.3 5.3 11.2 16.6 15.6 12.0 11.5 8.6 13.8 8.7 8.6 8.6 8.7 12.8 13.2 14.0 13.4 14.8 fityk-1.3.1/samples/enso.fit000066400000000000000000000013241302634723100157570ustar00rootroot00000000000000# Fityk 1.1.2 ### see https://github.com/wojdyr/fityk/wiki/Southern-Oscillation set lm_stop_rel_change=1e-20, numeric_format='%.10E', default_sigma=one # load index as x and column 1 as y @0 < '_SCRIPT_DIR_/enso.dat:0:1::' # now x is set as 0-based index, we prefer 1-based index X=n+1 plot [] [-5:] #define Enso(b1, b2, b3, b4, b5, b6, b7, b8, b9) = b1 + b2*cos(t/12) + b3*sin(t/12) + b5*cos(t/b4) + b6*sin(t/b4) + b8*cos(t/b7) + b9*sin(t/b7) where t=2*pi*x #F = Enso(~11.0, ~3.0, ~0.5, ~40.0, ~-0.7, ~-1.3, ~25.0, ~-0.3, ~1.4) define Cycle(period, a, b) = a*cos(2*pi*x/period) + b*sin(2*pi*x/period) F = Constant(~11) + Cycle(12, ~3.0, ~0.5) + Cycle(~40.0, ~-0.7, ~-1.3) + Cycle(~25.0, ~-0.3, ~1.4) fit info errors fityk-1.3.1/samples/hello.c000066400000000000000000000016051302634723100155600ustar00rootroot00000000000000/* Example of using libfityk from ANSI C. */ #include #include #include #include int main() { int i; double x[500], y[500], sigma[500]; const double mu = 12.345; double d; Fityk *f = fityk_create(); char *s = fityk_get_info(f, "version", 0); printf("%s\n", s); free(s); d = fityk_calculate_expr(f, "ln(2)", 0); printf("ln(2) = %g\n", d); for (i = 0; i != 500; ++i) { x[i] = i / 100. + 10; y[i] = ceil(100 * exp(-(x[i]-mu)*(x[i]-mu)/2)); sigma[i] = sqrt(y[i]); } fityk_load_data(f, 0, x, y, sigma, 500, "noisy gaussian"); fityk_execute(f, "Y = randnormal(y, s)"); fityk_execute(f, "guess %gauss = Gaussian"); fityk_execute(f, "fit"); d = fityk_calculate_expr(f, "%gauss.Center", 0); printf("peak center: %g\n", d); fityk_delete(f); return 0; } fityk-1.3.1/samples/hello.cc000066400000000000000000000012301302634723100157150ustar00rootroot00000000000000 #include #include #include using namespace std; using namespace fityk; int main() { Fityk *f = new Fityk; cout << f->get_info("version") << endl; cout << "ln(2) = " << f->calculate_expr("ln(2)") << endl; const double mu = 12.345; for (int i = 0; i != 500; ++i) { double x = i / 100. + 10; double y = ceil(100 * exp(-(x-mu)*(x-mu)/2)); f->add_point(x, y, sqrt(y)); } f->execute("Y = randnormal(y, s)"); f->execute("guess %gauss = Gaussian"); f->execute("fit"); cout << "peak center: " << f->calculate_expr("%gauss.Center") << endl; delete f; return 0; } fityk-1.3.1/samples/hello.java000066400000000000000000000037101302634723100162560ustar00rootroot00000000000000// Example of using libfityk from Java. // To run this example: // - compile dynamic module for Java: after compiling fityk go to src/, // run "make java" with proper paths. On Fedora Linux it means: // $ JAVAINC=/usr/lib/jvm/java/include // $ make java CPPFLAGS="-I$JAVAINC -I/$JAVAINC/linux" // Put fitykJ.so into a directory in dynamic library path. // (libfityk.so should also be installed.) // - java files in swig/java are in "package fityk", so compile the files: // $ cd ..../src/swig/java // $ javac *.java // and put them in a directory named fityk in CLASSPATH. // Link will also do: // $ cd ..../samples // $ ln -s .../src/swig/java ./fityk; export CLASSPATH=. // Now you can try this sample: // $ java hello import fityk.Fityk; public class hello extends Fityk { static { System.loadLibrary("fitykJ"); } public static void main(String argv[]) { Fityk f = new Fityk(); System.out.println(f.get_info("version")); System.out.println("ln(2) = " + f.get_info("version")); hello g = new hello("nacl01.dat"); g.run(); g.save_session("tmp_save.fit"); } // Actual class content starts here. // It's named `hello' and kept in the same file as main because // we like each sample to be in a single file. String filename; public hello (String filename) { this.filename = filename; execute(String.format("@0 < '%s'", filename)); System.out.println("Data info:" + get_info("data", 0)); } public void run() { execute("guess %gauss = Gaussian"); System.out.println("Fitting " + filename + " ..."); execute("fit"); System.out.println("WSSR=" + get_wssr()); System.out.println("Gaussian center: " + calculate_expr("%gauss.center")); } public void save_session(String sessionFilename) { execute(String.format("info state >'%s'", sessionFilename)); } } fityk-1.3.1/samples/hello.lua000077500000000000000000000017561302634723100161310ustar00rootroot00000000000000-- Sample of Lua scripting in Fityk. -- -- Lua interpreter embedded in libfityk sets global F (an instance of -- fityk.Fityk) which can be used to access and change the state of the program. print("swig_type(F): ", swig_type(F)) -- -> stdout F:out("libfityk version: " .. F:get_info("version")) -- -> fityk output F:out("ln(2) = " .. F:calculate_expr("ln(2)")) F:out("Testing error handling...") status, err = pcall(function() F:execute("fit") end) if status == false then F:out("OK. Error caught: " .. err) end -- try to find directory of this file if type(arg) == 'table' then directory = string.match(arg[0], "^.*[/\\]") or "" else directory = "" end filename = directory .. "nacl01.dat" F:execute("@0 < '"..filename.."'") F:out("Data info: "..F:get_info("data", 0)) F:execute("guess %gauss = Gaussian") F:out("Fitting "..filename.." ...") F:execute("fit") F:out("WSSR="..F:get_wssr()) F:out("Gaussian center: "..F:calculate_expr("%gauss.center")) F:execute("info state >tmp_save.fit") fityk-1.3.1/samples/hello.pl000077500000000000000000000023101302634723100157460ustar00rootroot00000000000000#!/usr/bin/perl -w use Fityk; my $ftk = new Fityk::Fityk; printf "libfityk version: %s\n", $ftk->get_info("version", 0); printf "ln(2) = %g\n", $ftk->calculate_expr("ln(2)"); # check error handling print "Croaks on error: ", ($ftk->get_throws() ? "yes" : "no" ), "\n"; $ftk->set_throws(0); print "Croaks on error: ", ($ftk->get_throws() ? "yes" : "no" ), "\n"; $ftk->last_error() and print "last error: ", $ftk->last_error(), "\n"; $ftk->execute("bleh"); # SyntaxError $ftk->last_error() and print "last error: ", $ftk->last_error(), "\n"; $ftk->execute("fit"); # ExecuteError $ftk->last_error() and print "last error: ", $ftk->last_error(), "\n"; $ftk->clear_last_error(); $ftk->redir_messages(STDOUT); # redirect fityk messages to stdout #$ftk->redir_messages(0); # this disables fityk messages my $filename = "nacl01.dat"; print "Reading data from $filename ...\n"; $ftk->execute("\@0 < '$filename'"); printf "Data info:\n%s\n", $ftk->get_info('data', 0); $ftk->execute('guess %gauss = Gaussian'); print "Fitting...\n"; $ftk->execute("fit"); printf "WSSR=%f\n", $ftk->get_wssr(); printf "Gaussian center: %g\n", $ftk->calculate_expr("%gauss.center"); $ftk->execute("info state >tmp_save.fit"); $ftk->DESTROY(); fityk-1.3.1/samples/hello.py000077500000000000000000000021041302634723100157640ustar00rootroot00000000000000#!/usr/bin/env python import os.path, sys from fityk import Fityk class GaussianFitter(Fityk): def __init__(self, filename): Fityk.__init__(self) if not os.path.isfile(filename): raise ValueError("File `%s' not found." % filename) self.filename = filename self.execute("@0 < '%s'" % filename) print "Data info:", self.get_info("data", 0) def run(self): self.execute("guess Gaussian") gauss = self.all_functions()[-1] # the last function (just created) print "initial Gaussian center: %g" % gauss.get_param_value("center") print "Fitting %s ..." % self.filename self.execute("fit") print "WSSR=", self.get_wssr() print "Gaussian center: %g" % gauss.get_param_value("center") def save_session(self, filename): self.execute("info state >'%s'" % filename) f = Fityk() print f.get_info("version") print "ln(2) =", f.calculate_expr("ln(2)") del f g = GaussianFitter(os.path.join(os.path.dirname(sys.argv[0]), "nacl01.dat")) g.run() g.save_session("tmp_save.fit") fityk-1.3.1/samples/hello.rb000077500000000000000000000017661302634723100157540ustar00rootroot00000000000000#!/usr/bin/env ruby # Example of using libfityk from ruby. # To run this example, you need fityk extension for Ruby: after compiling # fityk go to src/, run "make ruby" and copy swig/fityk.so. require 'fityk' class GaussianFitter < Fityk::Fityk def initialize(filename) super() raise "File `#{filename}' not found." unless File::exists? filename @filename = filename execute("@0 < '#{filename}'") puts "Data info: " + get_info("data", 0) end def run() execute("guess %gauss = Gaussian") puts "Fitting #{@filename}..." execute("fit") puts "WSSR=%g" % get_wssr() puts "Gaussian center: %.5g" % calculate_expr("%gauss.center") end def save_session(filename) execute("info state >'%s'" % filename) end end f = Fityk::Fityk.new puts f.get_info("version") puts "ln(2) = %.9f" % f.calculate_expr("ln(2)") f = nil gauss = GaussianFitter.new("nacl01.dat") gauss.run() gauss.save_session("tmp_save.fit") fityk-1.3.1/samples/nacl01.dat000066400000000000000000000266201302634723100160650ustar00rootroot0000000000000019.9143 31 19.953 25 19.9917 27 20.0304 32 20.069 21 20.1077 19 20.1464 28 20.1851 30 20.2238 36 20.2625 31 20.3012 33 20.3399 26 20.3786 24 20.4173 39 20.4559 31 20.4946 30 20.5333 34 20.572 36 20.6107 36 20.6494 41 20.6881 30 20.7268 41 20.7655 36 20.8042 47 20.8428 31 20.8815 41 20.9202 41 20.9589 51 20.9976 50 21.0363 54 21.075 60 21.1137 81 21.1524 111 21.1911 181 21.2297 218 21.2684 336 21.3071 441 21.3458 570 21.3845 586 21.4232 494 21.4619 456 21.5006 367 21.5393 278 21.578 198 21.6166 139 21.6553 116 21.694 74 21.7327 69 21.7714 53 21.8101 62 21.8488 35 21.8875 55 21.9262 51 21.9649 44 22.0035 52 22.0422 54 22.0809 47 22.1196 44 22.1583 60 22.197 54 22.2357 55 22.2744 51 22.3131 48 22.3517 57 22.3904 50 22.4291 66 22.4678 62 22.5065 71 22.5452 52 22.5839 63 22.6226 60 22.6613 54 22.7 71 22.7386 56 22.7773 75 22.816 83 22.8547 67 22.8934 78 22.9321 74 22.9708 69 23.0095 59 23.0482 85 23.0869 79 23.1255 76 23.1642 65 23.2029 72 23.2416 80 23.2803 82 23.319 93 23.3577 99 23.3964 74 23.4351 91 23.4738 75 23.5124 122 23.5511 112 23.5898 103 23.6285 111 23.6672 94 23.7059 104 23.7446 131 23.7833 109 23.822 180 23.8607 177 23.8993 200 23.938 225 23.9767 271 24.0154 284 24.0541 343 24.0928 300 24.1315 311 24.1702 380 24.2089 382 24.2476 406 24.2862 498 24.3249 608 24.3636 1036 24.4023 1973 24.441 4132 24.4797 7808 24.5184 14314 24.5571 24268 24.5958 36953 24.6345 50000 24.6731 60969 24.7118 66424 24.7505 64484 24.7892 56587 24.8279 43799 24.8666 30844 24.9053 19309 24.944 11123 24.9827 5894 25.0214 2968 25.06 1415 25.0987 825 25.1374 507 25.1761 317 25.2148 260 25.2535 221 25.2922 185 25.3309 164 25.3696 155 25.4082 126 25.4469 96 25.4856 108 25.5243 111 25.563 92 25.6017 103 25.6404 89 25.6791 88 25.7178 103 25.7565 86 25.7951 88 25.8338 88 25.8725 81 25.9112 68 25.9499 97 25.9886 81 26.0273 82 26.066 81 26.1047 79 26.1434 89 26.182 71 26.2207 63 26.2594 77 26.2981 62 26.3368 63 26.3755 85 26.4142 92 26.4529 90 26.4916 64 26.5303 74 26.5689 85 26.6076 82 26.6463 66 26.685 73 26.7237 68 26.7624 60 26.8011 72 26.8398 82 26.8785 65 26.9172 79 26.9558 67 26.9945 76 27.0332 95 27.0719 94 27.1106 101 27.1493 116 27.188 110 27.2267 108 27.2654 128 27.3041 121 27.3427 117 27.3814 98 27.4201 109 27.4588 92 27.4975 80 27.5362 83 27.5749 73 27.6136 68 27.6523 91 27.691 62 27.7296 86 27.7683 77 27.807 92 27.8457 103 27.8844 82 27.9231 84 27.9618 90 28.0005 90 28.0392 74 28.0779 70 28.1165 79 28.1552 80 28.1939 69 28.2326 76 28.2713 59 28.31 75 28.3487 67 28.3874 80 28.4261 77 28.4647 81 28.5034 80 28.5421 89 28.5808 76 28.6195 81 28.6582 70 28.6969 67 28.7356 73 28.7743 73 28.813 63 28.8516 76 28.8903 77 28.929 68 28.9677 82 29.0064 80 29.0451 65 29.0838 66 29.1225 79 29.1612 77 29.1999 72 29.2385 77 29.2772 69 29.3159 81 29.3546 75 29.3933 82 29.432 74 29.4707 85 29.5094 93 29.5481 75 29.5868 76 29.6254 77 29.6641 81 29.7028 74 29.7415 70 29.7802 76 29.8189 82 29.8576 69 29.8963 78 29.935 70 29.9737 110 30.0123 109 30.051 138 30.0897 129 30.1284 115 30.1671 127 30.2058 124 30.2445 144 30.2832 145 30.3219 134 30.3606 153 30.3992 146 30.4379 134 30.4766 148 30.5153 137 30.554 157 30.5927 168 30.6314 137 30.6701 164 30.7088 150 30.7475 143 30.7861 169 30.8248 134 30.8635 137 30.9022 137 30.9409 176 30.9796 127 31.0183 145 31.057 143 31.0957 160 31.1344 149 31.173 139 31.2117 153 31.2504 156 31.2891 151 31.3278 171 31.3665 126 31.4052 135 31.4439 139 31.4826 157 31.5212 131 31.5599 114 31.5986 179 31.6373 135 31.676 163 31.7147 164 31.7534 147 31.7921 144 31.8308 127 31.8695 143 31.9081 154 31.9468 151 31.9855 144 32.0242 152 32.0629 174 32.1016 170 32.1403 126 32.179 155 32.2177 137 32.2564 153 32.295 137 32.3337 158 32.3724 152 32.4111 163 32.4498 134 32.4885 134 32.5272 165 32.5659 170 32.6046 158 32.6433 159 32.6819 177 32.7206 159 32.7593 177 32.798 162 32.8367 194 32.8754 218 32.9141 193 32.9528 186 32.9915 193 33.0302 186 33.0688 163 33.1075 177 33.1462 149 33.1849 180 33.2236 151 33.2623 155 33.301 164 33.3397 151 33.3784 143 33.4171 160 33.4557 146 33.4944 159 33.5331 165 33.5718 162 33.6105 153 33.6492 148 33.6879 172 33.7266 195 33.7653 157 33.804 162 33.8426 165 33.8813 194 33.92 155 33.9587 181 33.9974 171 34.0361 167 34.0748 186 34.1135 159 34.1522 164 34.1909 168 34.2295 175 34.2682 189 34.3069 186 34.3456 215 34.3843 251 34.423 242 34.4617 251 34.5004 373 34.5391 402 34.5777 577 34.6164 771 34.6551 1178 34.6938 1659 34.7325 2398 34.7712 3211 34.8099 4054 34.8486 4871 34.8873 5571 34.926 6000 34.9646 5882 35.0033 5583 35.042 4818 35.0807 3992 35.1194 3076 35.1581 2389 35.1968 1630 35.2355 1223 35.2742 805 35.3129 596 35.3515 427 35.3902 362 35.4289 269 35.4676 266 35.5063 242 35.545 184 35.5837 186 35.6224 208 35.6611 208 35.6998 176 35.7384 202 35.7771 175 35.8158 191 35.8545 183 35.8932 191 35.9319 202 35.9706 165 36.0093 158 36.048 177 36.0867 178 36.1253 186 36.164 162 36.2027 182 36.2414 169 36.2801 167 36.3188 149 36.3575 157 36.3962 154 36.4349 198 36.4736 147 36.5122 158 36.5509 170 36.5896 171 36.6283 165 36.667 173 36.7057 160 36.7444 163 36.7831 167 36.8218 175 36.8605 177 36.8991 166 36.9378 162 36.9765 169 37.0152 169 37.0539 159 37.0926 161 37.1313 167 37.17 167 37.2087 162 37.2474 185 37.286 144 37.3247 194 37.3634 138 37.4021 173 37.4408 146 37.4795 164 37.5182 189 37.5569 157 37.5956 163 37.6342 164 37.6729 166 37.7116 162 37.7503 171 37.789 170 37.8277 183 37.8664 186 37.9051 185 37.9438 163 37.9825 194 38.0211 199 38.0598 153 38.0985 167 38.1372 154 38.1759 171 38.2146 171 38.2533 184 38.292 165 38.3307 177 38.3694 163 38.408 168 38.4467 148 38.4854 159 38.5241 166 38.5628 175 38.6015 167 38.6402 150 38.6789 174 38.7176 189 38.7563 187 38.7949 157 38.8336 176 38.8723 160 38.911 171 38.9497 165 38.9884 166 39.0271 180 39.0658 179 39.1045 192 39.1432 167 39.1818 188 39.2205 189 39.2592 173 39.2979 188 39.3366 206 39.3753 204 39.414 230 39.4527 234 39.4914 228 39.5301 201 39.5687 264 39.6074 206 39.6461 228 39.6848 211 39.7235 199 39.7622 153 39.8009 189 39.8396 188 39.8783 150 39.917 176 39.9556 159 39.9943 174 40.033 157 40.0717 153 40.1104 171 40.1491 145 40.1878 163 40.2265 158 40.2652 161 40.3039 152 40.3425 149 40.3812 154 40.4199 157 40.4586 170 40.4973 169 40.536 179 40.5747 190 40.6134 182 40.6521 187 40.6907 194 40.7294 228 40.7681 268 40.8068 285 40.8455 298 40.8842 339 40.9229 355 40.9616 381 41.0003 396 41.039 366 41.0776 315 41.1163 292 41.155 257 41.1937 233 41.2324 229 41.2711 204 41.3098 178 41.3485 193 41.3872 165 41.4259 165 41.4645 171 41.5032 165 41.5419 139 41.5806 151 41.6193 161 41.658 168 41.6967 174 41.7354 142 41.7741 168 41.8128 163 41.8514 171 41.8901 178 41.9288 178 41.9675 159 42.0062 157 42.0449 157 42.0836 168 42.1223 180 42.161 169 42.1997 171 42.2383 187 42.277 198 42.3157 217 42.3544 228 42.3931 267 42.4318 366 42.4705 432 42.5092 584 42.5479 771 42.5866 1056 42.6252 1284 42.6639 1583 42.7026 1736 42.7413 2011 42.78 2045 42.8187 2079 42.8574 1924 42.8961 1754 42.9348 1505 42.9735 1161 43.0121 956 43.0508 713 43.0895 547 43.1282 419 43.1669 306 43.2056 298 43.2443 267 43.283 230 43.3217 213 43.3604 199 43.399 193 43.4377 180 43.4764 166 43.5151 192 43.5538 174 43.5925 144 43.6312 158 43.6699 167 43.7086 204 43.7472 180 43.7859 193 43.8246 159 43.8633 174 43.902 152 43.9407 149 43.9794 148 44.0181 166 44.0568 152 44.0955 197 44.1341 148 44.1728 148 44.2115 162 44.2502 171 44.2889 175 44.3276 170 44.3663 172 44.405 159 44.4437 165 44.4824 181 44.521 150 44.5597 166 44.5984 187 44.6371 175 44.6758 157 44.7145 200 44.7532 141 44.7919 175 44.8306 152 44.8693 179 44.9079 160 44.9466 136 44.9853 184 45.024 168 45.0627 138 45.1014 158 45.1401 158 45.1788 182 45.2175 169 45.2562 178 45.2948 177 45.3335 171 45.3722 159 45.4109 167 45.4496 168 45.4883 180 45.527 161 45.5657 141 45.6044 173 45.6431 183 45.6817 180 45.7204 190 45.7591 192 45.7978 157 45.8365 192 45.8752 166 45.9139 197 45.9526 158 45.9913 182 46.03 179 46.0686 169 46.1073 175 46.146 165 46.1847 166 46.2234 165 46.2621 194 46.3008 174 46.3395 178 46.3782 185 46.4169 160 46.4555 182 46.4942 178 46.5329 188 46.5716 178 46.6103 173 46.649 160 46.6877 192 46.7264 172 46.7651 183 46.8037 178 46.8424 209 46.8811 180 46.9198 165 46.9585 193 46.9972 207 47.0359 184 47.0746 181 47.1133 180 47.152 181 47.1906 191 47.2293 207 47.268 204 47.3067 204 47.3454 195 47.3841 194 47.4228 193 47.4615 209 47.5002 183 47.5389 177 47.5775 222 47.6162 213 47.6549 222 47.6936 245 47.7323 223 47.771 209 47.8097 214 47.8484 221 47.8871 249 47.9258 223 47.9644 206 48.0031 231 48.0418 232 48.0805 226 48.1192 221 48.1579 213 48.1966 231 48.2353 238 48.274 248 48.3127 237 48.3513 250 48.39 231 48.4287 227 48.4674 266 48.5061 269 48.5448 282 48.5835 247 48.6222 272 48.6609 291 48.6996 322 48.7382 290 48.7769 292 48.8156 301 48.8543 309 48.893 326 48.9317 385 48.9704 373 49.0091 436 49.0478 516 49.0865 622 49.1251 799 49.1638 1140 49.2025 1505 49.2412 2019 49.2799 2560 49.3186 3221 49.3573 3824 49.396 4140 49.4347 4377 49.4734 4166 49.512 3862 49.5507 3371 49.5894 2696 49.6281 2166 49.6668 1537 49.7055 1042 49.7442 724 49.7829 493 49.8216 347 49.8602 269 49.8989 181 49.9376 187 49.9763 152 50.015 160 50.0537 136 50.0924 123 50.1311 114 50.1698 118 50.2085 116 50.2471 126 50.2858 116 50.3245 140 50.3632 106 50.4019 134 50.4406 110 50.4793 112 50.518 108 50.5567 117 50.5954 94 50.634 94 50.6727 112 50.7114 111 50.7501 121 50.7888 114 50.8275 127 50.8662 96 50.9049 94 50.9436 104 50.9823 89 51.0209 101 51.0596 118 51.0983 106 51.137 102 51.1757 114 51.2144 100 51.2531 95 51.2918 88 51.3305 95 51.3692 110 51.4078 100 51.4465 87 51.4852 116 51.5239 87 51.5626 118 51.6013 101 51.64 110 51.6787 82 51.7174 93 51.7561 117 51.7947 96 51.8334 94 51.8721 95 51.9108 91 51.9495 105 51.9882 104 52.0269 112 52.0656 96 52.1043 100 52.143 94 52.1816 95 52.2203 94 52.259 126 52.2977 96 52.3364 113 52.3751 104 fityk-1.3.1/samples/nacl01.fit000066400000000000000000000007541302634723100160770ustar00rootroot00000000000000# Fityk 1.1.2 ### the minimal example @0 < '_SCRIPT_DIR_/nacl01.dat' # load data from file a = (23.0 < x and x < 26.0) # disactivate data outside of (23.0,26.0) range. %p = Gaussian(~60000, ~24.6, ~0.2) # define function %p with type Gaussian # and fittable parameters F += %p # add function %p to curve, which will be fitted to data fit # and fit using default fitting method with default settings info prop %p # show properties of the function fityk-1.3.1/samples/read-shockley.fit000066400000000000000000000007321302634723100175470ustar00rootroot00000000000000# Fityk 0.9.7 ### see: https://github.com/wojdyr/fityk/wiki/ReadShockley M=9 X[0]=0, X[1]=4.24, X[2]=6.73, X[3]=8.80, X[4]=10.39, X[5]=12.68, X[6]=14.25, X[7]=16.26, X[8]=18.93 Y[0]=0, Y[1]=1.06, Y[2]=1.39, Y[3]=1.61, Y[4]= 1.75, Y[5]= 1.94, Y[6]= 2.07, Y[7]= 2.02, Y[8]= 2.30 A = X > 0 and X < 15 # Read-Shockley equation (with degrees to radians conversion) define ReadShockley(sigma0=1, a=1) = sigma0 * t * (a - ln(t)) where t=x*pi/180 guess ReadShockley plot [] fit fityk-1.3.1/tests/000077500000000000000000000000001302634723100140055ustar00rootroot00000000000000fityk-1.3.1/tests/catch.cpp000066400000000000000000000001751302634723100155760ustar00rootroot00000000000000 // building CATCH main is slow so we build it in a separate translation unit #define CATCH_CONFIG_MAIN #include "catch.hpp" fityk-1.3.1/tests/gradient.cpp000066400000000000000000000107041302634723100163100ustar00rootroot00000000000000 #include #include #include "fityk/logic.h" #include "fityk/data.h" #include "fityk/fit.h" #include "catch.hpp" using namespace std; using namespace fityk; // Box and Betts exponential quadratic sum, equivalent to least-squares of // f(x) = exp(-0.1*a0*x) - exp(-0.1*a1*x) - a2 * (exp(-0.1*x) - exp(-x)) // with points (1,0), (2,0), ... (10,0) // // domains of a0, a1, a2 are, respectively, (0.9, 1.2), (9, 11.2), (0.9, 1.2) // minimum: (1,10,1) -> 0 // modified boxbetts_f() from nlopt-2.3/test/testfuncs.c static double boxbetts_f(const double *a, double *grad) { double f = 0; if (grad) grad[0] = grad[1] = grad[2] = 0; for (int x = 1; x <= 10; ++x) { double e0 = exp(-0.1*x*a[0]); double e1 = exp(-0.1*x*a[1]); double e2 = exp(-0.1*x) - exp(-x); double g = e0 - e1 - e2 * a[2]; f += g*g; if (grad) { grad[0] += (2 * g) * (-0.1*x*e0); grad[1] += (2 * g) * (0.1*x*e1); grad[2] += -(2 * g) * e2; } } return f; } static double boxbetts_in_fityk(const double *a, double *grad) { boost::scoped_ptr ftk(new Fityk); Full* priv = ftk->priv(); ftk->set_option_as_number("verbosity", -1); for (int i = 1; i <= 10; ++i) priv->dk.data(0)->add_one_point(i, 0, 1); ftk->execute("define BoxBetts(a0,a1,a2) = " "exp(-0.1*a0*x) - exp(-0.1*a1*x) - a2 * (exp(-0.1*x) - exp(-x))"); ftk->execute("F = BoxBetts(~0.9, ~11.8, ~1.08)"); priv->get_fit()->get_dof(priv->dk.datas()); // to invoke update_par_usage() vector avec(a, a+3); return priv->get_fit()->compute_wssr_gradient(avec, priv->dk.datas(), grad); } #if 0 static int test_gradient() { const double a[3] = { 0.9, 11.8, 1.08 }; double grad[3], grad_again[3]; double ssr = boxbetts_f(a, grad); printf("ssr=%.10g grad: %.10g %.10g %.10g\n", ssr, grad[0], grad[1], grad[2]); double ssr_again = boxbetts_in_fityk(a, grad_again); printf("ssr=%.10g grad: %.10g %.10g %.10g\n", ssr_again, grad_again[0], grad_again[1], grad_again[2]); return 0; } int main() { return test_gradient(); } #endif TEST_CASE("gradient", "test Fit::compute_wssr_gradient()") { const double a[3] = { 0.9, 11.8, 1.08 }; double grad[3], grad_again[3]; double ssr = boxbetts_f(a, grad); double ssr_again = boxbetts_in_fityk(a, grad_again); REQUIRE(ssr == Approx(ssr_again)); REQUIRE(grad[0] == Approx(grad_again[0])); REQUIRE(grad[1] == Approx(grad_again[1])); REQUIRE(grad[2] == Approx(grad_again[2])); } //----------- + some unrelated random tests TEST_CASE("set-throws", "test Fityk::set_throws()") { boost::scoped_ptr fik(new Fityk); REQUIRE(fik->get_throws() == true); REQUIRE_THROWS_AS(fik->execute("hi"), SyntaxError); REQUIRE_THROWS_AS(fik->execute("fit"), ExecuteError); fik->set_throws(false); REQUIRE_NOTHROW(fik->execute("hi")); fik->execute("hi"); REQUIRE(fik->last_error() != ""); REQUIRE(fik->last_error().substr(0,12) == "SyntaxError:"); fik->clear_last_error(); REQUIRE(fik->last_error() == ""); } TEST_CASE("set-get-option", "test Fityk::[gs]et_option_as_*()") { boost::scoped_ptr fik(new Fityk); REQUIRE(fik->get_option_as_string("numeric_format") == "%g"); // string REQUIRE(fik->get_option_as_string("on_error") == "stop"); // enum REQUIRE(fik->get_option_as_number("verbosity") == 0.); // integer REQUIRE(fik->get_option_as_number("fit_replot") == 0.); // bool REQUIRE(fik->get_option_as_number("epsilon") == 1e-12); // double // no such option REQUIRE_THROWS_AS(fik->get_option_as_string("hi"), ExecuteError); // non-numeric option REQUIRE_THROWS_AS(fik->get_option_as_number("on_error"), ExecuteError); REQUIRE_THROWS_AS(fik->get_option_as_number("cwd"), ExecuteError); fik->set_option_as_string("numeric_format", "%.8E"); fik->set_option_as_string("on_error", "nothing"); fik->set_option_as_number("verbosity", -1); fik->set_option_as_number("fit_replot", 1); fik->set_option_as_number("epsilon", 1e-10); REQUIRE(fik->get_option_as_string("numeric_format") == "%.8E"); // string REQUIRE(fik->get_option_as_string("on_error") == "nothing"); // enum REQUIRE(fik->get_option_as_number("verbosity") == -1); // integer REQUIRE(fik->get_option_as_number("fit_replot") == 1.); // bool REQUIRE(fik->get_option_as_number("epsilon") == 1e-10); // double } fityk-1.3.1/tests/guess.cpp000066400000000000000000000044001302634723100156350ustar00rootroot00000000000000 #include #include #include "fityk/logic.h" #include "fityk/guess.h" #include "fityk/data.h" #include "catch.hpp" using namespace std; using namespace fityk; // data from http://www.itl.nist.gov/div898/strd/lls/data/LINKS/DATA/Norris.dat namespace norris { const double yx[][2] = { { 0.1 , 0.2 }, { 338.8 , 337.4 }, { 118.1 , 118.2 }, { 888.0 , 884.6 }, { 9.2 , 10.1 }, { 228.1 , 226.5 }, { 668.5 , 666.3 }, { 998.5 , 996.3 }, { 449.1 , 448.6 }, { 778.9 , 777.0 }, { 559.2 , 558.2 }, { 0.3 , 0.4 }, { 0.1 , 0.6 }, { 778.1 , 775.5 }, { 668.8 , 666.9 }, { 339.3 , 338.0 }, { 448.9 , 447.5 }, { 10.8 , 11.6 }, { 557.7 , 556.0 }, { 228.3 , 228.1 }, { 998.0 , 995.8 }, { 888.8 , 887.6 }, { 119.6 , 120.2 }, { 0.3 , 0.3 }, { 0.6 , 0.3 }, { 557.6 , 556.8 }, { 339.3 , 339.1 }, { 888.0 , 887.2 }, { 998.5 , 999.0 }, { 778.9 , 779.0 }, { 10.2 , 11.1 }, { 117.6 , 118.3 }, { 228.9 , 229.2 }, { 668.4 , 669.1 }, { 449.2 , 448.9 }, { 0.2 , 0.5 } }; const double cert_b0 = -0.262323073774029; const double cert_b1 = 1.00211681802045; } // namespace norris template bool is_vector_sorted(const vector& v) { for (typename vector::const_iterator i = v.begin()+1; i < v.end(); ++i) if (*i < *(i-1)) return false; return true; } TEST_CASE("linear-guess", "test Guess::estimate_linear_parameters()") { boost::scoped_ptr ftk(new Full); Data *data = ftk->dk.data(0); //ftk->settings_mgr()->set_as_number("verbosity", -1); int n = sizeof(norris::yx) / sizeof(norris::yx[0]); for (int i = 0; i < n; ++i) { double x = norris::yx[i][1]; double y = norris::yx[i][0]; data->add_one_point(x, y, 1); } REQUIRE(is_vector_sorted(data->points())); Guess g(ftk->get_settings()); g.set_data(ftk->dk.data(0), RealRange(), -1); vector lin_est = g.estimate_linear_parameters(); //printf("slope %.14f\nintercept %.14f\n", lin_est[0], lin_est[1]); REQUIRE(lin_est[0] == Approx(norris::cert_b1)); REQUIRE(lin_est[1] == Approx(norris::cert_b0)); } fityk-1.3.1/tests/lua.cpp000066400000000000000000000007301302634723100152720ustar00rootroot00000000000000 #include #include #include "fityk/fityk.h" #include "fityk/logic.h" #include "fityk/luabridge.h" #include "catch.hpp" TEST_CASE("formatted F:execute", "") { boost::scoped_ptr fik(new fityk::Fityk); fityk::Full* priv = fik->priv(); std::string str = "a=123.456; F:execute('$v = %g' % a)"; priv->lua_bridge()->exec_lua_string(str); double v = fik->get_variable("v")->value(); REQUIRE(v == 123.456); } fityk-1.3.1/tests/mpfit_deriv.cpp000066400000000000000000000012611302634723100170210ustar00rootroot00000000000000 #include "fityk/fityk.h" // When the deriv_debug option is used in MPFIT // both user-calculated and MPFIT-calculated numerical derivatives // are printed to stdout. This test is half-manual. namespace fityk { extern bool debug_deriv_in_mpfit; } int main() { fityk::debug_deriv_in_mpfit=true; fityk::Fityk* ftk = new fityk::Fityk; ftk->execute("set verbosity=-1"); ftk->execute("set pseudo_random_seed=1234567"); ftk->execute("M=40; x=n/5"); ftk->execute("Y = 4.5 + 0.5*x + 37*exp(-ln(2)*((x-3.1)/0.7)^2)"); ftk->execute("guess Linear; guess Gaussian"); ftk->execute("set fitting_method=mpfit"); ftk->execute("fit"); delete ftk; return 0; } fityk-1.3.1/tests/num.cpp000066400000000000000000000037771302634723100153260ustar00rootroot00000000000000 #include #include "fityk/numfuncs.h" #include "catch.hpp" using std::vector; using fityk::invert_matrix; TEST_CASE("invert-matrix-1x1", "") { vector mat(1, 4.); invert_matrix(mat, 1); REQUIRE(mat[0] == 0.25); } TEST_CASE("invert-matrix-4x4", "") { const double a[16] = { 1., 2., 3., 4., -1., 0., 1., 2., 2., 3., 1., 4., 1., 2., 1., 0. }; const double a_inv[16] = { 0.5, -1.0, 0.0, -0.5, -0.5, 0.6, 0.2, 0.7, 0.5, -0.2, -0.4, 0.1, 0.0, 0.1, 0.2, -0.3 }; vector mat(a, a+16); invert_matrix(mat, 4); for (size_t i = 0; i != mat.size(); ++i) REQUIRE(mat[i] == Approx(a_inv[i])); invert_matrix(mat, 4); for (size_t i = 0; i != mat.size(); ++i) REQUIRE(mat[i] == Approx(a[i])); } TEST_CASE("invert-matrix-with-zeros", "") { const double a[9] = { 4., 0., 7., 0., 0., 0., 2., 0., 6. }; const double a_inv[9] = { 0.6, 0.0, -0.7, 0.0, 0.0, 0.0, -0.2, 0.0, 0.4 }; vector mat(a, a+9); invert_matrix(mat, 3); for (size_t i = 0; i != mat.size(); ++i) REQUIRE(mat[i] == Approx(a_inv[i])); } /* TEST_CASE("pseudo-inverse", "") { const double a[16] = { 1., 2., 3., 4., -1., 0., 1., 2., 1., 2., 3., 4., // same as 1st row 1., 2., 1., 0. }; const double a_inv[16] = { 0.25 , -1. , 0.25 , -0.5 , -0.125, 5./12., -0.125, 2./3., 0. , 1./6. , 0. , 1./6., 0.125, -1./12., 0.125, -1./3. }; //a . a_inv = almost I, rows 1 and 3 are avaraged [.5 0 .5 0] vector mat(a, a+16); invert_matrix(mat, 4); for (size_t i = 0; i != mat.size(); ++i) REQUIRE(mat[i] == Approx(a_inv[i])); invert_matrix(mat, 4); for (size_t i = 0; i != mat.size(); ++i) REQUIRE(mat[i] == Approx(a[i])); } */ fityk-1.3.1/tests/psvoigt.cpp000066400000000000000000000113421302634723100162050ustar00rootroot00000000000000 #include #include #include "fityk/fityk.h" // derivatives need private API #include "fityk/logic.h" #include "fityk/model.h" // get_nonzero_range() needs private API #include "fityk/func.h" #include "catch.hpp" using namespace std; // these definitions of Pseudo-Voigt should be identical to the built-in one. static const char* PV2 = "define PV2(height, center, hwhm, shape) = " "Gaussian((1-shape)*height, center, hwhm) + " "Lorentzian(shape*height, center, hwhm)"; static const char* PV3 = "define PV3(height, center, hwhm, shape) = " "(1-shape)*height*exp(-ln(2)*((x-center)/hwhm)^2) + " "shape*height/(1+((x-center)/hwhm)^2)"; static const char* PV4 = "define PV4(height, center, hwhm, shape) = " "SplitPseudoVoigt(height, center, hwhm, hwhm, shape, shape)"; TEST_CASE("pseudo-voigt", "") { boost::scoped_ptr fik(new fityk::Fityk); fik->set_option_as_number("verbosity", -1); fik->execute(PV2); fik->execute(PV3); fik->execute(PV4); const char* types[] = { "PseudoVoigt", "PV2", "PV3", "PV4" }; for (int i = 0; i < 4; ++i) { string t = types[i]; INFO( "Testing " << t ); fik->execute("%pv = " + t + "(~1.2, ~2.3, ~3.4, ~0.3)"); double height = fik->calculate_expr("%pv.height"); REQUIRE(height == 1.2); double center = fik->calculate_expr("%pv.Center"); REQUIRE(center == 2.3); if (t != "PV3") { if (t != "PV2") { double fwhm = fik->calculate_expr("%pv.FWHM"); REQUIRE(fwhm == 2*3.4); } double area = fik->calculate_expr("%pv.Area"); REQUIRE(area == Approx(9.925545022985)); double H = fik->calculate_expr("%pv.Height"); REQUIRE(H == height); double ib = fik->calculate_expr("%pv.IB"); REQUIRE(ib == area/height); } const fityk::Func *f = fik->get_function("pv"); double at_ctr = f->value_at(center); REQUIRE(at_ctr == height); double at_2 = f->value_at(2); REQUIRE(at_2 == Approx(1.1926980547071)); double at_3 = f->value_at(3); REQUIRE(at_3 == Approx(1.1610401512578)); fik->execute("F=%pv"); vector deriv = fik->priv()->dk.get_model(0)->get_symbolic_derivatives(3.0, NULL); double expected_deriv[5] = { 0.967533459381518, 0.108597246412477, 0.022358256614333, -0.014052616793924, -0.108597246412477 }; for (int j = 0; j != 5; ++j) REQUIRE(deriv[j] == Approx(expected_deriv[j])); } } // test Function::get_nonzero_range() implementations static double nonzero_left(double level, const string& func) { boost::scoped_ptr fik(new fityk::Fityk); fik->set_option_as_number("verbosity", -1); fik->execute("%f = " + func); const fityk::Func *f = fik->get_function("f"); double left, right; const fityk::Function *fpriv = dynamic_cast(f); bool r = fpriv->get_nonzero_range(level, left, right); REQUIRE(r == true); double y_left = f->value_at(left); return y_left; } TEST_CASE("Gaussian::get_nonzero_range()", "") { REQUIRE(nonzero_left(0.01, "Gaussian(0.9, 11.8, 1.08)") == Approx(0.01)); REQUIRE(nonzero_left(1e-5, "Gaussian(-20.2, -0.8, 6.7)") == Approx(-1e-5)); } TEST_CASE("Lorentzian::get_nonzero_range()", "") { REQUIRE(nonzero_left(0.01, "Lorentzian(0.9, 11.8, 1.08)") == Approx(0.01)); REQUIRE(nonzero_left(1e-5, "Lorentzian(-20, -0.8, 6.7)") == Approx(-1e-5)); } TEST_CASE("Pearson7::get_nonzero_range()", "") { REQUIRE(nonzero_left(0.01, "Pearson7(0.9, 11.8, 1.08, 1.3)") == Approx(0.01)); REQUIRE(nonzero_left(1e-5, "Pearson7(-20.2, -0.8, 6.7, 1.3)") == Approx(-1e-5)); } TEST_CASE("PseudoVoigt::get_nonzero_range()", "") { // PseudoVoigt::get_nonzero_range() uses rough estimation double b = nonzero_left(0.01, "PseudoVoigt(0.9, 11.8, 1.08, 0.7)"); REQUIRE(b > 0.004); REQUIRE(b < 0.01); REQUIRE(nonzero_left(1e-5, "PseudoVoigt(-20, -0.8, 6.7, 0.7)") == Approx(-1e-5)); } TEST_CASE("Voigt::get_nonzero_range()", "") { // Voigt::get_nonzero_range() also uses rough estimation double b1 = nonzero_left(0.04, "Voigt(0.9, 11.8, 1.08, 0.4)"); REQUIRE(b1 > 0.026); REQUIRE(b1 < 0.04); double b2 = nonzero_left(0.8, "Voigt(0.9, 11.8, 1.08, 1.8)"); REQUIRE(b2 > 0.7); REQUIRE(b2 < 0.8); double b3 = nonzero_left(0.2, "Voigt(0.9, 11.8, 1.08, 1.8)"); REQUIRE(b3 > 0.14); REQUIRE(b3 < 0.2); REQUIRE(nonzero_left(1e-5, "Voigt(-20, -0.8, 6.7, 1.1)") == Approx(-1e-5)); } fityk-1.3.1/tests/test_data_load.py000077500000000000000000000143101302634723100173300ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # run tests with: python -m unittest test_data_load # or python -m unittest discover import os import sys import random import tempfile import gzip import unittest import fityk #locale.setlocale(locale.LC_NUMERIC, 'C') class FileLoadBase(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) prefix = getattr(self, 'file_prefix', 'tmp') f = tempfile.NamedTemporaryFile(prefix=prefix, delete=False) self.data = self.generate_data() for d in self.data: f.write(self.line_format(d)) f.close() self.data.sort() self.filename = f.name def generate_data(self): return [(random.uniform(-100, 100), random.gauss(10, 20)) for _ in range(30)] def tearDown(self): #print "remove " + self.filename os.unlink(self.filename) def compare(self, out, ndigits): self.assertEqual([i.x for i in out], [round(i[0], ndigits) for i in self.data]) self.assertEqual([i.y for i in out], [round(i[1], ndigits) for i in self.data]) class TextFileLoadBase(FileLoadBase): def line_format(self, t): return " %.7f %.7f\n" % t def test_load(self): self.ftk.execute("@0 < '%s'" % self.filename) self.compare(self.ftk.get_data(), 7) def test_load_with_lua(self): self.ftk.execute("lua F:load([[%s]])" % self.filename) self.compare(self.ftk.get_data(), 7) def test_load_with_py(self): self.ftk.load(self.filename, 0) self.compare(self.ftk.get_data(), 7) class TestText(TextFileLoadBase): def test_load_strict(self): self.ftk.execute("@0 < '%s' text strict" % self.filename) self.compare(self.ftk.get_data(), 7) def test_load_decimal_comma(self): # this option only replaces commas with dots, so it's still possible # to read file with decimal point '.' self.ftk.execute("@0 < '%s' text decimal_comma" % self.filename) self.compare(self.ftk.get_data(), 7) class TestUtf8Filename(TextFileLoadBase): def setUp(self): self.file_prefix = 'tmp_Zażółć_gęślÄ…_jaźń' # string, not u'' FileLoadBase.setUp(self) class TestFilenameWithQuotes(TextFileLoadBase): def setUp(self): self.file_prefix = """tmp'"!@#""" FileLoadBase.setUp(self) def test_load(self): pass # would fail class TestTextComma(FileLoadBase): def line_format(self, t): return (" %.7f %.7f\n" % t).replace('.', ',') def test_load(self): self.ftk.execute("@0 < '%s' text decimal_comma" % self.filename) self.compare(self.ftk.get_data(), 7) def test_load_strict(self): self.ftk.execute("@0 < '%s' text decimal_comma strict" % self.filename) self.compare(self.ftk.get_data(), 7) def test_load_decimal_point(self): # should fail self.ftk.execute("@0 < '%s'" % self.filename) self.assertNotEqual([i.x for i in self.ftk.get_data()], [round(i[0], 7) for i in self.data]) class Test5ColsFile(FileLoadBase): def generate_data(self): return [(random.uniform(-100, 100), random.gauss(0, 20), random.gauss(10, 1), random.gauss(20, 1), random.gauss(30, 1)) for _ in range(30)] def line_format(self, t): return "%.7f %.7f %.7f %.7f %.7f\n" % t def test_load_default(self): self.ftk.execute("@0 < '%s'" % self.filename) self.compare(self.ftk.get_data(), ndigits=7) self.ftk.execute("@0 < '%s::::'" % self.filename) self.compare(self.ftk.get_data(), ndigits=7) self.ftk.execute("@0 < '%s:1:2::0'" % self.filename) self.compare(self.ftk.get_data(), ndigits=7) def test_load_with_index(self): self.ftk.execute("@0 < '%s:0:2::'" % self.filename) out = self.ftk.get_data() self.assertEqual([i.x for i in out], range(len(out))) def test_load_with_sigma(self): self.ftk.execute("@0 < '%s:1:2:3:'" % self.filename) out = self.ftk.get_data() self.assertEqual([i.sigma for i in out], [round(i[2], 7) for i in self.data]) def test_load_multi_y(self): self.ftk.execute("@+ < '%s:1:2..3,5:4:'" % self.filename) for n, y_col in enumerate([2,3,5]): out = self.ftk.get_data(n) self.assertEqual([i.x for i in out], [round(i[0], 7) for i in self.data]) self.assertEqual([i.y for i in out], [round(i[y_col-1], 7) for i in self.data]) self.assertEqual([i.sigma for i in out], [round(i[3], 7) for i in self.data]) class TestSimpleScript(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) f = tempfile.NamedTemporaryFile(delete=False) f.write("M=1\n X[0]=1.1, Y[0]=-5, S[0]=0.8") f.close() self.filename = f.name def tearDown(self): os.unlink(self.filename) def test_simple_script(self): self.ftk.get_ui_api().exec_fityk_script(self.filename) data = self.ftk.get_data() self.assertEqual(len(data), 1) self.assertEqual(data[0].x, 1.1) self.assertEqual(data[0].y, -5) self.assertEqual(data[0].sigma, 0.8) class TestGzippedScript(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) f = tempfile.NamedTemporaryFile(suffix='.gz', delete=False) self.filename = f.name gf = gzip.GzipFile(fileobj=f) gf.write("M=1\n X[0]=1.1, Y[0]=-5, S[0]=0.8") gf.close() def tearDown(self): os.unlink(self.filename) def test_gzipped_script(self): self.ftk.get_ui_api().exec_fityk_script(self.filename) data = self.ftk.get_data() self.assertEqual(len(data), 1) self.assertEqual(data[0].x, 1.1) self.assertEqual(data[0].y, -5) self.assertEqual(data[0].sigma, 0.8) if __name__ == '__main__': unittest.main() fityk-1.3.1/tests/test_guess.py000077500000000000000000000025661302634723100165600ustar00rootroot00000000000000#!/usr/bin/env python import os import sys import math import unittest import fityk class TestGuessability(unittest.TestCase): def setUp(self): xx = [(n-5)/2. for n in range(25)] yy = [11.2/(1+(x-3.3)**2) + math.sin(40*x)/40 - x/10. for x in xx] self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) self.ftk.load_data(0, xx, yy, [1]*len(xx), "loren") #self.ftk.execute("info state > debug.fit") def create_guessability_test(func_type): def do_test(self): self.ftk.execute("guess %f = " + func_type) f = self.ftk.get_function('f') self.assertIsInstance(f, fityk.Func) self.assertEqual(f.get_template_name(), func_type) try: ctr = f.get_param_value("Center") if func_type not in ['Sigmoid']: self.assertAlmostEqual(ctr, 3.3, delta=0.3) except fityk.ExecuteError: pass self.ftk.execute("delete %f") return do_test def add_guessability_tests(): all_types = fityk.Fityk().get_info('types') for func_type in all_types.split(): if func_type not in ['FCJAsymm']: test = create_guessability_test(func_type) test.__name__ = 'test_' + func_type setattr(TestGuessability, test.__name__, test) add_guessability_tests() if __name__ == '__main__': unittest.main() fityk-1.3.1/tests/test_info.py000077500000000000000000000030721302634723100163560ustar00rootroot00000000000000#!/usr/bin/env python # run tests with: python -m unittest test_info # or python -m unittest discover import unittest import fityk class TestFormula(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) self.voigt = "Voigt(926, 43.2, 0.144, 0.1)" self.splitvoigt = "SplitVoigt(926, 43.2, 0.144, 0.143, 0.1, 0.13)" self.splitvoigt_formula = ('x < 43.2 ? Voigt(926, 43.2, 0.144, 0.1) ' ': Voigt(926, 43.2, 0.143, 0.13)') def test_voigt(self): self.ftk.execute("F = " + self.voigt) formula = self.ftk.get_info("formula") self.assertEqual(formula, self.voigt) gaussian_fwhm=self.ftk.calculate_expr f_voigt = self.ftk.get_components(0)[0] gauss_fwhm = f_voigt.get_param_value('GaussianFWHM') self.assertEqual(round(gauss_fwhm, 13), 0.2397757280134) # not verified def test_voigt_s(self): self.ftk.execute("F = " + self.voigt) formula = self.ftk.get_info("simplified_formula") self.assertEqual(formula, self.voigt) def test_splitvoigt(self): self.ftk.execute("F = " + self.splitvoigt) formula = self.ftk.get_info("formula") self.assertEqual(formula, self.splitvoigt_formula) def test_splitvoigt_s(self): self.ftk.execute("F = " + self.splitvoigt) formula = self.ftk.get_info("simplified_formula") self.assertEqual(formula, self.splitvoigt_formula) if __name__ == '__main__': unittest.main() fityk-1.3.1/tests/test_model.py000077500000000000000000000135031302634723100165230ustar00rootroot00000000000000#!/usr/bin/env python # run tests with: python -m unittest test_model # or python -m unittest discover import os import sys import unittest import fityk class TestCopy(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) def test_copy_func(self): self.ftk.execute("%f = Gaussian(~10, ~0, 0.5)") self.ftk.execute("%g = copy(%f)") self.assertEqual(self.ftk.get_parameter_count(), 4) self.ftk.execute("%g.center = ~2.3") self.assertEqual(self.ftk.get_parameter_count(), 4) self.ftk.execute("F = %f + %g") self.ftk.execute("@+ = 0") self.ftk.execute("@1.F = copy(@0.F)") self.assertEqual(self.ftk.get_parameter_count(), 8) self.ftk.execute("@+ = 0") self.ftk.execute("@2.F = @0.F") self.assertEqual(self.ftk.get_parameter_count(), 8) self.ftk.execute("%g.center = ~2.4") d0_funcs = self.ftk.get_components(0) d1_funcs = self.ftk.get_components(1) d2_funcs = self.ftk.get_components(2) self.assertEqual(d0_funcs[0].get_param_value('center'), 0) self.assertEqual(d0_funcs[1].get_param_value('center'), 2.4) self.assertEqual(d1_funcs[0].get_param_value('center'), 0) self.assertEqual(d1_funcs[1].get_param_value('center'), 2.3) self.assertEqual(d2_funcs[0].get_param_value('center'), 0) self.assertEqual(d2_funcs[1].get_param_value('center'), 2.4) def test_copy_var(self): self.ftk.execute("%f = Gaussian(~10, ~0, 0.5)") self.ftk.execute("$v = copy(%f.height)") v = self.ftk.get_variable("v") self.assertEqual(v.value(), 10) class TestBounds(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) self.ftk.execute("$a = ~3.14 [-1:4.5]") def test_basic(self): a = self.ftk.get_variable("a") self.assertEqual(a.value(), 3.14) self.assertEqual(a.domain.lo, -1) self.assertEqual(a.domain.hi, 4.5) self.assertFalse(a.domain.lo_inf()) self.assertFalse(a.domain.hi_inf()) def test_change_value(self): a = self.ftk.get_variable("a") self.assertRaises(fityk.SyntaxError, self.ftk.execute, "$a = ~") self.assertRaises(fityk.SyntaxError, self.ftk.execute, "$a = ~~9") self.assertRaises(fityk.SyntaxError, self.ftk.execute, "$a = ~-sin(2)") self.ftk.execute("$a = ~{-sin(2)}") self.ftk.execute("$a = ~-0.15") self.assertEqual(a.domain.lo, -1) self.assertEqual(a.domain.hi, 4.5) self.ftk.execute("$a = ~3.15 [:77]") self.assertTrue(a.domain.lo_inf()) self.assertEqual(a.domain.hi, 77) self.ftk.execute("$a = ~3.15 [:]") self.assertTrue(a.domain.lo_inf()) self.assertTrue(a.domain.hi_inf()) def test_assign_var(self): self.ftk.execute("$b = $a") # b is compound variable b = self.ftk.get_variable("b") self.assertEqual(b.value(), 3.14) self.assertTrue(b.domain.lo_inf()) self.assertTrue(b.domain.hi_inf()) self.ftk.execute("$c = ~0.1 [0.0:0.2]") self.ftk.execute("$c = $a") c = self.ftk.get_variable("c") self.assertEqual(c.value(), 3.14) self.assertEqual(c.domain.lo, 0.0) self.assertEqual(c.domain.hi, 0.2) def test_assign_value(self): self.ftk.execute("$b = ~{$a}") b = self.ftk.get_variable("b") self.assertEqual(b.value(), 3.14) self.assertTrue(b.domain.lo_inf()) self.assertTrue(b.domain.hi_inf()) def test_copy_var(self): self.ftk.execute("$b = copy($a)") b = self.ftk.get_variable("b") self.assertEqual(b.value(), 3.14) self.assertEqual(b.domain.lo, -1) self.assertEqual(b.domain.hi, 4.5) class TestDefaultValues(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) def test_pseudovoigt_shape_domain(self): self.ftk.execute("%f = PseudoVoigt(height=~11, center=~12, hwhm=~13)") f = self.ftk.get_function('f') shape = self.ftk.get_variable(f.var_name('shape')) self.assertEqual(shape.value(), 0.5) self.assertEqual(shape.domain.lo, 0) self.assertEqual(shape.domain.hi, 1) def test_defval_bounds(self): self.ftk.execute("define My(a=3, b=0.1[-1:1]) = a*exp(b*x)") self.ftk.execute("%f=My(a=3)") self.assertEqual(self.ftk.get_variable("%f.b").name, "_2") a = self.ftk.get_variable("_2") self.assertEqual(a.value(), 0.1) self.assertEqual(a.domain.lo, -1) self.assertEqual(a.domain.hi, 1) class TestBoxConstraints(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) xx = [(n-5)/2. for n in range(25)] yy = [-7+3*x for x in xx] self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) self.ftk.load_data(0, xx, yy, [1]*len(xx), "line") self.ftk.execute("F = Linear(~0, ~0[:2.5])") self.methods = ["mpfit"] if self.ftk.get_info("compiler"): self.methods += ["nlopt_lbfgs", "nlopt_nm", "nlopt_bobyqa", "nlopt_sbplx"] def fit(self, fitting_method): self.ftk.set_option_as_string("fitting_method", fitting_method) self.ftk.execute("fit") return self.ftk.calculate_expr("F[0].a1") def test_box(self): for m in self.methods: self.assertAlmostEqual(self.fit(m), 2.5) def test_no_box(self): self.ftk.set_option_as_number("box_constraints", 0) for m in self.methods: self.assertAlmostEqual(self.fit(m), 3.0) if __name__ == '__main__': unittest.main() fityk-1.3.1/tests/test_nist.py000077500000000000000000000237171302634723100164100ustar00rootroot00000000000000#!/usr/bin/env python # run tests with: python -m unittest discover import os import sys import re import urllib2 import unittest import fityk DATA_URL_BASE = "http://www.itl.nist.gov/div898/strd/nls/data/LINKS/DATA/" CACHE_DIR = os.path.join(os.path.dirname(__file__), "strd_data") VERBOSE = 1 # 0, 1, 2 or 3 class NistParameter: def __init__(self, name, start1, start2, param_str, stddev_str): self.name = name self.start1 = float(start1) self.start2 = float(start2) self.value_str = param_str self.value = float(param_str) self.stddev_str = stddev_str self.stddev = float(stddev_str) class NistReferenceData: def __init__(self, name): self.name = name self.data = [] self.model = None self.parameters = [] self.dof = None self.ssr = None def __str__(self): return "" % ( len(self.data), len(self.parameters)) def open_nist_data(name): name_ext = name + ".dat" local_file = os.path.join(CACHE_DIR, name_ext) if os.path.exists(local_file): text = open(local_file).read() else: sys.stderr.write("Local data copy not found. Trying itl.nist.gov...\n") text = urllib2.urlopen(DATA_URL_BASE + name_ext).read() if not os.path.isdir(CACHE_DIR): os.mkdir(CACHE_DIR) open(local_file, "wb").write(text) return text def read_reference_data(name): refdat = NistReferenceData(name) text = open_nist_data(name) n_data = int(re.search("\nNumber of Observations: +(\d+)", text).group(1)) refdat.dof = int(re.search("\nDegrees of Freedom: +(\d+)", text).group(1)) # correct wrong number in one of the files: if name == "Rat43": refdat.dof = 11 refdat.ssr = float(re.search("\nResidual Sum of Squares:(.+)\n", text) .group(1)) data_start = re.search("Data: +y +x\s+", text).end() for line in text[data_start:].splitlines(): x, y = line.split() refdat.data.append((float(x), float(y))) param_block = re.search( #"Start 1 +Start 2 +Parameter +Standard Deviation\s+(.+?\n)\r?\n", "Start 1 +Start 2 +Parameter +Standard Deviation\s+((.+?=.+\n)+)", text).group(1) for line in param_block.splitlines(): tokens = line.split() tokens.remove('=') refdat.parameters.append(NistParameter(*tokens)) assert len(refdat.data) == n_data assert n_data - len(refdat.parameters) == refdat.dof, \ "%d - %d != %d" % (n_data, len(refdat.parameters), refdat.dof) model = re.search("\n *y += *(.*?) +\+ +e", text, flags=re.DOTALL).group(1) repl = { "[": "(", "]": ")", "**": "^", "arctan": "atan" } for key in repl: model = model.replace(key, repl[key]) refdat.model = re.sub("\s{2,}", " ", model) return refdat def has_nlopt(): ftk = fityk.Fityk() return "NLopt" in ftk.get_info("compiler") def run(data_name, fit_method, easy=True): uses_gradient = (fit_method in ("mpfit", "levenberg_marquardt")) if uses_gradient: tolerance = { "wssr": 1e-10, "param": 4e-7, "err": 5e-3 } else: tolerance = { "wssr": 1e-7, "param": 1e-4 } if fit_method == "nelder_mead_simplex": tolerance["err"] = 5e-5 #if fit_method in ("mpfit", "levenberg_marquardt"): if VERBOSE > 0: print "Testing %s (start%s) on %-10s" % (fit_method, easy+1, data_name), if VERBOSE > 1: print ref = read_reference_data(data_name) if VERBOSE > 2: print ref.model ftk = fityk.Fityk() if VERBOSE < 3: ftk.execute("set verbosity=-1") y, x = zip(*ref.data) ftk.load_data(0, x, y, [1]*len(x), data_name) par_names = [p.name for p in ref.parameters] par_inits = ["~%g" % (p.start2 if easy else p.start1) for p in ref.parameters] ftk.execute("define OurFunc(%s) = %s" % (", ".join(par_names), ref.model)) ftk.execute("F = OurFunc(%s)" % ", ".join(par_inits)) ftk.execute("set fitting_method=" + fit_method) ftk.execute("set pseudo_random_seed=1234567") #ftk.execute("set numeric_format='%.10E'") ftk.execute("set lm_stop_rel_change=1e-16") #ftk.execute("set lm_max_lambda=1e+50") ftk.execute("set nm_convergence=1e-10") if fit_method == "mpfit": ftk.execute("set ftol_rel=1e-18") ftk.execute("set xtol_rel=1e-18") if fit_method == "genetic_algorithms": ftk.execute("set max_wssr_evaluations=5e5") elif not uses_gradient: ftk.execute("set max_wssr_evaluations=2e4") try: ftk.execute("fit") #ftk.execute("set fitting_method=levenberg_marquardt") #ftk.execute("fit") except fityk.ExecuteError as e: print "fityk.ExecuteError: %s" % e return False ssr = ftk.get_ssr() ssr_diff = (ssr - ref.ssr) / ref.ssr # Lanczos1 and Lanczos2 have near-zero SSR, we need to be more tolerant if ssr < 1e-20: tolerance["wssr"] *= 1e8 elif ssr < 1e-10: tolerance["wssr"] *= 1e2 ok = (abs(ssr_diff) < tolerance["wssr"]) if ref.ssr > 1e-10 and ssr_diff < -1e-10: print "Eureka! %.10E < %.10E" % (ssr, ref.ssr) fmt = " %8s %13E %13E %+.1E" if VERBOSE > 2 or (VERBOSE == 2 and not ok): print fmt % ("SSR", ssr, ref.ssr, ssr_diff) our_func = ftk.all_functions()[0] for par in ref.parameters: calc_value = our_func.get_param_value(par.name) val_diff = (calc_value - par.value) / par.value param_ok = (abs(val_diff) < tolerance["param"]) err_ok = True if "err" in tolerance: vname = our_func.var_name(par.name) calc_err = ftk.calculate_expr("$%s.error" % vname) err_diff = (calc_err - par.stddev) / par.stddev err_ok = (abs(err_diff) < tolerance["err"]) if VERBOSE > 2 or (VERBOSE == 2 and (not param_ok or not err_ok)): print fmt % (par.name, calc_value, par.value, val_diff) if "err" in tolerance: print fmt % ("+/-", calc_err, par.stddev, err_diff) ok = (ok and param_ok and err_ok) if VERBOSE == 1: print("OK" if ok else "FAILED") return ok datasets = [ # lower difficulty "Misra1a", "Chwirut2", "Chwirut1", "Lanczos3", "Gauss1", "Gauss2", "DanWood", "Misra1b", # average difficulty (skipping Nelson which is y(x1,x2)) "Kirby2", "Hahn1", "MGH17", "Lanczos1", "Lanczos2", "Gauss3", "Misra1c", "Misra1d", "Roszman1", "ENSO", # higher difficulty "MGH09", "Thurber", "BoxBOD", "Rat42", "MGH10", "Eckerle4", "Rat43", "Bennett5" ] # L-M finds local minimum when starting from start1 for: lm_fails = ["MGH17", "BoxBOD", "MGH10", "Eckerle4"] mpfit_fails = ["MGH17", "BoxBOD", "MGH10", "MGH09", "Bennett5"] #, "ENSO" nm_fails = ["MGH17", "BoxBOD", "ENSO", "Eckerle4", "MGH09", "Bennett5"] nl_nm_fails = ["MGH17", "BoxBOD", "MGH10", "ENSO"] class TestSequenceFunctions(unittest.TestCase): def setUp(self): global VERBOSE VERBOSE = 0 def test_levmar(self): for data_name in datasets: self.assertTrue(run(data_name, "mpfit", easy=True)) self.assertTrue(run(data_name, "levenberg_marquardt", True)) self.assertIs(run(data_name, "mpfit", easy=False), data_name not in mpfit_fails) self.assertIs(run(data_name, "levenberg_marquardt", False), data_name not in lm_fails) def test_nelder_mead(self): for data_name in datasets: ## Lanczos* converge slowly with gradient-less methods, avoid if "Lanczos" in data_name: continue self.assertTrue(run(data_name, "nelder_mead_simplex", easy=True)) self.assertTrue(run(data_name, "nlopt_nm", easy=True)) self.assertIs(run(data_name, "nelder_mead_simplex", easy=False), data_name not in nm_fails) self.assertIs(run(data_name, "nlopt_nm", easy=False), data_name not in nl_nm_fails) def test_ga(self): # Since in these problems parameter domains are not defined, # we only have starting point, methods that have random-search element # don't work well. # Like Genetic Algorithms. Additionally, GA are not very practical for # most of tasks -- slow and require adjusting plenty of parameters. # But still it may solve some cases where other methods fail: self.assertTrue(run("BoxBOD", "genetic_algorithms", easy=False)) @unittest.skipIf(not has_nlopt(), "Fityk compiled w/o NLopt support.") def test_nlopt(self): # Selected methods from NLopt library. # For this test suite (which may not be representative for real # problems) the best NLopt method is Nelder-Mead (tested above). # The methods below can be useful as well. # (I haven't tried all algorithms, but almost all). self.assertTrue(run("MGH17", "nlopt_lbfgs", easy=False)) for data_name in ["BoxBOD", "Eckerle4", "ENSO"]: self.assertTrue(run(data_name, "nlopt_var2", easy=False)) for data_name in ["BoxBOD", "Eckerle4", "ENSO"]: self.assertTrue(run(data_name, "nlopt_praxis", easy=False)) for data_name in ["Thurber", "BoxBOD", "Rat43"]: self.assertTrue(run(data_name, "nlopt_bobyqa", easy=False)) for data_name in ["Rat42", "Eckerle4"]: self.assertTrue(run(data_name, "nlopt_sbplx", easy=False)) def try_method(method): all_count = 0 ok_count = 0 for data_name in datasets: for is_easy in (True, False): ok = run(data_name, method, is_easy) all_count += 1 if ok: ok_count += 1 sys.stdout.flush() print "OK: %2d / %2d" % (ok_count, all_count) if __name__ == '__main__': if len(sys.argv) > 2 and sys.argv[1] == 'method': # syntax: ./test_nist.py method nlopt_bobyqa try_method(sys.argv[2]) else: unittest.main() fityk-1.3.1/tests/test_syntax.fit000066400000000000000000000161041302634723100171000ustar00rootroot00000000000000# Fityk 1.2.1 ### syntax testing ### this script doesn't assume location of any other files (ie. no data files ### are read, and produces only file in current directory, which start with ### `tmp_' prefix, eg. tmp_foo.xy # first set some options useful for testing set on_error = exit set autoplot = 0 set pseudo_random_seed = 174924 set verbosity = 1 # ... and then issue as many commands as possible, checking for sytax errors # predefined data transformations M=500 x=n/100 M=500; x=n/100; y=sin(x); s=1 Y = Y[n-1] + y[n];S = sqrt(max2(1,y)) Y = (y[n+1]-y[n])/(x[n+1]-x[n]);X = (x[n+1]+x[n])/2 M=M-1;S = sqrt(max2(1,y)) S = s / sum(n > 0 ? (x[n] - x[n-1]) * (y[n-1] + y[n])/2 : 0); Y = y / sum(n > 0 ? (x[n] - x[n-1]) * (y[n-1] + y[n])/2 : 0) X = n avg(y)) p darea(y-@0.F(x) if 15tmp_foo.fit info history[:0] >>tmp_foo.fit set logfile='tmp_log.fit' set log_full=1, logfile='tmp_log.fit' set logfile='' exec 'tmp_log.fit' # it's an empty file (with some comments) @0: print all: x, y @*: print all: x, y, s > 'tmp_foo2.xy' @0: print all: x, y, a > 'tmp_foo3.xy' @0: print all: x, y, s, @0.F(x), (y-@0.F(x))/s, a > 'tmp_foo4.xy' @0: print all: x, y, s, F(x), (y-F(x))/s, a >> tmp_foo4.xy @0: info peaks > tmp_foo5.xy @0: info peaks_err > tmp_foo6.xy @0: info formula > tmp_foo7.xy @0: info simplified_gnuplot_formula > tmp_foo8.xy @*: info peaks > tmp_foo9.xy i history >> tmp_foo9.xy i models >> tmp_foo9.xy info state > tmp_dump.fit delete file 'tmp_foo.fit', file 'tmp_foo2.xy', file 'tmp_foo3.xy' delete file 'tmp_foo4.xy', file 'tmp_foo5.xy', file 'tmp_foo6.xy' delete file 'tmp_foo7.xy', file 'tmp_foo8.xy', file 'tmp_foo9.xy' delete file tmp_dump.fit delete file tmp_log.fit lua print("current date and time:\t\t" .. os.date()) = "again: \t" .. os.date() = "again:", os.date() exec= "info version" = F:get_info('version'):lower(), _VERSION lua F:out((F:get_info("F[0]"))) # settings set function_cutoff = 0 set fitting_method = levenberg_marquardt set height_correction = 1 set lm_lambda_down_factor = 10 set lm_lambda_start = 0.001 set lm_lambda_up_factor = 10 set lm_max_lambda = 1e+15 set lm_stop_rel_change = 0.0001 set max_wssr_evaluations = 1000 set nm_convergence = 0.0001 set nm_distribution = bound set nm_move_all = 0 set nm_move_factor = 1 set domain_percent = 30 set width_correction = 1 set epsilon = 1e-12 set default_sigma=one set default_sigma=sqrt set verbosity = 1 set numeric_format = '%.2f' set on_error = nothing set cwd = '/tmp' # it can cause error, paths are not cross-platform set cwd = 'C:\' # it can cause error, paths are not cross-platform info set cwd set on_error = stop reset #quit fityk-1.3.1/tests/test_tranform.py000077500000000000000000000113251302634723100172530ustar00rootroot00000000000000#!/usr/bin/env python # run tests with: python -m unittest test_tranform # python -m unittest discover import os import sys import unittest import fityk try: import numpy except ImportError: numpy = None def get_data_as_lists(ftk): data = ftk.get_data() return [p.x for p in data], [p.y for p in data], [p.sigma for p in data] class TestTransform(unittest.TestCase): def setUp(self): self.x = [(n-5)/2. for n in range(20)] self.y = [x*(x-3.1) for x in self.x] self.sigma = [1 for n in self.y] self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) self.ftk.load_data(0, self.x, self.y, self.sigma, "test-data") def test_load(self): xx, yy, ss = get_data_as_lists(self.ftk) self.assertEqual(xx, self.x) self.assertEqual(yy, self.y) self.assertEqual(ss, self.sigma) #print self.x #print self.y def assert_expr(self, expr, val, places=None): expr_val = self.ftk.calculate_expr(expr) if places is None: self.assertEqual(expr_val, val) else: self.assertAlmostEqual(expr_val, val, places=places) def test_expr(self): xx, yy, ss = get_data_as_lists(self.ftk) M = len(yy) self.assert_expr("M", M) self.assert_expr("count(y>0)", len([y for y in yy if y > 0])) self.assert_expr("sum(x)", sum(xx)) self.assert_expr("sum(y)", sum(yy)) self.assert_expr("darea(y)", sum(yy[n]*(xx[min(n+1, M-1)]-xx[max(n-1, 0)])/2 for n in range(M))) if not numpy: return self.assert_expr("avg(x)", numpy.mean(xx)) self.assert_expr("min(x)", numpy.min(xx)) self.assert_expr("max(x)", numpy.max(xx)) self.assert_expr("stddev(x)", numpy.std(xx, ddof=1)) self.assert_expr("avg(y)", numpy.mean(yy), places=12) self.assert_expr("min(y)", numpy.min(yy)) self.assert_expr("max(y)", numpy.max(yy)) self.assert_expr("stddev(y)", numpy.std(yy, ddof=1), places=12) self.assert_expr("argmin(y)", xx[numpy.argmin(yy)]) self.assert_expr("argmax(y)", xx[numpy.argmax(yy)]) def test_delete(self): self.ftk.execute("delete(x < 0)") xx, yy, ss = get_data_as_lists(self.ftk) self.assertEqual(xx, [x for x in self.x if x >= 0]) def test_delete2(self): self.ftk.execute("A = x >= 0; delete(not a)") xx, yy, ss = get_data_as_lists(self.ftk) self.assertEqual(xx, [x for x in self.x if x >= 0]) def test_normalize(self): self.ftk.execute("Y = y / darea(y)") self.assertEqual(self.ftk.calculate_expr("darea(y)"), 1) def test_set_y(self): self.ftk.execute("Y[3] = 1.2; Y[-2] = 12.34") xx, yy, ss = get_data_as_lists(self.ftk) self.assertEqual(yy[3], 1.2) self.assertEqual(yy[-2], 12.34) def test_xy_swap(self): self.ftk.execute("X=y, Y=x") # swap & sort! xx, yy, ss = get_data_as_lists(self.ftk) self.assertEqual(xx, sorted(self.y)) xymap = { x: y for x, y in zip(self.y, self.x) } self.assertEqual(yy, [xymap[x] for x in xx]) self.assertEqual(ss, self.sigma) class TestFuncProperties(unittest.TestCase): def setUp(self): self.ftk = fityk.Fityk() self.ftk.set_option_as_number("verbosity", -1) self.ftk.execute("%f = Quadratic(~1, 2, ~3)") self.ftk.execute("%g = Constant(7.5)") self.ftk.execute("F = %f + %g") def _check(self, expr, val, places=12): expr_val = self.ftk.calculate_expr(expr) self.assertAlmostEqual(expr_val, val, places=places) def test_numarea(self): # Integral of 1+2*x+3*x^2 = x+x^2+x^3| from 2 to 4 = 84-14 = 70 self._check("%f.numarea(2, 4, 1000)", 70, places=5) self._check("%g.numarea(2, 4, 3)", 2*7.5) self._check("F.numarea(2, 4, 300)", 70 + 2*7.5, places=4) def test_findx(self): self._check("%f.findx(0, 5, 6)", 1.0, places=12) self._check("%f.findx(-1.5, 1.2, 6)", 1.0, places=12) self.ftk.calculate_expr("%g.findx(-10, 10, 7.5)") # anything self._check("F.findx(-1.5, 1.2, 13.5)", 1.0, places=12) self.ftk.execute("Z = Constant(0.2)") self._check("F.findx(-1.5, 1.2, 13.5)", 1.0-0.2, places=12) def test_extremum(self): self._check("%f.extremum(-10, 10)", -1.0/3, places=13) self.ftk.calculate_expr("%g.extremum(-10, 10)") # anything self._check("F.extremum(-10, 10)", -1.0/3, places=13) self.ftk.execute("Z = Constant(0.2)") self._check("F.extremum(-10, 10)", -1.0/3-0.2, places=12) if __name__ == '__main__': unittest.main() fityk-1.3.1/wxgui/000077500000000000000000000000001302634723100140065ustar00rootroot00000000000000fityk-1.3.1/wxgui/Makefile.am000066400000000000000000000072141302634723100160460ustar00rootroot00000000000000 bin_PROGRAMS = fityk # tested only on MinGW if OS_WIN32 AM_LDFLAGS = -mwindows RC_FLAGS_ALL=$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) $(WX_CPPFLAGS) RC_FLAGS=`echo $(RC_FLAGS_ALL) | sed -e 's/-mthreads//g' ` fityk_res = winres.o $(fityk_res): winres.rc img/fityk.ico $(RC) -o $@ $(RC_FLAGS) $< powdifpat_res = powdifpatres.o $(powdifpat_res): powdifpat.rc img/powdifpat.ico $(RC) -o $@ $(RC_FLAGS) $< else HELP_DEF= -DHELP_DIR=\"$(pkgdatadir)\" endif #OS_WIN32 noinst_LIBRARIES = libceria.a libceria_a_SOURCES = ceria.cpp ceria.h atomtables.c atomtables.h \ sgtables.c sgtables.h fityk_SOURCES = cmn.cpp cmn.h gradient.cpp gradient.h parpan.cpp parpan.h \ drag.cpp drag.h recent.cpp recent.h \ inputline.cpp inputline.h listptxt.cpp listptxt.h \ dload.cpp dload.h xybrowser.cpp xybrowser.h \ plotpane.cpp plotpane.h textpane.cpp textpane.h \ statbar.cpp statbar.h sidebar.cpp sidebar.h \ history.cpp history.h datatable.cpp datatable.h \ dataedit.cpp dataedit.h defmgr.cpp defmgr.h \ setdlg.cpp setdlg.h print.cpp print.h editor.cpp editor.h \ plot.cpp plot.h aplot.cpp aplot.h mplot.cpp mplot.h \ uplot.cpp uplot.h about.cpp about.h fitinfo.cpp fitinfo.h \ fitrun.cpp fitrun.h modelinfo.cpp modelinfo.h \ merge.cpp merge.h exportd.cpp exportd.h bgm.cpp bgm.h \ frame.cpp frame.h app.cpp app.h \ powdifpat.cpp powdifpat.h sgchooser.cpp sgchooser.h fityk_CPPFLAGS = -I$(top_srcdir) $(WX_CPPFLAGS) $(HELP_DEF) fityk_CXXFLAGS = $(WX_CXXFLAGS_ONLY) fityk_LDADD = ../fityk/libfityk.la libceria.a -lxy $(WX_LIBS) $(fityk_res) inputline: sample_inputline.cpp inputline.cpp inputline.h `wx-config --cxx` `wx-config --cxxflags` -g -Wall -W -O0 -o $@ \ $< $(srcdir)/inputline.cpp `wx-config --libs` if POWDIFPAT bin_PROGRAMS += powdifpat powdifpat_SOURCES = powdifpat.cpp powdifpat.h sgchooser.cpp sgchooser.h \ uplot.cpp uplot.h cmn.cpp cmn.h parpan.cpp parpan.h powdifpat_CPPFLAGS = $(WX_CPPFLAGS) -DSTANDALONE_POWDIFPAT powdifpat_LDADD = libceria.a $(WX_LIBS) -lxy $(powdifpat_res) endif ## to find icons not listed here use (in bash): ## for i in img/*.xpm img/*.h; do [ `grep -c $i Makefile.am` -eq 0 ] && ls $i; done EXTRA_DIST = \ winres.rc powdifpat.rc \ \ img/active_mode.xpm \ img/addpeak_mode.xpm \ img/add_peak.xpm \ img/add.xpm \ img/bg_mode.xpm \ img/close.xpm \ img/colorsel.xpm \ img/color.xpm \ img/cont_fit.xpm \ img/convert.xpm \ img/copyfunc.xpm \ img/edit_data.xpm \ img/editf.xpm \ img/exec_down.xpm \ img/exec_selected.xpm \ img/filter.xpm \ img/fityk.xpm \ img/goto.xpm \ img/lock.xpm \ img/lock_open.xpm \ img/manual.xpm \ img/open_data_custom.xpm \ img/open_data.xpm \ img/rename.xpm \ img/right_pane.xpm \ img/run_fit.xpm \ img/run_script.xpm \ img/save.xpm \ img/save_as.xpm \ img/save_data.xpm \ img/save_script.xpm \ img/shiftup.xpm \ img/dpsize.xpm \ img/strip_bg.xpm \ img/sum.xpm \ img/undo_fit.xpm \ img/unused.xpm \ img/zoom_all.xpm \ img/zoom_left.xpm \ img/zoom_mode.xpm \ img/zoom_prev.xpm \ img/zoom_right.xpm \ img/zoom_up.xpm \ img/zoom_vert.xpm \ img/zshift.xpm \ \ img/eq_fwhm.h \ img/eq_shape.h \ \ img/book16.h \ img/editor16.h \ img/export16.h \ img/fileopen16.h \ img/filereload16.h \ img/filesaveas16.h \ img/function16.h \ img/image16.h \ img/info16.h \ img/preferences16.h \ img/recordmacro16.h \ img/redo16.h \ img/reload16.h \ img/revert16.h \ img/run16.h \ img/runmacro16.h \ img/stopmacro16.h \ img/undo16.h \ img/web16.h \ img/zoom-fit16.h \ \ img/mouse16.h \ img/sbprefs.h \ img/ok24.h \ \ img/correction.h \ img/info32.h \ img/peak32.h \ img/radiation32.h \ img/rubik32.h \ img/run32.h \ img/sizes32.h \ \ img/fityk96.h \ \ img/fityk.ico \ \ img/powdifpat16.xpm \ img/powdifpat48.xpm \ img/powdifpat.ico fityk-1.3.1/wxgui/about.cpp000066400000000000000000000071311302634723100156260ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include "about.h" #include // BOOST_VERSION #include // get_version() #include #include "cmn.h" // pchar2wx, s2wx, GET_BMP #include "fityk/common.h" // VERSION #include "fityk/info.h" // embedded_lua_version() #include "img/fityk96.h" AboutDlg::AboutDlg(wxWindow* parent) : wxDialog(parent, -1, wxT("About Fityk"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->Add(new wxStaticBitmap(this, -1, GET_BMP(fityk96)), wxSizerFlags().Centre().Border()); wxBoxSizer *name_sizer = new wxBoxSizer(wxVERTICAL); wxStaticText *name = new wxStaticText(this, -1, wxT("fityk ") + pchar2wx(VERSION)); name->SetFont(wxFont(24, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD)); name_sizer->Add(name, wxSizerFlags().Centre().Border()); wxStaticText *desc = new wxStaticText(this, -1, wxT("A curve fitting and data analysis program")); name_sizer->Add(desc, wxSizerFlags().Centre().Border(wxLEFT|wxRIGHT)); wxString link = wxT("http://fityk.nieto.pl"); wxHyperlinkCtrl *link_ctrl = new wxHyperlinkCtrl(this, -1, link, link); name_sizer->Add(link_ctrl, wxSizerFlags().Centre().Border()); hsizer->Add(name_sizer, wxSizerFlags(1).Expand()); sizer->Add(hsizer, wxSizerFlags()); wxTextCtrl *txt = new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition, #ifdef __WXMSW__ wxSize(-1,120), #else wxSize(-1,160), #endif wxTE_MULTILINE|wxTE_RICH|wxNO_BORDER |wxTE_READONLY); #ifdef __WXGTK__ //wxColour bg_col = wxStaticText::GetClassDefaultAttributes().colBg; wxColour bg_col = name->GetDefaultAttributes().colBg; #else wxColour bg_col = GetBackgroundColour(); #endif txt->SetBackgroundColour(bg_col); txt->SetDefaultStyle(wxTextAttr(wxNullColour, bg_col, *wxITALIC_FONT)); txt->AppendText(wxT("powered by: ") wxVERSION_STRING); txt->AppendText(wxString::Format(wxT(", Boost %d.%d.%d"), BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100)); txt->AppendText(wxString(", ") + fityk::embedded_lua_version()); txt->AppendText(wxT(" and xylib ") + pchar2wx(xylib_get_version()) + wxT("\n")); txt->SetDefaultStyle(wxTextAttr(wxNullColour, bg_col, *wxNORMAL_FONT)); txt->AppendText(wxT("\nCopyright 2001 - 2016 Marcin Wojdyr\n\n")); txt->SetDefaultStyle(wxTextAttr(wxNullColour, bg_col, *wxSMALL_FONT)); txt->AppendText( wxT("This program is free software; you can redistribute it and/or modify ") wxT("it under the terms of the GNU General Public License as published by ") wxT("the Free Software Foundation; either version 2 of the License, or ") wxT("(at your option) any later version.") ); txt->ShowPosition(0); sizer->Add(txt, 1, wxLEFT|wxRIGHT|wxTOP|wxEXPAND|wxFIXED_MINSIZE, 10); //sizer->Add (new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 10); wxButton *button = new wxButton (this, wxID_CLOSE); SetEscapeId(wxID_CLOSE); //button->SetDefault(); sizer->Add(button, wxSizerFlags().Right().Border()); SetSizerAndFit(sizer); } fityk-1.3.1/wxgui/about.h000066400000000000000000000005101302634723100152650ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // AboutDlg: "about..." dialog #ifndef FITYK_WX_ABOUT_H_ #define FITYK_WX_ABOUT_H_ #include class AboutDlg : public wxDialog { public: AboutDlg(wxWindow* parent); }; #endif // FITYK_WX_ABOUT_H_ fityk-1.3.1/wxgui/aplot.cpp000066400000000000000000000561021302634723100156350ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// In this file: /// Auxiliary Plot, for displaying residuals, peak positions, etc. (AuxPlot) #include #include #include #include "aplot.h" #include "frame.h" #include "plotpane.h" #include "fityk/model.h" #include "fityk/func.h" #include "fityk/data.h" #include "fityk/logic.h" using namespace std; using fityk::Data; using fityk::Model; enum { ID_aux_prefs = 25310, ID_aux_plot0 = 25311, ID_aux_mark_pos = 25340, ID_aux_yz_fit , ID_aux_yz_auto }; class AuxPlotConfDlg : public wxDialog { public: AuxPlotConfDlg(AuxPlot* ap); private: AuxPlot *ap_; wxCheckBox* rev_cb_; wxSpinCtrl* zoom_sc_; wxColourPickerCtrl *bg_cp_, *active_cp_, *inactive_cp_, *axis_cp_; wxFontPickerCtrl *tics_fp_; void OnPlotKind(wxCommandEvent& event); void OnReversedDiff(wxCommandEvent& event); void OnMarkPeakPositions(wxCommandEvent& e) {ap_->OnMarkPeakPositions(e);} void OnAutoZoom(wxCommandEvent& event); void OnZoomSpin(wxSpinEvent& event); void OnColor(wxColourPickerEvent& event); void OnTicsFont(wxFontPickerEvent& event); }; //=============================================================== // AuxPlot (auxiliary plot) //=============================================================== BEGIN_EVENT_TABLE (AuxPlot, FPlot) EVT_PAINT ( AuxPlot::OnPaint) EVT_MOTION ( AuxPlot::OnMouseMove) EVT_LEAVE_WINDOW ( AuxPlot::OnLeaveWindow) EVT_LEFT_DOWN ( AuxPlot::OnLeftDown) EVT_LEFT_UP ( AuxPlot::OnLeftUp) EVT_RIGHT_DOWN ( AuxPlot::OnRightDown) EVT_MIDDLE_DOWN ( AuxPlot::OnMiddleDown) EVT_MENU (ID_aux_prefs, AuxPlot::OnPrefs) EVT_MENU_RANGE (ID_aux_plot0, ID_aux_plot0+10, AuxPlot::OnPopupPlot) EVT_MENU (ID_aux_mark_pos, AuxPlot::OnMarkPeakPositions) EVT_MENU (ID_aux_yz_fit, AuxPlot::OnPopupYZoomFit) EVT_MENU (ID_aux_yz_auto, AuxPlot::OnAutoZoom) END_EVENT_TABLE() AuxPlot::AuxPlot(wxWindow *parent, FPlot *master, wxString const& name) : FPlot(parent), master_(master), name_(name), y_zoom_(1.), y_zoom_base_(1.), fit_y_once_(false) { overlay.switch_mode(Overlay::kVLine); } void AuxPlot::OnPaint(wxPaintEvent&) { update_buffer_and_blit(); } namespace { inline double model_value(vector::const_iterator pt, Model const* model) { return model->value(pt->x); } double diff_of_data_for_draw_data (vector::const_iterator i, Model const* model) { return i->y - model_value(i, model); } double rdiff_of_data_for_draw_data (vector::const_iterator i, Model const* model) { return model_value(i, model) - i->y; } double diff_stddev_of_data_for_draw_data (vector::const_iterator i, Model const* model) { return (i->y - model_value(i, model)) / i->sigma; } double rdiff_stddev_of_data_for_draw_data (vector::const_iterator i, Model const* model) { return (model_value(i, model) - i->y) / i->sigma; } double diff_chi2_of_data_for_draw_data (vector::const_iterator i, Model const* model) { double t = (i->y - model_value(i, model)) / i->sigma; return t*t; } double diff_y_perc_of_data_for_draw_data (vector::const_iterator i, Model const* model) { return i->y ? (i->y - model_value(i, model)) / i->y * 100 : 0; } double rdiff_y_perc_of_data_for_draw_data (vector::const_iterator i, Model const* model) { return i->y ? (model_value(i, model) - i->y) / i->y * 100 : 0; } } // anonymous namespace void AuxPlot::draw(wxDC &dc, bool monochrome) { //printf("AuxPlot::draw()\n"); int pos = frame->get_focused_data_index(); const Data* data = ftk->dk.data(pos); const Model* model = data->model(); if (auto_zoom_y_ || fit_y_once_) { fit_y_zoom(data, model); fit_y_once_ = false; } const int pixel_width = get_pixel_width(dc); const int pixel_height = get_pixel_height(dc); set_scale(pixel_width, pixel_height); if (monochrome) { dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxBLACK_BRUSH); } else dc.SetPen(wxPen(xAxisCol, pen_width)); if (mark_peak_pos_) { v_foreach (int, i, model->get_ff().idx) { realt x; if (ftk->mgr.get_function(*i)->get_center(&x)) { int X = xs.px(x - model->zero_shift(x)); dc.DrawLine(X, 0, X, pixel_height); } } } if (kind_ == apk_empty || data->is_empty()) return; if (x_axis_visible) { int Y0 = ys.px(0.); dc.DrawLine (0, Y0, pixel_width, Y0); if (kind_ == apk_diff) draw_zoom_text(dc, !monochrome); } if (y_axis_visible) { int X0 = xs.px(0.); dc.DrawLine (X0, 0, X0, pixel_height); } if (ytics_visible) { fityk::Rect rect(0, 0, ys.val(pixel_height), ys.val(0)); draw_ytics(dc, rect, !monochrome); } double (*f)(vector::const_iterator, Model const*) = NULL; bool cummulative = false; if (kind_ == apk_diff) f = reversed_diff_ ? rdiff_of_data_for_draw_data : diff_of_data_for_draw_data; else if (kind_ == apk_diff_stddev) f = reversed_diff_ ? rdiff_stddev_of_data_for_draw_data : diff_stddev_of_data_for_draw_data; else if (kind_ == apk_diff_y_perc) f = reversed_diff_ ? rdiff_y_perc_of_data_for_draw_data : diff_y_perc_of_data_for_draw_data; else if (kind_ == apk_cum_chi2) { f = diff_chi2_of_data_for_draw_data; cummulative = true; } wxColour col = monochrome ? dc.GetPen().GetColour() : wxNullColour; draw_data (dc, f, data, model, col, col, 0, cummulative); } /// print zoom info - how it compares to zoom of the master plot (e.g. "x3"), /// it makes sense only for apk_diff plot, when master plot is not logarithmic void AuxPlot::draw_zoom_text(wxDC& dc, bool set_pen) { if (master_->get_y_scale().logarithm) return; if (set_pen) dc.SetTextForeground(xAxisCol); set_font(dc, *wxNORMAL_FONT); #ifdef __WXMSW__ // U+00D7 is not rendered correctly on Windows XP string s = "x" + S(y_zoom_); #else string s = "\u00D7" + S(y_zoom_); // U+00D7 == × #endif wxCoord w, h; dc.GetTextExtent (s2wx(s), &w, &h); dc.DrawText (s2wx(s), get_pixel_width(dc) - w - 2, 2); } void AuxPlot::OnMouseMove(wxMouseEvent &event) { int X = event.GetX(); frame->set_status_coords(xs.valr(X), ys.valr(event.GetY()), pte_aux); if (downX == INT_MIN) { if (X < move_plot_margin_width) { SetCursor(wxCURSOR_POINT_LEFT); X = -1; // don't draw lines } else if (X > GetClientSize().GetWidth() - move_plot_margin_width) { SetCursor(wxCURSOR_POINT_RIGHT); X = -1; // don't draw lines } else SetCursor(wxCURSOR_CROSS); } overlay.change_pos(X, 0); frame->plot_pane()->draw_vertical_lines(X, downX, this); } void AuxPlot::OnLeaveWindow (wxMouseEvent&) { frame->clear_status_coords(); overlay.change_pos(-1, -1); frame->plot_pane()->draw_vertical_lines(-1, -1, this); } bool AuxPlot::is_zoomable() { return kind_ == apk_diff || kind_ == apk_diff_stddev || kind_ == apk_diff_y_perc || kind_ == apk_cum_chi2; } void AuxPlot::set_scale(int pixel_width, int pixel_height) { // This functions depends on the x and y scales in MainPlot. // Since the order in which the plots are redrawn is undetermined, // we are updating here the MainPlot scale. // But don't change MainPlot's scale when printing. if (pixel_height == GetClientSize().GetHeight()) // probably not printing master_->set_scale(pixel_width, master_->GetClientSize().GetHeight()); xs = master_->get_x_scale(); if (kind_ == apk_cum_chi2) { ys.scale = -1. * y_zoom_base_ * y_zoom_; ys.origin = - pixel_height / ys.scale; return; } switch (kind_) { case apk_empty: ys.scale = 1.; //y scale doesn't matter break; case apk_diff: if (master_->get_y_scale().logarithm) ys.scale = y_zoom_; else ys.scale = master_->get_y_scale().scale * y_zoom_; break; case apk_diff_stddev: case apk_diff_y_perc: ys.scale = -1. * y_zoom_base_ * y_zoom_; break; case apk_cum_chi2: // FIXME break; } ys.origin = - pixel_height / 2. / ys.scale; } void AuxPlot::read_settings(wxConfigBase *cf) { wxString path = wxT("/AuxPlot_") + name_; cf->SetPath(path); kind_ = static_cast(cf->Read (wxT("kind"), apk_diff)); mark_peak_pos_ = cfg_read_bool (cf, wxT("markCtr"), false); reversed_diff_ = cfg_read_bool (cf, wxT("reversedDiff"), false); auto_zoom_y_ = cfg_read_bool(cf, wxT("autozoom"), false); line_between_points = cfg_read_bool(cf, wxT("line_between_points"), true); point_radius = cf->Read (wxT("point_radius"), 1); y_max_tics = cf->Read(wxT("yMaxTics"), 5); y_tic_size = cf->Read(wxT("yTicSize"), 4); cf->SetPath(wxT("Visible")); // nothing here now cf->SetPath(wxT("../Colors")); set_bg_color(cfg_read_color (cf, wxT("bg"), wxColour(34, 34, 34))); activeDataCol = cfg_read_color (cf, wxT("active_data"), wxColour(wxT("GREEN"))); inactiveDataCol = cfg_read_color(cf,wxT("inactive_data"), wxColour(128, 128, 128)); cf->SetPath(wxT("..")); FPlot::read_settings(cf); refresh(); } void AuxPlot::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("/AuxPlot_") + name_); cf->Write(wxT("kind"), (int) kind_); cf->Write(wxT("markCtr"), mark_peak_pos_); cf->Write(wxT("reversedDiff"), reversed_diff_); cf->Write(wxT("line_between_points"), line_between_points); cf->Write(wxT("autozoom"), auto_zoom_y_); cf->Write(wxT("point_radius"), point_radius); cf->Write(wxT("yMaxTics"), y_max_tics); cf->Write(wxT("yTicSize"), y_tic_size); cf->SetPath(wxT("Visible")); // nothing here now cf->SetPath(wxT("../Colors")); cfg_write_color(cf, wxT("bg"), get_bg_color()); cfg_write_color(cf, wxT("active_data"), activeDataCol); cfg_write_color(cf, wxT("inactive_data"),inactiveDataCol); // We don't call FPlot::save_settings() to not clutter the config, // the only configurable settings from FPlot are xAxisCol and ticsFont. //cf->SetPath(wxT("..")); //FPlot::save_settings(cf); cfg_write_color (cf, wxT("xAxis"), xAxisCol); cf->SetPath(wxT("..")); cfg_write_font (cf, wxT("ticsFont"), ticsFont); } void AuxPlot::OnLeftDown (wxMouseEvent &event) { if (downX != INT_MIN) cancel_mouse_left_press(); if (event.ShiftDown()) { // the same as OnMiddleDown() frame->GViewAll(); return; } int X = event.GetX(); // if mouse pointer is near to left or right border, move view if (X < move_plot_margin_width) frame->scroll_view_horizontally(-0.33); // <-- else if (X > GetClientSize().GetWidth() - move_plot_margin_width) frame->scroll_view_horizontally(+0.33); // --> else { downX = X; overlay.start_mode(Overlay::kVRange, downX, 0); overlay.draw_overlay(); SetCursor(wxCURSOR_SIZEWE); frame->set_status_text("Select x range and release button to zoom..."); CaptureMouse(); connect_esc_to_cancel(true); } } void AuxPlot::cancel_mouse_left_press() { if (downX == INT_MIN) return; if (GetCapture() == this) ReleaseMouse(); connect_esc_to_cancel(false); downX = INT_MIN; SetCursor(wxCURSOR_CROSS); frame->set_status_text(""); overlay.switch_mode(Overlay::kVLine); overlay.draw_overlay(); frame->plot_pane()->draw_vertical_lines(-1, -1, this); } void AuxPlot::OnLeftUp (wxMouseEvent &event) { if (downX == INT_MIN) return; double x1 = xs.val(event.GetX()); double x2 = xs.val(downX); // must be called before cancel_mouse...() if (GetCapture() == this) ReleaseMouse(); connect_esc_to_cancel(false); downX = INT_MIN; SetCursor(wxCURSOR_CROSS); overlay.switch_mode(Overlay::kVLine); if (abs(event.GetX() - downX) >= 5) { RealRange all; frame->change_zoom(RealRange(min(x1,x2), max(x1,x2)), all); } else { frame->set_status_text(""); overlay.draw_overlay(); frame->plot_pane()->draw_vertical_lines(event.GetX(), -1, this); } } //popup-menu void AuxPlot::OnRightDown (wxMouseEvent &event) { if (downX != INT_MIN) { cancel_mouse_left_press(); return; } wxMenu popup_menu; popup_menu.Append(ID_aux_prefs, wxT("&Configure..."), wxT("")); popup_menu.AppendSeparator(); popup_menu.Append (ID_aux_yz_fit, wxT("&Fit to window")); popup_menu.Enable(ID_aux_yz_fit, is_zoomable()); popup_menu.AppendCheckItem (ID_aux_yz_auto, wxT("&Auto-fit")); popup_menu.Check (ID_aux_yz_auto, auto_zoom_y_); popup_menu.Enable(ID_aux_yz_auto, is_zoomable()); popup_menu.AppendSeparator(); popup_menu.AppendRadioItem(ID_aux_plot0+0, wxT("&empty"), wxT("nothing")); popup_menu.AppendRadioItem(ID_aux_plot0+1, wxT("&diff"), wxT("y_d - y_s")); popup_menu.AppendRadioItem(ID_aux_plot0+2, wxT("&weighted diff"), wxT("(y_d - y_s) / sigma")); popup_menu.AppendRadioItem(ID_aux_plot0+3, wxT("&diff/y [%]"), wxT("(y_d - y_s) / y_d [%]")); popup_menu.AppendRadioItem(ID_aux_plot0+4, wxT("c&umulative \u03c7\u00b2"), wxT("cumulative weighted sum of squared residuals")); popup_menu.Check(ID_aux_plot0+kind_, true); popup_menu.AppendSeparator(); popup_menu.AppendCheckItem(ID_aux_mark_pos, wxT("Show &Peak Positions"), wxT("mark centers of peaks")); popup_menu.Check(ID_aux_mark_pos, mark_peak_pos_); PopupMenu (&popup_menu, event.GetX(), event.GetY()); } void AuxPlot::OnMiddleDown (wxMouseEvent&) { if (downX == INT_MIN) frame->GViewAll(); else cancel_mouse_left_press(); } void AuxPlot::show_pref_dialog() { AuxPlotConfDlg dlg(this); dlg.ShowModal(); } void AuxPlot::OnPopupPlot (wxCommandEvent& event) { change_plot_kind(static_cast(event.GetId()-ID_aux_plot0)); Refresh(false); // needed on Windows (i don't know why) } void AuxPlot::change_plot_kind(AuxPlotKind kind) { kind_ = kind; //fit_y_zoom(); fit_y_once_ = true; refresh(); } void AuxPlot::OnMarkPeakPositions(wxCommandEvent& event) { mark_peak_pos_ = event.IsChecked(); refresh(); Refresh(false); // needed on Windows (i don't know why) } void AuxPlot::OnPopupYZoomFit (wxCommandEvent&) { //fit_y_zoom(); fit_y_once_ = true; refresh(); Refresh(false); // needed on Windows (i don't know why) } void AuxPlot::fit_y_zoom(Data const* data, Model const* model) { if (!is_zoomable()) return; double y = 0.; vector::const_iterator first = data->get_point_at(ftk->view.left()), last = data->get_point_at(ftk->view.right()); if (data->is_empty() || last==first) return; int pixel_height = GetClientSize().GetHeight(); switch (kind_) { case apk_diff: { y = get_max_abs_y(diff_of_data_for_draw_data, first, last, model); Scale const& mys = master_->get_y_scale(); y_zoom_ = fabs (pixel_height / (2 * y * (mys.logarithm ? 1 : mys.scale))); double order = pow (10, floor (log10(y_zoom_))); y_zoom_ = floor(y_zoom_ / order) * order; } break; case apk_diff_stddev: y = get_max_abs_y(diff_stddev_of_data_for_draw_data, first, last, model); y_zoom_base_ = pixel_height / (2. * y); y_zoom_ = 0.9; break; case apk_diff_y_perc: y = get_max_abs_y(diff_y_perc_of_data_for_draw_data, first, last, model); y_zoom_base_ = pixel_height / (2. * y); y_zoom_ = 0.9; break; case apk_cum_chi2: y = 0.; for (vector::const_iterator i = first; i < last; i++) y += diff_chi2_of_data_for_draw_data(i, model); y_zoom_base_ = pixel_height / y; y_zoom_ = 0.9; break; case apk_empty: //assert(0); break; } } void AuxPlot::OnAutoZoom(wxCommandEvent& event) { auto_zoom_y_ = event.IsChecked(); if (auto_zoom_y_) { //fit_y_zoom() is called from draw refresh(); Refresh(false); // needed on Windows (i don't know why) } } // ======================================================================== AuxPlotConfDlg::AuxPlotConfDlg(AuxPlot* ap) : wxDialog(NULL, -1, wxString(wxT("Configure Auxiliary Plot")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), ap_(ap) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *hor_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *left_sizer = new wxBoxSizer(wxVERTICAL); wxArrayString plot_choices; plot_choices.Add(wxT("&Empty")); plot_choices.Add(wxT("&Diff")); plot_choices.Add(wxT("&Weighted diff")); plot_choices.Add(wxT("Diff as % of &y")); plot_choices.Add(wxT("&Cumulative \u03c7\u00b2")); // chi2 wxRadioBox* plot_rb = new wxRadioBox(this, -1, wxT("plot"), wxDefaultPosition, wxDefaultSize, plot_choices, 1, wxRA_SPECIFY_COLS); plot_rb->SetSelection(ap_->kind_); left_sizer->Add(plot_rb, 0, wxALL, 5); rev_cb_ = new wxCheckBox(this, -1, wxT("&Reversed")); rev_cb_->SetValue(ap_->reversed_diff_); rev_cb_->Enable(ap_->kind_ != apk_empty && ap_->kind_ != apk_cum_chi2); left_sizer->Add(rev_cb_, 0, wxALL, 5); wxCheckBox* pos_cb = new wxCheckBox(this, -1, wxT("&Show peak positions")); pos_cb->SetValue(ap_->mark_peak_pos_); left_sizer->Add(pos_cb, 0, wxALL, 5); wxCheckBox* auto_cb = new wxCheckBox(this, -1, wxT("&Auto-zoom y scale")); auto_cb->SetValue(ap_->auto_zoom_y_); left_sizer->Add(auto_cb, 0, wxALL, 5); wxBoxSizer *zoom_sizer = new wxBoxSizer(wxHORIZONTAL); zoom_sizer->AddSpacer(10); zoom_sizer->Add(new wxStaticText(this, -1, wxT("y zoom")), 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); zoom_sc_ = new SpinCtrl(this, -1, iround(ap_->y_zoom_ * 100), 0, 999999, 70); zoom_sc_->Enable(!ap_->auto_zoom_y_); zoom_sizer->Add(zoom_sc_, 0, wxALL, 5); zoom_sizer->Add(new wxStaticText(this, -1, wxT("%")), 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5); left_sizer->Add(zoom_sizer, 0); wxGridSizer *gsizer = new wxGridSizer(2, 5, 5); wxSizerFlags cl = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL), cr = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT); gsizer->Add(new wxStaticText(this, -1, wxT("background color")), cr); bg_cp_ = new wxColourPickerCtrl(this, -1, ap_->get_bg_color()); gsizer->Add(bg_cp_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("active data color")), cr); active_cp_ = new wxColourPickerCtrl(this, -1, ap_->activeDataCol); gsizer->Add(active_cp_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("inactive data color")), cr); inactive_cp_ = new wxColourPickerCtrl(this, -1, ap_->inactiveDataCol); gsizer->Add(inactive_cp_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("axis & tics color")), cr); axis_cp_ = new wxColourPickerCtrl(this, -1, ap_->xAxisCol); gsizer->Add(axis_cp_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("tic label font")), cr); tics_fp_ = new wxFontPickerCtrl(this, -1, ap_->ticsFont); gsizer->Add(tics_fp_, cl); hor_sizer->Add(left_sizer, wxSizerFlags().Border()); hor_sizer->Add(gsizer, wxSizerFlags().Border()); top_sizer->Add(hor_sizer, 0); top_sizer->Add(persistance_note(this), wxSizerFlags().Center().Border()); top_sizer->Add(new wxButton(this, wxID_CLOSE), wxSizerFlags().Right().Border()); SetSizerAndFit(top_sizer); SetEscapeId(wxID_CLOSE); Connect(plot_rb->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(AuxPlotConfDlg::OnPlotKind)); Connect(rev_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(AuxPlotConfDlg::OnReversedDiff)); Connect(pos_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(AuxPlotConfDlg::OnMarkPeakPositions)); Connect(auto_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(AuxPlotConfDlg::OnAutoZoom)); Connect(zoom_sc_->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(AuxPlotConfDlg::OnZoomSpin)); Connect(bg_cp_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, wxColourPickerEventHandler(AuxPlotConfDlg::OnColor)); Connect(active_cp_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, wxColourPickerEventHandler(AuxPlotConfDlg::OnColor)); Connect(inactive_cp_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, wxColourPickerEventHandler(AuxPlotConfDlg::OnColor)); Connect(axis_cp_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, wxColourPickerEventHandler(AuxPlotConfDlg::OnColor)); Connect(tics_fp_->GetId(), wxEVT_COMMAND_FONTPICKER_CHANGED, wxFontPickerEventHandler(AuxPlotConfDlg::OnTicsFont)); } void AuxPlotConfDlg::OnPlotKind(wxCommandEvent& event) { AuxPlotKind k = static_cast(event.GetSelection()); ap_->change_plot_kind(k); rev_cb_->Enable(k != apk_empty && k != apk_cum_chi2); } void AuxPlotConfDlg::OnReversedDiff(wxCommandEvent& event) { ap_->reversed_diff_ = event.IsChecked(); ap_->refresh(); } void AuxPlotConfDlg::OnAutoZoom(wxCommandEvent& event) { ap_->OnAutoZoom(event); zoom_sc_->Enable(!ap_->auto_zoom_y_); } void AuxPlotConfDlg::OnZoomSpin(wxSpinEvent& event) { ap_->y_zoom_ = event.GetPosition() / 100.; ap_->refresh(); } void AuxPlotConfDlg::OnTicsFont(wxFontPickerEvent& event) { ap_->ticsFont = event.GetFont(); ap_->refresh(); } void AuxPlotConfDlg::OnColor(wxColourPickerEvent& event) { int id = event.GetId(); if (id == bg_cp_->GetId()) ap_->set_bg_color(event.GetColour()); else if (id == active_cp_->GetId()) ap_->activeDataCol = event.GetColour(); else if (id == inactive_cp_->GetId()) ap_->inactiveDataCol = event.GetColour(); else if (id == axis_cp_->GetId()) ap_->xAxisCol = event.GetColour(); ap_->refresh(); } fityk-1.3.1/wxgui/aplot.h000066400000000000000000000041761302634723100153060ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_APLOT_H_ #define FITYK_WX_APLOT_H_ #include "plot.h" enum AuxPlotKind { apk_empty, apk_diff, apk_diff_stddev, apk_diff_y_perc, apk_cum_chi2 }; //Auxiliary plot, usually shows residuals or peak positions class AuxPlot : public FPlot { friend class AuxPlotConfDlg; public: AuxPlot(wxWindow *parent, FPlot *master, wxString const& name); ~AuxPlot() {} void save_settings(wxConfigBase *cf) const; void read_settings(wxConfigBase *cf); void show_pref_dialog(); private: static const int move_plot_margin_width = 20; FPlot* master_; const wxString name_; AuxPlotKind kind_; bool mark_peak_pos_; bool reversed_diff_; double y_zoom_, y_zoom_base_; bool auto_zoom_y_; bool fit_y_once_; void OnPaint(wxPaintEvent &event); virtual void draw(wxDC &dc, bool monochrome=false); void OnLeaveWindow (wxMouseEvent& event); void OnMouseMove(wxMouseEvent &event); void OnLeftDown(wxMouseEvent &event); void OnLeftUp(wxMouseEvent &event); void OnRightDown(wxMouseEvent &event); void OnMiddleDown(wxMouseEvent &event); // function called when Esc is pressed virtual void cancel_action() { cancel_mouse_left_press(); } void cancel_mouse_left_press(); void set_scale(int pixel_width, int pixel_height); bool is_zoomable(); //false if kind is eg. empty or peak-position void OnPrefs(wxCommandEvent&) { show_pref_dialog(); } void OnPopupPlot(wxCommandEvent& event); void OnMarkPeakPositions(wxCommandEvent& event); void OnPopupYZoom(wxCommandEvent& event); void OnPopupYZoomFit(wxCommandEvent& event); void OnAutoZoom(wxCommandEvent& event); void draw_diff (wxDC& dc, std::vector::const_iterator first, std::vector::const_iterator last); void draw_zoom_text(wxDC& dc, bool set_pen=true); void fit_y_zoom(fityk::Data const* data, fityk::Model const* model); void change_plot_kind(AuxPlotKind kind); DECLARE_EVENT_TABLE() }; #endif fityk-1.3.1/wxgui/app.cpp000066400000000000000000000361411302634723100152770ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include #include #include #include #include #ifdef __WXGTK3__ #error "Not everything is working with wxGTK3. Use default wxGTK instead, " \ "based on GTK+2. If you want to test it, just remove this #error." #endif #include #include #include #include #include #ifndef _WIN32 # include #endif #include "app.h" #include "cmn.h" #include "frame.h" #include "plotpane.h" #include "dataedit.h" //DataEditorDlg::read_transforms() #include "sidebar.h" // initializations #include "statbar.h" // initializations #include "mplot.h" // MainPlot::bgm() #include "bgm.h" // [gs]et_bg_subtracted() #include "fityk/logic.h" #include "fityk/info.h" // build_info() using namespace std; using fityk::UserInterface; using fityk::range_vector; IMPLEMENT_APP(FApp) /// command line options static const wxCmdLineEntryDesc cmdLineDesc[] = { { wxCMD_LINE_SWITCH, "h", "help", "show this help message", wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP }, { wxCMD_LINE_SWITCH, "V", "version", "output version information and exit", wxCMD_LINE_VAL_NONE, 0 }, { wxCMD_LINE_SWITCH, "", "full-version", "print version with additional info and exit", wxCMD_LINE_VAL_NONE, 0 }, { wxCMD_LINE_OPTION, "c", "cmd", "script passed in as string", wxCMD_LINE_VAL_STRING, 0 }, { wxCMD_LINE_OPTION, "g", "config", "choose GUI configuration", wxCMD_LINE_VAL_STRING, 0 }, { wxCMD_LINE_SWITCH, "I", "no-init", "don't process $HOME/.fityk/init file", wxCMD_LINE_VAL_NONE, 0 }, { wxCMD_LINE_SWITCH, "r", "reorder", "reorder data (50.xy before 100.xy)", wxCMD_LINE_VAL_NONE, 0 }, { wxCMD_LINE_PARAM, 0, 0, "script or data file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL|wxCMD_LINE_PARAM_MULTIPLE }, { wxCMD_LINE_NONE, 0, 0, 0, wxCMD_LINE_VAL_NONE, 0 } }; //---------------- C A L L B A C K S -------------------------------------- static void gui_show_message(UserInterface::Style style, const string& s) { frame->output_text(style, s + "\n"); } static string gui_user_input(const string& prompt) { if (contains_element(prompt, "[y/n]")) { int r = wxMessageBox(s2wx(prompt), "Query", wxYES_NO); if (r == wxYES) return "y"; else if (r == wxNO) return "n"; else return ""; } else { wxString s = wxGetTextFromUser(s2wx(prompt), "Query"); return strip_string(wx2s(s)); } } static void gui_draw_plot(UserInterface::RepaintMode mode, const char* filename) { if (filename == NULL) { bool now = (mode == UserInterface::kRepaintImmediately); frame->plot_pane()->refresh_plots(now, kAllPlots); } else { wxString path(filename); wxBitmap bmp = frame->plot_pane()->prepare_bitmap_for_export(640, 480, false); if (path.Lower().EndsWith(".bmp")) bmp.SaveFile(path, wxBITMAP_TYPE_BMP); else if (path.Lower().EndsWith(".png")) bmp.ConvertToImage().SaveFile(path, wxBITMAP_TYPE_PNG); else ftk->ui()->warn("Plot path must end with .bmp or .png"); } } static void gui_hint(const string& key, const string& value) { static wxWindowDisabler *wd = NULL; if (key == "busy") { // This is typically used during time-consuming computations. if (!value.empty()) wd = new wxWindowDisabler(); else { delete wd; wd = NULL; } } else if (key == "yield") { wxYield(); } else if (key == "bg_subtracted_from") { frame->get_main_plot()->bgm()->set_bg_subtracted(value, true); } else { ftk->ui()->warn("[GUI] unknown property: " + key); } } static string ui_state() { string ret; string bg_subtracted = frame->get_main_plot()->bgm()->get_bg_subtracted(); if (!bg_subtracted.empty()) ret += "\nui bg_subtracted_from =" + bg_subtracted; return ret; } static UserInterface::Status gui_exec_command(const string& s) { //FIXME should I limit number of displayed lines? //const int max_lines_in_output_win = 1000; //don't output plot command - it is generated by every zoom in/out etc. bool output = strncmp(s.c_str(), "plot", 4) != 0; if (output) frame->output_text(UserInterface::kInput, "=-> " + s + "\n"); else frame->set_status_text(s); wxBusyCursor wait; UserInterface::Status r; try { r = ftk->ui()->execute_line(s); } catch(fityk::ExitRequestedException) { frame->Close(true); return UserInterface::kStatusOk; } frame->after_cmd_updates(); return r; } //------------------------------------------------------------------------- static void interrupt_handler (int /*signum*/) { fityk::user_interrupt = 1; // set flag to stop computations } static void write_white_config(wxConfigBase *w) { cfg_write_color(w, "MainPlot/Colors/bg", wxColour(255, 255, 255)); cfg_write_color(w, "MainPlot/Colors/model", wxColour(0, 0, 127)); cfg_write_color(w, "MainPlot/Colors/xAxis", wxColour(0, 0, 0)); cfg_write_color(w, "MainPlot/Colors/data/0", wxColour(0, 127, 0)); cfg_write_color(w, "MainPlot/Colors/peak/0", wxColour(255, 89, 89)); cfg_write_color(w, "AuxPlot_0/Colors/bg", wxColour(255, 255, 255)); cfg_write_color(w, "AuxPlot_0/Colors/active_data", wxColour(0, 127, 0)); cfg_write_color(w, "AuxPlot_0/Colors/xAxis", wxColour(0, 0, 0)); cfg_write_color(w, "AuxPlot_1/Colors/bg", wxColour(255, 255, 255)); cfg_write_color(w, "AuxPlot_1/Colors/active_data", wxColour(0, 127, 0)); cfg_write_color(w, "AuxPlot_1/Colors/xAxis", wxColour(0, 0, 0)); cfg_write_color(w, "OutputWin/Colors/normal", wxColour(51, 51, 51)); cfg_write_color(w, "OutputWin/Colors/warn", wxColour(172, 0, 0)); cfg_write_color(w, "OutputWin/Colors/quot", wxColour(46, 58, 107)); cfg_write_color(w, "OutputWin/Colors/input", wxColour(0, 76, 9)); cfg_write_color(w, "OutputWin/Colors/bg", wxColour(255, 255, 255)); } FApp::FApp() { #ifdef __WXGTK__ // ubuntu menu-proxy makes the program crashing, see e.g. // https://bugs.launchpad.net/ubuntu/+source/unity-gtk-module/+bug/1452791 // workaround as per http://trac.wxwidgets.org/ticket/14302#comment:6 wxSetEnv("UBUNTU_MENUPROXY", "0"); #endif } bool FApp::OnInit(void) { #ifndef _WIN32 // setting Ctrl-C handler if (signal (SIGINT, interrupt_handler) == SIG_IGN) signal (SIGINT, SIG_IGN); #endif //_WIN32 SetAppName(wxT("fityk")); // if options can be parsed wxCmdLineParser cmdLineParser(cmdLineDesc, argc, argv); if (cmdLineParser.Parse(false) != 0) { cmdLineParser.Usage(); return false; //false = exit the application } else if (cmdLineParser.Found(wxT("V"))) { wxMessageOutput::Get()->Printf(wxT("fityk version %s\n"), wxT(VERSION)); return false; //false = exit the application } else if (cmdLineParser.Found("full-version")) { wxMessageOutput::Get()->Printf("fityk version %s\n%s\n%s\n", VERSION, fityk::build_info().c_str(), wxVERSION_STRING); return false; //false = exit the application } //the rest of options will be processed in process_argv() ftk = new fityk::Full; // set callbacks ftk->ui()->connect_show_message(gui_show_message); ftk->ui()->connect_draw_plot(gui_draw_plot); ftk->ui()->connect_hint_ui(gui_hint); ftk->ui()->connect_exec_command(gui_exec_command); ftk->ui()->connect_user_input(gui_user_input); ftk->ui()->connect_ui_state(ui_state); wxImage::AddHandler(new wxPNGHandler); //global settings #if wxUSE_TOOLTIPS wxToolTip::Enable (true); wxToolTip::SetDelay (500); #endif //create user data directory, if it doesn't exists wxString fityk_dir = wxStandardPaths::Get().GetUserDataDir(); if (!wxDirExists(fityk_dir)) wxMkdir(fityk_dir); wxConfig::DontCreateOnDemand(); // set config file for options automatically saved // it will be accessed only via wxConfig::Get() wxFileConfig *config = new wxFileConfig(wxEmptyString, wxEmptyString, get_conf_file("wxoptions")); wxConfig::Set(config); // directory for configs config_dir = fityk_dir + wxFILE_SEP_PATH + wxT("configs") + wxFILE_SEP_PATH; if (!wxDirExists(config_dir)) { wxMkdir(config_dir); // create white-background config boost::scoped_ptr w(new wxFileConfig("", "", config_dir+"white")); write_white_config(w.get()); } // moving configs from ver. <= 0.9.7 to the current locations wxString old_config = get_conf_file("config"); if (wxFileExists(old_config)) wxRenameFile(old_config, config_dir + wxT("default"), false); wxString old_alt_config = get_conf_file("alt-config"); if (wxFileExists(old_alt_config)) wxRenameFile(old_alt_config, config_dir + wxT("alt-config"), false); EditTransDlg::read_transforms(false); // Create the main frame window frame = new FFrame(NULL, -1, wxT("fityk"), wxDEFAULT_FRAME_STYLE); wxString ini_conf = wxT("default"); // if the -g option was given, it replaces default config cmdLineParser.Found(wxT("g"), &ini_conf); wxConfigBase *cf = new wxFileConfig(wxT(""), wxT(""), config_dir+ini_conf); frame->read_all_settings(cf); frame->Show(true); // sash inside wxNoteBook can have wrong position (eg. wxGTK 2.7.1) frame->sidebar_->read_settings(cf); // sash on the status bar is also in the wrong place (wxGTK), // because for some reason wxSplitterWindow had width=0 before Show() frame->status_bar_->read_settings(cf); delete cf; SetTopWindow(frame); if (!cmdLineParser.Found(wxT("I"))) { // run initial commands wxString startup_file = get_conf_file(fityk::startup_commands_filename()); if (wxFileExists(startup_file)) { ftk->ui()->exec_fityk_script(wx2s(startup_file)); } } try { process_argv(cmdLineParser); } catch(fityk::ExitRequestedException) { return false; } frame->after_cmd_updates(); return true; } int FApp::OnExit() { delete ftk; wxConfig::Get()->Write(wxT("/FitykVersion"), pchar2wx(VERSION)); delete wxConfig::Set((wxConfig *) NULL); return 0; } #ifdef __WXMAC__ #include void FApp::MacOpenFile(const wxString &filename) { try { ftk->process_cmd_line_arg(wx2s(filename)); } catch (runtime_error const& e) { wxMessageBox(s2wx(e.what()), "Open File Error", wxOK|wxICON_ERROR); } } #endif namespace { struct less_filename : public binary_function { int n; less_filename(int n_) : n(n_) {} bool operator()(string x, string y) { if (isdigit(x[n]) && isdigit(y[n])) { string xc(x, n), yc(y, n); return strtod(xc.c_str(), 0) < strtod(yc.c_str(), 0); } else return x < y; } }; int find_common_prefix_length(vector const& p) { assert(p.size() > 1); for (size_t n = 0; n < p.begin()->size(); ++n) for (vector::const_iterator i = p.begin()+1; i != p.end(); ++i) if (n >= i->size() || (*i)[n] != (*p.begin())[n]) return n; return p.begin()->size(); } } // anonymous namespace /// parse and execute command line switches and arguments void FApp::process_argv(wxCmdLineParser &cmdLineParser) { wxString cmd; if (cmdLineParser.Found(wxT("c"), &cmd)) ftk->ui()->exec_and_log(wx2s(cmd)); //the rest of parameters/arguments are scripts and/or data files vector p; for (unsigned int i = 0; i < cmdLineParser.GetParamCount(); i++) p.push_back(wx2s(cmdLineParser.GetParam(i))); if (cmdLineParser.Found(wxT("r")) && p.size() > 1) { // reorder sort(p.begin(), p.end(), less_filename(find_common_prefix_length(p))); } for (vector::const_iterator i = p.begin(); i != p.end(); ++i) { try { ftk->process_cmd_line_arg(*i); } catch (runtime_error const& e) { fprintf(stderr, "Error: %s\n", e.what()); exit(1); } } #ifdef __WXMAC__ // I'm not sure if it's a bug or undocumented feature: // on Mac the last argv is handled also in MacOpenFile() // Here is workaround: if (!p.empty()) OSXStoreOpenFiles(wxArrayString()); #endif if (ftk->dk.count() > 1) { frame->SwitchSideBar(true); // zoom to show all loaded datafiles RealRange r; ftk->view.change_view(r, r, range_vector(0, ftk->dk.count())); } } // search for `name' in two or three directories: // wxStandardPaths::GetResourcesDir() // on Mac: appname.app/Contents/Resources bundle subdir // on Win: dir where executable is // HELP_DIR = $(pkgdatadir), not defined on Win // {exedir}/../../doc/ and {exedir}/../../../doc/ - for uninstalled program wxString get_help_url(const wxString& name) { wxString dir = wxFILE_SEP_PATH + wxString(wxT("html")); wxPathList paths; // installed path #if defined(__WXMAC__) || defined(__WXMSW__) paths.Add(wxStandardPaths::Get().GetResourcesDir() + dir); #endif #ifdef HELP_DIR paths.Add(wxT(HELP_DIR) + dir); #endif // uninstalled paths, relative to executable wxString up = wxFILE_SEP_PATH + wxString(wxT("..")); paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up + wxFILE_SEP_PATH + wxT("doc") + dir); paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up + up + wxFILE_SEP_PATH + wxT("doc") + dir); wxString path = paths.FindAbsoluteValidPath(name); if (!path.IsEmpty()) return wxFileSystem::FileNameToURL(path); else return wxT("http://fityk.nieto.pl/") + name; } wxString get_sample_path(const wxString& name) { wxString dir = wxFILE_SEP_PATH + wxString(wxT("samples")); wxPathList paths; // installed path #if defined(__WXMAC__) || defined(__WXMSW__) paths.Add(wxStandardPaths::Get().GetResourcesDir() + dir); #endif #ifdef HELP_DIR paths.Add(wxT(HELP_DIR) + dir); #endif // uninstalled paths, relative to executable wxString up = wxFILE_SEP_PATH + wxString(wxT("..")); paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up + dir); paths.Add(wxPathOnly(wxGetApp().argv[0]) + up + up + up + dir); wxFileName path(paths.FindAbsoluteValidPath(name)); path.Normalize(wxPATH_NORM_DOTS); return path.GetFullPath(); } #ifdef __WXMAC__ void open_new_instance() { string res = wx2s(wxStandardPaths::Get().GetResourcesDir()); // it has "/Contents/Resources" (19 chars) after bundle.app if (res.size() > 19) system(("open -n " + res.substr(0, res.size()-19)).c_str()); } #endif fityk-1.3.1/wxgui/app.h000066400000000000000000000014021302634723100147340ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_APP_H_ #define FITYK_WX_APP_H_ class wxCmdLineParser; /// Fityk-GUI "main loop" class FApp: public wxApp { public: // directory for (named by user) config files wxString config_dir; FApp(); virtual bool OnInit(void); virtual int OnExit(); #ifdef __WXMAC__ virtual void MacOpenFile(const wxString &fileName); #endif private: bool is_fityk_script(std::string filename); void process_argv(wxCmdLineParser &cmdLineParser); }; wxString get_help_url(const wxString& name); wxString get_sample_path(const wxString& name); #ifdef __WXMAC__ void open_new_instance(); #endif DECLARE_APP(FApp) #endif fityk-1.3.1/wxgui/atomtables.c000066400000000000000000001227661302634723100163230ustar00rootroot00000000000000/* debyer -- program for calculation of diffration patterns * Copyright (C) 2009 Marcin Wojdyr (only code, not the tabular data) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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. * * $Id$ */ #include "atomtables.h" #include #include #include #ifdef _MSC_VER // disable warning about truncation from 'double' to 'float' #pragma warning (disable : 4305) #endif /* Periodic system of elements data. * This data can be also found in cctbx, ObjCryst and atominfo. * I'm not sure from which of these programs/libraries this was copied. * Reference: * CRC Handbook of Chemistry & Physics, 63rd edition, 1982-1983 * CRC Handbook of Chemistry & Physics, 70th edition, 1989-1990 */ const t_pse pse_table[] = { { 1, "H", "hydrogen", 1.008 }, { 1, "D", "deuterium", 2.000 }, { 2, "He", "helium", 4.003 }, { 3, "Li", "lithium", 6.941 }, { 4, "Be", "beryllium", 9.012 }, { 5, "B", "boron", 10.811 }, { 6, "C", "carbon", 12.011 }, { 7, "N", "nitrogen", 14.007 }, { 8, "O", "oxygen", 15.999 }, { 9, "F", "fluorine", 18.998 }, { 10, "Ne", "neon", 20.180 }, { 11, "Na", "sodium", 22.990 }, { 12, "Mg", "magnesium", 24.305 }, { 13, "Al", "aluminium", 26.982 }, { 14, "Si", "silicon", 28.086 }, { 15, "P", "phosphorus", 30.974 }, { 16, "S", "sulphur", 32.066 }, { 17, "Cl", "chlorine", 35.452 }, { 18, "Ar", "argon", 39.948 }, { 19, "K", "potassium", 39.098 }, { 20, "Ca", "calcium", 40.078 }, { 21, "Sc", "scandium", 44.956 }, { 22, "Ti", "titanium", 47.883 }, { 23, "V", "vanadium", 50.941 }, { 24, "Cr", "chromium", 51.996 }, { 25, "Mn", "manganese", 54.938 }, { 26, "Fe", "iron", 55.847 }, { 27, "Co", "cobalt", 58.933 }, { 28, "Ni", "nickel", 58.691 }, { 29, "Cu", "copper", 63.546 }, { 30, "Zn", "zinc", 65.392 }, { 31, "Ga", "gallium", 69.723 }, { 32, "Ge", "germanium", 72.612 }, { 33, "As", "arsenic", 74.922 }, { 34, "Se", "selenium", 78.963 }, { 35, "Br", "bromine", 79.904 }, { 36, "Kr", "krypton", 83.801 }, { 37, "Rb", "rubidium", 85.468 }, { 38, "Sr", "strontium", 87.621 }, { 39, "Y", "yttrium", 88.906 }, { 40, "Zr", "zirconium", 91.224 }, { 41, "Nb", "niobium", 92.906 }, { 42, "Mo", "molybdenum", 95.941 }, { 43, "Tc", "technetium", 98.000 }, { 44, "Ru", "ruthenium", 101.072 }, { 45, "Rh", "rhodium", 102.905 }, { 46, "Pd", "palladium", 106.421 }, { 47, "Ag", "silver", 107.868 }, { 48, "Cd", "cadmium", 112.411 }, { 49, "In", "indium", 114.821 }, { 50, "Sn", "tin", 118.710 }, { 51, "Sb", "antimony", 121.753 }, { 52, "Te", "tellurium", 127.603 }, { 53, "I", "iodine", 126.904 }, { 54, "Xe", "xenon", 131.292 }, { 55, "Cs", "caesium", 132.905 }, { 56, "Ba", "barium", 137.327 }, { 57, "La", "lanthanum", 138.906 }, { 58, "Ce", "cerium", 140.115 }, { 59, "Pr", "praseodymium", 140.908 }, { 60, "Nd", "neodymium", 144.243 }, { 61, "Pm", "promethium", 145.000 }, { 62, "Sm", "samarium", 150.363 }, { 63, "Eu", "europium", 151.965 }, { 64, "Gd", "gadolinium", 157.253 }, { 65, "Tb", "terbium", 158.925 }, { 66, "Dy", "dysprosium", 162.503 }, { 67, "Ho", "holmium", 164.930 }, { 68, "Er", "erbium", 167.263 }, { 69, "Tm", "thulium", 168.934 }, { 70, "Yb", "ytterbium", 173.043 }, { 71, "Lu", "lutetium", 174.967 }, { 72, "Hf", "hafnium", 178.492 }, { 73, "Ta", "tantalum", 180.948 }, { 74, "W", "tungsten", 183.853 }, { 75, "Re", "rhenium", 186.207 }, { 76, "Os", "osmium", 190.210 }, { 77, "Ir", "iridium", 192.223 }, { 78, "Pt", "platinum", 195.083 }, { 79, "Au", "gold", 196.967 }, { 80, "Hg", "mercury", 200.593 }, { 81, "Tl", "thallium", 204.383 }, { 82, "Pb", "lead", 207.210 }, { 83, "Bi", "bismuth", 208.980 }, { 84, "Po", "polonium", 209.000 }, { 85, "At", "astatine", 210.000 }, { 86, "Rn", "radon", 222.000 }, { 87, "Fr", "francium", 223.000 }, { 88, "Ra", "radium", 226.025 }, { 89, "Ac", "actinium", 227.028 }, { 90, "Th", "thorium", 232.038 }, { 91, "Pa", "protactinium", 231.035 }, { 92, "U", "uranium", 238.028 }, { 93, "Np", "neptunium", 237.048 }, { 94, "Pu", "plutonium", 244.000 }, { 95, "Am", "americium", 243.000 }, { 96, "Cm", "curium", 247.000 }, { 97, "Bk", "berkelium", 247.000 }, { 98, "Cf", "californium", 251.000 }, { 99, "Es", "einsteinium", 254.000 }, { 100, "Fm", "fermium", 257.000 }, { 101, "Md", "mendelevium", 258.000 }, { 102, "No", "nobelium", 259.000 }, { 103, "Lr", "lawrencium", 260.000 }, { 0, NULL, NULL, 0. } }; const t_pse *find_in_pse(const char *label) { const t_pse *it; char buf[3] = { 0, 0, 0 }; /* empty label */ if (label == NULL || *label == '\0') return NULL; buf[0] = toupper(label[0]); if (strlen(label) > 1 && isalpha(label[1])) buf[1] = tolower(label[1]); for (it = pse_table; it->Z != 0; it++) if (strcmp(it->symbol, buf) == 0) return it; return NULL; } const t_pse *find_Z_in_pse(int Z) { if (Z == 1) return &pse_table[0]; else if (Z > 1 && Z <= 103) return &pse_table[Z]; else return NULL; } /***************************************************************************/ const t_it92_coeff it92_table[] = { { "H", { 0.493002, 0.322912, 0.140191, 0.040810 }, { 10.5109, 26.1257, 3.14236, 57.7997 }, 0.003038 }, { "H'", { 0.489918, 0.262003, 0.196767, 0.049879 }, { 20.6593, 7.74039, 49.5519, 2.20159 }, 0.001305 }, /* "'" added */ { "D", { 0.489918, 0.262003, 0.196767, 0.049879 }, { 20.6593, 7.74039, 49.5519, 2.20159 }, 0.001305 }, /* copy of "H'" */ { "H1-", { 0.897661, 0.565616, 0.415815, 0.116973 }, { 53.1368, 15.1870, 186.576, 3.56709 }, 0.002389 }, { "He", { 0.873400, 0.630900, 0.311200, 0.178000 }, { 9.10370, 3.35680, 22.9276, 0.982100 }, 0.006400 }, { "Li", { 1.12820, 0.750800, 0.617500, 0.465300 }, { 3.95460, 1.05240, 85.3905, 168.261 }, 0.037700 }, { "Li1+", { 0.696800, 0.788800, 0.341400, 0.156300 }, { 4.62370, 1.95570, 0.631600, 10.0953 }, 0.016700 }, { "Be", { 1.59190, 1.12780, 0.539100, 0.702900 }, { 43.6427, 1.86230, 103.483, 0.542000 }, 0.038500 }, { "Be2+", { 6.26030, 0.884900, 0.799300, 0.164700 }, { 0.002700, 0.831300, 2.27580, 5.11460 }, -6.1092 }, { "B", { 2.05450, 1.33260, 1.09790, 0.706800 }, { 23.2185, 1.02100, 60.3498, 0.140300 }, -0.19320 }, { "C", { 2.31000, 1.02000, 1.58860, 0.865000 }, { 20.8439, 10.2075, 0.568700, 51.6512 }, 0.215600 }, { "Cval", { 2.26069, 1.56165, 1.05075, 0.839259 }, { 22.6907, 0.656665, 9.75618, 55.5949 }, 0.286977 }, { "N", { 12.2126, 3.13220, 2.01250, 1.16630 }, { 0.005700, 9.89330, 28.9975, 0.582600 }, -11.529 }, { "O", { 3.04850, 2.28680, 1.54630, 0.867000 }, { 13.2771, 5.70110, 0.323900, 32.9089 }, 0.250800 }, { "O1-", { 4.19160, 1.63969, 1.52673, -20.307 }, { 12.8573, 4.17236, 47.0179, -0.01404 }, 21.9412 }, { "O2-", { 3.75040, 2.84294, 1.54298, 1.62091 }, { 16.5151, 6.59203, 0.319201, 43.3486 }, 0.242060 }, /* Hovestreydt, Acta Cryst. (1983) A39, 268-269 */ { "F", { 3.53920, 2.64120, 1.51700, 1.02430 }, { 10.2825, 4.29440, 0.261500, 26.1476 }, 0.277600 }, { "F1-", { 3.63220, 3.51057, 1.26064, 0.940706 }, { 5.27756, 14.7353, 0.442258, 47.3437 }, 0.653396 }, { "Ne", { 3.95530, 3.11250, 1.45460, 1.12510 }, { 8.40420, 3.42620, 0.230600, 21.7184 }, 0.351500 }, { "Na", { 4.76260, 3.17360, 1.26740, 1.11280 }, { 3.28500, 8.84220, 0.313600, 129.424 }, 0.676000 }, { "Na1+", { 3.25650, 3.93620, 1.39980, 1.00320 }, { 2.66710, 6.11530, 0.200100, 14.0390 }, 0.404000 }, { "Mg", { 5.42040, 2.17350, 1.22690, 2.30730 }, { 2.82750, 79.2611, 0.380800, 7.19370 }, 0.858400 }, { "Mg2+", { 3.49880, 3.83780, 1.32840, 0.849700 }, { 2.16760, 4.75420, 0.185000, 10.1411 }, 0.485300 }, { "Al", { 6.42020, 1.90020, 1.59360, 1.96460 }, { 3.03870, 0.742600, 31.5472, 85.0886 }, 1.11510 }, { "Al3+", { 4.17448, 3.38760, 1.20296, 0.528137 }, { 1.93816, 4.14553, 0.228753, 8.28524 }, 0.706786 }, { "Si", { 6.29150, 3.03530, 1.98910, 1.54100 }, { 2.43860, 32.3337, 0.678500, 81.6937 }, 1.14070 }, /* copy of "Siv" */ { "Siv", { 6.29150, 3.03530, 1.98910, 1.54100 }, { 2.43860, 32.3337, 0.678500, 81.6937 }, 1.14070 }, { "Sival", { 5.66269, 3.07164, 2.62446, 1.39320 }, { 2.66520, 38.6634, 0.916946, 93.5458 }, 1.24707 }, { "Si4+", { 4.43918, 3.20345, 1.19453, 0.416530 }, { 1.64167, 3.43757, 0.214900, 6.65365 }, 0.746297 }, { "P", { 6.43450, 4.17910, 1.78000, 1.49080 }, { 1.90670, 27.1570, 0.526000, 68.1645 }, 1.11490 }, { "S", { 6.90530, 5.20340, 1.43790, 1.58630 }, { 1.46790, 22.2151, 0.253600, 56.1720 }, 0.866900 }, { "Cl", { 11.4604, 7.19640, 6.25560, 1.64550 }, { 0.010400, 1.16620, 18.5194, 47.7784 }, -9.5574 }, { "Cl1-", { 18.2915, 7.20840, 6.53370, 2.33860 }, { 0.006600, 1.17170, 19.5424, 60.4486 }, -16.378 }, { "Ar", { 7.48450, 6.77230, 0.653900, 1.64420 }, { 0.907200, 14.8407, 43.8983, 33.3929 }, 1.44450 }, { "K", { 8.21860, 7.43980, 1.05190, 0.865900 }, { 12.7949, 0.774800, 213.187, 41.6841 }, 1.42280 }, { "K1+", { 7.95780, 7.49170, 6.35900, 1.19150 }, { 12.6331, 0.767400, -0.00200, 31.9128 }, -4.9978 }, { "Ca", { 8.62660, 7.38730, 1.58990, 1.02110 }, { 10.4421, 0.659900, 85.7484, 178.437 }, 1.37510 }, { "Ca2+", { 15.6348, 7.95180, 8.43720, 0.853700 }, { -0.00740, 0.608900, 10.3116, 25.9905 }, -14.875 }, { "Sc", { 9.18900, 7.36790, 1.64090, 1.46800 }, { 9.02130, 0.572900, 136.108, 51.3531 }, 1.33290 }, { "Sc3+", { 13.4008, 8.02730, 1.65943, 1.57936 }, { 0.298540, 7.96290, -0.28604, 16.0662 }, -6.6667 }, { "Ti", { 9.75950, 7.35580, 1.69910, 1.90210 }, { 7.85080, 0.500000, 35.6338, 116.105 }, 1.28070 }, { "Ti2+", { 9.11423, 7.62174, 2.27930, 0.087899 }, { 7.52430, 0.457585, 19.5361, 61.6558 }, 0.897155 }, { "Ti3+", { 17.7344, 8.73816, 5.25691, 1.92134 }, { 0.220610, 7.04716, -0.15762, 15.9768 }, -14.652 }, { "Ti4+", { 19.5114, 8.23473, 2.01341, 1.52080 }, { 0.178847, 6.67018, -0.29263, 12.9464 }, -13.280 }, { "V", { 10.2971, 7.35110, 2.07030, 2.05710 }, { 6.86570, 0.438500, 26.8938, 102.478 }, 1.21990 }, { "V2+", { 10.1060, 7.35410, 2.28840, 0.022300 }, { 6.88180, 0.440900, 20.3004, 115.122 }, 1.22980 }, { "V3+", { 9.43141, 7.74190, 2.15343, 0.016865 }, { 6.39535, 0.383349, 15.1908, 63.9690 }, 0.656565 }, { "V5+", { 15.6887, 8.14208, 2.03081, -9.5760 }, { 0.679003, 5.40135, 9.97278, 0.940464 }, 1.71430 }, { "Cr", { 10.6406, 7.35370, 3.32400, 1.49220 }, { 6.10380, 0.392000, 20.2626, 98.7399 }, 1.18320 }, { "Cr2+", { 9.54034, 7.75090, 3.58274, 0.509107 }, { 5.66078, 0.344261, 13.3075, 32.4224 }, 0.616898 }, { "Cr3+", { 9.68090, 7.81136, 2.87603, 0.113575 }, { 5.59463, 0.334393, 12.8288, 32.8761 }, 0.518275 }, { "Mn", { 11.2819, 7.35730, 3.01930, 2.24410 }, { 5.34090, 0.343200, 17.8674, 83.7543 }, 1.08960 }, { "Mn2+", { 10.8061, 7.36200, 3.52680, 0.218400 }, { 5.27960, 0.343500, 14.3430, 41.3235 }, 1.08740 }, { "Mn3+", { 9.84521, 7.87194, 3.56531, 0.323613 }, { 4.91797, 0.294393, 10.8171, 24.1281 }, 0.393974 }, { "Mn4+", { 9.96253, 7.97057, 2.76067, 0.054447 }, { 4.84850, 0.283303, 10.4852, 27.5730 }, 0.251877 }, { "Fe", { 11.7695, 7.35730, 3.52220, 2.30450 }, { 4.76110, 0.307200, 15.3535, 76.8805 }, 1.03690 }, { "Fe2+", { 11.0424, 7.37400, 4.13460, 0.439900 }, { 4.65380, 0.305300, 12.0546, 31.2809 }, 1.00970 }, { "Fe3+", { 11.1764, 7.38630, 3.39480, 0.072400 }, { 4.61470, 0.300500, 11.6729, 38.5566 }, 0.970700 }, { "Co", { 12.2841, 7.34090, 4.00340, 2.34880 }, { 4.27910, 0.278400, 13.5359, 71.1692 }, 1.01180 }, { "Co2+", { 11.2296, 7.38830, 4.73930, 0.710800 }, { 4.12310, 0.272600, 10.2443, 25.6466 }, 0.932400 }, { "Co3+", { 10.3380, 7.88173, 4.76795, 0.725591 }, { 3.90969, 0.238668, 8.35583, 18.3491 }, 0.286667 }, { "Ni", { 12.8376, 7.29200, 4.44380, 2.38000 }, { 3.87850, 0.256500, 12.1763, 66.3421 }, 1.03410 }, { "Ni2+", { 11.4166, 7.40050, 5.34420, 0.977300 }, { 3.67660, 0.244900, 8.87300, 22.1626 }, 0.861400 }, { "Ni3+", { 10.7806, 7.75868, 5.22746, 0.847114 }, { 3.54770, 0.223140, 7.64468, 16.9673 }, 0.386044 }, { "Cu", { 13.3380, 7.16760, 5.61580, 1.67350 }, { 3.58280, 0.247000, 11.3966, 64.8126 }, 1.19100 }, { "Cu1+", { 11.9475, 7.35730, 6.24550, 1.55780 }, { 3.36690, 0.227400, 8.66250, 25.8487 }, 0.89000 }, { "Cu2+", { 11.8168, 7.11181, 5.78135, 1.14523 }, { 3.37484, 0.244078, 7.98760, 19.8970 }, 1.14431 }, { "Zn", { 14.0743, 7.03180, 5.16520, 2.41000 }, { 3.26550, 0.233300, 10.3163, 58.7097 }, 1.30410 }, { "Zn2+", { 11.9719, 7.38620, 6.46680, 1.39400 }, { 2.99460, 0.203100, 7.08260, 18.0995 }, 0.780700 }, { "Ga", { 15.2354, 6.70060, 4.35910, 2.96230 }, { 3.06690, 0.241200, 10.7805, 61.4135 }, 1.71890 }, { "Ga3+", { 12.6920, 6.69883, 6.06692, 1.00660 }, { 2.81262, 0.227890, 6.36441, 14.4122 }, 1.53545 }, { "Ge", { 16.0816, 6.37470, 3.70680, 3.68300 }, { 2.85090, 0.251600, 11.4468, 54.7625 }, 2.13130 }, { "Ge4+", { 12.9172, 6.70003, 6.06791, 0.859041 }, { 2.53718, 0.205855, 5.47913, 11.6030 }, 1.45572 }, { "As", { 16.6723, 6.07010, 3.43130, 4.27790 }, { 2.63450, 0.264700, 12.9479, 47.7972 }, 2.53100 }, { "Se", { 17.0006, 5.81960, 3.97310, 4.35430 }, { 2.40980, 0.272600, 15.2372, 43.8163 }, 2.84090 }, { "Br", { 17.1789, 5.23580, 5.63770, 3.98510 }, { 2.17230, 16.5796, 0.260900, 41.4328 }, 2.95570 }, { "Br1-", { 17.1718, 6.33380, 5.57540, 3.72720 }, { 2.20590, 19.3345, 0.287100, 58.1535 }, 3.17760 }, { "Kr", { 17.3555, 6.72860, 5.54930, 3.53750 }, { 1.93840, 16.5623, 0.226100, 39.3972 }, 2.82500 }, { "Rb", { 17.1784, 9.64350, 5.13990, 1.52920 }, { 1.78880, 17.3151, 0.274800, 164.934 }, 3.48730 }, { "Rb1+", { 17.5816, 7.65980, 5.89810, 2.78170 }, { 1.71390, 14.7957, 0.160300, 31.2087 }, 2.07820 }, { "Sr", { 17.5663, 9.81840, 5.42200, 2.66940 }, { 1.55640, 14.0988, 0.166400, 132.376 }, 2.50640 }, { "Sr2+", { 18.0874, 8.13730, 2.56540, -34.193 }, { 1.49070, 12.6963, 24.5651, -0.01380 }, 41.4025 }, { "Y", { 17.7760, 10.2946, 5.72629, 3.26588 }, { 1.40290, 12.8006, 0.125599, 104.354 }, 1.91213 }, { "Y3+", { 17.9268, 9.15310, 1.76795, -33.108 }, { 1.35417, 11.2145, 22.6599, -0.01319 }, 40.2602 }, { "Zr", { 17.8765, 10.9480, 5.41732, 3.65721 }, { 1.27618, 11.9160, 0.117622, 87.6627 }, 2.06929 }, { "Zr4+", { 18.1668, 10.0562, 1.01118, -2.6479 }, { 1.21480, 10.1483, 21.6054, -0.10276 }, 9.41454 }, { "Nb", { 17.6142, 12.0144, 4.04183, 3.53346 }, { 1.18865, 11.7660, 0.204785, 69.7957 }, 3.75591 }, { "Nb3+", { 19.8812, 18.0653, 11.0177, 1.94715 }, { 0.019175, 1.13305, 10.1621, 28.3389 }, -12.912 }, { "Nb5+", { 17.9163, 13.3417, 10.7990, 0.337905 }, { 1.12446, 0.028781, 9.28206, 25.7228 }, -6.3934 }, { "Mo", { 3.70250, 17.2356, 12.8876, 3.74290 }, { 0.277200, 1.09580, 11.0040, 61.6584 }, 4.38750 }, { "Mo3+", { 21.1664, 18.2017, 11.7423, 2.30951 }, { 0.014734, 1.03031, 9.53659, 26.6307 }, -14.421 }, { "Mo5+", { 21.0149, 18.0992, 11.4632, 0.740625 }, { 0.014345, 1.02238, 8.78809, 23.3452 }, -14.316 }, { "Mo6+", { 17.8871, 11.1750, 6.57891, 0.000000 }, { 1.03649, 8.48061, 0.058881, 0.000000 }, 0.344941 }, { "Tc", { 19.1301, 11.0948, 4.64901, 2.71263 }, { 0.864132, 8.14487, 21.5707, 86.8472 }, 5.40428 }, { "Ru", { 19.2674, 12.9182, 4.86337, 1.56756 }, { 0.808520, 8.43467, 24.7997, 94.2928 }, 5.37874 }, { "Ru3+", { 18.5638, 13.2885, 9.32602, 3.00964 }, { 0.847329, 8.37164, 0.017662, 22.8870 }, -3.1892 }, { "Ru4+", { 18.5003, 13.1787, 4.71304, 2.18535 }, { 0.844582, 8.12534, 0.36495, 20.8504 }, 1.42357 }, { "Rh", { 19.2957, 14.3501, 4.73425, 1.28918 }, { 0.751536, 8.21758, 25.8749, 98.6062 }, 5.32800 }, { "Rh3+", { 18.8785, 14.1259, 3.32515, -6.1989 }, { 0.764252, 7.84438, 21.2487, -0.01036 }, 11.8678 }, { "Rh4+", { 18.8545, 13.9806, 2.53464, -5.6526 }, { 0.760825, 7.62436, 19.3317, -0.01020 }, 11.2835 }, { "Pd", { 19.3319, 15.5017, 5.29537, 0.605844 }, { 0.698655, 7.98929, 25.2052, 76.8986 }, 5.26593 }, { "Pd2+", { 19.1701, 15.2096, 4.32234, 0.000000 }, { 0.696219, 7.55573, 22.5057, 0.000000 }, 5.29160 }, { "Pd4+", { 19.2493, 14.7900, 2.89289, -7.9492 }, { 0.683839, 7.14833, 17.9144, 0.005127 }, 13.0174 }, { "Ag", { 19.2808, 16.6885, 4.80450, 1.04630 }, { 0.644600, 7.47260, 24.6605, 99.8156 }, 5.17900 }, { "Ag1+", { 19.1812, 15.9719, 5.27475, 0.357534 }, { 0.646179, 7.19123, 21.7326, 66.1147 }, 5.21572 }, { "Ag2+", { 19.1643, 16.2456, 4.37090, 0.000000 }, { 0.645643, 7.18544, 21.4072, 0.000000 }, 5.21404 }, { "Cd", { 19.2214, 17.6444, 4.46100, 1.60290 }, { 0.594600, 6.90890, 24.7008, 87.4825 }, 5.06940 }, { "Cd2+", { 19.1514, 17.2535, 4.47128, 0.000000 }, { 0.597922, 6.80639, 20.2521, 0.000000 }, 5.11937 }, { "In", { 19.1624, 18.5596, 4.29480, 2.03960 }, { 0.547600, 6.37760, 25.8499, 92.8029 }, 4.93910 }, { "In3+", { 19.1045, 18.1108, 3.78897, 0.000000 }, { 0.551522, 6.32470, 17.3595, 0.000000 }, 4.99635 }, { "Sn", { 19.1889, 19.1005, 4.45850, 2.46630 }, { 5.83030, 0.503100, 26.8909, 83.9571 }, 4.78210 }, { "Sn2+", { 19.1094, 19.0548, 4.56480, 0.487000 }, { 0.503600, 5.83780, 23.3752, 62.2061 }, 4.78610 }, { "Sn4+", { 18.9333, 19.7131, 3.41820, 0.019300 }, { 5.76400, 0.465500, 14.0049, -0.75830 }, 3.91820 }, { "Sb", { 19.6418, 19.0455, 5.03710, 2.68270 }, { 5.30340, 0.460700, 27.9074, 75.2825 }, 4.59090 }, { "Sb3+", { 18.9755, 18.9330, 5.10789, 0.288753 }, { 0.467196, 5.22126, 19.5902, 55.5113 }, 4.69626 }, { "Sb5+", { 19.8685, 19.0302, 2.41253, 0.000000 }, { 5.44853, 0.467973, 14.1259, 0.000000 }, 4.69263 }, { "Te", { 19.9644, 19.0138, 6.14487, 2.52390 }, { 4.81742, 0.420885, 28.5284, 70.8403 }, 4.35200 }, { "I", { 20.1472, 18.9949, 7.51380, 2.27350 }, { 4.34700, 0.381400, 27.7660, 66.8776 }, 4.07120 }, { "I1-", { 20.2332, 18.9970, 7.80690, 2.88680 }, { 4.35790, 0.381500, 29.5259, 84.9304 }, 4.07140 }, { "Xe", { 20.2933, 19.0298, 8.97670, 1.99000 }, { 3.92820, 0.344000, 26.4659, 64.2658 }, 3.71180 }, { "Cs", { 20.3892, 19.1062, 10.6620, 1.49530 }, { 3.56900, 0.310700, 24.3879, 213.904 }, 3.33520 }, { "Cs1+", { 20.3524, 19.1278, 10.2821, 0.961500 }, { 3.55200, 0.308600, 23.7128, 59.4565 }, 3.27910 }, { "Ba", { 20.3361, 19.2970, 10.8880, 2.69590 }, { 3.21600, 0.275600, 20.2073, 167.202 }, 2.77310 }, { "Ba2+", { 20.1807, 19.1136, 10.9054, 0.77634 }, { 3.21367, 0.283310, 20.0558, 51.7460 }, 3.02902 }, { "La", { 20.5780, 19.5990, 11.3727, 3.28719 }, { 2.94817, 0.244475, 18.7726, 133.124 }, 2.14678 }, { "La3+", { 20.2489, 19.3763, 11.6323, 0.336048 }, { 2.92070, 0.250698, 17.8211, 54.9453 }, 2.40860 }, { "Ce", { 21.1671, 19.7695, 11.8513, 3.33049 }, { 2.81219, 0.226836, 17.6083, 127.113 }, 1.86264 }, { "Ce3+", { 20.8036, 19.5590, 11.9369, 0.612376 }, { 2.77691, 0.231540, 16.5408, 43.1692 }, 2.09013 }, { "Ce4+", { 20.3235, 19.8186, 12.1233, 0.144583 }, { 2.65941, 0.218850, 15.7992, 62.2355 }, 1.59180 }, { "Pr", { 22.0440, 19.6697, 12.3856, 2.82428 }, { 2.77393, 0.222087, 16.7669, 143.644 }, 2.05830 }, { "Pr3+", { 21.3727, 19.7491, 12.1329, 0.975180 }, { 2.64520, 0.214299, 15.3230, 36.4065 }, 1.77132 }, { "Pr4+", { 20.9413, 20.0539, 12.4668, 0.296689 }, { 2.54467, 0.202481, 14.8137, 45.4643 }, 1.24285 }, { "Nd", { 22.6845, 19.6847, 12.7740, 2.85137 }, { 2.66248, 0.210628, 15.8850, 137.903 }, 1.98486 }, { "Nd3+", { 21.9610, 19.9339, 12.1200, 1.51031 }, { 2.52722, 0.199237, 14.1783, 30.8717 }, 1.47588 }, { "Pm", { 23.3405, 19.6095, 13.1235, 2.87516 }, { 2.56270, 0.202088, 15.1009, 132.721 }, 2.02876 }, { "Pm3+", { 22.5527, 20.1108, 12.0671, 2.07492 }, { 2.41740, 0.185769, 13.1275, 27.4491 }, 1.19499 }, { "Sm", { 24.0042, 19.4258, 13.4396, 2.89604 }, { 2.47274, 0.196451, 14.3996, 128.007 }, 2.20963 }, { "Sm3+", { 23.1504, 20.2599, 11.9202, 2.71488 }, { 2.31641, 0.174081, 12.1571, 24.8242 }, 0.954586 }, { "Eu", { 24.6274, 19.0886, 13.7603, 2.92270 }, { 2.38790, 0.194200, 13.7546, 123.174 }, 2.57450 }, { "Eu2+", { 24.0063, 19.9504, 11.8034, 3.87243 }, { 2.27783, 0.173530, 11.6096, 26.5156 }, 1.36389 }, { "Eu3+", { 23.7497, 20.3745, 11.8509, 3.26503 }, { 2.22258, 0.163940, 11.3110, 22.9966 }, 0.759344 }, { "Gd", { 25.0709, 19.0798, 13.8518, 3.54545 }, { 2.25341, 0.181951, 12.9331, 101.398 }, 2.41960 }, { "Gd3+", { 24.3466, 20.4208, 11.8708, 3.71490 }, { 2.13553, 0.155525, 10.5782, 21.7029 }, 0.645089 }, { "Tb", { 25.8976, 18.2185, 14.3167, 2.95354 }, { 2.24256, 0.196143, 12.6648, 115.362 }, 3.58324 }, { "Tb3+", { 24.9559, 20.3271, 12.2471, 3.77300 }, { 2.05601, 0.149525, 10.0499, 21.2773 }, 0.691967 }, { "Dy", { 26.5070, 17.6383, 14.5596, 2.96577 }, { 2.18020, 0.202172, 12.1899, 111.874 }, 4.29728 }, { "Dy3+", { 25.5395, 20.2861, 11.9812, 4.50073 }, { 1.98040, 0.143384, 9.34972, 19.5810 }, 0.689690 }, { "Ho", { 26.9049, 17.2940, 14.5583, 3.63837 }, { 2.07051, 0.197940, 11.4407, 92.6566 }, 4.56796 }, { "Ho3+", { 26.1296, 20.0994, 11.9788, 4.93676 }, { 1.91072, 0.139358, 8.80018, 18.5908 }, 0.852795 }, { "Er", { 27.6563, 16.4285, 14.9779, 2.98233 }, { 2.07356, 0.223545, 11.3604, 105.703 }, 5.92046 }, { "Er3+", { 26.7220, 19.7748, 12.1506, 5.17379 }, { 1.84659, 0.137290, 8.36225, 17.8974 }, 1.17613 }, { "Tm", { 28.1819, 15.8851, 15.1542, 2.98706 }, { 2.02859, 0.238849, 10.9975, 102.961 }, 6.75621 }, { "Tm3+", { 27.3083, 19.3320, 12.3339, 5.38348 }, { 1.78711, 0.136974, 7.96778, 17.2922 }, 1.63929 }, { "Yb", { 28.6641, 15.4345, 15.3087, 2.98963 }, { 1.98890, 0.257119, 10.6647, 100.417 }, 7.56672 }, { "Yb2+", { 28.1209, 17.6817, 13.3335, 5.14657 }, { 1.78503, 0.159970, 8.18304, 20.3900 }, 3.70983 }, { "Yb3+", { 27.8917, 18.7614, 12.6072, 5.47647 }, { 1.73272, 0.138790, 7.64412, 16.8153 }, 2.26001 }, { "Lu", { 28.9476, 15.2208, 15.1000, 3.71601 }, { 1.90182, 9.98519, 0.261033, 84.3298 }, 7.97628 }, { "Lu3+", { 28.4628, 18.1210, 12.8429, 5.59415 }, { 1.68216, 0.142292, 7.33727, 16.3535 }, 2.97573 }, { "Hf", { 29.1440, 15.1726, 14.7586, 4.30013 }, { 1.83262, 9.59990, 0.275116, 72.0290 }, 8.58154 }, { "Hf4+", { 28.8131, 18.4601, 12.7285, 5.59927 }, { 1.59136, 0.128903, 6.76232, 14.0366 }, 2.39699 }, { "Ta", { 29.2024, 15.2293, 14.5135, 4.76492 }, { 1.77333, 9.37046, 0.295977, 63.3644 }, 9.24354 }, { "Ta5+", { 29.1587, 18.8407, 12.8268, 5.38695 }, { 1.50711, 0.116741, 6.31524, 12.4244 }, 1.78555 }, { "W", { 29.0818, 15.4300, 14.4327, 5.11982 }, { 1.72029, 9.22590, 0.321703, 57.0560 }, 9.88750 }, { "W6+", { 29.4936, 19.3763, 13.0544, 5.06412 }, { 1.42755, 0.104621, 5.93667, 11.1972 }, 1.01074 }, { "Re", { 28.7621, 15.7189, 14.5564, 5.44174 }, { 1.67191, 9.09227, 0.350500, 52.0861 }, 10.4720 }, { "Os", { 28.1894, 16.1550, 14.9305, 5.67589 }, { 1.62903, 8.97948, 0.382661, 48.1647 }, 11.0005 }, { "Os4+", { 30.4190, 15.2637, 14.7458, 5.06795 }, { 1.37113, 6.84706, 0.165191, 18.0030 }, 6.49804 }, { "Ir", { 27.3049, 16.7296, 15.6115, 5.83377 }, { 1.59279, 8.86553, 0.417916, 45.0011 }, 11.4722 }, { "Ir3+", { 30.4156, 15.8620, 13.6145, 5.82008 }, { 1.34323, 7.10909, 0.204633, 20.3254 }, 8.27903 }, { "Ir4+", { 30.7058, 15.5512, 14.2326, 5.53672 }, { 1.30923, 6.71983, 0.167252, 17.4911 }, 6.96824 }, { "Pt", { 27.0059, 17.7639, 15.7131, 5.78370 }, { 1.51293, 8.81174, 0.424593, 38.6103 }, 11.6883 }, { "Pt2+", { 29.8429, 16.7224, 13.2153, 6.35234 }, { 1.32927, 7.38979, 0.263297, 22.9426 }, 9.85329 }, { "Pt4+", { 30.9612, 15.9829, 13.7348, 5.92034 }, { 1.24813, 6.60834, 0.168640, 16.9392 }, 7.39534 }, { "Au", { 16.8819, 18.5913, 25.5582, 5.86000 }, { 0.461100, 8.62160, 1.48260, 36.3956 }, 12.0658 }, { "Au1+", { 28.0109, 17.8204, 14.3359, 6.58077 }, { 1.35321, 7.73950, 0.356752, 26.4043 }, 11.2299 }, { "Au3+", { 30.6886, 16.9029, 12.7801, 6.52354 }, { 1.21990, 6.82872, 0.212867, 18.6590 }, 9.09680 }, { "Hg", { 20.6809, 19.0417, 21.6575, 5.96760 }, { 0.545000, 8.44840, 1.57290, 38.3246 }, 12.6089 }, { "Hg1+", { 25.0853, 18.4973, 16.8883, 6.48216 }, { 1.39507, 7.65105, 0.443378, 28.2262 }, 12.0205 }, { "Hg2+", { 29.5641, 18.0600, 12.8374, 6.89912 }, { 1.21152, 7.05639, 0.284738, 20.7482 }, 10.6268 }, { "Tl", { 27.5446, 19.1584, 15.5380, 5.52593 }, { 0.655150, 8.70751, 1.96347, 45.8149 }, 13.1746 }, { "Tl1+", { 21.3985, 20.4723, 18.7478, 6.82847 }, { 1.47110, 0.517394, 7.43463, 28.8482 }, 12.5258 }, { "Tl3+", { 30.8695, 18.3841, 11.9328, 7.00574 }, { 1.10080, 6.53852, 0.219074, 17.2114 }, 9.80270 }, /* IT Vol IV 1974: a2 = 18.3841 IT Vol C 1992: a2 = 18.3481 */ { "Pb", { 31.0617, 13.0637, 18.4420, 5.96960 }, { 0.690200, 2.35760, 8.61800, 47.2579 }, 13.4118 }, { "Pb2+", { 21.7886, 19.5682, 19.1406, 7.01107 }, { 1.33660, 0.488383, 6.77270, 23.8132 }, 12.4734 }, { "Pb4+", { 32.1244, 18.8003, 12.0175, 6.96886 }, { 1.00566, 6.10926, 0.147041, 14.7140 }, 8.08428 }, { "Bi", { 33.3689, 12.9510, 16.5877, 6.46920 }, { 0.704000, 2.92380, 8.79370, 48.0093 }, 13.5782 }, { "Bi3+", { 21.8053, 19.5026, 19.1053, 7.10295 }, { 1.23560, 6.24149, 0.469999, 20.3185 }, 12.4711 }, { "Bi5+", { 33.5364, 25.0946, 19.2497, 6.91555 }, { 0.916540, 0.39042, 5.71414, 12.8285 }, -6.7994 }, { "Po", { 34.6726, 15.4733, 13.1138, 7.02588 }, { 0.700999, 3.55078, 9.55642, 47.0045 }, 13.6770 }, { "At", { 35.3163, 19.0211, 9.49887, 7.42518 }, { 0.685870, 3.97458, 11.3824, 45.4715 }, 13.7108 }, { "Rn", { 35.5631, 21.2816, 8.00370, 7.44330 }, { 0.663100, 4.06910, 14.0422, 44.2473 }, 13.6905 }, { "Fr", { 35.9299, 23.0547, 12.1439, 2.11253 }, { 0.646453, 4.17619, 23.1052, 150.645 }, 13.7247 }, { "Ra", { 35.7630, 22.9064, 12.4739, 3.21097 }, { 0.616341, 3.87135, 19.9887, 142.325 }, 13.6211 }, { "Ra2+", { 35.2150, 21.6700, 7.91342, 7.65078 }, { 0.604909, 3.57670, 12.6010, 29.8436 }, 13.5431 }, { "Ac", { 35.6597, 23.1032, 12.5977, 4.08655 }, { 0.589092, 3.65155, 18.5990, 117.020 }, 13.5266 }, { "Ac3+", { 35.1736, 22.1112, 8.19216, 7.05545 }, { 0.579689, 3.41437, 12.9187, 25.9443 }, 13.4637 }, { "Th", { 35.5645, 23.4219, 12.7473, 4.80703 }, { 0.563359, 3.46204, 17.8309, 99.1722 }, 13.4314 }, { "Th4+", { 35.1007, 22.4418, 9.78554, 5.29444 }, { 0.555054, 3.24498, 13.4661, 23.9533 }, 13.3760 }, { "Pa", { 35.8847, 23.2948, 14.1891, 4.17287 }, { 0.547751, 3.41519, 16.9235, 105.251 }, 13.4287 }, { "U", { 36.0228, 23.4128, 14.9491, 4.18800 }, { 0.529300, 3.32530, 16.0927, 100.613 }, 13.3966 }, { "U3+", { 35.5747, 22.5259, 12.2165, 5.37073 }, { 0.520480, 3.12293, 12.7148, 26.3394 }, 13.3092 }, { "U4+", { 35.3715, 22.5326, 12.0291, 4.79840 }, { 0.516598, 3.05053, 12.5723, 23.4582 }, 13.2671 }, { "U6+", { 34.8509, 22.7584, 14.0099, 1.21457 }, { 0.507079, 2.89030, 13.1767, 25.2017 }, 13.1665 }, { "Np", { 36.1874, 23.5964, 15.6402, 4.18550 }, { 0.511929, 3.25396, 15.3622, 97.4908 }, 13.3573 }, { "Np3+", { 35.7074, 22.6130, 12.9898, 5.43227 }, { 0.502322, 3.03807, 12.1449, 25.4928 }, 13.2544 }, { "Np4+", { 35.5103, 22.5787, 12.7766, 4.92159 }, { 0.498626, 2.96627, 11.9484, 22.7502 }, 13.2116 }, { "Np6+", { 35.0136, 22.7286, 14.3884, 1.75669 }, { 0.489810, 2.81099, 12.3300, 22.6581 }, 13.1130 }, { "Pu", { 36.5254, 23.8083, 16.7707, 3.47947 }, { 0.499384, 3.26371, 14.9455, 105.980 }, 13.3812 }, { "Pu3+", { 35.8400, 22.7169, 13.5807, 5.66016 }, { 0.484938, 2.96118, 11.5331, 24.3992 }, 13.1991 }, { "Pu4+", { 35.6493, 22.6460, 13.3595, 5.18831 }, { 0.481422, 2.89020, 11.3160, 21.8301 }, 13.1555 }, { "Pu6+", { 35.1736, 22.7181, 14.7635, 2.28678 }, { 0.473204, 2.73848, 11.5530, 20.9303 }, 13.0582 }, { "Am", { 36.6706, 24.0992, 17.3415, 3.49331 }, { 0.483629, 3.20647, 14.3136, 102.273 }, 13.3592 }, { "Cm", { 36.6488, 24.4096, 17.3990, 4.21665 }, { 0.465154, 3.08997, 13.4346, 88.4834 }, 13.2887 }, { "Bk", { 36.7881, 24.7736, 17.8919, 4.23284 }, { 0.451018, 3.04619, 12.8946, 86.0030 }, 13.2754 }, { "Cf", { 36.9185, 25.1995, 18.3317, 4.24391 }, { 0.437533, 3.00775, 12.4044, 83.7881 }, 13.2674 }, /* { "Es", { 0., 0., 0., 0. }, { 0., 0., 0., 0. }, 0. }, { "Fm", { 0., 0., 0., 0. }, { 0., 0., 0., 0. }, 0. }, { "Md", { 0., 0., 0., 0. }, { 0., 0., 0., 0. }, 0. }, { "No", { 0., 0., 0., 0. }, { 0., 0., 0., 0. }, 0. }, { "Lr", { 0., 0., 0., 0. }, { 0., 0., 0., 0. }, 0. }, */ { NULL, { 0., 0., 0., 0. }, { 0., 0., 0., 0. }, 0. } }; /* Changes (in place) case of letters to match symbols in tables (i.e. to Abc), * replaces +/- (if doesn't follow a digit) with 1+/1-, * strips junk from the end. * Returns number of initial alpha characters. * `buf' should have one more character allocated after the string, * in case + is changed to 1+. */ int fix_label(char *buf) { int i; if (buf == NULL || *buf == '\0') return 0; buf[0] = toupper(buf[0]); for (i = 1; isalpha(buf[i]); i++) buf[i] = tolower(buf[i]); if (buf[i] == '+' || buf[i] == '-') { buf[i+1] = buf[i]; buf[i] = '1'; buf[i+2] = '\0'; } else if (isdigit(buf[i]) && (buf[i+1] == '+' || buf[i+1] == '-')) buf[i+2] = '\0'; else buf[i] = '\0'; return i; } const t_it92_coeff *find_in_it92(const char *label) { size_t alpha_len; char buf[16]; const t_it92_coeff *p; strncpy(buf, label, 14); alpha_len = fix_label(buf); for (p = it92_table; p->symbol != NULL; p++) if (strcmp(buf, p->symbol) == 0) return p; /* try again, comparing only alpha characters */ if (alpha_len != strlen(buf)) for (p = it92_table; p->symbol != NULL; p++) if (strncmp(buf, p->symbol, alpha_len) == 0) return p; return NULL; } double calculate_it92_factor(const t_it92_coeff *p, double stol2) { int i; double sf = p->c; for (i = 0; i < 4; i++) sf += p->a[i] * exp(-p->b[i] * stol2); return sf; } /***************************************************************************/ const t_nn92_record nn92_table[] = { {"H", -3.7390,0, 0.3326}, {"D", 6.671, 0, 0.000519}, {"He", 3.26, 0, 0.00747}, {"Li", -1.90, 0, 70.5}, {"Be", 7.79, 0, 0.0076}, {"B", 5.30, -0.213, 767.}, {"C", 6.6460, 0, 0.0035}, {"N", 9.36, 0, 1.9}, {"O", 5.803, 0, 0.00019}, {"F", 5.654, 0, 0.0096}, {"Ne", 4.566, 0, 0.039}, {"Na", 3.63, 0, 0.53}, {"Mg", 5.375, 0, 0.063}, {"Al", 3.449, 0, 0.231}, {"Si", 4.1491, 0, 0.171}, {"P", 5.13, 0, 0.172}, {"S", 2.847, 0, 0.53}, {"Cl", 9.5770, 0, 33.5}, {"Ar", 1.909, 0, 0.675}, {"K", 3.67, 0, 2.1}, {"Ca", 4.70, 0, 0.43}, {"Sc", 12.29, 0, 27.5}, {"Ti", -3.438, 0, 6.09}, {"V", -0.3824,0, 5.08}, {"Cr", 3.635, 0, 3.05}, {"Mn", -3.73, 0, 13.3}, {"Fe", 9.45, 0, 2.56}, {"Co", 2.49, 0, 37.18}, {"Ni", 10.3, 0, 4.49}, {"Cu", 7.718, 0, 3.78}, {"Zn", 5.680, 0, 1.11}, {"Ga", 7.288, 0, 2.75}, {"Ge", 8.185, 0, 2.2}, {"As", 6.58, 0, 4.5}, {"Se", 7.970, 0, 11.7}, {"Br", 6.795, 0, 6.9}, {"Kr", 7.81, 0, 25.}, {"Rb", 7.09, 0, 0.38}, {"Sr", 7.02, 0, 1.28}, {"Y", 7.75, 0, 1.28}, {"Zr", 7.16, 0, 0.185}, {"Nb", 7.054, 0, 1.15}, {"Mo", 6.715, 0, 2.48}, {"Tc", 6.8, 0, 20.}, {"Ru", 7.03, 0, 2.56}, {"Rh", 5.88, 0, 144.8}, {"Pd", 5.91, 0, 6.9}, {"Ag", 5.922, 0, 63.3}, {"Cd", 4.87, -0.70, 2520.}, {"In", 4.065, -0.0539,193.8}, {"Sn", 6.225, 0, 0.626}, {"Sb", 5.57, 0, 4.91}, {"Te", 5.80, 0, 4.7}, {"I", 5.28, 0, 6.15}, {"Xe", 4.92, 0, 23.9}, {"Cs", 5.42, 0, 29.0}, {"Ba", 5.07, 0, 1.1}, {"La", 8.24, 0, 8.97}, {"Ce", 4.84, 0, 0.63}, {"Pr", 4.58, 0, 11.5}, {"Nd", 7.69, 0, 50.5}, {"Pm", 12.6, 0, 168.4}, {"Sm", 0.80, -1.65, 5922.}, {"Eu", 7.22, -1.26, 4530.}, {"Gd", 6.5, -13.82, 49700.}, {"Tb", 7.38, 0, 23.4}, {"Dy", 16.9, -0.276, 994.}, {"Ho", 8.01, 0, 64.7}, {"Er", 7.79, 0, 159.}, {"Tm", 7.07, 0, 100.}, {"Yb", 12.43, 0, 34.8}, {"Lu", 7.21, 0, 74.}, {"Hf", 7.7, 0, 104.1}, {"Ta", 6.91, 0, 20.6}, {"W", 4.86, 0, 18.3}, {"Re", 9.2, 0, 89.7}, {"Os", 10.7, 0, 16}, {"Ir", 10.6, 0, 425.}, {"Pt", 9.60, 0, 10.3}, {"Au", 7.63, 0, 98.65}, {"Hg", 12.692, 0, 372.3}, {"Tl", 8.776, 0, 3.43}, {"Pb", 9.405, 0, 0.171}, {"Bi", 8.532, 0, 0.0338}, {"Th", 10.31, 0, 7.37}, {"U", 8.417, 0, 7.57}, {NULL, 0, 0, 0} }; const t_nn92_record *find_in_nn92(const char *label) { const t_nn92_record *it; char buf[3] = { 0, 0, 0 }; /* empty label */ if (label == NULL || *label == '\0') return NULL; buf[0] = toupper(label[0]); if (strlen(label) > 1 && isalpha(label[1])) buf[1] = tolower(label[1]); for (it = nn92_table; it->symbol != NULL; it++) if (strcmp(it->symbol, buf) == 0) return it; return NULL; } fityk-1.3.1/wxgui/atomtables.h000066400000000000000000000064251302634723100163210ustar00rootroot00000000000000/* debyer -- program for calculation of diffration patterns * Copyright 2009 Marcin Wojdyr * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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. * * $Id$ * * Functions for access to the following data: * - periodic system of elements * - x-ray scattering factors (based on IT92 data) * - neutron scattering lengths and cross sections (NN92) * * The data in tables is taken from sources cited below. */ #ifndef DEBYER_ATOMTABLES_H_ #define DEBYER_ATOMTABLES_H_ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* element of periodic system of elements */ typedef struct { int Z; // atomic number const char* symbol; const char* name; float mass; } t_pse; /* Finds element with the symbol that matches `label' in periodic table. * Match is case insensitive. Trailing non-alpha characters in label are * ignored. * Returns NULL if not found. */ const t_pse *find_in_pse(const char *label); /* Finds element with atomic number Z. Returns NULL if not found. */ const t_pse *find_Z_in_pse(int Z); /* Coefficients for approximation to the scattering factor called IT92. * AFAIR the data was taken from ObjCryst. It can be also found * in cctbx and in old atominfo program, and originaly comes from the paper * publication cited below. */ /* International Tables for Crystallography Volume C Mathematical, Physical and Chemical Tables Edited by A.J.C. Wilson Kluwer Academic Publishers Dordrecht/Boston/London 1992 Table 6.1.1.4 (pp. 500-502) Coefficients for analytical approximation to the scattering factors of Tables 6.1.1.1 and 6.1.1.3 [ Table 6.1.1.4 is a reprint of Table 2.2B, pp. 99-101, International Tables for X-ray Crystallography, Volume IV, The Kynoch Press: Birmingham, England, 1974. There is just one difference, see "Tl3+". ] */ typedef struct { const char* symbol; float a[4], b[4], c; } t_it92_coeff; /* Finds record in IT92 table with the symbol that matches `label'. */ const t_it92_coeff *find_in_it92(const char *label); /* Calculate scattering factor using coefficients p. * stol2 = (sin(theta)/lambda)^2 */ double calculate_it92_factor(const t_it92_coeff *p, double stol2); /* Neutron bound scattering lengths & cross-section Data from: http://www.ncnr.nist.gov/resources/n-lengths/list.html All of this data was taken from the Special Feature section of neutron scattering lengths and cross sections of the elements and their isotopes in Neutron News, Vol. 3, No. 3, 1992, pp. 29-37. */ typedef struct { const char *symbol; float bond_coh_scatt_length; float bond_coh_scatt_length_imag; float abs_cross_sect; /* for 2200 m/s neutrons*/ } t_nn92_record; const t_nn92_record *find_in_nn92(const char *label); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* DEBYER_ATOMTABLES_H_ */ fityk-1.3.1/wxgui/bgm.cpp000066400000000000000000000213271302634723100152640ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // BgManager - background (baseline) manager. Used for manual, interactive // background setting. #include #include "bgm.h" #include "frame.h" #include "plot.h" #include "fityk/logic.h" #include "fityk/data.h" #include "fityk/func.h" using namespace std; using fityk::PointQ; using fityk::PointD; using fityk::ModelManager; BgManager::BgManager(const Scale& x_scale) : x_scale_(x_scale), spline_(true), data_idx_(-1) { read_recent_baselines(); } BgManager::~BgManager() { write_recent_baselines(); } void BgManager::update_focused_data(int idx) { if (data_idx_ == idx) return; define_bg_func(); data_idx_ = idx; bg_from_func(); frame->update_toolbar(); } string BgManager::get_bg_name() const { return "bg" + S(data_idx_); } void BgManager::set_stripped(bool value) { stripped_.resize(ftk->dk.count()); stripped_[data_idx_] = value; } bool BgManager::stripped() const { return is_index(data_idx_, stripped_) && stripped_[data_idx_]; } const wxString& BgManager::get_recent_bg_name(int n) const { static const wxString empty; int idx = recent_bg_.size() - 1 - n; return (is_index(idx, recent_bg_) ? recent_bg_[idx].first : empty); } void BgManager::bg_from_func() { if (data_idx_ == -1 || stripped()) { bg_.clear(); return; } string name = get_bg_name(); int nr = ftk->mgr.find_function_nr(name); if (nr == -1) { bg_.clear(); return; } const fityk::Function *f = ftk->mgr.get_function(nr); if (f->tp()->name != "Spline" && f->tp()->name != "Polyline") { bg_.clear(); return; } int len = f->nv() / 2; bg_.resize(len); for (int i = 0; i < len; ++i) { bg_[i].x = f->av()[2*i]; bg_[i].y = f->av()[2*i+1]; } } void BgManager::add_background_point(double x, double y) { if (bg_.empty() && ftk->mgr.find_function_nr(get_bg_name()) >= 0) { int r = wxMessageBox(wxT("Function %") + s2wx(get_bg_name()) + wxT(" already exists\n") wxT("and your actions may overwrite it.\n") wxT("Continue?"), wxT("Start a new background?"), wxICON_QUESTION|wxYES_NO); if (r != wxYES) return; set_stripped(false); frame->update_toolbar(); } rm_background_point(x); PointQ t(x, y); vector::iterator l = lower_bound(bg_.begin(), bg_.end(), t); bg_.insert (l, t); } void BgManager::rm_background_point (double x) { int X = x_scale_.px(x); double lower = x_scale_.val(X - min_dist); double upper = x_scale_.val(X + min_dist); if (lower > upper) swap(lower, upper); vector::iterator l = lower_bound(bg_.begin(), bg_.end(), PointQ(lower, 0)); vector::iterator u = upper_bound(bg_.begin(), bg_.end(), PointQ(upper, 0)); if (u > l) bg_.erase(l, u); } void BgManager::clear_background() { bg_.clear(); string name = get_bg_name(); int nr = ftk->mgr.find_function_nr(name); if (nr != -1) exec("delete %" + name); } void BgManager::define_bg_func() { if (bg_.empty()) return; string name = get_bg_name(); string ftype = (spline_ ? "Spline" : "Polyline"); // if the function already exists and if it's exactly the same, return int nr = ftk->mgr.find_function_nr(name); if (nr != -1) { const fityk::Function *f = ftk->mgr.get_function(nr); if (f->tp()->name == ftype && f->nv() == 2 * (int) bg_.size()) { bool the_same = true; for (size_t i = 0; i != bg_.size(); ++i) { const fityk::Variable *vx = ftk->mgr.find_variable(f->used_vars().get_name(2*i)); const fityk::Variable *vy = ftk->mgr.find_variable(f->used_vars().get_name(2*i+1)); if (!ModelManager::is_auto(vx->name) || !vx->is_constant() || S(vx->value()) != S(bg_[i].x) || !ModelManager::is_auto(vy->name) || !vy->is_constant() || S(vy->value()) != S(bg_[i].y)) { the_same = false; break; } } if (the_same) return; } } string cmd = "%" + name + " = " + ftype + "("; v_foreach (PointQ, i, bg_) cmd += S(i->x) + "," + S(i->y) + (i+1 == bg_.end() ? ")" : ", "); exec(cmd); } void BgManager::strip_background() { if (bg_.empty()) return; wxString name = wxDateTime::Now().Format("%Y-%m-%d %H:%M:%S"); name += wxString::Format(wxT(" (%d points)"), (int) bg_.size()); recent_bg_.push_back(make_pair(name, bg_)); define_bg_func(); bg_.clear(); set_stripped(true); exec(frame->get_datasets() + "Y = y - %" + get_bg_name() + "(x)"); } void BgManager::add_background() { string name = get_bg_name(); int nr = ftk->mgr.find_function_nr(name); if (nr == -1) return; set_stripped(false); bg_from_func(); exec(frame->get_datasets() + "Y = y + %" + name + "(x)"); } vector BgManager::calculate_bgline(int window_width, const Scale& y_scale) { vector bgline(window_width); if (spline_) prepare_spline_interpolation(bg_); for (int i = 0; i < window_width; i++) { double x = x_scale_.val(i); double y = spline_ ? get_spline_interpolation(bg_, x) : get_linear_interpolation(bg_, x); bgline[i] = y_scale.px_d(y); } return bgline; } void BgManager::set_as_recent(int n) { int idx = recent_bg_.size() - 1 - n; if (!is_index(idx, recent_bg_)) return; bg_ = recent_bg_[idx].second; } void BgManager::set_as_convex_hull() { fityk::SimplePolylineConvex convex; const fityk::Data* data = ftk->dk.data(data_idx_); for (int i = 0; i < data->get_n(); ++i) convex.push_point(data->get_x(i), data->get_y(i)); const vector& vertices = convex.get_vertices(); bg_.resize(vertices.size()); for (size_t i = 0; i != bg_.size(); ++i) { bg_[i].x = vertices[i].x; bg_[i].y = vertices[i].y; } } bool BgManager::has_fn() const { string name = get_bg_name(); return ftk->mgr.find_function_nr(name) != -1; } void BgManager::write_recent_baselines() { wxConfigBase *c = wxConfig::Get(); if (!c) return; wxString t = wxT("/RecentBaselines"); if (c->HasGroup(t)) c->DeleteGroup(t); int len = recent_bg_.size(); int start = max(len-10, 0); for (int i = start; i < len; ++i) { wxString group = t + wxString::Format(wxT("/%d"), i-start); c->Write(group + wxT("/Name"), recent_bg_[i].first); wxString points; for (size_t j = 0; j != recent_bg_[i].second.size(); ++j) { const PointQ& p = recent_bg_[i].second[j]; points += wxString::Format(wxT("%g %g "), p.x, p.y); } c->Write(group + wxT("/Points"), points); } } void BgManager::read_recent_baselines() { recent_bg_.clear(); wxConfigBase *c = wxConfig::Get(); wxString t = wxT("/RecentBaselines"); if (!c || !c->HasGroup(t)) return; for (int i = 0; i < 10; i++) { wxString group = t + wxString::Format(wxT("/%d"), i); if (c->HasEntry(group + wxT("/Name"))) { wxString name = c->Read(group + wxT("/Name"), wxT("?")); wxString points = c->Read(group + wxT("/Points"), wxT("")); vector pp = split_string(wx2s(points), ' '); vector q; for (size_t j = 0; j < pp.size() / 2; ++j) { double x = strtod(pp[2*j].c_str(), NULL); double y = strtod(pp[2*j+1].c_str(), NULL); q.push_back(PointQ(x, y)); } recent_bg_.push_back(make_pair(name, q)); } } } void BgManager::set_bg_subtracted(const string& index_list, bool value) { stripped_.resize(ftk->dk.count()); const char* str = index_list.c_str(); while (*str != '\0') { char *endptr; int n = strtol(str, &endptr, 10); if (str == endptr) break; if (is_index(n, stripped_) && ftk->mgr.find_function_nr("bg"+S(n)) != -1) { stripped_[n] = value; } str = endptr; } } string BgManager::get_bg_subtracted() const { string r; for (size_t i = 0; i != stripped_.size(); ++i) if (stripped_[i]) r += " " + S(i); return r; } fityk-1.3.1/wxgui/bgm.h000066400000000000000000000033161302634723100147270ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_BGM_H_ #define FITYK_WX_BGM_H_ #include "fityk/numfuncs.h" // PointQ definition class Scale; class BgManager { public: //minimal distance in X between bg points static const int min_dist = 8; BgManager(const Scale& x_scale); ~BgManager(); void update_focused_data(int idx); void add_background_point(double x, double y); void rm_background_point(double x); void clear_background(); void strip_background(); // reverses strip_background(), unless %bgX was changed in the meantime void add_background(); void define_bg_func(); void bg_from_func(); bool can_strip() const { return !bg_.empty(); } bool has_fn() const; void set_spline_bg(bool s) { spline_ = s; } void set_as_recent(int n); void set_as_convex_hull(); std::vector calculate_bgline(int window_width, const Scale& y_scale); const std::vector& get_bg() const { return bg_; } bool stripped() const; const wxString& get_recent_bg_name(int n) const; void read_recent_baselines(); void write_recent_baselines(); // handle "ui bg_subtracted_from = index_list" void set_bg_subtracted(const std::string& index_list, bool value); std::string get_bg_subtracted() const; private: const Scale& x_scale_; bool spline_; std::vector bg_; std::vector > > recent_bg_; std::vector stripped_; int data_idx_; std::string get_bg_name() const; void set_stripped(bool value); }; #endif fityk-1.3.1/wxgui/ceria.cpp000066400000000000000000000602411302634723100156000ustar00rootroot00000000000000// Author: Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include "ceria.h" #ifdef _MSC_VER #define _USE_MATH_DEFINES #endif #include #include #include #include #include #include using namespace std; static Pos apply_seitz(Pos const& p0, SeitzMatrix const& s) { Pos p; p.x = s.R[0]*p0.x + s.R[1]*p0.y + s.R[2]*p0.z + s.T[0]/12.; p.y = s.R[3]*p0.x + s.R[4]*p0.y + s.R[5]*p0.z + s.T[1]/12.; p.z = s.R[6]*p0.x + s.R[7]*p0.y + s.R[8]*p0.z + s.T[2]/12.; return p; } string fullHM(const SpaceGroupSetting *sgs) { if (sgs == NULL) return ""; else if (sgs->ext == 0) return sgs->HM; else return string(sgs->HM) + ":" + sgs->ext; } static bool check_symmetric_hkl(const SgOps &sg_ops, const Miller &p1, const Miller &p2) { for (size_t i = 0; i < sg_ops.seitz.size(); ++i) { const int* R = sg_ops.seitz[i].R; int h = R[0] * p1.h + R[3] * p1.k + R[6] * p1.l; int k = R[1] * p1.h + R[4] * p1.k + R[7] * p1.l; int l = R[2] * p1.h + R[5] * p1.k + R[8] * p1.l; if (h == p2.h && k == p2.k && l == p2.l) return true; // we assume Friedel symmetry here if (h == -p2.h && k == -p2.k && l == -p2.l) return true; } return false; } static bool is_position_empty(const vector& pp, const Pos& p) { const double eps = 0.01; for (vector::const_iterator j = pp.begin(); j != pp.end(); ++j) { if ((fabs(p.x - j->x) < eps || fabs(p.x - j->x) > 1 - eps) && (fabs(p.y - j->y) < eps || fabs(p.y - j->y) > 1 - eps) && (fabs(p.z - j->z) < eps || fabs(p.z - j->z) > 1 - eps)) return false; } return true; } static double mod1(double x) { return x - floor(x); } void add_symmetric_images(Atom& a, const SgOps& sg_ops) { assert(a.pos.size() == 1); // iterate over translation, Seitz matrices and inversion for (size_t nt = 0; nt != sg_ops.tr.size(); ++nt) { const TransVec& t = sg_ops.tr[nt]; for (size_t ns = 0; ns != sg_ops.seitz.size(); ++ns) { Pos ps = apply_seitz(a.pos[0], sg_ops.seitz[ns]); Pos p = { mod1(ps.x + t.x/12.), mod1(ps.y + t.y/12.), mod1(ps.z + t.z/12.) }; if (is_position_empty(a.pos, p)) { a.pos.push_back(p); } if (sg_ops.inv) { Pos p2 = { mod1(-ps.x + t.x/12.), mod1(-ps.y + t.y/12.), mod1(-ps.z + t.z/12.) }; if (is_position_empty(a.pos, p2)) { a.pos.push_back(p2); } } } } } int parse_atoms(const char* s, Crystal& cr) { int line_with_error = -1; int atom_count = 0; // to avoid not necessary copying, don't use atoms.clear() for (int line_nr = 1; ; ++line_nr) { // skip whitespace while(isspace(*s) && *s != '\n') ++s; if (*s == '\n') { ++s; continue; } if (*s == '\0') break; // usually the atom is not changed, so we first parse data // into a new struct Atom, and if it is different we copy it // and do calculations Atom a; // parse symbol const char* word_end = s; while (isalnum(*word_end)) ++word_end; int symbol_len = word_end - s; if (symbol_len == 0 || symbol_len >= 8) { line_with_error = line_nr; break; } memcpy(a.symbol, s, symbol_len); a.symbol[symbol_len] = '\0'; s = word_end; // parse x, y, z char *endptr; a.pos[0].x = strtod(s, &endptr); s = endptr; a.pos[0].y = strtod(s, &endptr); s = endptr; a.pos[0].z = strtod(s, &endptr); // check if the numbers were parsed if (endptr == s || // one or more numbers were not parsed (!isspace(*endptr) && *endptr != '\0')) // e.g. "Si 0 0 0foo" { line_with_error = line_nr; break; } s = endptr; // if there is more than 4 words in the line, ignore the extra words while (*s != '\n' && *s != '\0') ++s; if (*s == '\n') ++s; // check if the atom needs to be copied, and copy it if necessary if (atom_count == (int) cr.atoms.size()) { a.xray_sf = find_in_it92(a.symbol); a.neutron_sf = find_in_nn92(a.symbol); cr.atoms.push_back(a); add_symmetric_images(cr.atoms[atom_count], cr.sg_ops); } else { Atom &b = cr.atoms[atom_count]; if (strcmp(a.symbol, b.symbol) != 0) { memcpy(b.symbol, a.symbol, 8); b.xray_sf = find_in_it92(b.symbol); b.neutron_sf = find_in_nn92(b.symbol); } if (a.pos[0].x != b.pos[0].x || a.pos[0].y != b.pos[0].y || a.pos[0].z != b.pos[0].z) { b.pos.resize(1); b.pos[0] = a.pos[0]; add_symmetric_images(b, cr.sg_ops); } } ++atom_count; } // vector cr.atoms may be longer than necessary cr.atoms.resize(atom_count); return line_with_error; } void PlanesWithSameD::add(Miller const& hkl, const SgOps& sg_ops) { for (vector::iterator i = planes.begin(); i != planes.end(); ++i) { if (check_symmetric_hkl(sg_ops, *i, hkl)) { i->multiplicity++; return; } } // equivalent plane not found planes.push_back(Plane(hkl)); } Crystal::Crystal() : uc(NULL) { atoms.reserve(16); sg_ops.tr.push_back(TransVec(0, 0, 0)); // always keep trivial tr // add unit seitz matrix SeitzMatrix sm = { { 1, 0, 0, 0, 1, 0, 0, 0, 1, }, { 0, 0, 0 } }; sg_ops.seitz.push_back(sm); } Crystal::~Crystal() { delete uc; } // in the same order as in enum CrystalSystem const char *CrystalSystemNames[] = { "Undefined", // 0 NULL, "Triclinic", // 2 "Monoclinic", "Orthorhombic", "Tetragonal", "Trigonal", "Hexagonal", "Cubic" // 8 }; const char* get_crystal_system_name(CrystalSystem xs) { return CrystalSystemNames[xs]; } CrystalSystem get_crystal_system(int space_group) { if (space_group <= 2) return TriclinicSystem; else if (space_group <= 15) return MonoclinicSystem; else if (space_group <= 74) return OrthorhombicSystem; else if (space_group <= 142) return TetragonalSystem; else if (space_group <= 167) return TrigonalSystem; else if (space_group <= 194) return HexagonalSystem; else return CubicSystem; } int get_sg_order(const SgOps& sg_ops) { return sg_ops.tr.size() * sg_ops.seitz.size() * (sg_ops.inv ? 2 : 1); } static char parse_sg_extension(const char *symbol, char *qualif) { if (symbol == NULL || *symbol == '\0') { if (qualif != NULL) qualif[0] = '\0'; return 0; } char ext = 0; while (isspace(*symbol) || *symbol == ':') ++symbol; if (isdigit(*symbol) || *symbol == 'R' || *symbol == 'H') { ext = *symbol; ++symbol; while (isspace(*symbol) || *symbol == ':') ++symbol; } if (qualif != NULL) { strncpy(qualif, symbol, 4); qualif[4] = '\0'; } return ext; } static const SpaceGroupSetting* parse_hm_or_hall(const char *symbol) { // copy and 'normalize' symbol (up to ':') to table s char s[32]; for (int i = 0; i < 32; ++i) { if (*symbol == '\0' || *symbol == ':') { s[i] = '\0'; break; } else if (isspace(*symbol)) { s[i] = ' '; ++symbol; while (isspace(*symbol)) ++symbol; } else { // In HM symbols, first character is upper case letter. // In Hall symbols, the second character is upper case. // The first and second chars are either upper or ' ' or '-'. // The rest of alpha chars is lower case. s[i] = (i < 2 ? toupper(*symbol) : tolower(*symbol)); ++symbol; } } // now *symbol is either '\0' or ':' for (const SpaceGroupSetting *p = space_group_settings; p->sgnumber != 0; ++p) { if (strcmp(p->HM, s) == 0) { if (*symbol == ':') { char ext = parse_sg_extension(symbol+1, NULL); while (p->ext != ext) { ++p; if (strcmp(p->HM, s) != 0) // full match not found return NULL; } } return p; } else if (strcmp(p->Hall + (p->Hall[0] == ' ' ? 1 : 0), s) == 0) { return p; } } return NULL; } static const SpaceGroupSetting* find_space_group_setting(int sgn, const char *setting) { char qualif[5]; char ext = parse_sg_extension(setting, qualif); const SpaceGroupSetting *p = find_first_sg_with_number(sgn); if (p == NULL) return NULL; while (p->ext != ext || strcmp(p->qualif, qualif) != 0) { ++p; if (p->sgnumber != sgn) // not found return NULL; } return p; } const SpaceGroupSetting* parse_any_sg_symbol(const char *symbol) { if (symbol == NULL) return NULL; while (isspace(*symbol)) ++symbol; if (isdigit(*symbol)) { const char* colon = strchr(symbol, ':'); int sgn = strtol(symbol, NULL, 10); return find_space_group_setting(sgn, colon); } else { return parse_hm_or_hall(symbol); } } void Crystal::set_space_group(const SpaceGroupSetting* sgs_) { sgs = sgs_; sg_ops.tr.resize(1); // leave only the trivial tr (0, 0, 0) sg_ops.inv = false; sg_ops.inv_t.x = sg_ops.inv_t.y = sg_ops.inv_t.z = 0; if (sgs == NULL) return; int n_seitz = get_seitz_mx_count(sgs); // the first seitz matrix is unit matrix sg_ops.seitz.resize(n_seitz + 1); for (int i = 0; i != n_seitz; ++i) get_seitz_mx(sgs, i, &sg_ops.seitz[i+1]); switch (sgs->Hall[1]) { case 'A': sg_ops.tr.push_back(TransVec(0,6,6)); break; case 'B': sg_ops.tr.push_back(TransVec(6,0,6)); break; case 'C': sg_ops.tr.push_back(TransVec(6,6,0)); break; case 'I': sg_ops.tr.push_back(TransVec(6,6,6)); break; case 'P': break; case 'R': sg_ops.tr.push_back(TransVec(8,4,4)); sg_ops.tr.push_back(TransVec(4,8,8)); break; case 'F': sg_ops.tr.push_back(TransVec(0,6,6)); sg_ops.tr.push_back(TransVec(6,0,6)); sg_ops.tr.push_back(TransVec(6,6,0)); break; default: assert(0); } if (sgs->Hall[0] == '-') { sg_ops.inv = true; } else { const char* t = strstr(sgs->Hall, " -1"); if (t != NULL) { sg_ops.inv = true; t += 3; if (strcmp(t, "ab") == 0) sg_ops.inv_t = TransVec(6, 6, 0); else if (strcmp(t, "ac") == 0) sg_ops.inv_t = TransVec(6, 0, 6); else if (strcmp(t, "bc") == 0) sg_ops.inv_t = TransVec(0, 6, 6); else if (strcmp(t, "ad") == 0) sg_ops.inv_t = TransVec(9, 3, 3); else if (strcmp(t, "bw") == 0) sg_ops.inv_t = TransVec(0, 6, 3); else if (strcmp(t, "d" ) == 0) sg_ops.inv_t = TransVec(3, 3, 3); else if (strcmp(t, "n" ) == 0) sg_ops.inv_t = TransVec(6, 6, 6); else assert(0); } } } // returns true if exists t in sg_ops.tr, such that: h*(t+T) != n // used by is_sys_absent() static bool has_nonunit_tr(const SgOps& sg_ops, const int* T, int h, int k, int l) { for (vector::const_iterator t = sg_ops.tr.begin(); t != sg_ops.tr.end(); ++t) if (((T[0]+t->x) * h + (T[1]+t->y) * k + (T[2]+t->z) * l) % 12 != 0) return true; return false; } static bool is_sys_absent(const SgOps& sg_ops, int h, int k, int l) { for (size_t i = 0; i < sg_ops.seitz.size(); ++i) { const int* R = sg_ops.seitz[i].R; const int* T = sg_ops.seitz[i].T; int M[3] = { h * R[0] + k * R[3] + l * R[6], h * R[1] + k * R[4] + l * R[7], h * R[2] + k * R[5] + l * R[8] }; if (h == M[0] && k == M[1] && l == M[2]) { if (has_nonunit_tr(sg_ops, T, h, k, l)) return true; } else if (h == -M[0] && k == -M[1] && l == -M[2] && sg_ops.inv) { int ts[3] = { sg_ops.inv_t.x - T[0], sg_ops.inv_t.y - T[1], sg_ops.inv_t.z - T[2] }; if (has_nonunit_tr(sg_ops, ts, h, k, l)) return true; } } return false; } // helper to generate sequence 0, 1, -1, 2, -2, 3, ... static int inc_neg(int h) { return h > 0 ? -h : -h+1; } void Crystal::generate_reflections(double min_d) { bp.clear(); UnitCell reciprocal = uc->get_reciprocal(); // set upper limit for iteration of Miller indices // TODO: smarter algorithm, like in uctbx::unit_cell::max_miller_indices() int max_h = 20; int max_k = 20; int max_l = 20; if (fabs(uc->alpha - M_PI/2) < 1e-9 && fabs(uc->beta - M_PI/2) < 1e-9 && fabs(uc->gamma - M_PI/2) < 1e-9) { max_h = (int) (uc->a / min_d); max_k = (int) (uc->b / min_d); max_l = (int) (uc->c / min_d); } // Don't generate too many reflections (it could happen // when user chooses Q instead of 2T, or puts wrong wavelength) if (max_h * max_k * max_l > 8000) max_h = max_k = max_l = 20; for (int h = 0; h != max_h+1; h = inc_neg(h)) for (int k = 0; k != max_k+1; k = inc_neg(k)) for (int l = (h==0 && k==0 ? 1 : 0); l != max_l+1; l = inc_neg(l)) { double d = 1 / reciprocal.calculate_distance(h, k, l); //double d = uc->calculate_d(h, k, l); // the same if (d < min_d) continue; // check for systematic absence if (is_sys_absent(sg_ops, h, k, l)) continue; Miller hkl = { h, k, l }; bool found = false; for (vector::iterator i = bp.begin(); i != bp.end(); ++i) { if (fabs(d - i->d) < 1e-9) { i->add(hkl, sg_ops); found = true; break; } } if (!found) { PlanesWithSameD new_p; new_p.planes.push_back(Plane(hkl)); new_p.d = d; new_p.lpf = 0.; new_p.intensity = 0.; new_p.enabled = true; bp.push_back(new_p); } } sort(bp.begin(), bp.end()); old_min_d = min_d; } // stol = sin(theta)/lambda static void set_F2(Plane& p, const vector& atoms, RadiationType radiation, double stol) { // calculating F_hkl, (Pecharsky & Zavalij, eq. (2.89) and (2.103)) // assuming population g = 1 // assuming temperature factor t = 1 double F_real = 0.; double F_img = 0; for (vector::const_iterator i = atoms.begin(); i != atoms.end(); ++i){ double f = 1.; if (radiation == kXRay && i->xray_sf) f = calculate_it92_factor(i->xray_sf, stol*stol); else if (radiation == kNeutron && i->neutron_sf) f = i->neutron_sf->bond_coh_scatt_length; for (vector::const_iterator j = i->pos.begin(); j != i->pos.end(); ++j) { double hx = p.h * j->x + p.k * j->y + p.l * j->z; F_real += f * cos(2*M_PI * hx); F_img += f * sin(2*M_PI * hx); } } p.F2 = F_real*F_real + F_img*F_img; //printf("hkl=(%d %d %d) F=(%g, %g) F2=%g\n", // p.h, p.k, p.l, F_real, F_img, p.F2); } static void set_lpf(PlanesWithSameD &bp, RadiationType radiation, double lambda) { if (lambda == 0) bp.lpf = 1.; else { double T = asin(bp.stol() * lambda); // theta if (radiation == kXRay) { // for x-rays, we assume K=0.5 and // LP = (1 + cos(2T)^2) / (cos(T) sin(T)^2) // (Pecharsky & Zavalij, eq. (2.70), p. 192) bp.lpf = (1 + cos(2*T)*cos(2*T)) / (cos(T)*sin(T)*sin(T)); } else if (radiation == kNeutron) { // Kisi & Howard, Applications of Neutron Powder Diffraction (2.38) // no polarization only the Lorentz factor: // L = 1 / (4 sin^2(T) cos(T)) bp.lpf = 1 / (4 * sin(T)*sin(T)*cos(T)); // for TOF diffractometers with a fixed diffraction angle: // L = d^4 sin(theta) } } } void Crystal::update_intensities(RadiationType r, double lambda) { if (atoms.empty()) return; for (vector::iterator i = bp.begin(); i != bp.end(); ++i) { set_lpf(*i, r, lambda); double t = 0; for (vector::iterator j = i->planes.begin(); j != i->planes.end(); ++j) { set_F2(*j, atoms, r, i->stol()); t += j->multiplicity * j->F2; } i->intensity = i->lpf * t; } } double UnitCell::calculate_V() const { // Giacovazzo p.62 double cosA = cos(alpha), cosB = cos(beta), cosG = cos(gamma); double t = 1 - cosA*cosA - cosB*cosB - cosG*cosG + 2*cosA*cosB*cosG; return a*b*c * sqrt(t); } /* double UnitCell::calculate_d(int h, int k, int l) const { double sinA=sin(alpha), sinB=sin(beta), sinG=sin(gamma), cosA=cos(alpha), cosB=cos(beta), cosG=cos(gamma); return sqrt((1 - cosA*cosA - cosB*cosB - cosG*cosG + 2*cosA*cosB*cosG) / ( (h/a*sinA) * (h/a*sinA) //(h/a*sinA)^2 + (k/b*sinB) * (k/b*sinB) //(k/b*sinB)^2 + (l/c*sinG) * (l/c*sinG) //(l/c*sinG)^2 + 2*h*l/a/c*(cosA*cosG-cosB) + 2*h*k/a/b*(cosA*cosB-cosG) + 2*k*l/b/c*(cosB*cosG-cosA) ) ); } */ // [ 1/a 0 0 ] // M = [ -cosG/(a sinG) 1/(b sinG) 0 ] // [ a*cosB* b*cosA* c* ] // // where A is alpha, B is beta, G is gamma, * means reciprocal space. // (Giacovazzo, p.68) void UnitCell::set_M() { double sinA=sin(alpha), sinB=sin(beta), sinG=sin(gamma), cosA=cos(alpha), cosB=cos(beta), cosG=cos(gamma); M[0][0] = 1/a; M[0][1] = 0.; M[0][2] = 0.; M[1][0] = -cosG/(a*sinG); M[1][1] = 1/(b*sinG); M[1][2] = 0.; M[2][0] = b * c * sinA / V // a* * (cosA*cosG-cosB) / (sinA*sinG); //cosB* M[2][1] = a * c * sinB / V // b* * (cosB*cosG-cosA) / (sinB*sinG); //cosA* M[2][2] = a * b * sinG / V; // c* M_1[0][0] = a; M_1[0][1] = 0; M_1[0][2] = 0; M_1[1][0] = b * cosG; M_1[1][1] = b * sinG; M_1[1][2] = 0; M_1[2][0] = c * cosB; M_1[2][1] = -c * sinB * (cosB*cosG-cosA) / (sinB*sinG); M_1[2][2] = 1 / M[2][2]; } // returns UnitCell reciprocal to this, i.e. that has parameters a*, b*, ... // (Giacovazzo, p. 64) UnitCell UnitCell::get_reciprocal() const { double ar = b * c * sin(alpha) / V; double br = a * c * sin(beta) / V; double cr = a * b * sin(gamma) / V; double cosAr = (cos(beta)*cos(gamma)-cos(alpha)) / (sin(beta)*sin(gamma)); double cosBr = (cos(alpha)*cos(gamma)-cos(beta)) / (sin(alpha)*sin(gamma)); double cosGr = (cos(alpha)*cos(beta)-cos(gamma)) / (sin(alpha)*sin(beta)); return UnitCell(ar, br, cr, acos(cosAr), acos(cosBr), acos(cosGr)); } // returns 1/|v|, where v = M * [h k l]; double UnitCell::calculate_distance(double h, double k, double l) const { double v2 = 0.; for (int i = 0; i != 3; ++i) { double t = h * M_1[0][i] + k * M_1[1][i] + l * M_1[2][i]; v2 += t*t; } return sqrt(v2); } const Anode anodes[] = { { "Cu", 1.54056, 1.54439 }, { "Cr", 2.28970, 2.29361 }, { "Fe", 1.93604, 1.93998 }, { "Mo", 0.70930, 0.71359 }, { "Ag", 0.55941, 0.56380 }, { "Co", 1.78901, 1.79290 }, { NULL, 0, 0 } }; static const char* default_cel_files[][2] = { {"bSiC", "cell 4.358 4.358 4.358 90 90 90\n" "Si 14 0 0 0\n" "C 6 0.25 0.25 0.25\n" "rgnr 216" }, {"aSiC", "cell 3.082 3.082 15.123 90 90 120\n" "SI1 14 0 0 0\n" "SI2 14 0.3333 0.6667 0.1667\n" "SI3 14 0.3333 0.6667 0.8333\n" "C1 6 0.0 0.0 0.125\n" "C2 6 0.3333 0.6667 0.2917\n" "C3 6 0.3333 0.6667 0.9583\n" "rgnr 186", }, {"NaCl", "cell 5.64009 5.64009 5.64009 90 90 90\n" "Na 11 0 0 0\n" "Cl 17 0.5 0 0\n" "rgnr 225" }, {"diamond", "cell 3.5595 3.5595 3.5595 90 90 90\n" "C 6 0 0 0\n" "rgnr 227" }, {"Si", "cell 5.4309 5.4309 5.4309 90 90 90\n" "Si 14 0 0 0\n" "rgnr 227" }, {"CeO2", "cell 5.41 5.41 5.41 90 90 90\n" "Ce 58 0 0 0\n" "O 8 0.25 0.25 0.25\n" "rgnr 225" }, {"Zn", "cell 2.665 2.665 4.946 90 90 120\n" "Zn 30 0.33333 0.66667 0.25\n" "rgnr 194" }, {NULL, NULL} }; CelFile read_cel_file(FILE *f) { CelFile cel = { 0., 0., 0., 0., 0., 0., NULL, vector() }; if (!f) return cel; char s[20]; int r = fscanf(f, "%4s %lf %lf %lf %lf %lf %lf", s, &cel.a, &cel.b, &cel.c, &cel.alpha, &cel.beta, &cel.gamma); if (r != 7) return cel; if (strcmp(s, "cell") != 0 && strcmp(s, "CELL") != 0 && strcmp(s, "Cell") != 0) { return cel; } while (1) { r = fscanf(f, "%12s", s); if (r != 1) return cel; if (strcmp(s, "RGNR") == 0 || strcmp(s, "rgnr") == 0 || strcmp(s, "Rgnr") == 0) break; AtomInCell atom; r = fscanf(f, "%d %lf %lf %lf", &atom.Z, &atom.x, &atom.y, &atom.z); if (r != 4) { return cel; } cel.atoms.push_back(atom); // skip the rest of the line for (int c = fgetc(f); c != '\n' && c != EOF; c = fgetc(f)) ; } int sgn; r = fscanf(f, "%d", &sgn); if (r != 1) return cel; if (sgn < 1 || sgn > 230) return cel; cel.sgs = find_first_sg_with_number(sgn); for (int c = fgetc(f); c != '\n' && c != EOF; c = fgetc(f)) { if (c == ':') { r = fscanf(f, "%8s", s); if (r == 1) cel.sgs = find_space_group_setting(sgn, s); break; } else if (isdigit(c)) { ungetc(c, f); int pc_setting; r = fscanf(f, "%d", &pc_setting); if (r == 1) cel.sgs = get_sg_from_powdercell_rgnr(sgn, pc_setting); break; } else if (!isspace(c)) break; } return cel; } void write_cel_file(CelFile const& cel, FILE *f) { //for (int i = 1; i != 104; ++i) // assert(find_Z_in_pse(i)->Z == i); fprintf(f, "cell %g %g %g %g %g %g\n", cel.a, cel.b, cel.c, cel.alpha, cel.beta, cel.gamma); for (vector::const_iterator i = cel.atoms.begin(); i != cel.atoms.end(); ++i) { const t_pse* pse = find_Z_in_pse(i->Z); fprintf(f, "%-2s %2d %g %g %g\n", pse->symbol, i->Z, i->x, i->y, i->z); } int sgn = cel.sgs->sgnumber; fprintf(f, "rgnr %d", sgn); if (sgn != 1 && (cel.sgs-1)->sgnumber == sgn) { fprintf(f, " :"); if (cel.sgs->ext != 0) fprintf(f, "%c", cel.sgs->ext); fprintf(f, "%s", cel.sgs->qualif); } fprintf(f, "\n"); } void write_default_cel_files(const char* path_prefix) { for (const char*(*s)[2] = default_cel_files; (*s)[0] != NULL; ++s) { string filename = string(path_prefix) + (*s)[0] + ".cel"; FILE *f = fopen(filename.c_str(), "w"); if (!f) continue; fprintf(f, "%s\n", (*s)[1]); fclose(f); } } fityk-1.3.1/wxgui/ceria.h000066400000000000000000000107171302634723100152500ustar00rootroot00000000000000// Author: Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_CERIA_H_ #define FITYK_WX_CERIA_H_ #include // FILE #include #include #include "atomtables.h" #include "sgtables.h" enum RadiationType { kXRay, kNeutron }; struct TransVec { int x, y, z; // divide by 12. before use TransVec() {} TransVec(int x_, int y_, int z_) : x(x_), y(y_), z(z_) {} }; // symmetry operations for the space group struct SgOps { std::vector seitz; // Seitz matrices std::vector tr; // translation vectors bool inv; // has center of inversion TransVec inv_t; // translation for centre of inversion }; std::string fullHM(const SpaceGroupSetting *sgs); const SpaceGroupSetting* parse_any_sg_symbol(const char *symbol); struct AtomInCell { int Z; double x, y, z; }; struct CelFile { double a, b, c, alpha, beta, gamma; const SpaceGroupSetting* sgs; std::vector atoms; }; CelFile read_cel_file(FILE* f); void write_cel_file(CelFile const& cel, FILE* f); void write_default_cel_files(const char* path_prefix); class UnitCell { public: const double a, b, c, alpha, beta, gamma; const double V; double M[3][3]; double M_1[3][3]; // M^-1 UnitCell(double a_, double b_, double c_, double alpha_, double beta_, double gamma_) : a(a_), b(b_), c(c_), alpha(alpha_), beta(beta_), gamma(gamma_), V(calculate_V()) { set_M(); } double calculate_V() const; // pre: V should be set void set_M(); UnitCell get_reciprocal() const; // returns |v|, where v = M_1 * [h k l]; double calculate_distance(double h, double k, double l) const; // calculate interplanar distance //double calculate_d(int h, int k, int l) const; }; struct Miller { int h, k, l; }; struct Plane : public Miller { int multiplicity; double F2; // |F_hkl|^2 (_not_ multiplied by multiplicity) Plane() {} Plane(Miller const& hkl) : Miller(hkl), multiplicity(1), F2(0.){} }; struct PlanesWithSameD { std::vector planes; double d; double lpf; // Lorentz-polarization factor double intensity; // total intensity = lpf * sum(multiplicity * F2) bool enabled; // include this peak in model bool operator<(const PlanesWithSameD& p) const { return d > p.d; } void add(Miller const& hkl, const SgOps& sg_ops); double stol() const { return 1. / (2 * d); } // returns sin(theta)/lambda }; struct Pos // position in unit cell, 0 <= x,y,z < 1 { double x, y, z; }; struct Atom { char symbol[8]; // Contains positions of all symmetrically equivalent atoms in unit cell. // pos[0] contains the "original" atom. std::vector pos; const t_it92_coeff *xray_sf; const t_nn92_record *neutron_sf; Atom() : pos(1) { pos[0].x = pos[0].y = pos[0].z = 0.; } }; // crystal system, we keep it compatible with SgLite enum CrystalSystem { UndefinedSystem = 0, TriclinicSystem = 2, MonoclinicSystem = 3, OrthorhombicSystem = 4, TetragonalSystem = 5, TrigonalSystem = 6, HexagonalSystem = 7, CubicSystem = 8 }; CrystalSystem get_crystal_system(int space_group); const char* get_crystal_system_name(CrystalSystem xs); class Crystal { public: const SpaceGroupSetting* sgs; // space group SgOps sg_ops; // symmetry operations UnitCell* uc; int n_atoms; std::vector atoms; std::vector bp; // boundles of hkl planes double old_min_d; Crystal(); ~Crystal(); void set_space_group(const SpaceGroupSetting* name); void generate_reflections(double min_d); void set_unit_cell(UnitCell *unit_cell) { delete uc; uc = unit_cell; } void update_intensities(RadiationType r, double lambda); CrystalSystem xs() const { return sgs ? get_crystal_system(sgs->sgnumber) : UndefinedSystem; } private: Crystal(const Crystal&); // disallow copy void operator=(const Crystal&); // disallow assign }; int parse_atoms(const char* s, Crystal& cr); extern const char *CrystalSystemNames[]; extern const SpaceGroupSetting space_group_settings[]; void add_symmetric_images(Atom& a, const SgOps& sg_ops); // Returns the order of the space group, // i.e. the maximum number of symmetry equivalent positions. int get_sg_order(const SgOps& sg_ops); struct Anode { const char *name; double alpha1, alpha2; }; extern const Anode anodes[]; #endif // FITYK_WX_CERIA_H_ fityk-1.3.1/wxgui/cmn.cpp000066400000000000000000000223301302634723100152670ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include #include #include #include #include #include #include "cmn.h" using namespace std; namespace { /// Round real to integer. Defined here to avoid dependency on ../common.h. int iround(double d) { return static_cast(floor(d+0.5)); } } bool cfg_read_bool(wxConfigBase *cf, const wxString& key, bool def_val) { bool b; cf->Read(key, &b, def_val); return b; } double cfg_read_double(wxConfigBase *cf, const wxString& key, double def_val) { double d; cf->Read(key, &d, def_val); return d; } // the storing of color values was changed in 0.9.7 // before: // config->Write(key + wxT("/Red"), (int) value.Red()); // config->Write(key + wxT("/Green"), (int) value.Green()); // config->Write(key + wxT("/Blue"), (int) value.Blue()); // after: // config->Write(key + wxT("_col"), value.GetAsString(wxC2S_CSS_SYNTAX)); wxColour cfg_read_color(const wxConfigBase *config, const wxString& key, const wxColour& default_value) { wxString val = config->Read(key + wxT("_col"), wxEmptyString); if (val.empty() && config->Exists(key + wxT("/Red"))) return wxColour( config->Read (key + wxT("/Red"), (int) default_value.Red()), config->Read (key + wxT("/Green"), (int) default_value.Green()), config->Read (key + wxT("/Blue"), (int) default_value.Blue())); return val.empty() ? default_value : wxColour(val); } void cfg_write_color(wxConfigBase *config, const wxString& key, const wxColour& value) { config->Write(key + wxT("_col"), value.GetAsString(wxC2S_CSS_SYNTAX)); if (config->Exists(key + wxT("/Red"))) config->DeleteGroup(key); } wxFont cfg_read_font(wxConfigBase const *config, wxString const& key, wxFont const &default_value) { wxString str = config->Read(key, wxEmptyString); if (str.empty()) return default_value; wxFont font; bool ok = font.SetNativeFontInfo(str); return ok ? font : default_value; } void cfg_write_font (wxConfigBase *config, const wxString& key, const wxFont& value) { config->Write(key, value.IsOk() ? value.GetNativeFontInfoDesc() : wxString()); } bool change_color_dlg(wxColour& col) { wxColourData col_data; col_data.SetCustomColour(0, col); col_data.SetColour(col); wxColourDialog dialog(0, &col_data); bool ok = (dialog.ShowModal() == wxID_OK); if (ok) col = dialog.GetColourData().GetColour(); return ok; } void add_apply_close_buttons(wxWindow *parent, wxSizer *top_sizer) { top_sizer->Add(new wxStaticLine(parent, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 5); wxBoxSizer *s = new wxBoxSizer(wxHORIZONTAL); s->Add(new wxButton(parent, wxID_APPLY, wxT("&Apply")), 0, wxALL, 5); s->Add(new wxButton(parent, wxID_CLOSE, wxT("&Close")), 0, wxALL, 5); top_sizer->Add(s, 0, wxALL|wxALIGN_CENTER, 0); } //=============================================================== // ProportionalSplitter //=============================================================== ProportionalSplitter::ProportionalSplitter(wxWindow* parent, wxWindowID id, float proportion, const wxSize& size, long style) : wxSplitterWindow(parent, id, wxDefaultPosition, size, style), m_proportion(proportion), m_firstpaint(true) { //wxASSERT(m_proportion >= 0. && m_proportion <= 1.); SetMinimumPaneSize(20); ResetSash(); Connect(GetId(), wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, (wxObjectEventFunction) &ProportionalSplitter::OnSashChanged); Connect(GetId(), wxEVT_SIZE, (wxObjectEventFunction) &ProportionalSplitter::OnReSize); //hack to set sizes on first paint event Connect(GetId(), wxEVT_PAINT, (wxObjectEventFunction) &ProportionalSplitter::OnPaint); } bool ProportionalSplitter::SplitHorizProp(wxWindow* win1, wxWindow* win2, float proportion) { if (proportion >= 0. && proportion <= 1.) m_proportion = proportion; int height = GetClientSize().GetHeight(); int h = iround(height * m_proportion); //sometimes there is a strange problem without it (why?) if (h < GetMinimumPaneSize() || h > height-GetMinimumPaneSize()) h = 0; return wxSplitterWindow::SplitHorizontally(win1, win2, h); } bool ProportionalSplitter::SplitVertProp(wxWindow* win1, wxWindow* win2, float proportion) { if (proportion >= 0. && proportion <= 1.) m_proportion = proportion; int width = GetClientSize().GetWidth(); int w = iround(width * m_proportion); if (w < GetMinimumPaneSize() || w > width-GetMinimumPaneSize()) w = 0; return wxSplitterWindow::SplitVertically(win1, win2, w); } int ProportionalSplitter::GetExpectedSashPosition() { return iround(GetWindowSize() * m_proportion); } void ProportionalSplitter::SetSashPosition(int position) { if (position < 0 || position > GetWindowSize()) return; m_proportion = float(position) / GetWindowSize(); wxSplitterWindow::SetSashPosition(position); } void ProportionalSplitter::ResetSash() { wxSplitterWindow::SetSashPosition(GetExpectedSashPosition()); } void ProportionalSplitter::OnReSize(wxSizeEvent& event) { // We may need to adjust the sash based on m_proportion. ResetSash(); event.Skip(); } void ProportionalSplitter::OnSashChanged(wxSplitterEvent &event) { // This event is triggered on start-up in some cases, // eg. on wxGTK, in a setup with h-splitter containing two v-splitters, // if the inner splitters are split first the lower v-splitter gets it. if (!m_firstpaint) { event.Skip(); return; } // We'll change m_proportion now based on where user dragged the sash. const wxSize& s = GetSize(); int t = GetSplitMode() == wxSPLIT_HORIZONTAL ? s.GetHeight() : s.GetWidth(); float prop = float(event.GetSashPosition()) / t; if (prop > 0. && prop < 1.) m_proportion = prop; event.Skip(); } void ProportionalSplitter::OnPaint(wxPaintEvent &event) { if (m_firstpaint) { if (GetSashPosition() != GetExpectedSashPosition()) ResetSash(); m_firstpaint = false; } event.Skip(); } // KFTextCtrl void KFTextCtrl::OnKillFocus(wxFocusEvent& event) { wxCommandEvent ev(wxEVT_COMMAND_TEXT_ENTER, GetId()); ev.SetEventObject(this); ProcessEvent(ev); event.Skip(); } BEGIN_EVENT_TABLE(KFTextCtrl, wxTextCtrl) EVT_KILL_FOCUS(KFTextCtrl::OnKillFocus) END_EVENT_TABLE() /// All configuration is stored in files in directory: /// Unix: ~/.fityk /// Windows: C:\Documents and Settings\username\Application Data\fityk /// Mac: ~/Library/Application Support/fityk wxString get_conf_file(string const& filename) { return wxStandardPaths::Get().GetUserDataDir() + wxFILE_SEP_PATH + s2wx(filename); } bool should_focus_input(wxKeyEvent& event) { if (event.AltDown() || event.ControlDown() || event.CmdDown()) return false; int c = event.GetKeyCode(); return c < 128 && (c == ' ' || isalnum(c) || ispunct(c)); } void updateControlWithItems(wxControlWithItems *cwi, vector const& v) { if (v.size() != (size_t) cwi->GetCount()) { cwi->Clear(); for (size_t i = 0; i < v.size(); ++i) cwi->Append(s2wx(v[i])); } else for (size_t i = 0; i < v.size(); ++i) if (cwi->GetString(i) != s2wx(v[i])) cwi->SetString(i, s2wx(v[i])); } SmallStaticText::SmallStaticText(wxWindow* parent, const wxString& label) : wxStaticText(parent, wxID_ANY, label) { wxFont font = GetFont(); #ifdef __WXMSW__ font.SetPointSize(font.GetPointSize() - 1); #else font.SetPointSize(font.GetPointSize() - 2); #endif SetFont(font); } DialogCloser* DialogCloser::instance_ = NULL; DialogCloser* DialogCloser::instance() { if (instance_ == NULL) instance_ = new DialogCloser(); return instance_; } void DialogCloser::OnClose(wxCommandEvent& event) { wxWindow* w = (wxWindow*) event.GetEventObject(); while (!w->IsTopLevel()) w = w->GetParent(); wxDialog *dialog = wxDynamicCast(w, wxDialog); assert(dialog->IsModal()); dialog->EndModal(wxID_CANCEL); } TextComboDlg::TextComboDlg(wxWindow *parent, const wxString& message, const wxString& caption) : wxDialog(parent, -1, caption) { wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL); topsizer->Add(CreateTextSizer(message), wxSizerFlags().DoubleBorder()); combo = new wxComboBox(this, -1); topsizer->Add(combo, wxSizerFlags().Expand().TripleBorder(wxLEFT|wxRIGHT)); wxSizer *buttonSizer = CreateSeparatedButtonSizer(wxOK|wxCANCEL); if (buttonSizer) topsizer->Add(buttonSizer, wxSizerFlags().DoubleBorder().Expand()); SetSizerAndFit(topsizer); combo->SetFocus(); } fityk-1.3.1/wxgui/cmn.h000066400000000000000000000162661302634723100147470ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_CMN_H_ #define FITYK_WX_CMN_H_ #include #include #include #include #include #include #include // input mode, changes functions of left and right clicks enum MouseModeEnum { mmd_zoom=0, // normal mode mmd_bg, // baseline mode mmd_add, // add-peak mode mmd_activate, // data-range mode mmd_peak, // mouse-over-peak-top mode mmd_readonly // read-only mode, used for saving the plot as image }; // plot types, e.g. to tell where is mouse enum PlotTypeEnum { pte_main, pte_aux }; // used in refresh_plots() enum WhichPlot { kMainPlot, kAllPlots }; inline wxString pchar2wx(char const* pc) { return wxString::FromUTF8(pc); } inline wxString s2wx(std::string const& s) { return pchar2wx(s.c_str()); } inline std::string wx2s(wxString const& w) { return std::string((const char*) w.ToUTF8()); } inline wxArrayString stl2wxArrayString(std::vector const& vs) { wxArrayString wxas; for (std::vector::const_iterator i = vs.begin(); i != vs.end(); ++i) wxas.Add(s2wx(*i)); return wxas; } // convenient wxArrayString constructors inline wxArrayString ArrayString(wxString const& s1) { wxArrayString a(1, &s1); return a; } inline wxArrayString ArrayString(wxString const& s1, wxString const& s2) { wxArrayString a(1, &s1); a.Add(s2); return a; } inline wxArrayString ArrayString(wxString const& s1, wxString const& s2, wxString const& s3) { wxArrayString a(1, &s1); a.Add(s2); a.Add(s3); return a; } /// wxTextCtrl for real number input, will be enhanced class RealNumberCtrl : public wxTextCtrl { public: RealNumberCtrl(wxWindow* parent, wxWindowID id, wxString const& value) : wxTextCtrl(parent, id, value) {} RealNumberCtrl(wxWindow* parent, wxWindowID id, std::string const& value) : wxTextCtrl(parent, id, s2wx(value)) {} RealNumberCtrl(wxWindow* parent, wxWindowID id, double value) : wxTextCtrl(parent, id) { set(value); } void set(double value) { SetValue(wxString::Format(wxT("%g"), value)); } }; // only wxString and long types can be read conveniently from wxConfig // these functions are defined in plot.cpp class wxConfigBase; class wxString; bool cfg_read_bool(wxConfigBase* cf, wxString const& key, bool def_val); double cfg_read_double(wxConfigBase* cf, wxString const& key, double def_val); wxColour cfg_read_color(wxConfigBase const* config, wxString const& key, wxColour const& default_value); void cfg_write_color(wxConfigBase* config, const wxString& key, const wxColour& value); wxFont cfg_read_font(wxConfigBase const* config, wxString const& key, wxFont const& default_value); void cfg_write_font(wxConfigBase* config, wxString const& key, wxFont const& value); bool should_focus_input(wxKeyEvent& event); bool change_color_dlg(wxColour& col); void add_apply_close_buttons(wxWindow *parent, wxSizer *top_sizer); /// based on http://wiki.wxpython.org/index.cgi/ProportionalSplitterWindow /// it is like wxSplitterWindow, but when resized, both windows are resized /// proporionally class ProportionalSplitter: public wxSplitterWindow { public: ProportionalSplitter(wxWindow* parent, wxWindowID id=-1, float proportion=0.66, // 0. - 1. const wxSize& size = wxDefaultSize, long style=wxSP_NOBORDER|wxSP_3DSASH); bool SplitHorizProp(wxWindow* win1, wxWindow* win2, float proportion=-1); bool SplitVertProp(wxWindow* win1, wxWindow* win2, float proportion=-1); float GetProportion() const { return m_proportion; } void SetProportion(float proportion) {m_proportion=proportion; ResetSash();} void SetSashPosition(int position); private: float m_proportion; //0-1 bool m_firstpaint; void ResetSash(); int GetExpectedSashPosition(); void OnReSize(wxSizeEvent& event); void OnSashChanged(wxSplitterEvent &event); void OnPaint(wxPaintEvent &event); }; class SpinCtrl: public wxSpinCtrl { public: SpinCtrl(wxWindow* parent, wxWindowID id, int val, int min, int max, int width=50) : wxSpinCtrl (parent, id, wxString::Format(wxT("%i"), val), wxDefaultPosition, wxSize(width, -1), wxSP_ARROW_KEYS, min, max, val) {} }; /// wxTextCtrl which sends wxEVT_COMMAND_TEXT_ENTER when loses the focus class KFTextCtrl : public wxTextCtrl { public: KFTextCtrl(wxWindow* parent, wxWindowID id, wxString const& value, int size=-1, long style=0) : wxTextCtrl(parent, id, value, wxDefaultPosition, wxSize(size, -1), style | wxTE_PROCESS_ENTER) {} void OnKillFocus(wxFocusEvent&); DECLARE_EVENT_TABLE() }; /// get path ~/.fityk/filename or equivalent on other platforms wxString get_conf_file(std::string const& filename); // same as cwi->Clear(), cwi->Append(...), but optimized for some special cases void updateControlWithItems(wxControlWithItems *cwi, std::vector const& v); #if !wxCHECK_VERSION(2, 9, 0) # define wxPENSTYLE_SHORT_DASH wxSHORT_DASH # define wxPENSTYLE_DOT wxDOT # define wxPENSTYLE_DOT_DASH wxDOT_DASH typedef int wxPenStyle; // SetEscapeId is buggy in wxgtk 2.8 (ticket #10746), disable it # ifdef __WXGTK__ # define SetEscapeId(id) \ Connect(id, wxEVT_COMMAND_BUTTON_CLICKED, \ wxCommandEventHandler(DialogCloser::OnClose), NULL, \ DialogCloser::instance()); # endif #endif class DialogCloser : public wxEvtHandler { public: static DialogCloser* instance(); void OnClose(wxCommandEvent& event); private: static DialogCloser* instance_; }; // from http://www.wxwidgets.org/wiki/index.php/Embedding_PNG_Images inline wxBitmap GetBitmapFromMemory_(const unsigned char *data, int length) { wxMemoryInputStream is(data, length); return wxBitmap(wxImage(is, wxBITMAP_TYPE_PNG)); } #define GET_BMP(name) \ GetBitmapFromMemory_(name##_png, sizeof(name##_png)) class SmallStaticText: public wxStaticText { public: SmallStaticText(wxWindow* parent, const wxString& label); }; inline wxStaticText* persistance_note(wxWindow *parent) { return new SmallStaticText(parent, wxT("To save preferences use GUI \u2023 Save current config")); } // similar to wxTextEntryDialog, but uses wxComboBox instead of wxTextCtrl class TextComboDlg : public wxDialog { public: TextComboDlg(wxWindow *parent, const wxString& message, const wxString& caption); wxComboBox *combo; }; // this wrapper is only to avoid wxLogSysError when the file can't be open class FFile: public wxFFile { public: FFile(const wxString& filename, const wxString& mode) { FILE* fp = wxFopen(filename, mode); if (fp) Attach(fp, filename); } }; #endif // FITYK_WX_CMN_H_ fityk-1.3.1/wxgui/dataedit.cpp000066400000000000000000000443101302634723100162730ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include #include #include #include #include #include "dataedit.h" #include "frame.h" #include "cmn.h" #include "app.h" // get_help_url() #include "fityk/data.h" // Data, Point #include "fityk/logic.h" // ui() using namespace std; // ';' will be replaced by line break static const char *default_transforms[] = { "std.dev.=1" "||" "|s=1" "|Y", "std.dev.=sqrt(y)" "||std.dev. = sqrt(y) (or 1 if y<1)" "|s=sqrt(max2(1,y))" "|Y", "integrate" "||" "|Y = Y[n-1] + (x[n] - x[n-1]) * (y[n-1] + y[n]) / 2" "|Y", "differentiate" "||compute numerical derivative f'(x)" "|Y = (y[n+1]-y[n])/(x[n+1]-x[n])" ";X = (x[n+1]+x[n])/2" ";M=M-1" ";S = sqrt(max2(1,y))" "|Y", "accumulate" "||Accumulate y of data and adjust std. dev." "|Y = Y[n-1] + y[n]" ";S = sqrt(max2(1,y))" "|Y", "normalize area" "||" "divide all Y (and std. dev.) values by the current data area" " (it gives unit area)" "|Y = y/darea(y), S = s / darea(y)" "|Y", "reduce 2x" "||join every two adjacent points" "|X = (x[n]+x[n+1])/2" ";Y = y[n]+y[n+1]" ";S = s[n]+s[n+1]" ";delete(mod(n,2)==1)" "|Y", "equilibrate step" "||make equal step, keep the number of points" "|X = x[0] + n * (x[M-1]-x[0]) / (M-1), Y = y[index(X)], S = s[index(X)], A = a[index(X)]" "|Y", "zero negative y" "||zero the Y value; of points with negative Y" "|Y=max2(y,0)" "|Y", "clear inactive" "||delete inactive points" "|delete(not a)" "|Y", "swap axes" "||Swap X and Y axes and adjust std. dev." "|Y=x , X=y , S=sqrt(max2(1,Y))" "|N", "generate sinusoid" "||replaces current data with sinusoid" "|M=2000" ";x=n/100" ";y=sin(x)" ";s=1" "|N", "invert" "||inverts y value of points" "|Y=-y" "|N", "activate all" "||activate all data points" "|a=true" "|N", "Q -> 2theta(Cu)" "||rescale X axis (for powder diffraction patterns)" "|X = asin(x/(4*pi)*1.54051) * 2*180/pi" "|N", "2theta(Cu) -> Q" "||rescale X axis (for powder diffraction patterns)" "|X = 4*pi * sin(x/2*pi/180) / 1.54051" "|N" }; static DataTransform line_to_datatran(const wxString& line) { DataTransform t = { "", "", "", false, false }; wxStringTokenizer tokenizer(line, "|"); if (tokenizer.CountTokens() < 4) return t; t.name = tokenizer.GetNextToken(); (void) tokenizer.GetNextToken(); // "category" field has been removed t.description = tokenizer.GetNextToken(); t.description.Replace(";", "\n"); t.code = tokenizer.GetNextToken(); t.code.Replace(";", "\n"); t.in_menu = (tokenizer.GetNextToken() == "Y"); return t; } // side effect: changes | to / in strings static wxString datatran_to_line(DataTransform& tr) { // don't bother with quoting, what are |'s doing here anyway tr.name.Replace("|", "/"); tr.description.Replace("|", "/"); tr.code.Replace("|", "/"); // The second field is reserved. It used to be "category". wxString s = tr.name + "||" + tr.description + "|" + tr.code + "|" + (tr.in_menu ? "Y" : "N"); s.Replace("\n", ";"); return s; } std::vector EditTransDlg::transforms; EditTransDlg::EditTransDlg (wxWindow* parent, wxWindowID id, ndnd_type const& dd) : wxDialog(parent, id, wxT("Data Transformations"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), ndnd(dd) { init(); } void EditTransDlg::init() { ProportionalSplitter *splitter = new ProportionalSplitter(this, -1, 0.5); // left side of the dialog wxPanel *left_panel = new wxPanel(splitter); wxBoxSizer *left_sizer = new wxBoxSizer(wxVERTICAL); left_sizer->Add(new wxStaticText(left_panel, -1, wxT("Transformations in menu:")), wxSizerFlags().Border(wxLEFT|wxRIGHT|wxTOP)); wxBoxSizer *lh_sizer = new wxBoxSizer(wxHORIZONTAL); trans_list = new wxCheckListBox(left_panel, -1); trans_list->SetMinSize(wxSize(200, -1)); lh_sizer->Add(trans_list, wxSizerFlags(1).Expand().Border()); // buttons on the right of the list wxBoxSizer *lbutton_sizer = new wxBoxSizer(wxVERTICAL); add_btn = new wxButton(left_panel, wxID_ADD); lbutton_sizer->Add(add_btn, wxSizerFlags().Border()); remove_btn = new wxButton(left_panel, wxID_REMOVE); lbutton_sizer->Add(remove_btn, wxSizerFlags().Border()); up_btn = new wxButton(left_panel, wxID_UP); lbutton_sizer->Add(up_btn, wxSizerFlags().Border()); down_btn = new wxButton(left_panel, wxID_DOWN); lbutton_sizer->Add(down_btn, wxSizerFlags().Border()); lh_sizer->Add(lbutton_sizer, wxSizerFlags().Center()); left_sizer->Add(lh_sizer, wxSizerFlags(1).Expand()); left_panel->SetSizerAndFit(left_sizer); // right side of the dialog wxPanel *right_panel = new wxPanel(splitter); wxBoxSizer *right_sizer = new wxBoxSizer(wxVERTICAL); right_sizer->AddSpacer(10); wxBoxSizer *name_sizer = new wxBoxSizer(wxHORIZONTAL); name_sizer->Add(new wxStaticText(right_panel, -1, wxT("Name:")), wxSizerFlags().Border(wxLEFT).Centre()); name_tc = new wxTextCtrl(right_panel, -1, wxEmptyString); name_sizer->Add(name_tc, wxSizerFlags(1).Border()); right_sizer->Add(name_sizer, wxSizerFlags().Expand()); right_sizer->Add(new wxStaticText(right_panel, -1, wxT("Description (optional):")), wxSizerFlags().Border(wxLEFT|wxRIGHT|wxTOP)); description_tc = new wxTextCtrl(right_panel, -1, wxEmptyString, wxDefaultPosition, wxSize(-1, 50), wxTE_MULTILINE); right_sizer->Add(description_tc, wxSizerFlags().Expand().Border()); wxBoxSizer *cl_sizer = new wxBoxSizer(wxHORIZONTAL); cl_sizer->Add(new wxStaticText(right_panel, -1, wxT("Code:")), wxSizerFlags().Border().Center()); wxString help_url = get_help_url(wxT("data.html")) #ifndef __WXMSW__ // wxMSW converts URI back to filename, and it can't handle #fragment + wxT("#data-point-transformations") #endif ; wxHyperlinkCtrl *help_ctrl = new wxHyperlinkCtrl(right_panel, -1, wxT("syntax reference"), help_url); cl_sizer->AddStretchSpacer(); cl_sizer->Add(help_ctrl, wxSizerFlags().Center().Border(wxRIGHT)); right_sizer->Add(cl_sizer, wxSizerFlags().Expand()); code_tc = new wxTextCtrl(right_panel, -1, wxEmptyString, wxDefaultPosition, wxSize(-1, 100), wxTE_MULTILINE|wxHSCROLL|wxVSCROLL); right_sizer->Add(code_tc, wxSizerFlags().Expand().Border(wxLEFT|wxRIGHT|wxBOTTOM)); wxString t = (ndnd.size() == 1 ? wxString::Format(wxT("@%d"), ndnd[0].first) : wxString::Format(wxT("%d datasets"), (int) ndnd.size())); wxSizer *apply_sizer = new wxStaticBoxSizer(wxHORIZONTAL, right_panel, wxT("Apply to ") + t); apply_btn = new wxButton(right_panel, wxID_APPLY); rezoom_btn = new wxButton(right_panel, wxID_ZOOM_FIT); undo_btn = new wxButton(right_panel, wxID_UNDO); undo_btn->SetToolTip(wxT("Read the dataset from file again (if possible)")); apply_sizer->Add(apply_btn, wxSizerFlags().Border()); apply_sizer->Add(rezoom_btn, wxSizerFlags().Border()); apply_sizer->Add(undo_btn, wxSizerFlags().Border()); right_sizer->Add(apply_sizer, wxSizerFlags().Border().Expand()); right_panel->SetSizerAndFit(right_sizer); /* help_btn = new wxButton(left_panel, wxID_HELP); */ splitter->SplitVertProp(left_panel, right_panel); wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); top_sizer->Add(splitter, wxSizerFlags(1).Expand()); top_sizer->Add (new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 10); // buttons at the bottom of the dialog wxBoxSizer *bb_sizer = new wxBoxSizer(wxHORIZONTAL); save_btn = new wxButton(this, wxID_SAVE); bb_sizer->Add(save_btn, wxSizerFlags().Border()); revert_btn = new wxButton(this, wxID_REVERT_TO_SAVED); bb_sizer->Add(revert_btn, wxSizerFlags().Border()); todefault_btn = new wxButton(this, -1, wxT("Restore &to Default")); todefault_btn->SetToolTip(wxT("Load default transformations.")); bb_sizer->Add(todefault_btn, wxSizerFlags().Border()); bb_sizer->AddStretchSpacer(); bb_sizer->Add(new wxButton(this, wxID_CLOSE, wxT("&Close")), wxSizerFlags().Border().Right()); top_sizer->Add(bb_sizer, wxSizerFlags().Expand()); SetSizerAndFit(top_sizer); SetEscapeId(wxID_CLOSE); // workaround for wxMSW 2.5.3 strange problem -- very small dialog window if (GetClientSize().GetHeight() < 200) SetClientSize(500, 500); Centre(); initialize_checklist(); update_right_side(); update_apply_button(); Connect(wxID_ADD, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnAdd)); Connect(wxID_REMOVE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnRemove)); Connect(wxID_UP, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnUp)); Connect(wxID_DOWN, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnDown)); Connect(wxID_SAVE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnSave)); Connect(wxID_REVERT_TO_SAVED, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnRevert)); Connect(todefault_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnToDefault)); Connect(wxID_APPLY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnApply)); Connect(wxID_ZOOM_FIT, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnReZoom)); Connect(wxID_UNDO, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(EditTransDlg::OnUndo)); Connect(name_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(EditTransDlg::OnNameText)); Connect(description_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(EditTransDlg::OnDescText)); Connect(code_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(EditTransDlg::OnCodeText)); Connect(trans_list->GetId(), wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(EditTransDlg::OnListItemSelected)); Connect(trans_list->GetId(), wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler(EditTransDlg::OnListItemToggled)); } void EditTransDlg::read_transforms(bool skip_file) { transforms.clear(); wxTextFile f(get_conf_file("transform")); if (!skip_file && f.Exists() && f.Open()) { for (wxString s = f.GetFirstLine(); !f.Eof(); s = f.GetNextLine()) { DataTransform tr = line_to_datatran(s); if (!tr.name.empty()) transforms.push_back(tr); } } else { int n = sizeof(default_transforms) / sizeof(default_transforms[0]); transforms.reserve(n); for (int i = 0; i != n; ++i) { DataTransform tr = line_to_datatran(default_transforms[i]); transforms.push_back(tr); } } } void EditTransDlg::initialize_checklist() { wxArrayString array; array.Alloc(transforms.size()); for (vector::const_iterator i = transforms.begin(); i != transforms.end(); ++i) array.Add(i->name); trans_list->Set(array); for (size_t i = 0; i != transforms.size(); ++i) trans_list->Check(i, transforms[i].in_menu); } void EditTransDlg::OnAdd(wxCommandEvent&) { wxString name; for (int i = 1; ; ++i) { name.Printf(wxT("transform %d"), i); bool uniq = true; for (vector::const_iterator j = transforms.begin(); j != transforms.end(); ++j) if (j->name == name) { uniq = false; break; } if (uniq) break; } DataTransform new_transform = { name, wxEmptyString, wxEmptyString, false, false }; int pos = trans_list->GetSelection() + 1; transforms.insert(transforms.begin() + pos, new_transform); trans_list->Insert(name, pos); trans_list->SetSelection(pos); update_right_side(); apply_btn->Enable(false); name_tc->SetFocus(); name_tc->SetSelection(-1, -1); } void EditTransDlg::OnRemove(wxCommandEvent&) { int item = trans_list->GetSelection(); if (item == wxNOT_FOUND) return; transforms.erase(transforms.begin() + item); trans_list->Delete(item); trans_list->SetSelection(item > 0 ? item-1 : 0); update_right_side(); } void EditTransDlg::OnUp(wxCommandEvent&) { int item = trans_list->GetSelection(); if (item == wxNOT_FOUND || item == 0) return; swap(transforms[item-1], transforms[item]); trans_list->SetString(item-1, transforms[item-1].name); trans_list->Check(item-1, transforms[item-1].in_menu); trans_list->SetString(item, transforms[item].name); trans_list->Check(item, transforms[item].in_menu); trans_list->SetSelection(item-1); up_btn->Enable(item-1 > 0); down_btn->Enable(true); } void EditTransDlg::OnDown(wxCommandEvent&) { int item = trans_list->GetSelection(); if (item == wxNOT_FOUND || item >= (int) transforms.size() - 1) return; swap(transforms[item], transforms[item+1]); trans_list->SetString(item, transforms[item].name); trans_list->Check(item, transforms[item].in_menu); trans_list->SetString(item+1, transforms[item+1].name); trans_list->Check(item+1, transforms[item+1].in_menu); trans_list->SetSelection(item+1); up_btn->Enable(true); down_btn->Enable(item+1 < (int) trans_list->GetCount() - 1); } void EditTransDlg::OnSave(wxCommandEvent&) { FFile f(get_conf_file("transform"), "w"); if (!f.IsOpened()) { wxMessageBox("Cannot open file" + f.GetName(), "Error", wxOK|wxICON_ERROR); return; } for (vector::iterator i = transforms.begin(); i != transforms.end(); ++i) { i->name.Trim(); if (i->name.empty()) wxMessageBox("A transform without a name will not be saved.", "Warning", wxOK); f.Write(datatran_to_line(*i) + "\n"); i->is_changed = false; } for (size_t i = 0; i != transforms.size(); ++i) { trans_list->SetString(i, transforms[i].name); trans_list->Check(i, transforms[i].in_menu); } } void EditTransDlg::OnRevert(wxCommandEvent&) { read_transforms(false); initialize_checklist(); update_right_side(); } void EditTransDlg::OnToDefault(wxCommandEvent&) { read_transforms(true); initialize_checklist(); update_right_side(); } void EditTransDlg::OnApply(wxCommandEvent&) { string code = wx2s(code_tc->GetValue()); execute_tranform(code); } void EditTransDlg::OnReZoom(wxCommandEvent&) { frame->GViewAll(); } void EditTransDlg::OnUndo(wxCommandEvent& event) { frame->OnDataRevert(event); // TODO: Real undo. This would require additional commands, e.g. // @n.mark, @n.rollback } void EditTransDlg::update_menu_name(int item) { DataTransform& tr = transforms[item]; wxString s = tr.is_changed ? "*" + tr.name : tr.name; trans_list->SetString(item, s); } void EditTransDlg::OnNameText(wxCommandEvent&) { int item = trans_list->GetSelection(); if (item == wxNOT_FOUND) return; transforms[item].name = name_tc->GetValue(); update_menu_name(item); trans_list->Check(item, transforms[item].in_menu); } void EditTransDlg::OnDescText(wxCommandEvent&) { int item = trans_list->GetSelection(); if (item == wxNOT_FOUND) return; transforms[item].description = description_tc->GetValue(); if (!transforms[item].is_changed) { transforms[item].is_changed = true; update_menu_name(item); trans_list->Check(item, transforms[item].in_menu); } } void EditTransDlg::OnCodeText(wxCommandEvent&) { int item = trans_list->GetSelection(); if (item == wxNOT_FOUND) return; update_apply_button(); transforms[item].code = code_tc->GetValue(); if (!transforms[item].is_changed) { transforms[item].is_changed = true; update_menu_name(item); trans_list->Check(item, transforms[item].in_menu); } } void EditTransDlg::OnListItemToggled(wxCommandEvent& event) { int item = event.GetInt(); transforms[item].in_menu = trans_list->IsChecked(item); } void EditTransDlg::execute_tranform(string const& code) { string t = conv_code_to_one_line(code); exec(frame->get_datasets() + t); } bool EditTransDlg::update_apply_button() { string code = wx2s(code_tc->GetValue()); string text = conv_code_to_one_line(code); bool ok = ftk->check_syntax(text); apply_btn->Enable(ok); return ok; } string EditTransDlg::conv_code_to_one_line(string const& code) { string cmd; const char* p = code.c_str(); for (;;) { while(isspace(*p)) ++p; while (*p == '#') { while(*p != '\0' && *p != '\n') ++p; while(isspace(*p)) ++p; } if (*p == '\0') break; const char* start = p; while (*p != '\0' && *p != '#' && *p != '\n') ++p; if (!cmd.empty()) cmd += "; "; cmd += string(start, p); } return cmd; } void EditTransDlg::update_right_side() { int item = trans_list->GetSelection(); if (item == wxNOT_FOUND) { item = 0; trans_list->SetSelection(0); } const DataTransform& dt = transforms[item]; name_tc->ChangeValue(dt.name); description_tc->ChangeValue(dt.description); code_tc->ChangeValue(dt.code); up_btn->Enable(item > 0); down_btn->Enable(item < (int) trans_list->GetCount() - 1); //remove_btn->Enable(item >= 0); apply_btn->Enable(true); } fityk-1.3.1/wxgui/dataedit.h000066400000000000000000000040511302634723100157360ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// EditTransDlg: Data > Edit Transformations #ifndef FITYK_WX_DATAEDIT_H_ #define FITYK_WX_DATAEDIT_H_ #include #include namespace fityk { class Data; } struct DataTransform { wxString name; wxString description; wxString code; bool in_menu; bool is_changed; }; class EditTransDlg : public wxDialog { typedef std::vector > ndnd_type; public: EditTransDlg (wxWindow* parent, wxWindowID id, ndnd_type const& dd); static std::vector const& get_transforms() { return transforms; } static void read_transforms(bool skip_file); static void execute_tranform(std::string const& code); private: static std::vector transforms; ndnd_type ndnd; wxCheckListBox *trans_list; wxTextCtrl *name_tc, *description_tc, *code_tc; wxButton *add_btn, *remove_btn, *up_btn, *down_btn, *save_btn, *revert_btn, *todefault_btn, *apply_btn, *rezoom_btn, *undo_btn/*, *help_btn*/; void OnAdd(wxCommandEvent& event); void OnRemove(wxCommandEvent& event); void OnUp(wxCommandEvent& event); void OnDown(wxCommandEvent& event); void OnSave(wxCommandEvent& event); void OnRevert(wxCommandEvent& event); void OnToDefault(wxCommandEvent& event); void OnApply(wxCommandEvent& event); void OnReZoom(wxCommandEvent& event); void OnUndo(wxCommandEvent&); void OnNameText(wxCommandEvent&); void OnDescText(wxCommandEvent&); void OnCodeText(wxCommandEvent&); void OnListItemSelected(wxCommandEvent&) { update_right_side(); } void OnListItemToggled(wxCommandEvent& event); void init(); void initialize_checklist(); bool update_apply_button(); void update_right_side(); void update_menu_name(int item); static std::string conv_code_to_one_line(std::string const& code); }; #endif // FITYK_WX_DATAEDIT_H_ fityk-1.3.1/wxgui/datatable.cpp000066400000000000000000000241411302634723100164350ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include "datatable.h" #include #include #include #include "frame.h" #include "fityk/data.h" using namespace std; using fityk::Point; using fityk::Data; class BetterGridCellFloatEditor : public wxGridCellFloatEditor { void BeginEdit(int row, int col, wxGrid* grid) { // printf("screenposition1: %d\n", Text()->GetScreenPosition().y); wxGridCellTextEditor::BeginEdit(row, col, grid); // there is a bug in wxGTK: when edition is started, the previously // edited cell is made visible } }; // helper needed by wxGrid class GridTable: public wxGridTableBase { public: GridTable(int data_nr, Data const* data) : wxGridTableBase(), data_nr_(data_nr), data_(data), dataset_str_("@" + S(data_nr_) + ": "), instant_update_(true) { has_last_num_[0] = has_last_num_[1] = has_last_num_[2] = false; } virtual int GetNumberRows() { return get_points().size() + 1; } virtual int GetNumberCols() { return 4; } // this function is used e.g. for control of text overflow, // returning always false should be fine virtual bool IsEmptyCell(int /*row*/, int /*col*/) { return false; } virtual wxString GetValue(int row, int col) { if (col == 0) return GetValueAsBool(row, col) ? wxT("1") : wxT("0"); if (row == GetNumberRows() - 1 && !has_last_num_[col-1]) return wxEmptyString; return wxString::Format((col == 3 ? wxT("%g") : wxT("%.12g")), GetValueAsDouble(row, col)); } // this function is pure virtual in the base class, but is never used virtual void SetValue(int, int, const wxString&) { assert(0); } virtual wxString GetTypeName(int /*row*/, int col) { return col == 0 ? wxGRID_VALUE_BOOL : wxGRID_VALUE_FLOAT; } virtual bool CanGetValueAs(int /*row*/, int col, const wxString& typeName) { return (col == 0 && typeName == wxGRID_VALUE_BOOL) || (col > 0 && typeName == wxGRID_VALUE_STRING); } virtual bool CanSetValueAs(int row, int col, const wxString& typeName) { return typeName == GetTypeName(row, col); } virtual double GetValueAsDouble(int row, int col) { if ((size_t) row > get_points().size()) return 0; const Point &p = get_point(row); switch (col) { case 1: return p.x; case 2: return p.y; case 3: return p.sigma; default: assert(0); return 0.; } } virtual bool GetValueAsBool(int row, int col) { assert(col == 0); if ((size_t) row > get_points().size()) return false; return get_point(row).is_active; } virtual void SetValueAsDouble(int row, int col, double value) { if (row == GetNumberRows() - 1) { update_point(last_point_, col, value); has_last_num_[col-1] = true; if (has_last_num_[0] && has_last_num_[1]) { char buffer[128]; sprintf(buffer, "X[%d]=%.12g, Y[%d]=%.12g, S[%d]=%.12g, A[%d]=%d", row, (double) last_point_.x, row, (double) last_point_.y, row, (double) last_point_.sigma, row, last_point_.is_active); change_value(buffer); if (!instant_update_) local_points_.push_back(last_point_); last_point_ = Point(); has_last_num_[0] = has_last_num_[1] = has_last_num_[2] = false; wxGridTableMessage msg(this, wxGRIDTABLE_NOTIFY_ROWS_APPENDED, 1); GetView()->ProcessTableMessage(msg); } } else { if (value == GetValueAsDouble(row, col)) return; char buffer[32]; switch (col) { case 1: buffer[0] = 'X'; break; case 2: buffer[0] = 'Y'; break; case 3: buffer[0] = 'S'; break; default: assert(0); } sprintf(buffer+1, "[%d]=%.12g", row, value); change_value(buffer); if (!instant_update_) update_point(local_points_[row], col, value); } } virtual void SetValueAsBool(int row, int col, bool value) { assert(col == 0); if (row == GetNumberRows() - 1) { last_point_.is_active = value; return; } char buffer[32]; sprintf(buffer, "A[%d]=%s", row, (value ? "true" : "false")); change_value(buffer); if (!instant_update_) local_points_[row].is_active = value; } virtual wxString GetRowLabelValue(int row) { return wxString::Format(wxT("%i"), row); } virtual wxString GetColLabelValue(int col) { switch (col) { case 0: return wxT(" "); case 1: return wxT("x"); case 2: return wxT("y"); case 3: return wxT("\u03C3"); // sigma default: assert(0); return wxEmptyString; } } vector const& get_points() { return instant_update_ ? data_->points() : local_points_; } Point const& get_point(int row) { vector const& points = get_points(); if (row == (int) points.size()) return last_point_; return points[row]; } void update_point(Point& point, int column, double value) { switch (column) { case 1: point.x = value; break; case 2: point.y = value; break; case 3: point.sigma = value; break; } } void change_value(const char* buffer) { if (instant_update_) exec(dataset_str_ + buffer); else { if (!pending_cmd_.empty()) pending_cmd_ += ", "; pending_cmd_ += buffer; } } void apply_pending_cmd() { if (pending_cmd_.empty()) return; exec(dataset_str_ + pending_cmd_); pending_cmd_.clear(); // when Apply is pressed, the data may need to be sorted if (!instant_update_) local_points_ = data_->points(); } void set_instant_update(bool instant) { if (instant) apply_pending_cmd(); else local_points_ = data_->points(); instant_update_ = instant; } private: int data_nr_; Data const* data_; string dataset_str_; bool instant_update_; string pending_cmd_; vector local_points_; Point last_point_; bool has_last_num_[3]; }; DataTableDlg::DataTableDlg(wxWindow* parent, wxWindowID id, int data_nr, Data* data) : wxDialog(parent, id, wxString::Format(wxT("@%d "), data_nr) + s2wx(data->get_title()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); grid = new wxGrid(this, -1, wxDefaultPosition, wxSize(-1, 400)); grid_table = new GridTable(data_nr, data); grid->SetTable(grid_table, true, wxGrid::wxGridSelectRows); grid->EnableEditing(true); grid->SetColSize(0, 40); grid->SetRowLabelSize(60); // the default render uses %f format, we prefer %g grid->RegisterDataType(wxGRID_VALUE_FLOAT, new wxGridCellStringRenderer, new BetterGridCellFloatEditor); sizer->Add(grid, wxSizerFlags(1).Expand()); cb = new wxCheckBox(this, -1, wxT("update and sort instantly")); sizer->Add(cb, wxSizerFlags().Border()); add_apply_close_buttons(this, sizer); SetEscapeId(wxID_CLOSE); SetSizerAndFit(sizer); // apparently the initial width of wxGrid leaves no space for scrollbar SetClientSize(GetClientSize() + wxSize(20, 0)); cb->SetValue(true); FindWindow(wxID_APPLY)->Enable(false); Connect(cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(DataTableDlg::OnUpdateCheckBox)); Connect(wxID_APPLY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DataTableDlg::OnApply)); #if !wxCHECK_VERSION(2, 9, 0) # define wxEVT_GRID_CELL_CHANGED wxEVT_GRID_CELL_CHANGE #endif Connect(grid->GetId(), wxEVT_GRID_CELL_CHANGED, wxGridEventHandler(DataTableDlg::OnCellChanged)); Connect(grid->GetId(), wxEVT_GRID_CELL_RIGHT_CLICK, wxGridEventHandler(DataTableDlg::OnCellRightClick)); Connect(wxID_COPY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DataTableDlg::OnCopy)); Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(DataTableDlg::OnKeyDown)); } void DataTableDlg::OnApply(wxCommandEvent&) { grid_table->apply_pending_cmd(); grid->ForceRefresh(); } void DataTableDlg::OnUpdateCheckBox(wxCommandEvent& event) { bool checked = event.IsChecked(); grid_table->set_instant_update(checked); FindWindow(wxID_APPLY)->Enable(!checked); } void DataTableDlg::OnCellChanged(wxGridEvent& event) { if (event.GetCol() == 1 && cb->GetValue()) // order of items can be changed grid->ForceRefresh(); } void DataTableDlg::OnCellRightClick(wxGridEvent& event) { wxMenu menu; menu.Append(wxID_COPY); if (!grid->IsSelection()) menu.Enable(wxID_COPY, false); PopupMenu(&menu, event.GetPosition()); } void DataTableDlg::Copy() { if (!grid->IsSelection()) return; wxString data; wxArrayInt sel = grid->GetSelectedRows(); for (size_t i=0; i < sel.GetCount(); ++i) { if (i != 0) data += "\n"; int row = sel.Item(i); data += grid->GetCellValue(row, 1) + "\t" + grid->GetCellValue(row, 2) + "\t" + grid->GetCellValue(row, 3); } if (wxTheClipboard->Open()) { wxTheClipboard->SetData(new wxTextDataObject(data)); wxTheClipboard->Close(); } } void DataTableDlg::OnKeyDown(wxKeyEvent& event) { if (event.GetUnicodeKey() == 'C' && event.ControlDown()) Copy(); event.Skip(); } fityk-1.3.1/wxgui/datatable.h000066400000000000000000000016221302634723100161010ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// DataTableDlg: Data > Table dialog #ifndef FITYK_WX_DATATABLE_H_ #define FITYK_WX_DATATABLE_H_ #include namespace fityk { class Data; } class GridTable; class wxGrid; class wxGridEvent; class wxCheckBox; class DataTableDlg : public wxDialog { friend class GridTable; public: DataTableDlg(wxWindow* parent, wxWindowID id, int data_nr, fityk::Data* data); private: GridTable *grid_table; wxGrid* grid; wxCheckBox *cb; void OnApply(wxCommandEvent& event); void OnUpdateCheckBox(wxCommandEvent& event); void OnCellChanged(wxGridEvent& event); void OnCellRightClick(wxGridEvent& event); void OnCopy(wxCommandEvent&) { Copy(); } void Copy(); void OnKeyDown(wxKeyEvent& event); }; #endif // FITYK_WX_DATATABLE_H_ fityk-1.3.1/wxgui/defmgr.cpp000066400000000000000000000224601302634723100157620ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Definition Manager Dialog (DefinitionMgrDlg) #include #include #include #include "defmgr.h" #include "cmn.h" //s2wx, wx2s #include "frame.h" // ftk #include "app.h" // get_help_url() #include "fityk/logic.h" #include "fityk/func.h" #include "fityk/lexer.h" #include "fityk/udf.h" #include "fityk/guess.h" //Guess::Kind using namespace std; using fityk::Tplate; DefinitionMgrDlg::DefinitionMgrDlg(wxWindow* parent) : wxDialog(parent, -1, wxT("Function Definition Manager"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), selected_(-1), parser_(ftk) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *lb_sizer = new wxBoxSizer(wxVERTICAL); lb = new wxListBox(this, -1, wxDefaultPosition, wxDefaultSize, 0, 0, wxLB_SINGLE); lb_sizer->Add(lb, 1, wxEXPAND|wxALL, 5); wxBoxSizer *ar_sizer = new wxBoxSizer(wxHORIZONTAL); wxButton* add_btn = new wxButton(this, wxID_ADD); ar_sizer->Add(add_btn, 0, wxALL|wxALIGN_CENTER, 5); remove_btn = new wxButton(this, wxID_REMOVE); ar_sizer->Add(remove_btn, 0, wxALL|wxALIGN_CENTER, 5); lb_sizer->Add(ar_sizer, 0, wxEXPAND); hsizer->Add(lb_sizer, 0, wxEXPAND); wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL); def_label_st = new wxStaticText(this, -1, wxT("definition:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE); vsizer->Add(def_label_st, 0, wxEXPAND|wxALL, 5); def_tc = new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); vsizer->Add(def_tc, 1, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5); desc_tc = new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY); wxBoxSizer *link_sizer = new wxBoxSizer(wxHORIZONTAL); link_sizer->Add(new wxStaticText(this, -1, wxT("Description:")), 0); link_sizer->AddStretchSpacer(); base_url_ = get_help_url("model.html"); link = new wxHyperlinkCtrl(this, -1, "documentation", base_url_); link_sizer->Add(link, 0); vsizer->Add(link_sizer, 0, wxALL|wxEXPAND, 5); vsizer->Add(desc_tc, 1, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5); desc_tc->SetBackgroundColour(GetBackgroundColour()); hsizer->Add(vsizer, 1, wxEXPAND); top_sizer->Add(hsizer, 1, wxEXPAND); top_sizer->Add(new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 5); top_sizer->Add(CreateButtonSizer (wxOK|wxCANCEL), 0, wxALL|wxALIGN_CENTER, 5); SetSizerAndFit(top_sizer); SetSize(560, 512); // fill functions list lb->Clear(); modified_.clear(); modified_.reserve(ftk->get_tpm()->tpvec().size()); v_foreach (Tplate::Ptr, i, ftk->get_tpm()->tpvec()) { lb->Append(s2wx((*i)->name)); modified_.push_back(**i); } Connect(def_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(DefinitionMgrDlg::OnDefChanged)); Connect(wxID_ADD, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DefinitionMgrDlg::OnAddButton)); Connect(wxID_REMOVE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DefinitionMgrDlg::OnRemoveButton)); Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DefinitionMgrDlg::OnOk)); Connect(lb->GetId(), wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(DefinitionMgrDlg::OnFunctionChanged)); ok_btn = (wxButton*) FindWindow(wxID_OK); lb->SetSelection(0); select_function(); } void DefinitionMgrDlg::parse_definition() { assert(selected_ >= 0 && selected_ < (int) modified_.size()); assert(modified_.size() == lb->GetCount()); Tplate& tp = modified_[selected_]; if (tp.is_coded()) return; string value = wx2s(def_tc->GetValue().Trim()); if (value.empty()) { desc_tc->Clear(); if (lb->GetString(selected_) != wxT("-")) lb->SetString(selected_, wxT("-")); ok_btn->Enable(false); return; } try { fityk::Lexer lex(value.c_str()); tp = *parser_.parse_define_args(lex); update_desc(tp); // We check if SetString() is needed, because on wxGTK 2.8 // the program crashed when pressing PgDown or PgUp in the listbox, // and these checks helped to avoid crashes. Now parse_definition() // is not called from the listbox selection event, so it should not // matter, but the checks are left just in case. if (lb->GetString(selected_) != s2wx(tp.name)) lb->SetString(selected_, s2wx(tp.name)); } catch (exception &e) { desc_tc->ChangeValue(pchar2wx(e.what())); if (lb->GetString(selected_) != wxT("-")) lb->SetString(selected_, wxT("-")); } bool all_ok = (lb->FindString(wxT("-")) == wxNOT_FOUND); ok_btn->Enable(all_ok); } void DefinitionMgrDlg::update_desc(const Tplate& tp) { wxString desc = wxString::Format(wxT("%d args:"), (int)tp.fargs.size()); v_foreach (string, i, tp.fargs) desc += wxT(" ") + s2wx(*i); desc += "\ntraits:"; bool has_traits = false; if (tp.traits & Tplate::kLinear) { desc += " linear"; has_traits = true; } if (tp.traits & Tplate::kPeak) { if (has_traits) desc += " +"; desc += " peak"; has_traits = true; } if (tp.traits & Tplate::kSigmoid) { if (has_traits) desc += " +"; desc += " sigmoid"; has_traits = true; } if (!has_traits) desc += " none"; desc += "\nused by:"; bool used = false; v_foreach (Tplate::Ptr, i, ftk->get_tpm()->tpvec()) v_foreach (Tplate::Component, c, (*i)->components) if (c->p && c->p->name == tp.name) { desc += wxT(" ") + s2wx((*i)->name); used = true; break; // don't report the same tplate twice } v_foreach (fityk::Function*, i, ftk->mgr.functions()) if ((*i)->tp()->name == tp.name) { desc += " %" + s2wx((*i)->name); used = true; } if (!used) desc += wxT(" -"); desc_tc->ChangeValue(desc); } void DefinitionMgrDlg::select_function() { int n = lb->GetSelection(); if (n == selected_) return; if (n == wxNOT_FOUND) { lb->SetSelection(selected_); return; } if (selected_ != wxNOT_FOUND) { const Tplate& old = modified_[selected_]; wxString name = old.rhs.empty() ? wxString(wxT("-")) : s2wx(old.name); if (lb->GetString(selected_) != name) lb->SetString(selected_, name); } selected_ = n; const Tplate& tp = modified_[n]; Tplate::Ptr orig_ptr = ftk->get_tpm()->get_shared_tp(tp.name); // minimal use_count() is 2: this pointer and the one in TplateMgr::tpvec_ bool used = (orig_ptr.use_count() > 2); def_tc->ChangeValue(s2wx(tp.as_formula())); def_tc->SetEditable(!tp.is_coded() && !used); def_label_st->SetLabel(tp.is_coded() ? wxT("definition (equivalent):") : wxT("definition:")); remove_btn->Enable(!used); link->Enable(tp.docs_fragment != NULL); if (tp.docs_fragment != NULL) // wxMSW converts URI back to filename, and it can't handle #fragment #ifndef __WXMSW__ link->SetURL(base_url_ + "#" + tp.docs_fragment); #else link->SetURL(base_url_); #endif else link->SetURL("no docs for " + s2wx(tp.name)); update_desc(tp); } vector DefinitionMgrDlg::get_commands() { vector ss; v_foreach (Tplate::Ptr, i, ftk->get_tpm()->tpvec()) { bool found = false; v_foreach (Tplate, j, modified_) { if ((*i)->name == j->name) { found = true; break; } } if (!found) ss.push_back("undefine " + (*i)->name); } v_foreach (Tplate, i, modified_) { bool need_define = true; v_foreach (Tplate::Ptr, j, ftk->get_tpm()->tpvec()) { if (i->name == (*j)->name) { if (i->fargs == (*j)->fargs && i->defvals == (*j)->defvals && i->rhs == (*j)->rhs) need_define = false; else ss.push_back("undefine " + i->name); break; } } if (need_define) ss.push_back("define " + i->as_formula()); } return ss; } void DefinitionMgrDlg::OnAddButton(wxCommandEvent &) { Tplate tp; tp.create = NULL; modified_.push_back(tp); lb->Append(wxT("-")); lb->SetSelection(lb->GetCount() - 1); select_function(); def_tc->SetFocus(); } void DefinitionMgrDlg::OnRemoveButton(wxCommandEvent &) { if (!is_index(selected_, modified_)) return; modified_.erase(modified_.begin() + selected_); lb->Delete(selected_); if (modified_.empty()) return; lb->SetSelection(selected_ > 0 ? selected_ - 1 : 0); selected_ = -1; select_function(); } void DefinitionMgrDlg::OnOk(wxCommandEvent&) { if (lb->FindString(wxT("new")) != wxNOT_FOUND) return; EndModal(wxID_OK); } fityk-1.3.1/wxgui/defmgr.h000066400000000000000000000020461302634723100154250ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_DEFMGR_H_ #define FITYK_WX_DEFMGR_H_ #include #include #include "fityk/func.h" #include "fityk/cparser.h" class wxHyperlinkCtrl; class DefinitionMgrDlg : public wxDialog { public: DefinitionMgrDlg(wxWindow* parent); void OnFunctionChanged(wxCommandEvent &) { select_function(); } void OnDefChanged(wxCommandEvent &) { parse_definition(); } void OnAddButton(wxCommandEvent &); void OnRemoveButton(wxCommandEvent &); void OnOk(wxCommandEvent &event); std::vector get_commands(); private: int selected_; wxString base_url_; std::vector modified_; fityk::Parser parser_; wxListBox *lb; wxTextCtrl *def_tc, *desc_tc; wxStaticText *def_label_st; wxButton *remove_btn, *ok_btn; wxHyperlinkCtrl *link; void select_function(); void parse_definition(); void update_desc(const fityk::Tplate& tp); }; #endif fityk-1.3.1/wxgui/dload.cpp000066400000000000000000000121501302634723100155740ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Custom Data Load Dialog (DLoadDlg) and helpers #include #include #include #include #include #include "dload.h" #include "xybrowser.h" #include "frame.h" // frame->add_recent_data_file() #include "fityk/logic.h" // ftk->get_settings() #include "fityk/settings.h" #include "fityk/data.h" // get_file_basename() #include "fityk/common.h" using namespace std; using fityk::Data; /// data_idx - data slot to be used by "Replace ..." button, -1 means none /// data - used for default settings (path, columns, etc.), not NULL DLoadDlg::DLoadDlg(wxWindow* parent, int data_idx, Data* data, const wxString& dir) : wxDialog(parent, wxID_ANY, wxT("Load Data"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), data_idx_(data_idx) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); browser_ = new XyFileBrowser(this); top_sizer->Add(browser_, 1, wxEXPAND); top_sizer->Add(new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 5); wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); wxString repl = "&Replace @" + s2wx(data_idx >= 0 ? S(data_idx) : S("?")); open_here_btn_ = new wxButton(this, -1, repl); if (data_idx < 0) open_here_btn_->Enable(false); open_new_btn_ = new wxButton(this, -1, wxT("&Open in new slot")); button_sizer->Add(open_here_btn_, 0, wxALL, 5); button_sizer->Add(open_new_btn_, 0, wxALL, 5); button_sizer->Add(new wxButton(this, wxID_CLOSE, wxT("&Close")), 0, wxALL, 5); top_sizer->Add(button_sizer, 0, wxALL|wxALIGN_CENTER, 0); SetSizerAndFit(top_sizer); SetSize(wxSize(700, 600)); SetEscapeId(wxID_CLOSE); wxFileName path; if (!data->get_filename().empty()) browser_->filectrl->SetPath(s2wx(data->get_filename())); else browser_->filectrl->SetDirectory(dir); browser_->update_file_options(); if (data->get_given_x() != fityk::LoadSpec::NN) browser_->x_column->SetValue(data->get_given_x()); if (data->get_given_y() != fityk::LoadSpec::NN) browser_->y_column->SetValue(data->get_given_y()); if (data->get_given_s() != fityk::LoadSpec::NN) { browser_->std_dev_b->SetValue(true); browser_->s_column->SetValue(data->get_given_s()); } else if (S(ftk->get_settings()->default_sigma) == "sqrt") { browser_->sd_sqrt_rb->SetValue(true); } else { browser_->sd_1_rb->SetValue(true); } browser_->update_s_column(); Connect(open_here_btn_->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DLoadDlg::OnOpenHere)); Connect(open_new_btn_->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DLoadDlg::OnOpenNew)); } void DLoadDlg::exec_command(bool replace) { string cols; int x = browser_->x_column->GetValue(); int y = browser_->y_column->GetValue(); bool has_s = browser_->std_dev_b->GetValue(); int sig = browser_->s_column->GetValue(); int b = browser_->block_ch->GetSelection(); // default parameter values are not passed explicitely if (x != 1 || y != 2 || has_s || b != 0) { cols = ":" + S(x) + ":" + S(y) + ":"; if (has_s) cols += S(sig); cols += ":"; if (b != 0) cols += S(b); } string with_options; if (!has_s) { bool default_sqrt = (S(ftk->get_settings()->default_sigma) == "sqrt"); bool set_sqrt = browser_->sd_sqrt_rb->GetValue(); if (set_sqrt != default_sqrt) { if (set_sqrt) with_options = "with default_sigma=sqrt "; else with_options = "with default_sigma=one "; } } wxArrayString paths; browser_->filectrl->GetPaths(paths); string trailer; string lua_trailer; string fmt = browser_->get_filetype(); if (fmt != "" || browser_->comma_cb->GetValue()) { trailer = " " + (fmt == "" ? "_" : fmt); lua_trailer = ", '" + fmt + "'"; if (browser_->comma_cb->GetValue()) { trailer += " decimal_comma"; lua_trailer += ", 'decimal_comma'"; } } for (size_t i = 0; i < paths.GetCount(); ++i) { string cmd; if (paths[i].Find('\'') == wxNOT_FOUND) cmd = "@" + (replace ? S(data_idx_) : S("+")) + " < '" + wx2s(paths[i]) + cols + "'" + trailer; else // very special case cmd = "lua F:load(" + S(replace ? data_idx_ : -1) + ", [[" + wx2s(paths[i]) + "]], " + S(b) + ", " + S(x) + ", " + S(y) + ", " + S(sig) + lua_trailer + ")"; exec(with_options + cmd); wxString title = browser_->title_tc->GetValue().Trim(); if (!title.empty() && title != browser_->auto_title_) { int slot = (replace ? data_idx_ : ftk->dk.count() - 1); exec("@" + S(slot) + ": title = '" + wx2s(title) + "'"); } frame->add_recent_data_file(paths[i]); } } fityk-1.3.1/wxgui/dload.h000066400000000000000000000013041302634723100152400ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_DLOAD_H_ #define FITYK_WX_DLOAD_H_ namespace fityk { class Data; } class XyFileBrowser; class DLoadDlg : public wxDialog { public: DLoadDlg(wxWindow* parent, int data_idx, fityk::Data* data, const wxString& dir); private: int data_idx_; XyFileBrowser* browser_; wxButton *open_here_btn_, *open_new_btn_; std::string get_command(std::string const& ds, int d_nr); void OnOpenHere(wxCommandEvent&) { exec_command(true); } void OnOpenNew(wxCommandEvent&) { exec_command(false); } void exec_command(bool replace); }; #endif fityk-1.3.1/wxgui/drag.cpp000066400000000000000000000116411302634723100154320ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// DraggedFunc - used for dragging function in MainPlot #include "drag.h" #include "fityk/func.h" #include "fityk/tplate.h" #include "fityk/mgr.h" #include "fityk/common.h" // for index_of_element, eS, etc using namespace std; using namespace fityk; static int find_parameter_with_name(const Tplate& tp, const string& name) { // search for Function(..., height, ...) int idx = index_of_element(tp.fargs, name); if (idx == -1) { const vector& defvals = tp.defvals; // search for Function(..., foo=height, ...) idx = index_of_element(defvals, name); // search for Function(..., foo=height*..., ...) if (idx == -1) { v_foreach (string, i, defvals) if (startswith(*i, name+"*")) { idx = i - defvals.begin(); //string mult = defvals.substr(name.size()+1); //double extra_multiplier = TODO(parse mult) break; } } } return idx; } static bool bind_param(const ModelManager& mgr, DraggedFunc::Drag &drag, const string& name, const Function* p, DraggedFunc::DragType how, double multiplier=1.) { int idx = find_parameter_with_name(*p->tp(), name); if (idx == -1) return false; const Variable* var = mgr.get_variable(p->used_vars().get_idx(idx)); if (var->is_simple()) { drag.how = how; drag.parameter_idx = idx; drag.parameter_name = p->get_param(idx); drag.variable_name = p->used_vars().get_name(idx); drag.value = drag.ini_value = p->av()[idx]; drag.multiplier = multiplier; drag.ini_x = 0.; } else { drag.how = DraggedFunc::no_drag; } return true; } void DraggedFunc::start(const Function* p, int X, int Y, double x, double y, DraggedFuncObserver* callback) { callback_ = callback; drag_x_.how = drag_y_.how = drag_shift_x_.how = drag_shift_y_.how = no_drag; drag_x_.parameter_name = drag_y_.parameter_name = drag_shift_x_.parameter_name = drag_shift_y_.parameter_name = "-"; bind_param(mgr_, drag_x_, "center", p, absolute_value) || bind_param(mgr_, drag_x_, "xmid", p, absolute_value); bind_param(mgr_, drag_y_, "height", p, absolute_value) || bind_param(mgr_, drag_y_, "area", p, relative_value) || bind_param(mgr_, drag_y_, "avgy", p, absolute_value) || bind_param(mgr_, drag_y_, "intercept", p, absolute_value) || bind_param(mgr_, drag_y_, "upper", p, absolute_value); bind_param(mgr_, drag_shift_x_, "hwhm", p, absolute_value) || bind_param(mgr_, drag_shift_x_, "fwhm", p, absolute_value, 2.) || bind_param(mgr_, drag_shift_x_, "wsig", p, absolute_value, 1.); bind_param(mgr_, drag_shift_y_, "lower", p, absolute_value); status_ = "Move to change: " + drag_x_.parameter_name + "/" + drag_y_.parameter_name + ", with [Shift]: " + drag_shift_x_.parameter_name + "/" + drag_shift_y_.parameter_name; pX_ = X; pY_ = Y; px_ = x; py_ = y; } void DraggedFunc::move(bool shift, int X, int Y, double x, double y) { Drag &hor = shift ? drag_shift_x_ : drag_x_; change_value(&hor, x, x - px_, X - pX_); pX_ = X; px_ = x; Drag &vert = shift ? drag_shift_y_ : drag_y_; change_value(&vert, y, y - py_, Y - pY_); pY_ = Y; py_ = y; } void DraggedFunc::change_value(Drag *drag, double x, double dx, int dX) { if (dx == 0. || dX == 0) return; switch (drag->how) { case no_drag: return; case relative_value: if (drag->ini_x == 0.) { drag->ini_x = x - dx; if (is_zero(drag->ini_x)) drag->ini_x += dx; } //drag->value += dx * fabs(value / x) * multiplier; drag->value = x / drag->ini_x * drag->ini_value; break; case absolute_value: drag->value += dx * drag->multiplier; break; case absolute_pixels: drag->value += dX * drag->multiplier; break; } callback_->change_parameter_value(drag->parameter_idx, drag->value); has_changed_ = true; } void DraggedFunc::stop() { drag_x_.how = drag_y_.how = drag_shift_x_.how = drag_shift_y_.how = no_drag; has_changed_ = false; } string DraggedFunc::get_cmd() const { const Drag* drags[] = { &drag_x_, &drag_y_, &drag_shift_x_, &drag_shift_y_, NULL }; string cmd; for (const Drag **d = drags; *d != NULL; ++d) { const Drag& drag = **d; if (drag.how != no_drag && drag.value != drag.ini_value) { if (!cmd.empty()) cmd += "; "; cmd += "$" + drag.variable_name + " = ~" + eS(drag.value); } } return cmd; } fityk-1.3.1/wxgui/drag.h000066400000000000000000000035641302634723100151040ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// DraggedFunc - used for dragging function in MainPlot #ifndef FITYK_WX_FDRAG_H_ #define FITYK_WX_FDRAG_H_ #include namespace fityk { class Function; class ModelManager; } class DraggedFuncObserver { public: virtual ~DraggedFuncObserver() {} virtual void change_parameter_value(int idx, double value) = 0; }; class DraggedFunc { public: enum DragType { no_drag, relative_value, //eg. for area absolute_value, //eg. for width absolute_pixels }; struct Drag { DragType how; int parameter_idx; std::string parameter_name; std::string variable_name; /// name of variable that are to be changed double value; /// current value of parameter double ini_value; /// initial value of parameter double multiplier; /// increases or decreases changing rate double ini_x; Drag() : how(no_drag) {} }; DraggedFunc(const fityk::ModelManager& mgr) : mgr_(mgr), has_changed_(false) {} void start(const fityk::Function* p, int X, int Y, double x, double y, DraggedFuncObserver* callback); void move(bool shift, int X, int Y, double x, double y); void stop(); const std::string& status() const { return status_; } bool has_changed() { return has_changed_; } std::string get_cmd() const; private: const fityk::ModelManager& mgr_; DraggedFuncObserver* callback_; Drag drag_x_; ///for horizontal dragging (x axis) Drag drag_y_; /// y axis Drag drag_shift_x_; ///x with [shift] Drag drag_shift_y_; ///y with [shift] double px_, py_; int pX_, pY_; std::string status_; bool has_changed_; void change_value(Drag *drag, double x, double dx, int dX); }; #endif fityk-1.3.1/wxgui/editor.cpp000066400000000000000000000402701302634723100160030ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Script Editor and Debugger (EditorDlg) #include #include "editor.h" #include "frame.h" //ftk, exec() #include "fityk/logic.h" #include "fityk/luabridge.h" #include "img/exec_selected.xpm" #include "img/exec_down.xpm" #include "img/save.xpm" #include "img/save_as.xpm" #include "img/close.xpm" #include #ifdef __WXOSX_CARBON__ #include #define wxToolBar wxButtonToolBar #endif using namespace std; enum { ID_SE_EXEC = 28300, ID_SE_STEP , ID_SE_SAVE , ID_SE_SAVE_AS , ID_SE_CLOSE , ID_SE_EDITOR }; BEGIN_EVENT_TABLE(EditorDlg, wxDialog) EVT_TOOL(ID_SE_EXEC, EditorDlg::OnExec) EVT_TOOL(ID_SE_STEP, EditorDlg::OnStep) EVT_TOOL(ID_SE_SAVE, EditorDlg::OnSave) EVT_TOOL(ID_SE_SAVE_AS, EditorDlg::OnSaveAs) EVT_TOOL(ID_SE_CLOSE, EditorDlg::OnButtonClose) #if wxUSE_STC EVT_STC_CHANGE(ID_SE_EDITOR, EditorDlg::OnTextChange) #endif EVT_CLOSE(EditorDlg::OnCloseDlg) END_EVENT_TABLE() // compare with // http://sourceforge.net/p/scintilla/scite/ci/default/tree/src/lua.properties // http://git.geany.org/geany/tree/data/filetypes.lua static const char* kLuaMostOfKeywords = "and break do else elseif end for function goto if in local not" " or repeat return then until while"; static const char* kLuaValueKeywords = "false nil true"; // constants and functions static const char* kLuaFunctions = "_G _VERSION _ENV " " assert collectgarbage dofile error getmetatable ipairs load loadfile" " next pairs pcall print rawequal rawget rawlen rawset require" " select setmetatable tonumber tostring type xpcall" " bit32.arshift bit32.band bit32.bnot bit32.bor bit32.btest bit32.bxor" " bit32.extract bit32.lrotate bit32.lshift bit32.replace bit32.rrotate" " bit32.rshift" " coroutine.create coroutine.resume coroutine.running" " coroutine.status coroutine.wrap coroutine.yield" " debug.debug debug.getfenv debug.gethook debug.getinfo debug.getlocal" " debug.getmetatable debug.getregistry debug.getupvalue" " debug.getuservalue debug.setfenv debug.sethook debug.setlocal" " debug.setmetatable debug.setupvalue debug.setuservalue debug.traceback" " debug.upvalueid debug.upvaluejoin " " io.close io.flush io.input io.lines io.open io.output io.popen io.read" " io.stderr io.stdin io.stdout io.tmpfile io.type io.write" " math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos" " math.cosh math.deg math.exp math.floor math.fmod math.frexp math.huge" " math.ldexp math.log math.log10 math.max math.min math.modf math.pi" " math.pow math.rad math.random math.randomseed math.sin math.sinh" " math.sqrt math.tan math.tanh" " os.clock os.date os.difftime os.execute os.exit os.getenv os.remove" " os.rename os.setlocale os.time os.tmpname" " package.config package.cpath package.loaded package.loadlib package.path" " package.preload package.searchers package.searchpath" " string.byte string.char string.dump string.find" " string.format string.gmatch string.gsub string.len string.lower" " string.match string.rep string.reverse string.sub string.upper" " table.concat table.insert table.maxn table.pack table.remove" " table.sort table.unpack"; static const char* kLuaMethods = "close flush lines read seek setvbuf write" " byte find format gmatch gsub len lower match rep reverse sub upper"; static const char* kLuaTableF = "F:add_point F:all_functions F:all_parameters F:all_variables" " F:calculate_expr F:execute F:get_components" " F:get_covariance_matrix F:get_data F:get_dataset_count" " F:get_default_dataset F:get_dof F:get_function F:get_info" " F:get_model_value F:get_option_as_number F:get_option_as_string" " F:get_parameter_count F:get_rsquared F:get_ssr F:get_variable" " F:get_view_boundary F:get_wssr F:input F:load_data F:out" " F:set_option_as_number F:set_option_as_string"; #if wxUSE_STC class FitykEditor : public wxStyledTextCtrl { public: FitykEditor(wxWindow* parent, wxWindowID id) : wxStyledTextCtrl(parent, id) { SetMarginType(0, wxSTC_MARGIN_NUMBER); SetMarginWidth(0, 32); SetUseVerticalScrollBar(true); #ifdef __WXMAC__ const int font_size = 13; #else const int font_size = 11; #endif wxFont mono(wxFontInfo(font_size).Family(wxFONTFAMILY_TELETYPE)); StyleSetFont(wxSTC_STYLE_DEFAULT, mono); SetIndent(2); SetUseTabs(false); SetTabIndents(true); SetBackSpaceUnIndents(true); AutoCompSetAutoHide(false); AutoCompSetCancelAtStart(false); SetIndentationGuides(3 /*SC_IV_LOOKBOTH*/); wxFont bold(StyleGetFont(wxSTC_STYLE_DEFAULT).Bold()); StyleSetFont(wxSTC_STYLE_BRACELIGHT, bold); StyleSetForeground(wxSTC_STYLE_BRACELIGHT, wxColour(0, 0, 255)); StyleSetFont(wxSTC_STYLE_BRACEBAD, bold); StyleSetForeground(wxSTC_STYLE_BRACEBAD, wxColour(144, 0, 0)); Connect(wxID_ANY, wxEVT_STC_CHARADDED, wxStyledTextEventHandler(FitykEditor::OnCharAdded)); Connect(wxID_ANY, wxEVT_STC_UPDATEUI, wxStyledTextEventHandler(FitykEditor::OnUpdateUI)); } void set_filetype(bool lua) { wxColour comment_col(10, 150, 10); if (lua) { // use similar colors as in Lua wiki SetLexer(wxSTC_LEX_LUA); //SetProperty("fold", "1"); StyleSetForeground(wxSTC_LUA_COMMENT, comment_col); StyleSetForeground(wxSTC_LUA_COMMENTLINE, comment_col); StyleSetForeground(wxSTC_LUA_COMMENTDOC, comment_col); wxColour string_col(0, 144, 144); StyleSetForeground(wxSTC_LUA_STRING, string_col); StyleSetForeground(wxSTC_LUA_CHARACTER, string_col); StyleSetForeground(wxSTC_LUA_LITERALSTRING, string_col); StyleSetForeground(wxSTC_LUA_NUMBER, wxColour(32, 80, 96)); SetKeyWords(0, kLuaMostOfKeywords); wxFont bold(StyleGetFont(wxSTC_STYLE_DEFAULT).Bold()); StyleSetFont(wxSTC_LUA_WORD, bold); StyleSetForeground(wxSTC_LUA_WORD, wxColour(0, 0, 128)); SetKeyWords(1, kLuaValueKeywords); StyleSetForeground(wxSTC_LUA_WORD2, wxColour(0, 0, 128)); SetKeyWords(2, kLuaFunctions); StyleSetForeground(wxSTC_LUA_WORD3, wxColour(144, 0, 144)); SetKeyWords(3, kLuaMethods); StyleSetForeground(wxSTC_LUA_WORD4, wxColour(144, 0, 144)); SetKeyWords(4, "F"); StyleSetFont(wxSTC_LUA_WORD5, bold); } else { // actually we set filetype to apache config, but since // we only customize colors of comments it works fine. SetLexer(wxSTC_LEX_CONF); StyleSetForeground(wxSTC_CONF_COMMENT, comment_col); } } void OnCharAdded(wxStyledTextEvent& event) { // auto-indentation (the same as previous line) if (event.GetKey() == '\n') { int line = GetCurrentLine(); if (line > 0) { // just in case int indent = GetLineIndentation(line-1); if (indent > 0) { SetLineIndentation(line, indent); LineEnd(); } } } // auto-completion if (GetLexer() == wxSTC_LEX_LUA && !AutoCompActive()) LuaAutocomp(); } void LuaAutocomp() { int pos = GetCurrentPos() - 1; // GetCurrentPos() returns if (pos < 1) return; char key = GetCharAt(pos); if (key == ':' && GetStyleAt(pos-1) == wxSTC_LUA_WORD5) { // wxSTC_LUA_WORD5 is only "F", so other checks are redundant: // GetCharAt(pos-1) == 'F' && // WordStartPosition(pos-1, true) == pos-1) AutoCompShow(2, kLuaTableF); } else if (key == '.' && GetStyleAt(pos-1) == wxSTC_LUA_IDENTIFIER) { int start = WordStartPosition(pos-1, true); wxString word = GetTextRange(start, pos); if (word == "bit32" || word == "coroutine" || word == "debug" || word == "io" || word == "math" || word == "os" || word == "package" || word == "string" || word == "table") { AutoCompShow(pos-start+1, kLuaFunctions); } } } void OnUpdateUI(wxStyledTextEvent&) { const char* braces = "(){}[]"; int p = GetCurrentPos(); int brace_pos = -1; if (p > 1 && strchr(braces, GetCharAt(p-1))) brace_pos = p - 1; else if (strchr(braces, GetCharAt(p))) brace_pos = p; if (brace_pos != -1) { int match_pos = BraceMatch(brace_pos); if (match_pos == wxSTC_INVALID_POSITION) BraceBadLight(brace_pos); else BraceHighlight(brace_pos, match_pos); } else { BraceBadLight(wxSTC_INVALID_POSITION); // remove brace light } } }; #else class FitykEditor : public wxTextCtrl { public: FitykEditor(wxWindow* parent, wxWindowID id) : wxTextCtrl(parent, id, "", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH) {} void set_filetype(bool) {} int GetCurrentLine() const { long x, y; PositionToXY(GetInsertionPoint(), &x, &y); return y; } void GotoLine(int line) { SetInsertionPoint(ed_->XYToPosition(0, line)); } }; #endif EditorDlg::EditorDlg(wxWindow* parent) : wxDialog(parent, -1, wxT(""), wxDefaultPosition, wxSize(600, 500), wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), lua_file_(false) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); tb_ = new wxToolBar(this, -1, wxDefaultPosition, wxDefaultSize, wxTB_TEXT | wxTB_HORIZONTAL | wxNO_BORDER); tb_->SetToolBitmapSize(wxSize(24, 24)); tb_->AddTool(ID_SE_EXEC, wxT("Execute"), wxBitmap(exec_selected_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Execute all or selected lines")); tb_->AddTool(ID_SE_STEP, wxT("Step"), wxBitmap(exec_down_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Execute line and go to the next line")); tb_->AddSeparator(); tb_->AddTool(ID_SE_SAVE, wxT("Save"), wxBitmap(save_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Save to file")); tb_->AddTool(ID_SE_SAVE_AS, wxT("Save as"), wxBitmap(save_as_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Save a copy to file")); #if 0 tb_->AddSeparator(); tb_->AddTool(wxID_UNDO, wxT("Undo"), wxBitmap(undo_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Undo"), wxT("Undo the last edit")); tb_->AddTool(wxID_REDO, wxT("Redo"), wxBitmap(redo_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Redo"), wxT("Redo the last undone edit")); #endif tb_->AddSeparator(); tb_->AddTool(ID_SE_CLOSE, wxT("Close"), wxBitmap(close_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Exit debugger"), wxT("Close debugger")); #ifdef __WXOSX_CARBON__ for (size_t i = 0; i < tb_->GetToolsCount(); ++i) { const wxToolBarToolBase *tool = tb_->GetToolByPos(i); tb_->SetToolShortHelp(tool->GetId(), tool->GetLabel()); } #endif tb_->Realize(); top_sizer->Add(tb_, 0, wxEXPAND); ed_ = new FitykEditor(this, ID_SE_EDITOR); top_sizer->Add(ed_, 1, wxALL|wxEXPAND, 0); SetSizerAndFit(top_sizer); SetSize(600, 500); } void EditorDlg::open_file(const wxString& path) { if (wxFileExists(path)) ed_->LoadFile(path); else ed_->Clear(); path_ = path; lua_file_ = path.Lower().EndsWith("lua"); ed_->set_filetype(lua_file_); #if wxUSE_STC // i don't know why, but in wxGTK 2.9.3 initially all text is selected ed_->ClearSelections(); #endif ed_->DiscardEdits(); update_title(); } void EditorDlg::new_file_with_content(const wxString& content) { ed_->ChangeValue(content); path_.clear(); lua_file_ = content.StartsWith("--"); ed_->set_filetype(lua_file_); #if wxUSE_STC // i don't know why, but in wxGTK 2.9.3 initially all text is selected ed_->ClearSelections(); ed_->GotoLine(ed_->GetLineCount() - 1); #else ed_->SetInsertionPointEnd(); #endif ed_->DiscardEdits(); update_title(); } void EditorDlg::on_save() { if (!path_.empty()) do_save_file(path_); else on_save_as(); } void EditorDlg::on_save_as() { wxFileDialog dialog(this, "save script as...", frame->script_dir(), "", "Fityk scripts (*.fit)|*.fit;*.FIT" "|Lua scripts (*.lua)|*.lua;*.LUA" "|all files|*", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (lua_file_) dialog.SetFilterIndex(1); if (dialog.ShowModal() == wxID_OK) { do_save_file(dialog.GetPath()); frame->set_script_dir(dialog.GetDirectory()); } } void EditorDlg::do_save_file(const wxString& save_path) { bool r = ed_->SaveFile(save_path); if (r) { path_ = save_path; ed_->DiscardEdits(); update_title(); } } string EditorDlg::get_editor_line(int n) { string line = wx2s(ed_->GetLineText(n)); if (!line.empty() && *(line.end()-1) == '\n') { line.resize(line.size() - 1); if (!line.empty() && *(line.end()-1) == '\r') line.resize(line.size() - 1); } return line; } int EditorDlg::exec_fityk_line(int n) { if (n < 0) return 1; string s = get_editor_line(n); int counter = 1; while (!s.empty() && *(s.end()-1) == '\\') { s.resize(s.size() - 1); s += get_editor_line(n+counter); ++counter; } // the same replacement as in UserInterface::exec_script() if (s.find("_SCRIPT_DIR_/") != string::npos) { string dir = fityk::get_directory(wx2s(path_)); fityk::replace_all(s, "_EXECUTED_SCRIPT_DIR_/", dir);// old magic string fityk::replace_all(s, "_SCRIPT_DIR_/", dir); // new magic string } exec(s); /* UserInterface::Status r = exec(s); if (r == UserInterface::kStatusOk) { } else { // error } */ return counter; } int EditorDlg::exec_lua_line(int n) { if (n < 0) return 1; string s = get_editor_line(n); int counter = 1; if (s.empty()) return counter; while (ftk->lua_bridge()->is_lua_line_incomplete(s.c_str())) { if (n+counter >= ed_->GetLineCount()) break; s += "\n " + get_editor_line(n+counter); ++counter; } exec("lua " + s); /* UserInterface::Status r = exec(s); if (r == UserInterface::kStatusOk) { } else { // error } */ return counter; } void EditorDlg::OnExec(wxCommandEvent&) { long p1, p2; ed_->GetSelection(&p1, &p2); long y1=0, y2=0; if (p1 != p2) { //selection, exec whole lines long x; ed_->PositionToXY(p1, &x, &y1); ed_->PositionToXY(p2, &x, &y2); } else y2 = ed_->GetNumberOfLines(); for (int i = y1; i <= y2; ) i += lua_file_ ? exec_lua_line(i) : exec_fityk_line(i); } void EditorDlg::OnStep(wxCommandEvent&) { int y = ed_->GetCurrentLine(); int n = lua_file_ ? exec_lua_line(y) : exec_fityk_line(y); ed_->GotoLine(y+n); } void EditorDlg::OnTextChange(wxStyledTextEvent&) { if (GetTitle().EndsWith(wxT(" *")) != ed_->IsModified()) update_title(); #if 0 tb_->EnableTool(wxID_UNDO, ed_->CanUndo()); tb_->EnableTool(wxID_REDO, ed_->CanRedo()); #endif } void EditorDlg::update_title() { wxString p = path_.empty() ? wxString(wxT("unnamed")) : path_; if (ed_->IsModified()) p += wxT(" *"); SetTitle(p); tb_->EnableTool(ID_SE_SAVE, !path_.empty() && ed_->IsModified()); } void EditorDlg::OnCloseDlg(wxCloseEvent& event) { if (ed_->IsModified()) { int r = wxMessageBox("Save before closing?", "Save?", wxYES_NO | wxCANCEL | wxICON_QUESTION); if (r == wxCANCEL) { event.Veto(); return; } if (r == wxYES) on_save(); } Destroy(); } fityk-1.3.1/wxgui/editor.h000066400000000000000000000020431302634723100154440ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_EDITOR_H_ #define FITYK_WX_EDITOR_H_ class FitykEditor; class wxStyledTextEvent; class EditorDlg : public wxDialog { public: EditorDlg(wxWindow* parent); void open_file(const wxString& path); void new_file_with_content(const wxString& content); private: wxToolBarBase *tb_; FitykEditor *ed_; wxString path_; bool lua_file_; void do_save_file(const wxString& save_path); void update_title(); void on_save(); void on_save_as(); std::string get_editor_line(int n); int exec_fityk_line(int n); int exec_lua_line(int n); void OnSave(wxCommandEvent&) { on_save(); } void OnSaveAs(wxCommandEvent&) { on_save_as(); } void OnExec(wxCommandEvent&); void OnStep(wxCommandEvent&); void OnButtonClose(wxCommandEvent&) { Close(); } void OnCloseDlg(wxCloseEvent& event); void OnTextChange(wxStyledTextEvent&); DECLARE_EVENT_TABLE() }; #endif fityk-1.3.1/wxgui/exportd.cpp000066400000000000000000000207341302634723100162050ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// export_data_dlg() and export_peak_parameters() /// which are called from the GUI menu. #include #include #include #include #include "exportd.h" #include "cmn.h" #include "frame.h" //ftk #include "fityk/logic.h" #include "fityk/model.h" // get_ff() using namespace std; ExtraCheckBox::ExtraCheckBox(wxWindow* parent, const wxString& label, bool value) : wxPanel(parent, -1) { cb = new wxCheckBox(this, -1, label); cb->SetValue(value); wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); #ifdef __WXMSW__ sizer->AddSpacer(100); sizer->Add(cb, 0, wxLEFT|wxBOTTOM, 5); #else sizer->Add(cb); #endif SetSizerAndFit(sizer); } Extra2CheckBoxes::Extra2CheckBoxes(wxWindow* parent, const wxString& label1, bool value1, const wxString& label2, bool value2) : wxPanel(parent, -1) { cb1 = new wxCheckBox(this, -1, label1); cb1->SetValue(value1); cb2 = new wxCheckBox(this, -1, label2); cb2->SetValue(value2); wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); #ifdef __WXMSW__ sizer->Add(cb1, 0, wxLEFT|wxBOTTOM, 10); sizer->Add(cb2, 0, wxLEFT|wxBOTTOM, 10); #else sizer->Add(cb1); sizer->Add(cb2, 0, wxTOP, 5); #endif SetSizerAndFit(sizer); } // helper for export_data_dlg() class DataExportDlg : public wxDialog { public: DataExportDlg(wxWindow* parent, wxWindowID id, int f_count); std::string get_text() { return wx2s(text->GetValue()); } private: void OnCheckChanged(wxCommandEvent&) { on_widget_change(); } void OnInactiveChanged(wxCommandEvent&) { on_widget_change(); } void OnTextChanged(wxCommandEvent&); void OnOk(wxCommandEvent& event); void on_widget_change(); wxCheckListBox *list; wxCheckBox *only_a_cb; wxTextCtrl *text; wxArrayString cv; }; DataExportDlg::DataExportDlg(wxWindow* parent, wxWindowID id, int f_count) : wxDialog(parent, id, wxT("Export data/functions as points"), wxDefaultPosition, wxSize(600, 500), wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxStaticText *st1 = new wxStaticText(this, -1, wxT(" Step 1: Select columns")); top_sizer->Add(st1, 0, wxTOP|wxLEFT|wxRIGHT, 5); wxStaticText *st2 = new wxStaticText(this, -1, wxT(" Step 2: Choose a file")); st2->Enable(false); top_sizer->Add(st2, 0, wxALL, 5); wxArrayString choices; choices.Add(wxT("x")); cv.Add(wxT("x")); choices.Add(wxT("y")); cv.Add(wxT("y")); choices.Add(wxT("\u03C3 (std. dev. of y)")); cv.Add(wxT("s")); choices.Add(wxT("active (0/1)")); cv.Add(wxT("a")); choices.Add(wxT("all component functions")); wxString all_func; for (int i = 0; i < f_count; ++i) { if (!all_func.empty()) all_func += wxT(", "); all_func += wxString::Format(wxT("F[%d](x)"), i); } cv.Add(all_func); choices.Add(wxT("model (sum)")); cv.Add(wxT("F(x)")); choices.Add(wxT("x-correction")); cv.Add(wxT("Z(x)")); choices.Add(wxT("residuals")); cv.Add(wxT("y-F(x)")); choices.Add(wxT("absolute residuals")); cv.Add(wxT("abs(y-F(x))")); choices.Add(wxT("weighted residuals")); cv.Add(wxT("(y-F(x))/s")); list = new wxCheckListBox(this, -1, wxDefaultPosition, wxDefaultSize, choices); top_sizer->Add(list, 0, wxALL|wxEXPAND, 5); only_a_cb = new wxCheckBox(this, -1, wxT("only active points")); top_sizer->Add(only_a_cb, 0, wxALL, 5); text = new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition, wxSize(300,-1)); top_sizer->Add(text, 0, wxEXPAND|wxALL, 5); top_sizer->Add (new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 5); top_sizer->Add(CreateButtonSizer(wxOK|wxCANCEL), 0, wxALL|wxALIGN_CENTER, 5); SetSizerAndFit(top_sizer); Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DataExportDlg::OnOk)); Connect(list->GetId(), wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler(DataExportDlg::OnCheckChanged)); Connect(only_a_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(DataExportDlg::OnInactiveChanged)); Connect(text->GetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(DataExportDlg::OnTextChanged)); wxString t = wxConfig::Get()->Read(wxT("/exportPoints"), wxT("all: x, y, F(x)")); text->SetValue(t); } void DataExportDlg::on_widget_change() { wxString s = (only_a_cb->GetValue() ? wxT("if a: ") : wxT("all: ")); for (size_t i = 0; i < list->GetCount(); ++i) { if (list->IsChecked(i)) { if (!s.EndsWith(wxT(": ")) && !cv[i].empty()) s += wxT(", "); s += cv[i]; } } text->ChangeValue(s); FindWindow(wxID_OK)->Enable(true); } void DataExportDlg::OnTextChanged(wxCommandEvent&) { //if (!text->IsModified()) // return; string s = wx2s(text->GetValue()); size_t colon = s.find(':'); bool parsable = (ftk->check_syntax("print " + s) && colon != string::npos); FindWindow(wxID_OK)->Enable(parsable); if (parsable) { only_a_cb->SetValue(s.substr(0, colon) == "if a"); vector v = split_string(s.substr(colon + 1), ','); vm_foreach (string, i, v) *i = strip_string(*i); for (size_t i = 0; i < list->GetCount(); ++i) list->Check(i, contains_element(v, wx2s(cv[i]))); } } void DataExportDlg::OnOk(wxCommandEvent& event) { wxConfig::Get()->Write(wxT("/exportPoints"), text->GetValue()); event.Skip(); } void exec_redirected_command(const vector& sel, const string& cmd, const wxString& path) { if (sel.size() == 1) { exec("@" + S(sel[0]) + ": " + cmd + " > '" + wx2s(path) + "'"); return; } string datasets; if (ftk->dk.count() == (int) sel.size()) datasets = "@*"; else datasets = "@" + join_vector(sel, " @"); if (wxFileExists(path)) exec("delete file '" + wx2s(path) + "'"); exec(datasets + ": " + cmd + " >> '" + wx2s(path) + "'"); } static wxString get_default_name(const vector& sel, const char* ext) { if (sel.size() == 1) { const string& filename = ftk->dk.data(sel[0])->get_filename(); if (!filename.empty()) return wxFileName(s2wx(filename)).GetName() + ext; } return ""; } /// show "Export data" dialog void export_data_dlg(const vector& sel, wxWindow *parent, wxString *export_dir) { int f_count = 0; if (sel.size() == 1) { f_count = ftk->dk.get_model(sel[0])->get_ff().names.size(); } DataExportDlg ded(parent, -1, f_count); if (ded.ShowModal() != wxID_OK) return; wxFileDialog fdlg(parent, "Export data to file", *export_dir, get_default_name(sel, ".dat"), "x y data (*.dat, *.xy)|*.dat;*.DAT;*.xy;*.XY", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (fdlg.ShowModal() == wxID_OK) exec_redirected_command(sel, "print " + ded.get_text(), fdlg.GetPath()); *export_dir = fdlg.GetDirectory(); } static wxWindow* peakparam_extra(wxWindow* parent) { return new ExtraCheckBox(parent, "include standard errors", false); } void export_peak_parameters(const vector& sel, wxWindow *parent, wxString *export_dir) { wxFileDialog fdlg(parent, "Export parameters to file", *export_dir, get_default_name(sel, ".peaks"), "parameters of functions (*.peaks)|*.peaks|all files|*", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); // on wxOSX/Carbon SetExtraControlCreator() is unreliable #ifndef __WXOSX_CARBON__ fdlg.SetExtraControlCreator(&peakparam_extra); #endif if (fdlg.ShowModal() == wxID_OK) { wxWindow *extra = fdlg.GetExtraControl(); if (extra != NULL && wxDynamicCast(extra,ExtraCheckBox)->is_checked()) exec_redirected_command(sel, "info peaks_err", fdlg.GetPath()); else exec_redirected_command(sel, "info peaks", fdlg.GetPath()); } *export_dir = fdlg.GetDirectory(); } fityk-1.3.1/wxgui/exportd.h000066400000000000000000000022501302634723100156430ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_EXPORTD_H_ #define FITYK_WX_EXPORTD_H_ #include #include void export_data_dlg(const std::vector& sel, wxWindow *parent, wxString *export_dir); void export_peak_parameters(const std::vector& sel, wxWindow *parent, wxString *export_dir); // helper used also in frame.cpp void exec_redirected_command(const std::vector& sel, const std::string& cmd, const wxString& path); class ExtraCheckBox: public wxPanel { public: ExtraCheckBox(wxWindow* parent, const wxString& label, bool value); bool is_checked() const { return cb->GetValue(); } private: wxCheckBox *cb; }; class Extra2CheckBoxes: public wxPanel { public: Extra2CheckBoxes(wxWindow* parent, const wxString& label1, bool value1, const wxString& label2, bool value2); bool is_checked1() const { return cb1->GetValue(); } bool is_checked2() const { return cb2->GetValue(); } private: wxCheckBox *cb1, *cb2; }; #endif fityk-1.3.1/wxgui/fitinfo.cpp000066400000000000000000000234501302634723100161540ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include #include #include #include #include "fitinfo.h" #include "frame.h" //frame #include "cmn.h" //ProportionalSplitter #include "fityk/logic.h" #include "fityk/fit.h" #include "fityk/data.h" #include "fityk/var.h" using namespace std; using fityk::Variable; NumericFormatPanel::NumericFormatPanel(wxWindow* parent) : wxPanel(parent, -1) { wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(new wxStaticText(this, -1, wxT("precision:")), wxSizerFlags().Center()); prec_sc = new SpinCtrl(this, -1, 6, 0, 30); sizer->Add(prec_sc, wxSizerFlags().Center()); wxArrayString fmt_choices; fmt_choices.Add(wxT("g")); fmt_choices.Add(wxT("e")); fmt_choices.Add(wxT("E")); fmt_choices.Add(wxT("f")); fmt_c = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, fmt_choices); fmt_c->SetSelection(0); fmt_c->SetToolTip(wxT("g: mixed format\n") wxT("e: 1.234e+02\n") wxT("E: 1.234E+02\n") wxT("f: 123.400")); sizer->Add(fmt_c, wxSizerFlags(1).Center()); SetSizerAndFit(sizer); update_format(); Connect(fmt_c->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(NumericFormatPanel::OnFormatChanged)); Connect(prec_sc->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(NumericFormatPanel::OnPrecisionSpin)); } void NumericFormatPanel::update_format() { format_= "%." + S(prec_sc->GetValue()) + REALT_LENGTH_MOD + wx2s(fmt_c->GetStringSelection()); wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, GetId()); AddPendingEvent(event); } FitInfoDlg::FitInfoDlg(wxWindow* parent, wxWindowID id) : wxDialog(parent, id, wxString(wxT("Fit Info")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { } bool FitInfoDlg::Initialize() { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxSplitterWindow *hsplit = new ProportionalSplitter(this, -1, 0.25); wxPanel *left_panel = new wxPanel(hsplit); wxSizer *lsizer = new wxBoxSizer(wxVERTICAL); nf = new NumericFormatPanel(left_panel); lsizer->Add(nf, wxSizerFlags().Expand().Border(wxTOP|wxBOTTOM)); left_tc = new wxTextCtrl(left_panel, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH|wxTE_READONLY); lsizer->Add(left_tc, wxSizerFlags(1).Expand()); left_panel->SetSizerAndFit(lsizer); wxPanel *right_panel = new wxPanel(hsplit); wxSizer *rsizer = new wxBoxSizer(wxVERTICAL); wxArrayString choices; // \u00B1 == +/- choices.Add(wxT("\u00B1 standard errors: sqrt(WSSR/DoF COV_kk)")); choices.Add(wxT("\u00B1 sqrt(COV_kk)")); choices.Add(wxT("\u00B1 50% confidence intervals")); choices.Add(wxT("\u00B1 90% confidence intervals")); choices.Add(wxT("\u00B1 95% confidence intervals")); choices.Add(wxT("\u00B1 99% confidence intervals")); choices.Add(wxT("covariance matrix")); right_c = new wxChoice(right_panel, -1, wxDefaultPosition, wxDefaultSize, choices); right_c->SetSelection(0); rsizer->Add(right_c, wxSizerFlags().Expand().Border()); right_tc = new wxTextCtrl(right_panel, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH|wxTE_READONLY| wxTE_DONTWRAP); int font_size = right_tc->GetFont().GetPointSize(); #ifndef __WXMSW__ font_size -= 1; #endif wxFont font(font_size, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); wxTextAttr attr; attr.SetFont(font); right_tc->SetDefaultStyle(attr); rsizer->Add(right_tc, wxSizerFlags(1).Expand()); right_panel->SetSizerAndFit(rsizer); hsplit->SplitVertically(left_panel, right_panel); top_sizer->Add(hsplit, wxSizerFlags(1).Expand().Border()); wxBoxSizer *btn_sizer = new wxBoxSizer(wxHORIZONTAL); btn_sizer->Add(new wxButton(this, wxID_COPY), wxSizerFlags().Border()); btn_sizer->AddStretchSpacer(); btn_sizer->Add(new wxButton(this, wxID_CLOSE), wxSizerFlags().Right().Border()); top_sizer->Add(btn_sizer, wxSizerFlags().Expand()); SetSizerAndFit(top_sizer); SetSize(wxSize(640, 440)); SetEscapeId(wxID_CLOSE); try { update_left_tc(); update_right_tc(); } catch (fityk::ExecuteError &e) { ftk->ui()->warn(string("Error: ") + e.what()); return false; } // connect both right_c and nf (NumericFormatPanel) Connect(-1, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(FitInfoDlg::OnChoice)); Connect(wxID_COPY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(FitInfoDlg::OnCopy)); return true; } void FitInfoDlg::update_left_tc() { string s; vector datas = frame->get_selected_datas(); const vector &pp = ftk->mgr.parameters(); fityk::Fit *fit = ftk->get_fit(); int dof = fit->get_dof(datas); double wssr = fit->compute_wssr(pp, datas, true); wssr_over_dof = wssr / dof; double ssr = fit->compute_wssr(pp, datas, false); double r2 = fit->compute_r_squared(pp, datas); int points = 0; for (vector::const_iterator i = datas.begin(); i != datas.end(); ++i) points += (*i)->get_n(); if (datas.size() == 1) s = "dataset " + S(frame->get_selected_data_indices()[0]) + ": " + datas[0]->get_title() + "\n"; else s = S(datas.size()) + " datasets\n"; s += "points: " + S(points) + "\n\nDoF: " + S(dof) + "\nWSSR: " + nf->fmt(wssr) + "\nSSR: " + nf->fmt(ssr) + "\nWSSR/DoF: " + nf->fmt(wssr_over_dof) + "\nRes.St.Dev.: " + nf->fmt(sqrt(wssr_over_dof)) + "\nR-squared: " + nf->fmt(r2) + "\n"; left_tc->SetValue(s2wx(s)); } void FitInfoDlg::update_right_tc() { fityk::Fit *fit = ftk->get_fit(); int choice = right_c->GetSelection(); vector datas = frame->get_selected_datas(); vector const &pp = ftk->mgr.parameters(); int na = pp.size(); wxString s; if (choice <= 5) { vector errors; if (choice == 0 || choice == 1) { try { errors = fit->get_standard_errors(datas); } catch (fityk::ExecuteError&) { errors.resize(na, 0.); } if (choice == 1) vm_foreach (double, i, errors) *i *= 1. / sqrt(wssr_over_dof); } else { int level; if (choice == 2) level = 50; else if (choice == 3) level = 90; else if (choice == 4) level = 95; else //if (choice == 5) level = 99; try { errors = fit->get_confidence_limits(datas, level); } catch (fityk::ExecuteError&) { errors.resize(na, 0.); } } for (int i = 0; i < na; ++i) { if (fit->is_param_used(i)) { const Variable *var = ftk->mgr.gpos_to_var(i); vector in = ftk->mgr.get_variable_references(var->name); wxString name = wxT("$") + s2wx(var->name); if (in.size() == 1 && in[0][0] == '%') name += wxT(" = ") + s2wx(in[0]); else if (in.size() == 1) name += wxT(" (in ") + s2wx(in[0]) + wxT(")"); else name += wxT(" (") + s2wx(S(in.size())) + wxT(" refs)"); wxString val = s2wx(nf->fmt(pp[i])); // \u00B1 == +/- s += wxString::Format(wxT("\n%20s = %10s \u00B1 "), name.c_str(), val.c_str()); if (errors[i] == 0.) s += wxT("??"); else s += s2wx(nf->fmt(errors[i])); } } } else { s = wxT(" "); vector alpha; try { alpha = fit->get_covariance_matrix(datas); } catch (fityk::ExecuteError&) { alpha.resize(na*na, 0.); } for (int i = 0; i < na; ++i) if (fit->is_param_used(i)) { string name = ftk->mgr.gpos_to_var(i)->name; s += wxString::Format("%10s", s2wx("$"+name).c_str()); } for (int i = 0; i < na; ++i) { if (fit->is_param_used(i)) { string name = ftk->mgr.gpos_to_var(i)->name; s += wxString::Format("\n%10s", s2wx("$"+name).c_str()); for (int j = 0; j < na; ++j) { if (fit->is_param_used(j)) { double val = alpha[na*i + j]; if (fabs(val) < 1e-99) val = 0.; s += wxString::Format(wxT(" %9s"), s2wx(nf->fmt(val)).c_str()); } } } } } // On wxMSW 2.9.0 wxTextCtrl::ChangeValue() ignores default styles //right_tc->ChangeValue(s); right_tc->Clear(); right_tc->AppendText(s); } void FitInfoDlg::OnCopy(wxCommandEvent&) { wxString sel = right_tc->GetStringSelection(); if (sel.empty()) sel = left_tc->GetStringSelection(); if (sel.empty()) sel = right_tc->GetValue(); if (wxTheClipboard->Open()) { wxTheClipboard->SetData(new wxTextDataObject(sel)); wxTheClipboard->Close(); } } fityk-1.3.1/wxgui/fitinfo.h000066400000000000000000000025251302634723100156210ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_FITINFO_H_ #define FITYK_WX_FITINFO_H_ #include #include #include #include "cmn.h" //SpinCtrl #include "fityk/common.h" //realt /// Control for changing numeric precision and format. /// Sends wxEVT_COMMAND_CHOICE_SELECTED when the precision changes. class NumericFormatPanel: public wxPanel { public: NumericFormatPanel(wxWindow* parent); std::string fmt(realt d) { return format1(format_.c_str(), d); } const std::string& format() const { return format_; } private: std::string format_; wxSpinCtrl *prec_sc; wxChoice *fmt_c; void update_format(); void OnPrecisionSpin(wxSpinEvent&) { update_format(); } void OnFormatChanged(wxCommandEvent&) { update_format(); } }; /// Status bar configuration dialog class FitInfoDlg: public wxDialog { public: FitInfoDlg(wxWindow* parent, wxWindowID id); bool Initialize(); private: wxTextCtrl *left_tc, *right_tc; wxChoice *right_c; double wssr_over_dof; NumericFormatPanel *nf; void update_left_tc(); void update_right_tc(); void OnChoice(wxCommandEvent&) { update_left_tc(); update_right_tc(); } void OnCopy(wxCommandEvent&); }; #endif // FITYK_WX_FITINFO_H_ fityk-1.3.1/wxgui/fitrun.cpp000066400000000000000000000116041302634723100160230ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ #include #include #include "fitrun.h" #include "frame.h" #include "fityk/fit.h" #include "fityk/logic.h" using namespace std; using fityk::FitManager; BEGIN_EVENT_TABLE(FitRunDlg, wxDialog) EVT_SPINCTRL (-1, FitRunDlg::OnSpinEvent) EVT_CHOICE (-1, FitRunDlg::OnChangeDsOrMethod) EVT_RADIOBOX (-1, FitRunDlg::OnChangeDsOrMethod) END_EVENT_TABLE() FitRunDlg::FitRunDlg(wxWindow* parent, wxWindowID id) : wxDialog(parent, id, wxT("fit functions to data"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxArrayString data_choices; vector sel = frame->get_selected_data_indices(); string a = S(sel.size()) + " selected dataset"; if (sel.size() == 1) a += ": @" + S(sel[0]); else a += "s"; data_choices.Add(s2wx(a)); data_choices.Add(wxT("all datasets")); data_rb = new wxRadioBox(this, -1, wxT("fit..."), wxDefaultPosition, wxDefaultSize, data_choices, 1, wxRA_SPECIFY_COLS); separately_cb = new wxCheckBox(this, -1, "fit each dataset separately"); if (ftk->dk.count() == 1) { data_rb->Enable(1, false); separately_cb->Enable(false); } else { bool independent = ftk->are_independent(ftk->dk.datas()); separately_cb->SetValue(independent); } top_sizer->Add(data_rb, 0, wxALL|wxEXPAND, 5); top_sizer->Add(separately_cb, 0, wxALL|wxEXPAND, 5); wxBoxSizer *method_sizer = new wxBoxSizer(wxHORIZONTAL); method_sizer->Add(new wxStaticText(this, -1, wxT("method:")), 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); wxArrayString m_choices; for (int i = 0; FitManager::method_list[i][0] != NULL; ++i) m_choices.Add(FitManager::method_list[i][1]); method_c = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, m_choices); int method_nr = ftk->settings_mgr()->get_enum_index("fitting_method"); method_c->SetSelection(method_nr); method_sizer->Add(method_c, 0, wxALL, 5); top_sizer->Add(method_sizer, 0); wxFlexGridSizer *max_sizer = new wxFlexGridSizer(2, 3, 0, 0); max_sizer->Add(new wxStaticText(this, -1, wxT("max. iterations")), 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5); maxiter_sc = new SpinCtrl(this, -1, 0, 0, 999999, 70); max_sizer->Add(maxiter_sc, 0, wxALL, 5); nomaxiter_st = new wxStaticText(this, -1, wxT("(unlimited)")); max_sizer->Add(nomaxiter_st, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5); max_sizer->Add(new wxStaticText(this, -1, wxT("max. WSSR evaluations")), 0, wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT, 5); int default_max_eval = ftk->get_settings()->max_wssr_evaluations; maxeval_sc = new SpinCtrl(this, -1, default_max_eval, 0, 999999, 70); max_sizer->Add(maxeval_sc, 0, wxALL, 5); nomaxeval_st = new wxStaticText(this, -1, wxT("(unlimited)")); max_sizer->Add(nomaxeval_st, 0, wxALIGN_CENTER_VERTICAL, 0); top_sizer->Add(max_sizer, 0); autoplot_cb = new wxCheckBox(this, -1, wxT("refresh plot after each iteration")); autoplot_cb->SetValue(ftk->get_settings()->fit_replot); top_sizer->Add(autoplot_cb, 0, wxALL, 5); top_sizer->Add(new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 10); top_sizer->Add(CreateButtonSizer(wxOK|wxCANCEL), 0, wxALL|wxALIGN_CENTER, 5); SetSizerAndFit(top_sizer); update_unlimited(); } void FitRunDlg::update_unlimited() { nomaxeval_st->Show(maxeval_sc->GetValue() == 0); nomaxiter_st->Show(maxiter_sc->GetValue() == 0); } string FitRunDlg::get_cmd() const { string cmd; int sel = method_c->GetSelection(); string m = ftk->settings_mgr()->get_allowed_values("fitting_method")[sel]; if (m != ftk->get_settings()->fitting_method) cmd += "with fitting_method=" + m + " "; if (autoplot_cb->GetValue() != ftk->get_settings()->fit_replot) cmd += string(cmd.empty() ? "with" : ",") + " fit_replot=" + (autoplot_cb->GetValue() ? "1 " : "0 "); int max_eval = maxeval_sc->GetValue(); if (max_eval != ftk->get_settings()->max_wssr_evaluations) cmd += string(cmd.empty() ? "with" : ",") + " max_wssr_evaluations=" + S(max_eval) + " "; cmd += "fit"; int max_iter = maxiter_sc->GetValue(); if (max_iter > 0) cmd += " " + S(max_iter); bool only_selected = (data_rb->GetSelection() == 0); string ds = only_selected ? frame->get_datasets() : "@*: "; if (separately_cb->GetValue()) cmd = ds + cmd; // e.g. @*: fit else cmd += " " + ds.substr(0, ds.size() - 2); // e.g. fit @* return cmd; } fityk-1.3.1/wxgui/fitrun.h000066400000000000000000000013271302634723100154710ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_FITRUN_H_ #define FITYK_WX_FITRUN_H_ #include #include #include "cmn.h" class FitRunDlg : public wxDialog { public: FitRunDlg(wxWindow* parent, wxWindowID id); std::string get_cmd() const; private: wxRadioBox* data_rb; wxChoice* method_c; wxCheckBox *separately_cb, *autoplot_cb; SpinCtrl *maxiter_sc, *maxeval_sc; wxStaticText *nomaxeval_st, *nomaxiter_st; void OnSpinEvent(wxSpinEvent &) { update_unlimited(); } void OnChangeDsOrMethod(wxCommandEvent&) {} void update_unlimited(); DECLARE_EVENT_TABLE() }; #endif fityk-1.3.1/wxgui/frame.cpp000066400000000000000000002514401302634723100156120ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "frame.h" #include "recent.h" #include "plot.h" #include "mplot.h" #include "aplot.h" #include "bgm.h" #include "merge.h" #include "fitrun.h" #include "exportd.h" #include "history.h" #include "about.h" #include "dload.h" #include "textpane.h" #include "plotpane.h" #include "sidebar.h" #include "print.h" #include "datatable.h" #include "dataedit.h" #include "defmgr.h" #include "editor.h" #include "setdlg.h" #include "statbar.h" #include "fitinfo.h" #include "modelinfo.h" #include "inputline.h" #include "app.h" #include "powdifpat.h" #include "fityk/common.h" #include "fityk/logic.h" #include "fityk/fit.h" #include "fityk/data.h" #include "fityk/settings.h" #include "fityk/guess.h" #include "fityk/tplate.h" #include "img/fityk.xpm" //toolbars icons #include "img/active_mode.xpm" #include "img/addpeak_mode.xpm" #include "img/add_peak.xpm" #include "img/bg_mode.xpm" #include "img/edit_data.xpm" //#include "img/manual.xpm" #include "img/open_data_custom.xpm" #include "img/open_data.xpm" //#include "img/right_pane.xpm" #include "img/run_fit.xpm" #include "img/run_script.xpm" #include "img/save_data.xpm" #include "img/save_script.xpm" #include "img/strip_bg.xpm" #include "img/undo_fit.xpm" #include "img/zoom_all.xpm" #include "img/zoom_left.xpm" #include "img/zoom_mode.xpm" #include "img/zoom_prev.xpm" #include "img/zoom_right.xpm" #include "img/zoom_up.xpm" #include "img/zoom_vert.xpm" #include "img/book16.h" #include "img/editor16.h" #include "img/export16.h" #include "img/fileopen16.h" //#include "img/filereload16.h" #include "img/filesaveas16.h" #include "img/function16.h" #include "img/image16.h" #include "img/preferences16.h" #include "img/recordmacro16.h" #include "img/redo16.h" #include "img/reload16.h" #include "img/run16.h" #include "img/info16.h" #include "img/runmacro16.h" #include "img/stopmacro16.h" #include "img/undo16.h" #include "img/revert16.h" #include "img/web16.h" #include "img/zoom-fit16.h" #include "img/powdifpat16.xpm" //using namespace std; using std::string; using std::vector; #if XYLIB_VERSION < 10500 typedef shared_ptr dataset_shared_ptr; #endif using fityk::FitManager; FFrame *frame = NULL; fityk::Full *ftk = NULL; UserInterface::Status exec(const std::string &s) { return ftk->ui()->exec_and_log(s); } static const wxString discussions_url( wxT("http://groups.google.com/group/fityk-users/topics")); static const wxString website_url( wxT("http://fityk.nieto.pl/")); static const wxString wiki_url( wxT("https://github.com/wojdyr/fityk/wiki")); static const wxString feedback_url( wxT("http://fityk.nieto.pl/feedback/") + pchar2wx(VERSION)); enum { // menu ID_H_MANUAL = 24001 , ID_H_WEBSITE , ID_H_WIKI , ID_H_DISCUSSIONS , ID_H_FEEDBACK , ID_H_EXAMPLE1 , ID_H_EXAMPLE2 , ID_H_EXAMPLE3 , ID_H_EXAMPLE4 , ID_D_QLOAD , ID_D_XLOAD , ID_D_RECENT , //and next ones ID_D_RECENT_END = ID_D_RECENT+50 , ID_D_REVERT , ID_D_TABLE , ID_D_EDITOR , ID_D_SDT , ID_D_SDT_END = ID_D_SDT+50 , ID_D_MERGE , ID_D_RM_SHIRLEY , ID_D_CALC_SHIRLEY , ID_D_EXPORT , ID_DEFMGR , ID_S_GUESS , ID_S_PFINFO , ID_S_AUTOFREEZE , ID_S_EXPORTP , ID_S_EXPORTF , ID_S_EXPORTD , ID_F_METHOD , ID_F_RUN , ID_F_INFO , ID_F_UNDO , ID_F_REDO , ID_F_HISTORY , ID_T_PD , ID_T_KEBE , ID_F_M , ID_F_M_END = ID_F_M+50 , ID_SESSION_LOG , ID_LOG_START , ID_LOG_STOP , ID_LOG_WITH_OUTPUT , ID_SAVE_HISTORY , ID_SESSION_RESET , ID_SESSION_NEWWIN , ID_PAGE_SETUP , ID_COPY_TO_CLIPB , ID_SAVE_IMAGE , ID_SESSION_INCLUDE , ID_SESSION_RECENT , ID_SESSION_RECENT_END = ID_SESSION_RECENT+50, ID_SESSION_NEW_F , ID_SESSION_NEW_L , ID_SESSION_NEW_H , ID_SCRIPT_EDIT , ID_SESSION_LOAD , ID_SESSION_SAVE , ID_SESSION_SET , ID_SESSION_EI , ID_G_MODE , ID_G_M_ZOOM , ID_G_M_RANGE , ID_G_M_BG , ID_G_M_ADD , ID_G_BG_STRIP , ID_G_BG_UNDO , ID_G_BG_CLEAR , ID_G_BG_SPLINE , ID_G_BG_RECENT , ID_G_BG_RECENT_END=ID_G_BG_RECENT+50, ID_G_BG_HULL , ID_G_BG_SUB , ID_G_M_PEAK , ID_G_M_PEAK_N , ID_G_M_PEAK_N_END = ID_G_M_PEAK_N+300, ID_G_SHOW , ID_G_S_TOOLBAR , ID_G_S_STATBAR , ID_G_S_SIDEB , ID_G_S_A1 , ID_G_S_A2 , ID_G_S_TEXT , ID_G_C_MAIN , ID_G_C_A1 , ID_G_C_A2 , ID_G_C_OUTPUT , ID_G_C_SB , ID_G_C_DIRS , ID_G_CROSSHAIR , ID_G_ANTIALIAS , ID_G_FULLSCRN , ID_G_V_ALL , ID_G_V_VERT , ID_G_SHOWY0 , ID_G_V_SCROLL_L , ID_G_V_SCROLL_R , ID_G_V_SCROLL_U , ID_G_V_EXTH , ID_G_V_ZOOM_PREV , ID_G_V_ZOOM_FIRST , ID_G_V_ZOOM_PREV_END = ID_G_V_ZOOM_FIRST+150, ID_G_LCONF , ID_G_LCONFB , ID_G_LCONF_X , ID_G_LCONF_X_END = ID_G_LCONF_X+50, ID_G_SCONF , ID_G_SCONFD , ID_G_SCONFAS , // toolbar ID_T_ZOOM , ID_T_RANGE , ID_T_BG , ID_T_ADD , ID_T_PZ , ID_T_STRIP , ID_T_RUN , ID_T_UNDO , ID_T_AUTO , //ID_T_BAR , ID_T_CHOICE }; static void append_mi(wxMenu* menu, int id, wxBitmap const& bitmap, const wxString& text=wxT(""), const wxString& helpString=wxT("")) { wxMenuItem *item = new wxMenuItem(menu, id, text, helpString); //#if wxUSE_OWNER_DRAWN || defined(__WXGTK__) #if defined(__WXGTK__) item->SetBitmap(bitmap); #endif menu->Append(item); } BEGIN_EVENT_TABLE(FFrame, wxFrame) EVT_MENU (ID_SESSION_INCLUDE, FFrame::OnInclude) EVT_MENU (ID_SESSION_NEW_F, FFrame::OnNewFitykScript) EVT_MENU (ID_SESSION_NEW_L, FFrame::OnNewLuaScript) EVT_MENU (ID_SESSION_NEW_H, FFrame::OnNewHistoryScript) EVT_MENU (ID_SCRIPT_EDIT, FFrame::OnScriptEdit) EVT_MENU_RANGE (ID_SESSION_RECENT+1, ID_SESSION_RECENT_END, FFrame::OnRecentScript) #ifdef __WXMAC__ EVT_MENU (ID_SESSION_NEWWIN, FFrame::OnNewWindow) #endif EVT_MENU (ID_SESSION_LOAD, FFrame::OnSessionLoad) EVT_MENU (ID_SESSION_SAVE, FFrame::OnSessionSave) EVT_MENU (ID_SAVE_HISTORY, FFrame::OnSaveHistory) EVT_UPDATE_UI (ID_LOG_START, FFrame::OnMenuLogStartUpdate) EVT_MENU (ID_LOG_START, FFrame::OnLogStart) EVT_UPDATE_UI (ID_LOG_STOP, FFrame::OnMenuLogStopUpdate) EVT_MENU (ID_LOG_STOP, FFrame::OnLogStop) EVT_UPDATE_UI (ID_LOG_WITH_OUTPUT, FFrame::OnMenuLogOutputUpdate) EVT_MENU (ID_LOG_WITH_OUTPUT, FFrame::OnLogWithOutput) EVT_MENU (wxID_PRINT, FFrame::OnPrint) EVT_MENU (ID_COPY_TO_CLIPB, FFrame::OnCopyToClipboard) EVT_MENU (ID_PAGE_SETUP, FFrame::OnPageSetup) EVT_MENU (ID_SAVE_IMAGE, FFrame::OnSaveAsImage) EVT_MENU (ID_SESSION_SET, FFrame::OnSettings) EVT_MENU (ID_SESSION_EI, FFrame::OnEditInit) EVT_MENU (ID_SESSION_RESET, FFrame::OnReset) EVT_MENU (ID_D_QLOAD, FFrame::OnDataQLoad) EVT_MENU (ID_D_XLOAD, FFrame::OnDataXLoad) EVT_MENU_RANGE (ID_D_RECENT+1, ID_D_RECENT_END, FFrame::OnDataRecent) EVT_UPDATE_UI (ID_D_REVERT, FFrame::OnDataRevertUpdate) EVT_MENU (ID_D_REVERT, FFrame::OnDataRevert) EVT_MENU (ID_D_TABLE, FFrame::OnDataTable) EVT_MENU (ID_D_EDITOR, FFrame::OnDataEditor) EVT_MENU_RANGE (ID_D_SDT+1, ID_D_SDT_END, FFrame::OnSavedDT) EVT_MENU (ID_D_MERGE, FFrame::OnDataMerge) EVT_MENU (ID_D_RM_SHIRLEY, FFrame::OnDataRmShirley) EVT_MENU (ID_D_CALC_SHIRLEY,FFrame::OnDataCalcShirley) EVT_MENU (ID_D_EXPORT, FFrame::OnDataExport) EVT_MENU (ID_DEFMGR, FFrame::OnDefinitionMgr) EVT_MENU (ID_S_GUESS, FFrame::OnSGuess) EVT_MENU (ID_S_PFINFO, FFrame::OnSPFInfo) EVT_MENU (ID_S_AUTOFREEZE, FFrame::OnAutoFreeze) EVT_MENU (ID_S_EXPORTP, FFrame::OnParametersExport) EVT_MENU (ID_S_EXPORTF, FFrame::OnModelExport) EVT_MENU (ID_S_EXPORTD, FFrame::OnDataExport) EVT_UPDATE_UI_RANGE (ID_F_M, ID_F_M_END, FFrame::OnFMethodUpdate) EVT_MENU_RANGE (ID_F_M, ID_F_M_END, FFrame::OnFOneOfMethods) EVT_UPDATE_UI (ID_F_RUN, FFrame::OnMenuFitRunUpdate) EVT_MENU (ID_F_RUN, FFrame::OnFRun) EVT_MENU (ID_F_INFO, FFrame::OnFInfo) EVT_UPDATE_UI (ID_F_UNDO, FFrame::OnMenuFitUndoUpdate) EVT_MENU (ID_F_UNDO, FFrame::OnFUndo) EVT_UPDATE_UI (ID_F_REDO, FFrame::OnMenuFitRedoUpdate) EVT_MENU (ID_F_REDO, FFrame::OnFRedo) EVT_UPDATE_UI (ID_F_HISTORY, FFrame::OnMenuFitHistoryUpdate) EVT_MENU (ID_F_HISTORY, FFrame::OnFHistory) EVT_MENU (ID_T_PD, FFrame::OnPowderDiffraction) EVT_MENU (ID_T_KEBE, FFrame::OnXpsKEBE) EVT_MENU (ID_G_M_ZOOM, FFrame::OnChangeMouseMode) EVT_MENU (ID_G_M_RANGE, FFrame::OnChangeMouseMode) EVT_MENU (ID_G_M_BG, FFrame::OnChangeMouseMode) EVT_MENU (ID_G_M_ADD, FFrame::OnChangeMouseMode) EVT_MENU_RANGE (ID_G_M_PEAK_N, ID_G_M_PEAK_N_END, FFrame::OnChangePeakType) EVT_UPDATE_UI(ID_G_BG_STRIP, FFrame::OnMenuBgStripUpdate) EVT_UPDATE_UI(ID_G_BG_UNDO, FFrame::OnMenuBgUndoUpdate) EVT_UPDATE_UI(ID_G_BG_CLEAR, FFrame::OnMenuBgClearUpdate) EVT_MENU (ID_G_BG_STRIP, FFrame::OnStripBg) EVT_MENU (ID_G_BG_UNDO, FFrame::OnUndoBg) EVT_MENU (ID_G_BG_CLEAR, FFrame::OnClearBg) EVT_MENU_RANGE (ID_G_BG_RECENT+1, ID_G_BG_RECENT_END, FFrame::OnRecentBg) EVT_MENU (ID_G_BG_HULL, FFrame::OnConvexHullBg) EVT_MENU (ID_G_BG_SPLINE, FFrame::OnSplineBg) EVT_MENU (ID_G_S_SIDEB, FFrame::OnSwitchSideBar) EVT_MENU_RANGE (ID_G_S_A1, ID_G_S_A2, FFrame::OnSwitchAuxPlot) EVT_UPDATE_UI_RANGE (ID_G_S_A1, ID_G_S_A2, FFrame::OnMenuShowAuxUpdate) EVT_MENU (ID_G_S_TEXT, FFrame::OnSwitchTextPane) EVT_MENU (ID_G_S_TOOLBAR, FFrame::OnSwitchToolbar) EVT_MENU (ID_G_S_STATBAR, FFrame::OnSwitchStatbar) EVT_MENU_RANGE (ID_G_C_MAIN, ID_G_C_A2, FFrame::OnShowPrefDialog) EVT_MENU (ID_G_C_OUTPUT, FFrame::OnConfigureOutputWin) EVT_MENU (ID_G_C_SB, FFrame::OnConfigureStatusBar) EVT_MENU (ID_G_C_DIRS, FFrame::OnConfigureDirectories) EVT_MENU (ID_G_CROSSHAIR, FFrame::OnSwitchCrosshair) EVT_MENU (ID_G_ANTIALIAS, FFrame::OnSwitchAntialias) EVT_MENU (ID_G_FULLSCRN, FFrame::OnSwitchFullScreen) EVT_MENU (ID_G_V_ALL, FFrame::OnGViewAll) EVT_MENU (ID_G_V_VERT, FFrame::OnGFitHeight) EVT_MENU (ID_G_SHOWY0, FFrame::OnGShowY0) EVT_MENU (ID_G_V_SCROLL_L, FFrame::OnGScrollLeft) EVT_MENU (ID_G_V_SCROLL_R, FFrame::OnGScrollRight) EVT_MENU (ID_G_V_SCROLL_U, FFrame::OnGScrollUp) EVT_MENU (ID_G_V_EXTH, FFrame::OnGExtendH) EVT_MENU_RANGE (ID_G_V_ZOOM_FIRST, ID_G_V_ZOOM_PREV_END, FFrame::OnPreviousZoom) EVT_MENU (ID_G_LCONFB, FFrame::OnConfigBuiltin) EVT_MENU_RANGE (ID_G_LCONF_X, ID_G_LCONF_X_END, FFrame::OnConfigX) EVT_MENU (ID_G_SCONFD, FFrame::OnSaveDefaultConfig) EVT_MENU (ID_G_SCONFAS, FFrame::OnSaveConfigAs) EVT_MENU (ID_H_MANUAL, FFrame::OnShowHelp) EVT_MENU (ID_H_WEBSITE, FFrame::OnOnline) EVT_MENU (ID_H_WIKI, FFrame::OnOnline) EVT_MENU (ID_H_DISCUSSIONS, FFrame::OnOnline) EVT_MENU (ID_H_FEEDBACK, FFrame::OnOnline) EVT_MENU_RANGE (ID_H_EXAMPLE1, ID_H_EXAMPLE4, FFrame::OnExample) EVT_MENU (wxID_ABOUT, FFrame::OnAbout) EVT_MENU (wxID_EXIT, FFrame::OnQuit) END_EVENT_TABLE() FFrame::FFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const long style) : wxFrame(parent, id, title, wxDefaultPosition, wxDefaultSize, style), main_pane_(NULL), sidebar_(NULL), status_bar_(NULL), toolbar_(NULL), zoom_hist_(ftk->view.str()) { const int default_peak_nr = 7; // Gaussian wxConfigBase *config = wxConfig::Get(); peak_type_nr_ = config->Read(wxT("/DefaultFunctionType"), default_peak_nr); update_peak_type_list(); // Load icon and bitmap SetIcon (wxICON (fityk)); script_dir_ = config->Read(wxT("/execScriptDir")); export_dir_ = config->Read(wxT("/exportDir")); data_dir_ = config->Read(wxT("/loadDataDir")); //sizer, splitters, etc. wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); v_splitter_ = new ProportionalSplitter(this); main_pane_ = new ProportionalSplitter(v_splitter_); plot_pane_ = new PlotPane(main_pane_); text_pane_ = new TextPane(main_pane_); main_pane_->SplitHorizProp(plot_pane_, text_pane_); sidebar_ = new SideBar(v_splitter_); sidebar_->Show(false); v_splitter_->Initialize(main_pane_); sizer->Add(v_splitter_, 1, wxEXPAND, 0); set_menubar(); toolbar_ = new FToolBar(this, -1); toolbar_->update_peak_type(peak_type_nr_, &peak_types_); SetToolBar(toolbar_); // Realize() is called here and in SwitchToolbar() not in FToolBar ctor // as a workaround for wxOSX/Cocoa problem: // http://trac.wxwidgets.org/ticket/13888 toolbar_->Realize(); //status bar status_bar_ = new FStatusBar(this); sizer->Add(status_bar_, 0, wxEXPAND, 0); SetSizer(sizer); sizer->SetSizeHints(this); print_mgr_ = new PrintManager(plot_pane_); update_menu_functions(); update_menu_saved_transforms(); update_menu_recent_baselines(); get_main_plot()->set_hint_receiver(status_bar_); text_pane_->SetFocus(); } FFrame::~FFrame() { wxConfigBase *common_config = wxConfig::Get(); recent_scripts_->save_to_config(common_config); recent_data_->save_to_config(common_config); common_config->Write(wxT("/DefaultFunctionType"), peak_type_nr_); delete print_mgr_; #ifdef __WXMAC__ // On wxCarbon 2.9.2svn assertion pops up on exit // (from wxObject::CreateRefData src/common/object.cpp:418). // It's somehow related to the toolbar. This is a workaround: SwitchToolbar(false); #endif } void FFrame::OnQuit(wxCommandEvent&) { Close(true); } void FFrame::update_peak_type_list() { peak_types_.clear(); v_foreach(fityk::Tplate::Ptr, i, ftk->get_tpm()->tpvec()) peak_types_.push_back((*i)->name); if (peak_type_nr_ >= (int) peak_types_.size()) peak_type_nr_ = 0; if (toolbar_) toolbar_->update_peak_type(peak_type_nr_, &peak_types_); } void FFrame::add_recent_data_file(const wxString& filename) { recent_data_->add(filename, ""); } void FFrame::read_all_settings(wxConfigBase *cf) { read_settings(cf); plot_pane_->read_settings(cf); text_pane_->output_win->read_settings(cf); status_bar_->read_settings(cf); sidebar_->read_settings(cf); sidebar_->update_lists(); } void FFrame::read_settings(wxConfigBase *cf) { // restore window layout, frame position and size cf->SetPath(wxT("/Frame")); SwitchToolbar(cfg_read_bool(cf, wxT("ShowToolbar"), true)); SwitchStatbar(cfg_read_bool(cf, wxT("ShowStatbar"), true)); int display_w, display_h; wxDisplaySize(&display_w, &display_h); int default_h = display_h >= 768 ? 670 : 480; int default_w = default_h * 3 / 2; int w = cf->Read(wxT("w"), default_w), h = cf->Read(wxT("h"), default_h); SetSize(w, h); v_splitter_->SetProportion( cfg_read_double(cf, wxT("VertSplitProportion"), 0.75)); SwitchSideBar(cfg_read_bool(cf, wxT("ShowSideBar"), true)); main_pane_->SetProportion( cfg_read_double(cf, wxT("MainPaneProportion"), 0.84)); SwitchTextPane(cfg_read_bool(cf, wxT("ShowTextPane"), true)); SwitchCrosshair(cfg_read_bool(cf, wxT("ShowCrosshair"), false)); antialias_ = cfg_read_bool(cf, wxT("AntiAliasing"), true); GetMenuBar()->Check(ID_G_ANTIALIAS, antialias_); ftk->view.set_y0_factor(cfg_read_double(cf, wxT("ShowY0"), 10)); GetMenuBar()->Check(ID_G_SHOWY0, ftk->view.y0_factor() != 0); } void FFrame::save_all_settings(wxConfigBase *cf) const { cf->Write(wxT("/FitykVersion"), pchar2wx(VERSION)); save_settings(cf); plot_pane_->save_settings(cf); text_pane_->output_win->save_settings(cf); status_bar_->save_settings(cf); sidebar_->save_settings(cf); } void FFrame::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("/Frame")); cf->Write(wxT("ShowToolbar"), toolbar_ != 0); cf->Write(wxT("ShowStatbar"), status_bar_ != 0); cf->Write(wxT("VertSplitProportion"), v_splitter_->GetProportion()); cf->Write(wxT("ShowSideBar"), v_splitter_->IsSplit()); cf->Write(wxT("MainPaneProportion"), main_pane_->GetProportion()); cf->Write(wxT("ShowTextPane"), main_pane_->IsSplit()); cf->Write(wxT("ShowCrosshair"), get_main_plot()->crosshair_cursor()); cf->Write(wxT("AntiAliasing"), antialias_); cf->Write(wxT("ShowY0"), ftk->view.y0_factor()); int w, h; GetSize(&w, &h); cf->Write(wxT("w"), (long) w); cf->Write(wxT("h"), (long) h); //cf->Write (wxT("BotWinHeight"), bottom_window->GetClientSize().GetHeight()); } void FFrame::set_menubar() { recent_data_ = new RecentFiles(ID_D_RECENT+1, "/RecentDataFiles"); recent_scripts_ = new RecentFiles(ID_SESSION_RECENT+1, "/RecentScriptFiles"); wxConfigBase *common_config = wxConfig::Get(); recent_data_->load_from_config(common_config); recent_scripts_->load_from_config(common_config); wxMenu* session_menu = new wxMenu; append_mi(session_menu, ID_SESSION_INCLUDE, GET_BMP(runmacro16), wxT("&Execute Script\tCtrl-X"), wxT("Execute commands from a file")); wxMenu *session_new_script_menu = new wxMenu; session_new_script_menu->Append(ID_SESSION_NEW_F, "&Blank Fityk Script"); session_new_script_menu->Append(ID_SESSION_NEW_L, "Blank &Lua Script"); session_new_script_menu->Append(ID_SESSION_NEW_H, "&From Command History"); session_menu->Append(-1, "&New Script", session_new_script_menu); append_mi(session_menu, ID_SCRIPT_EDIT, GET_BMP(editor16), wxT("E&dit Script"), wxT("Show script editor")); session_menu->Append(ID_SESSION_RECENT, "&Recent Scripts", recent_scripts_->menu()); #ifdef __WXMAC__ session_menu->Append (ID_SESSION_NEWWIN, "New Window", "Open new window (new process)"); #endif session_menu->AppendSeparator(); append_mi(session_menu, ID_SESSION_LOAD, GET_BMP(fileopen16), "&Load Session", "Reset session and execute script"); append_mi(session_menu, ID_SESSION_SAVE, GET_BMP(filesaveas16), wxT("&Save Session..."), wxT("Save current program state (as fityk script)")); append_mi(session_menu, ID_SAVE_HISTORY, GET_BMP(filesaveas16), wxT("Save &History..."), wxT("Save all commands executed so far to file (fityk script)")); wxMenu *session_log_menu = new wxMenu; append_mi(session_log_menu, ID_LOG_START, GET_BMP(recordmacro16), wxT("Choose Log File"), wxT("Start logging commands to file")); append_mi(session_log_menu, ID_LOG_STOP, GET_BMP(stopmacro16), wxT("Stop Logging"), wxT("Finish logging commands to file")); session_log_menu->AppendCheckItem(ID_LOG_WITH_OUTPUT,wxT("Log also output"), wxT("output can be included in logfile as comments")); session_menu->Append(ID_SESSION_LOG, wxT("Logging"), session_log_menu); session_menu->AppendSeparator(); session_menu->Append(ID_PAGE_SETUP, wxT("Page Se&tup..."), wxT("Page setup")); session_menu->Append(wxID_PRINT, wxT("&Print...\tCtrl-P"), wxT("Print plots")); session_menu->AppendSeparator(); session_menu->Append(ID_COPY_TO_CLIPB, wxT("&Copy to Clipboard"), wxT("Copy main plot to clipboard.")); append_mi(session_menu, ID_SAVE_IMAGE, GET_BMP(image16), wxT("Sa&ve as Image..."), wxT("Save plot as PNG image.")); session_menu->AppendSeparator(); append_mi(session_menu, ID_SESSION_SET, GET_BMP(preferences16), wxT("&Settings"), wxT("Preferences and options")); session_menu->Append (ID_SESSION_EI, wxT("Edit &Init File"), wxT("Edit the script run at startup")); session_menu->AppendSeparator(); append_mi(session_menu, ID_SESSION_RESET, GET_BMP(reload16), wxT("&Reset"), wxT("Reset current session")); session_menu->Append(wxID_EXIT, wxT("&Quit")); wxMenu* data_menu = new wxMenu; append_mi(data_menu, ID_D_QLOAD, GET_BMP(fileopen16), wxT("&Quick Load File\tCtrl-O"), wxT("Load data from file")); append_mi(data_menu, ID_D_XLOAD, GET_BMP(fileopen16), wxT("&Load File\tCtrl-M"), wxT("Load data from file, with some options")); data_menu->Append(ID_D_RECENT, "&Recent Files", recent_data_->menu()); append_mi(data_menu, ID_D_REVERT, GET_BMP(revert16), wxT("Re&vert"), wxT("Reload data from file(s)")); data_menu->AppendSeparator(); data_menu->Append (ID_D_TABLE, wxT("T&able"), wxT("Data Table")); this->data_ft_menu_ = new wxMenu; data_menu->Append (ID_D_SDT, wxT("&Transformations"), data_ft_menu_, wxT("Custom data transformations")); data_menu->Append (ID_D_EDITOR, wxT("E&dit Transformations..."), wxT("Open editor of data operations")); data_menu->AppendSeparator(); data_menu->Append (ID_D_MERGE, wxT("&Merge Points..."), wxT("Reduce the number of points")); wxMenu* data_xps_menu = new wxMenu; data_xps_menu->Append(ID_D_RM_SHIRLEY, wxT("&Remove Shirley BG"), wxT("Remove Shirley BG")); data_xps_menu->Append(ID_D_CALC_SHIRLEY, wxT("&Calculate Shirley BG"), wxT("put Shirley BG to new dataset")); data_menu->Append(-1, wxT("&XPS"), data_xps_menu); data_menu->AppendSeparator(); append_mi(data_menu, ID_D_EXPORT, GET_BMP(export16), wxT("&Export Points\tCtrl-S"), wxT("Save data to file")); wxMenu* sum_menu = new wxMenu; func_type_menu_ = new wxMenu; sum_menu->Append (ID_G_M_PEAK, wxT("Function &Type"), func_type_menu_); // the function list is created in update_menu_functions() append_mi(sum_menu, ID_DEFMGR, GET_BMP(function16), wxT("&Definition Manager"), wxT("Add or modify funtion types")); sum_menu->Append (ID_S_GUESS, wxT("&Guess Peak"),wxT("Guess and add peak")); /* this item doesn't add much to the program, remove it for now sum_menu->Append (ID_S_PFINFO, wxT("Peak-Find &Info"), wxT("Show where guessed peak would be placed")); */ sum_menu->AppendCheckItem(ID_S_AUTOFREEZE, wxT("Auto-Freeze"), wxT("In Data-Range mode: freeze functions in disactivated range")); sum_menu->AppendSeparator(); append_mi(sum_menu, ID_S_EXPORTP, GET_BMP(export16), wxT("&Export Peak Parameters"), wxT("Export function parameters to file")); append_mi(sum_menu, ID_S_EXPORTF, GET_BMP(export16), wxT("&Export Formula"), wxT("Export mathematic formula to file")); append_mi(sum_menu, ID_S_EXPORTD, GET_BMP(export16), wxT("&Export Points"), wxT("Export points to file")); wxMenu* fit_menu = new wxMenu; wxMenu* fit_method_menu = new wxMenu; for (int i = 0; FitManager::method_list[i][0] != NULL; ++i) fit_method_menu->AppendRadioItem(ID_F_M+i, wxString("&") + FitManager::method_list[i][1], FitManager::method_list[i][2]); fit_menu->Append (ID_F_METHOD, wxT("&Method"), fit_method_menu, wxT("")); fit_menu->AppendSeparator(); append_mi(fit_menu, ID_F_RUN, GET_BMP(run16), wxT("&Run...\tCtrl-R"), wxT("Fit sum to data")); append_mi(fit_menu, ID_F_INFO, GET_BMP(info16), wxT("&Info"), wxT("Info about current fit")); fit_menu->AppendSeparator(); append_mi(fit_menu, ID_F_UNDO, GET_BMP(undo16), wxT("&Undo"), wxT("Undo change of parameter")); append_mi(fit_menu, ID_F_REDO, GET_BMP(redo16), wxT("R&edo"), wxT("Redo change of parameter")); fit_menu->Append (ID_F_HISTORY, wxT("&Parameter History"), wxT("Go back or forward in parameter history")); wxMenu* tools_menu = new wxMenu; append_mi(tools_menu, ID_T_PD, wxBitmap(powdifpat16_xpm), wxT("&Powder Diffraction"), wxT("A tool for Pawley fitting")); tools_menu->Append(ID_T_KEBE, "&XPS KE<->BE", "Requires known source energy"); wxMenu* gui_menu = new wxMenu; wxMenu* gui_menu_mode = new wxMenu; gui_menu_mode->AppendRadioItem (ID_G_M_ZOOM, wxT("&Normal\tF1"), wxT("Use mouse for zooming, moving peaks etc.")); gui_menu_mode->AppendRadioItem (ID_G_M_RANGE, wxT("&Range\tF2"), wxT("Use mouse for activating and disactivating data")); gui_menu_mode->AppendRadioItem (ID_G_M_BG, wxT("&Baseline\tF3"), wxT("Use mouse for subtracting background")); gui_menu_mode->AppendRadioItem (ID_G_M_ADD, wxT("&Peak-Add\tF4"), wxT("Use mouse for adding new peaks")); gui_menu->Append(ID_G_MODE, wxT("&Mode"), gui_menu_mode); wxMenu* baseline_menu = new wxMenu; baseline_menu->Append (ID_G_BG_STRIP, wxT("&Subtract Baseline"), wxT("Subtract baseline function from data")); baseline_menu->Append (ID_G_BG_UNDO, wxT("&Add Baseline"), wxT("Add baseline function to data")); baseline_menu->Append (ID_G_BG_CLEAR, wxT("&Clear Baseline"), wxT("Clear baseline points, disable undo")); wxMenu* recent_b_menu = new wxMenu; baseline_menu->AppendSeparator(); baseline_menu->Append(ID_G_BG_RECENT, wxT("&Recent"), recent_b_menu); baseline_menu->Append (ID_G_BG_HULL, wxT("&Set As Convex Hull"), wxT("Set baseline as convex hull of data")); baseline_menu->AppendSeparator(); baseline_menu->AppendCheckItem(ID_G_BG_SPLINE, wxT("Cubic &Spline"), wxT("Cubic spline interpolation of points")); baseline_menu->Check(ID_G_BG_SPLINE, true); gui_menu->Append(ID_G_BG_SUB, wxT("&Baseline Handling"), baseline_menu); gui_menu->AppendSeparator(); wxMenu* gui_menu_show = new wxMenu; gui_menu_show->AppendCheckItem (ID_G_S_TOOLBAR, wxT("&Toolbar"), wxT("Show/hide toolbar")); gui_menu_show->Check(ID_G_S_TOOLBAR, true); gui_menu_show->AppendCheckItem (ID_G_S_STATBAR, wxT("&Status Bar"), wxT("Show/hide status bar")); gui_menu_show->Check(ID_G_S_STATBAR, true); gui_menu_show->AppendCheckItem (ID_G_S_SIDEB, wxT("&SideBar"), wxT("Show/hide pane at right hand side")); gui_menu_show->AppendCheckItem (ID_G_S_A1, wxT("&Auxiliary Plot 1"), wxT("Show/hide auxiliary plot I")); gui_menu_show->Check(ID_G_S_A1, true); gui_menu_show->AppendCheckItem (ID_G_S_A2, wxT("A&uxiliary Plot 2"), wxT("Show/hide auxiliary plot II")); gui_menu_show->Check(ID_G_S_A2, false); gui_menu_show->AppendCheckItem (ID_G_S_TEXT, wxT("&Input/Output Text Pane"), wxT("Show/hide text input/output")); gui_menu_show->Check(ID_G_S_TEXT, true); gui_menu->Append(ID_G_SHOW, wxT("S&how"), gui_menu_show); wxMenu* gui_menu_config = new wxMenu; gui_menu_config->Append(ID_G_C_MAIN, wxT("&Main Plot"), wxT("Show main plot pop-up menu")); gui_menu_config->Append(ID_G_C_A1, wxT("&Auxliliary Plot 1"), wxT("Show aux. plot 1 pop-up menu")); gui_menu_config->Append(ID_G_C_A2, wxT("A&uxliliary Plot 2"), wxT("Show aux. plot 2 pop-up menu")); gui_menu_config->Append(ID_G_C_OUTPUT, wxT("&Output Window"), wxT("Configure output window")); gui_menu_config->Append(ID_G_C_SB, wxT("&Status Bar"), wxT("Configure Status Bar")); gui_menu_config->Append(ID_G_C_DIRS, "&Default Directories", "Configure output window"); gui_menu->Append(-1, wxT("Confi&gure"), gui_menu_config); gui_menu->AppendCheckItem(ID_G_CROSSHAIR, wxT("&Crosshair Cursor"), wxT("Show crosshair cursor")); gui_menu->AppendCheckItem(ID_G_ANTIALIAS, wxT("&Anti-aliasing"), wxT("Switch anti-aliasing")); gui_menu->AppendCheckItem(ID_G_FULLSCRN, wxT("&Full Screen\tF11"), wxT("Switch full screen")); gui_menu->AppendSeparator(); wxMenu* gui_menu_zoom = new wxMenu; append_mi(gui_menu_zoom, ID_G_V_ALL, GET_BMP(zoom_fit16), wxT("Zoom &All\tCtrl-A"), wxT("View whole data")); gui_menu_zoom->Append(ID_G_V_VERT, wxT("Fit &Vertically\tCtrl-V"), wxT("Adjust vertical zoom")); gui_menu_zoom->Append(ID_G_V_SCROLL_L, wxT("Scroll &Left\tCtrl-["), wxT("Scroll view left")); gui_menu_zoom->Append(ID_G_V_SCROLL_R, wxT("Scroll &Right\tCtrl-]"), wxT("Scroll view right")); gui_menu_zoom->Append(ID_G_V_SCROLL_U, wxT("Extend Zoom &Up\tCtrl--"), wxT("Double vertical range")); gui_menu_zoom->Append(ID_G_V_EXTH, wxT("Extend &Horizontally\tCtrl-;"), wxT("Extend zoom horizontally")); gui_menu->Append(-1, wxT("Plot &Range"), gui_menu_zoom); gui_menu->AppendCheckItem(ID_G_SHOWY0, wxT("Zoom All Shows Y=&0"), wxT("Tend to include Y=0 when adjusting view.")); wxMenu* gui_menu_zoom_prev = new wxMenu; gui_menu->Append(ID_G_V_ZOOM_PREV, wxT("&Zoom History"), gui_menu_zoom_prev); gui_menu->AppendSeparator(); wxMenu* gui_menu_lconfig = new wxMenu; gui_menu_lconfig->Append(ID_G_LCONFB, wxT("&built-in"), wxT("Built-in configuration")); gui_menu_lconfig->AppendSeparator(); update_config_menu(gui_menu_lconfig); gui_menu->Append(ID_G_LCONF, wxT("&Load Config..."), gui_menu_lconfig); wxMenu* gui_menu_sconfig = new wxMenu; gui_menu_sconfig->Append(ID_G_SCONFD, wxT("As Default"), wxT("Save current configuration to default config file")); gui_menu_sconfig->Append(ID_G_SCONFAS, wxT("As ..."), wxT("Save current configuration to other config file")); gui_menu->Append(ID_G_SCONF, wxT("&Save Current Config"), gui_menu_sconfig); wxMenu *help_menu = new wxMenu; append_mi(help_menu, ID_H_MANUAL, GET_BMP(book16), wxT("&Manual"), wxT("User's Manual")); append_mi(help_menu, ID_H_WEBSITE, GET_BMP(web16), wxT("&Visit Website"), website_url); append_mi(help_menu, ID_H_WIKI, GET_BMP(web16), wxT("&Visit Wiki"), wiki_url); append_mi(help_menu, ID_H_DISCUSSIONS, GET_BMP(web16), wxT("&Visit Discussions"), discussions_url); /* append_mi(help_menu, ID_H_FEEDBACK, GET_BMP(web16), wxT("&Anonymous Feedback"), feedback_url); */ wxMenu* help_menu_examples = new wxMenu; help_menu_examples->Append(ID_H_EXAMPLE1, wxT("&Single Peak"), wxT("nacl01.fit")); help_menu_examples->Append(ID_H_EXAMPLE2, wxT("&Multiple Peaks"), wxT("SiC_Zn.fit")); help_menu_examples->Append(ID_H_EXAMPLE3, wxT("Southern &Oscillation"), wxT("enso.fit")); help_menu_examples->Append(ID_H_EXAMPLE4, wxT("&Read-Shockley equation"), wxT("read-shockley.fit")); help_menu->Append(-1, wxT("&Examples"), help_menu_examples); help_menu->Append(wxID_ABOUT, wxT("&About..."), wxT("Show about dialog")); wxMenuBar *menu_bar = new wxMenuBar(); menu_bar->Append (session_menu, wxT("&Session") ); menu_bar->Append (data_menu, wxT("&Data") ); menu_bar->Append (sum_menu, wxT("&Functions") ); menu_bar->Append (fit_menu, wxT("F&it") ); menu_bar->Append (tools_menu, wxT("&Tools") ); menu_bar->Append (gui_menu, wxT("&GUI")); menu_bar->Append (help_menu, wxT("&Help")); SetMenuBar(menu_bar); } static void clear_menu(wxMenu *menu) { for (int i = menu->GetMenuItemCount()-1; i >= 0; --i) { #ifndef __WXOSX__ wxMenuItem *item = menu->FindItemByPosition(i); #else // workaround for http://trac.wxwidgets.org/ticket/15956 wxMenuItem *item = menu->FindItemByPosition(0); #endif menu->Destroy(item); } } //construct GUI->Previous Zooms menu void FFrame::update_menu_previous_zooms() { static size_t old_pos = (size_t) -1; size_t pos = zoom_hist_.pos(); if (old_pos == pos) return; wxMenu *menu = GetMenuBar()->FindItem(ID_G_V_ZOOM_PREV)->GetSubMenu(); clear_menu(menu); const vector& items = zoom_hist_.items(); int last = std::min(items.size() - 1, pos + 5); for (int i = last; i >= 0 && i > last - 10; i--) menu->AppendRadioItem(ID_G_V_ZOOM_FIRST + i, s2wx(items[i])); menu->Check(ID_G_V_ZOOM_FIRST + pos, true); old_pos = pos; if (toolbar_) toolbar_->EnableTool(ID_T_PZ, zoom_hist_.pos() > 0); } // construct GUI -> Baseline Handling -> Previous menu void FFrame::update_menu_recent_baselines() { wxMenu *menu = GetMenuBar()->FindItem(ID_G_BG_RECENT)->GetSubMenu(); clear_menu(menu); for (int i = 0; i < 10; ++i) { wxString name = get_main_plot()->bgm()->get_recent_bg_name(i); if (name.empty()) break; if (i == 0) name += wxT("\tShift-F3"); menu->Append(ID_G_BG_RECENT+i+1, name); } } void FFrame::OnShowHelp(wxCommandEvent&) { wxString help_url = get_help_url(wxT("fityk-manual.html")); bool r = wxLaunchDefaultBrowser(help_url); if (!r) wxMessageBox(wxT("Can't open browser.\nManual is here:\n") + help_url, wxT("Manual"), wxOK|wxICON_INFORMATION); } void FFrame::OnAbout(wxCommandEvent&) { AboutDlg* dlg = new AboutDlg(this); dlg->ShowModal(); dlg->Destroy(); } void FFrame::OnOnline(wxCommandEvent& event) { const wxString* url; if (event.GetId() == ID_H_WEBSITE) url = &website_url; else if (event.GetId() == ID_H_WIKI) url = &wiki_url; else if (event.GetId() == ID_H_DISCUSSIONS) url = &discussions_url; else //if (event.GetId() == ID_H_FEEDBACK) url = &feedback_url; bool r = wxLaunchDefaultBrowser(*url); if (!r) wxMessageBox(wxT("Can not open URL in browser,") wxT("\nplease open it manually:\n") + *url, wxT("Browser Launch Failed"), wxOK); } void FFrame::OnExample(wxCommandEvent& event) { int id = event.GetId(); wxString filename = GetMenuBar()->FindItem(id)->GetHelp(); wxString path = get_sample_path(filename); if (path.empty()) { wxMessageBox(wxT("Example files not found."), wxT("Sorry"), wxOK|wxICON_ERROR); return; } int r = wxMessageBox(wxT("This will reset current session.\n") wxT("Do you want to continue?"), wxT("Are you sure?"), wxYES_NO | wxCENTRE | wxICON_QUESTION); if (r == wxYES) { get_main_plot()->bgm()->clear_background(); exec("reset; exec '" + wx2s(path) + "'"); } } namespace { wxWindow* qload_filedialog_extra(wxWindow* parent) { bool def_sqrt = (S(ftk->get_settings()->default_sigma) == "sqrt"); bool decimal_comma = wxConfig::Get()->ReadBool("decimalComma", false); return new Extra2CheckBoxes(parent, wxT("data weighting: \u03C3=max(\u221Ay, 1)"), def_sqrt, "decimal comma", decimal_comma); } } // anonymous namespace void FFrame::OnDataQLoad (wxCommandEvent&) { wxFileDialog fdlg (this, wxT("Load data from a file"), data_dir_, wxT(""), wxT("All Files (*)|*|") + s2wx(xylib::get_wildcards_string()), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE); // on wxOSX/Carbon SetExtraControlCreator() is unreliable #ifndef __WXOSX_CARBON__ fdlg.SetExtraControlCreator(&qload_filedialog_extra); #endif int ret = fdlg.ShowModal(); data_dir_ = fdlg.GetDirectory(); if (ret != wxID_OK) return; string cmd; string options; wxWindow *extra = fdlg.GetExtraControl(); if (extra != NULL) { Extra2CheckBoxes *extracb = wxDynamicCast(extra,Extra2CheckBoxes); string selected = extracb->is_checked1() ? "sqrt" : "one"; if (ftk->get_settings()->default_sigma != selected) cmd = "with default_sigma=" + selected + " "; bool decimal_comma = extracb->is_checked2(); if (decimal_comma) options += "decimal_comma"; wxConfig::Get()->Write("decimalComma", decimal_comma); } wxArrayString paths; fdlg.GetPaths(paths); int count = paths.GetCount(); if (count == 1) { string f = wx2s(paths[0]); if (endswith(f, ".fit")) { int r = wxMessageBox( "The .fit file is probably a Fityk script\n" "(or a saved session, which is also a script).\n" "To run the script, click Cancel and use\n" "Session > Execute Script (Ctrl-X).\n\n" "To load it as a data file, click OK.", wxT("Continue?"), wxOK|wxCANCEL | wxCENTRE | wxICON_QUESTION); if (r != wxOK) return; } try { dataset_shared_ptr d = xylib::cached_load_file(f, "", ""); if (d->get_block_count() > 1) { wxArrayString choices; for (int i = 0; i < d->get_block_count(); ++i) { wxString name = s2wx(d->get_block(i)->get_name()); if (name.empty()) name.Printf(wxT("Block #%d"), i+1); choices.push_back(name); } wxMultiChoiceDialog mdlg(this, wxT("Select data blocks:"), wxT("Choose blocks"), choices); wxArrayInt sel; sel.push_back(0); mdlg.SetSelections(sel); if (mdlg.ShowModal() != wxID_OK) return; sel = mdlg.GetSelections(); paths.clear(); for (size_t i = 0; i < sel.size(); ++i) paths.push_back(s2wx(f + "::::" + S(sel[i]))); } } catch (const std::runtime_error& /*e*/) { } // ignore the exception here, it'll be thrown later } bool has_single_quote = false; for (size_t i = 0; i < paths.size(); ++i) { if (i != 0) cmd += " ; "; if (!has_single_quote) if (paths[i].Find('\'') != wxNOT_FOUND) { has_single_quote = true; cmd += "lua "; } if (has_single_quote) { // very special case cmd += "F:load(-1, [[" + wx2s(paths[i]) + "]], 0, 1, 2, 0, '', '" + options + "')"; } else { cmd += "@+ <'" + wx2s(paths[i]) + "'"; if (!options.empty()) cmd += " _ " + options; } recent_data_->add(paths[i], options.empty() ? "" : "_ "+options); } exec(cmd); if (count > 1) SwitchSideBar(true); } void FFrame::OnDataXLoad (wxCommandEvent&) { vector sel = get_selected_data_indices(); int n = (sel.size() == 1 ? sel[0] : -1); // in case of multi-selection, use the first item fityk::Data *data = ftk->dk.data(sel[0]); DLoadDlg dload_dialog(this, n, data, data_dir_); dload_dialog.ShowModal(); } void FFrame::OnDataRecent (wxCommandEvent& event) { const RecentFiles::Item& item = recent_data_->pull(event.GetId()); wxString path = item.fn.GetFullPath(); if (path.Find('\'') == wxNOT_FOUND) { string cmd = "@+ <'" + wx2s(path) + "'"; if (!item.options.empty()) cmd += " " + item.options; exec(cmd); } else { // very special case // ignoring options exec("lua F:load(-1, [[" + wx2s(path) + "]])"); } } void FFrame::OnDataRevertUpdate (wxUpdateUIEvent& event) { vector sel = get_selected_data_indices(); event.Enable(sel.size() == 1 && !ftk->dk.data(sel[0])->get_filename().empty()); } void FFrame::OnDataRevert (wxCommandEvent&) { vector sel = get_selected_data_indices(); string cmd; for (vector::const_iterator i = sel.begin(); i != sel.end(); ++i) { if (i != sel.begin()) cmd += "; "; cmd += "@" + S(*i) + "< ."; } exec(cmd); } void FFrame::OnDataTable(wxCommandEvent&) { int data_nr = get_focused_data_index(); DataTableDlg data_table(this, -1, data_nr, ftk->dk.data(data_nr)); data_table.ShowModal(); } void FFrame::OnDataEditor (wxCommandEvent&) { vector > dd; vector sel = get_selected_data_indices(); for (vector::const_iterator i = sel.begin(); i != sel.end(); ++i) dd.push_back(std::make_pair(*i, ftk->dk.data(*i))); EditTransDlg data_editor(this, -1, dd); data_editor.ShowModal(); update_menu_saved_transforms(); } void FFrame::update_menu_saved_transforms() { // delete old items int item_count = data_ft_menu_->GetMenuItemCount(); for (int i = 0; i != item_count; ++i) data_ft_menu_->Delete(ID_D_SDT+i+1); // create new items const vector &all = EditTransDlg::get_transforms(); int counter = 0; for (vector::const_iterator i = all.begin(); i != all.end(); ++i) if (i->in_menu) { ++counter; data_ft_menu_->Append(ID_D_SDT+counter, i->name, i->description); } } void FFrame::OnSavedDT (wxCommandEvent& event) { wxString name = GetMenuBar()->GetLabel(event.GetId()); const vector &transforms = EditTransDlg::get_transforms(); for (vector::const_iterator i = transforms.begin(); i != transforms.end(); ++i) if (i->name == name) { EditTransDlg::execute_tranform(wx2s(i->code)); return; } } void FFrame::OnDataMerge (wxCommandEvent&) { MergePointsDlg *dlg = new MergePointsDlg(this); if (dlg->ShowModal() == wxID_OK) exec(dlg->get_command()); dlg->Destroy(); } void FFrame::OnDataCalcShirley (wxCommandEvent&) { vector sel = get_selected_data_indices(); for (vector::const_iterator i = sel.begin(); i != sel.end(); ++i) { string title = ftk->dk.data(*i)->get_title(); int c = ftk->dk.count(); exec("@+ = shirley_bg(@" + S(*i) + ")"); exec("@" + S(c) + ": title = '" + title + "-Shirley'"); } } void FFrame::OnDataRmShirley (wxCommandEvent&) { vector sel = get_selected_data_indices(); string cmd; for (vector::const_iterator i = sel.begin(); i != sel.end(); ++i) { string dstr = "@" + S(*i); if (i != sel.begin()) cmd += "; "; cmd += dstr + " = " + dstr + " - shirley_bg(" + dstr + ")"; } exec(cmd); } void FFrame::OnDataExport (wxCommandEvent&) { export_data_dlg(get_selected_data_indices(), this, &export_dir_); } void FFrame::OnDefinitionMgr(wxCommandEvent&) { DefinitionMgrDlg* dlg = new DefinitionMgrDlg(this); if (dlg->ShowModal() == wxID_OK) { vector commands = dlg->get_commands(); v_foreach (string, c, commands) exec(*c); } dlg->Destroy(); } void FFrame::OnSGuess (wxCommandEvent&) { exec(get_datasets() + "guess " + get_guess_string(get_peak_type())); } void FFrame::OnSPFInfo (wxCommandEvent&) { exec(get_datasets() + "info guess"); } void FFrame::OnAutoFreeze(wxCommandEvent& event) { plot_pane_->get_plot()->set_auto_freeze(event.IsChecked()); } void FFrame::OnModelExport(wxCommandEvent&) { ModelInfoDlg dlg(this, -1); if (!dlg.Initialize()) return; if (dlg.ShowModal() == wxID_OK) export_as_info(dlg.get_info_cmd(), "Export to file", ".formula", "mathematic formula (*.formula)|*.formula"); } void FFrame::OnParametersExport(wxCommandEvent&) { export_peak_parameters(get_selected_data_indices(), this, &export_dir_); } void FFrame::export_as_info(const string& info, const char* caption, const char* ext, const char* wildcards) { wxString name; vector sel = get_selected_data_indices(); if (sel.size() == 1) { const string& filename = ftk->dk.data(sel[0])->get_filename(); if (!filename.empty()) name = wxFileName(s2wx(filename)).GetName() + ext; } wxFileDialog fdlg(this, caption, export_dir_, name, wildcards + wxString("|all files|*"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (fdlg.ShowModal() == wxID_OK) { exec_redirected_command(sel, info, fdlg.GetPath()); } export_dir_ = fdlg.GetDirectory(); } void FFrame::OnFMethodUpdate (wxUpdateUIEvent& event) { int n = ftk->settings_mgr()->get_enum_index("fitting_method"); event.Check(ID_F_M + n == event.GetId()); } void FFrame::OnMenuFitRunUpdate(wxUpdateUIEvent& event) { event.Enable(!ftk->mgr.parameters().empty()); } void FFrame::OnMenuFitUndoUpdate(wxUpdateUIEvent& event) { event.Enable(ftk->fit_manager()->can_undo()); } void FFrame::OnMenuFitRedoUpdate(wxUpdateUIEvent& event) { event.Enable(ftk->fit_manager()->has_param_history_rel_item(1)); } void FFrame::OnMenuFitHistoryUpdate(wxUpdateUIEvent& event) { event.Enable(ftk->fit_manager()->get_param_history_size() != 0); } void FFrame::OnFOneOfMethods (wxCommandEvent& event) { int m = event.GetId() - ID_F_M; const char** values = ftk->settings_mgr()->get_allowed_values("fitting_method"); exec("set fitting_method=" + S(values[m])); } void FFrame::OnFRun (wxCommandEvent&) { FitRunDlg dlg(this, -1); if (dlg.ShowModal() == wxID_OK) { string cmd = dlg.get_cmd(); exec(cmd); } } void FFrame::OnFInfo (wxCommandEvent&) { FitInfoDlg dlg(this, -1); if (dlg.Initialize()) dlg.ShowModal(); } void FFrame::OnFUndo (wxCommandEvent&) { exec("fit undo"); } void FFrame::OnFRedo (wxCommandEvent&) { exec("fit redo"); } void FFrame::OnFHistory (wxCommandEvent&) { SumHistoryDlg *dialog = new SumHistoryDlg(this, -1); dialog->ShowModal(); dialog->Destroy(); } void FFrame::OnPowderDiffraction (wxCommandEvent&) { PowderDiffractionDlg(this, -1).ShowModal(); } void FFrame::OnXpsKEBE(wxCommandEvent&) { vector dd = get_selected_data_indices(); v_foreach(int, i, dd) { Data *data = ftk->dk.data(*i); double e = data->xps_source_energy(); if (e > 0) { exec("@" + S(*i) + ": X = " + eS(e) + (data->get_x_min() > 0 ? " - x" : " + x")); } else { wxMessageBox("Switching between Kinetic and Binding Energy\n" "works only when the source energy is known\n" "from the data file in VAMAS or other XPS format.", "Unknown source energy", wxOK|wxICON_ERROR); } } } void FFrame::OnMenuLogStartUpdate (wxUpdateUIEvent& event) { event.Enable(ftk->get_settings()->logfile.empty()); } void FFrame::OnMenuLogStopUpdate (wxUpdateUIEvent& event) { event.Enable(!ftk->get_settings()->logfile.empty()); } void FFrame::OnMenuLogOutputUpdate (wxUpdateUIEvent& event) { if (!ftk->get_settings()->logfile.empty()) event.Check(ftk->get_settings()->log_output); } static wxWindow* log_filedialog_extra(wxWindow* parent) { bool init_value = ftk->get_settings()->log_output; return new ExtraCheckBox(parent, "log also output", init_value); } void FFrame::OnLogStart (wxCommandEvent&) { wxFileDialog fdlg (this, wxT("Log to file"), export_dir_, wxT(""), wxT("Fityk script file (*.fit)|*.fit;*.FIT") wxT("|All files |*"), wxFD_SAVE); #ifndef __WXOSX_CARBON__ fdlg.SetExtraControlCreator(&log_filedialog_extra); #endif const string& logfile = ftk->get_settings()->logfile; if (!logfile.empty()) fdlg.SetPath(s2wx(logfile)); if (fdlg.ShowModal() == wxID_OK) { string cmd = "set logfile='" + wx2s(fdlg.GetPath()) + "'"; wxWindow *extra = fdlg.GetExtraControl(); if (extra != NULL) { bool checked = wxDynamicCast(extra,ExtraCheckBox)->is_checked(); if (checked != ftk->get_settings()->log_output) cmd += ", log_output=" + S(checked ? "1" : "0"); } exec(cmd); } export_dir_ = fdlg.GetDirectory(); } void FFrame::OnLogStop (wxCommandEvent&) { exec("set logfile=''"); } void FFrame::OnLogWithOutput (wxCommandEvent& event) { bool checked = event.IsChecked(); GetMenuBar()->Check(ID_LOG_WITH_OUTPUT, checked); exec("set log_output=" + S((int)checked)); } void FFrame::OnSaveHistory (wxCommandEvent&) { wxFileDialog fdlg(this, wxT("Save all commands from this session to file"), export_dir_, wxT(""), wxT("fityk file (*.fit)|*.fit;*.FIT"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (fdlg.ShowModal() == wxID_OK) { exec("info history > '" + wx2s(fdlg.GetPath()) + "'"); } export_dir_ = fdlg.GetDirectory(); } void FFrame::OnReset (wxCommandEvent&) { get_main_plot()->bgm()->clear_background(); exec("reset"); } #ifdef __WXMAC__ void FFrame::OnNewWindow (wxCommandEvent&) { open_new_instance(); } #endif static const char* fityk_lua_wildcards = "all supported scripts|*.fit;*.FIT;*.fit.gz;*.lua;*.LUA|" "Fityk script (*.fit, *.fit.gz)|*.fit;*.FIT;*.fit.gz|" "Lua script (*.lua)|*.lua;*.LUA|" "all files|*"; void FFrame::OnInclude (wxCommandEvent&) { wxFileDialog fdlg(this, "Execute commands from file", script_dir_, "", fityk_lua_wildcards, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (fdlg.ShowModal() == wxID_OK) { wxString path = fdlg.GetPath(); exec("exec '" + wx2s(path) + "'"); recent_scripts_->add(path, ""); } script_dir_ = fdlg.GetDirectory(); } void FFrame::OnRecentScript(wxCommandEvent& event) { wxString s = recent_scripts_->pull(event.GetId()).fn.GetFullPath(); exec("exec '" + wx2s(s) + "'"); } void FFrame::OnNewFitykScript(wxCommandEvent&) { show_editor("", fityk::fityk_version_line + wxString("\n")); } void FFrame::OnNewLuaScript(wxCommandEvent&) { show_editor("", "-- Lua script for Fityk.\n"); } void FFrame::OnNewHistoryScript(wxCommandEvent&) { wxString history = fityk::fityk_version_line + wxString("\n"); v_foreach(UserInterface::Cmd, c, ftk->ui()->cmds()) { history += s2wx(c->str()) + "\n"; } show_editor("", history); } void FFrame::OnScriptEdit(wxCommandEvent&) { wxFileDialog fdlg(this, "Open script file", script_dir_, "", fityk_lua_wildcards, wxFD_OPEN /*| wxFD_FILE_MUST_EXIST*/); if (fdlg.ShowModal() == wxID_OK) show_editor(fdlg.GetPath(), ""); script_dir_ = fdlg.GetDirectory(); } void FFrame::show_editor(const wxString& path, const wxString& content) { EditorDlg* dlg = new EditorDlg(this); if (!path.empty()) dlg->open_file(path); else dlg->new_file_with_content(content); dlg->Show(true); } void FFrame::OnSessionLoad(wxCommandEvent&) { wxFileDialog fdlg(this, "Run script (after resetting session)", script_dir_, "", fityk_lua_wildcards, wxFD_OPEN | wxFD_FILE_MUST_EXIST); if (fdlg.ShowModal() == wxID_OK) { get_main_plot()->bgm()->clear_background(); exec("reset; exec '" + wx2s(fdlg.GetPath()) + "'"); //last_include_path_ = wx2s(fdlg.GetPath()); //GetMenuBar()->Enable(ID_SESSION_RECENT, true); } script_dir_ = fdlg.GetDirectory(); } void FFrame::OnSessionSave(wxCommandEvent&) { wxFileDialog fdlg(this, wxT("Save everything as a script"), export_dir_, wxT(""), wxT("fityk file (*.fit)|*.fit;*.FIT"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (fdlg.ShowModal() == wxID_OK) { exec("info state > '" + wx2s(fdlg.GetPath()) + "'"); } export_dir_ = fdlg.GetDirectory(); } void FFrame::OnSettings (wxCommandEvent&) { SettingsDlg *dialog = new SettingsDlg(this); dialog->ShowModal(); dialog->Destroy(); } void FFrame::OnEditInit (wxCommandEvent&) { wxString startup_file = get_conf_file(fityk::startup_commands_filename()); show_editor(startup_file, ""); } void FFrame::change_mouse_mode(MouseModeEnum mode) { //enum MouseModeEnum { mmd_zoom=0, mmd_bg, mmd_add, mmd_activate, ... int menu_ids[] = { ID_G_M_ZOOM, ID_G_M_BG, ID_G_M_ADD, ID_G_M_RANGE }; int tool_ids[] = { ID_T_ZOOM, ID_T_BG, ID_T_ADD, ID_T_RANGE }; int idx = mode; GetMenuBar()->Check(menu_ids[idx], true); if (toolbar_) { toolbar_->ToggleTool(tool_ids[idx], true); toolbar_->EnableTool(ID_T_STRIP, (mode == mmd_bg)); } get_main_plot()->switch_to_mode(mode); } void FFrame::OnChangeMouseMode (wxCommandEvent& event) { switch (event.GetId()) { case ID_G_M_ZOOM: case ID_T_ZOOM: change_mouse_mode(mmd_zoom); break; case ID_G_M_RANGE: case ID_T_RANGE: change_mouse_mode(mmd_activate); break; case ID_G_M_BG: case ID_T_BG: change_mouse_mode(mmd_bg); break; case ID_G_M_ADD: case ID_T_ADD: change_mouse_mode(mmd_add); break; default: assert(0); } } void FFrame::update_menu_functions() { size_t cnt = func_type_menu_->GetMenuItemCount(); size_t pcnt = peak_types_.size(); // in wxGTK 2.9 (svn 11.2007) in wxMenu::GtkAppend() m_prevRadio is stored // and adding radio-item to menu when the last added radio-item is already // removed will cause error // a workaround is to delete and add all items: static bool was_deleted = false; if (pcnt < cnt) was_deleted = true; else if (pcnt > cnt && was_deleted) { for (size_t i = 0; i < cnt; i++) func_type_menu_->Destroy(ID_G_M_PEAK_N+i); cnt = 0; was_deleted = false; } // -- end of the workaround for (size_t i = 0; i < std::min(pcnt, cnt); i++) if (func_type_menu_->GetLabel(ID_G_M_PEAK_N+i) != s2wx(peak_types_[i])) func_type_menu_->SetLabel(ID_G_M_PEAK_N+i, s2wx(peak_types_[i])); for (size_t i = cnt; i < pcnt; i++) func_type_menu_->AppendRadioItem(ID_G_M_PEAK_N+i, s2wx(peak_types_[i])); for (size_t i = pcnt; i < cnt; i++) func_type_menu_->Destroy(ID_G_M_PEAK_N+i); func_type_menu_->Check(ID_G_M_PEAK_N + peak_type_nr_, true); func_type_menu_->UpdateUI(); } void FFrame::OnChangePeakType(wxCommandEvent& event) { peak_type_nr_ = event.GetId() - ID_G_M_PEAK_N; if (toolbar_) toolbar_->update_peak_type(peak_type_nr_, NULL); } void FFrame::OnMenuBgStripUpdate(wxUpdateUIEvent& event) { event.Enable(get_main_plot()->bgm()->can_strip()); } void FFrame::OnMenuBgUndoUpdate(wxUpdateUIEvent& event) { event.Enable(get_main_plot()->bgm()->has_fn()); } void FFrame::OnMenuBgClearUpdate(wxUpdateUIEvent& event) { BgManager* bgm = get_main_plot()->bgm(); event.Enable(bgm->can_strip() || bgm->has_fn()); } void FFrame::OnStripBg(wxCommandEvent&) { get_main_plot()->bgm()->strip_background(); update_menu_recent_baselines(); } void FFrame::OnUndoBg(wxCommandEvent&) { get_main_plot()->bgm()->add_background(); } void FFrame::OnClearBg(wxCommandEvent&) { get_main_plot()->bgm()->clear_background(); plot_pane_->refresh_plots(false, kMainPlot); } void FFrame::OnRecentBg(wxCommandEvent& event) { int n = event.GetId() - (ID_G_BG_RECENT + 1); change_mouse_mode(mmd_bg); get_main_plot()->bgm()->update_focused_data(get_focused_data_index()); get_main_plot()->bgm()->set_as_recent(n); plot_pane_->refresh_plots(false, kMainPlot); } void FFrame::OnConvexHullBg(wxCommandEvent&) { change_mouse_mode(mmd_bg); get_main_plot()->bgm()->update_focused_data(get_focused_data_index()); get_main_plot()->bgm()->set_as_convex_hull(); plot_pane_->refresh_plots(false, kMainPlot); } void FFrame::OnSplineBg(wxCommandEvent& event) { get_main_plot()->bgm()->set_spline_bg(event.IsChecked()); plot_pane_->refresh_plots(false, kMainPlot); } void FFrame::SwitchToolbar(bool show) { if (show && !GetToolBar()) { toolbar_ = new FToolBar(this, -1); SetToolBar(toolbar_); toolbar_->Realize(); update_toolbar(); update_peak_type_list(); //toolbar_->ToggleTool(ID_T_BAR, v_splitter_->IsSplit()); } else if (!show && GetToolBar()){ SetToolBar(NULL); delete toolbar_; toolbar_ = NULL; } GetMenuBar()->Check(ID_G_S_TOOLBAR, show); } void FFrame::SwitchStatbar (bool show) { status_bar_->Show(show); GetMenuBar()->Check(ID_G_S_STATBAR, show); } void FFrame::SwitchSideBar(bool show) { //v_splitter_->IsSplit() means sidebar_ is visible if (show && !v_splitter_->IsSplit()) { sidebar_->Show(true); v_splitter_->SplitVertProp(main_pane_, sidebar_); } else if (!show && v_splitter_->IsSplit()) { v_splitter_->Unsplit(); } GetMenuBar()->Check(ID_G_S_SIDEB, show); //if (toolbar_) // toolbar_->ToggleTool(ID_T_BAR, show); } void FFrame::OnSwitchAuxPlot(wxCommandEvent& ev) { plot_pane_->show_aux(ev.GetId() - ID_G_S_A1, ev.IsChecked()); } void FFrame::SwitchTextPane(bool show) { //main_pane_->IsSplit() means text_pane_ is visible if (show && !main_pane_->IsSplit()) { text_pane_->Show(true); main_pane_->SplitHorizProp(plot_pane_, text_pane_); } else if (!show && main_pane_->IsSplit()) { main_pane_->Unsplit(); } GetMenuBar()->Check(ID_G_S_TEXT, show); //if (toolbar_) toolbar_->ToggleTool(ID_T_..., show); } void FFrame::OnShowPrefDialog(wxCommandEvent& ev) { if (ev.GetId() == ID_G_C_MAIN) plot_pane_->get_plot()->OnConfigure(ev); else plot_pane_->get_aux_plot(ev.GetId() - ID_G_C_A1)->show_pref_dialog(); } void FFrame::OnConfigureStatusBar(wxCommandEvent& event) { if (status_bar_) status_bar_->OnPrefButton(event); } void FFrame::OnConfigureOutputWin(wxCommandEvent&) { text_pane_->output_win->show_preferences_dialog(); } void FFrame::OnConfigureDirectories(wxCommandEvent&) { wxDialog dlg(this, -1, "Configure Directories", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER); wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); top_sizer->Add(new wxStaticText(&dlg, -1, "Save as defaults for next sessions:"), wxSizerFlags().Center().Border()); wxFlexGridSizer *gsizer = new wxFlexGridSizer(2, 5, 5); gsizer->AddGrowableCol(1); wxSizerFlags sf = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL); gsizer->Add(new wxStaticText(&dlg, -1, "Data Directory"), sf); wxDirPickerCtrl *dp = new wxDirPickerCtrl(&dlg, -1, data_dir_, wxDirSelectorPromptStr, wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL); gsizer->Add(dp, wxSizerFlags().Center().Expand()); gsizer->Add(new wxStaticText(&dlg, -1, "Script Directory"), sf); wxDirPickerCtrl *sp = new wxDirPickerCtrl(&dlg, -1, script_dir_, wxDirSelectorPromptStr, wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL); gsizer->Add(sp, wxSizerFlags().Center().Expand()); gsizer->Add(new wxStaticText(&dlg, -1, "Export Directory"), sf); wxDirPickerCtrl *ep = new wxDirPickerCtrl(&dlg, -1, export_dir_, wxDirSelectorPromptStr, wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL); gsizer->Add(ep, wxSizerFlags().Center().Expand()); top_sizer->Add(gsizer, wxSizerFlags().Border().Expand()); wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); button_sizer->Add(new wxButton(&dlg, wxID_SAVE), wxSizerFlags()); button_sizer->Add(new wxButton(&dlg, wxID_CANCEL), wxSizerFlags()); top_sizer->Add(button_sizer, wxSizerFlags().Border().Right()); dlg.SetAffirmativeId(wxID_SAVE); dlg.SetSizerAndFit(top_sizer); dlg.SetSize(wxSize(600, -1)); dlg.Center(); if (dlg.ShowModal() == wxID_SAVE) { script_dir_ = sp->GetPath(); data_dir_ = dp->GetPath(); export_dir_ = ep->GetPath(); wxConfigBase *config = wxConfig::Get(); config->Write("/loadDataDir", data_dir_); config->Write("/exportDir", export_dir_); config->Write("/execScriptDir", script_dir_); } } void FFrame::SwitchCrosshair (bool show) { get_main_plot()->set_crosshair_cursor(show); GetMenuBar()->Check(ID_G_CROSSHAIR, show); } void FFrame::OnSwitchAntialias(wxCommandEvent& event) { antialias_ = event.IsChecked(); plot_pane_->refresh_plots(false, kAllPlots); } void FFrame::OnSwitchFullScreen(wxCommandEvent& event) { ShowFullScreen(event.IsChecked(), wxFULLSCREEN_NOBORDER|wxFULLSCREEN_NOCAPTION); } void FFrame::OnMenuShowAuxUpdate (wxUpdateUIEvent& event) { event.Check(plot_pane_->aux_visible(event.GetId() - ID_G_S_A1)); } void FFrame::GViewAll() { RealRange all; change_zoom(all, all); } void FFrame::OnGFitHeight (wxCommandEvent&) { RealRange all; change_zoom(ftk->view.hor, all); } void FFrame::OnGShowY0(wxCommandEvent& e) { ftk->view.set_y0_factor(e.IsChecked() ? 10 : 0); } void FFrame::OnGScrollLeft (wxCommandEvent&) { scroll_view_horizontally(-0.5); } void FFrame::OnGScrollRight (wxCommandEvent&) { scroll_view_horizontally(+0.5); } void FFrame::OnGScrollUp (wxCommandEvent&) { const fityk::View& view = ftk->view; const Scale& scale = plot_pane_->get_plot()->get_y_scale(); double top, bottom; if (scale.logarithm) { top = 10 * view.top(); bottom = 0.1 * view.bottom(); } else { const double factor = 2.; int Y0 = scale.px(0); int H = plot_pane_->get_plot()->GetSize().GetHeight(); bool Y0_visible = (Y0 >= 0 && Y0 < H); double pivot = (Y0_visible ? 0. : (view.bottom() + view.top()) / 2); top = pivot + factor * (view.top() - pivot); bottom = pivot + factor * (view.bottom() - pivot); } change_zoom(view.hor, RealRange(bottom, top)); } void FFrame::OnGExtendH (wxCommandEvent&) { const double factor = 0.5; double diff = ftk->view.width() * factor; change_zoom(RealRange(ftk->view.left() - diff, ftk->view.right() + diff), ftk->view.ver); } void FFrame::OnPreviousZoom(wxCommandEvent& event) { zoom_hist_.set_pos(event.GetId() - ID_G_V_ZOOM_FIRST); } static string format_range(const RealRange& r) { return r.lo_inf() && r.hi_inf() ? string(" [:]") : r.str(); } void FFrame::change_zoom(const RealRange& h, const RealRange& v) { string cmd = "plot" + format_range(h) + format_range(v); if (h.lo_inf() || h.hi_inf() || v.lo_inf() || v.hi_inf()) cmd += sidebar_->get_sel_datasets_as_string(); exec(cmd); zoom_hist_.push(ftk->view.str()); update_menu_previous_zooms(); } void FFrame::scroll_view_horizontally(double step) { double diff = ftk->view.width() * step; if (plot_pane_->get_plot()->get_x_reversed()) diff = -diff; change_zoom(RealRange(ftk->view.left() + diff, ftk->view.right() + diff), ftk->view.ver); } void FFrame::OnSaveDefaultConfig(wxCommandEvent&) { save_config_as(wxGetApp().config_dir + wxT("default")); } void FFrame::OnSaveConfigAs(wxCommandEvent&) { const wxString& dir = wxGetApp().config_dir; wxString msg = wxT("Choose config name.\n") wxT("This will be the name of file in:\n") + dir; TextComboDlg dlg(NULL, msg, wxT("Save configuration as...")); wxArrayString filenames; int n = wxDir::GetAllFiles(wxGetApp().config_dir, &filenames); for (int i = 0; i < n; ++i) dlg.combo->Append(wxFileName(filenames[i]).GetFullName()); if (dlg.ShowModal() == wxID_OK && !dlg.combo->GetValue().empty()) save_config_as(dir + dlg.combo->GetValue()); } void FFrame::save_config_as(wxString const& name) { wxFileConfig *config = new wxFileConfig(wxT(""), wxT(""), name, wxT(""), wxCONFIG_USE_LOCAL_FILE); save_all_settings(config); delete config; wxMenu *config_menu = GetMenuBar()->FindItem(ID_G_LCONF)->GetSubMenu(); update_config_menu(config_menu); } void FFrame::read_config(wxString const& name) { wxFileConfig *config = new wxFileConfig(wxT(""), wxT(""), name); read_all_settings(config); delete config; } void FFrame::OnConfigBuiltin (wxCommandEvent&) { // using fake config file, that does not exists, will get us default values // the file is not created when we only do reading wxString name = wxT("fake_d6DyY30KeMn9a3EyoM"); wxConfig *config = new wxConfig(wxT(""), wxT(""), name, wxT(""), wxCONFIG_USE_LOCAL_FILE); // just in case -- if the config was found, delete everything if (config->GetNumberOfEntries(true)) config->DeleteAll(); read_all_settings(config); delete config; } void FFrame::update_config_menu(wxMenu *menu) { // the first two items are "built-in" and separator, not to be deleted int old_count = menu->GetMenuItemCount() - 2; // delete old menu items for (int i = 0; i < old_count; ++i) menu->Destroy(ID_G_LCONF_X + i); // add new items wxArrayString filenames; int n = wxDir::GetAllFiles(wxGetApp().config_dir, &filenames); int config_number_limit = ID_G_LCONF_X_END - ID_G_LCONF_X; for (int i = 0; i < std::min(n, config_number_limit); ++i) { wxFileName fn(filenames[i]); menu->Append(ID_G_LCONF_X + i, fn.GetFullName(), fn.GetFullPath()); } } void FFrame::OnConfigX (wxCommandEvent& event) { wxMenu *menu = GetMenuBar()->FindItem(ID_G_LCONF)->GetSubMenu(); wxString name = menu->GetLabel(event.GetId()); if (name.IsEmpty()) return; wxString filename = wxGetApp().config_dir + name; // wxFileExists returns false for links, but it's not a problem if the menu // is updated if (!wxFileExists(filename)) update_config_menu(menu); read_config(filename); } void FFrame::OnPageSetup(wxCommandEvent&) { PageSetupDialog dlg(NULL, print_mgr_); int ret = dlg.ShowModal(); if (ret == wxID_PRINT) print_mgr_->print(); } void FFrame::OnPrint(wxCommandEvent&) { print_mgr_->print(); } void FFrame::OnCopyToClipboard(wxCommandEvent&) { if (!wxTheClipboard->Open()) return; wxSize size = get_main_plot()->get_bitmap().GetSize(); wxBitmap bmp = plot_pane()->prepare_bitmap_for_export(size.x, size.y, true); wxTheClipboard->SetData(new wxBitmapDataObject(bmp)); wxTheClipboard->Close(); } namespace { class SaveImageDlgExtra : public wxPanel { public: static wxSize size; SaveImageDlgExtra(wxWindow* parent) : wxPanel(parent, -1) { wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); wxSizerFlags c = wxSizerFlags().Center(); #ifdef __WXMSW__ sizer->AddSpacer(100); c.Border(wxBOTTOM); #endif sizer->Add(new wxStaticText(this, -1, "width:"), c); w_spin = new SpinCtrl(this, -1, size.x, 0, 9999, 70); sizer->Add(w_spin, c); sizer->AddSpacer(10); sizer->Add(new wxStaticText(this, -1, "height:"), c); h_spin = new SpinCtrl(this, -1, size.y, 0, 9999, 70); sizer->Add(h_spin, c); sizer->AddSpacer(10); aux_cb = new wxCheckBox(this, -1, "with auxiliary plots"); aux_cb->SetValue(false); sizer->Add(aux_cb, c); SetSizerAndFit(sizer); // workaround for wxMSW problem: GetValue() returned minimal value Connect(-1, wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(SaveImageDlgExtra::OnSpin)); } // workaround for wxMSW problem: GetValue() returned minimal value void OnSpin(wxSpinEvent& event) { int n = event.GetPosition(); if (event.GetId() == w_spin->GetId()) size.x = n; else size.y = n; } wxSpinCtrl *w_spin, *h_spin; wxCheckBox *aux_cb; }; wxSize SaveImageDlgExtra::size; wxWindow* save_image_filedialog_extra(wxWindow* parent) { return new SaveImageDlgExtra(parent); } } // anonymous namespace void FFrame::OnSaveAsImage(wxCommandEvent&) { wxFileDialog fdlg(this, wxT("Save main plot as image"), export_dir_, wxT(""), wxT("PNG image (*.png)|*.png;*.PNG|") wxT("Windows Bitmap (*.bmp)|*.bmp;*.BMP"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT); wxSize size = get_main_plot()->get_bitmap().GetSize(); SaveImageDlgExtra::size = size; #ifndef __WXOSX_CARBON__ fdlg.SetExtraControlCreator(&save_image_filedialog_extra); #endif if (fdlg.ShowModal() == wxID_OK) { wxString path = fdlg.GetPath(); wxWindow *extra = fdlg.GetExtraControl(); bool aux = false; if (extra != NULL) { SaveImageDlgExtra *sie = wxDynamicCast(extra,SaveImageDlgExtra); size.x = sie->w_spin->GetValue(); size.y = sie->h_spin->GetValue(); //wxMessageBox(wxString::Format("%d x %d", size.x, size.y)); // workaround for wxMSW problem: GetValue() returned minimal value if (size.x <= 10) size = SaveImageDlgExtra::size; aux = sie->aux_cb->GetValue(); } wxBitmap bmp = plot_pane()->prepare_bitmap_for_export(size.x, size.y, aux); if (path.Lower().EndsWith("bmp")) bmp.SaveFile(path, wxBITMAP_TYPE_BMP); else bmp.ConvertToImage().SaveFile(path, wxBITMAP_TYPE_PNG); } export_dir_ = fdlg.GetDirectory(); } string FFrame::get_peak_type() const { if (peak_type_nr_ >= (int) ftk->get_tpm()->tpvec().size()) return ""; return ftk->get_tpm()->tpvec()[peak_type_nr_]->name; } void FFrame::set_status_text(std::string const& text) { if (status_bar_) status_bar_->set_text(s2wx(text)); } void FFrame::set_status_coords(double x, double y, PlotTypeEnum pte) { if (status_bar_) status_bar_->set_coords(x, y, pte); } void FFrame::clear_status_coords() { if (status_bar_) status_bar_->clear_coords(); } void FFrame::output_text(UserInterface::Style style, const string& str) { text_pane_->output_win->append_text(style, s2wx(str)); } void FFrame::focus_input(wxKeyEvent& event) { if (should_focus_input(event)) text_pane_->input_field->RedirectKeyPress(event); else event.Skip(); } void FFrame::edit_in_input(string const& s) { text_pane_->edit_in_input(s); } /// here we update all GUI buttons, lists etc. that can be changed /// after execCommand() and can't be updated in another way void FFrame::after_cmd_updates() { sidebar_->update_lists(false); update_peak_type_list(); update_menu_functions(); update_menu_previous_zooms(); update_toolbar(); } void FFrame::update_toolbar() { if (!toolbar_) return; BgManager* bgm = get_main_plot()->bgm(); toolbar_->ToggleTool(ID_T_STRIP, bgm->has_fn() && bgm->stripped()); toolbar_->EnableTool(ID_T_RUN, !ftk->mgr.parameters().empty()); toolbar_->EnableTool(ID_T_UNDO, ftk->fit_manager()->can_undo()); } int FFrame::get_focused_data_index() { return sidebar_->get_focused_data(); } vector FFrame::get_selected_data_indices() { return sidebar_->get_selected_data_indices(); } string FFrame::get_datasets() { if (ftk->dk.count() == 1) return ""; vector sel = get_selected_data_indices(); if (ftk->dk.count() == (int) sel.size()) return "@*: "; else return "@" + join_vector(sel, " @") + ": "; } string FFrame::get_guess_string(const std::string& name) { string s; int nh = ftk->mgr.find_variable_nr("_hwhm"); int ns = ftk->mgr.find_variable_nr("_shape"); s = "("; if (nh != -1) s += "hwhm=$_hwhm"; if (ns != -1) { if (nh != -1) s += ", "; s += "shape=$_shape"; } const fityk::Tplate* tp = ftk->get_tpm()->get_tp(name); vector missing; try { missing = tp->get_missing_default_values(); } catch (fityk::SyntaxError&) { } v_foreach (string, arg, missing) { wxString value = wxGetTextFromUser(s2wx(*arg) + wxT(" = "), wxT("Initial value"), wxT("~0")); if (value.empty()) // pressing Cancel returns "" break; if (s.size() > 1) s += ", "; s += *arg + "=" + wx2s(value); } if (s.size() == 1) return name; else return name + s + ")"; } vector FFrame::get_selected_datas() { vector sel = get_selected_data_indices(); vector datas(sel.size()); for (size_t i = 0; i < sel.size(); ++i) datas[i] = ftk->dk.data(sel[i]); return datas; } MainPlot* FFrame::get_main_plot() { return plot_pane_->get_plot(); } MainPlot const* FFrame::get_main_plot() const { return plot_pane_->get_plot(); } void FFrame::update_data_pane() { sidebar_->update_lists(); } void FFrame::activate_function(int n) { sidebar_->activate_function(n); } void FFrame::update_app_title() { string title = "Fityk " VERSION; int pos = get_focused_data_index(); string const& filename = ftk->dk.data(pos)->get_filename(); if (!filename.empty()) title += " - " + filename; SetTitle(s2wx(title)); } // Overrides how menu items' help is displayed. // We show the help in our status bar, which is not derived from wxStatusBar. // Implementation based on wxFrameBase::DoGiveHelp(), see comments there. void FFrame::DoGiveHelp(const wxString& help, bool show) { if (!status_bar_) return; wxString text; if (show) { if (m_oldStatusText.empty()) { m_oldStatusText = status_bar_->get_text(); if (m_oldStatusText.empty()) { // use special value to prevent us from doing this the next time m_oldStatusText += _T('\0'); } } text = help; } else { text = m_oldStatusText; m_oldStatusText.clear(); } status_bar_->set_text(text); } //=============================================================== // FToolBar //=============================================================== BEGIN_EVENT_TABLE (FToolBar, wxToolBar) EVT_TOOL_RANGE (ID_T_ZOOM, ID_T_ADD, FToolBar::OnChangeMouseMode) EVT_TOOL_RANGE (ID_T_PZ, ID_T_AUTO, FToolBar::OnClickTool) //EVT_TOOL (ID_T_BAR, FToolBar::OnSwitchSideBar) EVT_CHOICE (ID_T_CHOICE, FToolBar::OnPeakChoice) EVT_TOOL_ENTER (-1, FToolBar::OnToolEnter) END_EVENT_TABLE() FToolBar::FToolBar (wxFrame *parent, wxWindowID id) : wxToolBar (parent, id, wxDefaultPosition, wxDefaultSize, wxNO_BORDER | /*wxTB_FLAT |*/ wxTB_DOCKABLE) { SetToolBitmapSize(wxSize(24, 24)); // mode MouseModeEnum m = frame ? frame->get_main_plot()->get_mouse_mode() : mmd_zoom; AddRadioTool(ID_T_ZOOM, wxT("Zoom"), wxBitmap(zoom_mode_xpm), wxNullBitmap, wxT("Normal Mode [F1]"), wxT("Use mouse for zooming, moving peaks etc.")); ToggleTool(ID_T_ZOOM, m == mmd_zoom); AddRadioTool(ID_T_RANGE, wxT("Range"), wxBitmap(active_mode_xpm), wxNullBitmap, wxT("Data-Range Mode [F2]"), wxT("Use mouse for activating and disactivating data (try also with [Shift])")); ToggleTool(ID_T_RANGE, m == mmd_activate); AddRadioTool(ID_T_BG, wxT("Background"), wxBitmap(bg_mode_xpm), wxNullBitmap, wxT("Baseline Mode [F3]"), wxT("Use mouse for subtracting background")); ToggleTool(ID_T_BG, m == mmd_bg); AddRadioTool(ID_T_ADD, wxT("Add peak"), wxBitmap(addpeak_mode_xpm), wxNullBitmap, wxT("Add-Peak Mode [F4]"), wxT("Use mouse for adding new peaks")); ToggleTool(ID_T_ADD, m == mmd_add); AddSeparator(); // view AddTool (ID_G_V_ALL, wxT("Whole"), wxBitmap(zoom_all_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("View whole [Ctrl+A]"), wxT("Fit data in window")); AddTool(ID_G_V_VERT, wxT("Fit height"), wxBitmap(zoom_vert_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Fit vertically [Ctrl+V]"), wxT("Set optimal y scale")); AddTool(ID_G_V_SCROLL_L, wxT("<-- scroll"), wxBitmap(zoom_left_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Scroll left (Ctrl+[)"), wxT("Scroll view left")); AddTool(ID_G_V_SCROLL_R, wxT("scroll -->"), wxBitmap(zoom_right_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Scroll right (Ctrl+])"), wxT("Scroll view right")); AddTool(ID_G_V_SCROLL_U, wxT("V-zoom-out"), wxBitmap(zoom_up_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Extend zoom up [Ctrl+-]"), wxT("Double vertical range")); AddTool(ID_T_PZ, wxT("Back"), wxBitmap(zoom_prev_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Previous view"), wxT("Go to the previous view")); AddSeparator(); //file AddTool(ID_SESSION_INCLUDE, wxT("Execute"), wxBitmap(run_script_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Execute script [Ctrl+X]"), wxT("Execute (include) script from file")); AddTool(ID_SESSION_SAVE, wxT("Save Session"), wxBitmap(save_script_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Save session to file"), wxT("Save current session to file")); AddSeparator(); //data AddTool(ID_D_QLOAD, wxT("Load"), wxBitmap(open_data_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Load file [Ctrl+O]"), wxT("Load data from file")); AddTool(ID_D_XLOAD, wxT("Load2"), wxBitmap(open_data_custom_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Load file (custom)"), wxT("Load data from file")); AddTool(ID_D_EDITOR, wxT("Tranform"), wxBitmap(edit_data_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Transform selected datasets"), wxT("Data transformations")); AddTool(ID_D_EXPORT, wxT("Save"), wxBitmap(save_data_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Save data as..."), wxT("Save data to file")); AddSeparator(); //background AddTool(ID_T_STRIP, wxT("Strip Bg"), wxBitmap(strip_bg_xpm), wxNullBitmap, wxITEM_CHECK, wxT("Strip background"), wxT("(Un)Remove selected background from data")); EnableTool(ID_T_STRIP, (m == mmd_bg)); AddSeparator(); peak_choice = new wxChoice(this, ID_T_CHOICE); peak_choice->SetSize(130, -1); //peak_choice->SetToolTip(wxT("function")); AddControl (peak_choice); AddTool (ID_T_AUTO, wxT("add"), wxBitmap(add_peak_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("auto-add"), wxT("")); AddSeparator(); //fit AddTool(ID_T_RUN, wxT("Run"), wxBitmap(run_fit_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Start fitting"), wxT("Start fitting sum to data")); AddTool(ID_T_UNDO, wxT("Undo"), wxBitmap(undo_fit_xpm), wxNullBitmap, wxITEM_NORMAL, wxT("Undo fitting"), wxT("Previous set of parameters")); //AddSeparator(); //AddTool(ID_T_BAR, wxT("SideBar"), // wxBitmap(right_pane_xpm), wxNullBitmap, wxITEM_CHECK, // wxT("Datasets Pane"), wxT("Show/hide datasets pane")); } void FToolBar::OnPeakChoice(wxCommandEvent &event) { if (frame) frame->peak_type_nr_ = event.GetSelection(); } void FToolBar::update_peak_type(int nr, vector const* peak_types) { if (peak_types) updateControlWithItems(peak_choice, *peak_types); peak_choice->SetSelection(nr); } void FToolBar::OnChangeMouseMode (wxCommandEvent& event) { frame->OnChangeMouseMode(event); } void FToolBar::OnSwitchSideBar (wxCommandEvent& event) { frame->OnSwitchSideBar(event); } void FToolBar::OnClickTool (wxCommandEvent& event) { wxCommandEvent dummy_cmd_event; switch (event.GetId()) { case ID_T_PZ: frame->zoom_hist().move(-1); break; case ID_T_STRIP: { BgManager* bgm = frame->get_main_plot()->bgm(); if (event.IsChecked()) { if (bgm->can_strip()) { bgm->strip_background(); frame->update_menu_recent_baselines(); } else ToggleTool(ID_T_STRIP, false); } else bgm->add_background(); break; } case ID_T_RUN: if (ftk->are_independent(frame->get_selected_datas())) exec(frame->get_datasets() + "fit"); else { string ds = frame->get_datasets(); ds.resize(ds.size() - 2); // we don't need ": " at the end exec("fit " + ds); } break; case ID_T_UNDO: exec("fit undo"); break; case ID_T_AUTO: frame->OnSGuess(dummy_cmd_event); break; default: assert(0); } } void FToolBar::OnToolEnter(wxCommandEvent& event) { if (event.GetSelection() == ID_T_AUTO) { on_addpeak_hover(); } } void FToolBar::on_addpeak_hover() { string info; try { fityk::Guess g(ftk->get_settings()); const Data* data = ftk->dk.data(frame->get_focused_data_index()); if (data->get_n() == 0) return; g.set_data(data, RealRange(), -1); if (frame->peak_type_nr_ >= (int) ftk->get_tpm()->tpvec().size()) return; int traits = ftk->get_tpm()->tpvec()[frame->peak_type_nr_]->traits; const vector* tr_names; vector v; if (traits & fityk::Tplate::kPeak) { tr_names = &fityk::Guess::peak_traits; v = g.estimate_peak_parameters(); } else if (traits & fityk::Tplate::kSigmoid) { tr_names = &fityk::Guess::sigmoid_traits; v = g.estimate_sigmoid_parameters(); } else { tr_names = &fityk::Guess::linear_traits; v = g.estimate_linear_parameters(); } for (size_t i = 0; i != v.size(); ++i) info += (i != 0 ? ", " : "") + (*tr_names)[i] + ": " + S(v[i]); } catch (fityk::ExecuteError &) { // ignore peak-outside-of-range or empty-range errors } frame->set_status_text(info); } fityk-1.3.1/wxgui/frame.h000066400000000000000000000224001302634723100152470ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_FRAME_H_ #define FITYK_WX_FRAME_H_ #include #include "cmn.h" // enums #include "plotpane.h" #include "fityk/ui.h" // UserInterface::Style class TextPane; class SideBar; class PrintManager; class FStatusBar; class RecentFiles; namespace fityk { class Full; struct RealRange; class Data; } extern fityk::Full *ftk; using fityk::UserInterface; using fityk::RealRange; using fityk::Data; // execute command(s) from string UserInterface::Status exec(const std::string &s); /// Toolbar bar in Fityk class FToolBar : public wxToolBar { public: FToolBar (wxFrame *parent, wxWindowID id); void update_peak_type(int nr, std::vector const* peak_types); void OnPeakChoice (wxCommandEvent& event); void OnChangeMouseMode (wxCommandEvent& event); void OnSwitchSideBar (wxCommandEvent& event); void OnClickTool (wxCommandEvent& event); void OnToolEnter(wxCommandEvent& event); private: wxChoice *peak_choice; void on_addpeak_hover(); DECLARE_EVENT_TABLE() }; /// Fityk-GUI main window class FFrame: public wxFrame { friend class FToolBar; friend class FApp; public: FFrame(wxWindow *parent, const wxWindowID id, const wxString& title, const long style); ~FFrame(); //void OnSize (wxSizeEvent& event); void OnShowHelp(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); void OnOnline(wxCommandEvent& event); void OnExample(wxCommandEvent& event); void OnQuit(wxCommandEvent& event); void OnDataRevertUpdate (wxUpdateUIEvent& event); void OnDataQLoad (wxCommandEvent& event); void OnDataXLoad (wxCommandEvent& event); void OnDataRecent (wxCommandEvent& event); void OnDataRevert (wxCommandEvent& event); void OnDataTable (wxCommandEvent& event); void OnDataEditor (wxCommandEvent& event); void OnSavedDT (wxCommandEvent& event); void OnDataMerge (wxCommandEvent&); void OnDataCalcShirley (wxCommandEvent&); void OnDataRmShirley (wxCommandEvent&); void OnDataExport (wxCommandEvent&); void OnDefinitionMgr (wxCommandEvent&); void OnSGuess (wxCommandEvent& event); void OnSPFInfo (wxCommandEvent& event); void OnAutoFreeze (wxCommandEvent& event); void OnParametersExport (wxCommandEvent& event); void OnModelExport (wxCommandEvent& event); void OnFMethodUpdate (wxUpdateUIEvent& event); void OnMenuFitRunUpdate (wxUpdateUIEvent& event); void OnMenuFitUndoUpdate (wxUpdateUIEvent& event); void OnMenuFitRedoUpdate (wxUpdateUIEvent& event); void OnMenuFitHistoryUpdate (wxUpdateUIEvent& event); void OnFOneOfMethods (wxCommandEvent& event); void OnFRun (wxCommandEvent& event); void OnFInfo (wxCommandEvent& event); void OnFUndo (wxCommandEvent& event); void OnFRedo (wxCommandEvent& event); void OnFHistory (wxCommandEvent& event); void OnPowderDiffraction (wxCommandEvent&); void OnXpsKEBE(wxCommandEvent&); void OnMenuLogStartUpdate (wxUpdateUIEvent& event); void OnMenuLogStopUpdate (wxUpdateUIEvent& event); void OnMenuLogOutputUpdate (wxUpdateUIEvent& event); void OnLogStart (wxCommandEvent& event); void OnLogStop (wxCommandEvent& event); void OnLogWithOutput (wxCommandEvent& event); void OnSaveHistory (wxCommandEvent& event); void OnInclude (wxCommandEvent& event); void OnRecentScript (wxCommandEvent& event); void OnNewFitykScript(wxCommandEvent&); void OnNewLuaScript(wxCommandEvent&); void OnNewHistoryScript(wxCommandEvent&); void OnScriptEdit (wxCommandEvent&); void show_editor (const wxString& path, const wxString& content); void OnReset (wxCommandEvent&); #ifdef __WXMAC__ void OnNewWindow (wxCommandEvent&); #endif void OnSessionLoad(wxCommandEvent&); void OnSessionSave(wxCommandEvent&); void OnSettings (wxCommandEvent&); void OnEditInit (wxCommandEvent&); void OnPageSetup (wxCommandEvent&); void OnPrint (wxCommandEvent&); void OnCopyToClipboard (wxCommandEvent&); void OnSaveAsImage (wxCommandEvent&); void OnChangeMouseMode (wxCommandEvent&); void OnChangePeakType(wxCommandEvent& event); void OnMenuBgStripUpdate(wxUpdateUIEvent& event); void OnMenuBgUndoUpdate(wxUpdateUIEvent& event); void OnMenuBgClearUpdate(wxUpdateUIEvent& event); void OnStripBg (wxCommandEvent& event); void OnUndoBg (wxCommandEvent& event); void OnClearBg (wxCommandEvent& event); void OnRecentBg (wxCommandEvent& event); void OnConvexHullBg (wxCommandEvent& event); void OnSplineBg (wxCommandEvent& event); void GViewAll(); void OnGViewAll (wxCommandEvent&) { GViewAll(); } void OnGFitHeight (wxCommandEvent& event); void OnGScrollLeft (wxCommandEvent& event); void OnGScrollRight (wxCommandEvent& event); void OnGScrollUp (wxCommandEvent& event); void OnGExtendH (wxCommandEvent& event); void OnPreviousZoom (wxCommandEvent& event); void OnConfigBuiltin (wxCommandEvent& event); void OnConfigX (wxCommandEvent& event); void OnSaveDefaultConfig(wxCommandEvent& event); void OnSaveConfigAs(wxCommandEvent&); void OnMenuShowAuxUpdate(wxUpdateUIEvent& event); void SwitchSideBar(bool show); void OnSwitchSideBar(wxCommandEvent& ev) {SwitchSideBar(ev.IsChecked());} void OnSwitchAuxPlot(wxCommandEvent& ev); void SwitchTextPane(bool show); void OnSwitchTextPane(wxCommandEvent& ev) {SwitchTextPane(ev.IsChecked());} void SwitchToolbar(bool show); void OnSwitchToolbar(wxCommandEvent& ev) {SwitchToolbar(ev.IsChecked());} void SwitchStatbar(bool show); void OnSwitchStatbar(wxCommandEvent& ev) {SwitchStatbar(ev.IsChecked());} void SwitchCrosshair(bool show); void OnShowPrefDialog(wxCommandEvent& ev); void OnConfigureStatusBar(wxCommandEvent& event); void OnConfigureOutputWin(wxCommandEvent&); void OnConfigureDirectories(wxCommandEvent&); void OnSwitchCrosshair(wxCommandEvent& e) {SwitchCrosshair(e.IsChecked());} void OnSwitchAntialias(wxCommandEvent& event); void OnSwitchFullScreen(wxCommandEvent& event); void OnGShowY0(wxCommandEvent& e); void save_config_as(wxString const& name); void read_config(wxString const& name); void save_all_settings(wxConfigBase *cf) const; void save_settings(wxConfigBase *cf) const; void read_all_settings(wxConfigBase *cf); void read_settings(wxConfigBase *cf); const FToolBar* get_toolbar() const { return toolbar_; } std::string get_peak_type() const; void set_status_text(std::string const& text); void set_status_coords(double x, double y, PlotTypeEnum pte); void clear_status_coords(); void output_text(UserInterface::Style style, std::string const& str); void change_zoom(const RealRange& h, const RealRange& v); void scroll_view_horizontally(double step); void focus_input(wxKeyEvent& event); void edit_in_input(std::string const& s); void after_cmd_updates(); void update_toolbar(); void update_config_menu(wxMenu *menu); int get_focused_data_index(); std::vector get_selected_data_indices(); std::vector get_selected_datas(); std::string get_datasets(); std::string get_guess_string(const std::string& name); PlotPane *plot_pane() { return plot_pane_; } ZoomHistory& zoom_hist() { return zoom_hist_; } MainPlot* get_main_plot(); MainPlot const* get_main_plot() const; void update_data_pane(); SideBar const* get_sidebar() const { return sidebar_; } SideBar* get_sidebar() { return sidebar_; } void activate_function(int n); void update_app_title(); void add_recent_data_file(const wxString& filename); void update_menu_functions(); void update_menu_saved_transforms(); void update_menu_recent_baselines(); void update_menu_previous_zooms(); // overridden from wxFrameBase, to show help in our status bar replacement void DoGiveHelp(const wxString& help, bool show); bool antialias() const { return antialias_; } // script_dir_ is accessed by EditorDlg const wxString& script_dir() const { return script_dir_; } void set_script_dir(const wxString& s) { script_dir_ = s; } private: ProportionalSplitter *v_splitter_; ProportionalSplitter *main_pane_; PlotPane *plot_pane_; TextPane *text_pane_; SideBar *sidebar_; FStatusBar *status_bar_; FToolBar *toolbar_; ZoomHistory zoom_hist_; int peak_type_nr_; std::vector peak_types_; PrintManager* print_mgr_; RecentFiles *recent_scripts_, *recent_data_; wxMenu *data_ft_menu_, *func_type_menu_; wxString script_dir_, data_dir_, export_dir_; bool antialias_; void place_plot_and_io_windows(wxWindow *parent); void create_io_panel(wxWindow *parent); void set_menubar(); void update_peak_type_list(); void change_mouse_mode(MouseModeEnum mode); void export_as_info(const std::string& info, const char* caption, const char* ext, const char* wildcards); DECLARE_EVENT_TABLE() }; extern FFrame *frame; #endif // FITYK_WX_FRAME_H_ fityk-1.3.1/wxgui/gradient.cpp000066400000000000000000000237451302634723100163220ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Gradient Dialog (GradientDlg) and helpers #include #include #include "gradient.h" #include "cmn.h" //SpinCtrl, change_color_dlg, add_apply_close_buttons #include "fityk/common.h" //iround() using namespace std; /// displays colors from data member from left to right (one pixel - one color) class ColorGradientDisplay : public wxPanel { public: ColorGradientDisplay(GradientDlg *parent) : wxPanel(parent, -1), gradient_dlg_(parent) { Connect(wxEVT_PAINT, wxPaintEventHandler(ColorGradientDisplay::OnPaint)); } void OnPaint(wxPaintEvent&) { wxPaintDC dc(this); wxSize size = GetClientSize(); wxPen pen; for (int i = 0; i < size.GetWidth(); ++i) { float d = i / (size.GetWidth() - 1.0); pen.SetColour(gradient_dlg_->get_value(d)); dc.SetPen(pen); dc.DrawLine(i, 0, i, size.GetHeight()); } } private: GradientDlg *gradient_dlg_; }; GradientDlg::GradientDlg(wxWindow *parent, wxWindowID id, const wxColour& first_col, const wxColour& last_col) : wxDialog(parent, id, wxT("Select color gradient"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) { wxBoxSizer* top_sizer = new wxBoxSizer(wxVERTICAL); from_cp_ = new wxColourPickerCtrl(this, -1, first_col, wxDefaultPosition, wxDefaultSize, wxCLRP_USE_TEXTCTRL); top_sizer->Add(from_cp_, 0, wxALL|wxEXPAND, 5); to_cp_ = new wxColourPickerCtrl(this, -1, last_col, wxDefaultPosition, wxDefaultSize, wxCLRP_USE_TEXTCTRL); top_sizer->Add(to_cp_, 0, wxALL|wxEXPAND, 5); rb1_ = new wxRadioButton(this, -1, wxT("HSV gradient, clockwise hue"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); rb2_ = new wxRadioButton(this, -1, wxT("HSV gradient, counter-clockwise")); rb3_ = new wxRadioButton(this, -1, wxT("RGB gradient")); rb4_ = new wxRadioButton(this, -1, wxT("one color")); top_sizer->Add(rb1_, 0, wxLEFT|wxRIGHT|wxTOP, 5); top_sizer->Add(rb2_, 0, wxLEFT|wxRIGHT|wxTOP, 5); top_sizer->Add(rb3_, 0, wxLEFT|wxRIGHT|wxTOP, 5); top_sizer->Add(rb4_, 0, wxALL, 5); display_ = new ColorGradientDisplay(this); display_->SetMinSize(wxSize(-1, 15)); top_sizer->Add(display_, 0, wxALL|wxEXPAND, 5); add_apply_close_buttons(this, top_sizer); SetSizerAndFit(top_sizer); SetEscapeId(wxID_CLOSE); Connect(-1, wxEVT_COMMAND_COLOURPICKER_CHANGED, wxColourPickerEventHandler(GradientDlg::OnColor)); Connect(-1, wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler(GradientDlg::OnRadioChanged)); } static void wxColour2hsv(const wxColour& color, unsigned char &h, unsigned char &s, unsigned char &v) { int r = color.Red(); int g = color.Green(); int b = color.Blue(); v = max(max(r, g), b); h = s = 0; if (v == 0) return; unsigned char delta = v - min(min(r, g), b); s = 255 * delta / v; if (s == 0) return; if (v == r) h = 43 * (g - b) / delta; else if (v == g) h = 85 + 43 * (b - r) / delta; else // v == b h = 171 + 43 * (r - g) / delta; } static wxColour hsv2wxColour(unsigned char h, unsigned char s, unsigned char v) { if (s == 0) return wxColour(v, v, v); float hx = h / 42.501; // 0 <= hx <= 5. int i = (int) floor(hx); float f = hx - i; float sx = s / 255.; unsigned char p = iround(v * (1 - sx)); unsigned char q = iround(v * (1 - sx * f)); unsigned char t = iround(v * (1 - sx * (1 - f))); switch(i) { case 0: return wxColour(v, t, p); case 1: return wxColour(q, v, p); case 2: return wxColour(p, v, t); case 3: return wxColour(p, q, v); case 4: return wxColour(t, p, v); case 5: default: return wxColour(v, p, q); } } wxColour GradientDlg::get_value(float x) { wxColour c; if (x < 0) x = 0; if (x > 1) x = 1; if (rb1_->GetValue() || rb2_->GetValue()) { // hsv unsigned char h1, s1, v1, h2, s2, v2; wxColour2hsv(from_cp_->GetColour(), h1, s1, v1); wxColour2hsv(to_cp_->GetColour(), h2, s2, v2); int corr = 0; if (rb1_->GetValue() && h1 > h2) corr = 256; else if (rb2_->GetValue() && h1 < h2) corr = -256; c = hsv2wxColour(iround(h1 * (1-x) + (h2 + corr) * x), iround(s1 * (1-x) + s2 * x), iround(v1 * (1-x) + v2 * x)); } else if (rb3_->GetValue()) { // rgb wxColour c1 = from_cp_->GetColour(); wxColour c2 = to_cp_->GetColour(); c = wxColour(iround(c1.Red() * (1-x) + c2.Red() * x), iround(c1.Green() * (1-x) + c2.Green() * x), iround(c1.Blue() * (1-x) + c2.Blue() * x)); } else { // one color c = from_cp_->GetColour(); } return c; } const wxColour MultiColorCombo::palette[21] = { wxColour(0x00, 0xCC, 0x00), // green wxColour(0x00, 0xBB, 0xFF), // light blue wxColour(0xFF, 0xBB, 0x00), // orange wxColour(0xEE, 0xEE, 0xBB), // beige wxColour(0x55, 0x88, 0x00), // dark green wxColour(0x00, 0x44, 0x99), // dark blue wxColour(0xDD, 0x00, 0x00), // red wxColour(0xFF, 0x00, 0xFF), // magenta wxColour(0xEE, 0xEE, 0x00), // yellow wxColour(0x00, 0x80, 0x80), // dark cyan wxColour(0xC0, 0xDC, 0xC0), // money green wxColour(0xFF, 0xFB, 0xF0), // cream wxColour(0x80, 0x00, 0x00), // dark red wxColour(0x00, 0x80, 0x00), // dark green wxColour(0x80, 0x80, 0x00), // dark yellow wxColour(0x00, 0x00, 0x80), // dark blue wxColour(0x80, 0x00, 0x80), // dark magenta wxColour(0x00, 0x00, 0xFF), // blue wxColour(0x00, 0xFF, 0xFF), // cyan wxColour(0xA6, 0xCA, 0xF0), // sky blue wxColour(0x00, 0xFF, 0x00), // green }; MultiColorCombo::MultiColorCombo(wxWindow* parent, const wxColour* bg_color, vector& colors) : bg_color_(bg_color), colors_(colors) { wxString choices[8] = { wxT(""), // current colors wxT(""), // palette wxT(""), // this and the next empty items are predefined color maps wxT(""), wxT(""), wxT(""), wxT(""), wxT("single color..."), }; wxOwnerDrawnComboBox::Create(parent, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, 8, choices, wxCB_READONLY); Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(MultiColorCombo::OnSelection)); } static wxColour jet_color(int t) { if (t < 32) // blue return wxColour(0, 0, 127 + 4 * t); else if (t < 3*32) // cyan return wxColour(0, 4 * (t - 32), 255); else if (t < 5*32) // yellow return wxColour(4 * (t - 3*32), 255, 255 - 4 * (t - 3*32)); else if (t < 7*32) // orange return wxColour(255, 255 - 4 * (t - 5*32), 0); else // red return wxColour(255 - 4 * (t - 7*32), 0, 0); } // t - position in gradient/palette (0 <= t <= 255) wxColour MultiColorCombo::get_color(int selection, int i) const { int t = 255 * i / (colors_.size() - 1); // some color maps here are copied from AtomEye (public domain code) switch (selection) { case 0: // current colors return colors_[i]; case 1: // palette return palette[i < 21 ? i : 0]; case 2: // from cyan to magenta return wxColour(t, 255-t, 255); case 3: // from green to blue return wxColour(0, 255-t, (255+t)/2); case 4: // from copper orange to black return wxColour(min(iround(1.25*(255-t)), 255), iround(0.7812*(255-t)), iround(0.4975*(255-t))); case 5: // hsv from blue to red return jet_color(t); case 6: // hsv from green to green return hsv2wxColour((t+64) % 255, 255, 255); default: assert(0); return wxColour(); } } void MultiColorCombo::OnSelection(wxCommandEvent& event) { int n = event.GetSelection(); if (n == 0) // current colors, nothing changes return; if (n == 7) { // single color... if (change_color_dlg(colors_[0])) for (size_t i = 1; i < colors_.size(); ++i) colors_[i] = colors_[0]; } else for (size_t i = 0; i < colors_.size(); ++i) colors_[i] = get_color(n, i); SetSelection(0); event.Skip(); } void MultiColorCombo::OnDrawItem(wxDC& dc, const wxRect& rect, int item, int /*flags*/) const { if (item == wxNOT_FOUND) return; if (item >= 7) { dc.DrawText(GetString(item), rect.x + 3, rect.y + (rect.height - dc.GetCharHeight()) / 2); return; } wxRect bg_rect(rect); bg_rect.Deflate(2); dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(wxBrush(*bg_color_)); //dc.SetPen(bg_pen); dc.DrawRectangle(bg_rect.x, bg_rect.y, bg_rect.width, bg_rect.height); dc.SetBrush(*wxTRANSPARENT_BRUSH); int y1 = bg_rect.y + 3; int y2 = bg_rect.y + bg_rect.height - 3; for (size_t i = 0; i < colors_.size(); ++i) { dc.SetPen(get_color(item, i)); int x = bg_rect.x + 3 + 2*i; dc.DrawLine(x, y1, x, y2); ++x; dc.DrawLine(x, y1, x, y2); } } // if the text is empty, wxComboCtrlBase::DoGetBestSize() sets text width // 150px. Let's decrease it to 142px. wxSize MultiColorCombo::DoGetBestSize() const { wxSize s = wxComboCtrlBase::DoGetBestSize(); s.x -= 8; CacheBestSize(s); return s; } fityk-1.3.1/wxgui/gradient.h000066400000000000000000000027151302634723100157610ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_GRADIENT_H_ #define FITYK_WX_GRADIENT_H_ #include #include #include class GradientDlg : public wxDialog { public: GradientDlg(wxWindow *parent, wxWindowID id, const wxColour& first_col, const wxColour& last_col); void OnColor(wxColourPickerEvent&) { display_->Refresh(); } void OnRadioChanged(wxCommandEvent &) { display_->Refresh(); } wxColour get_value(float x); private: wxRadioButton *rb1_, *rb2_, *rb3_, *rb4_; wxColourPickerCtrl *from_cp_, *to_cp_; wxPanel *display_; }; class MultiColorCombo : public wxOwnerDrawnComboBox { public: MultiColorCombo(wxWindow* parent, const wxColour* bg_color, std::vector& colors); virtual void OnDrawItem(wxDC& dc, const wxRect& rect, int item, int flags) const; virtual wxCoord OnMeasureItem(size_t) const { return 24; } virtual wxCoord OnMeasureItemWidth(size_t) const { return colors_.size() * 2 + 8; } virtual wxSize DoGetBestSize() const; private: static const wxColour palette[21]; const wxColour* bg_color_; // this class does not resize colors_, only changes values std::vector& colors_; wxColour get_color(int selection, int i) const; void OnSelection(wxCommandEvent& event); }; #endif fityk-1.3.1/wxgui/history.cpp000066400000000000000000000135331302634723100162200ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include "history.h" #include "cmn.h" #include "frame.h" #include "fityk/logic.h" #include "fityk/fit.h" using namespace std; using fityk::FitManager; enum { ID_SHIST_LC = 26100, ID_SHIST_CWSSR , ID_SHIST_V // and next 3 }; BEGIN_EVENT_TABLE(SumHistoryDlg, wxDialog) EVT_ACTIVATE (SumHistoryDlg::OnActivate) EVT_BUTTON (ID_SHIST_CWSSR, SumHistoryDlg::OnComputeWssrButton) EVT_BUTTON (wxID_CLEAR, SumHistoryDlg::OnClearHistory) EVT_LIST_ITEM_SELECTED (ID_SHIST_LC, SumHistoryDlg::OnSelectedItem) EVT_LIST_ITEM_FOCUSED (ID_SHIST_LC, SumHistoryDlg::OnFocusedItem) EVT_SPINCTRL (ID_SHIST_V+0, SumHistoryDlg::OnViewSpinCtrlUpdate) EVT_SPINCTRL (ID_SHIST_V+1, SumHistoryDlg::OnViewSpinCtrlUpdate) EVT_SPINCTRL (ID_SHIST_V+2, SumHistoryDlg::OnViewSpinCtrlUpdate) EVT_SPINCTRL (ID_SHIST_V+3, SumHistoryDlg::OnViewSpinCtrlUpdate) END_EVENT_TABLE() SumHistoryDlg::SumHistoryDlg (wxWindow* parent, wxWindowID id) : wxDialog(parent, id, wxT("Parameters History"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), compute_wssr_button(NULL), wssr_done(false) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); lc = new wxListView(this, ID_SHIST_LC, wxDefaultPosition, wxSize(450, 250), wxLC_REPORT|wxLC_SINGLE_SEL|wxLC_HRULES|wxLC_VRULES |wxSIMPLE_BORDER); initialize_lc(); hsizer->Add (lc, 1, wxEXPAND); top_sizer->Add (hsizer, 1, wxEXPAND); wxBoxSizer *buttons_sizer = new wxBoxSizer(wxHORIZONTAL); wxButton *clear_btn = new wxButton(this, wxID_CLEAR, wxT("Clear History")); buttons_sizer->Add(clear_btn, 0, wxALL, 5); clear_btn->Enable(ftk->fit_manager()->get_param_history_size() != 0); //compute_wssr_button = new wxButton (this, ID_SHIST_CWSSR, // wxT("Compute WSSRs")); //buttons_sizer->Add (compute_wssr_button, 0, wxALL, 5); buttons_sizer->Add (10, 10, 1); buttons_sizer->Add (new wxStaticText(this, -1, wxT("View parameters:")), 0, wxALL|wxALIGN_CENTER, 5); for (int i = 0; i < 4; i++) buttons_sizer->Add (new SpinCtrl(this, ID_SHIST_V + i, view[i], 0, view_max, 40), 0, wxALL, 5); buttons_sizer->Add (10, 10, 1); buttons_sizer->Add (new wxButton (this, wxID_CLOSE, wxT("&Close")), 0, wxALL, 5); top_sizer->Add (buttons_sizer, 0, wxALIGN_CENTER); SetSizer (top_sizer); top_sizer->SetSizeHints (this); int index = ftk->fit_manager()->get_active_nr(); lc->Select(index, true); lc->Focus(index); lc->SetFocus(); SetEscapeId(wxID_CLOSE); } void SumHistoryDlg::initialize_lc() { view_max = ftk->mgr.parameters().size() - 1; assert (view_max != -1); for (int i = 0; i < 4; i++) view[i] = min (i, view_max); lc->InsertColumn(0, wxT("No.")); lc->InsertColumn(1, wxT("parameters")); lc->InsertColumn(2, wxT("WSSR")); for (int i = 0; i < 4; i++) lc->InsertColumn(3 + i, wxString::Format(wxT("par. %i"), view[i])); FitManager const* fm = ftk->fit_manager(); for (int pos = 0; pos != fm->get_param_history_size(); ++pos) { // add item to lc const vector& item = fm->get_item(pos); lc->InsertItem(pos, wxString::Format(wxT(" %i "), pos)); lc->SetItem(pos, 1, wxString::Format(wxT("%i"), (int) item.size())); lc->SetItem(pos, 2, wxT(" ? ")); for (int j = 0; j < 4; j++) { int n = view[j]; if (n < (int) item.size()) lc->SetItem(pos, 3 + j, s2wx(S(item[n]))); } } for (int i = 0; i < 3+4; i++) lc->SetColumnWidth(i, wxLIST_AUTOSIZE); } void SumHistoryDlg::compute_all_wssr() { if (wssr_done) return; FitManager const* fm = ftk->fit_manager(); const vector orig = ftk->mgr.parameters(); vector datas = frame->get_selected_datas(); for (int i = 0; i != fm->get_param_history_size(); ++i) { vector const& item = fm->get_item(i); if (item.size() == orig.size()) { double wssr = ftk->get_fit()->compute_wssr(item, datas, true); lc->SetItem(i, 2, wxString::Format(wxT("%g"), wssr)); } } lc->SetColumnWidth(2, wxLIST_AUTOSIZE); if (compute_wssr_button) compute_wssr_button->Enable(false); wssr_done = true; } void SumHistoryDlg::clear_history() { exec("fit clear_history"); // we assume that the history is empty now and disable almost everything lc->DeleteAllItems(); } void SumHistoryDlg::OnSelectedItem(wxListEvent&) { } void SumHistoryDlg::OnFocusedItem(wxListEvent& event) { if (!IsShown()) return; int n = event.GetIndex(); if (n >= 0 && n != ftk->fit_manager()->get_active_nr()) exec("fit history " + S(n)); } void SumHistoryDlg::OnViewSpinCtrlUpdate (wxSpinEvent& event) { int v = event.GetId() - ID_SHIST_V; assert (0 <= v && v < 4); int n = event.GetPosition(); assert (0 <= n && n <= view_max); view[v] = n; //update header in wxListCtrl wxListItem li; li.SetMask (wxLIST_MASK_TEXT); li.SetText(wxString::Format(wxT("par. %i"), n)); lc->SetColumn(3 + v, li); //update data in wxListCtrl FitManager const* fm = ftk->fit_manager(); for (int i = 0; i != fm->get_param_history_size(); ++i) { vector const& item = fm->get_item(i); wxString s = n < (int) item.size() ? s2wx(S(item[n])) : wxString(); lc->SetItem(i, 3 + v, s); } } fityk-1.3.1/wxgui/history.h000066400000000000000000000020231302634723100156550ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2009 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// SumHistoryDlg: a dialog for Fit > Parameter History #ifndef FITYK_WX_HISTORY_H_ #define FITYK_WX_HISTORY_H_ #include #include #include class wxSpinEvent; class SumHistoryDlg : public wxDialog { public: SumHistoryDlg(wxWindow* parent, wxWindowID id); private: int view[4], view_max; wxListView *lc; wxButton *compute_wssr_button; bool wssr_done; // flag to avoid calculation of wssr again void OnComputeWssrButton(wxCommandEvent&) { compute_all_wssr(); } void OnClearHistory(wxCommandEvent&) { clear_history(); } void OnSelectedItem(wxListEvent& event); void OnFocusedItem(wxListEvent& event); void OnViewSpinCtrlUpdate(wxSpinEvent& event); void compute_all_wssr(); void clear_history(); void OnActivate(wxActivateEvent&) { compute_all_wssr(); } void initialize_lc(); DECLARE_EVENT_TABLE() }; #endif // FITYK_WX_HISTORY_H_ fityk-1.3.1/wxgui/img/000077500000000000000000000000001302634723100145625ustar00rootroot00000000000000fityk-1.3.1/wxgui/img/active_mode.xpm000066400000000000000000000014321302634723100175670ustar00rootroot00000000000000/* XPM */ static const char* active_mode_xpm[] = { "24 24 4 1", " c None", ". c #4E4E4E", "+ c #127704", "@ c #676767", " ", " .. ", " .. .. ", " .. .. ", " .. .. ", " .. ", " ++ ", " .. ++++ ", " .. ++++ ++ .. ", " .. ++ ++ .. ", " .. ++ ++ .. ", " ++ ++ .. @", " ++ ++ @@", " .. ++ ++ @@@", " .. ++ ++ ..@@ ", " .. ++ ++..@ ", " .. ++ +.. ", " ++ .. ", " +++ ", " @..++ ", "@@@..+ .. ", "@@@.. .. ", "@ .. .. ", " .. "}; fityk-1.3.1/wxgui/img/add.xpm000066400000000000000000000021001302634723100160310ustar00rootroot00000000000000/* XPM */ static const char * add_xpm[] = { "24 24 24 1", " c None", ". c #000000", "+ c #D0D9E3", "@ c #B9C6D5", "# c #909DAC", "$ c #7590AE", "% c #5E738B", "& c #5A6F86", "* c #ADBCCE", "= c #9DB0C5", "- c #93A6BD", "; c #839BB5", "> c #A5B6C9", ", c #B8C5D4", "' c #B6C4D3", ") c #93A0AD", "! c #C4CEDC", "~ c #617891", "{ c #7589A0", "] c #6883A1", "^ c #869DB8", "/ c #A2B3C7", "( c #A5B2C0", "_ c #4E6074", " ", " ", " ", " ... ", " .+@#. ", " .@$%. ", " .@$%. ", " .@$%. ", " .@$%. ", " ......@$&...... ", " .*=====-$;>,'''). ", " .!$$$$$$$$$$$$$~. ", " .{%%%%%$$]%%%%%%. ", " ......^$%....... ", " ./$%. ", " .'$%. ", " .'$%. ", " .'$%. ", " .(%_. ", " .... ", " ", " ", " ", " "}; fityk-1.3.1/wxgui/img/add_peak.xpm000066400000000000000000000020471302634723100170430ustar00rootroot00000000000000/* XPM */ static const char * add_peak_xpm[] = { "24 24 22 1", " c None", ". c #000000", "+ c #F5E8BC", "@ c #F1DE9C", "# c #E7C654", "$ c #E4BF3D", "% c #CBA41C", "& c #EED88B", "* c #ECD175", "= c #E9CC66", "- c #E6C551", "; c #F0DC97", "> c #E7C758", ", c #F3E3AC", "' c #D4AB1D", ") c #8FA3B9", "! c #E2BA31", "~ c #E1B726", "{ c #587492", "] c #314E6B", "^ c #ECD277", "/ c #AA8917", " ", " ... ", " .+@#. ", " .@$%. ", " ...@$%... ", " .&**=$-;;>. ", " .,$$$$$$$'.) ", " .!%%$$~%%%.{) ", " ...;$%...]])) ", " .;$%.)]]]]) ", " .^%/.)]))])) ", " ...)]{)){]) ", " ))]) )])) ", " )]{) ){]) ", " ))]) )])) ", " )]{ )]]) ", " ))]) ))]) ", " )]]) )]{) ", " ){]) ))]) ", " )]]) )])) ", " ){])) ){]{ ", " )))])) )]))) ", " )]]{) ){]]) ", " )))) )))) "}; fityk-1.3.1/wxgui/img/addpeak_mode.xpm000066400000000000000000000030321302634723100177030ustar00rootroot00000000000000/* XPM */ static const char * addpeak_mode_xpm[] = { "24 24 55 1", " c None", ". c #000000", "+ c #B8B39B", "@ c #6E6E6E", "# c #EBE8D3", "$ c #797979", "% c #FEFEED", "& c #7B7B7B", "* c #675E46", "= c #F4E7C2", "- c #FEFCE8", "; c #A27E36", "> c #645435", ", c #9A8558", "' c #C7AF7A", ") c #D9C28B", "! c #DFCA96", "~ c #F3E5BE", "{ c #CCB176", "] c #E1CC99", "^ c #DEC58D", "/ c #9F8B5F", "( c #442D0E", "_ c #7D5A22", ": c #BAA069", "< c #88601F", "[ c #5E4417", "} c #D6C08E", "| c #1A1A1A", "1 c #464646", "2 c #636363", "3 c #D8C291", "4 c #585858", "5 c #8C8C89", "6 c #A8A7A3", "7 c #8FA3B9", "8 c #A09069", "9 c #353535", "0 c #787775", "a c #C0BFBD", "b c #C2C1BD", "c c #314E6B", "d c #8B8B88", "e c #D2D0D0", "f c #587492", "g c #9C9B97", "h c #DBDAD8", "i c #B0AFAC", "j c #EFEDE9", "k c #969592", "l c #EAE8E3", "m c #868583", "n c #9B9996", "o c #6E6E6C", "p c #8B8A86", " . ", " .+. ", " @.#. ", " $..%..& ", " ..*=-;>.. ", " .,')!~{]^/. ", " ..(_:<[.. ", " ..}.|1. ", " 2.3.456. ", " 7.89.0ab. ", " 7c.7c.de6. ", " 7cf77fc.ghi. ", " 77c7 7c7.6jk. ", " 7cf7 7fc7.glm. ", " 77c7 7c77.nlo. ", " 7cf 7cc7 .kl0. ", " 77c7 77c7 .pl0.", " 7cc7 7cf7 .pl.", " 7fc7 77c7 .. ", " 7cc7 7c77 ", " 7fc77 7fcf ", "777c77 7c777 ", "7ccf7 7fcc7 ", "7777 7777 "}; fityk-1.3.1/wxgui/img/bg_mode.xpm000066400000000000000000000014271302634723100167100ustar00rootroot00000000000000/* XPM */ static const char * bg_mode_xpm[] = { "24 24 4 1", " c None", ". c #127704", "+ c #D1940C", "@ c #000000", " ", " ", " .. ", " .... ", " .... .. ", " .. .. ", " .. .. ", " .. .. .", " .. .. ..", " .. .. ...", " .. .. ... ", " .. ..... ", " .. ... ", " .. ++ ", " ... ++ @@@@++++ ", " ..... ++++@@ ++++@@", "...... ++++ ++ ", ".... @ ++ ", ".++ @ ", "++++@@ ", "++++ ", " ++ ", " ", " "}; fityk-1.3.1/wxgui/img/bin2c.c000066400000000000000000000053441302634723100157310ustar00rootroot00000000000000// bin2c.c // // from http://www.wxwidgets.org/wiki/index.php/Embedding_PNG_Images // // convert a binary file into a C source vector // // put into the public domain by Sandro Sigala // // syntax: bin2c [-c] [-z] // // -c add the "const" keyword to definition // -z terminate the array with a zero (useful for embedded C strings) // // examples: // bin2c -c myimage.png myimage_png.cpp // bin2c -z sometext.txt sometext_txt.cpp #include #include #include #include #ifndef PATH_MAX #define PATH_MAX 1024 #endif int useconst = 0; int zeroterminated = 0; int myfgetc(FILE *f) { int c = fgetc(f); if (c == EOF && zeroterminated) { zeroterminated = 0; return 0; } return c; } void process(const char *ifname, const char *ofname) { FILE *ifile, *ofile; ifile = fopen(ifname, "rb"); if (ifile == NULL) { fprintf(stderr, "cannot open %s for reading\n", ifname); exit(1); } ofile = fopen(ofname, "wb"); if (ofile == NULL) { fprintf(stderr, "cannot open %s for writing\n", ofname); exit(1); } char buf[PATH_MAX], *p; const char *cp; if ((cp = strrchr(ifname, '/')) != NULL) ++cp; else { if ((cp = strrchr(ifname, '\\')) != NULL) ++cp; else cp = ifname; } strcpy(buf, cp); for (p = buf; *p != '\0'; ++p) if (!isalnum(*p)) *p = '_'; fprintf(ofile, "static %sunsigned char %s[] = {\n", useconst ? "const " : "", buf); int c, col = 1; while ((c = myfgetc(ifile)) != EOF) { if (col >= 78 - 6) { fputc('\n', ofile); col = 1; } fprintf(ofile, "0x%.2x,", c); col += 6; } fprintf(ofile, "\n};\n"); fclose(ifile); fclose(ofile); } void usage(void) { fprintf(stderr, "usage: bin2c [-cz] \n"); exit(1); } int main(int argc, char **argv) { while (argc > 3) { if (!strcmp(argv[1], "-c")) { useconst = 1; --argc; ++argv; } else if (!strcmp(argv[1], "-z")) { zeroterminated = 1; --argc; ++argv; } else { usage(); } } if (argc != 3) { usage(); } process(argv[1], argv[2]); return 0; } fityk-1.3.1/wxgui/img/book16.h000066400000000000000000000076421302634723100160450ustar00rootroot00000000000000static const unsigned char book16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x02, 0x3f, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xb5, 0x93, 0x4b, 0x48, 0x54, 0x61, 0x14, 0xc7, 0x7f, 0xf7, 0xde, 0x19, 0xc7, 0x19, 0x9d, 0xc9, 0x7c, 0x64, 0x08, 0x8a, 0x58, 0xd2, 0x26, 0x5a, 0x44, 0x62, 0x86, 0xb4, 0x2f, 0x42, 0x82, 0x88, 0x82, 0x76, 0xb5, 0x10, 0xc1, 0x45, 0xe2, 0x32, 0xc8, 0xa0, 0xad, 0x62, 0x5b, 0x2b, 0x03, 0x17, 0x62, 0x99, 0x14, 0x08, 0xba, 0x70, 0x68, 0x11, 0x46, 0x04, 0x6a, 0x16, 0x83, 0x52, 0xa4, 0x8e, 0x92, 0xd9, 0x43, 0xc3, 0x79, 0xdd, 0x3b, 0x33, 0xdf, 0xfd, 0xee, 0xfd, 0x5a, 0xcc, 0x03, 0x91, 0xa0, 0x16, 0x75, 0xe0, 0x6c, 0x0e, 0xe7, 0xfc, 0xce, 0x8b, 0x3f, 0xfc, 0x63, 0xf3, 0x35, 0x1d, 0x3b, 0x31, 0x04, 0xa8, 0x3f, 0xb9, 0x3f, 0x58, 0xd9, 0x0d, 0xe8, 0xda, 0x3e, 0xc0, 0xd5, 0x50, 0x28, 0x34, 0xd6, 0xff, 0xf0, 0x19, 0xb3, 0x6f, 0x3f, 0x60, 0x99, 0x16, 0x89, 0x54, 0x92, 0x4c, 0x26, 0x8d, 0x52, 0x60, 0xe8, 0x1a, 0x86, 0x6e, 0x50, 0x6e, 0x64, 0x99, 0x1c, 0x19, 0x04, 0x30, 0xf4, 0x7d, 0x80, 0xb1, 0xe1, 0x89, 0x30, 0x73, 0x4b, 0x51, 0x12, 0x49, 0x93, 0x78, 0x32, 0x45, 0x3c, 0x91, 0x22, 0x65, 0xa6, 0x31, 0xad, 0x34, 0xc9, 0x94, 0x85, 0xcf, 0x03, 0xb1, 0x9f, 0x5b, 0x0a, 0x38, 0x03, 0xb8, 0x7b, 0x01, 0x97, 0x9a, 0x9b, 0x9b, 0x89, 0x25, 0x2d, 0xcc, 0x74, 0x06, 0xdb, 0xb6, 0xb1, 0xa5, 0xc4, 0x71, 0x1c, 0x00, 0x34, 0x0d, 0x0c, 0x8f, 0x81, 0x57, 0x65, 0xa9, 0x08, 0x94, 0x00, 0xbc, 0x06, 0x28, 0x00, 0x0c, 0x60, 0xa2, 0xaf, 0xff, 0x3e, 0x73, 0x91, 0x55, 0x32, 0x99, 0x2c, 0x42, 0x08, 0x84, 0x10, 0xb8, 0xae, 0x93, 0x4f, 0xd1, 0xa8, 0xa9, 0x28, 0x67, 0x77, 0x7b, 0xcb, 0xb5, 0xad, 0xb8, 0xba, 0xd9, 0xd3, 0xfb, 0x74, 0x2f, 0xe0, 0x46, 0x7b, 0x7b, 0x3b, 0xdf, 0x77, 0xd3, 0x24, 0x52, 0x56, 0xb1, 0xbb, 0xb4, 0xed, 0xe2, 0x78, 0xba, 0xae, 0xe1, 0xf7, 0xea, 0xc4, 0xb7, 0x37, 0x09, 0x96, 0x95, 0x71, 0x6f, 0x70, 0xe0, 0x32, 0x50, 0x52, 0x00, 0x0c, 0xf5, 0xf6, 0x0d, 0xb0, 0xf6, 0x65, 0x3b, 0x57, 0x9c, 0x77, 0xa7, 0xd8, 0x1d, 0xea, 0xaa, 0x0f, 0xb0, 0xb2, 0xbc, 0x40, 0x5b, 0xcb, 0x49, 0x7d, 0xfc, 0xc9, 0x98, 0x0e, 0x9c, 0x05, 0x84, 0x0e, 0x5c, 0xec, 0xe8, 0xe8, 0x20, 0xb2, 0xfa, 0x0d, 0xd3, 0x4a, 0x23, 0xa5, 0x44, 0x4a, 0x89, 0x23, 0x25, 0x4a, 0xa9, 0x22, 0x40, 0xd9, 0x26, 0x1e, 0x37, 0xcb, 0xa7, 0xd5, 0x35, 0x37, 0x1f, 0x9a, 0xcd, 0x2d, 0x06, 0xea, 0xd1, 0xe8, 0x73, 0xb5, 0xfe, 0x23, 0xa6, 0x49, 0x5b, 0x22, 0x6c, 0x1b, 0x21, 0x04, 0xb1, 0x44, 0x0a, 0xe5, 0xe6, 0x00, 0xd2, 0x71, 0xd8, 0xd9, 0x5c, 0xa1, 0xaa, 0xcc, 0xe0, 0xf1, 0xe8, 0x08, 0x5e, 0x5f, 0xe9, 0x6d, 0x3b, 0x9b, 0xb9, 0x0b, 0xe0, 0x01, 0x98, 0x09, 0xcf, 0x68, 0xcb, 0x8b, 0x73, 0x4e, 0x6d, 0x5d, 0x9d, 0x51, 0xe2, 0x35, 0x00, 0x10, 0xc2, 0x46, 0xba, 0xb9, 0xeb, 0x7b, 0x3c, 0x1e, 0x1a, 0x1b, 0x1a, 0x70, 0xa4, 0x0d, 0xb0, 0x54, 0x28, 0x2e, 0x02, 0xfc, 0x81, 0x00, 0xa7, 0x5a, 0x5b, 0x8c, 0x0b, 0xe7, 0xcf, 0xd1, 0x76, 0xba, 0x15, 0xe5, 0x2a, 0xfc, 0x81, 0x52, 0x94, 0x02, 0xc7, 0x75, 0x59, 0x8f, 0x46, 0x79, 0xf5, 0x66, 0x9e, 0x9e, 0xee, 0x4e, 0x34, 0x5d, 0xbf, 0xa3, 0x5c, 0xb7, 0xb8, 0x9a, 0x51, 0xdf, 0x78, 0x24, 0xf0, 0x32, 0x3c, 0x15, 0x5c, 0x5c, 0x98, 0xaf, 0xfd, 0xbc, 0x63, 0x9a, 0x91, 0x8f, 0x1b, 0x25, 0x42, 0xf3, 0x51, 0x5b, 0x5d, 0x81, 0x52, 0x0a, 0xbf, 0xcf, 0xc7, 0x5a, 0x74, 0x83, 0xe9, 0xe9, 0x29, 0x22, 0xef, 0xdf, 0x81, 0x52, 0x57, 0x7e, 0xa7, 0x81, 0x2a, 0xa0, 0x0b, 0x78, 0x00, 0xbc, 0x00, 0xbe, 0x02, 0xaa, 0xe9, 0xf8, 0x29, 0x71, 0xed, 0x7a, 0x97, 0x1c, 0x9f, 0x9c, 0xb1, 0x01, 0x15, 0x08, 0x55, 0xde, 0xfa, 0x1b, 0x41, 0x1d, 0xce, 0xbf, 0xa8, 0x33, 0x78, 0xb0, 0x66, 0xb8, 0x20, 0x9e, 0x43, 0xf5, 0x47, 0xc3, 0xfc, 0x0f, 0xfb, 0x05, 0xb1, 0xc1, 0x1e, 0xde, 0xac, 0x53, 0x34, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/book16.png000066400000000000000000000012121302634723100163650ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“?IDATxÚµ“KHTaÇ÷ÞÇÉ|dŠXÒ&ZDb†´/B‚ˆ‚vµÁEâ2È ­b[+b™ºphFjƒR¤Ž’ÙCÃyÝ;3ßýîýZÌ‘ uàlçü΋?ücó5;1¨?¹?XÙ èÚ>ÀÕP(4Öÿð³o?`™‰T’L&R`è†nPnd™0ô}€±á‰0sKQI“x2E<‘"e¦1­4É”…ϱŸ[ 8¸{—𛛉%-ÌtÛ¶±¥Äq4 We©”¼( `¢¯ÿ>s‘U2™,B„¸®“OѨ©(gw{˵­¸ºÙÓût/àF{{;ßwÓ$RV±»´íâxº®á÷êÄ·7 –•qopà2PR õö °öe;Wœw§Øêª°²¼@[ËI}üɘœ„\ìèè ²ú ÓJ#¥DJ‰#%J©"@Ù&7˧Õ57šÍ-êÑèsµþ#¦I["l!±D åæÒqØÙ\¡ªÌàñè^_ém;›¹ à˜ ÏhË‹sNm]Qâ5ÂFº¹ë{<p¤ °T(.ü§Z[Œ çÏÑvºå*üR”ÇuYFyõfžžîN4]¿£\·¸šQßx$ð2<\\˜¯ý¼cš‘%BóQ[]R ¿ÏÇZtƒéé)"ïßRW~§*  x¼¾ªéø)qíz—Ÿœ±UÞúAο¨3x°f¸ žCõGÃüû±ÁÞ¬S4)IEND®B`‚fityk-1.3.1/wxgui/img/close.xpm000066400000000000000000000013671302634723100164240ustar00rootroot00000000000000/* XPM */ static const char * close_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " ", " ", " . . ", " . ... ", " .. .... ", " .. ... ", " ..... ", " ... ", " ..... ", " ....... ", " ... .... ", " ... .... ", " ... .. ", " ", " ", " ", " ", " ", " ", " "}; fityk-1.3.1/wxgui/img/color.xpm000066400000000000000000000006321302634723100164270ustar00rootroot00000000000000/* XPM */ static const char * color_xpm[] = { "16 16 2 1", " c #000000", ". c #FFFFFF", " ", " ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ............ ", " ", " "}; fityk-1.3.1/wxgui/img/colorsel.xpm000066400000000000000000000114161302634723100171350ustar00rootroot00000000000000/* XPM */ static const char * colorsel_xpm[] = { "24 24 223 2", " c None", ". c #000000", "+ c #FEFDFD", "@ c #FAE2DD", "# c #F2AEA1", "$ c #274AFF", "% c #5F79FF", "& c #607BFF", "* c #637CFF", "= c #7B90FF", "- c #FCF8E9", "; c #FAF4DF", "> c #FAF5E1", ", c #F6EBC5", "' c #F4BBAF", ") c #EB8672", "! c #A7B5FF", "~ c #A8B7FF", "{ c #AAB8FF", "] c #F5E7B8", "^ c #F5E8BA", "/ c #F5E8BC", "( c #EDD37C", "_ c #ADBAFF", ": c #EDD47E", "< c #E88975", "[ c #8590C8", "} c #090600", "| c #8791C8", "1 c #A4B0F2", "2 c #F9F4E0", "3 c #F2E6BB", "4 c #F1E5BB", "5 c #F5E8BD", "6 c #F6E9BD", "7 c #EB8773", "8 c #A6B3F9", "9 c #574F4F", "0 c #FDFDFC", "a c #8791C6", "b c #E3DFD3", "c c #F6EABF", "d c #F1A89A", "e c #EC8773", "f c #D83C1D", "g c #778DFF", "h c #96A2E0", "i c #575050", "j c #FDFAF8", "k c #7A83B1", "l c #D8CEAE", "m c #ECD47F", "n c #E7C652", "o c #6D6767", "p c #F9F1EA", "q c #F6F2ED", "r c #F2ECE5", "s c #F2EDE7", "t c #D7C5B2", "u c #D6D6D6", "v c #BCBCBC", "w c #625C5B", "x c #F9EEE4", "y c #4F4D4A", "z c #868077", "A c #B6AEA3", "B c #EDE2D3", "C c #FBF0E0", "D c #F8D39F", "E c #E1D3C4", "F c #E1D4C6", "G c #E2D5C7", "H c #CAB197", "I c #9C9C9C", "J c #615C5B", "K c #F9F0E4", "L c #746C67", "M c #FEFDFC", "N c #FFFEFD", "O c #131210", "P c #897C69", "Q c #D8C3A5", "R c #F5C27A", "S c #CBB298", "T c #F3F2F2", "U c #98948F", "V c #F9EFE3", "W c #A09489", "X c #766D68", "Y c #736961", "Z c #A3A3A2", "` c #B3A188", " . c #DAAC6D", ".. c #E3D6C8", "+. c #E8E5E2", "@. c #97938E", "#. c #F6E9D8", "$. c #84817A", "%. c #FBF3EA", "&. c #908C86", "*. c #F1EDE7", "=. c #7B7975", "-. c #878786", ";. c #070000", ">. c #928470", ",. c #CEA468", "'. c #E4D7C9", "). c #CBB39A", "!. c #E2DFDC", "~. c #A8A199", "{. c #F0E0CE", "]. c #C8BFB4", "^. c #D5CCBF", "/. c #DFD7CD", "(. c #DAD3C9", "_. c #DDCFC4", ":. c #928C84", "<. c #8F816E", "[. c #CFA56A", "}. c #DBCAB8", "|. c #AF8A62", "1. c #040000", "2. c #D9D5D2", "3. c #D9CABB", "4. c #D7C8B8", "5. c #DECFBF", "6. c #D8C9B9", "7. c #E3D3C2", "8. c #C9BBAC", "9. c #D9CEC2", "0. c #7F766D", "a. c #887C6A", "b. c #D39B49", "c. c #060100", "d. c #C0BDBA", "e. c #8C8782", "f. c #C2B5A7", "g. c #BFB4A6", "h. c #B8AB9D", "i. c #BAAD9E", "j. c #BEB0A2", "k. c #948A7F", "l. c #716860", "m. c #FDFCFC", "n. c #F5E7E6", "o. c #E0B2AD", "p. c #93B48E", "q. c #332C2B", "r. c #5D5954", "s. c #79736C", "t. c #958C80", "u. c #8D8379", "v. c #988D82", "w. c #706760", "x. c #55565D", "y. c #ADB0BC", "z. c #94A0EB", "A. c #E9C8C4", "B. c #E9C9C6", "C. c #EACBC7", "D. c #D69B95", "E. c #AACFA4", "F. c #6A8166", "G. c #201A1A", "H. c #57514F", "I. c #625C59", "J. c #625A53", "K. c #6B625A", "L. c #585251", "M. c #696764", "N. c #080000", "O. c #545666", "P. c #BCC1E1", "Q. c #8D9AEA", "R. c #EACCC9", "S. c #C4EFBD", "T. c #ABD0A5", "U. c #A3AB9C", "V. c #050000", "W. c #0C0303", "X. c #080100", "Y. c #030000", "Z. c #2C2A30", "`. c #545665", " + c #6B6E80", ".+ c #C5CBED", "++ c #8E9BEB", "@+ c #F6E9E7", "#+ c #EBCDCA", "$+ c #EBCFCC", "%+ c #D79C96", "&+ c #CBF5C4", "*+ c #BADFB4", "=+ c #ECE4E2", "-+ c #DED7D5", ";+ c #D8D1D0", ">+ c #E0DBD7", ",+ c #E9E6E3", "'+ c #FCFBFA", ")+ c #030500", "!+ c #7E8195", "~+ c #CACFEE", "{+ c #929EEB", "]+ c #D89E97", "^+ c #CCF5C6", "/+ c #C8EFC1", "(+ c #0B0505", "_+ c #14100F", ":+ c #090806", "<+ c #000100", "[+ c #8B8EA3", "}+ c #CED3F3", "|+ c #7D8CE8", "1+ c #F0DAD7", "2+ c #BA554B", "3+ c #96EB88", "4+ c #97EC89", "5+ c #8FDF82", "6+ c #74B369", "7+ c #6A74B0", "8+ c #5E679A", "9+ c #6971A9", "0+ c #5B6EE2", " ", " . . . . . . . . . . . . . . . . . . . . . . ", " . + @ @ @ @ # . $ % & & * = . - ; > > > , . ", " . @ ' ' ' ' ) . % ! ! ~ ~ { . ; ] ] ^ / ( . ", " . @ ' ' ' ' ) . % ! ~ { { _ . > ] ^ / / : . ", " . @ ' ' ' ' < . & ~ [ } | 1 . 2 3 4 5 6 : . ", " . @ ' ' ' ' 7 . * 8 9 0 . a . b / / 5 c : . ", " . d ) ) ) e f . g h i j . k . l ( : m : n . ", " . . . . . . . . . . o p . . . . . . . . . . ", " . 0 q r r s t . u v w x y . . . z A B C D . ", " . r E F F G H . I . J K L M . N O . P Q R . ", " . r F F G G S . . T U V W + X M Y Z . ` .. ", " . s F G G ..S . . +.@.#.$.%.&.*.=.-.;.>.,.. ", " . s G G ..'.).. . !.~.{.].^./.(._.:.;.<.[.. ", " . }.S S ).).|.. 1.2.3.4.5.6.7.8.9.0.;.a.b.. ", " . . . . . . . . c.d.e.f.g.h.i.j.k.l.;.. . . ", " . m.n.n.n.n.o.. p.q.r.s.t.u.k.v.w.. x.y.z.. ", " . n.A.B.C.C.D.. E.F.G.H.I.J.K.L.M.N.O.P.Q.. ", " . n.B.C.C.R.D.. S.T.U.V.W.N.X.Y.Z.`. +.+++. ", " . @+R.#+#+$+%+. &+*+1.=+-+;+>+,+'+)+!+~+{+. ", " . @+#+#+$+$+]+. ^+/+1.(+V._+Y.:+. <+[+}+|+. ", " . 1+D.%+%+]+2+. 3+4+4+4+5+6+. 7+7+8+9+z.0+. ", " . . . . . . . . . . . . . . . . . . . . . . ", " "}; fityk-1.3.1/wxgui/img/cont_fit.xpm000066400000000000000000000033311302634723100171150ustar00rootroot00000000000000/* XPM */ static const char * cont_fit_xpm[] = { "24 24 68 1", " c None", ". c #000000", "+ c #CFCECA", "@ c #E1E1E0", "# c #97958F", "$ c #898781", "% c #8E8C85", "& c #838078", "* c #7B7973", "= c #67655F", "- c #403F3B", "; c #686661", "> c #7C7A72", ", c #DDDCDB", "' c #9A9992", ") c #53524E", "! c #171614", "~ c #767573", "{ c #9B9993", "] c #52504A", "^ c #7A7974", "/ c #86847D", "( c #9A9996", "_ c #B7B6B3", ": c #7D7B75", "< c #8A8883", "[ c #6B6964", "} c #78756C", "| c #5F5D56", "1 c #54534D", "2 c #403F3A", "3 c #E4E3E1", "4 c #E2E2E2", "5 c #B3B3B1", "6 c #484641", "7 c #9F9D96", "8 c #888781", "9 c #B0AFAD", "0 c #A8A7A1", "a c #908E86", "b c #97958E", "c c #807D74", "d c #595854", "e c #605E57", "f c #898883", "g c #76746B", "h c #43423F", "i c #282724", "j c #363430", "k c #6D6B63", "l c #E2E2E1", "m c #B6B5AF", "n c #21201E", "o c #0A0908", "p c #181816", "q c #E6E6E4", "r c #65635C", "s c #161614", "t c #8C8B89", "u c #DFDEDC", "v c #B0AFA9", "w c #D5D4D1", "x c #93918B", "y c #D6D5D2", "z c #ABA9A3", "A c #5D5C55", "B c #494943", "C c #42413C", " ... ", " ...+... ", " .@#$%&. ", " ..*=-;>.. ", " .,')!~{]. ", " ..^/(_:.. ", " .<[}|1.. ", " ...2... ... ", " ... .. .3. .. ", " .45.676.8.. ", " .90777abc6. ", " .77defcg. ", " ..67ehij7k6.. ", " ... .lm7dnopqcre. ", " ...+.....67fjstur6.. ", " .@#$%&. .vcmqwxr.. ", " ..*=-;>...yz7ccggA6. ", " .,')!~{]...d.6g6.B.. ", " ..^/(_:.. .. .C.... ", " .<[}|1.. ... ", " ...2... ", " ... ", " ", " "}; fityk-1.3.1/wxgui/img/convert.xpm000066400000000000000000000064351302634723100170000ustar00rootroot00000000000000/* XPM */ static const char * convert_xpm[] = { "24 24 128 2", " c None", ". c #000000", "+ c #0A0A0A", "@ c #B3B1B0", "# c #EEECEB", "$ c #F0DCAA", "% c #E5C470", "& c #DFB84F", "* c #8A681F", "= c #100E09", "- c #202020", "; c #EEECE9", "> c #E6D498", ", c #EED682", "' c #EED680", ") c #E3C15E", "! c #D29815", "~ c #976E15", "{ c #7F5B0A", "] c #1C190F", "^ c #EBE9E5", "/ c #CBB771", "( c #735817", "_ c #C6A546", ": c #E3C05D", "< c #BC8710", "[ c #AD7C10", "} c #252C33", "| c #AE9C5C", "1 c #010100", "2 c #9C7E2B", "3 c #AB7C12", "4 c #242012", "5 c #38414C", "6 c #A5BDD1", "7 c #2B333B", "8 c #3D351F", "9 c #A37819", "0 c #231F13", "a c #3E4954", "b c #556573", "c c #B5CFE5", "d c #3F566C", "e c #0B0B06", "f c #A97C1A", "g c #3F4A56", "h c #9DB8D2", "i c #4B6983", "j c #415B71", "k c #2B343C", "l c #221E11", "m c #EAE8E3", "n c #C58F13", "o c #B68411", "p c #826321", "q c #302C19", "r c #3E4955", "s c #5A6A79", "t c #363220", "u c #916F25", "v c #322F1E", "w c #2C333C", "x c #2B2719", "y c #353120", "z c #687A8B", "A c #394E62", "B c #937025", "C c #111418", "D c #364A5D", "E c #181C21", "F c #2F2C19", "G c #1E2B36", "H c #202F3B", "I c #080704", "J c #263644", "K c #060503", "L c #3B1C15", "M c #CD5446", "N c #CF5749", "O c #C74B3F", "P c #C03F35", "Q c #030301", "R c #D46051", "S c #DD7C6F", "T c #C4463A", "U c #992C25", "V c #C5483C", "W c #DF8477", "X c #EDC5BE", "Y c #DC7B6D", "Z c #C24D45", "` c #6B1813", " . c #D86E61", ".. c #DF8275", "+. c #CB6A63", "@. c #6E1813", "#. c #CB6A64", "$. c #821A16", "%. c #BA352D", "&. c #C25550", "*. c #6B110E", "=. c #98231D", "-. c #A62D26", ";. c #C14B43", ">. c #BC3930", ",. c #BB372E", "'. c #B8322A", "). c #C35C57", "!. c #B53732", "~. c #470705", "{. c #090805", "]. c #181818", "^. c #941E19", "/. c #AA3F3A", "(. c #C7645F", "_. c #C6635E", ":. c #C05350", "<. c #B33430", "[. c #520907", "}. c #37160F", "|. c #0E0E0E", "1. c #7F120E", "2. c #961712", "3. c #8F1611", "4. c #6F0E0B", "5. c #490504", "6. c #35170F", "7. c #030201", " . . . . . ", " + @ # $ % & * . = ", " - ; > , ' ' ) ! ~ { ] ", " . ^ / . . . ( _ : < [ ] ", " } . | 1 2 ' ! 3 4 ", " 5 6 7 . 8 ' ! 9 0 ", " a b c d 7 e . . . ' ! f . . . ", " g h c i j k l m ' ' ' ! n o p q ", " r s h c i i j } t m ' ' ! ! u v ", " g h h c i i i d w x m ' ! u y ", " r z h h c i i i i A 7 q m B v ", " C h h h c i i i i i D E q F ", " . h h c i i i i G . ", " . h c i i H . I . . . . 1 ", " . c J . K L . M N M O P . ", " . Q . M R S R M T U . ", " . V N W X Y N V Z ` ", " . T M ...R M T +.@.Q ", " . P O M N M O P #.$.. ", " . %.P T V T P %.&.*.1 ", " . =.-.;.>.,.'.).!.~.{. ", " ].^./.(._.:.<.[.. ", " }.|.1.2.3.4.5.. 6. ", " 7.. . . 7. "}; fityk-1.3.1/wxgui/img/copyfunc.xpm000066400000000000000000000036531302634723100171450ustar00rootroot00000000000000/* XPM */ static const char * copyfunc_xpm[] = { "24 24 82 1", " c None", ". c #000000", "+ c #797293", "@ c #625B81", "# c #595376", "$ c #010102", "% c #070609", "& c #585274", "* c #FFFFFF", "= c #DFDFDF", "- c #919191", "; c #404040", "> c #CDCDCD", ", c #E2E2E2", "' c #0C0C0C", ") c #090909", "! c #9A9A9A", "~ c #999999", "{ c #272727", "] c #979797", "^ c #CFCFCF", "/ c #E6E6E6", "( c #858585", "_ c #939393", ": c #010101", "< c #C5C5C5", "[ c #929292", "} c #5B5B5B", "| c #959595", "1 c #ADADAD", "2 c #202020", "3 c #D5D5D5", "4 c #828282", "5 c #D1DECF", "6 c #535353", "7 c #343434", "8 c #7E7E7E", "9 c #7DA377", "0 c #FEFEFE", "a c #494949", "b c #808080", "c c #DDDDDD", "d c #868686", "e c #E4ECE3", "f c #0F0F0F", "g c #7D7D7D", "h c #9F9F9F", "i c #5E5E5E", "j c #B3C9AF", "k c #D8D8D8", "l c #323232", "m c #DADADA", "n c #E9E9E9", "o c #EFEFEF", "p c #F1F1F1", "q c #8B8B8B", "r c #E4E4E4", "s c #3E3E3E", "t c #C9C9C9", "u c #E3E3E3", "v c #282828", "w c #CBCBCB", "x c #9C9C9C", "y c #9D9D9D", "z c #969696", "A c #020202", "B c #8F8F8F", "C c #E8E8E8", "D c #EBEBEB", "E c #B1B1B1", "F c #D2D2D2", "G c #DBDBDB", "H c #545454", "I c #909090", "J c #ECECEC", "K c #4A4A4A", "L c #D9D9D9", "M c #A0A0A0", "N c #A1A1A1", "O c #EEEEEE", "P c #CCCCCC", "Q c #333333", " ", " ... ", " .... ", " ........... ", " .+@#$%&@@+. ", " .*=-.;>,=*. ", " .*'...)!~*. ", " .*={.]^/(*. ", " .*_:.<[}.|. ", " .*1.234.5.. . ... ", " .*6.78.599. .. .... ", " .0a.bcd.999.e......... ", " .0f.g,hi.99j9.@@#$%&+. ", " .k.lmnopq.j99.,r_.st*. ", "..........e999.!'...)*. ", "... ......./uv._w*. ", " .*xyzA.4B*. ", " .*CDE.2FG*. ", " .*yhH.7Iz*. ", " .*DJK.bL,*. ", " .*MNf.g]x*. ", " .*OP.QmrD*. ", " ........... ", " ... "}; fityk-1.3.1/wxgui/img/correction.h000066400000000000000000000250751302634723100171130ustar00rootroot00000000000000static const unsigned char correction_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x01,0xab,0x00,0x00,0x00,0x1f, 0x08,0x04,0x00,0x00,0x00,0xf3,0x34,0x2a,0x31,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x00,0x02,0x62,0x4b,0x47,0x44,0x00,0xff,0x87,0x8f,0xcc,0xbf, 0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13, 0x00,0x00,0x0b,0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00, 0x07,0x74,0x49,0x4d,0x45,0x07,0xd8,0x03,0x1f,0x00,0x1d,0x02, 0x6c,0x01,0x04,0xcb,0x00,0x00,0x07,0xc9,0x49,0x44,0x41,0x54, 0x78,0xda,0xed,0x9c,0x2f,0x7b,0xeb,0xc6,0x12,0xc6,0x7f,0xa7, 0x37,0xe4,0xc0,0xed,0x47,0xd8,0xc2,0xc0,0x0d,0x2c,0xdc,0xc0, 0x42,0x1d,0x78,0xa0,0x02,0x6f,0x99,0xf2,0x11,0xd6,0xb4,0x4c, 0xa2,0x65,0x36,0xec,0x65,0xd2,0x47,0xb0,0x69,0x99,0x45,0xcb, 0x2c,0x5a,0xe6,0x0b,0x34,0x5a,0xaf,0xfe,0x38,0xb1,0xe5,0xd8, 0x72,0x5a,0x4d,0x9e,0x27,0x8f,0x62,0x3b,0xd2,0xab,0xd5,0xcc, 0xce,0xcc,0xbb,0xef,0xfa,0x0b,0xf7,0x65,0x86,0x08,0x4b,0x81, 0xa6,0x44,0xb3,0x60,0x33,0x19,0x92,0x08,0x33,0x29,0x12,0x45, 0x82,0xa1,0x04,0x2a,0x14,0x1b,0x32,0x66,0x9b,0x6d,0xa4,0x39, 0x20,0x67,0x89,0x02,0x22,0xb6,0x93,0xe1,0x50,0x24,0xc0,0x9a, 0x54,0x42,0x6c,0x3d,0xc1,0x48,0x28,0x1c,0x5b,0x34,0xa0,0xd8, 0xa3,0x67,0xe7,0x98,0x6d,0xac,0x69,0x60,0x87,0x11,0x67,0xde, 0x03,0x16,0x37,0x49,0x78,0x29,0x14,0x7b,0x54,0x80,0x24,0xc2, 0xe1,0xc8,0x89,0x6e,0x36,0x12,0x4b,0x12,0xc1,0xb2,0xc7,0x02, 0x31,0x09,0x4e,0x26,0x9d,0xd9,0x66,0x3b,0xab,0x0c,0xdc,0xf9, 0xf9,0xba,0x09,0xa7,0xfd,0x24,0x48,0x62,0x96,0x01,0x12,0x2d, 0x99,0xcb,0xb2,0xbb,0x59,0xe6,0x08,0x27,0x18,0x8d,0x95,0x91, 0x71,0xb8,0xd9,0x4d,0x66,0x3b,0xb7,0xf8,0x49,0xe5,0x68,0xeb, 0xdd,0x67,0x9a,0xb0,0x5a,0x12,0x7b,0xf7,0x4e,0x82,0x70,0xaf, 0x33,0xc7,0xf5,0xcd,0xfa,0x69,0x25,0x25,0x97,0x29,0xa7,0xfe, 0x2b,0x9a,0xdd,0x64,0xb6,0xf3,0x2c,0x97,0x60,0x72,0x3e,0x57, 0x4c,0x15,0x56,0x3b,0x71,0xdf,0xd4,0x07,0x7a,0xdb,0xd9,0xaf, 0x3f,0xc1,0xac,0xfd,0x15,0x95,0xbf,0xba,0x93,0xc2,0x70,0xb6, 0x3b,0xb6,0x2f,0x77,0x86,0x47,0xb1,0x63,0x01,0x28,0x2a,0x5e, 0x83,0xb0,0xba,0x3d,0x4e,0xcb,0x92,0xac,0x87,0x44,0x91,0xf3, 0x72,0x23,0x56,0x70,0x4d,0x81,0xa2,0x42,0xf1,0x4a,0x15,0x20, 0x48,0x29,0x66,0x5e,0xf0,0xf3,0x84,0x95,0x26,0xe7,0xa7,0x5e, 0xa7,0x13,0x01,0x9a,0xaa,0xf5,0x68,0x23,0xcc,0x95,0x48,0xdf, 0x88,0x84,0xa7,0xde,0xab,0x53,0x84,0x95,0x43,0xf1,0x32,0x30, 0x1a,0x0b,0x80,0x60,0x2c,0xae,0x39,0xc1,0xfc,0xd8,0xba,0x8e, 0xa6,0xa2,0x02,0x2c,0xf9,0xa4,0xd3,0xa1,0xc3,0x0e,0x3c,0xa3, 0xee,0xa4,0x64,0x01,0x43,0xc6,0xaa,0xf5,0x74,0xcd,0x1d,0x2e, 0x16,0x5c,0x19,0x95,0x63,0xdf,0x69,0x86,0x75,0xd0,0xb4,0xaf, 0x83,0x56,0x3e,0x95,0xc7,0xfe,0xf1,0x96,0x0e,0xb6,0xe3,0x53, 0x14,0x81,0x6b,0xdf,0x59,0x1d,0x82,0xca,0xc9,0x63,0xb8,0x05, 0x65,0x11,0xf7,0x48,0xfd,0x5c,0xca,0xbf,0x78,0x02,0xba,0xbf, 0x8d,0xec,0x3d,0xca,0x44,0xcb,0xd8,0x29,0x5f,0x48,0x5f,0xdb, 0x6f,0x2e,0xb9,0x9b,0xfc,0x9a,0xa8,0x2c,0x9a,0x9c,0x5d,0x8b, 0xbc,0x75,0xd2,0x24,0x83,0x66,0x2f,0x43,0xa5,0xfd,0x67,0xf6, 0xfe,0xdd,0x8f,0x0b,0xec,0x5d,0x8f,0xc0,0xd6,0x12,0xee,0x97, 0xb0,0x5f,0xf9,0x99,0x9f,0xaf,0xaf,0x99,0xb6,0xa8,0x09,0xcd, 0x8e,0xbd,0xfc,0x5c,0x1f,0x45,0xcc,0x9a,0x6d,0xa7,0x8b,0x32, 0xc4,0x38,0x1c,0xe9,0x88,0xb0,0xce,0x6f,0xea,0xaa,0x2e,0x98, 0x26,0xb7,0xc1,0xf8,0xbd,0xed,0x37,0xf9,0x04,0x41,0xa5,0xfd, 0x8a,0xe0,0x95,0x50,0xc5,0x80,0xed,0xe4,0xab,0x3c,0x68,0xcf, 0x9b,0x77,0x1a,0x4a,0x41,0xdd,0x8c,0x11,0xfb,0x08,0x1a,0xe4, 0xdf,0x8e,0x22,0xbf,0xf1,0xd5,0xd6,0x41,0x05,0xc4,0x89,0x7e, 0x93,0x4f,0x32,0x2e,0xcb,0x6b,0xa0,0xfa,0xc1,0xe7,0xaa,0x02, 0x28,0x28,0x88,0x83,0x7c,0xb5,0xf2,0x95,0xb1,0x06,0x4a,0x40, 0x63,0xa5,0x06,0xfd,0x2c,0x21,0x35,0xdb,0xed,0x6d,0x45,0xe1, 0x3b,0xc4,0x52,0xfc,0xe7,0x1e,0xfd,0x46,0x8b,0xdf,0xf3,0xd1, 0x75,0xd7,0x83,0xbf,0x40,0x7d,0xfa,0x05,0x39,0x89,0x67,0xbe, 0xb2,0x20,0x97,0x95,0xac,0x80,0x98,0x4a,0x8a,0x41,0x03,0x7e, 0xf0,0x0e,0x4d,0x6a,0xdf,0x5e,0x67,0x2f,0xbb,0x5b,0x3b,0x4d, 0x77,0x68,0xe4,0x33,0x10,0xf3,0x0d,0x8d,0x23,0xe2,0x99,0x82, 0x98,0x98,0x8a,0x0d,0x8a,0x0a,0xc3,0x2a,0xf8,0xef,0xcc,0x9f, 0xbf,0xa1,0x78,0x8e,0xfb,0xcd,0x29,0x25,0x65,0x5d,0xa6,0x95, 0xef,0x10,0x0b,0x11,0x31,0x1b,0x2a,0x2a,0x61,0x70,0x13,0xf1, 0xec,0x8c,0xa2,0x77,0x17,0x87,0x0a,0x4d,0xe3,0x46,0xa1,0x3a, 0x41,0xbd,0x6a,0x83,0x6a,0xbd,0xdb,0x5f,0xd5,0xa7,0x68,0xd6, 0xfb,0x73,0x4f,0x62,0xac,0xef,0xa4,0xb4,0x9a,0x8b,0xc0,0xf1, 0xd7,0x3e,0xa6,0x3b,0x54,0x2d,0x52,0xe4,0x20,0x96,0x8a,0x7d, 0x43,0x60,0xc5,0x6f,0xf6,0xe2,0xbc,0xd1,0x60,0xcb,0x7f,0x58, 0xda,0x3f,0xc5,0x6f,0xf2,0x23,0xc1,0x52,0xeb,0x4b,0x4c,0x80, 0x71,0xcf,0x9e,0x1d,0x69,0xcb,0x4f,0x23,0xf1,0xdb,0x44,0x90, 0xac,0xbd,0xf0,0x6b,0x4b,0x34,0x78,0x17,0x21,0x2a,0x77,0x26, 0xaa,0x61,0xf5,0x6a,0x44,0x5a,0xaf,0x2b,0x3e,0xb4,0x72,0x55, 0x3f,0x5f,0xd5,0xc0,0x96,0x3c,0x4b,0x34,0x5a,0x99,0x7d,0x34, 0xa6,0x47,0x3f,0x9f,0x66,0xd7,0x63,0xf5,0x16,0x2d,0xd4,0x71, 0x30,0x55,0x68,0xdf,0x31,0x96,0x9d,0xd9,0xee,0xe3,0xd1,0x14, 0x3c,0x4f,0x88,0xe2,0xcb,0x59,0xd7,0xce,0xa8,0xd0,0x64,0x32, 0x8b,0x83,0xf6,0xf3,0x79,0x58,0x14,0x95,0xac,0x59,0x51,0x1c, 0xc9,0x14,0xf5,0x6b,0xd5,0x80,0x4e,0x31,0x0e,0x96,0x28,0x8e, 0xf9,0x4d,0x58,0xe3,0xe8,0xa0,0xaf,0x3f,0x3c,0xc9,0x0d,0x25, 0x31,0x85,0xcf,0x06,0x9a,0xb2,0xf3,0xa4,0x1b,0x37,0xcf,0xa8, 0x80,0x05,0x0b,0x6a,0xd2,0xfc,0x49,0x90,0xad,0x48,0x58,0x0d, 0xde,0x45,0x83,0x0a,0x9f,0x55,0xfb,0xa4,0x4b,0x88,0xaa,0x08, 0xe2,0x24,0x03,0x0c,0xcf,0xb2,0x04,0xa2,0x01,0x4b,0xc4,0x37, 0x14,0xdb,0xfa,0x5c,0xb6,0xc3,0x2c,0xb5,0xf3,0x95,0x62,0x19, 0x0c,0x72,0x33,0x4f,0x25,0x03,0x39,0x6d,0xce,0x56,0x9f,0x91, 0xb2,0x68,0xeb,0x0e,0x9b,0x70,0xd8,0x77,0x02,0x24,0x25,0x67, 0x37,0x98,0xad,0xe8,0x1c,0x1d,0x2a,0x1c,0xd7,0x9a,0x38,0xde, 0xf7,0x9b,0xe3,0x18,0x9b,0xc5,0x8e,0x06,0xe3,0xf0,0x22,0x8c, 0x6b,0x85,0xc5,0xbe,0x77,0xdc,0xbd,0x8b,0xf0,0x3e,0xc6,0xa0, 0xea,0xaa,0x57,0x97,0x87,0x29,0xe2,0xa1,0x93,0xab,0xba,0xf9, 0x4a,0xe1,0x78,0x91,0x88,0x4c,0x58,0xf8,0xe5,0xc9,0xd8,0xbf, 0x3a,0xf7,0x56,0x9f,0xd9,0x2c,0x95,0xaf,0x43,0x0a,0x4a,0x20, 0xa2,0xe8,0x3c,0x59,0x27,0xcf,0x50,0x93,0x9f,0xbc,0x64,0xaa, 0x88,0xe4,0xbf,0x12,0x16,0xf0,0x86,0xdf,0x9c,0x72,0x2e,0x23, 0x1e,0xda,0x60,0xac,0x45,0x0a,0x26,0xf0,0xc7,0xba,0xf3,0xa2, 0x95,0x75,0x95,0x7f,0xb7,0x3c,0x72,0x17,0xcd,0xfb,0xc9,0x08, 0x54,0x10,0x79,0x42,0xaf,0x3e,0x8a,0x58,0x11,0x61,0xd8,0xb0, 0x7a,0x20,0x1a,0x60,0x67,0x4a,0x62,0x29,0x0d,0x96,0x64,0x32, 0x9b,0x35,0x5c,0xa1,0x02,0x1c,0x45,0x6b,0xf5,0xbc,0x9b,0x20, 0x67,0xfb,0x4c,0x61,0xd5,0x4c,0x8a,0x4f,0x80,0xa1,0xf2,0x25, 0xe1,0x61,0x56,0xae,0x9f,0x7d,0x79,0xb2,0x68,0x4b,0xe1,0x58, 0x89,0x57,0x29,0xf1,0x8e,0x63,0x7e,0x73,0x0a,0xc6,0x3a,0x00, 0x0c,0x91,0x14,0x76,0x2f,0x82,0x71,0x19,0x14,0xdc,0xaf,0xa4, 0xa2,0x04,0xb2,0x40,0x46,0x4c,0x2c,0x32,0xb8,0x3a,0xc0,0x87, 0xee,0xa2,0x46,0xd5,0xd0,0x71,0xe7,0x9a,0x91,0x33,0x39,0x36, 0x3e,0x79,0xac,0x28,0xd8,0x52,0x3c,0x78,0x9e,0xa5,0x6b,0x09, 0x2f,0xb8,0x56,0x0e,0x5a,0x00,0x0b,0x12,0x0c,0x8c,0xec,0xab, 0x66,0xbb,0xbf,0xb0,0x2a,0x48,0xa9,0x50,0x3c,0x51,0x89,0x8b, 0xd8,0x56,0x8e,0x82,0xca,0x7b,0xc1,0xc2,0x57,0x25,0x31,0xa5, 0x1c,0x39,0x32,0x7f,0xf4,0xea,0xf3,0x5b,0xec,0x4b,0xad,0x85, 0xfc,0x1e,0xef,0x37,0x96,0x0c,0x47,0x05,0x3c,0x49,0x16,0x3a, 0xe0,0x3a,0xd8,0x0a,0x58,0xb2,0xa1,0x92,0x20,0x79,0x16,0x09, 0x81,0xe6,0x95,0x55,0xef,0x2e,0xb8,0x18,0x95,0xc2,0xb2,0xc1, 0xa1,0xa8,0x84,0x59,0x2c,0xa9,0xa4,0xcb,0x34,0x9f,0xcb,0x09, 0xea,0x6d,0x7c,0x5d,0x1d,0x86,0xc3,0xb5,0xfa,0xbf,0x4b,0xba, 0x9a,0xf5,0x09,0x6a,0x8e,0x61,0x14,0xc9,0x07,0xa2,0x38,0xb7, 0x18,0x71,0xa4,0x3d,0xa9,0xd5,0x29,0xd7,0x3e,0x6c,0xd4,0xec, 0xb6,0xff,0x53,0xc8,0xc5,0x8e,0x8d,0xcf,0xb6,0x53,0x4d,0x25, 0x7e,0x8f,0x43,0x3e,0x21,0xaa,0xfe,0x8e,0xf1,0x7a,0x6f,0x81, 0x9e,0x8e,0x75,0x70,0x23,0xdd,0xc7,0x4a,0x75,0x1c,0x2a,0xcd, 0x6a,0x87,0x8a,0x82,0x6d,0x24,0x97,0x21,0x8b,0x47,0xa2,0x30, 0x17,0xa2,0x70,0xa3,0xa7,0x9a,0xf1,0x9a,0xb6,0x61,0x75,0x61, 0x4c,0xde,0x53,0x87,0x4e,0x67,0xba,0x17,0xe2,0xca,0x8b,0xb8, 0xa6,0x24,0xcd,0xfa,0xea,0x55,0xc5,0x12,0xc7,0x72,0xba,0xdd, 0x70,0xee,0xc2,0xff,0x3a,0x28,0xcd,0x62,0x99,0x4d,0xec,0xcd, 0x04,0x9c,0xc3,0x28,0xdc,0xc5,0x28,0xd2,0xd1,0x4e,0xf7,0xb6, 0xa6,0xed,0xed,0xa0,0xda,0xde,0xf9,0xee,0x2d,0xcb,0x32,0xd8, 0xce,0x7a,0x3f,0x36,0xa4,0x5e,0x9d,0xdc,0xc6,0x6d,0x04,0x3c, 0xcc,0xa0,0x4d,0x91,0xa2,0xd8,0x49,0xee,0x88,0x6e,0x56,0xb6, 0x0c,0xa1,0xd8,0xb6,0xbe,0xf3,0x62,0x8c,0x8d,0x55,0x50,0xbf, 0xaf,0x69,0x9b,0x6d,0x02,0xfb,0x61,0x92,0x48,0x1f,0xb7,0xb1, 0x62,0xe1,0x39,0xaa,0x46,0x69,0x16,0x51,0x5d,0x47,0xd3,0x75, 0x26,0x8a,0x86,0x92,0x36,0xa3,0x83,0xca,0x8d,0x2a,0x68,0xae, 0xa6,0x69,0x9b,0xed,0x32,0x7b,0x98,0x80,0x76,0x50,0x52,0x4a, 0xd5,0x94,0x7c,0xa3,0x05,0x68,0xf6,0xc0,0x3a,0x22,0x21,0x41, 0x35,0x65,0x6b,0xd5,0xeb,0xd5,0x3b,0x61,0xb3,0x26,0x1e,0x51, 0xf9,0x3d,0x50,0xe3,0xe8,0xfd,0xb6,0x52,0xcc,0xe2,0x30,0x7c, 0xb9,0x39,0x8a,0xc4,0x97,0x97,0xf5,0xb2,0x86,0xc5,0xa0,0xb0, 0x2c,0x58,0x81,0xa8,0xf0,0xbe,0x11,0x51,0x76,0xd0,0x5c,0xa2, 0x69,0x9b,0xed,0x1f,0x66,0xed,0x15,0xf9,0x66,0xd5,0x3b,0xf1, 0xed,0x73,0xa3,0x34,0x53,0x47,0xfa,0x85,0xa5,0xef,0x43,0xf6, 0xc1,0x17,0x7e,0x8d,0xab,0xbf,0xbb,0x4a,0xb1,0xb6,0x6e,0xe0, 0x54,0x14,0x07,0x0d,0x80,0xfb,0xc0,0x31,0xd1,0x81,0x4a,0x6f, 0x1f,0x14,0x7b,0xa6,0x57,0x02,0xde,0x8a,0x15,0x9b,0xed,0x6e, 0xb3,0x55,0xd7,0x7e,0xf4,0x45,0x8c,0x69,0x95,0x5a,0xf5,0x12, 0xe0,0x90,0xd2,0xac,0x92,0x75,0x06,0x0b,0xb2,0x20,0x17,0xc1, 0xc8,0x2d,0xd3,0x6f,0xeb,0xdd,0x4e,0x45,0x51,0xfa,0x7b,0xc8, 0x3e,0x6c,0x4c,0x34,0x9a,0x83,0x4a,0x0f,0x59,0xb0,0x6c,0xa3, 0x39,0xae,0x69,0x9b,0xed,0x5f,0xd7,0x5b,0x75,0xfb,0x83,0x54, 0x36,0x18,0x9c,0x56,0x42,0xea,0xd6,0xe2,0x5d,0x5b,0xd4,0x72, 0xbe,0xbd,0xb2,0x40,0x91,0xb0,0x7d,0x97,0x58,0x7f,0x1f,0x45, 0x34,0x1a,0x45,0xbf,0xd3,0x4a,0x50,0x9d,0xa2,0x6e,0x58,0x5c, 0xd3,0xdc,0xbf,0x1a,0xa5,0x13,0x98,0xed,0x1f,0x58,0x04,0x3a, 0x6a,0x06,0xcc,0x04,0xaf,0xda,0x56,0x41,0xd4,0x65,0xb7,0x8c, 0xa7,0x34,0x13,0xc0,0xc8,0xe7,0xf4,0x05,0x5f,0x88,0xe9,0x7c, 0x70,0x6f,0x07,0x8a,0xc0,0x73,0x50,0xc4,0x17,0x7d,0x2d,0x67, 0x38,0x26,0xb9,0x27,0xbd,0xf7,0x5e,0x19,0x70,0xc0,0x10,0xa2, 0x69,0x78,0xd0,0x7c,0xfe,0xe6,0xc0,0x39,0x5b,0x85,0x85,0x8c, 0xf1,0x7c,0x9a,0x0d,0x7e,0x1f,0xa3,0x17,0x22,0x91,0xa0,0xd4, 0x9a,0xfb,0x8d,0x6c,0x47,0x48,0x79,0x1d,0x9d,0x25,0x8c,0x5c, 0xf1,0x74,0xbd,0xdb,0x30,0x0a,0x45,0x72,0x01,0x8a,0x66,0x4c, 0x94,0x68,0xda,0x9a,0x11,0xa9,0xde,0x19,0x91,0xcb,0x34,0x6d, 0xb3,0x5d,0xcd,0xfe,0x33,0xc1,0x35,0xff,0xe2,0x2b,0xdf,0x31, 0x94,0x6c,0x28,0xf9,0xca,0x7f,0x79,0xc4,0x52,0xf0,0x88,0x26, 0x23,0xc1,0xf2,0xc8,0x57,0x0a,0x1c,0x3f,0xf3,0x15,0xe5,0x1d, 0xfe,0x0f,0x22,0xbe,0xcb,0x4f,0xcd,0x22,0x56,0x7c,0xe7,0x67, 0xfe,0xc7,0xef,0xa3,0xb1,0xfc,0x82,0x92,0x10,0xc9,0xf8,0x8b, 0x98,0xc8,0x5f,0xfb,0x3c,0x14,0x96,0xec,0x02,0x14,0xcd,0x98, 0x3c,0xf2,0x1b,0x7f,0xf3,0x27,0x31,0x8f,0xd2,0x39,0xfe,0x42, 0xc1,0xdf,0x24,0x82,0xa1,0x92,0xa3,0x46,0x0e,0x5b,0x12,0x63, 0x50,0xfc,0x3a,0x3b,0xf2,0x7d,0xd9,0xff,0x01,0x64,0x81,0x26, 0x61,0x1b,0xc3,0x37,0x8f,0x00,0x00,0x00,0x00,0x49,0x45,0x4e, 0x44,0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/correction.png000066400000000000000000000041051302634723100174370ustar00rootroot00000000000000‰PNG  IHDR«ó4*1sRGB®ÎébKGDÿ‡Ì¿ pHYs  šœtIMEØlËÉIDATxÚíœ/{ëÆÆ§7äÀíGØÂÀ ,ÜÀBx o™òÖ´L¢e6ìeÒG°i™EË,Zæ 4Z¯þ8±åØrZMž'b;Ò«ÕÌÎÌ»ïú ÷e†K¦D³`3’3)E‚¡*2f›m¤9 g‰"¶“áP$ÀšTBl=ÁH([4 Ø£gç˜m¬i`‡gÞ7Ix){T€$Âáȉn6KÁ²Ç1 N&Ùf;« Üùùº §ý$Hb–-™Ë²»Yæ'•‘q¸ÙMf;·øIåhëÝgš°Z{÷N‚p¯3ÇõÍúi%%—)§þ+šÝd¶ó,—`r>WLV;qßÔzÛÙ¯?Á¬ý•¿º“Âp¶;¶/w†G±c(*^ƒ°º=NË’¬‡D‘ór#VpM¢BñJ H)f^ðó„•&ç§^§šªõh#Ì•H߈„§Þ«S„•Cñ20 €`,®9ÁüØºŽ¦¢,ù¤Ó¡Ã<£î¤dCƪõtÍ.\•cßi†uд¯ƒV>•Çþñ–¶ãSkßY‚ÊÉc¸e÷Hý\Ê¿xº¿ì=ÊDËØ)_H_Ûo.¹›üš¨,šœ]‹¼uÒ$ƒf/C¥ýgöþÝ ì]ÀÖî—°_ù™Ÿ¯¯™¶¨ ÍŽ½ü\EÌšm§‹2Ä8鈰Îoêª.˜&·Áø½í7ùA¥ýŠà•PÅ€í䫦;T-Rä –Š}C`Åoöâ¼Ñ`ËXÚ?Åoò#ÁRëKL€qÏžiËO#ñÛD¬½ðkK4x!*w&ªaõjDZ¯+>´rU?_ÕÀ–Æ êªW—‡)â¡“«ºùJáx‘ˆLXøåÉØ¿:÷VŸÙ,•¯C J ¢èŠXaذz `gJb) –d2›5\¡Ekõ¼› gûLaÕLŠO€¡ò%áaV®Ÿ}y²hKáX‰W)ñŽc~s Æ: ‘v/‚qܯ¤¢²@FL,2¸:À‡î¢FÕÐqçš‘396>y¬(ØRlÔì¶ÿSÈŎ϶SM%~C>!ªþŽñzožŽup#ÝÇJu*Íj‡Š‚m$—!‹G¢0¢p£§šñš¶auaLÞS‡NgºâÊ‹¸¦$ÍúêUÅÇrºÝpîÂÿ:(Íb™MìÍœÃ(ÜÅ(ÒÑN÷¶¦íí ÚÞùî-Ë2ØÎz?6¤^ÜÆm<Ì M‘¢ØIîˆnV¶ ¡Ø¶¾óbŒUP¿¯i›mûa’H·±bá9ªFiQ]GÓu&І’6£ƒÊ*h®¦i›í2{˜€vPRJÕ”|£höÀ:"!A5ekÕëÕ;a³&Qù=Pãèý¶RÌâ0|¹9ŠÄ——õ²†Å °,X¨ð¾QvÐ\¢i›ífíùfÕ;ñís£4SGú…¥ïCöÁ~«¿»J±¶nàT €ûÀ1ÑJo{¦WÞŠ›ín³U×~ôEŒi•ZõàÒ¬’u ² ÁÈ-ÓoëÝNEQú{È>lL4šƒJY°l£9®i›í_×[uûƒT6œVBêÖâ][Ôr¾½²@‘°}—XE4E¿ÓJP¢nX\ÓÜ¿¥˜íX:j̯ÚVAÔe·Œ§4ÀÈçô_ˆé|poŠÀsPÄ}-g8&¹'½÷^pÀ¢ixÐ|þæÀ9[……Œñ|š ~£"‘ ÔšûlGHy%Œ\ñt½Û0 ErŠfL”hÚš©Þ‘Ë4m³]Íþ3Á5ÿâ+ß1”l(ùÊyÄRðˆ&#ÁòÈW ?óåþ"¾ËOÍ"V|çgþÇü‚’Éø‹˜È_û<–ì͘<òó'1Ò9þBÁß$‚¡’£F[cPü:;ò}Ùÿd&aÃ7IEND®B`‚fityk-1.3.1/wxgui/img/dpsize.xpm000066400000000000000000000004521302634723100166070ustar00rootroot00000000000000/* XPM */ static const char * dpsize_xpm[] = { "10 15 2 1", " c None", ". c #000000", " ", " ", " . ", " .. ", " .. ", " ... ", " ... ", " ... ... ", " ..... ", " .......", " .......", " .......", " ..... ", " ... ", " "}; fityk-1.3.1/wxgui/img/edit_data.xpm000066400000000000000000000032001302634723100172210ustar00rootroot00000000000000/* XPM */ static const char * edit_data_xpm[] = { "24 24 62 1", " c None", ". c #000000", "+ c #D7D7D7", "@ c #B5B5B5", "# c #FFFFFF", "$ c #C9C9C9", "% c #CCCCCC", "& c #ACACAC", "* c #F2F2F2", "= c #98C092", "- c #D1940C", "; c #EED680", "> c #96B04E", ", c #568106", "' c #127704", ") c #848808", "! c #EAE4CE", "~ c #CEC8B2", "{ c #F6F0DA", "] c #9ABF84", "^ c #2F861F", "/ c #C1D4A8", "( c #64A251", "_ c #7FB16B", ": c #D2DDB8", "< c #A1C38B", "[ c #439132", "} c #C8920B", "| c #3B7D05", "1 c #A48D0A", "2 c #117203", "3 c #A5A9A4", "4 c #5EA055", "5 c #429137", "6 c #62A359", "7 c #106C03", "8 c #839E7F", "9 c #0B4C02", "0 c #789A73", "a c #54944B", "b c #5C9055", "c c #3C8532", "d c #81AA7C", "e c #3A892F", "f c #CBCBCB", "g c #81A97B", "h c #F1F1F1", "i c #97C092", "j c #7EA779", "k c #39892E", "l c #C7C7C7", "m c #072F01", "n c #599950", "o c #54954B", "p c #498940", "q c #348329", "r c #498A40", "s c #959595", "t c #D1D1D1", "u c #D2D2D2", "v c #CECECE", "w c #B4B4B4", " ", " ..................... ", " .++++@#############$. ", " .+%%%&*************$. ", " .+%%%&*************$. ", " .+%%%&******=******$. ", " .-;-;-;-;->,');-;-;-. ", " .;!!!~{{{]''^'/{{{{;. ", " .-!!!~{{('((]'_:{{{-. ", " .;!!!~{]'(]{{('<{{{;. ", " .-!!!~{'[]{{{]'({{{-. ", " .;-;-;}'|;-;-;|'1;-;. 2", " .+%%%345=*****6'=**$.7'", " .+%%%8'5*******'6**$9'2", " .+%%%0'6*******6'=*a'7 ", " .+%%%b'=********'66'9 ", " .@&&&c'd%%%%%%%%d'e'. ", " .+ffg'6hhhhhhhhhhi'j. ", " .+ffk'6hhhhhhhhhhhhl. ", " mno''phhhhhhhhhhhhh$. ", "'9a'qrs%tuvu%tuvu%%%w. ", "'''9m................. ", "' ", " "}; fityk-1.3.1/wxgui/img/editf.xpm000066400000000000000000000025561302634723100164130ustar00rootroot00000000000000/* XPM */ static const char * editf_xpm[] = { "24 24 44 1", " c None", ". c #000000", "+ c #FFFFFF", "@ c #C2C2C2", "# c #292929", "$ c #040404", "% c #262626", "& c #BFBFBF", "* c #B6B6B6", "= c #494949", "- c #E6E6E6", "; c #5F5F5F", "> c #141414", ", c #212121", "' c #848484", ") c #272727", "! c #CBCBCB", "~ c #FBFBFB", "{ c #2D2D2D", "] c #D7D7D7", "^ c #373737", "/ c #C8C8C8", "( c #171717", "_ c #DEDEDE", ": c #515151", "< c #030303", "[ c #FDFDFD", "} c #919191", "| c #303030", "1 c #0A0A0A", "2 c #7B7B7B", "3 c #111111", "4 c #F2F2F2", "5 c #CACACA", "6 c #151515", "7 c #242424", "8 c #C7C7C7", "9 c #101010", "0 c #BDBDBD", "a c #929292", "b c #FEFEFE", "c c #D6D6D6", "d c #CCCCCC", "e c #484848", " ", " ", " ", " ", " ...................... ", ".++++++++++++++++++++++.", ".++++++++++++.+.++.++++.", ".+@#$%&+*=++++.-;>.,'++.", ".+).!.%~{]++++.^./(_:++.", ".+<.[.$}|#$%&+.1.234+++.", ".+%.5.676.!.)+.89...98+.", ".+0)<%{a<.b.$+.++432.1+.", ".++++c{~%.d.#+.+:_(/.^+.", ".++++e*+0%<)@+.+',.>;-+.", ".++++++++++++.+.++.++++.", ".++++++++++++++++++++++.", " ...................... ", " ", " ", " ", " ", " ", " ", " "}; fityk-1.3.1/wxgui/img/editor16.h000066400000000000000000000100121302634723100163620ustar00rootroot00000000000000static const unsigned char editor16_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10, 0x08,0x06,0x00,0x00,0x00,0x1f,0xf3,0xff,0x61,0x00,0x00,0x00, 0x04,0x73,0x42,0x49,0x54,0x08,0x08,0x08,0x08,0x7c,0x08,0x64, 0x88,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0d, 0xd7,0x00,0x00,0x0d,0xd7,0x01,0x42,0x28,0x9b,0x78,0x00,0x00, 0x00,0x19,0x74,0x45,0x58,0x74,0x53,0x6f,0x66,0x74,0x77,0x61, 0x72,0x65,0x00,0x77,0x77,0x77,0x2e,0x69,0x6e,0x6b,0x73,0x63, 0x61,0x70,0x65,0x2e,0x6f,0x72,0x67,0x9b,0xee,0x3c,0x1a,0x00, 0x00,0x02,0x9b,0x49,0x44,0x41,0x54,0x38,0x8d,0x75,0x90,0x4b, 0x6c,0x8c,0x51,0x18,0x86,0x9f,0x73,0xce,0x3f,0xa3,0xfd,0x4d, 0xca,0x4c,0x3b,0x0d,0xad,0xd4,0x65,0x52,0x75,0x0b,0x6d,0xd4, 0x25,0x68,0xe9,0x6a,0x48,0x44,0xc4,0x42,0xa2,0x21,0x48,0x48, 0x24,0x62,0x25,0x96,0x22,0x69,0xd2,0xb0,0x40,0xcb,0x82,0x05, 0x56,0xc4,0x2d,0x11,0x89,0x4b,0x52,0x11,0x09,0xa2,0x22,0x22, 0x33,0x94,0x50,0x55,0xa5,0x4c,0x5c,0x66,0x86,0xe8,0xf8,0xa7, 0x3d,0x67,0x66,0x32,0xbf,0x8d,0x96,0xde,0xde,0xcd,0xf3,0xe5, 0x4b,0xde,0x37,0xdf,0xfb,0x89,0x70,0x38,0x0c,0xc0,0x86,0x4d, 0xeb,0x9b,0x26,0x78,0xbd,0xfb,0x4d,0x26,0xf3,0x6c,0x82,0xd7, 0x5b,0x3b,0x92,0xda,0x98,0xa3,0x37,0xaf,0xdf,0x3e,0x04,0x70, 0x3e,0x16,0xf3,0x29,0x63,0x64,0x63,0x28,0x94,0x12,0x77,0xee, 0xde,0xda,0x27,0x95,0x3a,0x51,0x5e,0x3e,0x4d,0x04,0x4b,0x4a, 0x49,0x24,0xe3,0x8c,0xc5,0x0f,0xbd,0xef,0x49,0x26,0x92,0x6e, 0xd5,0xe9,0x73,0xf7,0x02,0x5d,0xef,0x56,0xe7,0x95,0xca,0x59, 0x70,0x40,0x6d,0xdf,0xb9,0xed,0xc9,0xca,0xe5,0xf5,0xe2,0xd2, 0x95,0x8b,0x94,0x04,0x4b,0x68,0x6b,0x6b,0x23,0x58,0x1a,0x1c, 0xc5,0xfb,0xf7,0x1f,0x10,0xf8,0xfa,0x4d,0xf4,0xd8,0x85,0xb3, 0xd2,0x33,0x67,0x29,0xff,0xd2,0x65,0x1e,0xf5,0xea,0x55,0x83, 0xcc,0x66,0xb3,0x02,0xa0,0xc8,0xe7,0xa7,0xe5,0x78,0x2b,0x7d, 0xbf,0x9c,0x51,0x6c,0x6d,0x39,0x81,0x3f,0xfd,0x85,0xf8,0xa4, 0x22,0xe6,0x37,0x6e,0x23,0x3a,0xa5,0x84,0x8f,0xa9,0x3e,0x5c, 0xc8,0x5b,0x5a,0x6b,0x00,0xd6,0xad,0x0d,0x53,0x5f,0xb7,0x0a, 0xcb,0xb2,0xc8,0xe5,0x72,0xc3,0xf8,0xe1,0xc6,0x31,0x7a,0x72, 0x05,0xf4,0xa7,0x1d,0x3a,0x3b,0x5f,0x93,0x1a,0xc8,0x10,0xeb, 0x77,0xdc,0x2a,0xd7,0xdd,0x63,0x69,0x6d,0x00,0xb0,0x6d,0x1b, 0xdb,0xb6,0x19,0x26,0xd7,0xe5,0xe7,0xd5,0xfd,0xcc,0xf8,0x15, 0x65,0x75,0xc3,0x1a,0xde,0x7f,0x8e,0x71,0xe3,0xa3,0xc1,0xef, 0x2b,0x80,0x1f,0xf9,0xcb,0x5b,0xca,0xcb,0x2f,0x58,0xe6,0xef, 0x05,0x00,0xd1,0xe7,0xd1,0xa1,0xb9,0x66,0x51,0x35,0xdd,0xa7, 0xb6,0x52,0xec,0x7e,0xa7,0xa2,0x61,0x0d,0x26,0xd1,0xcb,0xe4, 0x8c,0x17,0x8f,0x9b,0xa5,0xd0,0x89,0x5d,0x3a,0xdb,0xf5,0xa9, 0x11,0xc0,0xd2,0xc6,0xfc,0x33,0x55,0xd7,0x20,0x84,0x40,0xe0, 0x92,0x3c,0xbf,0x87,0x62,0x91,0xa0,0xa2,0xbe,0x0e,0x13,0xef, 0xe5,0x77,0xca,0x43,0x22,0xf2,0x88,0x82,0xc0,0x24,0xae,0x3d, 0x8d,0x35,0x0e,0x7a,0xa4,0xd6,0x1a,0x21,0x04,0x52,0x4a,0x5e, 0x74,0xbc,0x40,0x49,0x49,0xf7,0xc9,0xcd,0x48,0xa7,0x87,0x8a, 0xba,0x15,0x98,0x78,0x2f,0x4e,0x9f,0x45,0x32,0xd2,0xce,0xb4, 0x5d,0xe7,0xf8,0xaa,0xa6,0x0c,0x6b,0x39,0x14,0xa0,0x94,0xa2, 0x76,0xf1,0x12,0xcc,0x9b,0x6b,0x4c,0x9d,0x57,0xc9,0xf4,0x8d, 0xfb,0x30,0xf1,0x4f,0xfc,0xee,0x53,0x24,0x9e,0x3f,0x26,0xb8, 0xe3,0x0c,0x56,0x68,0x15,0x8e,0xe3,0x0c,0x0f,0x30,0xda,0x20, 0x84,0x44,0x4a,0x45,0x24,0x1a,0x41,0x27,0x3a,0x28,0x5a,0xb0, 0x1e,0x39,0x77,0x07,0xc6,0xae,0x26,0x1e,0x69,0xa7,0x7b,0xee, 0x6e,0xd2,0x81,0x79,0x68,0x6d,0x18,0x7c,0xfa,0xa0,0xac,0xff, 0x2f,0xf0,0xc9,0x34,0xb7,0xda,0xdf,0xb1,0xb9,0x68,0x26,0xdf, 0xde,0xee,0x25,0x9b,0x4a,0x62,0xc2,0x87,0xa9,0x0c,0x2d,0x43, 0x4a,0x89,0xc7,0xe3,0x21,0x93,0xcd,0x8c,0x0c,0x30,0x7f,0x7f, 0xa0,0x38,0xd2,0xdc,0x44,0xe4,0x65,0x17,0x73,0x66,0x57,0x32, 0xb1,0xac,0x16,0x55,0x56,0x45,0x30,0x58,0x46,0x20,0x10,0xc0, 0xe7,0xf3,0x21,0xa5,0x24,0x9b,0x19,0x19,0x60,0x34,0x52,0x4a, 0x00,0x0e,0x36,0xb7,0x30,0x3d,0x34,0x1f,0xdb,0xb6,0xb1,0x2c, 0x8b,0xb1,0x34,0xaa,0x82,0xd1,0xda,0x7d,0xf0,0xf0,0x9e,0x28, 0xb4,0x0b,0x01,0x78,0xdd,0xd9,0x31,0xa6,0x11,0x20,0xdd,0x3f, 0x40,0x3e,0x9f,0x77,0xff,0xdf,0x89,0x85,0xb5,0x4b,0xdd,0xf1, 0x0c,0xe3,0x69,0x6a,0xb1,0x5f,0x0c,0xce,0x7f,0x00,0x67,0xa1, 0x2e,0x36,0x12,0x87,0xe9,0xd5,0x00,0x00,0x00,0x00,0x49,0x45, 0x4e,0x44,0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/editor16.png000066400000000000000000000014361302634723100167310ustar00rootroot00000000000000‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<›IDAT8uKlŒQ†ŸsÎ?£ýMÊL; ­ÔeRu mÔ%héjHDÄB¢!HH$b%–"iÒ°@Ë‚VÄ-‰KR ¢""3”PU¥L\f†èø§=gf2¿–ÞÞÍóåKÞ7ßû‰p8 À†Më›&x½ûM&ól‚×[;’Ú˜£7¯ß>p>ó)cdc(”wîÞÚ'•:Q^>MKJI$ãŒÅ½ïI&’nÕés÷]ïVç•ÊYp@mß¹íÉÊåõâÒ•‹”Khkk#XÅû÷øúMôØ…³Ò3g)ÿÒeõêUƒÌf³ Èç§åx+}¿œQlm9?ý…ø¤"æ7n#:¥„©>\È[ZkÖ­ S_· ˲ÈårÃøáÆ1zrô§:;_“ÈëwÜ*×Ýcim°mÛ¶&×åçÕýÌøeuÃÞŽqã£Áï+€ùË[ÊË/XæïÑçÑ¡¹fQ5ݧ¶Rì~§¢a &ÑË䌛¥Ð‰]:Ûõ©ÀÒÆü3U× „@à’<¿‡b‘ ¢¾ïåwÊC"òˆ‚À$®=5z¤Ö!RJ^t¼@II÷ÉÍH§‡Šº˜x/NŸE2Òδ]çøª¦ k9 ”¢vñÌ›kLWÉôû0ñOüîS$ž?&¸ã VhŽã 0Ú „DJE$A':(Z°9wÆ®&i§{înÒyhm|ú ¬ÿ/ðÉ4·Úß±¹h&ßÞî%›Jb‡© -CJ‰Çã!“ÍŒ 0 8ÒÜDäesfW2±¬UVE0XF Àçó!¥$›`4RJ6·0=4Û¶±,‹±4ª‚ÑÚ}ððž(´ xÝÙ1¦ Ý?@>Ÿwÿ߉…µKÝñ ãij±_ Îg¡.6‡éÕIEND®B`‚fityk-1.3.1/wxgui/img/eq_fwhm.h000066400000000000000000000035721302634723100163700ustar00rootroot00000000000000static const unsigned char eq_fwhm_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x18, 0x08,0x06,0x00,0x00,0x00,0xe0,0x77,0x3d,0xf8,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff, 0xa0,0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73, 0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,0x13,0x01,0x00,0x9a,0x9c, 0x18,0x00,0x00,0x01,0x02,0x49,0x44,0x41,0x54,0x48,0xc7,0xed, 0x95,0x21,0x0e,0xc2,0x30,0x14,0x86,0x3f,0x06,0x57,0x98,0xe0, 0x04,0x38,0x92,0x65,0x09,0x69,0x32,0xc3,0x0c,0x8a,0x4d,0x70, 0x88,0x99,0x9d,0x00,0xb5,0x5d,0x00,0x89,0xe1,0x10,0x08,0x40, 0xe1,0x10,0x28,0x42,0xd0,0x70,0x02,0x6e,0x51,0xcc,0x48,0x06, 0xe9,0xba,0x95,0xd5,0x40,0x78,0x49,0x45,0x9b,0xf7,0xfe,0xf7, 0xff,0x7d,0x7f,0x5a,0xd0,0x47,0x06,0xc8,0x9a,0x95,0xe9,0x00, 0x1c,0xfe,0xd1,0x32,0x7e,0x6c,0x06,0x5e,0x9c,0x66,0x5e,0x9c, 0x66,0x26,0x35,0x5d,0x13,0x70,0x20,0x07,0xc6,0xfd,0xc1,0x88, 0xfb,0xf5,0x74,0xb0,0xcd,0x5c,0x96,0xf6,0xb2,0xa9,0x92,0xa6, 0x33,0xc8,0x81,0xa8,0xb4,0x8f,0x8a,0x33,0xfb,0xec,0x4d,0x55, 0x38,0x1f,0xb0,0xb7,0xa7,0xc2,0x8b,0xd3,0xa9,0x8a,0xfd,0x9b, 0x8a,0x69,0x1b,0x05,0xdb,0x1a,0x96,0x79,0x91,0x63,0xde,0xe0, 0xc9,0x6c,0x31,0x4f,0x5c,0x29,0x65,0xa2,0x5a,0x8b,0x79,0xe2, 0x96,0x73,0x55,0xd1,0xd3,0x34,0xf7,0x67,0x93,0x80,0x50,0x0c, 0x05,0x20,0x54,0x09,0xa1,0x18,0x32,0x9b,0x04,0xac,0xf7,0x47, 0x1f,0xd8,0x99,0xde,0x7f,0x23,0x97,0x54,0xb9,0xcc,0x6a,0x91, 0x8e,0x8c,0xa3,0x79,0x12,0x22,0x03,0x4e,0x11,0x90,0xab,0x9a, 0x74,0xab,0xc0,0x2f,0x9b,0x65,0xe3,0x3b,0xbd,0x5f,0x4f,0xb7, 0xfe,0x60,0x74,0x06,0x56,0xef,0xef,0x54,0xa7,0x70,0x40,0xd9, 0x6a,0x46,0xe0,0x0a,0xe7,0xbd,0x60,0x75,0x0a,0xd6,0x67,0x80, 0x4f,0x81,0xab,0x2c,0x0e,0xf8,0xdf,0xff,0xe7,0x3e,0x00,0x61, 0x02,0x81,0xa9,0xec,0x09,0x0f,0x57,0x00,0x00,0x00,0x00,0x49, 0x45,0x4e,0x44,0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/eq_fwhm.png000066400000000000000000000005571302634723100167250ustar00rootroot00000000000000‰PNG  IHDRàw=øsRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœIDATHÇí•!Â0†?W˜à8’e i2à ŠMpˆ™µ]‰á@á(BÐpnQÌH麕Õ@xIE›÷þ÷ÿ}ZÐGÈš•éþÑ2~l^œf^œf&5]p ÆýÁˆûõt°Í\–ö²©’¦3Ȩ´Š3ûìMU8°·§Â‹Ó©Šý›ŠiÛ–y‘cÞàÉl1O\)e¢Z‹yâ–sUÑÓ4÷g“€P  T ¡2›¬÷GØ™Þ#—T¹Ìj‘ŽŒ£y"N«št«À/›eã;½_O·þ`tVïïT§p@ÙjFà ç½`u Ög€O«,øßÿç>a©ì WIEND®B`‚fityk-1.3.1/wxgui/img/eq_shape.h000066400000000000000000000064631302634723100165310ustar00rootroot00000000000000static const unsigned char eq_shape_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x18, 0x08,0x06,0x00,0x00,0x00,0xe0,0x77,0x3d,0xf8,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0x00,0x00,0x00,0x00,0x00, 0xf9,0x43,0xbb,0x7f,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73, 0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,0x13,0x01,0x00,0x9a,0x9c, 0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xdb,0x03, 0x08,0x11,0x02,0x24,0x25,0xe8,0x5b,0x67,0x00,0x00,0x02,0x0f, 0x49,0x44,0x41,0x54,0x48,0xc7,0xed,0x95,0x5f,0x48,0x53,0x71, 0x14,0xc7,0x3f,0x77,0xce,0x08,0xca,0x32,0x0a,0x94,0xe8,0x41, 0x8d,0x76,0x5f,0xc2,0x71,0x37,0x71,0xd8,0x83,0xb4,0xa0,0x86, 0x23,0x26,0x41,0xd4,0x82,0x56,0x30,0xa2,0x1e,0x6e,0x52,0x17, 0x07,0x81,0xf8,0xd2,0x1f,0xa2,0xb7,0xb1,0x61,0xe1,0xa2,0x8c, 0x18,0x41,0x58,0xbd,0x37,0xeb,0xad,0x40,0x22,0x7d,0xb0,0x87, 0xd2,0x82,0xa0,0x5e,0xca,0x70,0xa0,0xf9,0x22,0xc9,0x3c,0xbd, 0xdc,0x9f,0x5c,0x66,0xdb,0x9c,0x4a,0x4f,0x1e,0xb8,0xf0,0xe3, 0x9c,0xdf,0xf9,0x9e,0x7f,0xdf,0xf3,0xbb,0x1a,0x95,0x45,0x2a, 0xd8,0xb5,0x72,0x46,0x17,0x9b,0xb2,0x9e,0xfe,0x6d,0xce,0xa0, 0x6a,0x31,0x22,0xa6,0x18,0x11,0x53,0x44,0x64,0x6c,0xb5,0x3e, 0xee,0x6a,0xc0,0x75,0x8f,0x0e,0x80,0xaf,0xfb,0xb2,0x5f,0x44, 0xc6,0x34,0x4d,0x6b,0xdb,0x90,0x00,0x0a,0x3c,0xe0,0xd5,0x97, 0x75,0xab,0x0d,0x52,0x71,0xc8,0xc9,0x6c,0x4e,0x00,0x02,0x5e, 0x1d,0x2b,0x16,0xd2,0xac,0x58,0x48,0x53,0x81,0xa6,0xf3,0xbf, 0xfd,0xeb,0xea,0x79,0x32,0x9b,0x13,0x23,0x62,0x4a,0x34,0x91, 0x5e,0x41,0xd5,0x68,0x22,0x2d,0x46,0xc4,0x94,0x9f,0x33,0x73, 0xb2,0xa6,0x0a,0x92,0xd9,0xdc,0x6e,0x75,0x76,0xb6,0xa6,0x9c, 0xae,0xda,0x16,0xcd,0xdc,0xea,0xb7,0x50,0x83,0xfd,0x97,0xe8, 0x1e,0x9d,0xae,0x78,0x1f,0xe5,0xaa,0x70,0x95,0xc8,0xbe,0xd1, 0x99,0xa9,0x15,0x0b,0xad,0xd8,0x56,0xe7,0x2c,0xd6,0x52,0xc1, 0x8f,0x77,0x13,0x53,0xcb,0x40,0xa5,0x9c,0x95,0xed,0xea,0x9d, 0xc7,0x25,0xab,0x50,0x34,0x0d,0x02,0x47,0x81,0x5d,0xdb,0xb6, 0xef,0xd8,0x39,0x3c,0x94,0x62,0xa1,0xae,0x19,0x4f,0x4b,0x13, 0xa3,0xdf,0x3e,0x1e,0x01,0x8e,0xdb,0x6f,0xce,0x0b,0xe0,0x2d, 0x90,0xb1,0xfd,0x96,0x1a,0x6a,0xe7,0x99,0x18,0x1f,0x05,0xce, 0x63,0xeb,0x47,0x6c,0xbc,0x3c,0xf0,0x48,0x55,0x70,0x02,0x78, 0x03,0xdc,0xb8,0x3e,0xf0,0xf4,0xcc,0x42,0x5d,0xb3,0x33,0x89, 0x25,0xe0,0x1a,0xf0,0xc0,0xbe,0x07,0x70,0xc9,0xfe,0x4c,0x7f, 0x47,0x90,0xfc,0xf7,0x49,0xba,0xe2,0x7d,0x7c,0x9a,0xfa,0x7c, 0x11,0xf8,0x05,0x58,0x76,0xa0,0x73,0x0a,0xa4,0x15,0x30,0x81, 0x9b,0x07,0x7c,0x9d,0xd2,0xd2,0x1e,0x16,0x9b,0xff,0x99,0xa2, 0x36,0xaa,0xcc,0x0f,0x03,0xb7,0x81,0x41,0x20,0xd3,0x11,0x0c, 0x8b,0x11,0x31,0x65,0x7f,0xeb,0x21,0x29,0x14,0x0a,0xe3,0xf6, 0x9d,0x5a,0xe0,0x9e,0x72,0xfe,0x00,0xdc,0x3d,0xdd,0x9b,0xea, 0x77,0xd7,0xef,0xa3,0x66,0x71,0xbe,0xb8,0x82,0x62,0x39,0x09, 0x3c,0x01,0x7a,0x80,0x01,0xc5,0xa8,0xd9,0xb9,0x59,0x8e,0x9d, 0xed,0xf5,0xd9,0xe0,0xed,0xc0,0xb4,0x3b,0x9a,0x48,0xcb,0xab, 0x67,0x83,0x00,0xbc,0x7e,0x7e,0x9f,0x86,0xc6,0xbd,0x84,0xc2, 0xdd,0x95,0xc8,0xf1,0x12,0xb8,0xe0,0x38,0x13,0xf0,0xea,0xbc, 0x1f,0xa9,0xe7,0xeb,0x97,0x49,0xf6,0x34,0x1d,0xfc,0xe3,0xde, 0xb2,0x95,0xb6,0xce,0x30,0x9a,0x73,0x4b,0x9d,0xb4,0x2b,0xc7, 0x9e,0x52,0x5b,0x3f,0x3c,0x94,0xe2,0x54,0xfc,0x0a,0x8a,0x81, 0x1b,0x2e,0x2e,0x57,0xcd,0xc3,0xff,0xfe,0x0f,0xf9,0x0b,0xd3, 0x41,0xaf,0xda,0x8e,0xf6,0x30,0x15,0x00,0x00,0x00,0x00,0x49, 0x45,0x4e,0x44,0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/eq_shape.png000066400000000000000000000012171302634723100170560ustar00rootroot00000000000000‰PNG  IHDRàw=øsRGB®ÎébKGDùC» pHYs  šœtIMEÛ$%è[gIDATHÇí•_HSqÇ?wÎÊ2 ”èAv_Âq7q؃´ †#&AÔ‚V0¢nRøÒ¢·±aᢌAX½7ë­@"}°‡Ò‚ ^Êp ù"É<½ÜŸ\fÛœJO¸ðãœßùžßó»•E*صrF›²žþmΠj1"¦SDdlµ>îjÀu€¯û²_DÆ4MkÛ <àÕ—u« RqÈÉlN^+Ò¬XHS¦ó¿ýëêy2›#bJ4‘^AÕh"-FÄ”Ÿ3s²¦ ’ÙÜnuv¶¦œ®ÚÍÜê·Pƒý—è®xåªp•Ⱦљ© ­ØVç,ÖRÁwSË@¥œ•íêÇ%«P4 G]Û¶ïØ9<”b¡®OK£ß>ŽÛoÎ à-±ý–jç™ÎcëGl¼<ðHUpxܸ>ðôÌB]³3‰%àðÀ¾pÉþLGü÷Iºâ}|šú|øXv s ¤0›|ÒÒ›ÿ™¢6ªÌ·A Ó ‹1eë!) ãöZàžrþÜ=Ý›êw×ï£fq¾¸‚b9 <z€ŨٹYŽíõÙàíÀ´;šHË«gƒ¼~~Ÿ†Æ½„ÂÝ•Èñ¸à8ð꼩çë—Iö4üãÞ²•¶Î0šsK´+ÇžR[?<”âTü Š..WÍÃÿþù ÓA¯ÚŽö0IEND®B`‚fityk-1.3.1/wxgui/img/exec_down.xpm000066400000000000000000000100771302634723100172700ustar00rootroot00000000000000/* XPM */ static const char * exec_down_xpm[] = { "24 24 178 2", " c None", ". c #000000", "+ c #E2E2E2", "@ c #F2F2F2", "# c #CFCECA", "$ c #A6A6A6", "% c #E8E8E8", "& c #F3F3F3", "* c #F7F7F7", "= c #F4F4F4", "- c #DBDBDB", "; c #F0F0F0", "> c #E0E0E0", ", c #E1E1E1", "' c #DFDFDF", ") c #E1E1E0", "! c #97958F", "~ c #898781", "{ c #8E8C85", "] c #838078", "^ c #858585", "/ c #CDCDCD", "( c #E4E4E4", "_ c #ECECEC", ": c #EEEEEE", "< c #EFEFEF", "[ c #EDEDED", "} c #898989", "| c #D9D9D9", "1 c #7B7973", "2 c #67655F", "3 c #403F3B", "4 c #686661", "5 c #7C7A72", "6 c #717171", "7 c #8B8B8B", "8 c #8E8E8E", "9 c #F1F1F1", "0 c #E7E7E7", "a c #DDDCDB", "b c #9A9992", "c c #53524E", "d c #171614", "e c #767573", "f c #9B9993", "g c #52504A", "h c #B0B0B0", "i c #D8D8D8", "j c #E3E3E3", "k c #8A8A8A", "l c #A8A8A8", "m c #DDDDDD", "n c #7A7974", "o c #86847D", "p c #9A9996", "q c #B7B6B3", "r c #7D7B75", "s c #646464", "t c #7E7E7E", "u c #8C8C8C", "v c #8F8F8F", "w c #E9E9E9", "x c #EAEAEA", "y c #D7D7D7", "z c #8B8984", "A c #6B6964", "B c #78756C", "C c #5F5D56", "D c #54534D", "E c #656565", "F c #B1B1B1", "G c #EBEBEB", "H c #E5E5E5", "I c #5C5B57", "J c #676662", "K c #93928C", "L c #63625E", "M c #403F3A", "N c #363433", "O c #4B4947", "P c #E6E6E6", "Q c #9C9A94", "R c #9C9B94", "S c #9D9B95", "T c #9B9A94", "U c #908E89", "V c #7C7A75", "W c #565552", "X c #050504", "Y c #050505", "Z c #656560", "` c #030303", " . c #E4E3E1", ".. c #979797", "+. c #0A0A0A", "@. c #5C5C58", "#. c #5D5C59", "$. c #9D9C96", "%. c #5C5A57", "&. c #565452", "*. c #504F4C", "=. c #474744", "-. c #444340", ";. c #DEDEDE", ">. c #B3B3B1", ",. c #484641", "'. c #9F9D96", "). c #080808", "!. c #888781", "~. c #F5F5F5", "{. c #9F9D97", "]. c #9E9D96", "^. c #908E86", "/. c #97958E", "(. c #807D74", "_. c #5E5D5A", ":. c #5F5D5A", "<. c #918F8A", "[. c #5F5E5B", "}. c #B5C9DC", "|. c #9BB6D0", "1. c #91B0CC", "2. c #49749C", "3. c #456F96", "4. c #595854", "5. c #605E57", "6. c #898883", "7. c #76746B", "8. c #AFC5DA", "9. c #A0BAD3", "0. c #9EB8D1", "a. c #3F6588", "b. c #375978", "c. c #43423F", "d. c #282724", "e. c #363430", "f. c #6D6B63", "g. c #F6F6F6", "h. c #909090", "i. c #7B7B7B", "j. c #B2C7DB", "k. c #9CB7D1", "l. c #9AB5CF", "m. c #21201E", "n. c #0A0908", "o. c #181816", "p. c #E6E6E4", "q. c #65635C", "r. c #B6CADD", "s. c #161614", "t. c #8C8B89", "u. c #DFDEDC", "v. c #B6B5AF", "w. c #D5D4D1", "x. c #93918B", "y. c #F8F8F8", "z. c #5D5C55", "A. c #DCDBDA", "B. c #5B88B2", "C. c #A4BDD5", "D. c #2A435B", "E. c #494943", "F. c #7A7975", "G. c #5080AD", "H. c #42413C", "I. c #111111", "J. c #7F7F7F", "K. c #070707", "L. c #C9C9C9", "M. c #97B3CE", "N. c #0E0E0E", "O. c #0D0D0D", "P. c #A3A3A3", "Q. c #3E3E39", "R. c #080D11", "S. c #5F8BB4", "T. c #95B2CE", "U. c #4C79A3", " ", " . . . . . . . . . . . . . . . . . . . . ", ". + @ @ @ @ @ . . . # . . . $ % & * * = - . ", ". ; > > , + ' . ) ! ~ { ] . ^ / ( _ : < [ . ", ". @ , } } | . . 1 2 3 4 5 . . 6 ^ 7 8 ; 9 . ", ". @ + 0 % 0 . a b c d e f g . h i _ ; 9 @ . ", ". & j k l m . . n o p q r . . s t u v @ & . ", ". & ( w x w y . z A B C D . E F i G < 9 & . ", ". & H I J K L . . . M . . . N O . . . ' _ . ", ". = P Q R S T U V . . . W X Y Z ` .` ..+.. ", ". = 0 @.#.$.#.%.&.*.=.-.` ;.>.` ,.'.,.).!.. . ", ". ~.% $.$.$.{.{.].. . . . . . . '.'.^./.(.,.. ", ". ~.w _.:.<.:.[.[.. }.|.1.2.3.. 4.5.6.(.7.. . ", ". ~.x @ & < = @ & . 8.9.0.a.b.. c.d.e.'.f.,.. . ", ". g.G h.i.... . . . j.k.l.a.b.. m.n.o.p.(.q.5.. ", ". * [ = . . . # . . r.k.l.a.b.. e.s.t.u.q.,.. . ", ". * : v . ) ! ~ { . r.|.|.a.b.. v.p.w.x.q.. . ", ". y.; . . 1 . . . . r.l.k.a.b.. . . . 7.z.,.. ", ". y.9 . A.b c . B.0.C.9.k.a.a.a.D.. ,.).E.. . ", ". @ @ . . F.o p . G.k.k.k.a.a.D.. H.I.J.K.. . ", ". L.[ + . z A B C . G.M.9.a.D.. I.N.O.P.8 . ", " . . . . . . Q.. . R.S.T.D.. . . . . . . ", " . . . . . U.. ", " . "}; fityk-1.3.1/wxgui/img/exec_selected.xpm000066400000000000000000000102031302634723100201000ustar00rootroot00000000000000/* XPM */ static const char * exec_selected_xpm[] = { "24 24 182 2", " c None", ". c #000000", "+ c #E2E2E2", "@ c #F2F2F2", "# c #CFCECA", "$ c #A6A6A6", "% c #E8E8E8", "& c #F3F3F3", "* c #F7F7F7", "= c #F4F4F4", "- c #DBDBDB", "; c #F0F0F0", "> c #E0E0E0", ", c #E1E1E1", "' c #DFDFDF", ") c #E1E1E0", "! c #97958F", "~ c #898781", "{ c #8E8C85", "] c #838078", "^ c #858585", "/ c #CDCDCD", "( c #E4E4E4", "_ c #ECECEC", ": c #EEEEEE", "< c #EFEFEF", "[ c #EDEDED", "} c #898989", "| c #D9D9D9", "1 c #7B7973", "2 c #67655F", "3 c #403F3B", "4 c #686661", "5 c #7C7A72", "6 c #717171", "7 c #8B8B8B", "8 c #8E8E8E", "9 c #F1F1F1", "0 c #E7E7E7", "a c #DDDCDB", "b c #9A9992", "c c #53524E", "d c #171614", "e c #767573", "f c #9B9993", "g c #52504A", "h c #B0B0B0", "i c #D8D8D8", "j c #E3E3E3", "k c #8A8A8A", "l c #A8A8A8", "m c #DDDDDD", "n c #7A7974", "o c #86847D", "p c #9A9996", "q c #B7B6B3", "r c #7D7B75", "s c #646464", "t c #7E7E7E", "u c #8C8C8C", "v c #8F8F8F", "w c #E9E9E9", "x c #EAEAEA", "y c #D7D7D7", "z c #8B8984", "A c #6B6964", "B c #78756C", "C c #5F5D56", "D c #54534D", "E c #656565", "F c #B1B1B1", "G c #EBEBEB", "H c #E5E5E5", "I c #5C5B57", "J c #676662", "K c #93928C", "L c #63625E", "M c #403F3A", "N c #363433", "O c #4B4947", "P c #E6E6E6", "Q c #9C9A94", "R c #9C9B94", "S c #9D9B95", "T c #9B9A94", "U c #908E89", "V c #7C7A75", "W c #565552", "X c #050504", "Y c #050505", "Z c #656560", "` c #030303", " . c #E4E3E1", ".. c #979797", "+. c #0A0A0A", "@. c #5C5C58", "#. c #5D5C59", "$. c #9D9C96", "%. c #5C5A57", "&. c #565452", "*. c #504F4C", "=. c #474744", "-. c #444340", ";. c #DEDEDE", ">. c #B3B3B1", ",. c #484641", "'. c #9F9D96", "). c #080808", "!. c #888781", "~. c #F5F5F5", "{. c #9F9D97", "]. c #9E9D96", "^. c #9A9893", "/. c #8F8D88", "(. c #070606", "_. c #B0AFAD", ":. c #A8A7A1", "<. c #908E86", "[. c #97958E", "}. c #807D74", "|. c #5E5D5A", "1. c #5F5D5A", "2. c #918F8A", "3. c #5F5E5B", "4. c #5F5E5A", "5. c #5F5F5B", "6. c #5D5D59", "7. c #454442", "8. c #595854", "9. c #605E57", "0. c #898883", "a. c #76746B", "b. c #F6F6F6", "c. c #010101", "d. c #43423F", "e. c #282724", "f. c #363430", "g. c #6D6B63", "h. c #909090", "i. c #7B7B7B", "j. c #666666", "k. c #6A6A6A", "l. c #E2E2E1", "m. c #B6B5AF", "n. c #21201E", "o. c #0A0908", "p. c #181816", "q. c #E6E6E4", "r. c #65635C", "s. c #040404", "t. c #161614", "u. c #8C8B89", "v. c #DFDEDC", "w. c #4D4D4D", "x. c #515151", "y. c #B0AFA9", "z. c #D5D4D1", "A. c #93918B", "B. c #F8F8F8", "C. c #D6D5D2", "D. c #ABA9A3", "E. c #5D5C55", "F. c #DCDBDA", "G. c #161616", "H. c #494943", "I. c #7A7975", "J. c #888888", "K. c #828282", "L. c #121212", "M. c #42413C", "N. c #111111", "O. c #7F7F7F", "P. c #070707", "Q. c #C9C9C9", "R. c #AFAFAF", "S. c #C3C3C3", "T. c #C2C2C2", "U. c #C0C0C0", "V. c #0E0E0E", "W. c #0D0D0D", "X. c #A3A3A3", "Y. c #3E3E39", " ", " . . . . . . . . . . . . . . . . . . . . ", ". + @ @ @ @ @ . . . # . . . $ % & * * = - . ", ". ; > > , + ' . ) ! ~ { ] . ^ / ( _ : < [ . ", ". @ , } } | . . 1 2 3 4 5 . . 6 ^ 7 8 ; 9 . ", ". @ + 0 % 0 . a b c d e f g . h i _ ; 9 @ . ", ". & j k l m . . n o p q r . . s t u v @ & . ", ". & ( w x w y . z A B C D . E F i G < 9 & . ", ". & H I J K L . . . M . . . N O . . . ' _ . ", ". = P Q R S T U V . . . W X Y Z ` .` ..+.. ", ". = 0 @.#.$.#.%.&.*.=.-.` ;.>.` ,.'.,.).!.. . ", ". ~.% $.$.$.{.{.].^.K /.(._.:.'.'.'.<.[.}.,.. ", ". ~.w |.1.2.1.3.3.4.5.6.7.` '.'.8.9.0.}.a.. . ", ". ~.x @ & < = @ & = b.c.c.,.'.9.d.e.f.'.g.,.. . ", ". b.G h.i.... . . j.k.c.l.m.'.8.n.o.p.q.}.r.9.. ", ". * [ = . . . # . . . c.s.,.'.0.f.t.u.v.r.,.. . ", ". * : v . ) ! ~ { ] . w.x.s.y.}.m.q.z.A.r.. . ", ". B.; . . 1 2 3 4 5 . . ).C.D.'.}.}.a.a.E.,.. ", ". B.9 . F.b c d e f g . s.G.8.` ,.a.,.).H.. . ", ". @ @ . . I.o p q r . . J.).).K.L.M.N.O.P.. . ", ". Q.[ + . z A B C D . k.R.S.T.U.N.V.W.X.8 . ", " . . . . . . Y.. . . . . . . . . . . . . ", " . . . . ", " "}; fityk-1.3.1/wxgui/img/export16.h000066400000000000000000000107011302634723100164220ustar00rootroot00000000000000static const unsigned char export16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd3, 0x02, 0x19, 0x0c, 0x2e, 0x31, 0x5c, 0x6c, 0x7f, 0x26, 0x00, 0x00, 0x02, 0x70, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9c, 0x9d, 0x93, 0x4d, 0x48, 0xd3, 0x71, 0x18, 0xc7, 0x3f, 0x7b, 0x31, 0xe7, 0x4b, 0x73, 0xf9, 0xb2, 0x29, 0x26, 0xea, 0x25, 0x69, 0x05, 0x79, 0x18, 0x9d, 0xac, 0x5c, 0xa6, 0x6e, 0x1e, 0xa2, 0x43, 0x42, 0x1e, 0x2a, 0xe8, 0x10, 0x58, 0x20, 0x88, 0x22, 0xd1, 0xa5, 0xf4, 0x52, 0x52, 0x14, 0x09, 0x46, 0x42, 0x77, 0x21, 0xb0, 0xc0, 0x8a, 0x56, 0x96, 0xa6, 0x08, 0x25, 0x4d, 0xb3, 0x94, 0x81, 0x14, 0x6a, 0xb1, 0xcd, 0x6d, 0xbe, 0x6e, 0x2c, 0xff, 0xff, 0xbd, 0xfc, 0xfd, 0x75, 0x58, 0x69, 0xda, 0xba, 0xf4, 0x85, 0xe7, 0xf2, 0xc0, 0xf7, 0xf3, 0x7c, 0x7f, 0x3c, 0xbf, 0x07, 0xa0, 0x16, 0x10, 0xff, 0x59, 0xf5, 0x2a, 0x40, 0x48, 0x72, 0x94, 0x69, 0x4f, 0x10, 0xa5, 0xaf, 0x9b, 0xb4, 0x14, 0x2d, 0x49, 0xa5, 0x4a, 0x58, 0xd4, 0x6a, 0x35, 0x4b, 0x27, 0x2e, 0x00, 0x60, 0x3d, 0x90, 0x8f, 0x16, 0xc0, 0xbd, 0x2a, 0x31, 0xe2, 0x9c, 0xc2, 0xac, 0x6c, 0x20, 0x16, 0xdd, 0x20, 0xc4, 0x0e, 0xb7, 0x00, 0x54, 0xa8, 0xd4, 0x2a, 0x52, 0x0c, 0xd9, 0x4c, 0x4c, 0xbb, 0x78, 0xf7, 0x76, 0x10, 0x20, 0x01, 0x08, 0x47, 0xe2, 0x00, 0x94, 0x9c, 0x6a, 0xa0, 0xac, 0xac, 0x2c, 0x79, 0x82, 0x5f, 0x8a, 0xc5, 0x62, 0xbc, 0xe8, 0x7d, 0x4d, 0x2c, 0x16, 0xd9, 0x02, 0xfc, 0xa9, 0x99, 0x99, 0x99, 0x7f, 0x9a, 0x85, 0x10, 0x14, 0x16, 0x16, 0xa2, 0x44, 0x23, 0x44, 0xe3, 0x4a, 0x72, 0xc0, 0xce, 0x04, 0x1b, 0x1b, 0x1b, 0xc8, 0xb2, 0x8c, 0x24, 0x49, 0x18, 0x8d, 0xc6, 0xcd, 0xbe, 0xed, 0x7c, 0x33, 0x00, 0xea, 0x64, 0x09, 0x7e, 0x97, 0xc3, 0xe1, 0x40, 0xaf, 0xd7, 0x63, 0x34, 0x1a, 0xe9, 0xef, 0xef, 0x47, 0xab, 0xd5, 0xf2, 0xd2, 0xf1, 0x1c, 0xb5, 0x46, 0x43, 0x70, 0xc9, 0xff, 0x77, 0x02, 0x93, 0xc9, 0x84, 0xc1, 0x60, 0x00, 0x20, 0x1c, 0x0e, 0x63, 0xb1, 0x58, 0xe8, 0xe8, 0xe8, 0xc0, 0xeb, 0x75, 0xd3, 0xd4, 0xd4, 0x44, 0x95, 0xb5, 0x02, 0x8f, 0x7b, 0x9e, 0xea, 0xe3, 0x47, 0x18, 0x70, 0x3c, 0xe2, 0xe6, 0x8d, 0xf6, 0xc4, 0x72, 0x3e, 0xce, 0x2f, 0x33, 0x38, 0xf6, 0x89, 0x52, 0x63, 0x16, 0x7b, 0x4d, 0xd9, 0x28, 0x91, 0x18, 0x72, 0x3c, 0x4e, 0xdd, 0x31, 0x0b, 0x43, 0x6f, 0x1c, 0xac, 0xac, 0x2c, 0xe3, 0xf7, 0x2d, 0x6c, 0x0e, 0x0a, 0x06, 0xd7, 0x48, 0x4d, 0xd5, 0xe1, 0xf7, 0x79, 0xb7, 0x27, 0x98, 0x0b, 0x04, 0xf9, 0xb2, 0xb0, 0xca, 0x7a, 0x38, 0x84, 0x1a, 0x38, 0xd7, 0xdc, 0xce, 0xd1, 0xca, 0x1a, 0x7a, 0xee, 0xdf, 0x01, 0xe0, 0xd5, 0xc0, 0x20, 0xa9, 0xbb, 0x34, 0xec, 0x37, 0x1f, 0x64, 0x6d, 0xd5, 0xcb, 0xba, 0x24, 0x6d, 0x07, 0x08, 0x21, 0x28, 0xce, 0x50, 0x51, 0x54, 0x6c, 0xa2, 0xa2, 0xa2, 0x02, 0x80, 0xda, 0xea, 0x4a, 0x00, 0x86, 0x87, 0x87, 0x09, 0x04, 0x16, 0xf1, 0x78, 0x3c, 0xb8, 0x5c, 0x33, 0x34, 0x36, 0x5e, 0x64, 0x62, 0x62, 0x7c, 0x3b, 0x40, 0x96, 0x65, 0x8a, 0x8a, 0x0c, 0x9b, 0xb0, 0xdb, 0xb7, 0x3a, 0x31, 0x9b, 0xf7, 0xe1, 0xf7, 0x2d, 0x10, 0x89, 0x2a, 0xcc, 0xce, 0xce, 0xe1, 0xf7, 0x07, 0xd0, 0x67, 0xe9, 0xa9, 0xb5, 0x9f, 0xe4, 0xdb, 0xfc, 0xec, 0xd6, 0x16, 0x22, 0xb1, 0x18, 0x4a, 0x34, 0xf1, 0x39, 0x74, 0x3a, 0x1d, 0x00, 0x6d, 0x57, 0xae, 0xd2, 0x75, 0xaf, 0x0b, 0x80, 0xf2, 0xf2, 0x43, 0xe4, 0xe5, 0x66, 0x93, 0xb9, 0x3b, 0x93, 0xd6, 0x96, 0x16, 0x22, 0xb2, 0x8c, 0xc7, 0xeb, 0x4b, 0x00, 0x1e, 0x3e, 0xe8, 0xde, 0x66, 0x2e, 0x28, 0x28, 0xa0, 0xf4, 0xb0, 0x8d, 0xba, 0xb3, 0x97, 0x18, 0x19, 0x1d, 0x63, 0x4f, 0x76, 0x0e, 0xd2, 0x8f, 0x20, 0xd7, 0xdb, 0xaf, 0x31, 0x39, 0x39, 0x89, 0xdd, 0x6e, 0xe3, 0xd9, 0xd3, 0x27, 0x00, 0x68, 0x00, 0xd7, 0x87, 0xd1, 0xa1, 0xfa, 0xfc, 0xdc, 0x5c, 0xbe, 0x7b, 0x7d, 0xe4, 0xa4, 0x81, 0xa2, 0x28, 0x94, 0xe4, 0x65, 0xd2, 0x73, 0xb7, 0x93, 0xc7, 0x7d, 0xbd, 0xc8, 0x92, 0x44, 0x7a, 0x7a, 0x06, 0xae, 0xe9, 0xcf, 0x8c, 0x3b, 0xdf, 0xe3, 0x74, 0x8e, 0x11, 0x0a, 0xad, 0xb1, 0x16, 0x0c, 0x6d, 0x3e, 0xbf, 0x9e, 0xc4, 0xc5, 0x4c, 0x01, 0x5f, 0xd9, 0x71, 0xb6, 0x0d, 0x67, 0x4e, 0x0b, 0x40, 0xd8, 0x6a, 0xac, 0xa2, 0xad, 0xf5, 0xb2, 0xb0, 0xd5, 0x58, 0x05, 0x20, 0xec, 0xf6, 0x2a, 0xf1, 0x13, 0xec, 0xf1, 0x1e, 0xae, 0x42, 0xf8, 0x34, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/export16.png000066400000000000000000000013431302634723100167610ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÓ .1\l&pIDATxœ“MHÓqÇ?{1çKsù²)&ê%iy¬\¦n¢CB*èX ˆ"Ñ¥ôRR FBw!°ÀŠV–¦%M³”j±Ím¾n,ÿÿ½üýuXiÚºô…çòÀ÷ó|<¿ ÿYõ*@Hr”iO¥¯›´-I¥JXÔj5K'.`=À½*1âœÂ¬l Ý Ä·T¨Ô*R ÙLL»x÷v G├j ¬¬,y‚_ŠÅb¼è}M,Ùü©™™™š…¢D#DãJrÀÎȲŒ$IÆÍ¾í|3êd ~—Ãá@¯×c4éïïG«ÕòÒñµFCpÉÿw“É„Á` c±XèèèÀëuÓÔÔD•µ{žêãGp<âæöÄr>Î/38ö‰Rc{MÙ(‘rèÞf.(( ô°º³—cOvÒ ×Û¯199‰ÝnãÙÓ'hׇѡúüÜ\¾{}䤢(”äeÒs·“Ç}½È’Dzz®éÏŒ;ßãtŽ ­± m>¿žÄÅL_Ùq¶ gN @Øj¬¢­õ²°ÕX ìö*ñìñ®Bø4ÈIEND®B`‚fityk-1.3.1/wxgui/img/fileopen16.h000066400000000000000000000070541302634723100167110ustar00rootroot00000000000000static const unsigned char fileopen16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd6, 0x09, 0x16, 0x16, 0x07, 0x04, 0x20, 0x56, 0xb2, 0xbc, 0x00, 0x00, 0x00, 0x1d, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, 0xef, 0x64, 0x25, 0x6e, 0x00, 0x00, 0x01, 0xb0, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0xa5, 0x92, 0x4b, 0x6b, 0x13, 0x51, 0x1c, 0xc5, 0x7f, 0x77, 0x3a, 0x82, 0x25, 0xa4, 0xb5, 0x1a, 0xa5, 0xee, 0xba, 0x0b, 0xa8, 0x8b, 0xf9, 0x08, 0x0d, 0x45, 0xb4, 0x1b, 0x5d, 0xa4, 0x2f, 0xba, 0x71, 0x51, 0x90, 0x22, 0xd1, 0x6f, 0x23, 0x3e, 0xb0, 0xd2, 0x5d, 0x45, 0xfa, 0x01, 0xba, 0xa9, 0xad, 0x16, 0xc4, 0x55, 0x08, 0x81, 0x08, 0x6e, 0xd2, 0x12, 0x5d, 0xf5, 0xaa, 0xe9, 0xb4, 0x9d, 0x66, 0x1e, 0xbd, 0xf7, 0xba, 0x18, 0x1b, 0x72, 0x3b, 0x09, 0x16, 0x3c, 0x9b, 0x0b, 0xff, 0xe7, 0x39, 0xff, 0x7b, 0xc4, 0x93, 0xca, 0xf2, 0xae, 0x94, 0x72, 0x82, 0x73, 0x28, 0x14, 0x0a, 0x5f, 0x5f, 0x3c, 0x7f, 0x75, 0x9b, 0x7f, 0xc0, 0x95, 0x52, 0x4e, 0x54, 0x2a, 0x8f, 0x70, 0x9c, 0xa1, 0x6e, 0xf0, 0x24, 0xe8, 0xf0, 0x66, 0x65, 0xed, 0x16, 0x17, 0x80, 0x0b, 0x10, 0xc7, 0x21, 0xbb, 0x7b, 0x4d, 0x30, 0x06, 0x63, 0x0c, 0x37, 0xae, 0xdf, 0x04, 0x60, 0x76, 0xbe, 0x6c, 0x06, 0x35, 0x8e, 0x8d, 0x5d, 0xd9, 0x7e, 0xfd, 0x72, 0xa5, 0xe4, 0x02, 0x84, 0x61, 0x44, 0x10, 0x9c, 0xa4, 0x19, 0x03, 0xdf, 0x7f, 0xb4, 0x98, 0x29, 0xdf, 0x23, 0x8a, 0x23, 0x04, 0x0e, 0x08, 0x61, 0x35, 0xc7, 0x71, 0xc2, 0xc6, 0xc6, 0xa7, 0xc9, 0x2e, 0x83, 0x5e, 0x34, 0x1a, 0x7b, 0xf8, 0x7e, 0x00, 0xd4, 0xfb, 0x6e, 0x1e, 0x1f, 0xbf, 0x8a, 0xe7, 0xdd, 0xb1, 0x25, 0xf4, 0xc2, 0xf7, 0x03, 0xde, 0xbf, 0x5b, 0x1f, 0xa8, 0x79, 0x6e, 0x61, 0x26, 0x7b, 0x03, 0xa5, 0x14, 0x49, 0x12, 0x5b, 0x87, 0x6c, 0xb7, 0x7f, 0xf5, 0xd1, 0x7d, 0x0d, 0x80, 0x24, 0x49, 0xec, 0x01, 0x5a, 0x6b, 0xd2, 0x57, 0x75, 0x13, 0xb5, 0x5a, 0x2d, 0x33, 0xa0, 0x54, 0x9a, 0x22, 0xbd, 0x59, 0xc7, 0x1e, 0x10, 0x45, 0x21, 0x9d, 0x4e, 0x68, 0x15, 0x7b, 0x9e, 0xc7, 0x85, 0xbf, 0x71, 0xe8, 0x92, 0x4b, 0x1c, 0x25, 0x56, 0x62, 0x67, 0xe7, 0x23, 0x6f, 0x57, 0x57, 0x51, 0x4a, 0x65, 0x9a, 0x36, 0x37, 0xbf, 0x90, 0xcb, 0xe5, 0x58, 0x58, 0x9c, 0x5b, 0x13, 0xb3, 0xf3, 0x65, 0x93, 0xcf, 0xe7, 0x91, 0x52, 0x5a, 0x45, 0x0f, 0x1f, 0xdc, 0xa5, 0x58, 0x2c, 0x32, 0x32, 0x92, 0xe7, 0x4c, 0xe6, 0xa9, 0x3a, 0xc5, 0x18, 0x30, 0x5a, 0xf1, 0x61, 0xeb, 0x33, 0xd5, 0x6a, 0x3d, 0x65, 0xf0, 0xec, 0xe9, 0x12, 0xc6, 0x64, 0x3d, 0x73, 0x7c, 0xec, 0xd3, 0x6c, 0x36, 0x10, 0xe7, 0x7c, 0x00, 0x30, 0x7d, 0x7f, 0x8a, 0x6a, 0xb5, 0x2e, 0xdd, 0xd4, 0x3b, 0x86, 0x56, 0xeb, 0x5b, 0x5f, 0x8d, 0x8e, 0xe3, 0x64, 0x62, 0x5a, 0x6b, 0x0e, 0x0e, 0x7c, 0x80, 0x23, 0x17, 0xa0, 0xfd, 0xfb, 0x27, 0xa3, 0xa3, 0x05, 0x8b, 0xc5, 0xd9, 0x56, 0x9b, 0x98, 0xf9, 0x1b, 0x13, 0x1c, 0x1e, 0xfa, 0x00, 0xbe, 0x78, 0xbc, 0xbc, 0xb4, 0xb5, 0xbf, 0x2f, 0x27, 0xd3, 0xc9, 0x03, 0xad, 0x8f, 0xe3, 0x88, 0x1e, 0x06, 0x86, 0xe1, 0xe1, 0xcb, 0x47, 0x5a, 0xeb, 0x45, 0xfe, 0x17, 0x7f, 0x00, 0x4c, 0x41, 0xba, 0x40, 0x96, 0xdc, 0xc6, 0x23, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/fileopen16.png000066400000000000000000000011141302634723100172350ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÖ  V²¼tEXtCommentCreated with The GIMPïd%n°IDAT8Ë¥’KkQÅw:‚%¤µ¥îº ¨‹ù E´]¤/ºqQ"Ño#>°Ò]Eúº©­ÄUnÒ]õªé´f½÷ºr; <› ÿç9ÿ{Ä“Êò®”r‚s( __<u›À•RNT*pœ¡nð$èðfeí€ Ç!»{M0c 7®ß`v¾l5Ž]Ù~ýr¥ä„aDœ¤ß´˜)ß#Š#a5ÇqÂÆÆ§É.ƒ^4{ø~Ôûn¿Šçݱ%ôÂ÷Þ¿[¨yna&{¥I[‡l·õÑ} €$IìZkÒWuµZ-3 Tš"½YÇE!Nh{žÇ…¿qè’K%Vbgç#oWWQJeš67¿ËåXXœ[³óe“Ïç‘RZEÜ¥X,22’çLæ©:Å0Zñaë3Õj=eðìéÆd=s|ìÓl6ç|0}Šjµ.ÝÔ;†Vë[_ŽãdbZk|€# ýû'££‹ÅÙV›˜ùú¾x¼¼´µ¿/'Óɭ㈆ááËGZëEþLAº@–ÜÆ#IEND®B`‚fityk-1.3.1/wxgui/img/filereload16.h000066400000000000000000000107351302634723100172160ustar00rootroot00000000000000static const unsigned char filereload16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x02, 0x9c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x85, 0x93, 0x5b, 0x48, 0x54, 0x51, 0x14, 0x86, 0xbf, 0xd4, 0xa6, 0x99, 0x8c, 0x2c, 0xc7, 0xac, 0x81, 0x72, 0xd2, 0xf2, 0x82, 0x95, 0x8a, 0x0f, 0x39, 0x15, 0x8c, 0x18, 0x5d, 0x84, 0x88, 0xca, 0x0b, 0x51, 0x69, 0x88, 0x89, 0xe0, 0x25, 0x12, 0x05, 0x09, 0x2b, 0x8c, 0x88, 0x88, 0x28, 0x0a, 0xc4, 0x32, 0x34, 0x48, 0xf0, 0x25, 0x04, 0x7d, 0x89, 0x92, 0x8a, 0x71, 0x84, 0x22, 0xd2, 0x22, 0x53, 0xd4, 0x02, 0x8b, 0x19, 0xc9, 0xe9, 0x8c, 0xa5, 0xe6, 0x05, 0x1c, 0xe7, 0x78, 0x5c, 0x3d, 0x98, 0x83, 0x66, 0xd4, 0x86, 0xff, 0xe1, 0x67, 0xaf, 0xf5, 0xed, 0xbd, 0xf6, 0xda, 0x0b, 0xe0, 0x20, 0x20, 0xf3, 0x2a, 0x2f, 0x4a, 0x96, 0x85, 0xfe, 0x3f, 0xca, 0x04, 0x90, 0x29, 0x8f, 0x57, 0x3a, 0x3e, 0x7f, 0x97, 0xec, 0xf4, 0x44, 0x19, 0x1d, 0x7c, 0x26, 0x80, 0x54, 0x54, 0x54, 0x88, 0xdb, 0xed, 0xf6, 0x69, 0x68, 0x68, 0x48, 0xdc, 0x6e, 0xb7, 0x8c, 0x8d, 0x8d, 0x49, 0x6b, 0x8f, 0x22, 0xad, 0x3d, 0xca, 0x3c, 0x04, 0xe9, 0x1f, 0x54, 0xe4, 0x64, 0x5a, 0x82, 0x8c, 0x0c, 0x3e, 0x97, 0x91, 0xde, 0xcb, 0x02, 0xc8, 0x16, 0xb3, 0x51, 0x62, 0x23, 0x43, 0x25, 0x78, 0xcd, 0x4a, 0x29, 0x29, 0x29, 0x91, 0xc6, 0xc6, 0x46, 0xb1, 0xdb, 0xed, 0xe2, 0x70, 0x38, 0xe4, 0xd6, 0x23, 0x9b, 0x64, 0x14, 0x5c, 0x14, 0x40, 0x02, 0x00, 0x2e, 0x14, 0x1e, 0xa0, 0xa6, 0xfa, 0x3a, 0x32, 0xf6, 0x0a, 0x80, 0x91, 0xde, 0xcb, 0x00, 0x7c, 0x71, 0x0e, 0xd3, 0xfe, 0x7e, 0x80, 0xc2, 0x8a, 0x3b, 0x4c, 0x4c, 0x4c, 0x50, 0x5b, 0x5b, 0x8b, 0xaa, 0xaa, 0x4c, 0x4d, 0xf5, 0xa0, 0xaa, 0xd3, 0x00, 0x04, 0x1c, 0xda, 0x17, 0xc3, 0xbd, 0xaa, 0xab, 0xc8, 0x78, 0x3b, 0x7f, 0xae, 0x08, 0xb3, 0x91, 0x08, 0xb3, 0x11, 0xd3, 0xfa, 0xd5, 0x1c, 0x3b, 0xf3, 0x80, 0xb8, 0xb8, 0x38, 0x72, 0x72, 0x72, 0xd0, 0xbc, 0xd3, 0x78, 0x67, 0xb4, 0x39, 0xc0, 0xec, 0xac, 0x50, 0x7f, 0x25, 0x83, 0xbd, 0x09, 0xba, 0x25, 0x00, 0x5d, 0xd0, 0x46, 0x56, 0xac, 0x0d, 0x23, 0x79, 0xd7, 0x6e, 0x1a, 0xaa, 0x8e, 0x93, 0x75, 0xf6, 0x1c, 0x56, 0xab, 0x75, 0x51, 0x4c, 0xc0, 0x53, 0xdb, 0x27, 0xbe, 0x0d, 0x99, 0x80, 0x61, 0x1f, 0x24, 0xbe, 0x78, 0x12, 0x80, 0xf2, 0xb4, 0x7e, 0x62, 0xc2, 0x9c, 0xec, 0xd9, 0x3d, 0x4a, 0xcc, 0x56, 0x0b, 0x00, 0x6d, 0x6d, 0x6d, 0xb0, 0x32, 0xcc, 0x07, 0xf0, 0x03, 0xd8, 0xb9, 0x37, 0x8b, 0x9a, 0xd6, 0x20, 0x5e, 0xf7, 0xa9, 0xbe, 0x8d, 0xb2, 0xb2, 0x32, 0x6e, 0x34, 0xcd, 0x60, 0xeb, 0xf4, 0xd2, 0xd7, 0xdd, 0x43, 0x84, 0xd9, 0x08, 0x80, 0xcb, 0xe5, 0x5a, 0x74, 0x03, 0x3f, 0x80, 0x82, 0xd2, 0xf3, 0xec, 0x3f, 0x55, 0xca, 0xb5, 0x66, 0x3d, 0x2d, 0x5d, 0xcb, 0x01, 0x98, 0xf4, 0x42, 0xc6, 0x89, 0xd3, 0x34, 0xd8, 0x35, 0x94, 0x91, 0x59, 0x5f, 0x82, 0xf3, 0xc7, 0xe4, 0x52, 0x00, 0x40, 0xf8, 0xb6, 0x24, 0x0e, 0xe7, 0x96, 0x73, 0xbf, 0x05, 0x02, 0x03, 0x75, 0xfc, 0x54, 0xfd, 0xd9, 0x91, 0x72, 0x14, 0x80, 0xd0, 0xa8, 0x5d, 0xdc, 0x7d, 0x38, 0xd7, 0xa1, 0x58, 0xcb, 0xbe, 0xc5, 0x6f, 0xb0, 0xd0, 0x84, 0x6f, 0xb7, 0x50, 0x7c, 0xfe, 0x36, 0xdd, 0x1d, 0x6d, 0xe4, 0x65, 0x1f, 0xc1, 0x60, 0x30, 0x50, 0x09, 0x24, 0x5a, 0x92, 0x48, 0x4b, 0xba, 0x8e, 0x71, 0xd3, 0x56, 0xcc, 0xab, 0x97, 0xe1, 0x1c, 0x97, 0xbf, 0x03, 0x3c, 0x1e, 0x0f, 0x29, 0xf1, 0x91, 0x24, 0xc5, 0x47, 0x92, 0x5e, 0x74, 0x09, 0xa5, 0xd3, 0xc6, 0x9b, 0xc7, 0x45, 0xd4, 0x37, 0xbe, 0x05, 0x40, 0x5d, 0x6e, 0xa0, 0xe5, 0xd5, 0x07, 0x92, 0x2d, 0x09, 0x4b, 0x4b, 0x98, 0x56, 0x55, 0x34, 0xef, 0xdc, 0xe7, 0xd0, 0xeb, 0xf5, 0x28, 0x9d, 0x36, 0x9a, 0xea, 0xb2, 0x78, 0xd7, 0xf5, 0x95, 0xca, 0x9b, 0x2f, 0xc8, 0xcd, 0xcd, 0xc5, 0x5f, 0xa7, 0xc7, 0xcf, 0xdf, 0x0f, 0x5d, 0xc0, 0x1f, 0x25, 0xd4, 0xd5, 0x54, 0xb3, 0x21, 0x2a, 0xc1, 0x97, 0x6c, 0x32, 0x99, 0x08, 0xdf, 0x99, 0x4a, 0x5a, 0x5e, 0x03, 0x00, 0xf9, 0xf9, 0xf9, 0x44, 0x47, 0x47, 0xd3, 0xdc, 0xfe, 0x71, 0xf1, 0xa9, 0x80, 0x3f, 0xd0, 0xdb, 0xf1, 0xb2, 0x35, 0x73, 0x43, 0x48, 0x08, 0x03, 0x2e, 0x05, 0xa3, 0x01, 0x34, 0x4d, 0x63, 0xf3, 0xba, 0x55, 0xa4, 0xa6, 0xa6, 0x62, 0xb5, 0x5a, 0xf1, 0x78, 0x3c, 0x68, 0x9a, 0x86, 0xe2, 0x1a, 0x45, 0x55, 0xa7, 0x08, 0x0e, 0x34, 0xf0, 0xc4, 0x66, 0x67, 0x42, 0x71, 0xf8, 0x40, 0x99, 0xbf, 0x27, 0xab, 0x1b, 0xe8, 0xff, 0xc7, 0xf8, 0x3a, 0x00, 0xe7, 0x02, 0x7f, 0xf0, 0x17, 0xa4, 0x91, 0x2b, 0xe5, 0x96, 0xd1, 0x3e, 0xac, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/filereload16.png000066400000000000000000000013471302634723100175520ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“œIDATxÚ…“[HTQ†¿Ô¦™Œ,ǬrÒò‚•Š9Œ]„ˆÊ Qiˆ‰à% +Œˆˆ( Ä24Hð%}‰’Šq„"Ò"SÔ‹É錥æçx\=˜ƒfÔ†ÿág¯õí½öÚ à ó*/J–…þ?Ê)W:>—ìôD|&€TTTˆÛíöihhHÜn·ŒIk"­=Ê<éTädZ‚Œ >—‘ÞËȳQb#C%xÍJ)))‘ÆÆF±Ûíâp8äÖ#›d\@. ¦ú:2ö €‘ÞË|qÓþ~€ÂŠ;LLLP[[‹ªªLMõ ªÓÚýª«Èx;®³‘³ÓúÕ;󀸸8rrrмÓxg´9Àì¬P%ƒ½ º%]ÐFV¬ #y×nªŽ“uöV«uQLÀSÛ'¾ ™€a$¾x€ò´~bœìÙ=JÌV mmm°2Ìðع7‹šÖ ^÷©¾²²2n4Í`ëôÒ×ÝC„Ù€ËåZt?€‚Òóì?Uʵf=-]˘ôBƉÓ4Ø5”‘Y_‚óÇäR@ø¶$ç–s¿uüTýÙ‘r€Ð¨]Ü}8סX˾Åo°Ð„o·P|þ6ÝmäeÁ`0P $Z’HKºŽqÓVÌ«—á—¿<)ñ‘$ÅG’^t ¥ÓÆ›ÇEÔ7¾@]n åÕ’- KK˜VU4ïÜçÐëõ(6šê²x×õ•Ê›/ÈÍÍÅ_§ÇÏß]À%ÔÕT³!*Á—l2™ß™JZ^ùùùDGGÓÜþqñ©€?ÐÛñ²5sCH.£4McóºU¤¦¦bµZñx¬IEND®B`‚fityk-1.3.1/wxgui/img/filesaveas16.h000066400000000000000000000072261302634723100172330ustar00rootroot00000000000000static const unsigned char filesaveas16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd6, 0x09, 0x0c, 0x14, 0x33, 0x0f, 0x30, 0x8e, 0xfb, 0x56, 0x00, 0x00, 0x01, 0xea, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x95, 0x91, 0x3f, 0x68, 0x13, 0x71, 0x14, 0xc7, 0x3f, 0xbf, 0x1f, 0x77, 0x17, 0x4c, 0x88, 0x48, 0xf0, 0x2f, 0x5e, 0x34, 0xa0, 0x14, 0x69, 0x41, 0xa8, 0x5a, 0x44, 0x10, 0x37, 0x97, 0xe2, 0x20, 0x3a, 0x18, 0xbb, 0x58, 0x8c, 0xa1, 0xb3, 0xe0, 0xa0, 0x20, 0x82, 0x5d, 0xa2, 0x88, 0xc6, 0x46, 0x70, 0x11, 0x0b, 0x45, 0xa1, 0x1a, 0x13, 0x27, 0xc1, 0xa1, 0x4b, 0x43, 0x6b, 0x17, 0x1d, 0xac, 0x96, 0x16, 0x34, 0x28, 0xd7, 0x53, 0xea, 0xd1, 0x24, 0x9e, 0xc6, 0x34, 0x6a, 0x4c, 0xce, 0x29, 0xb1, 0x97, 0x3f, 0x8a, 0x6f, 0x7b, 0xbc, 0xef, 0xe7, 0xfb, 0xde, 0xe3, 0x2b, 0x42, 0xfd, 0xb1, 0x71, 0x20, 0x0c, 0xf0, 0x38, 0x70, 0x81, 0x76, 0x95, 0xa9, 0x4a, 0x00, 0x76, 0x89, 0x1a, 0x9b, 0x24, 0x1c, 0x2b, 0xc4, 0xea, 0xa3, 0x07, 0x0a, 0x10, 0x1e, 0xbd, 0x12, 0xc1, 0xeb, 0x51, 0xd8, 0x3d, 0xff, 0xb4, 0x05, 0xbe, 0x95, 0x9c, 0xe6, 0xd4, 0xc8, 0x34, 0xc6, 0xd4, 0x23, 0x26, 0x53, 0x23, 0x1c, 0x3e, 0x7e, 0x90, 0xd1, 0x1d, 0x11, 0x00, 0x4e, 0x9f, 0xbf, 0x1b, 0x56, 0xea, 0xc2, 0xe4, 0x8c, 0x41, 0xef, 0xc0, 0x84, 0x0b, 0xbe, 0x3d, 0xb8, 0x86, 0xc1, 0xc4, 0x33, 0xcc, 0xcc, 0x3d, 0x66, 0x17, 0x96, 0x01, 0x58, 0xea, 0xbe, 0xca, 0x93, 0x99, 0x8f, 0x1c, 0xd9, 0xbb, 0x15, 0x00, 0xd9, 0xbc, 0xd1, 0xb2, 0x2c, 0x2c, 0xcb, 0x72, 0xc1, 0xaf, 0xde, 0xe6, 0xf9, 0x3c, 0x9f, 0xa6, 0xef, 0x44, 0x9c, 0x8d, 0xa1, 0x3d, 0x38, 0x8e, 0xd3, 0xd0, 0x2b, 0xab, 0x61, 0x55, 0x55, 0x09, 0x04, 0x02, 0x00, 0x18, 0x72, 0x3f, 0xaf, 0x27, 0xa7, 0x30, 0xde, 0x2c, 0x93, 0x9b, 0x4b, 0x73, 0xf4, 0x62, 0x86, 0x0d, 0xdb, 0x7b, 0xa9, 0x54, 0x2a, 0xae, 0x85, 0x2d, 0x17, 0x98, 0xa6, 0xc9, 0x9d, 0xe8, 0x5a, 0xb2, 0x4b, 0x79, 0x1e, 0xa6, 0x52, 0xe4, 0xe6, 0xd2, 0x1c, 0x38, 0x93, 0xe4, 0xbb, 0x5c, 0x8f, 0x69, 0x9a, 0x38, 0x8e, 0x83, 0x10, 0xa2, 0xfd, 0x05, 0x00, 0xc1, 0x60, 0x90, 0xb3, 0xe3, 0x35, 0xe2, 0x27, 0xb3, 0x8d, 0xad, 0x7f, 0xab, 0x16, 0x03, 0xaf, 0xd7, 0x4b, 0xad, 0x56, 0xeb, 0x08, 0x34, 0xcf, 0x5c, 0x06, 0xe7, 0xc6, 0x66, 0xf9, 0xdf, 0x72, 0x19, 0x94, 0xf3, 0x06, 0x3f, 0xec, 0x0f, 0x1d, 0xc5, 0x9e, 0x75, 0x3a, 0x3d, 0xdd, 0x3d, 0xbc, 0xb3, 0xbe, 0x75, 0x30, 0xf8, 0x9a, 0x63, 0xe0, 0x50, 0x17, 0x3e, 0x9f, 0x0f, 0x00, 0x5d, 0xd7, 0xd1, 0x34, 0x0d, 0xdb, 0xb6, 0x59, 0x34, 0x4d, 0xee, 0x67, 0xde, 0x93, 0xfd, 0xb4, 0x8d, 0x9d, 0x9b, 0xfd, 0xed, 0x0d, 0xc4, 0xaf, 0x95, 0x06, 0x7c, 0x33, 0x71, 0x03, 0x80, 0xeb, 0xd7, 0xe2, 0x14, 0x0a, 0x05, 0x70, 0x1c, 0x14, 0xe7, 0x27, 0xa2, 0xe9, 0x2a, 0x57, 0x8c, 0xf5, 0x74, 0x74, 0x5d, 0x77, 0xc5, 0x0a, 0xa0, 0x69, 0x5a, 0xdb, 0xb7, 0x24, 0xc0, 0xcb, 0x85, 0x45, 0xba, 0xb6, 0xf8, 0x1b, 0xb0, 0xaa, 0xaa, 0x2e, 0x51, 0xb5, 0x5a, 0xa5, 0x58, 0x2c, 0x76, 0x34, 0x18, 0x4e, 0x8c, 0x4d, 0xb0, 0xf2, 0xc5, 0x46, 0x00, 0x52, 0x4a, 0x6c, 0xdb, 0x26, 0x1a, 0x19, 0x22, 0x1a, 0x19, 0xa2, 0x54, 0x2a, 0x51, 0x2e, 0x97, 0xf1, 0x78, 0x3c, 0x48, 0x29, 0x10, 0x02, 0x14, 0xf9, 0xe7, 0x11, 0x01, 0x10, 0xea, 0x8f, 0x5d, 0x06, 0x2e, 0xf5, 0xf9, 0x5f, 0xfc, 0x33, 0xb6, 0xe7, 0xc5, 0x7d, 0xab, 0xdb, 0xe1, 0xdf, 0xbc, 0xff, 0xaf, 0xb4, 0xdf, 0x51, 0x19, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/filesaveas16.png000066400000000000000000000011351302634723100175610ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÖ 30ŽûVêIDAT8Ë•‘?hqÇ?¿wLˆHð/^4 iA¨ZD7—â :»XŒ¡³à  ‚]¢ˆÆFp E¡'Á¡KCk¬–4(×SêÑ$žÆ4jLÎ)±—?Šo{¼ïçûÞã+Bý±q ð8pv•©Jv‰›$+Äê£ ½ÁëQØ=ÿ´¾•œæÔÈ4ÆÔ#&S#>~ÑNŸ¿VêÂäŒAïÀ„ ¾=¸†ÁÄ3ÌÌ=f–Xê¾Ê“™Ù»ټѲ,,ËrÁ¯Þæù<Ÿ¦ïDœ¡=8ŽÓÐ+«aUU r?¯'§0Þ,“›Ksôb† Û{©T*®…-˜¦ÉèZ²Ky¦RäæÒ8“ä»\iš8Žƒ¢ýÁ`³ã5â'³­«¯×K­Vë4Ï\çÆfùßr”ó?ìÅžu:=Ý=¼³¾u0øšcàP>Ÿ]×Ñ4 Û¶Y4MîgÞ“ý´›ýí į•|3q€ë×â pç'¢é*WŒõtt]wÅ  iZÛ·$ÀË…Eº¶ø°ªª.QµZ¥X,v4NŒM°òÅFRJlÛ&"¢T*Q.—ñx c #D4D4D4", ", c #D0D0D0", "' c #E3E3E3", ") c #EDEDED", "! c #F6F6F6", "~ c #EAEAEA", "{ c #DADADA", "] c #CDCDCD", "^ c #C5C5C5", "/ c #C4C4C4", "( c #B9B9B9", "_ c #ADADAD", ": c #A7A7A7", "< c #898989", "[ c #D5D5D5", "} c #E8E8E8", "| c #F1F1F1", "1 c #FAFAFA", "2 c #DDDDDD", "3 c #C8C8C8", "4 c #BDBDBD", "5 c #B1B1B1", "6 c #AAAAAA", "7 c #8A8A8A", "8 c #3C3554", "9 c #D9D9D9", "0 c #FEFEFE", "a c #EFEFEF", "b c #C6C6C6", "c c #B6B6B6", "d c #ABABAB", "e c #F7F7F7", "f c #C3C3C3", "g c #B2B2B2", "h c #8B8B8B", "i c #E2E2E2", "j c #F0F0F0", "k c #CBCBCB", "l c #BEBEBE", "m c #939393", "n c #E4E4E4", "o c #DCDCDC", "p c #9D9D9D", "q c #E1E1E1", "r c #C7C7C7", "s c #D1D1D1", "t c #D2D2D2", "u c #CECECE", "v c #D3D3D3", "w c #B4B4B4", "..................... ", ".++++@++++@++++@+++#. ", ".+$$$%$$$$%$$$$%$$$#. ", ".@%%%%%%%%%%%%%%%%%&. ", ".*=================-. ", ".*=;=;.................", ".*====.**************>.", ".*=;=;.,')!*!~{]^/(_:<.", ".*====-.[}|11)2,34567. ", ".*=;=;;8.9)!0a2,bcd7. ", ".*======-.2|e)9,fgh.. ", ".*=;=;;;;8.i=j9klm.:. ", ".*========-.njo-p.--. ", ".*|;|;;;;;;8.nq:.3|r. ", ".*||||||||||3.9.3||r. ", ".*|||||||||||.>.|||-. ", ".astut$stut$s.v.$$$w. ", "..............t...... ", " ... "}; fityk-1.3.1/wxgui/img/fityk.ico000066400000000000000000000360561302634723100164160ustar00rootroot0000000000000000 h&6  (ž& hÆ7(0` ÿÿÿÿÿÿ€ñJ€ñ©òÓò°‚ò`ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòˆòÿòÿòÿòÿòÿ‚ò­ÿÿÿÿÿÿÿÿÿÿÿÿÿ€ñH‚ó~‚ó~€ðFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ñJòÿòÿòÿòÿòÿòÿòÿókÿÿÿÿÿÿ€óò¾òÿòÿòÿòÿ‚ó¹†òÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ñ©òÿòÿòÿòÿòÿòÿòÿóÌÿÿÿÿÿÿ‚ò¯òÿòÿòÿòÿòÿòÿò¬ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÓòÿòÿòÿòÿòÿòÿòÿòøÿÿ€ó,òÿòÿòÿòÿòÿòÿòÿòÿ€ó*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿò°òÿòÿòÿòÿòÿòÿòÿòÔÿÿÿòcòÿòÿòÿòÿòÿòÿòÿòÿñ]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ò`òÿòÿòÿòÿòÿòÿòÿñ‚ÿÿÿóSòÿòÿòÿòÿòÿòÿòÿòÿ€òNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ò­òÿòÿòÿòÿòÿóÍ’ÿÿÿÿ€ôòøòÿòÿòÿòÿòÿòÿòø…ôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿókóÌòøòÔñ‚’ÿÿÿÿÿÿÿÿÿÿó{òÿòÿòÿòÿòÿòÿ‚òvÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ‚ñpòôòÿòÿòò‚ójÿÿÿÿñIó‚ó|ôCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ€ô.€ô.€ÿÿÿÿ€õòÁòÿòÿòÿòÿ‚ò·†òÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ò·òÿòÿòÿòÿòÿòÿ€ñ§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ð2òÿòÿòÿòÿòÿòÿòÿòÿ€ð"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòeòÿòÿòÿòÿòÿòÿòÿòÿóUÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚óVòÿòÿòÿòÿòÿòÿòÿòÿ€ðFÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ„öòúòÿòÿòÿòÿòÿòÿóõ‡ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóòÿòÿòÿòÿòÿòÿñoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ñnòôòÿòÿòðòcÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ‚ô/€ó,ªÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ€ð2‚ò`€ñH‡ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ïôCñI€óÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ò&‚ñZòQ€õÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƒð#òÅòÿòÿòÿòð‚ò`ÿÿÿÿÿÿÿÿÿªÿó{òøòÿòÿòý€óŽÿ ÿÿÿÿÿÿ‡ð€ó¥òÿòÿòÿòû€ò…€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’ÿòÖòÿòÿòÿòÿòÿòÿñIÿÿÿÿÿÿó{òÿòÿòÿòÿòÿòÿ€ò›ÿÿÿÿÿÿ‚ò­òÿòÿòÿòÿòÿòÿó}ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ófòÿòÿòÿòÿòÿòÿòÿòÖÿÿÿ€ïòøòÿòÿòÿòÿòÿòÿòÿ€ó*€ñ6òÿòÿòÿòÿòÿòÿòÿòù‰ë ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòžòÿòÿòÿòÿòÿòÿòÿòþˆîôCòÿòÿòÿòÿòÿòÿòÿòÿòc‚ñnòÿòÿòÿòÿòÿòÿòÿòÿ€ó>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòžòÿòÿòÿòÿòÿòÿòÿòþˆîñIòÿòÿòÿòÿòÿòÿòÿòÿói‚ñnòÿòÿòÿòÿòÿòÿòÿòÿ€ó>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ófòÿòÿòÿòÿòÿòÿòÿòÖÿÿÿ€óòýòÿòÿòÿòÿòÿòÿòÿ‚ð3€ñ6òÿòÿòÿòÿòÿòÿòÿòù‰ë ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’ÿòÖòÿòÿòÿòÿòÿòÿñIÿÿÿÿÿÿ€óòÿòÿòÿòÿòÿòÿ‚ò¯ÿÿÿÿÿÿ‚ò­òÿòÿòÿòÿòÿòÿó}ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƒð#òÅòÿòÿòÿòð‚ò`ÿÿÿÿÿÿÿÿÿŽÿ €ò›òÿòÿòÿòÿ‚ò¯€òÿÿÿÿÿÿ‡ð€ó¥òÿòÿòÿòû€ò…€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ€ð2‚ò`€ñH‡ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ó*òcói‚ð3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ò&‚ñZòQ€õÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ…ô€ó“óÌñÏ€ò™„öÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ð2òìòÿòÿòÿòÿòñ‚ò=ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿòÓòÿòÿòÿòÿòÿòÿòÞŽÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ð3òÿòÿòÿòÿòÿòÿòÿòÿôCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñ[òÿòÿòÿòÿòÿòÿòÿòÿókÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ñ7òÿòÿòÿòÿòÿòÿòÿòÿñGÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’ÿòÞòÿòÿòÿòÿòÿòÿòç‰ë ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ó?óõòÿòÿòÿòÿòø€òLÿÿÿƒð#òs€ò›‚òv€ò(ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ð"€ò£òÜò߀ñ©ƒó)ÿÿÿ‚óhòöòÿòÿòÿòùñoÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ñ5òüòÿòÿòÿòÿòÿòþ€ó@ÿÿÿÿÿÿÿÿÿ€òPòªòÓò°ñ]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿó¦òÿòÿòÿòÿòÿòÿòÿò¶ÿÿÿÿÿÿñ–òÿòÿòÿòÿòÿ‚ò­ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿò×òÿòÿòÿòÿòÿòÿòÿòçÿÿÿ€òPòÿòÿòÿòÿòÿòÿòÿ‚ñnÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÃòÿòÿòÿòÿòÿòÿòÿòÓÿÿÿòªòÿòÿòÿòÿòÿòÿòÿòÊÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ñòÿòÿòÿòÿòÿòÿòÿóÿÿÿòÓòÿòÿòÿòÿòÿòÿòÿòóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€æ òÝòÿòÿòÿòÿòÿòãˆîÿÿÿ‚ò¯òÿòÿòÿòÿòÿòÿòÿòÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ…ô€ñ©òûòÿòü‚ò±€õÿÿÿÿÿÿñ]òÿòÿòÿòÿòÿòÿòÿ‚ó|ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿ‚ó+€æ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ò­òÿòÿòÿòÿòÿò€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ñnòÊòóòЂó|€ÿÿÿÿ( @ ÌÌÌÌò$ò•ò·òqÌÌÌÌÌÌò$òÊòþòþòüòqÌÌòGò´òºò[ÌÌò>òöòÿòÿòþò¸ÌòGòôòþòþòùò[ÌÌò$òÝòþòÿòþò–Ìò•òþòÿòÿòþò©ÌÌÌòKòÝòõòÊò$ÌògòüòÿòÿòþòÌÌÌò$ò>ò$ÌÌòòµòøòúòÈò"ÌÌÌÌÌÌÌÌ ÇýòòEòNò"ò4òoòoò4ÌÌÌÌò4òØòüòüòØò4ÌÌò}òýòÿòÿòýò}ÌÌò‘òþòÿòÿòþò‘ÌÌòHòïòþòþòïòHÌÌÌÌÌ ÇýòHòžòžòHÌÌÌÌÌÌÌÌÌÌÌ Çý Çý Çý Çýòòò Çý ÇýÌòVò¥òuòÌÌÌÌÌòò,ò ò Çý Çýò.ò¼òßò¥ò ÇýòVòøòþòýò¾òÌÌÌÌòòÆòöòéòoòò,òãòþòÿòþò®òò¾òþòÿòþòøòCÌÌÌÌò¦òþòÿòÿòøòPòNòûòÿòÿòÿòéòò¾òþòÿòþòøòCÌÌÌÌòÜòþòÿòÿòþò~ò2òóòÿòÿòþòÐòòVòøòþòýò¾òÌÌÌò·òþòÿòþòùòPòòsòöòþòïòF ÇýšôòVò¥òuòÌÌò,òàòüòôòòòòBòfò= ÇýØØØÌò,òLò1òÌò#òAò/òØØØÌò#òÇòöòêòyòØØÌÌò‹òýòÿòþòóò@ØØÌÌò¬òþòÿòÿòüòdØÌÌÌÌÌòeòúòþòþòáò2òJò•òhòÌÌÌÌÌÌÌòeò³òŸò2òJòôòþòýò¯òÌÌÌÌÌÌÌÌÌÌÌÌò¯òþòÿòþòóò;òòuò¯òuòÌÌÌÌÌÌÌò¯òþòÿòþòóò<òpòýòþòüòpòÌÌòJòôòþòýò¯òòÑòþòÿòþòÒòÌÌòJò•òhòòòÍòþòÿòþòÍòÌÌÌÌÌòòcòüòþòüòcòòò^òšò^ò<‚ê(  ‚ófòÝ‚ñl€ÿóSòQÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòÝòÿòå€òPòÿòÿ€ñHÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ñlòåòs€ôDòÿòÿ€ò<ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ò;‚ò9‚òvòÁ‚ò;ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€íòüòÿ‚ò³ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿò¬òôñ]ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ñ‚ñ^„öÿÿÿôC€ôDÿÿÿƒò'ñ[‹è ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ò³òÿòÚ~óAòÿòÿòOòðòÿ€ó“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ò³òÿòÚ~ôEòÿòÿóSòðòÿ€ó“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ñ‚ñ^„öÿÿÿ€ñH€òLÿÿƒò'ñ[‹è ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñIòÙ€òÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚òµòÿòþ€íÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€òNóáñ”ðE‚ój€æ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƒð#òþòÿòy‚ófòÝ‚ñlÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ôòùòÿ‚ójòÝòÿòåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƒð!€óBÿÿ‚ñlòåòsfityk-1.3.1/wxgui/img/fityk.xpm000066400000000000000000000023271302634723100164420ustar00rootroot00000000000000/* XPM */ static const char * fityk_xpm[] = { "32 32 2 1", " c None", ". c #F28100", " . ", " ... ", " . ..... ", " .... ..... ", " ..... ... ", " ..... . ", " .. .... ", " .... . ", " ..... ", " ..... ", " ... ", " ", " .... ", " ..... ... . ", " ..... ..... .... ", " ..... ..... ..... ", " ... ..... ..... ", " ... .... ", " . ", " .. ", " .... ", " ...... ", " .... ", " .... ", " ", " .... ", " ... ..... ", " ..... ...... ", " ..... .... ", " .... .. ", " .. ", " "}; fityk-1.3.1/wxgui/img/fityk96.h000066400000000000000000000276151302634723100162530ustar00rootroot00000000000000static const unsigned char fityk96_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe2, 0x98, 0x77, 0x38, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd7, 0x04, 0x13, 0x01, 0x2a, 0x0b, 0x8d, 0xb8, 0xa7, 0x11, 0x00, 0x00, 0x07, 0x56, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x9d, 0x6d, 0x88, 0x15, 0x55, 0x18, 0xc7, 0x7f, 0xbb, 0xdc, 0x2d, 0xd7, 0xcd, 0xb1, 0x75, 0x71, 0x7b, 0x21, 0x5d, 0xca, 0x0f, 0x6b, 0x69, 0xbe, 0xd1, 0x07, 0x21, 0xb3, 0x22, 0xc4, 0x5c, 0x17, 0xb5, 0x40, 0xd0, 0xb0, 0x55, 0xe8, 0x0d, 0xbf, 0xd5, 0xb7, 0x30, 0xe1, 0x72, 0x41, 0xc3, 0x4f, 0x12, 0xe1, 0x87, 0x30, 0x05, 0xcb, 0x48, 0x51, 0x30, 0x5b, 0xd6, 0x44, 0x16, 0x29, 0x45, 0xdb, 0x20, 0x11, 0xb3, 0xdd, 0x30, 0xcc, 0x85, 0xb4, 0xb0, 0x8c, 0xd5, 0x9c, 0xdc, 0x56, 0x73, 0xb5, 0x3e, 0xcc, 0x73, 0x69, 0x18, 0x67, 0xe6, 0xce, 0x99, 0x3b, 0xf7, 0xee, 0xcc, 0x9e, 0xf3, 0x87, 0x03, 0x7a, 0xef, 0xf9, 0xdf, 0xb9, 0xf7, 0xf9, 0x9f, 0xf3, 0x9c, 0x73, 0x9e, 0xe7, 0x9c, 0xb3, 0x60, 0x60, 0x60, 0x60, 0x30, 0x62, 0xa8, 0x31, 0x26, 0x88, 0x0f, 0xbb, 0x40, 0x13, 0xb0, 0x1a, 0x58, 0x0a, 0xcc, 0x04, 0x1a, 0x80, 0x8b, 0xc0, 0x31, 0x60, 0xb7, 0x95, 0xa7, 0xd3, 0x08, 0x50, 0x19, 0xc3, 0xd7, 0x03, 0x0b, 0x80, 0x77, 0x81, 0x69, 0x01, 0xd5, 0x06, 0x81, 0x83, 0xc0, 0x7a, 0x2b, 0xcf, 0x8f, 0x46, 0x80, 0x64, 0x8d, 0xdf, 0x0e, 0x7c, 0x08, 0x8c, 0x2f, 0x51, 0x7d, 0x18, 0x38, 0x01, 0xac, 0x09, 0x12, 0xa1, 0xd6, 0x98, 0x54, 0x19, 0x93, 0x81, 0x7c, 0x04, 0xe3, 0x03, 0xe4, 0x80, 0xc7, 0x81, 0x77, 0x82, 0x2a, 0x18, 0x01, 0xd4, 0x7d, 0xfe, 0xca, 0x10, 0xb7, 0xe3, 0x87, 0x06, 0x60, 0xbe, 0x5d, 0x60, 0x49, 0x90, 0x42, 0xba, 0x1a, 0xb3, 0x15, 0x68, 0x03, 0xe6, 0x02, 0x93, 0xe4, 0xe5, 0x0b, 0xc0, 0x37, 0xc0, 0x17, 0x01, 0x2e, 0xa3, 0x51, 0x7c, 0xbf, 0x2a, 0x8a, 0xbc, 0x4e, 0xed, 0x05, 0x90, 0x56, 0xfc, 0x02, 0xf0, 0x32, 0x30, 0x15, 0x18, 0x07, 0xdc, 0x2d, 0x6f, 0xcf, 0x02, 0x9e, 0x01, 0x96, 0xd9, 0x05, 0x76, 0x02, 0x9f, 0x59, 0x79, 0x06, 0x5c, 0xf4, 0xb1, 0x8a, 0xad, 0xbf, 0x24, 0x2f, 0xa7, 0xa1, 0xf1, 0x5f, 0x05, 0xde, 0x00, 0x1e, 0x02, 0xea, 0x3c, 0x55, 0xea, 0xa5, 0x34, 0x4a, 0xaf, 0x68, 0xb2, 0x0b, 0x6c, 0x73, 0x89, 0x90, 0x8b, 0xe8, 0xfb, 0xfd, 0xec, 0x3c, 0xde, 0x8c, 0x01, 0xf0, 0x1c, 0xb0, 0x0a, 0x68, 0xf1, 0x31, 0xbe, 0x1b, 0x75, 0x52, 0x67, 0x95, 0x70, 0xdc, 0xb3, 0x9a, 0xab, 0x31, 0x9e, 0x1b, 0xc8, 0xab, 0xd5, 0xa8, 0xf5, 0xb7, 0x02, 0x8b, 0x81, 0xd6, 0x88, 0xbf, 0xbb, 0x56, 0xea, 0x2e, 0x16, 0x2e, 0xc0, 0xdf, 0x40, 0x5f, 0x8c, 0xc7, 0x07, 0xf2, 0x74, 0xea, 0x01, 0xd3, 0x81, 0x39, 0x25, 0x5a, 0xbe, 0x5f, 0x4f, 0x98, 0x23, 0x5c, 0x80, 0x2b, 0x40, 0x77, 0x8c, 0x67, 0x07, 0xf2, 0x74, 0x12, 0x60, 0xb2, 0x6b, 0xb6, 0xa3, 0x82, 0x49, 0xc2, 0x45, 0xc6, 0x82, 0x5d, 0x8a, 0xbd, 0x60, 0x10, 0x38, 0x1a, 0x14, 0x96, 0xd0, 0x49, 0x80, 0x71, 0x52, 0xca, 0xe5, 0x9d, 0x07, 0x0a, 0x11, 0xc7, 0x82, 0x61, 0xe0, 0x7b, 0x60, 0xa3, 0x59, 0x88, 0xc1, 0x3f, 0x52, 0xca, 0xe2, 0x59, 0x79, 0x86, 0x80, 0x2e, 0xa0, 0xa3, 0x44, 0x4f, 0x18, 0x04, 0xf6, 0x87, 0x85, 0x21, 0x74, 0x9b, 0x86, 0xfe, 0x2e, 0xa5, 0x25, 0x26, 0x0f, 0x8f, 0x08, 0x9d, 0x76, 0x81, 0xe3, 0x94, 0x19, 0x0d, 0xd5, 0x49, 0x80, 0x33, 0x52, 0x5a, 0x62, 0xf2, 0xee, 0x80, 0x8c, 0x09, 0x9b, 0xa5, 0xc4, 0x42, 0xe6, 0x05, 0x90, 0x18, 0xcb, 0x02, 0x59, 0x69, 0x8e, 0x17, 0xdf, 0xdc, 0x07, 0x74, 0x7b, 0x5a, 0xe0, 0x29, 0x99, 0x89, 0xcc, 0x06, 0x9a, 0x23, 0x7e, 0xfc, 0x25, 0xe1, 0x9c, 0xaa, 0xd4, 0xf7, 0xaf, 0xc9, 0xb0, 0xe1, 0x5b, 0x71, 0xa2, 0x8c, 0xf3, 0x65, 0xe5, 0x3a, 0x56, 0x1a, 0xd4, 0xb0, 0xcc, 0xbb, 0xaf, 0x00, 0x47, 0x81, 0x8d, 0x45, 0x1f, 0x2c, 0x9c, 0xb7, 0x81, 0x15, 0xc0, 0x98, 0x12, 0x8f, 0xb8, 0x0e, 0xec, 0x06, 0x36, 0x85, 0xf9, 0xf0, 0x72, 0x51, 0x9b, 0x61, 0xe3, 0xef, 0x00, 0x5e, 0x14, 0x97, 0x62, 0xb9, 0x7a, 0x73, 0x4e, 0xfe, 0xdf, 0x22, 0xef, 0xef, 0x70, 0x2d, 0xa4, 0xfa, 0x81, 0xf7, 0x80, 0xed, 0xd2, 0xba, 0xc3, 0x5a, 0xfe, 0x76, 0xa9, 0xdb, 0x5f, 0xc9, 0xdf, 0x52, 0x93, 0x51, 0x01, 0xf6, 0x02, 0xcb, 0x22, 0xba, 0xd0, 0x61, 0x60, 0xbf, 0x95, 0x67, 0xb9, 0x70, 0xeb, 0x80, 0x26, 0x60, 0x1e, 0xb0, 0x04, 0xff, 0x68, 0x68, 0xa7, 0x0c, 0xa4, 0x03, 0x56, 0x9e, 0x9b, 0x46, 0x80, 0x3b, 0x7d, 0xfe, 0xa7, 0x32, 0xe3, 0x50, 0x59, 0x0c, 0xbd, 0xe4, 0x1e, 0x13, 0x24, 0xb3, 0x35, 0x41, 0x7a, 0x4b, 0x31, 0x1a, 0x7a, 0x03, 0xb0, 0x81, 0xcb, 0x32, 0xd3, 0xa9, 0x38, 0xb2, 0x38, 0x08, 0xaf, 0x50, 0x34, 0x3e, 0x52, 0x7f, 0x05, 0xae, 0x78, 0xbc, 0x18, 0xf8, 0x57, 0x29, 0x23, 0x86, 0x2c, 0x8e, 0x01, 0xf3, 0xaa, 0xcc, 0x33, 0x02, 0x78, 0xf0, 0x40, 0x95, 0x79, 0x46, 0x00, 0x1f, 0x7f, 0x5e, 0x4d, 0x9e, 0x11, 0xc0, 0x83, 0xef, 0xaa, 0xcc, 0x33, 0x02, 0x78, 0xf0, 0x79, 0x95, 0x79, 0x46, 0x00, 0x0f, 0x3e, 0x42, 0x3d, 0x2b, 0xd5, 0x27, 0x3c, 0x23, 0x40, 0xb9, 0x90, 0x00, 0xd8, 0x3a, 0xa2, 0xe7, 0x66, 0xaf, 0x02, 0xeb, 0x3c, 0xbb, 0x1b, 0x8c, 0x00, 0x65, 0xa2, 0x1b, 0x78, 0x2d, 0x42, 0x4f, 0xe8, 0x93, 0x7a, 0xdd, 0x69, 0xfd, 0x21, 0x59, 0x0e, 0xc6, 0xd5, 0xe3, 0xa4, 0x0a, 0x57, 0x12, 0x10, 0x0d, 0xc5, 0x49, 0x1f, 0x9e, 0xaf, 0xd6, 0xaa, 0x56, 0x2b, 0x01, 0x5c, 0x42, 0x34, 0x11, 0x10, 0x0d, 0x4d, 0xab, 0xdb, 0x31, 0xd0, 0xa5, 0x07, 0x98, 0xd6, 0x39, 0x42, 0x02, 0x8c, 0x16, 0xff, 0x9c, 0x49, 0x01, 0x5c, 0x07, 0x18, 0xf2, 0x84, 0x6f, 0x64, 0xed, 0xc3, 0xd9, 0xde, 0xd1, 0x15, 0x55, 0x84, 0xb4, 0x84, 0x90, 0x93, 0x44, 0x25, 0xc2, 0xd1, 0x0b, 0x88, 0x76, 0x7a, 0x64, 0x9a, 0xd4, 0xeb, 0x80, 0xf0, 0xdd, 0x03, 0x51, 0x93, 0x28, 0x76, 0xa1, 0x3a, 0x49, 0x94, 0xd4, 0xf6, 0x00, 0xf1, 0xf9, 0x47, 0x50, 0xdb, 0xc2, 0xdd, 0x07, 0x3c, 0x1d, 0x34, 0x26, 0x88, 0xf1, 0x1f, 0x93, 0xf9, 0xfc, 0x72, 0x82, 0x13, 0xea, 0x97, 0x80, 0xbd, 0x22, 0xea, 0x0f, 0x59, 0x11, 0x21, 0xe9, 0x1e, 0xb0, 0x1a, 0xf5, 0xfd, 0xf3, 0xd3, 0x84, 0x17, 0xb4, 0xb5, 0xe3, 0x11, 0xe0, 0x4d, 0x4a, 0x27, 0xd2, 0x9b, 0x81, 0x57, 0x70, 0x92, 0x2f, 0x9b, 0x20, 0x3c, 0x91, 0x6e, 0x17, 0xb8, 0x1f, 0x98, 0x01, 0x4c, 0x11, 0xb7, 0x06, 0x70, 0x19, 0x38, 0x07, 0x9c, 0xb6, 0xf2, 0xfc, 0x96, 0x45, 0x01, 0x96, 0x96, 0xc1, 0xdb, 0x1c, 0x32, 0x9e, 0xb4, 0x51, 0x7a, 0x17, 0x03, 0x52, 0xa7, 0x0d, 0xe8, 0xb5, 0x0b, 0xfe, 0x03, 0xbc, 0x5d, 0xe0, 0x1e, 0x9c, 0x0d, 0xb7, 0xed, 0xc0, 0x93, 0x01, 0x02, 0x1c, 0xb7, 0x0b, 0x74, 0x01, 0x27, 0xad, 0x3c, 0xd7, 0xb2, 0x24, 0xc0, 0xcc, 0x84, 0x79, 0xb3, 0x64, 0x4c, 0x69, 0x56, 0xf8, 0xac, 0x66, 0xe1, 0x7c, 0x0d, 0xf4, 0xf8, 0x18, 0x7f, 0x21, 0xf0, 0xba, 0x8c, 0x23, 0x96, 0x87, 0x7b, 0x9f, 0x94, 0xe9, 0xf2, 0x9d, 0xb6, 0xda, 0x05, 0x0e, 0x55, 0x52, 0x84, 0xa4, 0x05, 0x68, 0x48, 0x98, 0x37, 0x55, 0x8a, 0x2a, 0x8a, 0xbc, 0x1e, 0xcf, 0xeb, 0x73, 0xc4, 0xf8, 0xcf, 0x12, 0xbe, 0x4d, 0xdd, 0x92, 0x3a, 0x00, 0x7f, 0xe0, 0xec, 0x2f, 0xaa, 0x08, 0x92, 0x0e, 0xc6, 0x5d, 0x4c, 0x98, 0x57, 0x6c, 0x91, 0xaa, 0xb8, 0x83, 0x27, 0x3e, 0xbf, 0x5d, 0x5a, 0x7e, 0x94, 0x33, 0x02, 0x75, 0x52, 0xb7, 0x5d, 0xb8, 0x99, 0x10, 0xe0, 0x58, 0xc2, 0xbc, 0xbb, 0xa4, 0xa8, 0xc2, 0x8f, 0x37, 0x43, 0x7c, 0xbe, 0xa5, 0xf0, 0x39, 0x96, 0x70, 0x66, 0x64, 0x45, 0x80, 0xdd, 0xa8, 0xe7, 0x5e, 0x07, 0x85, 0xe7, 0x87, 0xbf, 0xa4, 0xa8, 0xc2, 0x8f, 0x37, 0x45, 0x8a, 0x2a, 0xe2, 0xf2, 0xaa, 0x2f, 0x80, 0x6c, 0x7c, 0x3a, 0x28, 0x31, 0x9f, 0x28, 0x18, 0x06, 0x0e, 0x86, 0x6c, 0xe3, 0x3e, 0x2f, 0x0b, 0x2d, 0x55, 0x5c, 0x10, 0xae, 0x1b, 0x13, 0x5c, 0xb3, 0x1d, 0x15, 0xc4, 0xe5, 0x8d, 0x48, 0x0f, 0x00, 0x58, 0x8f, 0x73, 0x3f, 0xc2, 0x60, 0x84, 0x96, 0x7f, 0x42, 0xea, 0x07, 0xa1, 0x17, 0x38, 0x09, 0x4a, 0x8b, 0xaa, 0x9b, 0xc2, 0xe9, 0xcd, 0xc2, 0x42, 0x2c, 0x71, 0x01, 0x64, 0x27, 0xf1, 0x1a, 0x60, 0x1f, 0xf0, 0xb3, 0xc4, 0x69, 0x86, 0x5d, 0x2d, 0xde, 0x96, 0xd7, 0xf7, 0x51, 0xe2, 0xf4, 0x88, 0xbc, 0x77, 0x40, 0x16, 0x55, 0xb7, 0x23, 0x3c, 0xfe, 0xb6, 0xd4, 0x3d, 0xe0, 0xf3, 0xb9, 0x97, 0xa5, 0xa8, 0x22, 0x2e, 0x6f, 0xc4, 0x62, 0x41, 0x45, 0xc3, 0x75, 0x28, 0xec, 0xdd, 0x0f, 0xc3, 0x61, 0xe0, 0x61, 0x82, 0x0f, 0x57, 0xbb, 0x5b, 0xfe, 0x2f, 0xc0, 0x27, 0xc2, 0xf1, 0xe2, 0x9c, 0x14, 0xd5, 0x59, 0x55, 0x91, 0x97, 0x1d, 0x01, 0x3c, 0x63, 0x42, 0x67, 0x99, 0x9f, 0x31, 0x60, 0x17, 0xd8, 0x06, 0x0c, 0xe0, 0x7f, 0xbd, 0xc0, 0x0d, 0x19, 0x70, 0xcf, 0x80, 0xef, 0xf5, 0x02, 0x45, 0x9c, 0x06, 0x8e, 0xcb, 0x22, 0x2b, 0xea, 0x4c, 0xc8, 0x16, 0xce, 0xe9, 0x4a, 0xd9, 0x28, 0x53, 0x29, 0xc9, 0x98, 0x17, 0x6c, 0xb8, 0xf9, 0xf3, 0x71, 0x0e, 0x75, 0x94, 0x5a, 0x88, 0x15, 0x7b, 0xd4, 0x97, 0x38, 0x07, 0x3c, 0x8e, 0x66, 0xb2, 0x07, 0x54, 0xc8, 0xb5, 0x95, 0x73, 0x5a, 0xe5, 0x24, 0xb0, 0x55, 0xfe, 0x3d, 0x37, 0xa4, 0x27, 0xd8, 0x22, 0xea, 0x56, 0xe1, 0x60, 0x7a, 0x40, 0x72, 0xbd, 0x28, 0x52, 0x30, 0x0e, 0xaa, 0x13, 0x8c, 0xd3, 0xf6, 0xca, 0xb2, 0xb4, 0x84, 0xa3, 0x0d, 0x0c, 0xf4, 0x46, 0x6a, 0x5d, 0x90, 0x2e, 0x2e, 0xa2, 0x26, 0x85, 0x86, 0x4f, 0xd5, 0x20, 0xa9, 0x95, 0x00, 0x11, 0x32, 0x56, 0x7e, 0xd3, 0xc4, 0x43, 0x59, 0x16, 0x21, 0x6d, 0xeb, 0x80, 0xd4, 0x65, 0xac, 0x2a, 0x8d, 0xda, 0x14, 0xb5, 0xfe, 0x54, 0x66, 0xac, 0xb4, 0x11, 0x80, 0x94, 0x66, 0xac, 0x74, 0x12, 0x20, 0x95, 0x19, 0x2b, 0x9d, 0x04, 0x48, 0x65, 0xc6, 0x4a, 0x27, 0x01, 0xb4, 0x44, 0x9a, 0x04, 0x48, 0x65, 0xc6, 0x4a, 0x27, 0x01, 0xe2, 0x66, 0x9e, 0x2a, 0x9a, 0xb1, 0xd2, 0x49, 0x80, 0x62, 0xc6, 0xca, 0x56, 0x99, 0xbd, 0x52, 0xe1, 0x8c, 0x95, 0x36, 0x02, 0x48, 0x6c, 0xa7, 0x4b, 0x56, 0xb8, 0x51, 0x76, 0x41, 0xdc, 0x94, 0xba, 0x5d, 0x59, 0x8e, 0x0b, 0xa5, 0x6d, 0x25, 0x9c, 0xba, 0x8c, 0x55, 0xa5, 0x61, 0x82, 0x71, 0x46, 0x80, 0xd0, 0xd0, 0x84, 0x09, 0x47, 0x27, 0x6c, 0xd4, 0xa7, 0x70, 0xa2, 0x9d, 0xb3, 0x81, 0x89, 0xc0, 0x10, 0x70, 0x16, 0xe7, 0x58, 0x53, 0x97, 0x95, 0xe7, 0x8a, 0x6e, 0xeb, 0x80, 0x9a, 0x2a, 0x19, 0x7e, 0x32, 0xb0, 0x16, 0xe7, 0x80, 0xdd, 0x83, 0x38, 0xe7, 0x01, 0xea, 0x80, 0x5b, 0x38, 0xe7, 0x86, 0xff, 0x04, 0xbe, 0x05, 0xb6, 0x00, 0x3d, 0x56, 0x9e, 0xeb, 0x46, 0x80, 0x64, 0x8d, 0xbf, 0x09, 0x78, 0x1e, 0xb8, 0x37, 0xe4, 0x99, 0x43, 0x38, 0x9b, 0xab, 0xd6, 0x01, 0x5f, 0xe9, 0x22, 0x42, 0x2e, 0x82, 0x01, 0xcb, 0xdd, 0x5e, 0xb8, 0x56, 0x8c, 0xdf, 0x58, 0xa2, 0x5e, 0xbd, 0xf8, 0xfc, 0xb7, 0x80, 0x9f, 0xa4, 0xe8, 0xdb, 0x03, 0xe2, 0x5c, 0x0d, 0x1c, 0xe0, 0xf3, 0x3f, 0x00, 0x1e, 0x55, 0xe8, 0x6d, 0x43, 0x38, 0xd7, 0x0b, 0xef, 0xd4, 0x61, 0x4c, 0xa8, 0x0d, 0x31, 0xfe, 0x0e, 0xd4, 0xaf, 0x06, 0xf6, 0x62, 0xa1, 0xf8, 0x7c, 0x15, 0x57, 0x57, 0x1f, 0xb1, 0xc7, 0x8c, 0x5e, 0x01, 0x80, 0x0d, 0xc0, 0x13, 0x94, 0x3e, 0x74, 0xd7, 0x20, 0xf5, 0x36, 0x04, 0xbc, 0x3f, 0x9b, 0x78, 0x07, 0xf7, 0xe2, 0xf2, 0xb2, 0x2f, 0x80, 0xf8, 0xfc, 0x45, 0x0a, 0xab, 0xe4, 0x1c, 0xb0, 0x28, 0xe0, 0x4f, 0xf5, 0x4d, 0x44, 0xed, 0x8f, 0xe6, 0xb8, 0x79, 0x39, 0x5d, 0x7b, 0x40, 0x39, 0x57, 0x03, 0xfb, 0xf9, 0xf3, 0x5b, 0x31, 0xbe, 0xd7, 0x10, 0xd1, 0x0e, 0x64, 0x8c, 0x4a, 0x01, 0x92, 0xbc, 0x1a, 0xf8, 0xac, 0x0c, 0xd8, 0xaa, 0x88, 0xcb, 0x1b, 0x15, 0x02, 0x24, 0x79, 0x35, 0xf0, 0x11, 0x59, 0x64, 0xa9, 0x22, 0x2e, 0x6f, 0x54, 0x08, 0x90, 0xe4, 0xd5, 0xc0, 0x5d, 0xb2, 0xc2, 0x55, 0xb9, 0xc7, 0xa7, 0x1f, 0xd8, 0x03, 0x7a, 0xdc, 0xa8, 0xe5, 0x27, 0x40, 0x62, 0x57, 0x03, 0xcb, 0x3c, 0x7e, 0x8b, 0xac, 0x70, 0xa3, 0x8c, 0x05, 0xd7, 0x80, 0xf7, 0x81, 0x5e, 0x2b, 0xaf, 0xef, 0x18, 0x90, 0xf4, 0xd5, 0xc0, 0x3d, 0x12, 0x5e, 0x38, 0x5c, 0xa2, 0x27, 0xf4, 0xe3, 0x1c, 0x59, 0xdd, 0x25, 0x42, 0x68, 0x81, 0x1a, 0x9f, 0x69, 0x68, 0x25, 0x2e, 0x5d, 0x1a, 0x83, 0x73, 0xc2, 0xb1, 0x4d, 0x16, 0x59, 0x7e, 0xd1, 0xd0, 0x3d, 0x38, 0x67, 0x7b, 0xaf, 0x59, 0x79, 0xfe, 0xd5, 0x56, 0x00, 0xd7, 0x5a, 0xe0, 0x63, 0xa2, 0xfd, 0xed, 0xdc, 0xab, 0x40, 0x47, 0x94, 0xb8, 0x90, 0x5d, 0xa0, 0x51, 0x56, 0xb8, 0x0d, 0x32, 0xcf, 0xbf, 0xcd, 0xff, 0xd1, 0xd0, 0x01, 0x5d, 0xdc, 0x8e, 0x77, 0x11, 0xe5, 0x87, 0xe2, 0xd5, 0xc0, 0x51, 0x2f, 0xde, 0x8b, 0x74, 0x35, 0xb0, 0x8c, 0x09, 0xda, 0xc5, 0xfc, 0x95, 0x7b, 0x80, 0xb4, 0x56, 0x73, 0xf5, 0xe4, 0x48, 0x0a, 0xe0, 0x19, 0x13, 0xcc, 0xe5, 0xab, 0x06, 0x06, 0x06, 0x15, 0xc0, 0x7f, 0x7a, 0x51, 0x72, 0xc7, 0xd4, 0x52, 0xbb, 0x60, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/fityk96.png000066400000000000000000000037111302634723100165770ustar00rootroot00000000000000‰PNG  IHDR``â˜w8bKGDÿÿÿ ½§“ pHYs  šœtIME×* ¸§VIDATxÚímˆUÇ»Ü-×ͱuq{!]Êki¾Ñ!³"Ä\µ@аUè ¿Õ·0árAÃOá‡0ËHQ0[ÖD)EÛ ³Ý0Ì…´°ŒÕœÜVsµ>ÌsigæÎ™;÷îÌžó‡zïùß¹÷ùŸóœsžçœ³````0b¨1&ˆ»@°X Ì€‹À1`·•§ÓPÃ× €wiÕƒÀz+ÏF€dß|Œ/Q}8¬ ¡Ö˜T“|ãä€Çw‚*Ô}þÊ·ã‡`¾]`IBº³hæ“äå À7À.£Q|¿*мNíVüð20Ü-oÏž–ÙvŸYy\ô±Š­¿$/§¡ñ_ÞêR®x¼øW)#†,ŽóªÌ3xð@•yF^MžÀƒïªÌ3xðy•yF>B=+Õ'<#@¹Ø:¢çf¯ë<»Œe¢x-BOè“zÝiý!YÆÕ㤠W ÅIž¯ÖªV+\B4 M«Û1Ð¥˜Ö9BŒÿœI\ò„odíÃÙÞÑU„´„“D%ÂÑ ˆvzdšÔë€ðÝQ“(v¡:I”ÔöñùGPÛÂÝ<4&ˆñ“ùür‚ê—€½"êY!é°õýóÓ„´µãàMJ'Ò›Wp’/› <‘n¸˜L·p8œ¶òü–E––ÁÛ2ž´QzR§ èµ þ¼]àœ ·íÀ“· t'­<ײ$ÀÌ„y³dLiVø¬fá| ôø!ðºŒ#–‡{Ÿ”éò¶ÚUR„¤hH˜7UŠ*мÏësÄøÏ¾MÝ’:àì/ª’Æ]L˜Wl‘ª¸ƒ'>¿]Z~”3uR·]¸™àX¼»¤¨Â7C|¾¥ð9–pfdE€Ý¨ç^…燿¤¨Â7EŠ*âòª/€l|:(1Ÿ(†lã>/ -U\®\³ÄåHXs?Â`„–Bê¡8 J‹ª›ÂéÍÂB,qd'ñ`ð³Äi†]-Þ–×÷Qâôˆ¼w@U·#<þ¶Ô=àó¹—¥¨".oÄbAEÃu(ìÝÃaàa‚W»[þ/À'ÂñâœÕYU‘—t× õ6¼?›x÷âò²/€øüE «ä°(àOõMDíæ¸y9]{@9Wûùó[1¾×ÑdŒJ’¼ø¬ تˆË$y5ðYd©".oTäÕÀ]²ÂU¹Ç§Øzܨå'@bWË<~‹¬p£Œ×€÷^+¯ïôÕÀ=^8\¢'ôãYÝ%BhŸih%.]ƒs±MY~ÑÐ=8g{¯YyþÕV×Zàc¢ýíÜ«@G”¸] QV¸ 2Ï¿ÍÿÑÐ]ÜŽwå‡âÕÀQ/Þ‹t5°Œ ÚÅü•{€´VsõäH àÌå«ÀzQrÇÔR»`IEND®B`‚fityk-1.3.1/wxgui/img/function16.h000066400000000000000000000054261302634723100167360ustar00rootroot00000000000000static const unsigned char function16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd2, 0x0c, 0x04, 0x0b, 0x2f, 0x0e, 0x20, 0x41, 0x97, 0x59, 0x00, 0x00, 0x01, 0x47, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xc5, 0xd2, 0x3d, 0x4b, 0x1e, 0x51, 0x10, 0x05, 0xe0, 0x47, 0xd1, 0x44, 0xd1, 0x14, 0x12, 0xb5, 0x52, 0x4b, 0x11, 0x21, 0x85, 0x41, 0x90, 0x08, 0x5a, 0x18, 0x82, 0x8b, 0x88, 0xc5, 0x16, 0x8b, 0x85, 0xa5, 0x95, 0x60, 0x23, 0xfe, 0x07, 0x4b, 0x21, 0xb1, 0x94, 0x98, 0x22, 0x20, 0x6c, 0xb1, 0x9d, 0xb0, 0x28, 0x16, 0x06, 0x09, 0x28, 0x82, 0xfe, 0x02, 0xc1, 0xe6, 0x6d, 0xb4, 0x11, 0xc5, 0x28, 0x04, 0x4c, 0x33, 0xc2, 0x22, 0x6f, 0x88, 0x16, 0xc1, 0x69, 0x66, 0xee, 0x3d, 0xcc, 0x99, 0x33, 0x1f, 0xfc, 0x07, 0x1b, 0xc0, 0x26, 0x6a, 0xb8, 0xc3, 0xe2, 0x73, 0x09, 0x36, 0x71, 0x8f, 0x69, 0xac, 0xe0, 0xf8, 0x39, 0xc9, 0x5d, 0xb8, 0xc1, 0xd9, 0x53, 0x13, 0x1a, 0x1f, 0xbd, 0x67, 0xd0, 0x8a, 0x9f, 0xd5, 0xcf, 0x2c, 0x4d, 0xc6, 0xff, 0x46, 0xd0, 0x54, 0x89, 0x2f, 0xf0, 0x36, 0xe2, 0x59, 0x4c, 0x66, 0x69, 0x32, 0x8a, 0x1f, 0x78, 0x13, 0xc4, 0x55, 0xd2, 0x5b, 0x2c, 0x54, 0x15, 0x74, 0xe2, 0x30, 0xe2, 0x4f, 0x59, 0x9a, 0xf4, 0xe0, 0x08, 0x27, 0x68, 0xab, 0x53, 0x7c, 0x03, 0x9f, 0x1b, 0x1e, 0xa9, 0xb9, 0x42, 0x0b, 0xba, 0xb2, 0x34, 0x59, 0xc3, 0x44, 0x5e, 0x94, 0xdd, 0x59, 0x9a, 0xd4, 0x42, 0x5d, 0x07, 0xbe, 0x45, 0xab, 0xdd, 0xb8, 0xac, 0x2a, 0x18, 0x8c, 0xe4, 0x5a, 0xb4, 0x33, 0x85, 0x2f, 0x81, 0xf5, 0xc5, 0x4a, 0xf7, 0xb0, 0x9e, 0x17, 0x65, 0x4b, 0x10, 0xde, 0x57, 0x09, 0xde, 0x87, 0x3f, 0x08, 0xdf, 0x8e, 0xef, 0x90, 0x17, 0xe5, 0x6f, 0xec, 0xe3, 0x34, 0x2f, 0xca, 0xed, 0xc0, 0xe7, 0x70, 0x5d, 0x8f, 0x60, 0x37, 0x7c, 0x03, 0xce, 0x63, 0x60, 0xfd, 0xb1, 0xe2, 0x99, 0x2c, 0x4d, 0x5e, 0x05, 0xbe, 0x88, 0xad, 0xea, 0x0c, 0xf6, 0xf1, 0x01, 0xbd, 0xa8, 0x65, 0x69, 0x72, 0x83, 0xaf, 0x98, 0x8f, 0x63, 0xfa, 0x88, 0xcb, 0x98, 0xd3, 0x31, 0x46, 0xd0, 0xf9, 0xb0, 0xc6, 0x66, 0x0c, 0x61, 0x27, 0x66, 0x00, 0xcb, 0x58, 0xcd, 0x8b, 0xf2, 0x75, 0xa5, 0x48, 0x73, 0x96, 0x26, 0xbf, 0xf0, 0x0e, 0xc3, 0x79, 0x51, 0xde, 0x3e, 0x00, 0x63, 0x71, 0xbe, 0x13, 0xff, 0xba, 0xbc, 0x7a, 0x47, 0x75, 0x12, 0xb2, 0x96, 0xbc, 0x84, 0xfd, 0x01, 0x60, 0x65, 0x4f, 0x14, 0x7b, 0x9c, 0x94, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/function16.png000066400000000000000000000007121302634723100172640ustar00rootroot00000000000000‰PNG  IHDRóÿagAMA± üabKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEÒ  / A—YGIDATxÚÅÒ=KQàGÑDѵRK!…AZ‚‹ˆÅ‹…¥•`#þK!±”˜" l±°( (‚þÁæm´Å(L3Â"oˆÁifî=Ì™3üÀ&j¸Ãâs 6qi¬àø9É]¸ÁÙS½gЊŸÕÏ,MÆÿFÐT‰/ð6âYLfi2ŠxÄUÒ[,Ttâ0âOYšôà'h«S|Ÿ©¹B º²4YÃD^”ÝYšÔB]¾E«Ý¸¬*ŒäZ´3…/õÅJ÷°žeKÞW Þ‡?ߎïåoìã4/ÊíÀçp]`7|Îc`ý±â™,M^¾ˆ­ê öñ½¨eirƒ¯˜cúˆË˜Ó1FÐù°Æf a'fËXÍ‹òu¥Hs–&¿ðÃyQÞ>cq¾ÿº¼zGu²–¼„ý`eO{œ”©IEND®B`‚fityk-1.3.1/wxgui/img/goto.xpm000066400000000000000000000021031302634723100162540ustar00rootroot00000000000000/* XPM */ static const char * goto_xpm[] = { "12 14 54 1", " c None", ". c #AA5500", "+ c #CC6600", "@ c #D55500", "# c #FF7100", "$ c #F37400", "% c #CA6000", "& c #DF6800", "* c #CC5E00", "= c #EF7804", "- c #CE5C00", "; c #F69C45", "> c #EA7100", ", c #D05D00", "' c #D05E00", ") c #E5740C", "! c #F9AC60", "~ c #D15D00", "{ c #D05E00", "] c #DA6600", "^ c #D05E00", "/ c #D05E00", "( c #DA731A", "_ c #DF7A25", ": c #DF7F2D", "< c #E58F43", "[ c #D06209", "} c #CF5C00", "| c #FAB979", "1 c #ED9A4D", "2 c #CE5C00", "3 c #D0630B", "4 c #F3A459", "5 c #F4B06F", "6 c #F4BF91", "7 c #F57900", "8 c #F57A01", "9 c #F57A02", "0 c #F57C05", "a c #F57E09", "b c #F68110", "c c #F7993C", "d c #F89C42", "e c #F8A04A", "f c #F8A757", "g c #F8A859", "h c #F8CBA0", "i c #F8CCA3", "j c #F9BF87", "k c #FAB979", "l c #FABA7C", "m c #FABE84", "n c #FABE85", "o c #FAC088", " ", " 22 ", " 2h2 ", " 2oi2 ", "[22223ogi2 ", "ooooooe8fi2 ", "baaaa0779k62", "moooooe8fi2 ", "}22223ogi2 ", " 2oi2 ", " 2h2 ", " 22 ", " ", " "}; fityk-1.3.1/wxgui/img/image16.h000066400000000000000000000063251302634723100161720ustar00rootroot00000000000000static const unsigned char image16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, 0x88, 0x00, 0x00, 0x01, 0xcb, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xa5, 0x91, 0xc1, 0x4b, 0x53, 0x71, 0x1c, 0xc0, 0x3f, 0xbf, 0xbd, 0xb7, 0xf7, 0xde, 0xa0, 0xbd, 0xc7, 0xb6, 0xde, 0x34, 0x7b, 0x1b, 0x6e, 0x1d, 0x94, 0x28, 0xa8, 0x3c, 0x54, 0x04, 0x1e, 0x8c, 0xce, 0x05, 0x41, 0xa4, 0xec, 0x60, 0xf7, 0x81, 0x24, 0x66, 0xe4, 0xa1, 0xdb, 0xc4, 0x69, 0x88, 0x10, 0xfd, 0x01, 0x41, 0x07, 0x3b, 0x75, 0xa8, 0x63, 0x97, 0x28, 0x6c, 0x2c, 0x34, 0x2a, 0x41, 0x72, 0xb1, 0x9c, 0x51, 0x10, 0x2f, 0x74, 0x0b, 0x06, 0xd5, 0x1b, 0xbf, 0xd7, 0xa5, 0xa6, 0x36, 0x43, 0xb3, 0x0f, 0x7c, 0x4f, 0xbf, 0xef, 0xe7, 0xf3, 0x3d, 0xfc, 0xe0, 0x3f, 0x11, 0xb7, 0xa6, 0xf3, 0x0b, 0x8d, 0x46, 0xe3, 0xf8, 0x5e, 0x64, 0x45, 0x51, 0x5e, 0x32, 0x31, 0x99, 0xf3, 0xf7, 0xca, 0xc4, 0x64, 0xce, 0x57, 0x7f, 0xd7, 0xa6, 0x67, 0xa6, 0xfe, 0xe9, 0xfa, 0xd5, 0xa1, 0x11, 0x00, 0x9a, 0x01, 0xcf, 0xf3, 0xf8, 0xf1, 0xb1, 0xb0, 0x2b, 0xd9, 0x70, 0x4e, 0x21, 0xa5, 0x04, 0x20, 0xb0, 0xf9, 0xc1, 0xd2, 0x25, 0x96, 0x2e, 0xd1, 0x84, 0xc7, 0xb3, 0xe2, 0x12, 0xab, 0xab, 0x9f, 0xb0, 0x74, 0x89, 0x22, 0xbf, 0x61, 0xe9, 0x92, 0x90, 0xea, 0x61, 0xe9, 0x12, 0xc4, 0x86, 0xb3, 0x25, 0x60, 0x1a, 0x12, 0xd3, 0x90, 0xb4, 0x99, 0x82, 0x8b, 0x7d, 0x69, 0x6c, 0x2b, 0xc8, 0xbd, 0x47, 0xf3, 0xac, 0x57, 0x6b, 0x54, 0x6b, 0x55, 0x9e, 0x14, 0x96, 0x79, 0xff, 0xe1, 0x33, 0x66, 0x38, 0x8c, 0x10, 0x62, 0x9b, 0x80, 0x2e, 0x9b, 0x63, 0x08, 0x8f, 0x52, 0xc5, 0x65, 0x9f, 0xa1, 0x70, 0xba, 0x3b, 0x42, 0x32, 0xa6, 0xe1, 0xae, 0xd7, 0xe9, 0xeb, 0x49, 0x12, 0xb7, 0xdb, 0xfe, 0x16, 0xf0, 0x31, 0x75, 0x9f, 0x68, 0x18, 0xda, 0xcd, 0x20, 0x57, 0xce, 0x75, 0xb2, 0xb4, 0xb2, 0x86, 0xef, 0x7d, 0xe7, 0xfe, 0xe3, 0x65, 0x6e, 0x66, 0x8e, 0xd2, 0xe1, 0xa4, 0xb0, 0xed, 0x78, 0xd3, 0x51, 0x37, 0x07, 0xac, 0x90, 0xe4, 0x50, 0x6f, 0x0f, 0x91, 0xd4, 0x11, 0x90, 0x12, 0xf7, 0xed, 0x22, 0x33, 0xf5, 0x3a, 0x99, 0xf1, 0xa7, 0x3c, 0xcc, 0x9d, 0xa1, 0x3d, 0x91, 0x26, 0x7c, 0xa0, 0x93, 0x9a, 0x69, 0x6d, 0x1f, 0xd8, 0x1f, 0x87, 0x48, 0xea, 0x30, 0x42, 0xed, 0x00, 0x04, 0x76, 0x37, 0x1c, 0x4b, 0xcd, 0xe3, 0xfb, 0x3e, 0xe9, 0xa4, 0xc3, 0x8d, 0x07, 0x6b, 0xc4, 0x62, 0x8b, 0x74, 0x75, 0x79, 0xac, 0x54, 0x2a, 0xad, 0x81, 0x0b, 0xf9, 0xaf, 0x90, 0xbf, 0xd3, 0xf2, 0x6d, 0x27, 0x7b, 0xcf, 0x72, 0xfb, 0xc5, 0x41, 0xa2, 0xd1, 0x2a, 0x03, 0x99, 0xcb, 0x14, 0x0b, 0x45, 0x4a, 0xef, 0x4a, 0x28, 0x82, 0xfe, 0x2d, 0x81, 0x81, 0x4b, 0xe7, 0x5b, 0xe4, 0x40, 0x20, 0x80, 0xe3, 0x24, 0x48, 0x38, 0x09, 0xe6, 0x9e, 0xcf, 0xf1, 0xfa, 0xd5, 0x1b, 0xa4, 0xf4, 0xd1, 0xd4, 0xe0, 0xe0, 0xd0, 0xf0, 0xe8, 0x6c, 0x33, 0x70, 0xfd, 0xda, 0x58, 0x8b, 0xfc, 0x27, 0xee, 0x17, 0x97, 0x72, 0xb9, 0x4c, 0x48, 0xd7, 0x06, 0xb3, 0xd9, 0xe1, 0xbb, 0x00, 0xaa, 0x16, 0xd4, 0x16, 0xf2, 0x53, 0xe3, 0x27, 0x76, 0xb4, 0x7f, 0xa1, 0x08, 0xfa, 0xb3, 0xd9, 0xd1, 0xd9, 0xdd, 0xee, 0xef, 0xc8, 0x4f, 0x3f, 0xc9, 0xc6, 0xcb, 0xc8, 0x6c, 0x58, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/image16.png000066400000000000000000000010241302634723100165160ustar00rootroot00000000000000‰PNG  IHDRóÿasBIT|dˆËIDAT8¥‘ÁKSqÀ?¿½·÷Þ ½Ç¶Þ4{n”(¨é¤ÃkÄb‹tuy¬T*­ ù¯¿Óòm'{ÏrûÅA¢Ñ*™Ë EJïJ(‚þ-Kç[ä@ €ã$H8 æžÏñúÕ¤ôÑÔààÐðèl3pýÚX‹ü'î—r¹LH׳ÙỪÔòSã'v´¡ú³ÙÑÙÝîïÈO?ÉÆËÈlXäIEND®B`‚fityk-1.3.1/wxgui/img/info16.h000066400000000000000000000054051302634723100160410ustar00rootroot00000000000000static const unsigned char info16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5, 0x06, 0x19, 0x04, 0x1a, 0x0a, 0x7b, 0x87, 0x71, 0x90, 0x00, 0x00, 0x01, 0x55, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x63, 0x60, 0xa0, 0x01, 0x90, 0x65, 0x60, 0x60, 0xe8, 0x60, 0x60, 0x60, 0xb8, 0xcc, 0xc0, 0xc0, 0xf0, 0x0b, 0x8a, 0x2f, 0x43, 0xc5, 0x64, 0xd1, 0x15, 0x33, 0xa2, 0xf1, 0x53, 0x18, 0x18, 0x18, 0xa6, 0x95, 0xb7, 0x4d, 0x63, 0x55, 0x54, 0x51, 0x67, 0x60, 0x64, 0x62, 0x66, 0xf8, 0xfb, 0xe7, 0x2f, 0xc3, 0xeb, 0x77, 0x1f, 0x18, 0x0e, 0x1f, 0xda, 0xcf, 0xb0, 0x67, 0xc5, 0x94, 0xdf, 0x0c, 0x0c, 0x0c, 0x59, 0x0c, 0x0c, 0x0c, 0x73, 0xb0, 0x19, 0x90, 0x22, 0xa3, 0xac, 0x3d, 0xbb, 0x6b, 0xd2, 0x5c, 0x86, 0x5b, 0x8f, 0x5f, 0x33, 0x7c, 0xfd, 0xf1, 0x1b, 0xab, 0xf3, 0x16, 0x74, 0x97, 0x32, 0xbc, 0x7e, 0x7a, 0x37, 0x15, 0x66, 0x08, 0x23, 0x92, 0xb3, 0xef, 0x6e, 0xd8, 0x7b, 0x8e, 0xf5, 0xc2, 0xed, 0xa7, 0x70, 0xcd, 0x5d, 0xf9, 0x81, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x65, 0x13, 0xd7, 0xa3, 0x18, 0xd2, 0x5d, 0x10, 0xf4, 0x9b, 0x81, 0x81, 0x41, 0x99, 0x81, 0x81, 0xe1, 0x31, 0x13, 0x54, 0x2c, 0x3b, 0xb5, 0xac, 0x13, 0x45, 0x33, 0x3e, 0x60, 0xe4, 0x16, 0xc3, 0xca, 0xc0, 0xc0, 0x90, 0x8d, 0xec, 0x82, 0xcb, 0x33, 0x56, 0xed, 0xd5, 0xb9, 0xfb, 0xec, 0x23, 0xd1, 0x21, 0xdd, 0x5d, 0x10, 0x74, 0x85, 0x81, 0x81, 0x41, 0x97, 0x05, 0xca, 0x57, 0xe7, 0xe5, 0xe2, 0x64, 0x60, 0x60, 0x40, 0x18, 0x00, 0x73, 0x3e, 0x36, 0x2f, 0xc0, 0xf4, 0x30, 0x30, 0x30, 0x30, 0xc0, 0xbc, 0xc0, 0xf0, 0xf7, 0xdf, 0x5f, 0x14, 0x59, 0x1c, 0x9a, 0x30, 0x00, 0xcc, 0x80, 0x9b, 0xbf, 0x7e, 0xfd, 0x22, 0x35, 0xbd, 0xdc, 0x44, 0x36, 0x60, 0xeb, 0xc3, 0x7b, 0xb7, 0x19, 0x7e, 0x7e, 0xff, 0x4c, 0x94, 0xce, 0xab, 0xa7, 0xf6, 0x33, 0x30, 0x30, 0x30, 0x6c, 0xc5, 0x88, 0xc6, 0xf6, 0xd9, 0xeb, 0x58, 0xdf, 0x7d, 0xc5, 0x0c, 0x03, 0x74, 0x2f, 0x21, 0x47, 0x23, 0x4a, 0x42, 0x12, 0x91, 0x56, 0x9e, 0xed, 0x13, 0x9b, 0xc7, 0x20, 0x2a, 0x21, 0x8b, 0xd3, 0xf6, 0xe9, 0xcd, 0x39, 0x0c, 0x5f, 0xde, 0x3e, 0x83, 0x27, 0x24, 0x66, 0x24, 0xb9, 0x73, 0xdf, 0x3e, 0xbf, 0x7f, 0x7a, 0xe1, 0xc8, 0x0e, 0x4f, 0x01, 0x21, 0x31, 0x66, 0x31, 0x69, 0x45, 0x0c, 0x67, 0x2f, 0xec, 0x2e, 0xfe, 0xfd, 0xeb, 0xfb, 0xe7, 0x0c, 0xe4, 0xa4, 0x4c, 0x71, 0x66, 0xa2, 0x18, 0x00, 0x00, 0xe5, 0x3e, 0x80, 0xed, 0xd9, 0x14, 0xca, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/info16.png000066400000000000000000000007101302634723100163700ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIMEÕ {‡qUIDAT8Ëc` e``è```¸ÌÀÀð Š/CÅdÑ3¢ñS¦•·McUTQg`dbføûç/ÃëwÚϰgÅ”ß Y s°"£¬=»kÒ\†[_3|ýñ«ót—2¼~z7f#’³ïnØ{ŽõÂí§pÍ]ù e×£Ò]ô›A™á1T,;µ¬E3>`äÃÊÀÀì‚Ë3VíÕ¹ûì#Ñ!Ý]t…A—ÊWçåâd``@s>6/Àô0000À¼Àð÷ß_Yš0Ì€›¿~ý"5½ÜD6`ëÃ{·~~ÿL”Ϋ§ö3000lňÆöÙëXß}Å t/!G#JB‘Vží›Ç *!‹ÓöéÍ9 _Þ>ƒ'$f$¹sß>¿záÈO!1f1iE g/ì.þýëûç ä¤Lqf¢å>€íÙÊèIEND®B`‚fityk-1.3.1/wxgui/img/info32.h000066400000000000000000000124671302634723100160450ustar00rootroot00000000000000static const unsigned char info32_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20, 0x08,0x06,0x00,0x00,0x00,0x73,0x7a,0x7a,0xf4,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff, 0xa0,0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73, 0x00,0x00,0x0d,0xd7,0x00,0x00,0x0d,0xd7,0x01,0x42,0x28,0x9b, 0x78,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd8,0x03, 0x1d,0x0f,0x13,0x0e,0x5a,0x61,0xea,0xd8,0x00,0x00,0x03,0xa3, 0x49,0x44,0x41,0x54,0x58,0xc3,0xc5,0x97,0x5d,0x68,0x5c,0x45, 0x14,0xc7,0x7f,0x93,0x2c,0x5b,0x3f,0x36,0xa9,0x24,0x4d,0x13, 0xb7,0x60,0xfd,0x8a,0x82,0xc9,0x26,0xb4,0x54,0x2d,0xb4,0xa0, 0xc2,0x76,0xc1,0xf4,0x21,0x09,0xfa,0x54,0xa4,0x68,0x75,0xd1, 0x07,0x13,0x02,0x69,0xd1,0xd0,0x8a,0x14,0x85,0x56,0xac,0xd8, 0x62,0xc0,0x87,0x80,0x34,0x20,0xe2,0x83,0xa4,0x49,0x85,0x3c, 0x2c,0x0b,0xfb,0x20,0x22,0x8d,0xd5,0xba,0x6d,0x53,0x89,0x6d, 0xa4,0x49,0xc8,0x26,0xda,0x34,0xab,0x04,0x49,0xd2,0xbd,0x33, 0xc7,0x07,0xe3,0x7e,0x74,0xf7,0xee,0xde,0xbb,0x8d,0x38,0xf0, 0x7f,0xb8,0x77,0xe6,0xcc,0xf9,0xdd,0x33,0x73,0x67,0xce,0x51, 0x22,0xc2,0xff,0xd9,0x3c,0x6e,0x06,0x87,0xc2,0xd1,0x7a,0x60, 0x2f,0xb0,0x13,0xd8,0xb2,0x26,0x0f,0x90,0x00,0x66,0x81,0x38, 0x70,0x36,0x32,0x10,0xfc,0xd5,0xe9,0x9c,0xca,0x49,0x04,0x42, 0xe1,0xe8,0x5e,0xe0,0xf0,0x9a,0x63,0xe5,0x60,0xde,0x71,0xe0, 0x23,0x34,0x83,0x91,0xcf,0x82,0xa6,0x6c,0x80,0x50,0x38,0xda, 0x0c,0xf4,0x03,0xcf,0x94,0x19,0xe1,0xcb,0x40,0x77,0x64,0x20, 0x18,0x73,0x0d,0x10,0x0a,0x47,0x3b,0x80,0xcf,0x81,0x7b,0xef, 0x70,0x99,0x35,0x70,0x30,0x32,0x10,0x3c,0x59,0xa8,0xb3,0xc2, 0xc6,0x79,0x17,0x30,0xb4,0x0e,0xce,0x01,0x2a,0x81,0x8f,0x43, 0xe1,0xe8,0x27,0x8e,0x22,0x10,0x0a,0x47,0xdb,0x80,0xaf,0xed, 0xe0,0x00,0xfc,0x75,0x77,0xb1,0x6b,0x7b,0x3d,0xbe,0xbb,0x3d, 0xc4,0x27,0x92,0xfc,0xf8,0xf3,0xa2,0x53,0x98,0x9e,0xc8,0x40, 0xf0,0x94,0x2d,0x40,0x28,0x1c,0x7d,0x14,0x38,0x0f,0x6c,0xb4, 0x9b,0xe1,0xe9,0x40,0x2d,0x47,0xde,0x68,0x61,0x83,0xb7,0x32, 0xfd,0x2e,0xf2,0x6d,0x82,0x13,0xa7,0xaf,0x38,0x5d,0x8e,0x3d, 0xd9,0x7b,0x22,0xe7,0x2b,0xc5,0xe8,0x13,0x46,0x5b,0x1b,0x8d, 0xb6,0x28,0x24,0xaf,0xc7,0x70,0xe8,0x40,0x53,0x8e,0x73,0x80, 0xd0,0x2e,0x3f,0xbb,0xb7,0x6d,0xc2,0xce,0x2e,0x4b,0x95,0x46, 0x5b,0xfd,0xa1,0x43,0xd1,0xca,0x3c,0x80,0xe0,0x6b,0xa3,0xbb, 0x0d,0x56,0xbb,0x28,0x8d,0x9d,0x1e,0x7e,0xc0,0x47,0xb5,0xcf, 0x5b,0xf0,0xd3,0x76,0x04,0x6a,0x28,0x66,0x9b,0xa5,0x27,0xf4, 0xe2,0xea,0x2b,0x79,0x00,0xc6,0x58,0x7d,0x22,0x9a,0x62,0x5a, 0x59,0xb9,0x65,0x1b,0xdb,0x95,0x55,0x8b,0x52,0xf6,0x59,0x7a, 0x3b,0x07,0xe0,0xd9,0x03,0x43,0x55,0x62,0x74,0x50,0x8c,0xa6, 0x98,0x26,0xa7,0x93,0x4c,0x25,0x96,0x0a,0x02,0xc4,0xce,0xcd, 0x50,0xca,0x3e,0x4b,0x8f,0x3c,0xf7,0xea,0x48,0x6b,0x1a,0x40, 0x8c,0x6e,0x33,0xc6,0xf2,0x1a,0x63,0x51,0x4c,0x96,0xb6,0x38, 0xfa,0xe9,0x77,0xcc,0xdd,0xf8,0x2b,0xed,0xd8,0xd2,0x86,0xfe, 0x2f,0x7e,0xe2,0xe2,0xc4,0xef,0x94,0xb2,0xcf,0x96,0x98,0x54, 0x47,0xfa,0x2e,0x10,0xd1,0x4f,0x3a,0x3a,0x60,0x81,0x6b,0xd3, 0x8b,0xec,0xef,0x1b,0x25,0xd0,0x58,0x4b,0x95,0x6f,0x03,0x97, 0xaf,0x2e,0x70,0x23,0xb9,0x8c,0x53,0xfb,0xcc,0x86,0xe7,0xa9, 0x0c,0x80,0x4e,0x35,0xa0,0x2a,0x4a,0x1a,0xb5,0x3e,0x5e,0xc7, 0x8e,0xa6,0x86,0x9c,0x77,0x0f,0xf9,0xab,0x00,0xf8,0xe6,0x87, 0x19,0x7e,0x99,0xfa,0xc3,0x0d,0x83,0x3f,0x03,0x60,0x74,0x03, 0x9e,0xd2,0x97,0x52,0x73,0xe3,0x26,0x5e,0xee,0x6c,0x29,0xd8, 0x37,0xb7,0xb0,0xc4,0xc4,0xf4,0x4d,0x37,0x00,0x5b,0xd2,0x00, 0x46,0x19,0xd0,0xc6,0x81,0x8d,0xfd,0x18,0x11,0x8d,0xd1,0x56, 0x79,0xf9,0x80,0x18,0x3d,0xef,0x64,0x70,0xec,0xdc,0x24,0xd7, 0x67,0xff,0x39,0x76,0xfd,0x9b,0xab,0xe9,0x7e,0x69,0x67,0x16, 0x80,0x20,0x46,0xbb,0xf1,0x3d,0x9b,0x01,0x50,0xce,0x00,0xa6, 0xe6,0x93,0x4c,0xcd,0x27,0x01,0x78,0x6c,0x6b,0xcd,0x5a,0x7a, 0x90,0x89,0x80,0x28,0x57,0x00,0x89,0xec,0x08,0x7c,0xef,0x3a, 0x76,0x62,0xf2,0x96,0xc7,0x65,0x04,0xc6,0x32,0x00,0x56,0x6a, 0x14,0x0f,0xb7,0x00,0xaf,0x73,0xff,0xb9,0xce,0x8c,0x18,0x84, 0x94,0x1b,0x80,0xe1,0xf4,0x41,0x34,0xf6,0x55,0xcf,0x92,0x18, 0x1d,0x75,0x71,0x92,0x61,0x6e,0xdf,0x90,0x62,0xdc,0x9c,0x84, 0x93,0x63,0x5f,0xf6,0xc4,0x73,0x92,0x52,0x31,0xfa,0x18,0x15, 0xb4,0xd9,0xe1,0x6e,0xae,0xf1,0x71,0x5f,0xf5,0x3d,0xe9,0xe7, 0xad,0xf7,0xe7,0xde,0xd8,0xf5,0x75,0x55,0x34,0x3e,0x58,0x0b, 0xc0,0xf2,0x6a,0x8a,0x99,0xb9,0xa4,0x7d,0xf4,0xb4,0x1c,0x2f, 0x98,0x0f,0x6c,0x7f,0xf1,0xf8,0x30,0x98,0xf6,0x42,0x46,0x87, 0x5f,0x7f,0x9e,0x17,0xf6,0x6c,0x73,0x96,0x08,0x5e,0x4d,0xb0, 0xbf,0xef,0xb4,0x5d,0xf7,0x15,0x7d,0x73,0xb9,0x25,0x1e,0x7b, 0x4f,0x17,0xc8,0x07,0x52,0x07,0x45,0xc9,0x9f,0x82,0xe6,0x76, 0xe5,0x6f,0xba,0x22,0xfb,0x03,0xa1,0xd0,0x1c,0x82,0xd6,0x82, 0x7e,0xf3,0x5f,0xe7,0x79,0x75,0xc1,0x85,0xa1,0x77,0xae,0xb5, 0x76,0xbe,0xbb,0x4f,0x29,0x95,0x97,0x92,0x9d,0x1f,0xbf,0x8e, 0xe0,0xac,0x88,0x99,0xfd,0x2d,0x59,0xf0,0x8f,0x10,0x91,0xde, 0xf8,0x99,0xa3,0xb1,0x92,0x59,0x71,0x4b,0xe7,0x91,0x2e,0xa5, 0xd4,0x29,0x5c,0x5f,0x31,0x45,0xa2,0x22,0xd2,0x7f,0xf1,0xcc, 0xfb,0x5d,0x8e,0xd3,0xf2,0x40,0x7b,0xdf,0xba,0xa6,0xe5,0x97, 0x46,0x8e,0x9d,0x74,0x5d,0x98,0x04,0x3a,0xde,0x6a,0x16,0x91, 0x3b,0x2a,0x4c,0x54,0xa5,0xea,0xbe,0x34,0xf4,0x81,0xfb,0xc2, 0x24,0xbb,0x35,0xb5,0xf7,0x96,0x55,0x9a,0xad,0xb0,0x30,0x38, 0x39,0x32,0x58,0x7e,0x69,0x96,0x07,0xd2,0xd1,0x5b,0x2f,0x46, 0x6c,0x8b,0x53,0xa5,0x54,0x1c,0x55,0x71,0x76,0x7c,0xf8,0xc3, 0xf5,0x2d,0x4e,0xff,0xcb,0xf6,0x37,0x8c,0x06,0xd9,0xe3,0x04, 0xde,0xe3,0xc8,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae, 0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/info32.png000066400000000000000000000020431302634723100163670ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEØZaêØ£IDATXÃÅ—]h\EÇ“,[?6©$M·`ýŠ‚É&´T-´ ÂvÁô! úT¤huÑiÑЊ…V¬ØbÀ‡€4 ⃤I…<, û "ÕºmS‰m¤IÈ&Ú4«IÒ½3Çã~t÷îÞ»8ð¸wæÌùÝ3sgÎQ"ÂÿÙK<÷êHk@Œn3ÆòcQL–¶8úéwÌÝø+íØÒ†þ/~ââÄϖ˜TGú.ÑO::`kÓ‹ìï%ÐXK•o—¯.p#¹ŒSûÌ†ç© €N5 *Jµ>^ÇŽ¦†œwù«øæ‡~™úà ƒ?`tžÒ—Rsã&^îl)Ø7·°ÄÄôM7[ÒFÐÆýÑVyù€=ïdpìÜ$×gÿ9vý›«é~ig€ F»ñ=›PΦæ“LÍ'xlkÍZz‰€(W‰ì|ï:vbò–ÇeÆ2Vj·¯sÿ¹ÎŒ„”€áôA4öUÏ’uq’anßbÜœ„“c_öÄs’R1ú´Ùán®ñq_õ=éç­÷çÞØõuU4>X ÀòjŠ™¹¤}ô´/˜lñø0˜öBF‡_žöls–^M°¿ï´]÷}s¹%{OÈREÉŸ‚ævåoº"û¡Ð‚Ö‚~ó_çyuÁ…¡w®µv¾»O)•—’¿Žà¬ˆ™ý-Yð‘Þø™£±’YqKç‘.¥Ô)\_1E¢"ÒñÌû]ŽÓò@{ߺ¦å—FŽt]˜:Þj‘;*LT¥ê¾4ôûÂ$»5µ÷–Uš­°0892X~i–ÒÑ[/Fl‹S¥TUqv|øÃõ-NÿËö7ŒÙãÞãÈIEND®B`‚fityk-1.3.1/wxgui/img/lock.xpm000066400000000000000000000031371302634723100162440ustar00rootroot00000000000000/* XPM */ static const char * lock_xpm[] = { "12 14 90 1", " c None", ". c #000000", "+ c #1E1E1E", "@ c #7A7A7A", "# c #D2D2D2", "$ c #DBDBDB", "% c #BCBCBC", "& c #727272", "* c #080808", "= c #848484", "- c #BEBEBE", "; c #383838", "> c #1C1C1C", ", c #4D4D4D", "' c #B1B1B1", ") c #2D2D2D", "! c #C2C2C2", "~ c #090909", "{ c #2E2E2E", "] c #AAAAAA", "^ c #2B2B2B", "/ c #C0C0C0", "( c #161616", "_ c #C1C0C0", ": c #13110E", "< c #9B9794", "[ c #201D1C", "} c #0B0B07", "| c #040302", "1 c #050403", "2 c #2F2921", "3 c #A8A39E", "4 c #1A130B", "5 c #A59176", "6 c #E0C4A0", "7 c #DFC4A3", "8 c #DABE9A", "9 c #D6BA94", "0 c #CDA676", "a c #815A2B", "b c #E2C5A1", "c c #D8B58C", "d c #CA9F68", "e c #AC8758", "f c #A78252", "g c #A78253", "h c #A37B4B", "i c #BC8849", "j c #AC712E", "k c #E3C6A2", "l c #D5AE7E", "m c #B08D5F", "n c #D5B284", "o c #CFAB7C", "p c #CFAC7B", "q c #CBA471", "r c #BC8746", "s c #AA6F2B", "t c #E1C4A0", "u c #D0A674", "v c #C79B64", "w c #AA8455", "x c #A47E4E", "y c #A07744", "z c #BA8442", "A c #E1C29C", "B c #CEA470", "C c #AD8D64", "D c #D2B289", "E c #CDAC83", "F c #CEAD83", "G c #CCA77B", "H c #B8803E", "I c #AD7332", "J c #E0C29E", "K c #D4AC79", "L c #CDA66E", "M c #AF8D5E", "N c #AB8758", "O c #AB8858", "P c #A8814C", "Q c #B47E3E", "R c #D0A874", "S c #C6965D", "T c #BE8D50", "U c #BA894B", "V c #BD8C4E", "W c #BC8A4C", "X c #BA8647", "Y c #A47136", " .... ", " +@#$$%&* ", " =-;>>,'= ", " )!~ {]. ", " ^/. (_. ", " :<[}||1234 ", ".567788890a.", ".bcdeffghij.", ".klmnoopqrs.", ".tuvwxxxyzj.", ".ABCDEEFGHI.", ".JKLMNNOPrQ.", ".RSTTUUVWXY.", " .......... "}; fityk-1.3.1/wxgui/img/lock_open.xpm000066400000000000000000000023741302634723100172670ustar00rootroot00000000000000/* XPM */ static const char * lock_open_xpm[] = { "12 14 66 1", " c None", ". c #000000", "+ c #1E1E1E", "@ c #7A7A7A", "# c #D2D2D2", "$ c #DBDBDB", "% c #727272", "& c #080808", "* c #848484", "= c #BEBEBE", "- c #363636", "; c #1D1D1D", "> c #B1B1B1", ", c #2D2D2D", "' c #C2C2C2", ") c #090909", "! c #2E2E2E", "~ c #AAAAAA", "{ c #2B2B2B", "] c #C0C0C0", "^ c #161616", "/ c #C1C0C0", "( c #13110E", "_ c #9B9794", ": c #201D1C", "< c #0B0B07", "[ c #040302", "} c #050403", "| c #A59176", "1 c #E0C4A0", "2 c #DFC4A3", "3 c #DABE9A", "4 c #E2C5A1", "5 c #D8B58C", "6 c #CA9F68", "7 c #AC8758", "8 c #A78252", "9 c #A78253", "0 c #E3C6A2", "a c #D5AE7E", "b c #B08D5F", "c c #D5B284", "d c #CFAB7C", "e c #CFAC7B", "f c #E1C4A0", "g c #D0A674", "h c #C79B64", "i c #AA8455", "j c #A47E4E", "k c #E1C29C", "l c #CEA470", "m c #AD8D64", "n c #D2B289", "o c #CDAC83", "p c #CEAD83", "q c #E0C29E", "r c #D4AC79", "s c #CDA66E", "t c #AF8D5E", "u c #AB8758", "v c #AB8858", "w c #D0A874", "x c #C6965D", "y c #BE8D50", "z c #BA894B", "A c #BD8C4E", " .. ", " +@#$%& ", " *=-;>* ", ",') !~. ", "{]. ^/. ", " (_:<[[}", " .|122333", " .4567889", " .0abcdde", " .fghijjj", " .klmnoop", " .qrstuuv", " .wxyyzzA", " ......."}; fityk-1.3.1/wxgui/img/manual.xpm000066400000000000000000000114541302634723100165720ustar00rootroot00000000000000/* XPM */ static const char * manual_xpm[] = { "24 24 225 2", " c None", ". c #000000", "+ c #11161D", "@ c #97A8BE", "# c #7D93AC", "$ c #738AA3", "% c #6C849C", "& c #647C96", "* c #5E768F", "= c #576F88", "- c #506982", "; c #566E86", "> c #495869", ", c #111822", "' c #768BA2", ") c #8EA2B8", "! c #768DA7", "~ c #567290", "{ c #4E6A88", "] c #466280", "^ c #3D5A78", "/ c #355270", "( c #314E6B", "_ c #36526F", ": c #3C5773", "< c #33404F", "[ c #151C25", "} c #0A0D11", "| c #99ACC0", "1 c #8096AE", "2 c #5B7694", "3 c #536F8D", "4 c #4A6785", "5 c #425F7D", "6 c #3A5775", "7 c #324F6D", "8 c #3B5772", "9 c #2D445C", "0 c #232F36", "a c #5B6979", "b c #758DA6", "c c #577391", "d c #4F6B88", "e c #476381", "f c #3F5B79", "g c #365371", "h c #34506D", "i c #293F56", "j c #353C41", "k c #8097B0", "l c #5C7896", "m c #54708E", "n c #4B6886", "o c #43607E", "p c #3B5876", "q c #33506E", "r c #33506B", "s c #395571", "t c #17222C", "u c #7E8285", "v c #353738", "w c #8FA3B9", "x c #587492", "y c #506C8A", "z c #486482", "A c #405C7A", "B c #385472", "C c #324F6C", "D c #3D5974", "E c #21272E", "F c #4A4C4D", "G c #8E9092", "H c #98ABBF", "I c #7F96AF", "J c #5D7997", "K c #55718F", "L c #4D6987", "M c #44617F", "N c #3C5977", "O c #34516F", "P c #385470", "Q c #2F465D", "R c #18242D", "S c #545759", "T c #65696A", "U c #333334", "V c #657583", "W c #8DA2B9", "X c #5A7593", "Y c #516D8B", "Z c #496583", "` c #415D7B", " . c #395573", ".. c #2A425A", "+. c #232B32", "@. c #46484A", "#. c #909295", "$. c #9BACBB", "%. c #879CB4", "&. c #637E9B", "*. c #35526E", "=. c #344B62", "-. c #19242D", ";. c #64686B", ">. c #6D6F70", ",. c #30475D", "'. c #65707D", "). c #91A5BC", "!. c #718BA6", "~. c #262E33", "{. c #575859", "]. c #8B8F95", "^. c #090D11", "/. c #7E8E9F", "(. c #8A9FB6", "_. c #6C85A1", ":. c #354C63", "<. c #1A2530", "[. c #484C4E", "}. c #737576", "|. c #435B73", "1. c #757777", "2. c #BDC6D3", "3. c #AEBECC", "4. c #A7B6C6", "5. c #A3B2C2", "6. c #9EADBD", "7. c #9AAAB9", "8. c #90A0B0", "9. c #7B8FA1", "0. c #798C9F", "a. c #708499", "b. c #556679", "c. c #32353B", "d. c #5B5E61", "e. c #8E9398", "f. c #0A0E11", "g. c #020709", "h. c #B0BAC4", "i. c #2C3E51", "j. c #24364A", "k. c #2B353F", "l. c #5E6268", "m. c #77787A", "n. c #46607A", "o. c #0D0F11", "p. c #87939D", "q. c #404145", "r. c #5F6060", "s. c #747474", "t. c #969696", "u. c #B1B1B1", "v. c #AFAFB0", "w. c #C5C5C6", "x. c #CECECF", "y. c #B4BBC1", "z. c #BCC2C9", "A. c #BDC4CA", "B. c #C4CBD2", "C. c #CBD2D9", "D. c #D6DADE", "E. c #90969B", "F. c #858A8F", "G. c #141B21", "H. c #0C0E0F", "I. c #6B7B8B", "J. c #575757", "K. c #7D7E80", "L. c #E2E4E6", "M. c #E1E1E1", "N. c #DFDFE0", "O. c #F2F2F2", "P. c #FDFDFE", "Q. c #F1F3F5", "R. c #A7A8AA", "S. c #B2B5B9", "T. c #696D71", "U. c #000102", "V. c #242527", "W. c #637281", "X. c #697C8E", "Y. c #546B83", "Z. c #455D78", "`. c #D6DCE1", " + c #E7EAED", ".+ c #EDEFF1", "++ c #EDEFF2", "@+ c #E5E6E7", "#+ c #DEDEDF", "$+ c #E1E1E2", "%+ c #E1E2E3", "&+ c #727A83", "*+ c #8B8F94", "=+ c #151B21", "-+ c #04060A", ";+ c #384A5D", ">+ c #4D6278", ",+ c #54687F", "'+ c #536A82", ")+ c #576F86", "!+ c #8797A7", "~+ c #D7DDE1", "{+ c #E2E6E9", "]+ c #E9ECEE", "^+ c #F8F9FA", "/+ c #81858A", "(+ c #A5A7A8", "_+ c #9CA2A8", ":+ c #010203", "<+ c #3B4B5E", "[+ c #445669", "}+ c #54677D", "|+ c #556B80", "1+ c #566C83", "2+ c #ACB8C3", "3+ c #DCE1E5", "4+ c #E8EBED", "5+ c #9FA3A6", "6+ c #151D24", "7+ c #303E4D", "8+ c #3D4E60", "9+ c #4F5F73", "0+ c #53657B", "a+ c #4C637C", "b+ c #010305", " ", " . . . . . . . . . . . . . . ", " + @ # $ % & * = - - - - - ; > , ", " . ' ) ! ~ { ] ^ / ( ( _ _ : _ < [ ", " } | 1 2 3 4 5 6 7 ( ( ( ( 8 9 0 ", " . a | b c d e f g ( ( ( ( h 8 i j . ", " . | k l m n o p q ( ( r ( s 9 t u v ", " . a w b x y z A B ( ( ( ( C D i E F G ", " . H I J K L M N O ( ( ( ( P Q R S T U ", " . V W ! X Y Z ` .( ( ( ( ( : ..+.@.#.. ", " . $.%.&.~ { ] ^ / ( ( ( ( *.=.-.;.>.,.. ", " . '.).!.l m n o p q ( ( ( ( D i ~.{.].^.. ", " . /.(._.x y z A B ( ( ( ( ( :.<.[.}.|.. ", ". 1.2.3.4.5.6.7.8.9.0.0.0.0.a.b.c.d.e.f.. ", "g.h.i.j.j.j.j.j.j.j.j.j.j.j.j.k.l.m.n.. ", "o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.. ", "H.I.J.K.L.L.M.N.N.O.P.Q.Q.Q.R.S.T.n.U. ", "V.W.X.Y.Z.`. +.+++@+#+$+$+N.%+&+*+=+. ", " . -+;+>+,+'+)+!+~+{+]+^+^+/+(+_+:+ ", " . . . . <+[+}+|+1+2+3+4+5+6+. ", " . . . . 7+8+9+0+a+b+ ", " . . . . . ", " ", " "}; fityk-1.3.1/wxgui/img/mouse16.h000066400000000000000000000104341302634723100162340ustar00rootroot00000000000000static const unsigned char mouse16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, 0x88, 0x00, 0x00, 0x02, 0x7f, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x75, 0xd2, 0x4b, 0x48, 0x54, 0x51, 0x1c, 0xc7, 0xf1, 0xef, 0x39, 0xf7, 0xde, 0x79, 0x34, 0x9a, 0x1a, 0x69, 0xa9, 0x34, 0x23, 0x99, 0x51, 0x19, 0x44, 0x2f, 0xa2, 0x64, 0x5a, 0x85, 0x11, 0x44, 0x90, 0xa2, 0x44, 0x44, 0x08, 0x49, 0x46, 0x45, 0xb8, 0x33, 0x5a, 0x09, 0x81, 0x20, 0xb4, 0x68, 0x53, 0xe6, 0x4e, 0x82, 0x10, 0x47, 0x5a, 0x54, 0x44, 0xcb, 0xa4, 0x16, 0x51, 0x8b, 0xec, 0x41, 0x62, 0x89, 0x94, 0x8f, 0xca, 0x7c, 0x3f, 0xc6, 0xb9, 0x2f, 0xef, 0x3d, 0x2d, 0x32, 0x30, 0xbb, 0xfe, 0xd6, 0xff, 0xff, 0xe7, 0xf0, 0xff, 0x71, 0x04, 0x40, 0x5d, 0x5d, 0x5d, 0xa4, 0xa3, 0xa3, 0xc3, 0x62, 0x45, 0x6a, 0x6a, 0x6a, 0xb2, 0x90, 0xfe, 0x55, 0x84, 0x38, 0xad, 0x50, 0xef, 0x27, 0xc7, 0xa6, 0x2e, 0xf7, 0xf4, 0xf4, 0x2c, 0xb1, 0x2a, 0x12, 0xc0, 0x34, 0xe7, 0x77, 0xfd, 0xbb, 0x7c, 0xfa, 0xb0, 0x92, 0xfe, 0x73, 0x20, 0x8e, 0x27, 0xea, 0x81, 0x9c, 0x8d, 0x9b, 0x36, 0x5e, 0x5c, 0xbd, 0x0c, 0xa0, 0x03, 0xf8, 0x82, 0x72, 0xe0, 0x6d, 0x73, 0x73, 0xb3, 0xfc, 0xd4, 0xff, 0xb1, 0x1e, 0xc5, 0x25, 0xe1, 0xcb, 0x2b, 0xdd, 0xdd, 0xdd, 0xaf, 0x00, 0x6a, 0x6b, 0xab, 0xee, 0x28, 0xc1, 0x4d, 0xe0, 0x6e, 0x20, 0xa0, 0x7c, 0x4a, 0xab, 0xab, 0xab, 0x77, 0xf4, 0xf5, 0x7d, 0xbc, 0x8e, 0x20, 0x47, 0x97, 0xa1, 0xca, 0xce, 0xae, 0xce, 0xc9, 0xbf, 0x43, 0x6e, 0x38, 0xd6, 0x1f, 0x0d, 0xad, 0xdb, 0x8d, 0x52, 0x02, 0x21, 0xd4, 0x4a, 0x40, 0xfc, 0x79, 0xa1, 0xba, 0x56, 0x09, 0xce, 0x01, 0xcf, 0xba, 0xbb, 0x1e, 0xde, 0x03, 0x54, 0x7b, 0x7b, 0xbb, 0xb1, 0xb0, 0x38, 0x7f, 0x5b, 0x29, 0xef, 0x7c, 0x26, 0x9a, 0xc8, 0x9a, 0x8b, 0xee, 0x20, 0xc7, 0xec, 0x27, 0x92, 0xf9, 0x96, 0x96, 0xc8, 0xfb, 0xeb, 0xb3, 0x73, 0x1b, 0x1b, 0x1a, 0x1a, 0x5c, 0x1d, 0x20, 0x95, 0x7a, 0x98, 0x02, 0x52, 0x2b, 0xe5, 0x74, 0x66, 0xee, 0x69, 0x51, 0x51, 0xe1, 0xd1, 0x13, 0xc7, 0x4f, 0x86, 0x53, 0x6f, 0xa6, 0xa8, 0x4c, 0xe4, 0xf0, 0x61, 0x28, 0x9b, 0x9a, 0x83, 0x95, 0x59, 0x4f, 0x9e, 0x3d, 0xba, 0x30, 0x31, 0x36, 0x51, 0x06, 0x54, 0x6a, 0x41, 0xc5, 0xb4, 0xde, 0x6a, 0xa9, 0x2a, 0xc8, 0xdf, 0x74, 0xed, 0x4c, 0xed, 0xd9, 0xa8, 0xed, 0x58, 0xbc, 0x1e, 0x98, 0xe7, 0xe7, 0x9c, 0x8d, 0x69, 0xb9, 0x94, 0x17, 0xea, 0x1c, 0xd8, 0x7f, 0x48, 0xff, 0x32, 0xf0, 0x79, 0x73, 0x45, 0xf2, 0x48, 0xbf, 0x0c, 0x02, 0x62, 0xd1, 0x68, 0x5b, 0x32, 0x79, 0x34, 0x96, 0xc9, 0x2c, 0xa2, 0x49, 0x8d, 0xdd, 0x89, 0x6c, 0x86, 0x27, 0x32, 0xec, 0x2c, 0x8e, 0xe2, 0xf9, 0x3e, 0x33, 0xd3, 0x53, 0x54, 0x54, 0x24, 0x63, 0xeb, 0x22, 0x91, 0xb6, 0x40, 0xc0, 0xb4, 0xec, 0xfc, 0xe2, 0xa2, 0x62, 0x1c, 0xc7, 0x46, 0x37, 0x0c, 0x8e, 0xed, 0x29, 0x22, 0x59, 0x38, 0xce, 0x91, 0xed, 0xb9, 0x68, 0x52, 0x62, 0x5a, 0x19, 0xe2, 0x5b, 0x12, 0x58, 0xb6, 0x9d, 0xaf, 0x07, 0x01, 0x9e, 0xe7, 0x09, 0xc3, 0x08, 0x31, 0x9b, 0x9e, 0x65, 0x6c, 0xf2, 0x07, 0x00, 0xdb, 0x12, 0x05, 0x7c, 0x1f, 0x1b, 0x02, 0x20, 0x1c, 0x8e, 0x12, 0x09, 0x47, 0xf0, 0x3c, 0x5f, 0x04, 0x02, 0xcb, 0x08, 0x5b, 0xe3, 0xa5, 0x48, 0xf9, 0x7f, 0x4d, 0x4b, 0x4b, 0x4b, 0xd8, 0x8e, 0x0d, 0x2c, 0xff, 0x83, 0xa0, 0x38, 0x8e, 0xcd, 0xf8, 0xc4, 0x2f, 0x34, 0x4d, 0x47, 0x4a, 0x81, 0x52, 0x0a, 0xcf, 0xf3, 0x30, 0x4d, 0x93, 0x85, 0xf4, 0x1c, 0x25, 0x89, 0xd2, 0xb5, 0x01, 0x21, 0x84, 0xb2, 0x6c, 0x4b, 0xcc, 0xcc, 0x4e, 0x13, 0x0a, 0x85, 0xd1, 0xa4, 0x86, 0xaf, 0x7c, 0x5c, 0xc7, 0xc1, 0xb4, 0x32, 0xa4, 0x17, 0xd3, 0xb8, 0xae, 0x8b, 0x10, 0x42, 0x05, 0x03, 0x9a, 0x1c, 0x1a, 0xfc, 0x3a, 0x58, 0xa2, 0xeb, 0x1a, 0xd3, 0x33, 0x53, 0x00, 0x28, 0xe5, 0xe3, 0xba, 0x2e, 0x00, 0x79, 0x79, 0x1b, 0x18, 0x19, 0x1d, 0x46, 0x68, 0x72, 0x28, 0x18, 0xf0, 0x68, 0x7c, 0xf9, 0xf2, 0xc5, 0x83, 0x7d, 0x7b, 0xf7, 0xc5, 0xe2, 0x5b, 0xe2, 0x18, 0x86, 0x81, 0xfa, 0xa3, 0xe0, 0x38, 0x0e, 0x23, 0xa3, 0xc3, 0xf4, 0xf6, 0xbe, 0x5b, 0x14, 0x1e, 0x8d, 0x62, 0xad, 0x0e, 0x5a, 0x5b, 0x5b, 0x4e, 0x69, 0x86, 0x6c, 0xf1, 0x3c, 0xbf, 0x4c, 0x29, 0x15, 0x5a, 0x71, 0x9e, 0xa3, 0x69, 0x72, 0xc0, 0x73, 0xfd, 0x1b, 0x4d, 0x4d, 0x37, 0x1e, 0xff, 0x06, 0xd3, 0x4c, 0x0a, 0x22, 0xa3, 0x48, 0x98, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/mouse16.png000066400000000000000000000013101302634723100165620ustar00rootroot00000000000000‰PNG  IHDRóÿasBIT|dˆIDAT8uÒKHTQÇñï9÷Þy4ši©4#™QD/¢dZ…D¢DDIFE¸3Z ´hSæN‚GZTDˤQ‹ìAb‰”Ê|?ƹ/ï=-20»þÖÿÿçðÿq@]]]¤££ÃbEjjj²þU„8­Pï'Ǧ.÷ôô,±*À4çwý»|ú°’þs Ž'ꜛ6^\½  ø‚ràmss³üÔÿ±Å%áË+ÝÝݯjk«î(ÁMàn  |J«««wôõ}¼Ž G—¡ÊήÎÉ¿Cn8Ö ­ÛR!ÔJ@üy¡ºV ÎϺ»ÞT{{»±°8[)ï|&šÈš‹î Çì'’ù––Èûë³s\ •z˜R+åtfîiQQáÑÇO†So¦¨Läða(›šƒ•YOž=º016QTjAÅ´Þj©*ÈßtíLíÙ¨íX¼˜ççœi¹”êØHÿ2ðysEòH¿ bÑh[2y4–É,¢I݉l†'2ì,Žâù>3ÓSTT$cë"‘¶@À´ìüâ¢bÇF7 Ží)"Y8Αí¹hRbZâ[X¶¯žç Ã1›želòÛ| Ž Gð<_Ë[ã¥HùMKKKØŽ ,ÿƒ 8ŽÍøÄ/4MGJR Ïó0M“…ô%‰Òµ!„²lKÌÌN …Ѥ†¯|\ÇÁ´2¤Ó¸®‹Bšü:X¢ëÓ3S(åãº.yyFhr(ðh|ùòŃ}{÷Åâ[â†ú£à8#£Ãôö¾[b­Z[[Ni†lñ<¿L)Zqž£irÀsýMM7ÿÓL "£H˜)IEND®B`‚fityk-1.3.1/wxgui/img/ok24.h000066400000000000000000000115711302634723100155170ustar00rootroot00000000000000static const unsigned char ok24_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x08, 0x06, 0x00, 0x00, 0x00, 0xe0, 0x77, 0x3d, 0xf8, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x02, 0xe1, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xad, 0x95, 0x5d, 0x48, 0x53, 0x61, 0x1c, 0xc6, 0x7f, 0x3b, 0x4b, 0xd3, 0x5a, 0x59, 0x53, 0x2b, 0x31, 0x2c, 0x2a, 0x9d, 0x60, 0x5a, 0x69, 0x41, 0x59, 0x58, 0x54, 0x50, 0x17, 0x41, 0x58, 0x61, 0x05, 0x45, 0xda, 0x27, 0x04, 0x85, 0x75, 0x13, 0x42, 0x17, 0xd5, 0x85, 0x65, 0x1f, 0x44, 0xd0, 0x4d, 0x45, 0x45, 0x04, 0x7d, 0x19, 0x91, 0x5a, 0x54, 0xa0, 0xe9, 0x9c, 0x60, 0x2b, 0x4c, 0x4a, 0x99, 0x82, 0x95, 0xba, 0xe6, 0x9c, 0xda, 0xe6, 0xd7, 0x3e, 0xfc, 0xd8, 0xf6, 0x76, 0x73, 0x82, 0x21, 0xdb, 0x92, 0x3a, 0xcf, 0xdd, 0x39, 0x70, 0xfe, 0xcf, 0x73, 0xfe, 0xef, 0xf3, 0x3c, 0x2f, 0x28, 0x8f, 0x29, 0x81, 0x0f, 0x92, 0x82, 0x83, 0x55, 0x80, 0x94, 0x98, 0x9a, 0x2a, 0x02, 0x5f, 0xaa, 0x15, 0x18, 0xac, 0x03, 0xee, 0x01, 0x7b, 0x54, 0x92, 0x34, 0x34, 0x6c, 0xb7, 0x4b, 0x08, 0xe1, 0x00, 0x84, 0x52, 0x7f, 0xb0, 0xbc, 0xf8, 0x51, 0xed, 0x9a, 0xe2, 0x27, 0x6f, 0x46, 0xe6, 0xa5, 0x2c, 0x2b, 0x11, 0x7e, 0xff, 0xe2, 0x40, 0xe1, 0xff, 0x4b, 0x90, 0x9d, 0xb2, 0x7a, 0xcb, 0xf1, 0xd9, 0x33, 0x34, 0xf1, 0x7a, 0x63, 0x67, 0x5e, 0x77, 0x6b, 0x63, 0xa4, 0x3c, 0xd3, 0xa7, 0x14, 0xc1, 0xd6, 0xdc, 0x23, 0x45, 0x39, 0x23, 0xe3, 0x5e, 0xea, 0x1e, 0x9c, 0x03, 0x78, 0x0e, 0x74, 0x2b, 0x75, 0xc8, 0x19, 0xba, 0x75, 0xdb, 0x8f, 0x2d, 0x9c, 0x33, 0x93, 0xb7, 0x86, 0xcf, 0xb8, 0x1c, 0xb6, 0x66, 0xa0, 0x1e, 0x68, 0x04, 0xfc, 0x4a, 0xb8, 0xe6, 0xcd, 0x99, 0xbb, 0xd5, 0xfe, 0xeb, 0x2f, 0x3e, 0x8a, 0xe9, 0xda, 0xb9, 0x3e, 0xe0, 0x32, 0xb0, 0x42, 0x29, 0x67, 0xe6, 0x65, 0xef, 0x3f, 0xeb, 0xd5, 0x7f, 0x35, 0x8b, 0xcc, 0xdc, 0x13, 0x02, 0x68, 0x05, 0xb6, 0x01, 0xd1, 0x93, 0xf9, 0x38, 0x5a, 0x0e, 0x4b, 0x28, 0x25, 0x92, 0x46, 0x3b, 0xa7, 0xea, 0x69, 0x8d, 0x49, 0x1c, 0xbc, 0xf6, 0x5a, 0x68, 0x62, 0xe7, 0xf9, 0x81, 0x1b, 0xc0, 0x92, 0x60, 0xb6, 0x9f, 0x38, 0x44, 0xb3, 0xe1, 0x58, 0x89, 0x3d, 0x26, 0x61, 0xe1, 0x37, 0x20, 0x03, 0x88, 0x0c, 0x42, 0x70, 0x6e, 0x67, 0xd1, 0xbd, 0x8d, 0xe3, 0x3e, 0x41, 0x93, 0xb1, 0x1a, 0xa7, 0xdd, 0xd6, 0x05, 0x18, 0x80, 0xde, 0x40, 0xf7, 0x84, 0x42, 0x5c, 0x82, 0x2e, 0xcb, 0xd2, 0x62, 0xfe, 0x25, 0x16, 0x64, 0x6e, 0x72, 0x03, 0xfb, 0x00, 0x8d, 0x9c, 0x52, 0x80, 0xf4, 0x84, 0x94, 0x8c, 0xda, 0x87, 0x95, 0xcd, 0x62, 0xef, 0xc5, 0x72, 0x11, 0x9b, 0x94, 0x2a, 0x80, 0xa7, 0xc0, 0xd2, 0x89, 0x15, 0x11, 0x0a, 0x6a, 0xe0, 0xe0, 0x9e, 0xe2, 0x32, 0x51, 0x5e, 0xdf, 0x26, 0x92, 0xd7, 0x6e, 0xf7, 0x46, 0x46, 0x45, 0x15, 0x02, 0x31, 0x80, 0x34, 0x2d, 0x46, 0xfb, 0xf2, 0x4a, 0xa9, 0x51, 0x9c, 0xbe, 0x55, 0x25, 0xd6, 0xe5, 0x9f, 0x17, 0x2a, 0x49, 0xe5, 0x02, 0x8e, 0x02, 0x71, 0x01, 0x22, 0xc2, 0xae, 0xc8, 0x07, 0x3c, 0x29, 0x2b, 0x29, 0xf8, 0xf4, 0xa1, 0xd5, 0x4a, 0x6e, 0x41, 0xa1, 0x3a, 0x31, 0x7d, 0xfd, 0xd5, 0x29, 0x53, 0xa7, 0x1e, 0x02, 0x2e, 0xeb, 0x36, 0xec, 0xde, 0xa6, 0x9b, 0xaf, 0xc5, 0xdc, 0x3b, 0x44, 0x47, 0x43, 0x25, 0xc2, 0x2f, 0x3e, 0x03, 0x26, 0x60, 0xf8, 0x4f, 0x35, 0x04, 0x53, 0x3c, 0x11, 0x5e, 0xef, 0xa8, 0xa7, 0xd6, 0xd2, 0xd5, 0x75, 0x74, 0xe9, 0xaa, 0x1c, 0xf5, 0xdc, 0xe4, 0x2c, 0xa9, 0xcf, 0x6a, 0xde, 0x3c, 0xd4, 0x6b, 0x4e, 0xb9, 0x79, 0xe7, 0xa1, 0xe6, 0x95, 0xf1, 0x3b, 0xdd, 0x9d, 0x6d, 0xb4, 0x54, 0x3f, 0xf6, 0xfb, 0xc6, 0xc7, 0xee, 0x03, 0x35, 0xc0, 0x40, 0x28, 0x82, 0x60, 0x4e, 0x11, 0x40, 0x7b, 0x47, 0xe3, 0xfb, 0x67, 0x5f, 0x4c, 0x6d, 0xa8, 0x25, 0x15, 0x07, 0x4e, 0x5d, 0x50, 0xbf, 0xfb, 0xf4, 0x3d, 0xbe, 0xbd, 0x67, 0x90, 0xbe, 0xfe, 0x61, 0x2c, 0x4d, 0x75, 0x8c, 0xb9, 0x9d, 0x3f, 0xe4, 0x50, 0xf5, 0x87, 0x0b, 0x56, 0xa8, 0x36, 0xf5, 0x21, 0x44, 0x8d, 0xfd, 0x67, 0x4b, 0xfe, 0xa2, 0x95, 0x5b, 0x34, 0xbd, 0x03, 0x2e, 0x1a, 0xda, 0x7a, 0x68, 0xb7, 0x3a, 0x70, 0xda, 0xad, 0xb4, 0xea, 0x4b, 0x19, 0x73, 0x0f, 0x57, 0x00, 0x15, 0x80, 0x2d, 0x94, 0xfa, 0xbf, 0xd5, 0xb5, 0x77, 0x64, 0xc8, 0x61, 0x76, 0xbb, 0x5c, 0xbb, 0xb4, 0x0b, 0xd2, 0x18, 0x1b, 0x71, 0xe3, 0x1d, 0x75, 0x63, 0xf9, 0x6a, 0xc0, 0x6a, 0xaa, 0x1f, 0x00, 0x6e, 0x03, 0x0d, 0x80, 0x27, 0x9c, 0x6b, 0xc2, 0xc5, 0xda, 0x0b, 0x54, 0x74, 0x36, 0x56, 0x7e, 0x18, 0xb4, 0xb5, 0x33, 0x3e, 0xea, 0xc1, 0xe9, 0xb0, 0xf1, 0xb3, 0xc9, 0x00, 0xa0, 0x07, 0x9a, 0x00, 0x67, 0x38, 0xf5, 0x93, 0x81, 0x04, 0x24, 0x4d, 0x9b, 0x15, 0xd7, 0x95, 0xb5, 0xe3, 0xa4, 0x48, 0x4c, 0xcb, 0x16, 0xf2, 0xce, 0x0f, 0x03, 0xf1, 0xa1, 0xac, 0xf9, 0x2f, 0x77, 0x6c, 0x7a, 0x44, 0x54, 0xb4, 0x09, 0x15, 0x1e, 0xe0, 0x92, 0x1c, 0xac, 0xc8, 0xc9, 0xde, 0xa3, 0x93, 0x41, 0x04, 0x10, 0x2b, 0xab, 0x76, 0xca, 0x07, 0xeb, 0x51, 0x92, 0xe0, 0xcf, 0xba, 0x54, 0xf2, 0xce, 0x15, 0xe9, 0x7b, 0x45, 0xf0, 0x1b, 0xe6, 0x8e, 0x1e, 0x4c, 0x31, 0xca, 0xec, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/ok24.png000066400000000000000000000014541302634723100160530ustar00rootroot00000000000000‰PNG  IHDRàw=øbKGDÿÿÿ ½§“áIDATxÚ­•]HSaÆ;KÓZYS+1,*`ZiAYXTPAXaEÚ'…uBÕ…eDÐMEE}‘ZT éœ`+LJ™‚•ºæœÚæ×>üØövs‚!Û’:ÏÝ9pþÏsþïóŠéÚ¹>à2°B)gæeï?ëÕ5‹ÌÜh¶Ñ“ù8ZK(%’F;§êiI¼öZhbçùÀ’`¶Ÿ8D³áX‰=&aá7 ˆ Bpngѽã>A“±§ÝÖ€Þ@÷„B\‚.ËÒbþ%dnrûœR€ô„”ŒÚ‡•ÍbïÅr›”*€§ÀÒ‰ jààžâ2Q^ß&’×n÷FFE1€4-FûòJ©Qœ¾U%ÖåŸ*IåŽq"®È<)+)øô¡ÕJnA¡:1}ýÕ)S§.ë6ìÞ¦›¯ÅÜ;DGC%Â/>&`øO5S<^﨧ÖÒÕutéªõÜä,©ÏjÞ<ÔkN¹yç¡æ•ñ;Ým´T?öûÆÇî5À@(‚`N@{Gãûg_Lm¨%N]P¿ûô=¾½g¾þa,MuŒ¹?äPõ‡ V¨6õ!DýgKþ¢•[4½.Úzh·:pÚ­´êKsW€-”ú¿ÕµwdÈav»\»´ ÒqãucùjÀjªn €'œkÂÅÚ Tt6V~´µ3>êÁé°ñ³É šg8õ“$M›וµã¤HLËòÎñ¡¬ù/wlzDT´ à’¬ÈÉÞ£“A+«vÊëQ’àϺTòÎé{EðæŽL1ÊìÕIEND®B`‚fityk-1.3.1/wxgui/img/open_data.xpm000066400000000000000000000101571302634723100172460ustar00rootroot00000000000000/* XPM */ static const char * open_data_xpm[] = { "24 24 181 2", " c None", ". c #127704", "+ c #000000", "@ c #117104", "# c #010100", "$ c #B5B8A5", "% c #E4E7D2", "& c #DAE1C8", "* c #19680C", "= c #0B0B0B", "- c #E2E5CF", "; c #CFD4AF", "> c #C5CFA6", ", c #52963E", "' c #348423", ") c #224A17", "! c #23241D", "~ c #9D9F90", "{ c #C6CAA6", "] c #C4C9A5", "^ c #C6CBA7", "/ c #97B57C", "( c #398927", "_ c #555847", ": c #1A1B15", "< c #117603", "[ c #20201A", "} c #D4D6C2", "| c #BEC2A0", "1 c #B3B896", "2 c #B0B595", "3 c #B3B797", "4 c #7EA466", "5 c #4F913B", "6 c #81856C", "7 c #3E3F32", "8 c #010101", "9 c #0B4C02", "0 c #072F01", "a c #127604", "b c #DADDC8", "c c #AFB494", "d c #AAAF8F", "e c #A3A789", "f c #A6AA8B", "g c #5B9247", "h c #6B9656", "i c #A4A88A", "j c #A1A588", "k c #AAAD96", "l c #B3B5A5", "m c #B8BBAA", "n c #BABCAB", "o c #C1C3B2", "p c #C7CAB7", "q c #4E903F", "r c #0C0C09", "s c #DDDFCB", "t c #969B7E", "u c #9DA286", "v c #95987C", "w c #96997E", "x c #378126", "y c #618B4D", "z c #9DA184", "A c #A5AA8B", "B c #A4A98A", "C c #A3A889", "D c #A2A588", "E c #A2A587", "F c #9FA386", "G c #648E50", "H c #0E5D03", "I c #D8DBC9", "J c #84866E", "K c #7D8169", "L c #151612", "M c #D7DAC9", "N c #797D67", "O c #3D3F34", "P c #E0E0D9", "Q c #EBEDDD", "R c #E8EBD9", "S c #E7EAD8", "T c #E3E6D4", "U c #DEE1D0", "V c #DADCCC", "W c #DADCD1", "X c #2B2C28", "Y c #88B278", "Z c #6F735E", "` c #0D0D0D", " . c #F4F4EC", ".. c #CED3AE", "+. c #CACFAB", "@. c #C6CBA8", "#. c #C2C6A4", "$. c #BBC09E", "%. c #ABB091", "&. c #23251E", "*. c #599A49", "=. c #494B3D", "-. c #DCDCD4", ";. c #EAECDD", ">. c #CDD2AD", ",. c #CCD1AC", "'. c #CACFAA", "). c #BABF9D", "!. c #B5B999", "~. c #81836C", "{. c #070806", "]. c #161616", "^. c #F2F2EA", "/. c #C9CEAA", "(. c #C7CCA8", "_. c #C8CDA9", ":. c #C4C9A6", "<. c #C1C5A3", "[. c #BCC09F", "}. c #B6BB9A", "|. c #B0B494", "1. c #9DA185", "2. c #535445", "3. c #749E65", "4. c #747470", "5. c #ECECE2", "6. c #C3C8A5", "7. c #C2C7A4", "8. c #C0C5A2", "9. c #BFC4A1", "0. c #BDC2A0", "a. c #B9BD9C", "b. c #B9BE9D", "c. c #A9AD8F", "d. c #A3A78A", "e. c #80836D", "f. c #020201", "g. c #A6A998", "h. c #B8BC9B", "i. c #AFB394", "j. c #ACB091", "k. c #A8AC8E", "l. c #A6AA8C", "m. c #9FA286", "n. c #9B9F83", "o. c #9A9D82", "p. c #8A8D75", "q. c #4F5243", "r. c #070705", "s. c #9E9F91", "t. c #E5E6DA", "u. c #ADB192", "v. c #A5A98C", "w. c #9FA387", "x. c #999D81", "y. c #95987E", "z. c #92957B", "A. c #8C8F76", "B. c #8A8D74", "C. c #71735F", "D. c #080908", "E. c #E3E5D9", "F. c #C0C3AF", "G. c #94987C", "H. c #8F9379", "I. c #8B8F75", "J. c #8A8E74", "K. c #888C73", "L. c #858970", "M. c #868971", "N. c #82866E", "O. c #80836C", "P. c #7D8069", "Q. c #797C66", "R. c #727560", "S. c #717460", "T. c #71745F", "U. c #6A6D59", "V. c #434538", "W. c #080907", "X. c #050504", " ", " ", " . . ", " . . . . ", " . . . . . . ", " . . . . ", " + + + + + + . @ . . ", " # $ % % % % & . * . . . ", " = - ; ; ; > , ' ) . . . . ", "! ~ - { ] ^ / . ( _ : . < . . . ", "[ } | 1 2 3 4 . 5 6 7 8 + + + + 9 . 0 a . . ", "! b c d e f g . h i j k l m n o p . q 9 . . ", "r s t u v w x . y z A B C D e E F G . H . ", "+ I J K L + + + + + + + + + + + + + + + 8 8 ", "+ M N O P Q R R R R R R R R R R R S T U V W X ", "+ Y Z ` .; ; ; ; ; ; ; ; ; ......+.@.#.$.%.&. ", "9 *.=.-.;.>.....>...>.>.>.>.>.,.'.@.#.).!.~.{. ", ". . ].^.+.'.+.'./.'./.(._._.@.:.<.[.}.|.1.2.r ", "9 3.4.5.6.7.7.#.8.#.9.0.8.0.a.b.3 2 c.d.e.f. ", "+ g.-.h.h.!.3 3 2 2 i.i.i.j.k.l.m.n.o.p.q.r. ", "+ s.t.u.c.l.v.d.d.j w.m.n.x.y.z.A.B.B.C.D. ", "+ E.F.G.H.I.J.K.K.L.M.N.O.P.Q.R.S.T.U.V.W. ", " + + + + + + + + + + + + + + + + + + X. ", " "}; fityk-1.3.1/wxgui/img/open_data_custom.xpm000066400000000000000000000072261302634723100206430ustar00rootroot00000000000000/* XPM */ static const char * open_data_custom_xpm[] = { "24 24 151 2", " c None", ". c #127704", "+ c #000000", "@ c #117104", "# c #010100", "$ c #B5B8A5", "% c #E4E7D2", "& c #DAE1C8", "* c #19680C", "= c #0B0B0B", "- c #E2E5CF", "; c #CFD4AF", "> c #C5CFA6", ", c #52963E", "' c #348423", ") c #224A17", "! c #23241D", "~ c #9D9F90", "{ c #C6CAA6", "] c #C4C9A5", "^ c #C6CBA7", "/ c #97B57C", "( c #398927", "_ c #555847", ": c #1A1B15", "< c #117603", "[ c #606060", "} c #20201A", "| c #D4D6C2", "1 c #BEC2A0", "2 c #B3B896", "3 c #B0B595", "4 c #B3B797", "5 c #7EA466", "6 c #4F913B", "7 c #81856C", "8 c #3E3F32", "9 c #010101", "0 c #FFFFFF", "a c #072F01", "b c #EFEFEF", "c c #DADDC8", "d c #AFB494", "e c #AAAF8F", "f c #A3A789", "g c #A6AA8B", "h c #5B9247", "i c #6B9656", "j c #A4A88A", "k c #A1A588", "l c #AAAD96", "m c #B3B5A5", "n c #B8BBAA", "o c #0C0C09", "p c #DDDFCB", "q c #969B7E", "r c #9DA286", "s c #95987C", "t c #96997E", "u c #378126", "v c #618B4D", "w c #9DA184", "x c #A5AA8B", "y c #A4A98A", "z c #A3A889", "A c #A2A588", "B c #C3C3C3", "C c #D8DBC9", "D c #84866E", "E c #7D8169", "F c #151612", "G c #878787", "H c #D7DAC9", "I c #797D67", "J c #3D3F34", "K c #E0E0D9", "L c #EBEDDD", "M c #E8EBD9", "N c #DADCCC", "O c #DADCD1", "P c #2B2C28", "Q c #88B278", "R c #6F735E", "S c #0D0D0D", "T c #F4F4EC", "U c #CED3AE", "V c #BBC09E", "W c #ABB091", "X c #23251E", "Y c #0B4C02", "Z c #599A49", "` c #494B3D", " . c #DCDCD4", ".. c #EAECDD", "+. c #CDD2AD", "@. c #CCD1AC", "#. c #B5B999", "$. c #81836C", "%. c #070806", "&. c #161616", "*. c #F2F2EA", "=. c #CACFAB", "-. c #CACFAA", ";. c #C9CEAA", ">. c #C7CCA8", ",. c #C8CDA9", "'. c #C6CBA8", "). c #C4C9A6", "!. c #9DA185", "~. c #535445", "{. c #749E65", "]. c #747470", "^. c #ECECE2", "/. c #C3C8A5", "(. c #C2C7A4", "_. c #C2C6A4", ":. c #C0C5A2", "<. c #BFC4A1", "[. c #BDC2A0", "}. c #B9BD9C", "|. c #B6B6B6", "1. c #A6A998", "2. c #B8BC9B", "3. c #AFB394", "4. c #ACB091", "5. c #9E9F91", "6. c #E5E6DA", "7. c #ADB192", "8. c #A9AD8F", "9. c #A6AA8C", "0. c #A5A98C", "a. c #A3A78A", "b. c #9FA387", "c. c #9FA286", "d. c #9B9F83", "e. c #999D81", "f. c #E3E5D9", "g. c #C0C3AF", "h. c #94987C", "i. c #8F9379", "j. c #8B8F75", "k. c #8A8E74", "l. c #888C73", "m. c #858970", "n. c #868971", "o. c #82866E", "p. c #80836C", "q. c #7D8069", "r. c #71745F", "s. c #6A6D59", "t. c #575550", " ", " ", " . . ", " . . . . ", " . . . . . . ", " . . . . ", " + + + + + + . @ . . ", " # $ % % % % & . * . . . ", " = - ; ; ; > , ' ) . . . . ", "! ~ - { ] ^ / . ( _ : + + < + + [ . . ", "} | 1 2 3 4 5 . 6 7 8 9 + + + 0 + . a + b + . ", "! c d e f g h . i j k l m n + 0 + + + + b + ", "o p q r s t u . v w x y z A + 0 b b b b B + ", "+ C D E F + + + + + + + + + + + 0 b b B + G ", "+ H I J K L M M M M M M M M M M + 0 B + N O P ", "+ Q R S T ; ; ; ; ; ; ; ; ; U U + 0 b + V W X ", "Y Z ` ...+.U U +.U +.+.+.+.+.@.+ 0 B + #.$.%. ", ". . &.*.=.-.=.-.;.-.;.>.,.,.'.).+ 0 b + !.~.o ", "Y {.].^./.(.(._.:._.<.[.:.[.}.+ 0 b B B + |. ", "+ 1. .2.2.#.4 4 3 3 3.3.3.4.+ 0 b b b b B + ", "+ 5.6.7.8.9.0.a.a.k b.c.d.e.+ 0 + + + + b + ", "+ f.g.h.i.j.k.l.l.m.n.o.p.q.+ 0 + r.s.+ b + ", " + + + + + + + + + + + + + + + + + + + + t. ", " "}; fityk-1.3.1/wxgui/img/peak32.h000066400000000000000000000146441302634723100160310ustar00rootroot00000000000000static const unsigned char peak32_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20, 0x08,0x06,0x00,0x00,0x00,0x73,0x7a,0x7a,0xf4,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff, 0xa0,0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73, 0x00,0x00,0x0e,0xc4,0x00,0x00,0x0e,0xc4,0x01,0x95,0x2b,0x0e, 0x1b,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd8,0x04, 0x09,0x0b,0x1e,0x29,0x20,0x97,0x95,0xfa,0x00,0x00,0x00,0x19, 0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x00, 0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68, 0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0x0e,0x17,0x00,0x00,0x04, 0x5d,0x49,0x44,0x41,0x54,0x58,0xc3,0xb5,0x97,0xbf,0x6f,0x53, 0x57,0x14,0xc7,0x3f,0xe7,0xde,0xf7,0xcb,0xcf,0xb1,0x43,0x42, 0x48,0x62,0x04,0x92,0x51,0x81,0xd2,0x2e,0x58,0x0e,0xb4,0x15, 0x42,0xd4,0xaa,0xaa,0x52,0x4b,0x15,0xa2,0x2c,0x54,0xed,0xe2, 0xc9,0x4c,0xa8,0x42,0x9d,0xba,0xb5,0x13,0x6b,0x3b,0x21,0xde, 0xc4,0xd2,0x2e,0xfc,0x01,0x91,0x8a,0x44,0xa3,0xaa,0x62,0xa8, 0x64,0x9a,0x0c,0x9d,0xc8,0x00,0x2a,0x24,0x98,0x1f,0x26,0x84, 0x24,0x8a,0xe3,0xf8,0xbd,0x0e,0x39,0x56,0xdd,0x54,0x80,0x63, 0xe1,0x2b,0x3d,0xe9,0xea,0xdc,0xef,0x39,0xf7,0xfc,0xba,0xdf, 0x7b,0x9f,0xd0,0xc7,0x28,0x96,0x2b,0x79,0xa0,0x04,0x8c,0xa9, 0xe8,0x09,0x30,0x73,0x7b,0xfa,0xda,0xdd,0x9d,0xda,0x72,0xe8, 0x6f,0x94,0x44,0xb8,0x6c,0x60,0x37,0x82,0x43,0xc2,0xb3,0x76, 0xc2,0x37,0xc0,0xb5,0x9d,0x1a,0xb2,0x7d,0x44,0x5f,0x02,0x2e, 0x03,0xfb,0x8c,0xe0,0x02,0x12,0x27,0xf8,0xc0,0x3b,0xb9,0x43, 0x85,0xbf,0x16,0xe7,0x67,0x77,0x94,0x05,0xd3,0x47,0xf4,0x1f, 0x02,0x47,0x00,0x27,0xf4,0x24,0x4e,0x7b,0x42,0xb2,0x65,0xe7, 0x88,0xae,0x31,0x30,0x07,0x8a,0xe5,0x4a,0x0e,0x38,0x06,0x6c, 0xfa,0x0e,0x71,0x2e,0x6b,0x65,0x32,0x6b,0xf1,0x1d,0x62,0x60, 0x13,0x38,0xa6,0x98,0x81,0xf5,0x40,0x0e,0xf8,0x0c,0xc0,0x88, 0xb4,0xb3,0x81,0x59,0x07,0xda,0x46,0x24,0x84,0xc4,0xd1,0xb5, 0x1c,0xb0,0x38,0xa8,0x12,0x7c,0x0c,0xac,0x09,0xb4,0x46,0x52, 0x66,0x1d,0xb8,0x0f,0xdc,0x19,0x49,0x99,0x75,0x81,0x16,0xb0, 0xa6,0x98,0x81,0xf5,0xc0,0x69,0x20,0x74,0x0c,0xf5,0xe1,0x40, 0x5a,0xc0,0x02,0xb0,0x30,0x1c,0x48,0xcb,0x1a,0x9e,0x01,0x21, 0x70,0x6a,0x90,0x0e,0x64,0x00,0x12,0x48,0xb9,0x8e,0xa4,0x54, 0xdf,0x73,0x1d,0x49,0x59,0xa1,0xa5,0x98,0x3d,0x03,0x71,0x40, 0xc9,0xa7,0x01,0x90,0x72,0xa5,0xe1,0x59,0xf1,0x81,0x3f,0x81, 0x7b,0x9e,0x15,0xdf,0x73,0x64,0x55,0xa1,0xcf,0x14,0xfb,0xc6, 0x33,0x50,0x02,0xde,0x05,0xea,0x43,0xbe,0x58,0x60,0x03,0x58, 0x65,0xab,0xf6,0x1b,0x43,0xbe,0x38,0x40,0x5d,0x31,0xa5,0x41, 0x39,0x30,0x21,0x90,0xf2,0xac,0xe4,0xf4,0x04,0x6d,0xaa,0x23, 0x8e,0x67,0x25,0x27,0x90,0x02,0x26,0x06,0xe5,0xc0,0x5e,0xc0, 0x73,0x2d,0x8f,0xb2,0x81,0x69,0x01,0x4d,0x60,0x54,0x8f,0x5c, 0x33,0x1b,0x98,0x96,0xb3,0xd5,0x88,0x1e,0x70,0xf0,0x8d,0x3a, 0xa0,0x35,0x75,0xf5,0xfc,0x3f,0xf5,0x1d,0x69,0x68,0xba,0x6b, 0xc0,0x23,0xa0,0xee,0x3b,0xd2,0x70,0xac,0xfc,0xad,0x2a,0x2b, 0xbd,0xf6,0x81,0xd9,0x41,0xfa,0xdf,0x02,0x16,0x32,0x81,0x34, 0x81,0x3c,0x30,0x07,0xcc,0xe8,0x37,0x07,0xe4,0x87,0x7c,0x89, 0xf5,0x68,0xf6,0xdc,0x07,0xa6,0xc7,0xe8,0x4f,0xb2,0x55,0xdf, 0xd8,0x0a,0x2b,0xba,0xd4,0x8a,0xa2,0xe8,0x6e,0x14,0x45,0x77, 0x3b,0x8c,0xea,0x18,0x9a,0x40,0xac,0xd8,0x93,0xbd,0x64,0xc1, 0xf4,0x18,0xfd,0x69,0x00,0x81,0x9b,0xa3,0xa1,0x59,0x53,0xf9, 0xc3,0x2e,0xcc,0x03,0x80,0x91,0x94,0x79,0x2e,0x70,0xb3,0x8b, 0xb4,0x4a,0x6f,0xc2,0x81,0xbc,0x32,0x5c,0x1c,0xb8,0x32,0x1f, 0x7a,0xe6,0x00,0xb0,0x02,0xf8,0x5d,0x18,0x01,0x56,0x42,0xcf, 0x1c,0x08,0x5c,0x99,0xd7,0x2c,0x84,0xaa,0xdb,0xbf,0x03,0xc5, 0x72,0xc5,0x02,0x05,0x60,0x08,0x68,0xa6,0x5c,0x59,0xd0,0x8d, 0x4d,0xa7,0x29,0x75,0xb8,0x2a,0xf3,0x15,0xd3,0x54,0x9d,0x82, 0xda,0xe8,0x3b,0x03,0x39,0xe0,0xa8,0x6e,0x60,0x77,0xa5,0x24, 0x04,0x02,0x65,0xc4,0xb9,0x2e,0xdc,0x9c,0xca,0x02,0xc5,0x58, 0xd5,0x39,0xaa,0x36,0xfa,0x76,0xe0,0x02,0xb0,0x5f,0xe7,0xf5, 0x8c,0x6f,0xf2,0xca,0x07,0x23,0xdb,0x5e,0x53,0x56,0x65,0x7b, 0x15,0x53,0x57,0xf9,0x7e,0xb5,0xb1,0x73,0x07,0xb4,0x83,0x2f, 0xaa,0xf1,0xd6,0x58,0xda,0x4c,0xbb,0x56,0xca,0x7a,0xe5,0xfe, 0xae,0xc7,0xaf,0x33,0x66,0x54,0xb6,0xe6,0x5a,0x29,0x8f,0xa5, 0xcd,0xb4,0x52,0xb4,0x05,0x2e,0xbe,0xea,0x34,0x98,0xd7,0x74, 0x7f,0x67,0xfd,0x56,0x7e,0xd4,0x69,0x68,0x44,0x01,0x70,0x23, 0x8a,0xa2,0x5a,0x07,0xa8,0xf3,0x1b,0xba,0xb6,0x5f,0xb1,0xb7, 0xba,0xf6,0x28,0xed,0xc8,0x81,0x62,0xb9,0x32,0x0e,0x9c,0xd1, 0x3a,0x36,0x5c,0xcb,0xaf,0xc0,0x09,0xc5,0xcf,0x6e,0x8b,0xbe, 0x3b,0x0b,0xb3,0x8a,0x39,0xa1,0x3a,0x0d,0xb5,0x71,0x46,0x6d, 0xf6,0x9c,0x81,0x9c,0x3e,0x2c,0x3c,0xe0,0x41,0x2e,0x63,0x6f, 0x03,0xe7,0xf4,0x68,0x85,0xdd,0xd1,0x6f,0xcb,0x42,0xa8,0xdf, 0x39,0xd5,0x79,0xa0,0x36,0x4e,0xbd,0xac,0x19,0xcd,0x4b,0x9e, 0xdd,0x57,0xb6,0xde,0x1d,0x2c,0x03,0xd7,0xc7,0x33,0xb6,0x93, 0xc2,0x15,0x20,0x7a,0x45,0xd9,0x22,0xc5,0xa0,0x3a,0xd7,0xd5, 0x46,0x02,0x5c,0x51,0xdb,0xff,0x19,0xb2,0x6d,0xf3,0x21,0xe0, 0x2a,0xf0,0xa5,0x52,0xeb,0x4f,0x87,0xf6,0x38,0x7f,0xa4,0x3d, 0xf3,0x63,0x57,0xa4,0xf2,0xaa,0xae,0xae,0x56,0xab,0x49,0x67, 0xbe,0xba,0x11,0x7f,0x7d,0xe7,0xf1,0xe6,0x7b,0x9b,0x31,0x5f, 0xa9,0xe8,0x67,0xe0,0xc2,0xed,0xe9,0x6b,0x2b,0x2f,0xcb,0xc0, 0x59,0xa5,0xd0,0x18,0x58,0x9c,0xc8,0xd8,0xfb,0x69,0xcf,0x5c, 0x02,0x96,0x74,0xfd,0xfb,0x1e,0x98,0xb3,0x83,0x59,0x4a,0x7b, 0xe6,0xd2,0x44,0xc6,0xde,0xd7,0x2b,0x3b,0x56,0xdb,0x67,0xff, 0xf7,0x67,0x54,0x2c,0x57,0xf2,0xfb,0x0e,0x17,0xce,0xab,0xf2, 0x24,0x90,0x0c,0xf9,0x72,0xe7,0xc0,0xa8,0xf3,0xbe,0x32,0xda, 0x32,0x70,0x29,0x8a,0xa2,0x1f,0x5e,0xb7,0x7b,0xad,0x56,0x9b, 0x99,0x9a,0x9a,0xba,0x07,0x7c,0x00,0x64,0x32,0xbe,0x79,0x7b, 0xb9,0x19,0xd7,0x37,0xda,0xe4,0x80,0xb4,0xc0,0xf1,0x7d,0x87, 0x0b,0x6b,0x93,0x07,0x0b,0x4f,0x17,0xe7,0x67,0x97,0x6c,0xb1, 0x5c,0xf9,0x5c,0x6b,0xf7,0x05,0xb0,0x1b,0x10,0xcf,0xb2,0x99, 0x1f,0x71,0x26,0x3d,0x47,0x46,0xf4,0xc5,0xf3,0x2d,0x30,0x53, 0xab,0xd5,0x96,0x7a,0xb9,0x62,0xa7,0xa6,0xa6,0x96,0x80,0x7b, 0x40,0x19,0x98,0x48,0x39,0x32,0xbe,0xbc,0x1e,0xc7,0xed,0x04, 0x2b,0x90,0x4d,0xe0,0x23,0xe0,0xd3,0xdc,0xa1,0xc2,0x43,0x29, 0x96,0x2b,0xd3,0xc0,0x27,0x00,0xd6,0x20,0x19,0x4f,0x92,0xf1, 0x8c,0x6d,0x67,0x03,0xd3,0xe1,0xf8,0x28,0x8a,0xa2,0x0b,0xfd, 0xfc,0xc1,0x56,0xab,0xd5,0xab,0x40,0x15,0x68,0x2d,0xaf,0xc7, 0x3c,0x7a,0xd1,0xb6,0x2f,0x36,0x12,0x69,0xc7,0x74,0xfa,0xe4, 0x17,0x47,0x09,0xe3,0xb8,0x11,0x1e,0xef,0x0e,0xcd,0xd2,0x58, 0xda,0x3c,0x0f,0x3d,0xb3,0xa6,0x8c,0x37,0xcd,0xbf,0xd7,0x6b, 0x3f,0xe3,0x3b,0xe0,0x37,0xa0,0x9c,0x0d,0x4c,0xe8,0x18,0xc2, 0x27,0xab,0xf1,0xf0,0x93,0xd5,0x78,0x57,0x9c,0xb0,0x07,0xb8, 0xf5,0x0f,0xef,0xd0,0x37,0xcf,0xff,0xba,0xa6,0xa6,0x00,0x00, 0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/peak32.png000066400000000000000000000024021302634723100163530ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYsÄÄ•+tIMEØ ) —•útEXtCommentCreated with GIMPW]IDATXõ—¿oSWÇ?çÞ÷ËϱCBHb’QÒ.X´BÔªªRK¢,TíâÉL¨Bºµk;!ÞÄÒ.ü‘ŠD£ªb¨dš È*$˜&„$Šãø½9VÝT€cá+=éêÜï9÷üºß{ŸÐÇ(–+y Œ©è 0s{úÚÝÚrèo”D¸l`7‚C³vÂ7Àµ²}D_.ûŒà'øÀ;¹C…¿çgw”ÓGôG'ô$N{B²e爮10ŠåJ8lúq.ke2kñb`8¦˜õ@ø Àˆ´³YÚF$„Äѵ°8¨| ¬ ´FRf¸ÜI™u°¦˜õÀi t õá@ZÀ°0HËž!pjdH¹Ž¤TßsIY¡¥˜=q@ɧr¥áYñ?{žßsdU¡ÏûÆ3PÞêC¾X`Xe«öC¾8@]1¥A90!ò¬äômª#Žg%'&åÀ^Às-²iM`T\3˜–³Õˆpð: 5uõü?õihºkÀ# î;Òp¬ü­*+½öÙAúß24<0Ìè7ä‡|‰õhöܦÇèO²Uߨ +ºÔŠ¢ènEw;Œêš@¬Ø“½dÁôýi›£¡YSùÃ.Ì€‘”y.p³‹´Jo¼2\¸2zæ°ø]VBÏ\™×,„ªÛ¿ÅrÅ`h¦\YÐM§)u¸*óÓT‚Úè;9à¨n`w¥$eĹ.ÜœÊÅXÕ9ª6úvà°_çõŒoòÊ#Û^SVe{SWù~µ±s´ƒ/ªñÖXÚL»VÊzåþ®Ç¯3fT¶æZ)¥Í´R´.¾ê4˜×tgýV~ÔihDp#Š¢Z¨óº¶_±·ºö(íÈb¹2œÑ:6\˯À ÅÏn‹¾; ³Š9¡: µqFmöœœ>,<àA.coçôh…ÝÑoËB¨ß9Õy 6N½¬ÍKžÝW¶Þ,×Ç3¶“ zEÙ"Å :×ÕF\QÛÿ²mó!à*ð¥RëO‡ö8¤=ócW¤òª®®V«Ig¾º}çñæ{›1_©ègàÂíék+/ËÀY¥ÐXœÈØûiÏ\–týû˜³ƒYJ{æÒDÆÞ×+;VÛgÿ÷gT,WòûΫò$ ùrçÀ¨ó¾2Ú2p)Š¢^·{­V›™ššº|d2¾y{¹×7Ú䀴Àñ}‡ k“ Oçg—l±\ù\k÷°ϲ™q&=GFôÅó-0S«Õ–z¹b§¦¦–€{@˜H92¾¼Çí+Mà#àÓÜ¡ÂC)–+ÓÀ'Ö O’ñŒmgÓáø(Š¢ ýüÁV«Õ«@h-¯Çÿÿ-ððÊÿÿæÿÿmÿÿ  1;²ÿÿÿÄ1A  ŒŒÿÿOÿÿáÿÿãÿÿÊÿÿæüüæóóçÆËìHI÷ÿÿÿ78ùÀÆìööçøøç÷÷ÐÿÿàÿÿÞÿÿNÿÿ  1;²ÿÿÿÄ1A /†ÿ.&hÿ7.zÿ4,tÿ( Zÿ;ÿÿ-“ ÿÿÿÿ'ÿÿ±ÿÿæýýæøùç Œóÿ.&hÿ7.zÿ4,tÿ( Zÿ;ÿÿ s€ôôôçùúæÿÿ¸ÿÿ#ÿÿ/†ÿ.&hÿ7.zÿ4,tÿ( Zÿ;ÿÿ-“  Tÿ;3{ÿYR’ÿ|u±ÿ{t°ÿqh¨ÿWL˜ÿCÿÿ,: ÿÿÿÿÿÿCýý´¨­îÿ;3{ÿYR’ÿ|u±ÿ{t°ÿqh¨ÿWL˜ÿCÿÿ½ÁÈ××Kÿÿÿÿ Tÿ;3{ÿYR’ÿ|u±ÿ{t°ÿqh¨ÿWL˜ÿCÿÿ,: º?7ÿJA‹ÿe^¦ÿVNžÿTLžÿQHšÿun¬ÿWNšÿ9ÿ‚ÿÿ¶¶¿?7ÿJA‹ÿe^¦ÿVNžÿTLžÿQHšÿun¬ÿWNšÿ9ÿ „36º?7ÿJA‹ÿe^¦ÿVNžÿTLžÿQHšÿun¬ÿWNšÿ9ÿ‚ ÿUKÿZR¤ÿ]W§ÿ_Y©ÿ]W§ÿZR¤ÿUKÿphªÿ*"XÿØ ÿUKÿZR¤ÿ]W§ÿ_Y©ÿ]W§ÿZR¤ÿUKÿphªÿ*"XÿØ ÿUKÿZR¤ÿ]W§ÿ_Y©ÿ]W§ÿZR¤ÿUKÿphªÿ*"XÿØ ÿZR¤ÿb\ªÿic±ÿkf²ÿic±ÿb\ªÿZR¤ÿ‚{µÿ4-kÿÿ ÿZR¤ÿb\ªÿic±ÿkf²ÿic±ÿb\ªÿZR¤ÿ‚{µÿ4-kÿÿ ÿZR¤ÿb\ªÿic±ÿkf²ÿic±ÿb\ªÿZR¤ÿ‚{µÿ4-kÿÿÿ]W§ÿic±ÿ~{¿ÿŒÈÿrn¸ÿic±ÿ]W§ÿyµÿ,&\ÿµÿ]W§ÿic±ÿ~{¿ÿŒÈÿrn¸ÿic±ÿ]W§ÿyµÿ,&\ÿµÿ]W§ÿic±ÿ~{¿ÿŒÈÿrn¸ÿic±ÿ]W§ÿyµÿ,&\ÿµ°_Y©ÿkf²ÿÉÿÉÉãÿˆ…Åÿkf²ÿ_Y©ÿg`¨ÿ,&Xÿy°_Y©ÿkf²ÿÉÿÉÉãÿˆ…Åÿkf²ÿ_Y©ÿg`¨ÿ,&Xÿy°_Y©ÿkf²ÿÉÿÉÉãÿˆ…Åÿkf²ÿ_Y©ÿg`¨ÿ,&Xÿy #Iÿic±ÿrn¸ÿ‰†Æÿrn¸ÿic±ÿ]W§ÿC=ÿÿ%2  #Iÿic±ÿrn¸ÿ‰†Æÿrn¸ÿic±ÿ]W§ÿC=ÿÿ%2  #Iÿic±ÿrn¸ÿ‰†Æÿrn¸ÿic±ÿ]W§ÿC=ÿÿ%2 "3‹ÿic±ÿkf²ÿic±ÿb\ªÿZR¤ÿÿ<|ÿü?ü?ÿÿøüÿÿðøÿÿàðÿÿàðÿøààÀÀÀÀààÀàààððàððøøøÿÏøóÿÿïð÷ÿÿçðçÿÿóàÏÿÿùÀŸÿÿüÀ?ÿø>|àðàÀðÀààÀààÀààÀààÀàààððàððø?üüÿÿÿÿÿÿÿÿÿÿÿÿfityk-1.3.1/wxgui/img/powdifpat16.xpm000066400000000000000000000007671302634723100174660ustar00rootroot00000000000000/* XPM */ static const char * powdifpat16_xpm[] = { "16 16 8 1", " c None", ". c #000000", "+ c #DCBBB6", "@ c #C9887F", "# c #B75447", "$ c #CB8A81", "% c #C8877E", "& c #8B3F35", " ... ... ...", ".+@#. .+@#. .+@#", ".$%#. .$%#. .$%#", ".##&. .##&. .##&", " ... ... ...", " ", " ... ... ...", ".+@#. .+@#. .+@#", ".$%#. .$%#. .$%#", ".##&. .##&. .##&", " ... ... ...", " ", " ... ... ...", ".+@#. .+@#. .+@#", ".$%#. .$%#. .$%#", ".##&. .##&. .##&"}; fityk-1.3.1/wxgui/img/powdifpat48.xpm000066400000000000000000000150011302634723100174560ustar00rootroot00000000000000/* XPM */ static const char * powdifpat48_xpm[] = { "48 48 112 2", " c None", ". c #000000", "+ c #020100", "@ c #331D1D", "# c #B16369", "$ c #B2666B", "% c #AA5C62", "& c #A4525A", "* c #B86E72", "= c #C68689", "- c #A7575D", "; c #813D43", "> c #A9595F", ", c #C98D90", "' c #E3C9C9", ") c #C58588", "! c #A86067", "~ c #58262C", "{ c #BF7B7E", "] c #C88C8F", "^ c #B5797F", "/ c #5C262C", "( c #030201", "_ c #B57B82", ": c #6B2D34", "< c #9D4B55", "[ c #AA6870", "} c #58222A", "| c #7F373F", "1 c #8B414A", "2 c #A65E65", "3 c #9E4E56", "4 c #9E4C54", "5 c #9A4851", "6 c #AC6E75", "7 c #9A4E57", "8 c #391317", "9 c #080706", "0 c #060600", "a c #0B0A05", "b c #181818", "c c #7B333B", "d c #925259", "e c #B1757C", "f c #B0747B", "g c #A86871", "h c #984C57", "i c #43171D", "j c #FDFD00", "k c #ADA803", "l c #C1BD06", "m c #2F1718", "n c #0E0E0E", "o c #68262E", "p c #7A2E37", "q c #742C34", "r c #5A2028", "s c #3B1319", "t c #2D1817", "u c #FFFF00", "v c #F9F800", "w c #8C7F0D", "x c #80730D", "y c #F4F400", "z c #FAF900", "A c #FCFC00", "B c #F3F301", "C c #CBC606", "D c #494800", "E c #383700", "F c #C6C007", "G c #F6F600", "H c #F8F800", "I c #F7F700", "J c #F0F000", "K c #F3F300", "L c #F3F200", "M c #E8E801", "N c #D8D703", "O c #E7E701", "P c #DAD903", "Q c #F0EF00", "R c #080700", "S c #D9D405", "T c #8D8906", "U c #4E4E00", "V c #1E1E00", "W c #373600", "X c #A4A005", "Y c #080800", "Z c #51371A", "` c #3A241B", " . c #E4E402", ".. c #252400", "+. c #FDFC00", "@. c #7A7A03", "#. c #E6E602", "$. c #3F3F00", "%. c #CBC705", "&. c #F2F201", "*. c #040300", "=. c #BBB508", "-. c #F1F101", ";. c #BDB608", ">. c #C2BC07", ",. c #F2F100", "'. c #DAD902", "). c #402C1B", "!. c #7B6714", "~. c #FBFB00", "{. c #BBB605", "]. c #C7C305", " ", " ", " . . . . + . . . . + . . . . + ", " @ . # $ # % & . @ . # $ # % & . @ . # $ # % & . ", " . # * = * # - ; . . # * = * # - ; . . # * = * # - ; . ", " . > $ , ' ) $ > ! ~ . > $ , ' ) $ > ! ~ . > $ , ' ) $ > ! ~ ", " . - # { ] * # - ^ / ( . - # { ] * # - ^ / ( . - # { ] * # - ^ / ( ", " . & % # $ # % & _ : . . & % # $ # % & _ : . . & % # $ # % & _ : . ", " . < & - > - & < [ } + . < & - > - & < [ } + . < & - > - & < [ } + ", " . | 1 2 3 4 5 6 7 8 9 0 | 1 2 3 4 5 6 7 8 a . | 1 2 3 4 5 6 7 8 9 ", " b c d e f g h i . j k b c d e f g h i . l b c d e f g h i . ", " m n o p q r s . t u u j v w n o p q r s . x y z u m n o p q r s . t ", " ( . . . ( u u u u A B C D . . . E F G H I u u ( . . . ( ", " u J u u u u u u u u u u u u J u ", " u u u u u u u u u u u u u u u u ", " u u u u u u u u u u u u u u ", " u u u u u u u u u u u u ", " u u u u u u u u u u ", " K A L G M N N O P Q ", " . . . . R S T U V . . W X Y . . . + ", " @ . # $ # % & . Z @ . # $ # % & . ` . # $ # % & . ", " . # * = * # - ; . . # * = * # - ; . . # * = * # - ; . ", " . > $ , ' ) $ > ! ~ . > $ , ' ) $ > ! ~ . > $ , ' ) $ > ! ~ ", " . - # { ] * # - ^ / ( . - # { ] * # - ^ / ( . - # { ] * # - ^ / ( ", " . & % # $ # % & _ : . .u u u u A . & % # $ # % & _ : . .u u u A . & % # $ # % & _ : . ", " . < & - > - & < [ } .. .u u u u +.. < & - > - & < [ } .. .u u u +.. < & - > - & < [ } + ", " . | 1 2 3 4 5 6 7 8 @.#.u u u u A $.| 1 2 3 4 5 6 7 8 @.#.u u u A $.| 1 2 3 4 5 6 7 8 9 ", " b c d e f g h i . %.&.u u u u j k b c d e f g h i . %.&.u u u j k b c d e f g h i . ", " m n o p q r s . x y z u u u u j v w n o p q r s . x y z u u u j v w n o p q r s . t ", " ( . . . *.=.G H H u u u u u A -. ( . . . ( ;.G H H u u u u A B >.*.. . . ( ", " u u u u ,.u u u u u u u u ,.u u u u ", " u u u u A u u u u u u u u A u u u u ", " u u u u u u u u u u u u u u ", " u u u u u u u u u u u ", " u u u u u u u u ", " . . . . + u u u . . . . + u u . . . . + ", " @ . # $ # % & . u u '. ).. # $ # % & . !.,.~.u @ . # $ # % & . ", " . # * = * # - ; . J {.. # * = * # - ; . ]. . # * = * # - ; . ", " . > $ , ' ) $ > ! ~ Y > $ , ' ) $ > ! ~ . > $ , ' ) $ > ! ~ ", " . - # { ] * # - ^ / ( . - # { ] * # - ^ / ( . - # { ] * # - ^ / ( ", " . & % # $ # % & _ : . . & % # $ # % & _ : . . & % # $ # % & _ : . ", " . < & - > - & < [ } + . < & - > - & < [ } + . < & - > - & < [ } + ", " . | 1 2 3 4 5 6 7 8 9 . | 1 2 3 4 5 6 7 8 9 . | 1 2 3 4 5 6 7 8 9 ", " b c d e f g h i . b c d e f g h i . b c d e f g h i . ", " m n o p q r s . t m n o p q r s . t m n o p q r s . t ", " ( . . . ( ( . . . ( ( . . . ( ", " ", " "}; fityk-1.3.1/wxgui/img/preferences16.h000066400000000000000000000062061302634723100174070ustar00rootroot00000000000000static const unsigned char preferences16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x43, 0xbb, 0x7f, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd6, 0x05, 0x1b, 0x17, 0x0b, 0x34, 0x9c, 0x62, 0x92, 0xf7, 0x00, 0x00, 0x01, 0x93, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x95, 0x93, 0xbd, 0x6a, 0xdb, 0x50, 0x14, 0xc7, 0x7f, 0xf7, 0x43, 0xb2, 0x6c, 0x48, 0x65, 0x13, 0x4f, 0x1e, 0x43, 0xa1, 0xd0, 0xae, 0x69, 0x3b, 0x35, 0x34, 0x5d, 0x0d, 0x4d, 0xb2, 0x1a, 0xbc, 0xf9, 0x01, 0xba, 0x14, 0x32, 0xa4, 0x73, 0xb7, 0x42, 0xa1, 0xa5, 0x8b, 0x70, 0xad, 0x87, 0xb0, 0xc1, 0x4b, 0xe7, 0x42, 0x9f, 0xc0, 0x20, 0xbc, 0xf8, 0x01, 0x9c, 0x36, 0xe0, 0xc5, 0xd2, 0x3d, 0x59, 0x22, 0x59, 0xaa, 0xe2, 0xc1, 0x07, 0x2e, 0x9c, 0x7b, 0xfe, 0xe7, 0xfe, 0x38, 0x1f, 0x5c, 0x35, 0x1e, 0x8f, 0x3f, 0x8a, 0xc8, 0x27, 0x11, 0xf1, 0x38, 0xc0, 0x94, 0x52, 0x99, 0xd6, 0xfa, 0x87, 0x15, 0x91, 0x9b, 0xe1, 0x70, 0x78, 0xa4, 0x94, 0xe2, 0x50, 0x8b, 0xe3, 0xf8, 0x83, 0x15, 0x11, 0xdf, 0xf3, 0x3c, 0x56, 0xab, 0x15, 0x4a, 0x29, 0x72, 0x50, 0xd9, 0x2f, 0x9b, 0x88, 0x00, 0xd0, 0xeb, 0xf5, 0x00, 0x94, 0xcd, 0x85, 0xf9, 0x7c, 0x5e, 0x4b, 0xee, 0xf7, 0xfb, 0x85, 0xbf, 0x48, 0x12, 0x94, 0xc0, 0xab, 0x97, 0xa7, 0xac, 0xd7, 0xeb, 0x22, 0xae, 0xcb, 0x0f, 0x46, 0xa3, 0x51, 0x71, 0x00, 0xfe, 0xdd, 0xdd, 0xa1, 0xf5, 0x2e, 0xe5, 0xcb, 0xb7, 0xef, 0x45, 0x75, 0x8f, 0x02, 0x00, 0x96, 0xcb, 0xa4, 0x72, 0x2f, 0x03, 0xfc, 0x20, 0xa8, 0xc5, 0x6a, 0x80, 0x93, 0x93, 0xa7, 0x95, 0x7b, 0x96, 0x65, 0x3b, 0x40, 0x23, 0xc0, 0x18, 0x53, 0x01, 0xd8, 0x72, 0x72, 0x14, 0x45, 0x7b, 0x87, 0x56, 0x5a, 0x5f, 0xb5, 0xc2, 0xdc, 0x79, 0x7b, 0xfe, 0x8e, 0x67, 0xcf, 0x5f, 0xf0, 0xeb, 0xf7, 0x1f, 0xde, 0x5f, 0x5c, 0xf0, 0xe6, 0xec, 0xac, 0x48, 0x9a, 0x4e, 0xa7, 0x24, 0x8b, 0x05, 0xe7, 0xaf, 0x4f, 0x89, 0xe3, 0x98, 0xd9, 0x6c, 0xb6, 0xab, 0x20, 0x27, 0x86, 0x4f, 0x8e, 0xb8, 0xfd, 0x7b, 0x0b, 0x40, 0x3b, 0x0c, 0xc9, 0xd2, 0x14, 0x63, 0x0c, 0x59, 0x96, 0xd1, 0x6a, 0xb5, 0x18, 0x0c, 0x06, 0xc5, 0xa3, 0xc9, 0x64, 0x52, 0xaf, 0x20, 0x07, 0xf9, 0x8d, 0xa0, 0x10, 0x9d, 0x73, 0x58, 0x6b, 0x1f, 0x5a, 0x71, 0x2c, 0x97, 0x09, 0xce, 0xb9, 0x4a, 0x0b, 0xf6, 0x7f, 0x80, 0xd7, 0x68, 0x54, 0x36, 0x60, 0x8c, 0x79, 0xd0, 0x75, 0x6d, 0xc0, 0x35, 0x40, 0xb7, 0xdb, 0xe5, 0xf3, 0xcd, 0x75, 0x21, 0x06, 0x41, 0x40, 0x9a, 0xa6, 0x6c, 0x36, 0x9b, 0xca, 0x80, 0x3d, 0xcf, 0x7b, 0x1c, 0xd0, 0x09, 0x43, 0xb4, 0xd6, 0x6c, 0xb7, 0x5b, 0xda, 0xed, 0x36, 0x5a, 0x6b, 0x9a, 0xcd, 0x26, 0x97, 0x57, 0x57, 0x88, 0x08, 0x22, 0x82, 0x73, 0xae, 0xd2, 0x86, 0x05, 0x52, 0x80, 0x4e, 0xa7, 0xb3, 0xf7, 0xd3, 0x74, 0x8f, 0x8f, 0xf7, 0x6a, 0xd6, 0x18, 0xf3, 0x35, 0x8a, 0xa2, 0x6b, 0xc0, 0x1c, 0xf8, 0x19, 0x9d, 0xef, 0xfb, 0x3f, 0xef, 0x01, 0x1d, 0x27, 0x7e, 0xbb, 0xed, 0x3f, 0x5c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/preferences16.png000066400000000000000000000010061302634723100177350ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC» pHYs  šœtIMEÖ 4œb’÷“IDAT8Ë•“½jÛPÇ÷C²lHeOC¡Ð®i;54] M²¼ùº2¤s·B¡¥‹p­‡°ÁKçBŸÀ ¼øœ6àÅÒ=Y"YªâÁ.œ{þçþ8\5?ŠÈ'ñ8À”R™Öú‡‘›ápx¤”âP‹ãøƒßó‘X,H3—®¡!xúi.\`4“aˆ¤Ë¿£V¿Õ0è{ì1Z‰tt@¦ƒÔ>û,ó¾ÕØHØN$BïsÏqAkýúÅ›g9Ür ùr±NÚ+ð3ìîn.è:o«†Á÷Þ‹–L¢ZVígåJ䃸êypìƧŸbärpø0³kÖàתŸŸG9žÐöíh¦Iõõœ=yëÔ)ÒAž ·—«óóØ›6]ïV4Š—L2õá‡\ Âqì—OžÄª¯ç¿ªã°fÝ:C«å`Çœ?¦nròz·R)Ô#G0;;q¥6ÇØ¡¦&Èåø‹öW<þ8 ÷ÝGõ«hiÁ;z£ü}Û&ÔÜŒ“ò¼ê«W#©ø>ª²bÃ_}EóCÕv^\““„n¾™¨ë^+ ŒŒÞº7(G_tu‘Ô4”mÓ\6mÂ;{–ô{ïaær({÷’¹q€‹AÓ°Ôl–‘þþ+ÎdPÆÇ <ÈÜ»ï2›N£LO/½Ú«­áa¼l–_îol$4íˆ`½ü2s€è:~$R89Ÿy¦ö=QЦ&âÀƒ  ‡Ãœÿþ{êî¹§¶óxœP[kX´ßUúû™¾ë.òžžŽœ|ž-ªˆäU•½ù&NÖ½ð åâ¾Ï?OCŽ7Þ §i|."¹Òë8qæLõ¶?ÎÔ8d>úˆ+Õ8°tÐXHömÛFÜq*æóX[¶TÎ ¥hnÆÅ®Ä±°p-ì¯É"õõüg÷îB$+Go/Wk‰ñâ‹ÌUâØµ‹ Óä@_b Jëê8wà—J m›©òˆV ºŽ?:º8¸ôôp©®Ž_€hÅPZbâVÃà×]»˜Èf Ň1£ªÁÄ‹xåfE°ë©§˜0MF€-Kô–™ŠšL“¾Ûn#>8X0ñûï$÷íc.½ž”˱jÞÞ½ÌÿüsáéükÛ6âõõ|SÜt&#EQšÆ~ {çNü×_'rûí…Ï’IÔ±1B‰!ßGÙ¼·¥oݺB€·Þ"wâ"Â×åå†Õ Ãi“að’çñ÷U«®.´X mÃX¿\·0˜Ú6üðî—_âÍÍ¡hÿÌfù‡ˆüQ•ÿFÇs]ço¦É®{m<—p˜+šÆt&Ã@>Ï¿3"RóDø*ø,L×~äpIEND®B`‚fityk-1.3.1/wxgui/img/recordmacro16.h000066400000000000000000000046371302634723100174140ustar00rootroot00000000000000static const unsigned char recordmacro16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x01, 0x53, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xa5, 0x93, 0xbf, 0x4b, 0x42, 0x71, 0x14, 0xc5, 0x3f, 0xef, 0x3d, 0xf1, 0x47, 0x60, 0x83, 0x41, 0xfb, 0xf3, 0x21, 0xbc, 0xff, 0xa0, 0xd9, 0x4d, 0x1e, 0x48, 0x7b, 0x81, 0x43, 0xad, 0x41, 0x34, 0xd8, 0x64, 0x9b, 0xe5, 0x6c, 0x8b, 0x10, 0x36, 0x34, 0xd4, 0xe4, 0x52, 0xe4, 0x10, 0x34, 0x38, 0xb6, 0xe6, 0x94, 0x46, 0xbc, 0x6f, 0x8d, 0x6a, 0x21, 0x09, 0xcf, 0x1f, 0xcb, 0x6d, 0x51, 0x11, 0x95, 0x54, 0xbc, 0x70, 0x97, 0xc3, 0x3d, 0x87, 0x73, 0xe0, 0x5c, 0x0d, 0xb0, 0x80, 0x3d, 0x56, 0x9f, 0x3b, 0xe0, 0x03, 0xe0, 0x0c, 0x88, 0xac, 0x48, 0x8e, 0x0c, 0x79, 0xe8, 0x43, 0xe0, 0x07, 0xd8, 0x01, 0x64, 0x89, 0x3d, 0x18, 0xde, 0x33, 0x29, 0x00, 0xf0, 0x22, 0x22, 0x2c, 0x5a, 0xe0, 0x7a, 0xd2, 0x8a, 0x3e, 0xed, 0xad, 0x52, 0xa9, 0x90, 0x4e, 0xa7, 0x31, 0x4d, 0x13, 0x4d, 0xd3, 0xb0, 0x2c, 0x8b, 0x6c, 0x36, 0x8b, 0x52, 0x8a, 0x6a, 0xb5, 0x3a, 0x93, 0xc5, 0x37, 0x0d, 0x94, 0xcb, 0x65, 0x5e, 0x9f, 0x9f, 0x78, 0x3c, 0x3d, 0x62, 0x73, 0x23, 0xc4, 0xaf, 0xd7, 0xe5, 0xe4, 0xea, 0x86, 0x40, 0x20, 0x80, 0xe3, 0x38, 0x33, 0x02, 0x33, 0x0e, 0x4a, 0xa5, 0x12, 0x99, 0x44, 0x9c, 0x41, 0xb3, 0x49, 0xeb, 0xf3, 0x8b, 0x41, 0xb3, 0x49, 0x26, 0x11, 0xa7, 0x58, 0x2c, 0x62, 0x18, 0xc6, 0x62, 0x07, 0x4a, 0x29, 0xfa, 0x8d, 0x16, 0xfd, 0x29, 0xbc, 0x5e, 0xaf, 0x2f, 0x27, 0x10, 0x8d, 0x46, 0x71, 0xdf, 0xde, 0x09, 0x87, 0x82, 0x63, 0xac, 0xd3, 0xed, 0x61, 0xdb, 0x36, 0xba, 0xae, 0x2f, 0x16, 0x48, 0xa5, 0x52, 0xe4, 0x2f, 0xce, 0xd9, 0xdf, 0xde, 0x22, 0x1c, 0x0c, 0xd2, 0xe9, 0xf5, 0xb8, 0x6d, 0x7c, 0x73, 0x9c, 0xbf, 0x9c, 0xeb, 0x60, 0x54, 0x24, 0x00, 0x11, 0x11, 0xa9, 0xd5, 0x6a, 0x92, 0xcb, 0xe5, 0x24, 0x16, 0x8b, 0x09, 0x20, 0xb6, 0x6d, 0x4b, 0xa1, 0x50, 0x10, 0x11, 0x11, 0xd7, 0x75, 0x47, 0x5d, 0x18, 0xf3, 0x7c, 0xd3, 0xf9, 0x3d, 0xcf, 0xc3, 0x71, 0x1c, 0x92, 0xc9, 0x24, 0x7e, 0xbf, 0x1f, 0x5d, 0xd7, 0x31, 0x0c, 0x03, 0xa5, 0x14, 0xed, 0x76, 0xfb, 0xdf, 0x08, 0xbb, 0xa6, 0x69, 0xde, 0x2f, 0x51, 0xe3, 0xc3, 0x79, 0x02, 0x11, 0xe0, 0x01, 0xd0, 0x56, 0xf8, 0x05, 0x18, 0x12, 0xd6, 0xfe, 0xc6, 0xb5, 0xe6, 0x0f, 0x4b, 0x04, 0x96, 0x6c, 0x84, 0x64, 0x2c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/recordmacro16.png000066400000000000000000000006141302634723100177400ustar00rootroot00000000000000‰PNG  IHDRóÿaSIDATxÚ¥“¿KBqÅ?ï=ñG`ƒAûó!¼ÿ ÙMH{C­A4Ød›ål‹64ÔäRä48¶æ”F¼oj! ÏËmQ•T¼p—Ã=‡sà\ °€=VŸ;àà ˆ¬HŽ yèCàØd‰=Þ3)ð"",ZàzÒŠ>í­R©N§1MMÓ°,‹l6‹RŠjµ:“Å7 ”Ëe^ŸŸx<=bs#į×åäê†@ €ã833J¥™DœA³Iëó‹A³I&§X,bÆbJ)úý)¼^¯/'FqßÞ ‡‚c¬ÓíaÛ6º®/H¥Rä/ÎÙßÞ" Òéõ¸m|sœ¿œë`T$©Õj’Ëå$‹ ¶mK¡P×uG]ó|Óù=ÏÃq’É$~¿]×1 ¥ívûß»¦iÞ/QãÃyàÐVøÖþƵæK–l„d,IEND®B`‚fityk-1.3.1/wxgui/img/redo16.h000066400000000000000000000063761302634723100160470ustar00rootroot00000000000000static const unsigned char redo16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x87, 0x00, 0x00, 0x0b, 0x87, 0x01, 0x93, 0x40, 0x87, 0x53, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd6, 0x04, 0x05, 0x13, 0x14, 0x09, 0x83, 0xff, 0x71, 0xb8, 0x00, 0x00, 0x01, 0xa8, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x8d, 0x93, 0x3f, 0x68, 0x13, 0x51, 0x1c, 0xc7, 0x3f, 0x17, 0x43, 0xd4, 0x64, 0x93, 0x5c, 0xdc, 0x15, 0x42, 0x69, 0xa1, 0x8e, 0x41, 0x70, 0x51, 0x41, 0xe8, 0xd2, 0x82, 0x4b, 0xe0, 0x82, 0x76, 0x68, 0xb9, 0x58, 0xb4, 0xe0, 0xe6, 0x1f, 0x50, 0x70, 0x71, 0x2b, 0x28, 0x44, 0x2c, 0x01, 0x29, 0x28, 0xa8, 0x28, 0x22, 0x39, 0xd3, 0x45, 0x24, 0xa5, 0x82, 0xd0, 0xa1, 0xd0, 0x20, 0xb1, 0xd0, 0x86, 0xb6, 0xa8, 0x24, 0x46, 0xa3, 0x21, 0xe6, 0x8a, 0x17, 0x2e, 0xb9, 0x3e, 0x07, 0x9b, 0x78, 0xc9, 0x25, 0xe1, 0xde, 0xf8, 0xbe, 0xef, 0xf3, 0x7d, 0xbf, 0xbf, 0xe0, 0xe2, 0x8c, 0x27, 0x7d, 0xa2, 0x9f, 0xe6, 0xc1, 0xe5, 0xe9, 0x67, 0xe2, 0xda, 0xe0, 0xc1, 0xe4, 0x4a, 0x4f, 0x13, 0x6f, 0x9f, 0xdf, 0x86, 0x81, 0x4f, 0xf6, 0x3b, 0x21, 0x35, 0xb9, 0x77, 0x31, 0x03, 0x9c, 0x11, 0x9a, 0x6a, 0x4a, 0x83, 0x42, 0xbd, 0x3c, 0x9e, 0xf4, 0x89, 0x27, 0x15, 0x45, 0x94, 0x1b, 0x79, 0x51, 0x34, 0x3f, 0x8a, 0x1f, 0x8d, 0x0d, 0x91, 0x33, 0x52, 0x62, 0x49, 0x9f, 0x13, 0x3b, 0xf5, 0x0f, 0xc2, 0x1e, 0x89, 0xd4, 0x0d, 0x03, 0x89, 0xbb, 0x17, 0x5e, 0x22, 0x7b, 0xc3, 0x14, 0x1a, 0x6b, 0x78, 0xf0, 0x52, 0xdb, 0x2b, 0xb1, 0x6b, 0x95, 0xdb, 0xef, 0x86, 0x0e, 0x9e, 0xe3, 0xea, 0xe3, 0xb3, 0x68, 0xaa, 0x29, 0x49, 0x36, 0x38, 0x0c, 0x6c, 0x4c, 0x45, 0x67, 0x39, 0xe9, 0x57, 0x29, 0x35, 0x73, 0x58, 0xa2, 0xc1, 0x2f, 0x6b, 0x07, 0x73, 0xef, 0x8f, 0x23, 0xd2, 0xa3, 0xcd, 0x13, 0xdc, 0x79, 0xa5, 0x74, 0xd4, 0x20, 0x26, 0xf4, 0xc3, 0x8c, 0x1e, 0x3a, 0x4f, 0xd5, 0xfa, 0xca, 0x62, 0xed, 0x26, 0xc5, 0xed, 0x4a, 0xcf, 0x34, 0x23, 0xb2, 0xc2, 0x7c, 0x46, 0x01, 0x88, 0xdb, 0x0d, 0x6e, 0x5f, 0x9a, 0xbe, 0x02, 0xc0, 0xa3, 0xcf, 0x31, 0xc2, 0x9e, 0x31, 0x42, 0xc1, 0x4e, 0x30, 0xfb, 0x73, 0x91, 0x48, 0x50, 0xe1, 0x45, 0xe6, 0x21, 0x40, 0x5c, 0x53, 0xcd, 0x64, 0x47, 0x17, 0x8e, 0xf9, 0x4e, 0x91, 0xae, 0x5d, 0x27, 0xec, 0x19, 0x23, 0x95, 0x7e, 0x0d, 0x01, 0xa3, 0xad, 0x4d, 0x9c, 0x56, 0xfe, 0xc1, 0x4b, 0xff, 0x61, 0xc7, 0x1c, 0x34, 0xa9, 0xe3, 0xaf, 0x1e, 0x27, 0xbf, 0xb5, 0x09, 0x01, 0x23, 0xab, 0xa9, 0xa6, 0xd4, 0x6a, 0x99, 0xff, 0xc0, 0x11, 0x07, 0xec, 0x30, 0xf8, 0x6d, 0x7d, 0x03, 0x60, 0xfd, 0xcb, 0x2a, 0xc0, 0x35, 0xbb, 0xf6, 0xec, 0x5d, 0xc2, 0x01, 0x3b, 0x0c, 0x16, 0x96, 0x6f, 0x11, 0x92, 0x43, 0x00, 0x68, 0xaa, 0xf9, 0xb6, 0xab, 0x76, 0x0e, 0xb8, 0xdb, 0x60, 0xa4, 0x5c, 0xd0, 0xa9, 0x0b, 0xbd, 0xd5, 0xd6, 0x68, 0x4b, 0xd8, 0x4f, 0x25, 0x39, 0x70, 0x17, 0x34, 0xd5, 0x5c, 0x07, 0xa8, 0x7e, 0x37, 0x98, 0x89, 0xde, 0x00, 0x78, 0xee, 0x66, 0x47, 0xba, 0x77, 0x41, 0x7e, 0xf3, 0xfe, 0x69, 0x6b, 0xe4, 0xee, 0xbb, 0x31, 0xf8, 0x0b, 0xaf, 0x7e, 0xb1, 0x1d, 0x08, 0xdc, 0x56, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/redo16.png000066400000000000000000000010331302634723100163650ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs ‡ ‡“@‡StIMEÖ ƒÿq¸¨IDAT8Ë“?hQÇ?CÔd“\ÜBi¡ŽApQAèÒ‚Kà‚vh¹X´àæPpq+(D,)(¨("9ÓE$¥‚СР±Ð†¶¨$F£!æŠ.¹>›xÉ%áÞø¾ïó}¿¿àâŒ'}¢ŸæÁåégâÚàÁäJOoŸß†Oö;!5¹w1œšjJƒB½<žô‰'E”yQ4?Š ‘3RbIŸ;õÂ‰Ô ‰»^"{ÃkxðRÛ+±k•Ûãêã³hª)I68 lLEg9éW)5sX¢Á/ksï#Ò£ÍÜy¥tÔ &ôÃŒ:OÕúÊbí&ÅíJÏ4#²Â|FˆÛ n_š¾À£Ï1ž1BÁN0ûs‘HPáEæ!@\SÍdGŽùN‘®]'ì#•~ £­MœVþÁKÿaÇ4©ã¯'¿µ #«©¦Ôj™ÿÀì0øm}`ýË*À5»öì]Â; –o’Chªù¶«v¸Û`¤\Щ ½ÕÖhKØO%9p4Õ\¨~7˜‰ÞxîfGºwA~óþikäî»1ø ¯~±ÜV/IEND®B`‚fityk-1.3.1/wxgui/img/reload16.h000066400000000000000000000125221302634723100163520ustar00rootroot00000000000000static const unsigned char reload16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, 0x88, 0x00, 0x00, 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x00, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x00, 0x00, 0x03, 0x0b, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x6d, 0x92, 0x4d, 0x68, 0x54, 0x57, 0x14, 0xc7, 0xff, 0xe7, 0xbe, 0xfb, 0x32, 0xce, 0x57, 0x26, 0xa3, 0x93, 0xcf, 0xc6, 0x98, 0x11, 0x41, 0x45, 0xd3, 0x16, 0x35, 0xa6, 0xd0, 0x90, 0xb6, 0x50, 0xe8, 0x62, 0x44, 0x4a, 0x15, 0x14, 0x41, 0x2c, 0xc5, 0x86, 0x82, 0x3b, 0xa1, 0xfa, 0x74, 0x23, 0xd8, 0xcd, 0x58, 0x41, 0x57, 0x25, 0x94, 0x56, 0x84, 0x92, 0xb4, 0xa5, 0x52, 0x29, 0x25, 0xaf, 0xb3, 0xa8, 0xad, 0xb6, 0x6a, 0xa1, 0x31, 0x22, 0x9a, 0x60, 0xd4, 0x36, 0xf3, 0x9a, 0x98, 0x64, 0x9a, 0x69, 0x62, 0x26, 0x99, 0x8f, 0x37, 0x99, 0x79, 0x73, 0x4f, 0x17, 0xce, 0x83, 0x59, 0x78, 0xe0, 0xee, 0xce, 0xf9, 0xf1, 0x3f, 0xbf, 0x73, 0x89, 0x99, 0xe1, 0x56, 0x34, 0x16, 0x5f, 0x4f, 0x44, 0x67, 0x01, 0xbc, 0xc1, 0xcc, 0x2d, 0x44, 0xb4, 0x04, 0xd0, 0x04, 0xb3, 0x1a, 0x00, 0xf0, 0xa3, 0x65, 0x1a, 0xe5, 0x9a, 0xde, 0x53, 0x00, 0x06, 0xc8, 0x05, 0x44, 0x63, 0xf1, 0x77, 0x41, 0xf4, 0xb5, 0x37, 0x10, 0x94, 0x6b, 0xc3, 0x41, 0xbd, 0x39, 0x52, 0x0f, 0xaf, 0xae, 0xc1, 0xb6, 0x57, 0x91, 0xfa, 0x77, 0x21, 0x97, 0xfa, 0x2f, 0x53, 0x01, 0xf3, 0x47, 0x96, 0x69, 0x7c, 0x1b, 0x8d, 0xc5, 0xfb, 0x01, 0x7c, 0x0e, 0xa0, 0x81, 0x98, 0x19, 0xd1, 0x58, 0x7c, 0x2b, 0x88, 0x46, 0x43, 0x91, 0x46, 0x9f, 0xc7, 0xe3, 0x41, 0xc8, 0xaf, 0xa3, 0x35, 0x12, 0x44, 0x24, 0xe4, 0x45, 0x24, 0xe4, 0x43, 0xc0, 0xab, 0x23, 0x93, 0x2d, 0xe0, 0x4a, 0x62, 0xb4, 0x90, 0xcd, 0x17, 0xef, 0xf8, 0xd6, 0xe8, 0xbb, 0xed, 0x62, 0xa9, 0x8e, 0x19, 0x6b, 0x9f, 0x03, 0xf6, 0x9c, 0xfb, 0xc2, 0xeb, 0x0f, 0x7c, 0x20, 0x34, 0x4d, 0xd8, 0xb9, 0x2c, 0x94, 0x52, 0x90, 0x82, 0x2a, 0x8d, 0xeb, 0x82, 0x85, 0xed, 0x9b, 0x3b, 0x02, 0x3b, 0xb6, 0xb4, 0x53, 0x9d, 0xae, 0x41, 0x6a, 0x84, 0xc4, 0xed, 0x09, 0xd5, 0xd3, 0xb5, 0x41, 0x7c, 0x36, 0x78, 0xbd, 0xe4, 0x54, 0x54, 0x44, 0x54, 0x57, 0x3a, 0xb8, 0x6a, 0xdb, 0x82, 0x9d, 0x32, 0xaf, 0x6b, 0x6e, 0x2e, 0x44, 0xda, 0xda, 0x4f, 0x38, 0x15, 0xb5, 0x3e, 0x95, 0x5e, 0xde, 0x77, 0xed, 0xd6, 0xf8, 0xbd, 0x6f, 0xcc, 0x91, 0x42, 0xce, 0x2e, 0x42, 0x97, 0x1a, 0xf6, 0xbf, 0xfd, 0xb2, 0xe8, 0x68, 0x6e, 0x00, 0x00, 0x02, 0xa0, 0x9e, 0x03, 0x98, 0xfd, 0x42, 0x90, 0xd3, 0xd7, 0xbb, 0xeb, 0xb2, 0xd0, 0xe4, 0x32, 0x80, 0xab, 0x96, 0x69, 0xa4, 0x2c, 0xd3, 0xf8, 0x39, 0x39, 0x7c, 0x72, 0xe7, 0xf4, 0xdc, 0xe2, 0xb1, 0x8b, 0x97, 0xaf, 0x61, 0x7e, 0x71, 0x05, 0x56, 0x6a, 0x05, 0x8e, 0x52, 0xae, 0x4b, 0x76, 0x13, 0xa8, 0x97, 0x5a, 0x9b, 0x3e, 0xa9, 0x0f, 0x78, 0x2f, 0x74, 0xb6, 0x37, 0x75, 0x01, 0xb0, 0x6a, 0x6c, 0x4b, 0x22, 0x3a, 0xfa, 0x66, 0xcf, 0xe6, 0x52, 0x47, 0x4b, 0x18, 0x4d, 0x61, 0x1f, 0xa4, 0x10, 0x6e, 0x02, 0x96, 0xd5, 0xbe, 0xf0, 0x8d, 0x81, 0xc3, 0x59, 0xbc, 0xb8, 0xbe, 0x64, 0xe6, 0xd7, 0xef, 0x8e, 0xff, 0x53, 0xbc, 0x3f, 0x31, 0x5d, 0x24, 0x10, 0x40, 0x80, 0x53, 0x51, 0x6b, 0x00, 0xb0, 0x7b, 0x85, 0x55, 0x00, 0xba, 0x1b, 0xab, 0xe6, 0xfd, 0x0a, 0xe0, 0x28, 0x80, 0xf2, 0x0b, 0xc0, 0xd2, 0x32, 0x8d, 0x19, 0x17, 0xe0, 0x9c, 0xff, 0xf8, 0x3d, 0x0d, 0x00, 0x94, 0x62, 0xdc, 0x18, 0x9d, 0x54, 0x89, 0xdf, 0xc7, 0x9e, 0x82, 0xf9, 0x55, 0xcb, 0x34, 0x32, 0xb5, 0x53, 0x67, 0x86, 0x1e, 0xb6, 0xad, 0xac, 0xe4, 0x37, 0xfc, 0x30, 0xfc, 0xcb, 0x4d, 0x00, 0x0d, 0xee, 0x0a, 0x20, 0x02, 0x26, 0x67, 0x97, 0xe1, 0x91, 0x40, 0xe2, 0xb7, 0x07, 0x04, 0xe0, 0xd3, 0xda, 0xe1, 0xee, 0xfe, 0x21, 0x3f, 0x11, 0x25, 0x7b, 0x5e, 0xd9, 0x34, 0x38, 0x35, 0x3d, 0xd7, 0x0d, 0x40, 0x03, 0xb0, 0x2a, 0x00, 0x40, 0x08, 0x22, 0x00, 0xe8, 0x6c, 0xad, 0x47, 0x6b, 0x63, 0x3d, 0x3e, 0x3c, 0xd0, 0x47, 0xa1, 0xa0, 0xef, 0xfc, 0xc6, 0x3d, 0xe7, 0x46, 0xa2, 0xb1, 0xf8, 0xee, 0x2a, 0xe3, 0x88, 0x47, 0x97, 0xd2, 0x9a, 0x4a, 0x1d, 0x7f, 0xf4, 0x38, 0xd9, 0x4b, 0x44, 0x65, 0xcb, 0x34, 0xca, 0xd2, 0xd5, 0x99, 0xcd, 0x97, 0x70, 0xf3, 0x5e, 0x92, 0xdf, 0xea, 0xde, 0x44, 0x6d, 0x8d, 0x21, 0x1c, 0xda, 0xfb, 0x9a, 0x6f, 0x64, 0x7c, 0x7a, 0xd7, 0x5f, 0x93, 0xb3, 0xd7, 0xa3, 0xb1, 0x78, 0x9d, 0x26, 0xa5, 0x04, 0x11, 0xcf, 0x29, 0x05, 0x21, 0x34, 0x22, 0xa2, 0xab, 0x00, 0x20, 0xab, 0xd6, 0xe8, 0xd2, 0xf7, 0xb7, 0xed, 0x99, 0xf9, 0x4c, 0xf2, 0xee, 0xd8, 0x54, 0xe7, 0x3b, 0x7d, 0x5d, 0xfe, 0x50, 0xd0, 0x8b, 0x8e, 0xb6, 0x08, 0xf9, 0xfc, 0x7e, 0x5f, 0x7a, 0x29, 0x8f, 0xf4, 0xb3, 0x2c, 0x2a, 0x8e, 0x22, 0x21, 0x04, 0x32, 0x0b, 0xe9, 0x02, 0x98, 0xcf, 0x02, 0x80, 0xa8, 0x8a, 0xa3, 0x99, 0xf9, 0xcc, 0x25, 0x6b, 0xf8, 0xe4, 0xf6, 0xe5, 0x6c, 0xfe, 0xfd, 0xef, 0x7e, 0xfa, 0x73, 0xe9, 0x4a, 0xe2, 0x4e, 0x6e, 0xec, 0xc9, 0x2c, 0xe6, 0x17, 0x73, 0xc8, 0xd9, 0x65, 0x30, 0x13, 0x9c, 0x72, 0xa9, 0x92, 0x59, 0x48, 0xdb, 0x60, 0xee, 0xb7, 0x4c, 0xe3, 0x21, 0x00, 0xb8, 0x57, 0xf8, 0x0a, 0xc0, 0x11, 0xcb, 0x34, 0xb8, 0xfa, 0x79, 0x74, 0x00, 0x7b, 0x89, 0xc4, 0x31, 0x80, 0xb7, 0x31, 0x73, 0x98, 0x88, 0xd2, 0x00, 0xfe, 0x60, 0xe6, 0xd3, 0x96, 0x69, 0xfc, 0xed, 0xca, 0xfd, 0x1f, 0xea, 0xba, 0x5e, 0xae, 0x3b, 0x4f, 0x3d, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/reload16.png000066400000000000000000000015711302634723100167110ustar00rootroot00000000000000‰PNG  IHDRóÿasBIT|dˆtEXtSoftwarewww.inkscape.org›î< IDAT8m’MhTWÇÿç¾û2ÎW&£“ÏÆ˜AEÓ5¦Ð¶PèbDJA,ņ‚;¡út#ØÍXAW%”V„’´¥R)%¯³¨­¶j¡1"š`Ô6óš˜dšib&™7™ysO΃YxàîÎùñ?¿s‰™áV4_ODg¼ÁÌ-D´Ð³ð£eåšÞSÈDcñwAôµ7”kÃA½9R¯®Á¶W‘úw!—ú/SóG–i|Åû| ˜ÑX|+ˆFC‘FŸÇãAȯ£5D$äE$äCÀ«#“-àJb´ÍïøÖè»íb©ŽkŸöœûÂë| 4Mع,”R‚*ë‚…í›;;¶´S®Aj„Äí ÕÓµA|6x½äTTDTW:¸jÛ‚2¯kn.DÚÚO8µ>•^ÞwíÖø½oÌ‘BÎ.B—ö¿ý²èhn ž˜ýBÓ×»ë²Ðä2€«–i¤,Óø99|rçôÜⱋ—¯a~qVjŽR®Kv¨—Z›>©x/t¶7u°jlK":úfÏæRGKMa¤n–Õ¾ðÃY¼¸¾dæ×ïŽÿS¼?1]$@€SQk°{…Uº«æý à(€ò ÀÒ2àœÿø= ”bÜT‰ßÇž‚ùUË42µSg†¶­¬ä7ü0üËM î &g—á‘@â·àÓÚáîþ!?%{^Ù485=× @°*@"èl­Gkc=><ÐG¡ ïüÆ=çF¢±øî*ãˆG—ÒšJô8ÙKDeË4ÊÒՙ͗pó^’ßêÞDm!Úûšod|z×_“³×£±x&¥Ï)!4"¢« «ÖèÒ÷·í™ùLòîØTç;}]þPÐ‹Ž¶ùü~_z)ô³,*Ž"!2 é˜Ï€¨Š£™ùÌ%køäöålþýï~úséJâNnìÉ,æsÈÙe0œr©’YHÛ`î·Lã!¸Wø ÀË4¸úyt{‰Ä1€·1s˜ˆÒþ`æÓ–iüíÊýêº^®;O=ÁIEND®B`‚fityk-1.3.1/wxgui/img/rename.xpm000066400000000000000000000013701302634723100165600ustar00rootroot00000000000000/* XPM */ static const char * rename_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " ", "....................... ", ". ", ". ", ". . . ", ". . ", ". . .... ... .... ", ". . . . . . . .", ". . . . .... . . .", ". . . . . . . . .", ". . . . . . . . .", ". . . . .... . . .", ". . . ", ". ", ". ", "....................... ", " ", " ", " ", " "}; fityk-1.3.1/wxgui/img/revert16.h000066400000000000000000000107311302634723100164130ustar00rootroot00000000000000static const unsigned char revert16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x02, 0x9c, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x85, 0x93, 0x5b, 0x48, 0x54, 0x51, 0x14, 0x86, 0xbf, 0xd4, 0xa6, 0x99, 0x8c, 0x2c, 0xc7, 0xac, 0x81, 0x72, 0xd2, 0xf2, 0x82, 0x95, 0x8a, 0x0f, 0x39, 0x15, 0x8c, 0x18, 0x5d, 0x84, 0x88, 0xca, 0x0b, 0x51, 0x69, 0x88, 0x89, 0xe0, 0x25, 0x12, 0x05, 0x09, 0x2b, 0x8c, 0x88, 0x88, 0x28, 0x0a, 0xc4, 0x32, 0x34, 0x48, 0xf0, 0x25, 0x04, 0x7d, 0x89, 0x92, 0x8a, 0x71, 0x84, 0x22, 0xd2, 0x22, 0x53, 0xd4, 0x02, 0x8b, 0x19, 0xc9, 0xe9, 0x8c, 0xa5, 0xe6, 0x05, 0x1c, 0xe7, 0x78, 0x5c, 0x3d, 0x98, 0x83, 0x66, 0xd4, 0x86, 0xff, 0xe1, 0x67, 0xaf, 0xf5, 0xed, 0xbd, 0xf6, 0xda, 0x0b, 0xe0, 0x20, 0x20, 0xf3, 0x2a, 0x2f, 0x4a, 0x96, 0x85, 0xfe, 0x3f, 0xca, 0x04, 0x90, 0x29, 0x8f, 0x57, 0x3a, 0x3e, 0x7f, 0x97, 0xec, 0xf4, 0x44, 0x19, 0x1d, 0x7c, 0x26, 0x80, 0x54, 0x54, 0x54, 0x88, 0xdb, 0xed, 0xf6, 0x69, 0x68, 0x68, 0x48, 0xdc, 0x6e, 0xb7, 0x8c, 0x8d, 0x8d, 0x49, 0x6b, 0x8f, 0x22, 0xad, 0x3d, 0xca, 0x3c, 0x04, 0xe9, 0x1f, 0x54, 0xe4, 0x64, 0x5a, 0x82, 0x8c, 0x0c, 0x3e, 0x97, 0x91, 0xde, 0xcb, 0x02, 0xc8, 0x16, 0xb3, 0x51, 0x62, 0x23, 0x43, 0x25, 0x78, 0xcd, 0x4a, 0x29, 0x29, 0x29, 0x91, 0xc6, 0xc6, 0x46, 0xb1, 0xdb, 0xed, 0xe2, 0x70, 0x38, 0xe4, 0xd6, 0x23, 0x9b, 0x64, 0x14, 0x5c, 0x14, 0x40, 0x02, 0x00, 0x2e, 0x14, 0x1e, 0xa0, 0xa6, 0xfa, 0x3a, 0x32, 0xf6, 0x0a, 0x80, 0x91, 0xde, 0xcb, 0x00, 0x7c, 0x71, 0x0e, 0xd3, 0xfe, 0x7e, 0x80, 0xc2, 0x8a, 0x3b, 0x4c, 0x4c, 0x4c, 0x50, 0x5b, 0x5b, 0x8b, 0xaa, 0xaa, 0x4c, 0x4d, 0xf5, 0xa0, 0xaa, 0xd3, 0x00, 0x04, 0x1c, 0xda, 0x17, 0xc3, 0xbd, 0xaa, 0xab, 0xc8, 0x78, 0x3b, 0x7f, 0xae, 0x08, 0xb3, 0x91, 0x08, 0xb3, 0x11, 0xd3, 0xfa, 0xd5, 0x1c, 0x3b, 0xf3, 0x80, 0xb8, 0xb8, 0x38, 0x72, 0x72, 0x72, 0xd0, 0xbc, 0xd3, 0x78, 0x67, 0xb4, 0x39, 0xc0, 0xec, 0xac, 0x50, 0x7f, 0x25, 0x83, 0xbd, 0x09, 0xba, 0x25, 0x00, 0x5d, 0xd0, 0x46, 0x56, 0xac, 0x0d, 0x23, 0x79, 0xd7, 0x6e, 0x1a, 0xaa, 0x8e, 0x93, 0x75, 0xf6, 0x1c, 0x56, 0xab, 0x75, 0x51, 0x4c, 0xc0, 0x53, 0xdb, 0x27, 0xbe, 0x0d, 0x99, 0x80, 0x61, 0x1f, 0x24, 0xbe, 0x78, 0x12, 0x80, 0xf2, 0xb4, 0x7e, 0x62, 0xc2, 0x9c, 0xec, 0xd9, 0x3d, 0x4a, 0xcc, 0x56, 0x0b, 0x00, 0x6d, 0x6d, 0x6d, 0xb0, 0x32, 0xcc, 0x07, 0xf0, 0x03, 0xd8, 0xb9, 0x37, 0x8b, 0x9a, 0xd6, 0x20, 0x5e, 0xf7, 0xa9, 0xbe, 0x8d, 0xb2, 0xb2, 0x32, 0x6e, 0x34, 0xcd, 0x60, 0xeb, 0xf4, 0xd2, 0xd7, 0xdd, 0x43, 0x84, 0xd9, 0x08, 0x80, 0xcb, 0xe5, 0x5a, 0x74, 0x03, 0x3f, 0x80, 0x82, 0xd2, 0xf3, 0xec, 0x3f, 0x55, 0xca, 0xb5, 0x66, 0x3d, 0x2d, 0x5d, 0xcb, 0x01, 0x98, 0xf4, 0x42, 0xc6, 0x89, 0xd3, 0x34, 0xd8, 0x35, 0x94, 0x91, 0x59, 0x5f, 0x82, 0xf3, 0xc7, 0xe4, 0x52, 0x00, 0x40, 0xf8, 0xb6, 0x24, 0x0e, 0xe7, 0x96, 0x73, 0xbf, 0x05, 0x02, 0x03, 0x75, 0xfc, 0x54, 0xfd, 0xd9, 0x91, 0x72, 0x14, 0x80, 0xd0, 0xa8, 0x5d, 0xdc, 0x7d, 0x38, 0xd7, 0xa1, 0x58, 0xcb, 0xbe, 0xc5, 0x6f, 0xb0, 0xd0, 0x84, 0x6f, 0xb7, 0x50, 0x7c, 0xfe, 0x36, 0xdd, 0x1d, 0x6d, 0xe4, 0x65, 0x1f, 0xc1, 0x60, 0x30, 0x50, 0x09, 0x24, 0x5a, 0x92, 0x48, 0x4b, 0xba, 0x8e, 0x71, 0xd3, 0x56, 0xcc, 0xab, 0x97, 0xe1, 0x1c, 0x97, 0xbf, 0x03, 0x3c, 0x1e, 0x0f, 0x29, 0xf1, 0x91, 0x24, 0xc5, 0x47, 0x92, 0x5e, 0x74, 0x09, 0xa5, 0xd3, 0xc6, 0x9b, 0xc7, 0x45, 0xd4, 0x37, 0xbe, 0x05, 0x40, 0x5d, 0x6e, 0xa0, 0xe5, 0xd5, 0x07, 0x92, 0x2d, 0x09, 0x4b, 0x4b, 0x98, 0x56, 0x55, 0x34, 0xef, 0xdc, 0xe7, 0xd0, 0xeb, 0xf5, 0x28, 0x9d, 0x36, 0x9a, 0xea, 0xb2, 0x78, 0xd7, 0xf5, 0x95, 0xca, 0x9b, 0x2f, 0xc8, 0xcd, 0xcd, 0xc5, 0x5f, 0xa7, 0xc7, 0xcf, 0xdf, 0x0f, 0x5d, 0xc0, 0x1f, 0x25, 0xd4, 0xd5, 0x54, 0xb3, 0x21, 0x2a, 0xc1, 0x97, 0x6c, 0x32, 0x99, 0x08, 0xdf, 0x99, 0x4a, 0x5a, 0x5e, 0x03, 0x00, 0xf9, 0xf9, 0xf9, 0x44, 0x47, 0x47, 0xd3, 0xdc, 0xfe, 0x71, 0xf1, 0xa9, 0x80, 0x3f, 0xd0, 0xdb, 0xf1, 0xb2, 0x35, 0x73, 0x43, 0x48, 0x08, 0x03, 0x2e, 0x05, 0xa3, 0x01, 0x34, 0x4d, 0x63, 0xf3, 0xba, 0x55, 0xa4, 0xa6, 0xa6, 0x62, 0xb5, 0x5a, 0xf1, 0x78, 0x3c, 0x68, 0x9a, 0x86, 0xe2, 0x1a, 0x45, 0x55, 0xa7, 0x08, 0x0e, 0x34, 0xf0, 0xc4, 0x66, 0x67, 0x42, 0x71, 0xf8, 0x40, 0x99, 0xbf, 0x27, 0xab, 0x1b, 0xe8, 0xff, 0xc7, 0xf8, 0x3a, 0x00, 0xe7, 0x02, 0x7f, 0xf0, 0x17, 0xa4, 0x91, 0x2b, 0xe5, 0x96, 0xd1, 0x3e, 0xac, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/revert16.png000066400000000000000000000013471302634723100167530ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“œIDATxÚ…“[HTQ†¿Ô¦™Œ,ǬrÒò‚•Š9Œ]„ˆÊ Qiˆ‰à% +Œˆˆ( Ä24Hð%}‰’Šq„"Ò"SÔ‹É錥æçx\=˜ƒfÔ†ÿág¯õí½öÚ à ó*/J–…þ?Ê)W:>—ìôD|&€TTTˆÛíöihhHÜn·ŒIk"­=Ê<éTädZ‚Œ >—‘ÞËȳQb#C%xÍJ)))‘ÆÆF±Ûíâp8äÖ#›d\@. ¦ú:2ö €‘ÞË|qÓþ~€ÂŠ;LLLP[[‹ªªLMõ ªÓÚýª«Èx;®³‘³ÓúÕ;󀸸8rrrмÓxg´9Àì¬P%ƒ½ º%]ÐFV¬ #y×nªŽ“uöV«uQLÀSÛ'¾ ™€a$¾x€ò´~bœìÙ=JÌV mmm°2Ìðع7‹šÖ ^÷©¾²²2n4Í`ëôÒ×ÝC„Ù€ËåZt?€‚Òóì?Uʵf=-]˘ôBƉÓ4Ø5”‘Y_‚óÇäR@ø¶$ç–s¿uüTýÙ‘r€Ð¨]Ü}8סX˾Åo°Ð„o·P|þ6ÝmäeÁ`0P $Z’HKºŽqÓVÌ«—á—¿<)ñ‘$ÅG’^t ¥ÓÆ›ÇEÔ7¾@]n åÕ’- KK˜VU4ïÜçÐëõ(6šê²x×õ•Ê›/ÈÍÍÅ_§ÇÏß]À%ÔÕT³!*Á—l2™ß™JZ^ùùùDGGÓÜþqñ©€?ÐÛñ²5sCH.£4McóºU¤¦¦bµZñx¬IEND®B`‚fityk-1.3.1/wxgui/img/right_pane.xpm000066400000000000000000000016611302634723100174340ustar00rootroot00000000000000/* XPM */ static const char * right_pane_xpm[] = { "24 24 14 1", " c None", ". c #000000", "+ c #565248", "@ c #ABABAB", "# c #D3D3D3", "$ c #A2A2A2", "% c #C8C8C8", "& c #A1A1A1", "* c #C7C7C7", "= c #8C8C8C", "- c #AAAAAA", "; c #ADADAD", "> c #ACACAC", ", c #C5C5C5", " ", " ..................... ", " .+++++++++++++.@####. ", " .+ +.$%%%#. ", " .+ +.$$$$@. ", " .+ +.$%%%#. ", " .+ +.$$$$@. ", " .+ +.$%%%#. ", " .+ +.$$$$@. ", " .+ +.$%%%#. ", " .+ +.$$$$@. ", " .+ +.$%%%#. ", " .+ +.$$$$@. ", " .+ +.$%%%#. ", " .+ +.$$$$@. ", " .+ +.$%%%#. ", " .+ +.$$$$@. ", " .+ +.&***#. ", " .+ +.&***#. ", " .+ +.&***#. ", " .+++++++++++++.=-;>,. ", " ..................... ", " ", " "}; fityk-1.3.1/wxgui/img/rubik32.h000066400000000000000000000024421302634723100162160ustar00rootroot00000000000000static const unsigned char rubik32_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20, 0x08,0x06,0x00,0x00,0x00,0x73,0x7a,0x7a,0xf4,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff, 0xa0,0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73, 0x00,0x00,0x00,0xec,0x00,0x00,0x00,0xec,0x01,0x79,0x28,0x71, 0xbd,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd9,0x0b, 0x0d,0x15,0x2f,0x16,0x80,0x7a,0xe2,0x2c,0x00,0x00,0x00,0x79, 0x49,0x44,0x41,0x54,0x58,0xc3,0x63,0x74,0x71,0x71,0xf9,0xcf, 0x30,0x80,0x80,0x89,0x61,0x80,0x01,0x0b,0x8c,0xb1,0x7b,0xf7, 0x6e,0xbc,0x0a,0x5d,0x5d,0x5d,0x19,0x18,0x18,0x18,0x18,0x26, 0x9c,0x3b,0x87,0x57,0x5d,0x81,0x91,0x11,0x49,0xe6,0x0d,0x78, 0x08,0x8c,0x3a,0x60,0xd4,0x01,0xa3,0x0e,0x60,0x1c,0x2d,0x09, 0x61,0x8c,0xa5,0x2b,0x2e,0xe0,0x55,0x18,0x1d,0x61,0xc0,0xc0, 0xc0,0xc0,0xc0,0xb0,0xc2,0x01,0xbf,0xba,0x88,0x03,0xa4,0xa9, 0x1b,0x4d,0x84,0xa3,0x0e,0x18,0x75,0xc0,0x68,0x49,0x38,0x78, 0x4a,0x42,0x62,0x4b,0x2e,0x62,0xdb,0x84,0xc4,0x96,0xac,0xa3, 0x89,0x70,0xd4,0x01,0xa3,0x0e,0x18,0x2d,0x09,0x07,0x3c,0x04, 0x00,0x64,0xd7,0x22,0x6f,0x2d,0xc5,0x23,0x0b,0x00,0x00,0x00, 0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/rubik32.png000066400000000000000000000003711302634723100165520ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎébKGDÿÿÿ ½§“ pHYsììy(q½tIMEÙ /€zâ,yIDATXÃctqqùÏ0€€‰a€ Œ±{÷n¼ ]]]&œ;‡W]‘Iæ xŒ:`Ô£`- aŒ¥+.àUaÀÀÀÀÀ°Â¿ºˆ¤©M„£uÀhI8xJBbK.bÛ„Ä–¬£‰pÔ£- <d×"o-Å# IEND®B`‚fityk-1.3.1/wxgui/img/run16.h000066400000000000000000000072471302634723100157200ustar00rootroot00000000000000static const unsigned char run16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0d, 0xd7, 0x00, 0x00, 0x0d, 0xd7, 0x01, 0x42, 0x28, 0x9b, 0x78, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd6, 0x05, 0x15, 0x0e, 0x24, 0x08, 0x52, 0x39, 0x39, 0xd1, 0x00, 0x00, 0x01, 0xee, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0xb5, 0x92, 0xcf, 0x4e, 0x13, 0x51, 0x14, 0xc6, 0xbf, 0x3b, 0xf7, 0x1a, 0xc3, 0x62, 0x36, 0x36, 0x3a, 0x31, 0xc5, 0xf7, 0xc0, 0x76, 0x05, 0x54, 0x08, 0x8d, 0x71, 0x03, 0x08, 0x51, 0x63, 0x5c, 0x18, 0x7d, 0x00, 0x03, 0x29, 0x6d, 0x98, 0x4c, 0xa6, 0x19, 0xdb, 0xc2, 0x5b, 0xf0, 0x47, 0xd0, 0x18, 0x20, 0xa5, 0x29, 0xb1, 0x65, 0xdb, 0x4a, 0xa2, 0xa0, 0xbe, 0x01, 0x0d, 0x33, 0x81, 0xd6, 0x74, 0x42, 0x3a, 0x8b, 0x19, 0xd3, 0x3b, 0xf7, 0xba, 0xaa, 0x71, 0x61, 0x64, 0x12, 0xe3, 0x59, 0x7d, 0x8b, 0x73, 0x72, 0xbe, 0xf3, 0xfd, 0x0e, 0x41, 0xc4, 0x2a, 0xae, 0x58, 0x72, 0xa0, 0x33, 0x8b, 0x39, 0x32, 0xd0, 0x4a, 0x94, 0xe1, 0x52, 0xc9, 0x52, 0x6c, 0xdb, 0xc1, 0x8b, 0xe7, 0x2f, 0x61, 0xdb, 0x0e, 0x4a, 0x25, 0x4b, 0x89, 0xba, 0x18, 0x85, 0xd5, 0x3c, 0x19, 0x1b, 0x1f, 0x15, 0x3d, 0xaf, 0x27, 0x85, 0x10, 0xb2, 0xe7, 0xf5, 0xe4, 0xd8, 0xf8, 0xa8, 0x28, 0xac, 0xe6, 0x09, 0x00, 0x90, 0xab, 0x6c, 0xdb, 0xb6, 0x03, 0x2b, 0x5f, 0xc0, 0xe1, 0x61, 0x9d, 0x37, 0x3f, 0x36, 0x64, 0xe2, 0x6e, 0x92, 0xa4, 0x52, 0xf7, 0x58, 0x6e, 0x79, 0x09, 0xc3, 0xc3, 0xf1, 0xab, 0x4f, 0x30, 0x0d, 0x13, 0xaa, 0xaa, 0xa2, 0x79, 0xd4, 0xc0, 0xad, 0x9b, 0xb1, 0xeb, 0xcd, 0xa3, 0x06, 0x54, 0x55, 0x85, 0x69, 0x98, 0xd1, 0x32, 0xd0, 0x0d, 0x1d, 0x9e, 0xe7, 0x21, 0x31, 0x92, 0x44, 0xe7, 0x7b, 0xf7, 0x47, 0x62, 0x24, 0x09, 0xcf, 0xf3, 0xa0, 0x1b, 0xfa, 0x7f, 0xc8, 0xe0, 0x4f, 0xa8, 0x1e, 0xce, 0xcf, 0x48, 0x29, 0x25, 0x34, 0x4d, 0x83, 0x69, 0x98, 0xd0, 0x0d, 0x1d, 0xed, 0x76, 0x1b, 0x84, 0x10, 0xbc, 0xdb, 0x7e, 0x4f, 0xc8, 0xef, 0xa8, 0xce, 0x1c, 0x27, 0x1c, 0x34, 0xdd, 0x89, 0xc7, 0xe9, 0xe7, 0x93, 0x93, 0x30, 0x9b, 0xc9, 0x21, 0x16, 0xbb, 0x81, 0x37, 0xdb, 0x9b, 0xbf, 0x16, 0x3d, 0x9a, 0x7f, 0x8c, 0x6e, 0xd7, 0xc5, 0xeb, 0xa2, 0xf5, 0x77, 0x9b, 0xb3, 0x73, 0xd3, 0xa2, 0xd5, 0x3a, 0x95, 0x41, 0x10, 0x48, 0xce, 0xfb, 0xd2, 0xf7, 0x7d, 0xc9, 0x79, 0x5f, 0x06, 0x41, 0x20, 0x5b, 0xad, 0x53, 0x39, 0x3b, 0x37, 0x2d, 0x94, 0xe2, 0x8a, 0x25, 0x9d, 0xb3, 0x73, 0xb1, 0xbb, 0xb3, 0x47, 0xea, 0xb5, 0x1a, 0x5f, 0x58, 0x7c, 0xd5, 0xaf, 0xd7, 0x6a, 0x7c, 0x77, 0x67, 0x8f, 0x68, 0x9a, 0x46, 0xb6, 0xde, 0x6e, 0x82, 0x52, 0x8a, 0xf5, 0x8d, 0x35, 0xff, 0xe9, 0xb3, 0x27, 0x62, 0x7d, 0x63, 0xcd, 0xa7, 0x94, 0xe2, 0xf8, 0xf8, 0x53, 0x9f, 0x32, 0xfa, 0x41, 0x89, 0x82, 0x8a, 0x73, 0x8e, 0xea, 0x41, 0x75, 0x08, 0x42, 0x61, 0xd5, 0x83, 0xea, 0x10, 0xe7, 0x1c, 0x9a, 0x76, 0xfb, 0x5a, 0xc8, 0xc3, 0xb4, 0x12, 0x05, 0x15, 0x63, 0x0c, 0xe9, 0xa9, 0xb4, 0x0f, 0x45, 0xf0, 0xf4, 0x54, 0xda, 0x67, 0x8c, 0xa1, 0xdd, 0x3e, 0xef, 0x53, 0x46, 0xab, 0xff, 0x9e, 0x01, 0x00, 0x2c, 0x2d, 0x2c, 0xcb, 0xc9, 0x89, 0x14, 0xcd, 0xe6, 0x32, 0xb8, 0xbc, 0x74, 0x91, 0xcd, 0x65, 0x30, 0x39, 0x91, 0xa2, 0x00, 0x88, 0xeb, 0xba, 0xe8, 0x74, 0x2e, 0xb0, 0x5f, 0x29, 0xf3, 0xaf, 0xdf, 0xbe, 0x84, 0xfb, 0x95, 0x32, 0xef, 0x74, 0x2e, 0xe0, 0xba, 0x2e, 0x00, 0x90, 0xc8, 0x7f, 0x40, 0x19, 0xab, 0x84, 0x9c, 0x3f, 0xa0, 0x8c, 0x95, 0x43, 0xce, 0xef, 0x13, 0x42, 0xa0, 0x80, 0x28, 0x3f, 0x01, 0x3f, 0x17, 0x5e, 0x0b, 0x35, 0xf1, 0x47, 0x02, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/run16.png000066400000000000000000000011411302634723100162400ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÖ$R99ÑîIDAT8˵’ÏNQÆ¿;÷Ãb66:1Å÷ÀvTqQc\})m˜L¦ÛÂ[ðGÐ ¥)±eÛJ¢ ¾ 3ÖtB:‹Ó;÷ºªqadãY}‹sr¾óýAÄ*®Xr 3‹92ÐJ”áRÉRlÛÁ‹ç/aÛJ%K‰º…Õ<=¯'…²çõ䨸¨(¬æ «lÛ¶+_Àáa7?6dân’¤R÷Xny ÃÃñ«O0 ªª¢yÔÀ­›±ëÍ£TU…i˜Ñ2Ð žç!1’Dç{÷Gb$ Ïó úÈàO¨ÎÏH)%4Mƒi˜Ð ív„¼Û~OÈï¨Î'4݉Çéç““0›É!»7Û›¿=šŒn×Åë¢õw›³sÓ¢Õ:•AHÎûÒ÷}Éy_A [­S9;7-”âŠ%³s±»³Gêµ_X|Õ¯×j|wghšF¶Þn‚RŠõ5ÿé³'b}cͧ”âøøSŸ2úA‰‚ŠsŽêAuBaÕƒêçšvûZÈôc é©´EðôTÚgŒ¡Ý>ïSF«ÿž,-,ËɉÍæ2¸¼t‘Íe09‘¢ˆëºèt.°_)ó¯ß¾„û•2ït.àº.È@«„œ? Œ•CÎïB €(??^ 5ñGIEND®B`‚fityk-1.3.1/wxgui/img/run32.h000066400000000000000000000307041302634723100157100ustar00rootroot00000000000000static const unsigned char run32_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20, 0x08,0x06,0x00,0x00,0x00,0x73,0x7a,0x7a,0xf4,0x00,0x00,0x00, 0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff,0xa0, 0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00, 0x00,0x0d,0xd7,0x00,0x00,0x0d,0xd7,0x01,0x42,0x28,0x9b,0x78, 0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd6,0x07,0x0c, 0x16,0x01,0x39,0xae,0xf0,0x50,0xb1,0x00,0x00,0x09,0x4e,0x49, 0x44,0x41,0x54,0x58,0xc3,0xc5,0x56,0x7b,0x70,0x54,0xd5,0x19, 0xff,0x9d,0x7b,0xee,0xdd,0xbb,0x9b,0xcd,0x66,0xf3,0xce,0x6e, 0x5e,0x64,0x13,0xc3,0x2b,0x90,0x90,0xb7,0x06,0x30,0x09,0xa0, 0x14,0xa6,0x3e,0x21,0x8a,0xe3,0xa3,0xad,0xa2,0xce,0x94,0x29, 0x3a,0x5a,0x94,0xaa,0x58,0x99,0x96,0x29,0xe2,0x54,0x9d,0x8a, 0x8f,0xa2,0x9d,0xe9,0xa8,0xb5,0x20,0xca,0x63,0x10,0x10,0x23, 0x46,0x34,0x04,0x42,0x48,0x10,0x50,0x30,0x4d,0xb2,0x9b,0x6c, 0xb2,0xaf,0x64,0xb3,0x49,0x36,0xbb,0x7b,0x77,0xf7,0xde,0xdd, 0xd3,0x3f,0xdc,0xc4,0x34,0x15,0xc4,0x8e,0x4e,0xbf,0x99,0x6f, 0xee,0x9d,0x73,0xbe,0x7b,0x7e,0xbf,0xf3,0x9d,0xef,0xfb,0xdd, 0x03,0xfc,0x9f,0x8d,0x4c,0x1f,0x58,0xb3,0xa6,0x21,0x23,0x0a, 0xe6,0x34,0xe5,0x99,0x30,0x23,0xcf,0xd4,0xd6,0xd4,0x74,0xf4, 0xee,0xfa,0xfa,0xa5,0x6f,0xf5,0xf5,0x5a,0x2a,0x2d,0xbd,0x16, 0x70,0x20,0x59,0x3b,0x77,0xee,0xb6,0xff,0x64,0x8c,0x1a,0x6e, 0x5f,0xc5,0xce,0x9c,0xe9,0x60,0x56,0x6b,0x2f,0xdb,0xbb,0xef, 0x7d,0xf9,0xc4,0xc9,0x16,0x65,0xef,0xbe,0xf7,0x65,0xab,0xb5, 0x97,0x9d,0x39,0xd3,0xc1,0x1a,0x6e,0x5f,0xc5,0x7e,0x4c,0x3c, 0x7e,0xfa,0x40,0xbe,0x29,0x9f,0x25,0x27,0x27,0x93,0xf4,0x74, 0x03,0x6e,0xf8,0xf9,0x8d,0xbc,0x2c,0x2b,0x10,0x2a,0x2a,0xa1, 0x28,0x11,0x30,0xf6,0xcd,0xfc,0x8f,0x49,0x80,0x9b,0x3e,0x30, 0x23,0x6f,0x46,0x47,0x7b,0x7b,0x9b,0x4c,0x29,0xc5,0x5b,0x6f, 0xbf,0x29,0xdd,0xff,0xe0,0x7d,0xc1,0xb7,0xde,0x7e,0x53,0xa2, 0x94,0xa2,0xbd,0xbd,0x4d,0x9e,0x91,0x37,0xa3,0xe3,0x27,0x25, 0xd0,0xd4,0xd4,0xb4,0x36,0x23,0xc3,0x28,0x28,0x8a,0x82,0x43, 0x87,0x0f,0x69,0x42,0x92,0x7c,0xdd,0xa1,0xc3,0x87,0x34,0x8a, 0xa2,0x20,0x23,0xc3,0x28,0x34,0x35,0x35,0xad,0x9b,0x5b,0x5a, 0x3a,0xa3,0xa4,0xb2,0xfa,0xaf,0x55,0x0b,0x17,0xf7,0x57,0xd4, 0x2c,0x66,0xc5,0xe5,0xe5,0xb7,0xfd,0xc7,0x31,0x36,0x34,0xd0, 0x92,0xf2,0xab,0xcb,0xff,0x27,0x02,0xf5,0xf5,0xf5,0x6f,0xb8, 0x5c,0x0e,0x99,0xe7,0x79,0xac,0x5c,0xb1,0x52,0x12,0x35,0x42, 0xe3,0xca,0x15,0x2b,0x25,0x9e,0xe7,0xe1,0x72,0x39,0xe4,0x6b, 0xaf,0xad,0x7d,0x55,0xa5,0x52,0xf7,0xde,0xfb,0xcb,0x7b,0x1e, 0xd8,0xf1,0xea,0xf6,0xec,0x2d,0x9b,0x9f,0x86,0x4a,0xa5,0x7e, 0x6c,0xea,0x1a,0x5d,0x7d,0xd6,0x9d,0x82,0xc8,0x9f,0xae,0x5a, 0xb4,0xd8,0x55,0x54,0x59,0xb9,0xf4,0x07,0xa5,0xe4,0xf1,0x8d, 0x1b,0xa2,0x7d,0x7d,0xbd,0x2c,0x18,0x0c,0x32,0x45,0x91,0x99, 0x24,0x49,0x4c,0x51,0x64,0x16,0x0c,0x06,0x59,0x5f,0x5f,0x2f, 0x7b,0x7c,0xe3,0x86,0x68,0x4d,0x5d,0x5d,0xc4,0x33,0xe2,0x61, 0x36,0xfb,0x00,0x73,0x3a,0x9d,0xac,0xa6,0x6e,0x49,0x64,0x62, 0x33,0xf3,0x2a,0x2a,0xea,0x96,0xfc,0x6c,0x05,0x1b,0x1c,0x1a, 0x64,0xad,0x6d,0xa7,0xd8,0x92,0xe5,0x2b,0x58,0x49,0x65,0xd5, 0x0b,0x57,0x5c,0x84,0x66,0x8b,0x99,0x78,0x3c,0x1e,0x10,0x02, 0xb4,0x77,0xb4,0x2b,0x06,0x83,0x91,0x38,0x9d,0x0e,0x56,0x5e, 0x56,0xce,0x7b,0x3c,0x1e,0x98,0x2d,0x66,0x02,0xc0,0x63,0xee, 0x31,0xa7,0x28,0xd1,0x30,0xb4,0x71,0x3a,0x2c,0xad,0xaf,0xe3, 0x14,0x45,0x56,0x28,0xa5,0xa1,0x48,0x24,0xa2,0xfa,0xdd,0x86, 0x47,0x31,0x3c,0x3c,0x8c,0x9c,0xec,0x6c,0x3c,0xfc,0x9b,0x5f, 0xe3,0x99,0x2d,0x5b,0xcb,0x7f,0x88,0x0e,0xcc,0x88,0x82,0xf5, 0x4e,0xe8,0xc0,0x3f,0x77,0xef,0xfe,0x88,0xa7,0xfc,0xaf,0x52, 0x12,0x75,0x99,0x1c,0xc7,0xc1,0xe7,0x93,0xd6,0xbb,0x86,0x47, 0xb7,0x3d,0xf6,0xc8,0x43,0xea,0xb9,0x73,0x66,0x43,0xaf,0xd7, 0x43,0x10,0x04,0xf0,0x94,0x87,0x14,0x94,0xe0,0x74,0x39,0x01, 0x06,0x0c,0xba,0x5d,0x28,0xcc,0x9f,0x85,0xf5,0x8f,0xfc,0x16, 0x4e,0xf7,0x60,0xde,0xd9,0xd6,0xd6,0xbe,0x2b,0x22,0x30,0xd5, 0xe6,0x97,0x55,0x55,0x25,0xe8,0xe3,0x5b,0x6f,0xbd,0xe9,0x46, 0xec,0xdd,0xbf,0x9f,0x29,0x4a,0xa4,0x13,0x20,0x33,0x5f,0xfc, 0xf3,0x36,0x6e,0xde,0xdc,0xb9,0x70,0x0f,0xbb,0xd1,0x3f,0x60, 0x85,0x2c,0x87,0x21,0x2b,0x32,0xb4,0x5a,0x2d,0xd2,0x53,0x33, 0xa0,0xd7,0xeb,0x61,0xb3,0xdb,0xd0,0xd3,0x63,0xc1,0xd6,0xe7, 0x5e,0xe8,0x6c,0x3f,0xd9,0x32,0xfb,0x8a,0x33,0x30,0xd5,0x2a, 0x6b,0x16,0xf5,0x3f,0xf5,0xe4,0xc6,0xec,0x25,0xb5,0xb5,0x18, 0x1a,0x1a,0xc2,0xc1,0x0f,0x3f,0xc4,0xd2,0xba,0x5a,0x18,0x0c, 0x46,0xb4,0x9e,0x6a,0x81,0xcf,0xef,0x03,0xc7,0x71,0x31,0x27, 0x93,0xef,0xa2,0x28,0xa2,0x20,0xbf,0x10,0x01,0x7f,0x00,0xeb, 0xd6,0x3f,0xc2,0x46,0x47,0x47,0xae,0xf9,0xe2,0xf4,0xe9,0x56, 0x00,0x28,0x2e,0x2e,0xd6,0x9e,0x3b,0x77,0xce,0xff,0xbd,0x04, 0x4a,0x4a,0x6a,0x8a,0x55,0x5a,0xee,0x6c,0xe3,0xe1,0x0f,0x30, 0xec,0x19,0x82,0xdd,0x61,0x47,0xa2,0x2e,0x09,0x79,0x26,0x13, 0x3e,0x3d,0x76,0x14,0xa1,0x70,0x68,0x0a,0xf8,0x7f,0x93,0xe0, 0x79,0x1e,0x39,0x59,0xb9,0xf0,0xf9,0xfc,0x78,0x60,0xdd,0x43, 0xe1,0x28,0x98,0x93,0xe7,0xf8,0xcc,0x70,0x38,0xc4,0x2b,0xd1, 0x48,0xdd,0xf9,0xb6,0xb6,0x63,0x00,0x40,0x2f,0x45,0xc0,0x64, 0xca,0xf2,0x32,0x82,0x45,0x4d,0xc7,0x3e,0xcb,0xab,0xaa,0xac, 0x00,0x4f,0x79,0xcc,0x99,0x3d,0x07,0xcd,0x2d,0xc7,0x20,0x05, 0x25,0x50,0x9e,0x82,0xa7,0x3c,0x74,0x3a,0x1d,0x92,0x93,0x53, 0x90,0x94,0x98,0x0c,0x4d,0x5c,0x1c,0x22,0x91,0x08,0x08,0x07, 0x70,0x84,0x43,0x20,0x18,0x40,0x46,0xba,0x01,0x59,0x59,0x46, 0xba,0xac,0xb6,0x4e,0x7f,0xd7,0x1d,0x6b,0xb8,0xfc,0xfc,0x7c, 0x9c,0x38,0xd1,0x9a,0xe4,0xb2,0xdb,0x76,0x5e,0x96,0xc0,0xc0, 0xc0,0x80,0x62,0xef,0xef,0xff,0xbb,0xa0,0xd6,0x5e,0x68,0x3c, 0xfa,0xc9,0xea,0x15,0xcb,0xaf,0x23,0x94,0x52,0xf4,0x59,0x2d, 0xa0,0x94,0x82,0xe7,0x79,0xa4,0xa5,0xa6,0x83,0x01,0xd8,0xf5, 0xee,0x1e,0xf4,0x59,0xad,0x48,0x4d,0x4d,0xc1,0xcc,0xc2,0x59, 0x90,0x82,0x01,0x00,0x0c,0x1c,0xc7,0x81,0xf2,0x14,0x09,0x09, 0x09,0x18,0x1e,0x76,0x83,0xa7,0x14,0x39,0xd9,0xd9,0xf8,0xe8, 0xe3,0x8f,0x8d,0x03,0xd6,0xbe,0xad,0xdf,0x29,0x44,0xd3,0xed, 0x7c,0xfb,0xa9,0xdd,0x8c,0xb1,0xb0,0xc1,0x60,0x80,0xc3,0x69, 0x03,0xa5,0x14,0x94,0x52,0x24,0x26,0x26,0xc1,0x1f,0x90,0xb0, 0x61,0xe3,0x26,0xa5,0xe9,0x58,0xf3,0xba,0x3d,0xfb,0x0f,0xdc, 0xfb,0xd4,0xa6,0x3f,0x4a,0x03,0x76,0x1b,0x72,0xb2,0x72,0x27, 0xe3,0x82,0xa1,0x20,0x12,0x74,0xf1,0x88,0xd3,0xc4,0x41,0x1b, 0xa7,0x85,0xcd,0xee,0x40,0x58,0x96,0xf5,0x75,0x75,0x75,0xfc, 0x77,0xea,0xc0,0x25,0x4c,0xa5,0x8d,0xd3,0xc2,0x3b,0xee,0x05, 0xa5,0x14,0x1c,0xc7,0x21,0x51,0x9f,0x84,0xfd,0x07,0x0e,0x42, 0x92,0xc2,0xeb,0xce,0x9d,0x3e,0xb5,0x03,0x00,0x4a,0xca,0xaa, 0x6c,0x9b,0xff,0xb0,0xf5,0xc8,0xfe,0xdd,0xbb,0x60,0x73,0xf4, 0x83,0xe3,0x38,0x10,0x02,0x08,0x2a,0x01,0xed,0x67,0xce,0xa2, 0xf1,0xe3,0x4f,0x58,0x30,0x24,0x5d,0x08,0xcb,0xd1,0x17,0x3e, 0x3d,0xf9,0x69,0xe4,0xb2,0x04,0x8a,0xcb,0xaa,0x6a,0x38,0x8a, 0xa7,0xd4,0x6a,0xcd,0xb2,0xb4,0xd4,0x14,0x12,0x0a,0x87,0x20, 0xaa,0x54,0x90,0xe5,0x30,0x38,0x8e,0x83,0x5a,0x54,0x63,0xc8, 0xed,0x06,0x89,0x30,0x69,0xf2,0x23,0x81,0x04,0x12,0xf5,0x7a, 0x08,0x82,0x0a,0x82,0xa0,0x02,0xc0,0x40,0x08,0x01,0xe5,0x78, 0x7c,0x72,0xec,0x73,0x38,0x07,0xac,0x9a,0xee,0xee,0xee,0xd0, 0x65,0x95,0x70,0x72,0x2d,0x15,0x7f,0xbc,0x61,0xf5,0xad,0xa8, 0x5d,0xbc,0x10,0x94,0xe3,0x10,0x0a,0x85,0xa0,0x12,0x45,0xd0, 0xa0,0x04,0x8e,0xe3,0xa0,0x44,0x14,0xdc,0x75,0xc7,0xed,0x38, 0xde,0x72,0xea,0xf5,0xf9,0x15,0x15,0x0e,0x12,0xa5,0x21,0x81, 0x17,0x0e,0xdc,0x73,0xe7,0x1a,0x04,0x24,0x3f,0x38,0x42,0x40, 0x38,0x0e,0x02,0x2f,0x40,0x56,0x64,0x84,0x43,0xe1,0xc8,0x74, 0xf0,0xcb,0xd6,0x00,0xcf,0x53,0x67,0x65,0x79,0x19,0xe2,0xb5, 0x71,0x70,0x0d,0x3a,0x31,0x3a,0x3a,0x82,0xe4,0xa4,0x14,0x50, 0x9e,0x82,0xf2,0x14,0xa3,0x63,0x1e,0x14,0x14,0x5c,0x85,0xe7, 0xb7,0x6d,0x11,0x2b,0x4a,0x4b,0x1b,0xd3,0xd2,0x93,0x3f,0x7b, 0xfe,0xd9,0x2d,0xfa,0xeb,0x97,0x5d,0x07,0xe7,0xa0,0xed,0x9b, 0x38,0x4a,0x21,0xa8,0x54,0x18,0x1a,0x1a,0x82,0x1c,0x91,0xb9, 0x92,0x8a,0x8a,0x9b,0xa6,0xe3,0x5c,0xaa,0x0b,0x48,0x6a,0x9a, 0x61,0x9e,0x5e,0x9f,0xb0,0x60,0x41,0x49,0x09,0x82,0xc1,0x10, 0xac,0xfd,0xfd,0x98,0x3d,0x73,0x36,0xbc,0x3e,0xef,0x64,0x90, 0xcf,0xef,0xc3,0xcc,0xc2,0x59,0xb8,0x6d,0xd5,0x6a,0xdc,0x73, 0xd7,0x9d,0x48,0x4d,0x49,0xc5,0x80,0xd3,0x8a,0x60,0x28,0x08, 0x42,0x08,0x08,0x08,0x44,0x51,0x0d,0x6b,0x9f,0x15,0x25,0xf3, 0xe7,0x91,0x2e,0xb3,0x65,0x4d,0x62,0x52,0xea,0x42,0xad,0x46, 0xfd,0xae,0xc7,0xe3,0x89,0x5e,0x4a,0x88,0x08,0x00,0x52,0x58, 0x5a,0x3a,0x4b,0xaf,0xd1,0x5e,0x10,0x78,0x1e,0x8c,0x30,0x49, 0x0e,0x2b,0xc2,0x2b,0x7f,0x79,0x9e,0xcf,0xc8,0x48,0x87,0xd3, 0x65,0x03,0x08,0x26,0x45,0x67,0xa2,0x30,0x09,0x21,0x20,0xe4, 0xdb,0x25,0x35,0xea,0x38,0xb8,0x87,0xdc,0x38,0x79,0xe2,0x24, 0xb2,0xb2,0x73,0x90,0x69,0xcc,0xc2,0xc6,0xa7,0x37,0x63,0x74, 0x68,0x64,0xf5,0xf9,0xb3,0x6d,0x7b,0x01,0x30,0x32,0xe5,0x27, 0x94,0x14,0x61,0x51,0x4f,0xbe,0x29,0x1f,0x26,0x93,0xe9,0xf3, 0x0f,0x0e,0x1e,0xdc,0x54,0x7d,0xf5,0xd5,0x2f,0x8f,0x8f,0x8d, 0x15,0x59,0x7a,0x2d,0x18,0x1c,0x74,0xff,0x3e,0x4a,0x84,0x67, 0x5e,0x7b,0xf9,0x45,0xa2,0x4b,0xd0,0xc1,0xed,0x76,0x81,0xc5, 0x7a,0x7d,0xc2,0xbf,0xdd,0x01,0x81,0x28,0x8a,0xf0,0xfb,0x03, 0x38,0x7c,0xe8,0x23,0xcc,0x9d,0x33,0x07,0x3a,0x9d,0x0e,0xfe, 0x40,0x00,0x9b,0xb7,0xfc,0xc9,0x7f,0xba,0xa5,0x25,0x15,0x40, 0x04,0x40,0x84,0x4e,0x05,0xbf,0xff,0x81,0xb5,0x28,0x2d,0x5f, 0x80,0xa0,0x24,0x65,0x5d,0x7f,0xfd,0xf2,0x5f,0x88,0x2a,0x3e, 0xa5,0x66,0x71,0x0d,0x57,0x54,0x54,0x84,0xce,0xaf,0xbf,0xae, 0x77,0xb8,0xdc,0x16,0xcf,0xb0,0x27,0xa9,0xa0,0xc0,0x04,0x83, 0x21,0x13,0x3c,0xcf,0x03,0x84,0x4c,0x56,0x3b,0xc7,0x51,0xa8, 0x04,0x15,0x44,0x51,0x0d,0x8f,0x67,0x14,0x9b,0x9e,0xde,0x82, 0x96,0xd6,0x36,0x73,0x5b,0x7b,0x47,0xa2,0xa8,0x56,0x93,0xf7, 0xf6,0xec,0xc3,0xa0,0xcb,0xbd,0x7e,0x78,0xd0,0x75,0x11,0x00, 0x03,0xc0,0x78,0x00,0x60,0x1c,0x53,0xe5,0xe7,0xe6,0x33,0xbd, 0x3e,0x81,0x14,0x16,0xcc,0x42,0xf1,0xdc,0x05,0xbc,0x2f,0xe0, 0x43,0x75,0x65,0x35,0xa4,0x90,0x84,0xae,0xee,0xaf,0x11,0x8d, 0x46,0x99,0x4a,0x54,0x99,0x6a,0xaf,0x5d,0x84,0x2f,0xcf,0x9d, 0x83,0xc3,0xee,0x40,0x5a,0x7a,0x1a,0xd2,0x52,0x53,0x21,0xc6, 0xab,0x20,0xcb,0x0a,0x42,0xe1,0x20,0xdc,0x43,0xc3,0xf8,0x57, 0x97,0x19,0x2f,0xbd,0xb2,0x23,0x3a,0xe8,0xb4,0x3f,0xd1,0x6f, 0xb1,0x34,0xeb,0x92,0x92,0x74,0xe3,0x63,0xde,0x27,0x19,0x21, 0xe3,0x9d,0x5f,0x9e,0x3d,0x0c,0x40,0x05,0x20,0x0a,0x20,0xca, 0x03,0xc0,0xae,0x77,0xde,0x73,0xbd,0xf2,0xda,0xf6,0x8e,0x9e, 0x6e,0x73,0xf1,0xfc,0xa2,0x05,0xc2,0x8e,0x37,0x5e,0x0b,0xb6, 0xb6,0x9e,0x22,0xd5,0xd5,0x55,0xec,0xfe,0xb5,0x0f,0xaa,0xbb, 0xbb,0x7a,0x14,0xbb,0x6b,0x78,0x64,0x41,0x71,0x49,0x5a,0x76, 0x76,0x16,0xc0,0xa2,0x08,0x05,0xc3,0x78,0xf8,0xd1,0xc7,0xc1, 0xa2,0x2c,0x22,0x88,0x6a,0x9a,0x6d,0x34,0xe0,0xe6,0x1b,0x56, 0xc2,0xe1,0xb2,0x23,0x51,0x9f,0x0c,0x8e,0x40,0xea,0xb7,0x58, 0xce,0x02,0xd0,0x8c,0x8f,0x8c,0x48,0xe7,0x47,0xda,0x37,0x00, 0x90,0x62,0xe0,0x72,0xcc,0x39,0x2e,0x56,0x74,0xdc,0x91,0x23, 0x47,0x1e,0x32,0x1a,0x32,0x05,0x7f,0xc0,0x8f,0xe6,0xe6,0xe3, 0x6a,0x6b,0xef,0xc0,0xdd,0xcd,0xcd,0xc7,0xd5,0xfe,0x80,0x1f, 0x99,0xc6,0x2c,0x5e,0x91,0x15,0xf7,0xc5,0x8b,0x17,0xd1,0xd9, 0xd9,0x05,0xa3,0x31,0x0b,0xff,0xd8,0xb5,0x1b,0x76,0xbb,0xfd, 0xd5,0xd6,0xe6,0xcf,0x1b,0x9a,0x8f,0x36,0xae,0xea,0x31,0xf7, 0x46,0x18,0x00,0x43,0x86,0x11,0xc6,0x0c,0x03,0x40,0xb8,0xb8, 0x2b,0xbd,0x94,0x52,0x00,0xe2,0xb2,0x65,0xcb,0xb6,0x3b,0x9c, 0x76,0x59,0x1b,0xa7,0xc5,0xa2,0x45,0x0b,0x83,0xb9,0x79,0xd9, 0x6f,0x2f,0x5c,0x58,0x13,0xd2,0xc6,0x69,0x61,0x77,0xd8,0x94, 0x35,0x0d,0xb7,0xd0,0x1e,0xb3,0xf9,0x89,0x17,0x5f,0x7a,0x79, 0xfc,0xd1,0x8d,0x4f,0xc2,0x62,0xe9,0x35,0x5b,0xbb,0xbb,0xf7, 0xc7,0x76,0x25,0xf9,0x03,0xfe,0x2f,0x3b,0xbb,0xba,0x21,0x8a, 0x6a,0x9c,0xff,0xea,0x2b,0x00,0x20,0xc9,0x69,0x69,0x29,0x13, 0xf3,0x31,0x0f,0x01,0x08,0xc7,0x76,0x1f,0x01,0x10,0x25,0x00, 0x34,0x33,0x67,0x15,0x1a,0x6f,0xb9,0xe5,0xe6,0xee,0x5b,0x57, 0xdf,0x4c,0x0a,0xaf,0x9a,0x0d,0x8d,0xa8,0x81,0x2f,0xe0,0x43, 0x7c,0x5c,0xfc,0x64,0x0d,0xec,0x79,0x6f,0x1f,0x7b,0x76,0xeb, 0x73,0xb5,0x00,0x42,0x39,0x79,0x85,0x55,0x63,0x1e,0xd7,0x05, 0xaf,0xd7,0xeb,0x9f,0x68,0xe5,0xcc,0xdc,0xdc,0xf2,0xb4,0x74, 0xc3,0x76,0x41,0x14,0xa4,0x40,0x20,0xf8,0x85,0xcf,0x3b,0xfa, 0x8e,0xb5,0xa7,0xa7,0x19,0x80,0x32,0x25,0xe5,0xe1,0x18,0x89, 0x09,0x22,0x0a,0x0f,0x40,0x18,0xf7,0x8e,0xab,0xcd,0x16,0x33, 0x19,0x1b,0xf3,0xa2,0xab,0xa7,0x13,0x3d,0x5d,0x3d,0x51,0xa3, 0x31,0x0b,0x0e,0x87,0x0d,0x05,0x85,0x05,0xdc,0xd8,0x98,0x77, 0xe2,0x32,0x1a,0x06,0xe0,0xeb,0xef,0xed,0x3a,0x12,0xab,0xe2, 0x49,0x35,0xb5,0x5b,0xad,0x8d,0x6e,0xa7,0x73,0x5e,0x38,0x1c, 0x0e,0xc5,0xe6,0xa2,0x13,0xad,0x16,0x73,0x65,0x9a,0x4f,0x66, 0x20,0x01,0x40,0x52,0x6e,0x6e,0x4e,0x51,0xf5,0x35,0x55,0x07, 0x01,0xa0,0xac,0xac,0xac,0xef,0x8d,0xd7,0xff,0x76,0xe0,0xbe, 0xb5,0xf7,0xde,0x38,0x36,0x3a,0x96,0x6b,0xb6,0x98,0x71,0xe8, 0x83,0xc3,0xcb,0xfd,0xfe,0x80,0x0d,0x80,0x37,0x46,0x24,0x32, 0x21,0x5a,0xd3,0x8e,0x75,0x02,0x7c,0xe2,0x39,0xdd,0x23,0x53, 0x63,0x08,0x00,0x0d,0x00,0x2d,0x00,0x3d,0x80,0x44,0x00,0xf1, 0xb1,0x31,0x1a,0x0b,0x0e,0x01,0xf0,0x03,0x18,0x03,0x30,0x0e, 0x20,0x10,0x4b,0x67,0x74,0x0a,0x38,0x99,0x02,0x3e,0xf1,0xfc, 0x3e,0x07,0x00,0xf6,0x6f,0xd9,0xb9,0x33,0xf9,0x65,0x1b,0x9d, 0x32,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60, 0x82, }; fityk-1.3.1/wxgui/img/run32.png000066400000000000000000000047011302634723100162430ustar00rootroot00000000000000‰PNG  IHDR szzôbKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEÖ 9®ðP± NIDATXÃÅV{pTÕÿ{îÝ»›ÍfóÎn^dÃ+·0  ¦>!Šã£­¢Î”):Z”ªX™–)âTТ鍵 Êc#F4BHP0M²›l²¯d³I6»{w÷ÞÝÓ?ÜÄ4ÄŽN¿™oîs¾{~¿óïûÝüŸLX³¦!# æ4å™0#ÏÔÖÔtôîúú¥oõõZ*-½p Y;wî¶ÿdŒn_ÅΜé`Vk/Û»ï}ùÄÉeï¾÷e«µ—9ÓÁn_Å~L<~ú@¾)Ÿ%''“ôtnøù¼,+**¡(0öÍüI€›>0#oFG{{›L)Å[o¿)Ýÿà}Á·Þ~S¢”¢½½Mž‘7£ã'%ÐÔÔ´6#Ã((Š‚C‡iB’|ݡÇ4Š¢ #Ã(455­›[Z:£¤²ú¯U ÷WÔ,fÅåå·ýÇ164Ð’ò«Ëÿ'õõõo¸\™çy¬\±R5BãÊ+%žçár9äk¯­}U¥R÷ÞûË{Øñêöì-›Ÿ†J¥~lê]}Ö‚ÈŸ®Z´ØUTY¹ô¥äñ¢}}½, 2E‘™$ILQd Y__/{|ã†hM]]Ä3âa6ûs:¬¦nIdb3ó**ê–üld­m§Ø’å+XIeÕ W\„f‹™x<´w´+ƒ‘8V^VÎ{<˜-fÀcî1§(Ñ0´q:,­¯ãEV(¥¡H$¢ú݆G1<<Œœìl<ü›_ã™-[ˈ̈‚õNèÀ?wïþˆ§ü¯Ru™ÇÁç“Ö»†G·=öÈCê¹sfC¯×C𔇔àt9 º](ÌŸ…õüN÷`ÞÙÖÖ¾+"0Õæ—UU%èã[o½éFìÝ¿Ÿ)J¤ 3_üó6nÞܹp»Ñ?`…,‡!+2´Z-ÒS3 ×ëa³ÛÐÓcÁÖç^èl?Ù2ûŠ30Õ*kõ?õäÆì%µµÂÁ?ÄÒºZ F´žjÏïÇq1'“ï¢(¢ ¿ëÖ?ÂFGG®ùâôéV(..Öž;wÎÿ½JJjŠUZîlãá0ì‚ÝaG¢. y&>=v¡ph ø“ày9Y¹ðùüx`ÝCá(˜“çøÌp8Ä+ÑHÝù¶¶c@/EÀdÊò2‚EMÇ>Ë«ª¬OyÌ™=Í-Ç %Pž‚§µJʪl›ÿ°õÈþÝ»`sôƒã8*íg΢ñãOX0$]ËÑ>=ùi䲊˪j8ЧÔjͲ´Ô ‡ ªTå08ŽƒZTcÈí‰0iò#õz‚ ‚ À@åx|rìs8¬šîîîÐe•pr-¼aõ­¨]¼”ã … EРŽã DÜuÇí8Þrêõù¥!Üsç$?8B@8/@Vd„CáÈtðËÖÏSgeyâµqp :1::‚ä¤Pž‚ò£c\…ç·m+JKÓÒ“?{þÙ-úë—]ç í›8J!¨T‚‘¹’ŠŠ›¦ã\ª Hjšaž^Ÿ°`AI ‚Á¬ýý˜=s6¼>ïdÏïÃÌÂY¸mÕjÜs×HMIÅ€ÓŠ`(BDQ kŸ%óç‘.³eMbRêB­Fý®Çã‰^JˆRXZ:K¯Ñ^xŒ0I+Â+yžÏÈH‡Óe&Eg¢0 ! äÛ%5ê8¸‡Ü8yâ$²²siÌÂÆ§7cthdõù³m{02å'”aQO¾)&“éóÜT}õÕ/Yz-tÿ>J„g^{ùE¢KÐÁívÅz}¿Ý(Šðû8|è#Ì3:þ@›·üɺ¥%@@„N¿ÿµ(-_€ $e]ýò_ˆ*>¥fq WTT„ί¿®w¸Üϰ'© Àƒ!<Ï„LV;ÇQ¨DQ g›žÞ‚–Ö6s[{G¢¨V“÷öìà˽~xÐuÀx`Såçæ3½>ÌBñܼ/àCue5¤„®î¯F™JT™j¯]„/σÃî@ZzÒRS!Æ« Ë Bá ÜCÃøW—/½²#:è´?Ño±4ë’’tãcÞ'!ã_ž= @ ÊÀ®wÞs½òÚöŽžnsñü¢ÂŽ7^ ¶¶ž"ÕÕUìþµª»»z»kxdAqIZvvÀ¢ÃxøÑÇÁ¢,"ˆjšm4àæVÂá²#QŸ Ž@ê·XÎÐŒŒHçGÚ7bàrÌ9.VtÜ‘#G22ÀææãjkïÀÝÍÍÇÕþ€™Æ,^‘÷Å‹ÑÙÙ£1 ÿصv»ýÕÖæÏš6®ê1÷FC†Æ @¸¸+½”Râ²e˶;œvY§Å¢E ƒ¹yÙo/\XÒÆiawØ”5 ·Ð³ù‰_zyüÑOÂbé5[»»÷Çv%ùþ/;»º!Šjœÿê+ Éii)ó1Çv%43go¹åæî[WßL ¯š ¨/àC|\üd ìyo{vësµB9y…Ucׯ×ëŸhåÌÜÜò´tÃvA¤@ ø…Ï;ú޵§§€2%åበ" @÷Ž«Í3󢫧=]=Q£1 ‡ …ÜØ˜wâ2àëïí:«âI5µ[­n§s^8Åæ¢­sešOf @RnnNQõ5U ¬¬¬ï×ÿvྵ÷Þ86:–k¶˜qèƒÃËýþ€ €7F$2!ZÓŽu|â9Ý#Sc -=€Dñ±1 ð0 Kgt 8™>ñü>öoÙ¹3ùe2IEND®B`‚fityk-1.3.1/wxgui/img/run_fit.xpm000066400000000000000000000035371302634723100167660ustar00rootroot00000000000000/* XPM */ static const char * run_fit_xpm[] = { "24 24 77 1", " c None", ". c #000000", "+ c #CFCECA", "@ c #E1E1E0", "# c #97958F", "$ c #898781", "% c #8E8C85", "& c #838078", "* c #7B7973", "= c #67655F", "- c #403F3B", "; c #686661", "> c #7C7A72", ", c #DDDCDB", "' c #9A9992", ") c #53524E", "! c #171614", "~ c #767573", "{ c #9B9993", "] c #52504A", "^ c #7A7974", "/ c #86847D", "( c #9A9996", "_ c #B7B6B3", ": c #7D7B75", "< c #EFE5BA", "[ c #8A8883", "} c #6B6964", "| c #78756C", "1 c #5F5D56", "2 c #54534D", "3 c #EED680", "4 c #EFE7C1", "5 c #403F3A", "6 c #EFE4B6", "7 c #E4E3E1", "8 c #E2E2E2", "9 c #B3B3B1", "0 c #484641", "a c #9F9D96", "b c #888781", "c c #C0AF73", "d c #B0AFAD", "e c #A8A7A1", "f c #908E86", "g c #97958E", "h c #807D74", "i c #D1940C", "j c #986B07", "k c #595854", "l c #605E57", "m c #898883", "n c #76746B", "o c #8F6406", "p c #43423F", "q c #282724", "r c #363430", "s c #6D6B63", "t c #E2E2E1", "u c #B6B5AF", "v c #21201E", "w c #0A0908", "x c #181816", "y c #E6E6E4", "z c #65635C", "A c #CBCAC6", "B c #161614", "C c #8C8B89", "D c #DFDEDC", "E c #B0AFA9", "F c #D5D4D1", "G c #93918B", "H c #D6D5D2", "I c #ABA9A3", "J c #5D5C55", "K c #494943", "L c #42413C", " ... ", " ...+... ", " .@#$%&. ", " ..*=-;>.. ", " .,')!~{]. ", " ... ..^/(_:.. ", " .<. .[}|12.. ", " .34. ...5... ... ", " .336. ... .. .7. .. ", " .333<. .89.0a0.b.. ", " .3333c. .deaaafgh0. ", " .iiij.. .aaklmhn. ", " .iio.. ..0alpqras0.. ", " .io.... .tuakvwxyhzl. ", " .j...A.....0amrBCDz0.. ", " ...@#$%&. .EhuyFGz.. ", " ..*=-;>...HIahhnnJ0. ", " .,')!~{]...k.0n0.K.. ", " ..^/(_:.. .. .L.... ", " .[}|12.. ... ", " ...5... ", " ... ", " ", " "}; fityk-1.3.1/wxgui/img/run_script.xpm000066400000000000000000000034101302634723100174760ustar00rootroot00000000000000/* XPM */ static const char * run_script_xpm[] = { "24 24 71 1", " c None", ". c #000000", "+ c #ECEBF0", "@ c #ECEAF0", "# c #BBB6CA", "$ c #C5C1D2", "% c #887FA3", "& c #F7F6F8", "* c #CAC6D6", "= c #404040", "- c #545454", "; c #555555", "> c #F4F3F6", ", c #FFFFFF", "' c #FAFAFA", ") c #D6D6D6", "! c #878787", "~ c #242424", "{ c #F0EFF3", "] c #FEFEFE", "^ c #E6E6E6", "/ c #F0F0F0", "( c #A0A0A0", "_ c #F8F8F8", ": c #D8D8D8", "< c #F5F5F5", "[ c #979797", "} c #252525", "| c #FDFDFD", "1 c #F7F7F7", "2 c #C9C9C9", "3 c #E0E0E0", "4 c #888888", "5 c #212121", "6 c #46A046", "7 c #625B81", "8 c #FDFDFC", "9 c #FCFCFC", "0 c #F6F6F6", "a c #BFBFBF", "b c #E1E1E1", "c c #C8C8C8", "d c #C2C2C2", "e c #8E8E8E", "f c #FCFCFB", "g c #F6F6F5", "h c #A9A9A9", "i c #666666", "j c #5D5D5D", "k c #565656", "l c #5A5A5A", "m c #848484", "n c #C7C7C6", "o c #A6A6A6", "p c #9A9A9A", "q c #6C6C6C", "r c #AEAEAE", "s c #DF421E", "t c #F9F9F9", "u c #C4C4C4", "v c #F8F8F7", "w c #F5F5F4", "x c #C3C3C3", "y c #F4F4F3", "z c #F2F2F1", "A c #C3C3C2", "B c #F1F1F0", "C c #EFEFEF", "D c #EEEEED", "E c #C2C2C1", "F c #EDEDEB", " ...... ", " .+@##. ", " ..+$%%..", " .&$*%%%.", "=========-; .>$%%. ", ",,,,,,,,,')!~ .{%. ", ",,]]]]]]]'^/(. .. ", "]]]]]]]]]_:,<[} ", "]]]]]]]||12||345 ", "67]|||8990ab)cde ", "]]||8999fghijklm. ", "77797777'1/)nopq. ", "'''''''''''''''r. ", "ss77'777'''''''d. ", "tttttttttttttttu. ", "77v77vvvvvvvvvvu. ", "000000000000000u. ", "wwwwwwwwwwwwwwwx. ", "7yyyyyyyyyyyyyyx. ", "zzzzzzzzzzzzzzzA. ", "sssB7B777B777BBA. ", "CCCCCCCCCCCCCCCd. ", "7777Dss7DDDDDDDE. ", "FFFFFFFFFFFFFFFE. "}; fityk-1.3.1/wxgui/img/runmacro16.h000066400000000000000000000053451302634723100167370ustar00rootroot00000000000000static const unsigned char runmacro16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x01, 0x77, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0x95, 0x91, 0x3f, 0x48, 0x42, 0x61, 0x14, 0xc5, 0x7f, 0xef, 0x61, 0x50, 0x2d, 0xce, 0xed, 0xed, 0x41, 0xa0, 0x8b, 0x8b, 0x08, 0x2d, 0x51, 0x3a, 0xb4, 0x05, 0x4d, 0x11, 0x81, 0x24, 0x04, 0x26, 0x45, 0x08, 0x11, 0x41, 0x18, 0x14, 0x44, 0x41, 0x10, 0x8e, 0x2d, 0xae, 0xd5, 0xea, 0xa0, 0x38, 0x09, 0x45, 0x9b, 0xfa, 0x9a, 0x44, 0x41, 0x85, 0x22, 0x7b, 0x04, 0x19, 0xbc, 0xfc, 0x6e, 0x43, 0xef, 0x99, 0x92, 0x9a, 0x5d, 0x38, 0xf0, 0x71, 0xff, 0x9c, 0x7b, 0xbe, 0x7b, 0x34, 0x46, 0x0b, 0x19, 0x90, 0xd7, 0x5c, 0x23, 0x12, 0xf0, 0xfc, 0xf4, 0x0a, 0x02, 0x0f, 0x77, 0x8f, 0x00, 0xcc, 0xcd, 0x7b, 0x01, 0x70, 0xfd, 0x67, 0xbb, 0x51, 0xac, 0x70, 0x9f, 0x37, 0x7a, 0x6a, 0xba, 0xdd, 0xd0, 0x0f, 0x0b, 0x4e, 0x57, 0xeb, 0xfd, 0x03, 0xa3, 0x50, 0x61, 0x6c, 0xec, 0x67, 0x5f, 0x62, 0xef, 0x0a, 0x00, 0x5d, 0x29, 0x85, 0x83, 0x76, 0xbb, 0x4d, 0xb9, 0x5c, 0x26, 0x9b, 0xcd, 0x02, 0xdc, 0x02, 0x4b, 0x40, 0x68, 0x62, 0x72, 0x9c, 0x99, 0xd9, 0x69, 0x2c, 0xeb, 0xb3, 0x43, 0xb0, 0xb3, 0xbf, 0x02, 0x10, 0xc2, 0x34, 0x4d, 0xe9, 0x46, 0x2e, 0x97, 0x13, 0xcb, 0xb2, 0x24, 0x95, 0x4a, 0x75, 0x2b, 0x09, 0x02, 0xf2, 0xda, 0x7c, 0x93, 0xc4, 0xde, 0x95, 0x93, 0x0f, 0x02, 0x68, 0xa6, 0x69, 0xf6, 0x5c, 0x38, 0x9d, 0x4e, 0x93, 0xcf, 0xe7, 0xa9, 0xd7, 0xeb, 0x54, 0xab, 0x55, 0x32, 0x99, 0x0c, 0x80, 0x66, 0x0f, 0x5c, 0xdb, 0x6d, 0x21, 0xe0, 0x06, 0x40, 0xef, 0xb9, 0x88, 0x08, 0x1e, 0x8f, 0x07, 0xb7, 0xdb, 0xcd, 0xcb, 0xcb, 0x33, 0x85, 0x42, 0xa1, 0xbb, 0x7c, 0x63, 0x13, 0x69, 0xce, 0x30, 0x80, 0xd6, 0x6c, 0x36, 0x7f, 0x79, 0x2c, 0xf2, 0x9d, 0x2a, 0x16, 0x8b, 0xf8, 0x7c, 0x3e, 0x47, 0x41, 0xdf, 0xd0, 0xa3, 0x1b, 0x67, 0x88, 0x48, 0x0f, 0x00, 0x94, 0x52, 0x9d, 0xf7, 0xb0, 0xd0, 0x8f, 0xcf, 0x23, 0xfd, 0xcd, 0xef, 0x22, 0x1b, 0x16, 0xae, 0xad, 0xc8, 0x39, 0x00, 0x47, 0xa7, 0x61, 0xb6, 0x37, 0x2f, 0x3a, 0x85, 0xb5, 0x70, 0x10, 0xa5, 0xd4, 0x9f, 0x04, 0x5a, 0xa3, 0xd1, 0x18, 0xb8, 0xa6, 0x54, 0x2a, 0xe1, 0xf7, 0xfb, 0x87, 0xde, 0xc0, 0xd5, 0x5a, 0xf6, 0x72, 0x30, 0xb5, 0x0a, 0xc0, 0xe1, 0xc9, 0x3a, 0xbb, 0xd1, 0x4b, 0x5b, 0xc1, 0xe2, 0x48, 0x5f, 0xd0, 0x6a, 0xb5, 0x9a, 0x0c, 0xba, 0x81, 0x61, 0x18, 0x04, 0x02, 0x81, 0xe1, 0x2e, 0xc4, 0x63, 0x49, 0x00, 0xe2, 0xb1, 0x24, 0xf1, 0x58, 0x12, 0x11, 0xe9, 0x38, 0x30, 0x8a, 0x82, 0x2f, 0x46, 0x02, 0xcc, 0xd9, 0x75, 0xaa, 0x40, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/runmacro16.png000066400000000000000000000007021302634723100172640ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“wIDATxÚ•‘?HBaÅïaP-ÎííA ‹‹-Q:´M$&EADAŽ-®Õê 8 E›úšDA…"{¼ünCï™’š]8ðqÿœ{¾{4F ×\#ðüô wÌÍ{pýg»Q¬pŸ7zjºÝÐ NWëý£Palìg_bï ])…ƒv»M¹\&›ÍÜK@hbrœ™Ùi,ë³C°³¿Â4MéF.—˲$•Ju+ òÚ|“ÄÞ•“h¦iö\8N“Ïç©×ëT«U2™ €f\Ûm!à@﹈·ÛÍËË3…B¡»|ciÎ0€Öl6y,ò*‹ø|>GAßУgˆH”R÷°ÐÏ#ýÍï"®­È9G§a¶7/:…µp¥ÔŸZ£Ñ¸¦T*á÷û‡ÞÀÕZör0µ ÀáÉ:»ÑK[ÁâH_Ðjµš ºaá.ÄcIâ±$ñXé80Š‚/FÌÙuª@ÛIEND®B`‚fityk-1.3.1/wxgui/img/save.xpm000066400000000000000000000113321302634723100162460ustar00rootroot00000000000000/* XPM */ static const char * save_xpm[] = { "24 24 220 2", " c None", ". c #000000", "+ c #C3D7F4", "@ c #A9CDE5", "# c #75757A", "$ c #EFC5BB", "% c #F1C8BE", "& c #F0C6BC", "* c #EEBCB2", "= c #EEBEB5", "- c #EEC1B8", "; c #EDBFB6", "> c #E9B7AD", ", c #E9B8AF", "' c #E9B9B1", ") c #E5BFBA", "! c #737277", "~ c #B3CDE3", "{ c #A1BED6", "] c #BBD6E8", "^ c #8AAAC5", "/ c #605F68", "( c #E08D7E", "_ c #E0826E", ": c #E0806E", "< c #DC7A68", "[ c #DC8171", "} c #DA7868", "| c #D48173", "1 c #D47D6E", "2 c #CE7265", "3 c #CF7264", "4 c #CE7567", "5 c #C4675B", "6 c #C36558", "7 c #626169", "8 c #87A3B7", "9 c #567187", "0 c #BAD5E9", "a c #88A7C3", "b c #686670", "c c #C8817B", "d c #CB7C74", "e c #CB7A73", "f c #CB7B73", "g c #CC7C72", "h c #CB7D73", "i c #BF6B64", "j c #CC7A70", "k c #C16A62", "l c #CC7C73", "m c #C2655B", "n c #C36459", "o c #BA6C6A", "p c #819EB6", "q c #547086", "r c #B6D3E7", "s c #87ABC1", "t c #737373", "u c #FFFFFF", "v c #83A0B8", "w c #526C80", "x c #B9D3E7", "y c #85A4BF", "z c #4F697C", "A c #B9D3E6", "B c #84A3BF", "C c #CECECE", "D c #CDCDCD", "E c #BFBFBF", "F c #88A4BB", "G c #486276", "H c #B7D2E7", "I c #82A0BB", "J c #636363", "K c #465E70", "L c #B5CAE5", "M c #7FA2B9", "N c #87A3BA", "O c #455C6D", "P c #AECCE5", "Q c #7DA0B6", "R c #C5C5C5", "S c #546069", "T c #B0D1E4", "U c #83A1B6", "V c #735B5B", "W c #515C64", "X c #AACEE3", "Y c #7B9BB2", "Z c #7A8E9A", "` c #7A7A7A", " . c #6B6F72", ".. c #6F6F6F", "+. c #696969", "@. c #6F777E", "#. c #86A2B9", "$. c #3A515D", "%. c #A9C9E2", "&. c #7494AF", "*. c #829FB7", "=. c #7F9DB6", "-. c #7E9CB5", ";. c #7998B2", ">. c #85A1B8", ",. c #8CA7BD", "'. c #8AA5BB", "). c #364A59", "!. c #ABC4E2", "~. c #7294AD", "{. c #6F90AC", "]. c #7192AE", "^. c #414A4E", "/. c #424A51", "(. c #525B63", "_. c #626F79", ":. c #5F6C76", "<. c #5C6971", "[. c #5A666F", "}. c #58636B", "|. c #57636A", "1. c #3B5360", "2. c #39424B", "3. c #7897B3", "4. c #A4B9CB", "5. c #364853", "6. c #AAC9E2", "7. c #7091AA", "8. c #6F8FA7", "9. c #4A5359", "0. c #97938C", "a. c #DFDDDA", "b. c #E3E1DE", "c. c #EBEAE8", "d. c #EAE9E7", "e. c #CFCEC9", "f. c #C9C6C0", "g. c #9B968E", "h. c #566168", "i. c #4B657A", "j. c #54738C", "k. c #AAC6DD", "l. c #34464E", "m. c #AAC9E1", "n. c #6C8EA6", "o. c #6C8CA4", "p. c #40474D", "q. c #DAD8D3", "r. c #E7E6E2", "s. c #67655E", "t. c #524F47", "u. c #D9D7D4", "v. c #C7C5BF", "w. c #C0BCB5", "x. c #B8B3AB", "y. c #434C54", "z. c #4D697F", "A. c #4F6F84", "B. c #B3CADC", "C. c #313E49", "D. c #A8C8E1", "E. c #6B8DA6", "F. c #728FA4", "G. c #E2E1DD", "H. c #F0EFEC", "I. c #CDCAC6", "J. c #C2BFB9", "K. c #CAC6C0", "L. c #DCDAD7", "M. c #4B555D", "N. c #4E697F", "O. c #BACCDC", "P. c #A4C4DE", "Q. c #698BA3", "R. c #708AA1", "S. c #383E43", "T. c #E0DEDA", "U. c #514E46", "V. c #4F4C44", "W. c #C7C4BE", "X. c #CBC8C2", "Y. c #E1E0DC", "Z. c #E9E8E6", "`. c #475158", " + c #4E6879", ".+ c #4D6C80", "++ c #A3C3DB", "@+ c #383F43", "#+ c #778999", "$+ c #6E899E", "%+ c #65859C", "&+ c #33383C", "*+ c #D7D4D0", "=+ c #D6D4D0", "-+ c #4E4A43", ";+ c #4D4942", ">+ c #D1CEC9", ",+ c #E6E5E2", "'+ c #EDECEA", ")+ c #454F55", "!+ c #486173", "~+ c #4D6678", "{+ c #A1C1DA", "]+ c #373C40", "^+ c #0C0D0F", "/+ c #4E5E6A", "(+ c #5B6E7C", "_+ c #4F5B62", ":+ c #A4A099", "<+ c #CCC9C3", "[+ c #D7D5D1", "}+ c #E4E2E0", "|+ c #DDDBD7", "1+ c #B8B5B0", "2+ c #3E474D", "3+ c #4A6176", "4+ c #4A6070", "5+ c #9BC3D8", "6+ c #363C41", "7+ c #28323E", " ", " . . . . . . . . . . . . . . . . . . . ", " . + @ # $ % & * = - ; > , > , ' ) ! ~ { . ", " . ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 . ", " . 0 a b c d e f g h i j k l m n o b p q . ", " . r s t u u u u u u u u u u u u u t v w . ", " . x y t u u u u u u u u u u u u u t v z . ", " . A B t C D D D D D D D D D D D E t F G . ", " . H I J u u u u u u u u u u u u u t F K . ", " . L M t u u u u u u u u u u u u u t N O . ", " . P Q t C D D D D D D D D D D D R t N S . ", " . T U V u u u u u u u u u u u u u t v W . ", " . X Y Z ` t t t t t ...t t t t +.@.#.$.. ", " . %.&.p v #.*.=.-.*.;.#.>.>.N *.,.v '.).. ", " . !.~.{.].^./.(._.:.<.[.}.|.(.1.2.3.4.5.. ", " . 6.7.8.9.0.a.b.c.c.d.a.e.f.g.h.i.j.k.l.. ", " . m.n.o.p.q.r.s.t.t.u.v.w.x.e.y.z.A.B.C.. ", " . D.E.F.p.G.H.s.t.t.I.J.w.K.L.M.N.A.O.C.. ", " . P.Q.R.S.T.c.U.V.V.W.w.X.Y.Z.`. +.+++@+. ", " . #+$+%+&+*+=+-+;+;+w.>+,+'+,+)+!+~+{+]+. ", " ^+/+(+_+:+w.x.<+<+[+}+d.|+1+2+3+4+5+6+. ", " . . . . . . . . . . . . . . . . 7+. ", " ", " "}; fityk-1.3.1/wxgui/img/save_as.xpm000066400000000000000000000125751302634723100167430ustar00rootroot00000000000000/* XPM */ static const char * save_as_xpm[] = { "24 24 262 2", " c None", ". c #000000", "+ c #FBE73B", "@ c #F2B64D", "# c #FCEB3D", "$ c #F7B544", "% c #5D502C", "& c #C3D7F4", "* c #A9CDE5", "= c #75757A", "- c #EFC5BB", "; c #F1C8BE", "> c #F0C6BC", ", c #EEBCB2", "' c #EEBEB5", ") c #EEC1B8", "! c #EDBFB6", "~ c #E8B6AC", "{ c #FCE93B", "] c #F7B545", "^ c #6C5F34", "/ c #434345", "( c #92A7B9", "_ c #96B1C7", ": c #BBD6E8", "< c #8AAAC5", "[ c #605F68", "} c #E08D7E", "| c #E0826E", "1 c #E0806E", "2 c #DC7A68", "3 c #DC8171", "4 c #DA7868", "5 c #D38072", "6 c #FAE43A", "7 c #F4B244", "8 c #615030", "9 c #783E35", "0 c #4D4C52", "a c #7790A2", "b c #526D82", "c c #BAD5E9", "d c #88A7C3", "e c #686670", "f c #C8817B", "g c #CB7C74", "h c #CB7A73", "i c #CB7B73", "j c #CC7C72", "k c #CA7C72", "l c #F9DF39", "m c #F3AF42", "n c #614F2F", "o c #8F4941", "p c #945554", "q c #5B5A62", "r c #7B97AE", "s c #536F84", "t c #B6D3E7", "u c #87ABC1", "v c #737373", "w c #FFFFFF", "x c #FEFEFE", "y c #F9DC38", "z c #EFB44D", "A c #665A32", "B c #BBBBBB", "C c #CDCDCD", "D c #E4E4E4", "E c #6E6E6E", "F c #819EB6", "G c #526C80", "H c #B9D3E7", "I c #85A4BF", "J c #F8D837", "K c #F0A93F", "L c #655930", "M c #BABABA", "N c #CCCCCC", "O c #E5E5E5", "P c #F7F7F7", "Q c #727272", "R c #83A0B8", "S c #4F697C", "T c #B9D3E6", "U c #84A3BF", "V c #CECECE", "W c #F6D236", "X c #EDA43E", "Y c #5C5130", "Z c #949494", "` c #A3A3A3", " . c #B7B7B7", ".. c #C6C6C6", "+. c #BDBDBD", "@. c #88A4BB", "#. c #486276", "$. c #B7D2E7", "%. c #82A0BB", "&. c #636363", "*. c #FDFDFD", "=. c #D7AE74", "-. c #61562F", ";. c #465E70", ">. c #B5CAE5", ",. c #7FA2B9", "'. c #4F4115", "). c #87A3BA", "!. c #455C6D", "~. c #AECCE5", "{. c #7DA0B6", "]. c #CBCBCB", "^. c #9B9B9B", "/. c #9C9C9C", "(. c #A7A7A7", "_. c #B8B8B8", ":. c #C5C5C5", "<. c #546069", "[. c #B0D1E4", "}. c #83A1B6", "|. c #735B5B", "1. c #F0F0F0", "2. c #D9D9D9", "3. c #D3D3D3", "4. c #E1E1E1", "5. c #EDEDED", "6. c #F8F8F8", "7. c #515C64", "8. c #AACEE3", "9. c #7B9BB2", "0. c #7A8E9A", "a. c #7A7A7A", "b. c #707070", "c. c #6C6C6C", "d. c #6F6F6F", "e. c #6A6E71", "f. c #696969", "g. c #6F777E", "h. c #86A2B9", "i. c #3A515D", "j. c #A9C9E2", "k. c #7494AF", "l. c #7E9BB4", "m. c #7D9AB3", "n. c #7998B2", "o. c #85A1B8", "p. c #829FB7", "q. c #8CA7BD", "r. c #8AA5BB", "s. c #364A59", "t. c #ABC4E2", "u. c #7294AD", "v. c #6F90AC", "w. c #7192AE", "x. c #414A4E", "y. c #424A51", "z. c #525B63", "A. c #626F79", "B. c #5F6C76", "C. c #5C6971", "D. c #5A666F", "E. c #58636B", "F. c #57636A", "G. c #3B5360", "H. c #39424B", "I. c #7897B3", "J. c #A4B9CB", "K. c #364853", "L. c #AAC9E2", "M. c #7091AA", "N. c #6F8FA7", "O. c #4A5359", "P. c #97938C", "Q. c #DFDDDA", "R. c #E3E1DE", "S. c #EBEAE8", "T. c #EAE9E7", "U. c #CFCEC9", "V. c #C9C6C0", "W. c #9B968E", "X. c #566168", "Y. c #4B657A", "Z. c #54738C", "`. c #AAC6DD", " + c #34464E", ".+ c #AAC9E1", "++ c #6C8EA6", "@+ c #6C8CA4", "#+ c #40474D", "$+ c #DAD8D3", "%+ c #E7E6E2", "&+ c #67655E", "*+ c #524F47", "=+ c #D9D7D4", "-+ c #C7C5BF", ";+ c #C0BCB5", ">+ c #B8B3AB", ",+ c #434C54", "'+ c #4D697F", ")+ c #4F6F84", "!+ c #B3CADC", "~+ c #313E49", "{+ c #A8C8E1", "]+ c #6B8DA6", "^+ c #728FA4", "/+ c #E2E1DD", "(+ c #F0EFEC", "_+ c #CDCAC6", ":+ c #C2BFB9", "<+ c #CAC6C0", "[+ c #DCDAD7", "}+ c #4B555D", "|+ c #4E697F", "1+ c #BACCDC", "2+ c #A4C4DE", "3+ c #698BA3", "4+ c #708AA1", "5+ c #383E43", "6+ c #E0DEDA", "7+ c #514E46", "8+ c #4F4C44", "9+ c #C7C4BE", "0+ c #CBC8C2", "a+ c #E1E0DC", "b+ c #E9E8E6", "c+ c #475158", "d+ c #4E6879", "e+ c #4D6C80", "f+ c #A3C3DB", "g+ c #383F43", "h+ c #778999", "i+ c #6E899E", "j+ c #65859C", "k+ c #33383C", "l+ c #D7D4D0", "m+ c #D6D4D0", "n+ c #4E4A43", "o+ c #4D4942", "p+ c #D1CEC9", "q+ c #E6E5E2", "r+ c #EDECEA", "s+ c #454F55", "t+ c #486173", "u+ c #4D6678", "v+ c #A1C1DA", "w+ c #373C40", "x+ c #0C0D0F", "y+ c #4E5E6A", "z+ c #5B6E7C", "A+ c #4F5B62", "B+ c #A4A099", "C+ c #CCC9C3", "D+ c #D7D5D1", "E+ c #E4E2E0", "F+ c #DDDBD7", "G+ c #B8B5B0", "H+ c #3E474D", "I+ c #4A6176", "J+ c #4A6070", "K+ c #9BC3D8", "L+ c #363C41", "M+ c #28323E", " . . ", " . + @ . ", " . . . . . . . . . . . . . # $ % . . . ", " . & * = - ; > , ' ) ! ~ . { ] ^ . / ( _ . ", " . : < [ } | 1 2 3 4 5 . 6 7 8 . 9 0 a b . ", " . c d e f g h i j k . l m n . o p q r s . ", " . t u v w w w w x . y z A . B C D E F G . ", " . H I v w w w x . J K L . M N O P Q R S . ", " . T U v V C N . W X Y . Z ` ...+.v @.#.. ", " . $.%.&.w w *.. =.-.. M N D P *.w v @.;.. ", " . >.,.v w x . '.. . M N D P *.w w v ).!.. ", " . ~.{.v V ].. . ^./.(._...].C C :.v ).<.. ", " . [.}.|.w *.1.2.3.4.5.6.x w w w w v R 7.. ", " . 8.9.0.a.Q b.c.c.d.e.E v v v v f.g.h.i.. ", " . j.k.F R h.F l.m.F n.h.o.o.).p.q.R r.s.. ", " . t.u.v.w.x.y.z.A.B.C.D.E.F.z.G.H.I.J.K.. ", " . L.M.N.O.P.Q.R.S.S.T.Q.U.V.W.X.Y.Z.`. +. ", " . .+++@+#+$+%+&+*+*+=+-+;+>+U.,+'+)+!+~+. ", " . {+]+^+#+/+(+&+*+*+_+:+;+<+[+}+|+)+1+~+. ", " . 2+3+4+5+6+S.7+8+8+9+;+0+a+b+c+d+e+f+g+. ", " . h+i+j+k+l+m+n+o+o+;+p+q+r+q+s+t+u+v+w+. ", " x+y+z+A+B+;+>+C+C+D+E+T.F+G+H+I+J+K+L+. ", " . . . . . . . . . . . . . . . . M+. ", " "}; fityk-1.3.1/wxgui/img/save_data.xpm000066400000000000000000000130371302634723100172430ustar00rootroot00000000000000/* XPM */ static const char * save_data_xpm[] = { "24 24 272 2", " c None", ". c #000000", "+ c #FBE73B", "@ c #F2B64D", "# c #FCEB3D", "$ c #F7B544", "% c #5D502C", "& c #C3D7F4", "* c #A9CDE5", "= c #75757A", "- c #EFC5BB", "; c #F1C8BE", "> c #F0C6BC", ", c #EEBCB2", "' c #EEBEB5", ") c #EEC1B8", "! c #EDBFB6", "~ c #E8B6AC", "{ c #FCE93B", "] c #F7B545", "^ c #6C5F34", "/ c #434345", "( c #92A7B9", "_ c #96B1C7", ": c #BBD6E8", "< c #8AAAC5", "[ c #605F68", "} c #E08D7E", "| c #E0826E", "1 c #E0806E", "2 c #DC7A68", "3 c #DC8171", "4 c #DA7868", "5 c #D38072", "6 c #FAE43A", "7 c #F4B244", "8 c #615030", "9 c #783E35", "0 c #4D4C52", "a c #7790A2", "b c #526D82", "c c #BAD5E9", "d c #88A7C3", "e c #686670", "f c #C8817B", "g c #CB7C74", "h c #CB7A73", "i c #CB7B73", "j c #CC7C72", "k c #CA7C72", "l c #F9DF39", "m c #F3AF42", "n c #614F2F", "o c #8F4941", "p c #945554", "q c #5B5A62", "r c #7B97AE", "s c #536F84", "t c #B6D3E7", "u c #87ABC1", "v c #737373", "w c #FFFFFF", "x c #FEFEFE", "y c #F9DC38", "z c #EFB44D", "A c #665A32", "B c #BBBBBB", "C c #CDCDCD", "D c #E4E4E4", "E c #6E6E6E", "F c #819EB6", "G c #526C80", "H c #B9D3E7", "I c #85A4BF", "J c #F8D837", "K c #F0A93F", "L c #655930", "M c #127704", "N c #A0B89D", "O c #E5E5E5", "P c #F7F7F7", "Q c #727272", "R c #83A0B8", "S c #4F697C", "T c #B9D3E6", "U c #84A3BF", "V c #CECECE", "W c #CCCCCC", "X c #F6D236", "Y c #EDA43E", "Z c #5C5130", "` c #010700", " . c #60885A", ".. c #61955A", "+. c #A9B9A7", "@. c #BDBDBD", "#. c #88A4BB", "$. c #486276", "%. c #B7D2E7", "&. c #82A0BB", "*. c #636363", "=. c #FDFDFD", "-. c #D7AE74", ";. c #61562F", ">. c #BABABA", ",. c #5D9E54", "'. c #A6CBA1", "). c #465E70", "!. c #B5CAE5", "~. c #7FA2B9", "{. c #4F4115", "]. c #9BC395", "^. c #67A85E", "/. c #87A3BA", "(. c #455C6D", "_. c #AECCE5", ":. c #7DA0B6", "<. c #CBCBCB", "[. c #000300", "}. c #010B00", "|. c #56894F", "1. c #9C9C9C", "2. c #A7A7A7", "3. c #B8B8B8", "4. c #C6C6C6", "5. c #3A892F", "6. c #9BB298", "7. c #546069", "8. c #117403", "9. c #B0D1E4", "0. c #83A1B6", "a. c #735B5B", "b. c #F2F7F2", "c. c #5DA054", "d. c #48913E", "e. c #86AE81", "f. c #E1E1E1", "g. c #EDEDED", "h. c #F8F8F8", "i. c #A0C89A", "j. c #515C64", "k. c #106F03", "l. c #AACEE3", "m. c #7B9BB2", "n. c #7A8E9A", "o. c #7A7A7A", "p. c #587355", "q. c #25741A", "r. c #6C6C6C", "s. c #6F6F6F", "t. c #6A6E71", "u. c #317128", "v. c #6F777E", "w. c #86A2B9", "x. c #3A515D", "y. c #0B4C02", "z. c #A9C9E2", "A. c #7494AF", "B. c #5E937B", "C. c #388343", "D. c #7D9AB3", "E. c #7998B2", "F. c #85A1B8", "G. c #3A8544", "H. c #558F70", "I. c #8AA5BB", "J. c #1E6622", "K. c #ABC4E2", "L. c #7294AD", "M. c #6F90AC", "N. c #7192AE", "O. c #286127", "P. c #38663D", "Q. c #626F79", "R. c #5F6C76", "S. c #5C6971", "T. c #5A666F", "U. c #58636B", "V. c #57636A", "W. c #525B63", "X. c #3B5360", "Y. c #368243", "Z. c #468E4B", "`. c #AAC9E2", " + c #7091AA", ".+ c #6F8FA7", "++ c #4A5359", "@+ c #377E29", "#+ c #8FB686", "$+ c #EBEAE8", "%+ c #EAE9E7", "&+ c #DFDDDA", "*+ c #CFCEC9", "=+ c #C9C6C0", "-+ c #9B968E", ";+ c #566168", ">+ c #346C4A", ",+ c #328832", "'+ c #AAC9E1", ")+ c #6C8EA6", "!+ c #6C8CA4", "~+ c #2D5A2F", "{+ c #5E9F54", "]+ c #67655E", "^+ c #524F47", "/+ c #D9D7D4", "(+ c #C7C5BF", "_+ c #C0BCB5", ":+ c #B8B3AB", "<+ c #434C54", "[+ c #4D697F", "}+ c #367250", "|+ c #24542D", "1+ c #A8C8E1", "2+ c #6B8DA6", "3+ c #728FA4", "4+ c #1B6C13", "5+ c #62A257", "6+ c #CDCAC6", "7+ c #C2BFB9", "8+ c #CAC6C0", "9+ c #DCDAD7", "0+ c #4B555D", "a+ c #4E697F", "b+ c #4F6F84", "c+ c #BACCDC", "d+ c #313E49", "e+ c #072F01", "f+ c #469252", "g+ c #317E3D", "h+ c #5C9C51", "i+ c #514E46", "j+ c #4F4C44", "k+ c #C7C4BE", "l+ c #CBC8C2", "m+ c #E1E0DC", "n+ c #E9E8E6", "o+ c #475158", "p+ c #4E6879", "q+ c #4D6C80", "r+ c #A3C3DB", "s+ c #383F43", "t+ c #367D39", "u+ c #237A24", "v+ c #1D6018", "w+ c #D7D4D0", "x+ c #D6D4D0", "y+ c #4E4A43", "z+ c #4D4942", "A+ c #D1CEC9", "B+ c #E6E5E2", "C+ c #EDECEA", "D+ c #454F55", "E+ c #486173", "F+ c #4D6678", "G+ c #A1C1DA", "H+ c #373C40", "I+ c #276D28", "J+ c #3D714C", "K+ c #4F5B62", "L+ c #A4A099", "M+ c #CCC9C3", "N+ c #D7D5D1", "O+ c #E4E2E0", "P+ c #DDDBD7", "Q+ c #B8B5B0", "R+ c #3E474D", "S+ c #4A6176", "T+ c #4A6070", "U+ c #9BC3D8", "V+ c #363C41", "W+ c #28323E", " . . ", " . + @ . ", " . . . . . . . . . . . . . # $ % . . . ", " . & * = - ; > , ' ) ! ~ . { ] ^ . / ( _ . ", " . : < [ } | 1 2 3 4 5 . 6 7 8 . 9 0 a b . ", " . c d e f g h i j k . l m n . o p q r s . ", " . t u v w w w w x . y z A . B C D E F G . ", " . H I v w w w x . J K L . M N O P Q R S . ", " . T U v V C W . X Y Z ` .M ..+.@.v #.$.. ", " . %.&.*.w w =.. -.;.. >.W ,.M '.w v #.).. ", " . !.~.v w x . {.. . >.W D ].M ^.w v /.(.. ", " . _.:.v V <.[.}.|.1.2.3.4.<.5.M 6.v /.7.. 8.", " . 9.0.a.w b.c.d.e.f.g.h.x w ^.M i.v R j.. k.M ", " . l.m.n.o.p.M q.r.s.t.E v v v M u.v.w.x.y.M 8.", " . z.A.F R B.M C.D.F E.w.F.F./.G.M H.I.J.M k. ", " . K.L.M.N.O.M P.Q.R.S.T.U.V.W.X.M Y.Z.M y. ", " . `. +.+++@+M #+$+$+%+&+*+=+-+;+>+M ,+M . ", " . '+)+!+~+M {+]+^+^+/+(+_+:+*+<+[+}+M |+. ", " . 1+2+3+4+M 5+]+^+^+6+7+_+8+9+0+a+b+c+d+. ", " e+f+g+M M h+$+i+j+j+k+_+l+m+n+o+p+q+r+s+. ", "M y.t+M u+v+w+x+y+z+z+_+A+B+C+B+D+E+F+G+H+. ", "M M M I+J+K+L+_+:+M+M+N+O+%+P+Q+R+S+T+U+V+. ", "M . . . . . . . . . . . . . . . . W+. ", " "}; fityk-1.3.1/wxgui/img/save_script.xpm000066400000000000000000000106411302634723100176340ustar00rootroot00000000000000/* XPM */ static const char * save_script_xpm[] = { "24 24 200 2", " c None", ". c #000000", "+ c #686A6D", "@ c #5B5B5B", "# c #F3EFE3", "$ c #F0EBD7", "% c #F9F3DC", "& c #F7EDCA", "* c #A39256", "= c #85838F", "- c #778A9E", "; c #6D7E90", "> c #333333", ", c #F5F1E5", "' c #F6F1E0", ") c #F3E4AD", "! c #DFB74A", "~ c #D9A72E", "{ c #D1940C", "] c #D4B150", "^ c #E2CB79", "/ c #8D7E4A", "( c #271614", "_ c #43526B", ": c #314E6C", "< c #2C4763", "[ c #F2E8D0", "} c #EED680", "| c #D59D1C", "1 c #B8820A", "2 c #050505", "3 c #070707", "4 c #C9B46B", "5 c #2D2D2D", "6 c #EDEDED", "7 c #ECECEC", "8 c #EEEEEE", "9 c #F0F0F0", "0 c #F1F1F1", "a c #F2F2F2", "b c #DEDEDE", "c c #BAB3A2", "d c #FAF5E3", "e c #E0B74C", "f c #986B07", "g c #1C1C1C", "h c #DCDCDC", "i c #E6E6E6", "j c #C4C4C4", "k c #262626", "l c #C8C8C8", "m c #EFEFEF", "n c #F3F3F3", "o c #DFDFDF", "p c #F2E9CE", "q c #121212", "r c #D7D7D7", "s c #E8E8E8", "t c #E9E9E9", "u c #F4F4F4", "v c #E0E0E0", "w c #F8F1D6", "x c #EAEAEA", "y c #3C3C3C", "z c #444444", "A c #F5F5F5", "B c #E1E1E1", "C c #F4E4AD", "D c #3A3A3A", "E c #373737", "F c #FBE73B", "G c #F2B64D", "H c #2F2F2F", "I c #F6F6F6", "J c #E2E2E2", "K c #F7F3DF", "L c #BC9F5F", "M c #FCEB3D", "N c #F7B544", "O c #5D502C", "P c #9C9C9C", "Q c #F7F7F7", "R c #E3E3E3", "S c #F9F6EA", "T c #BEA56F", "U c #D18F84", "V c #D6988D", "W c #E9D736", "X c #EDAE42", "Y c #6C5F34", "Z c #121416", "` c #BACFE1", " . c #F8F8F8", ".. c #F9F9F9", "+. c #E5E5E5", "@. c #F9F5E4", "#. c #F1DD97", "$. c #BCA36B", "%. c #150C0B", "&. c #CF8E84", "*. c #C77467", "=. c #C57366", "-. c #61522E", ";. c #72899A", ">. c #54697C", ",. c #FAFAFA", "'. c #303030", "). c #F9F5E6", "!. c #C3A970", "~. c #FDFDFD", "{. c #FEFEFE", "]. c #FCFCFC", "^. c #F9DF39", "/. c #F7B545", "(. c #B4B4B4", "_. c #84A0B5", ":. c #4F6475", "<. c #FBFBFB", "[. c #E7E7E7", "}. c #F2EFE4", "|. c #050607", "1. c #D9D9D9", "2. c #D6D6D6", "3. c #F8D837", "4. c #EFB44D", "5. c #584D2B", "6. c #8F8F8F", "7. c #819AAE", "8. c #496072", "9. c #4D4D4D", "0. c #262A2C", "a. c #95AFC2", "b. c #F6D236", "c. c #EDA43E", "d. c #584E2B", "e. c #AAAAAA", "f. c #D3D3D3", "g. c #485F71", "h. c #CFE0ED", "i. c #8DA9BE", "j. c #D5D5D5", "k. c #D7AE74", "l. c #61562F", "m. c #737373", "n. c #C5C5C5", "o. c #B0B0B0", "p. c #7F98AC", "q. c #4F4115", "r. c #8D8D8D", "s. c #EBEBEB", "t. c #ACBDCB", "u. c #6F767D", "v. c #9AA3AC", "w. c #BFCBD6", "x. c #BDC9D4", "y. c #A1B6C4", "z. c #8BA7BC", "A. c #809CB0", "B. c #6C8394", "C. c #7D97AB", "D. c #7D97AC", "E. c #A4ACB8", "F. c #B9B9B9", "G. c #C7C7C7", "H. c #D4D4D4", "I. c #9C9D9D", "J. c #2F4656", "K. c #80868C", "L. c #183042", "M. c #33495A", "N. c #132D3C", "O. c #586D80", "P. c #97A5B0", "Q. c #86A4B9", "R. c #CDCDCD", "S. c #2E4353", "T. c #5A7082", "U. c #BFBFBF", "V. c #112835", "W. c #9DA9B0", "X. c #6B7882", "Y. c #829DB1", "Z. c #CBCBCB", "`. c #213648", " + c #5F7989", ".+ c #C2C2C2", "++ c #B2B2B2", "@+ c #112C3A", "#+ c #9FA9B0", "$+ c #59636D", "%+ c #A1A1A1", "&+ c #C0C0C0", "*+ c #909090", "=+ c #868686", "-+ c #6E6E6E", ";+ c #7A7A7A", ">+ c #2D3949", ",+ c #3E4F5C", "'+ c #80878F", ")+ c #1A3140", " . . . . . . . . . . . . . . . . . . . . . ", " . + . @ # $ % & * . . = - - - - - - - ; . ", " . > , ' ) ! ~ { ] ^ / ( _ : : : : : : < . ", " . [ & } | { 1 . 2 3 4 5 6 7 6 8 9 0 a b . ", " . c d } e { f g h i j k l 7 6 m 9 0 a n o . ", " . p } } { { q r s t 7 7 6 8 m 9 0 a n u v . ", " . w } } { { 3 s t x 7 6 8 m y z 0 n u A B . ", ". . . C } } { { . 5 D E m 8 m . F G H u A I J . ", ". K } } } } { { { L . . . . . M N O . P I Q R . ", " . S } } } { { T . U U V . W X Y Z ` . ...+.. ", " . @.#.} { $.%.&.*.=.. M N -.. ;.>.. ..,.i . ", " '.).#.!.. ~.{.].. ^./.Y . (._.:.. ,.<.[.. ", " . . }.|.1.r 2.. 3.4.5.. 6.0 7.8.. <.].s . ", " . 9.0.a.r ~.. b.c.d.. e.f.0 7.g.. ].~.t . ", " . . h.i.r j.. k.l.. m.n.o.0 p.8.. s t 2.. ", " . . h.i.6 . q.. . r.f.s.s.7 7.8.. . . . . ", " . h.i.t.. . u.v.w.w.w.x.y.7.8.. . ", " . h.i.z.A.B.7.7.7.7.C.D.7.7.8.. ", " . h.i.z.E.F.F.G.B H.I.J.K.7.8.. ", " . h.i._.n.n.L.M.j.n.F.N.O.P.8.. ", " . h.Q.7.n.R.S.T.n.n.U.V.T.W.8.. ", " . X.Y.p.Z.+.`. +n..+++@+T.#+8.. ", " . . $+:.%+&+*+*+=+-+;+>+,+'+)+. ", " . . . . . . . . . . . . . . "}; fityk-1.3.1/wxgui/img/sbprefs.h000066400000000000000000000040351302634723100164010ustar00rootroot00000000000000static const unsigned char sbprefs_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x09, 0x08,0x06,0x00,0x00,0x00,0x02,0x4d,0x1d,0x69,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x00,0x06,0x62,0x4b,0x47,0x44,0x00,0xff,0x00,0xff,0x00,0xff, 0xa0,0xbd,0xa7,0x93,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73, 0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,0x13,0x01,0x00,0x9a,0x9c, 0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd9,0x0c, 0x1e,0x0a,0x10,0x37,0x73,0x3b,0x18,0x62,0x00,0x00,0x01,0x0f, 0x49,0x44,0x41,0x54,0x28,0xcf,0x5d,0x91,0xbf,0x4e,0xc2,0x50, 0x14,0xc6,0x7f,0xc7,0x40,0xb0,0x65,0x68,0xcb,0xee,0xe4,0x60, 0x27,0x26,0xc2,0x8b,0x20,0xe2,0x0b,0x18,0x44,0x24,0xbe,0x85, 0xba,0xaa,0x80,0x15,0xff,0xc4,0x38,0x11,0xc2,0xee,0x60,0xe2, 0x1b,0xa8,0x0f,0x61,0x48,0x9a,0x96,0xf5,0xa6,0xe3,0x71,0x30, 0xbd,0xb4,0x9c,0xe9,0x7c,0xf7,0xe4,0x7c,0xf7,0xcb,0xef,0xc8, 0xf7,0xcf,0x17,0x57,0xd7,0x97,0x4a,0xa1,0xa6,0xe3,0x48,0x54, 0x37,0x4f,0xaa,0x4a,0x51,0xaf,0x56,0xbf,0x90,0x65,0x19,0xdd, 0x5e,0x47,0xf3,0xea,0xf6,0x3a,0xba,0x5e,0xaf,0x69,0xb6,0xda, 0xda,0x6c,0xb5,0x35,0x4d,0x53,0x92,0x24,0xb1,0x3a,0x8e,0x63, 0x8c,0x31,0x54,0x72,0x97,0x8f,0xcf,0x77,0xeb,0x28,0x22,0xb8, 0xce,0xae,0xd5,0xc3,0xd1,0x40,0x0f,0xf6,0xf7,0x00,0x18,0x5d, 0x0c,0xf5,0xf5,0xe5,0x4d,0xec,0xe2,0xe3,0xec,0xb9,0xb4,0x18, 0x04,0xbe,0xed,0x01,0x16,0xf3,0x25,0x00,0x47,0xc7,0x87,0x00, 0xec,0x00,0xdc,0x4f,0x1e,0xa4,0x5a,0x73,0xa9,0xd6,0x5c,0x66, 0xd1,0x93,0x88,0x08,0x81,0xef,0x11,0xf8,0x1e,0xc5,0x44,0x79, 0x2a,0x11,0xd9,0x44,0x0d,0x02,0xcf,0x82,0xe8,0x0f,0x4e,0x2c, 0x89,0xc1,0xb0,0xaf,0xdb,0x89,0x54,0xf5,0xff,0x47,0x80,0x86, 0xef,0xd1,0xf0,0x3d,0x4b,0x6f,0x31,0x5f,0xda,0x78,0xd3,0x71, 0x24,0x61,0x18,0x12,0x86,0x21,0x77,0x37,0x13,0x01,0xa8,0xe4, 0xa8,0xeb,0x75,0xd7,0xba,0x6d,0xc3,0x2a,0xce,0x2d,0x07,0x63, 0x0c,0xc6,0x98,0x12,0x98,0xb3,0xf3,0xd3,0xd2,0x5d,0xc7,0xb7, 0xd3,0xd2,0x5d,0x1d,0xc7,0xe1,0x0f,0x41,0xdb,0x7f,0xa2,0xff, 0x45,0x78,0x4d,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae, 0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/sbprefs.png000066400000000000000000000006171302634723100167400ustar00rootroot00000000000000‰PNG  IHDR MisRGB®ÎébKGDÿÿÿ ½§“ pHYs  šœtIMEÙ  7s;bIDAT(Ï]‘¿NÂPÆÇ@°ehËîä`'&‹ â D$¾…ºª€ÿÄ8Âî`â¨aHš–õ¦ãq0½´œé|÷ä|÷ËïÈ÷ÏW×—J¡¦ãHT7OªJQ¯V¿eÝ^Góêö:º^¯i¶ÚÚlµ5MS’$±:ŽcŒ1Tr—Ïwë("¸Î®ÕÃÑ@ö÷] õõåMìâãì¹´¾íó%GLJìÜO¤Zs©Ö\fÑ“ˆïøÅDy*ÙD Ï‚èN,‰Á°¯Û‰TõÿG€†ïÑð=Ko1_ÚxÓq$a†!w7¨ä¨ëu׺mÃ*Î-c Ƙ˜³óÓÒ]Ç·ÓÒ]ÇáAÛ¢ÿExMIEND®B`‚fityk-1.3.1/wxgui/img/shiftup.xpm000066400000000000000000000005111302634723100167670ustar00rootroot00000000000000/* XPM */ static const char * shiftup_xpm[] = { "10 15 4 1", " c None", ". c #00FF00", "+ c #169616", "@ c #2E2E2E", "..........", "....++....", " @@ ", " @@@@ ", " @@@@@@ ", " @@@@@@@@ ", " @@ ", " @@ ", " @@ ", " @@ ", " @@ ", "..........", "....++....", " @@ ", " @@@@ "}; fityk-1.3.1/wxgui/img/sizes32.h000066400000000000000000000040661302634723100162430ustar00rootroot00000000000000static const unsigned char sizes32_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20, 0x08,0x06,0x00,0x00,0x00,0x73,0x7a,0x7a,0xf4,0x00,0x00,0x00, 0x01,0x73,0x52,0x47,0x42,0x00,0xae,0xce,0x1c,0xe9,0x00,0x00, 0x01,0x4e,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x96,0x31,0x4e, 0xc4,0x30,0x10,0x45,0x5f,0x76,0x0b,0x1a,0xf6,0x00,0x50,0x71, 0x06,0x96,0xca,0xcd,0x26,0x3d,0x97,0xa0,0xe2,0x02,0xee,0xb3, 0xae,0x68,0x86,0x73,0x70,0x8c,0x75,0x1a,0x57,0x1b,0x1a,0x2a, 0x3a,0xa8,0x38,0x00,0x1c,0x80,0xc6,0x48,0x51,0x94,0xb0,0x89, 0x19,0x2f,0x12,0x62,0xa4,0x34,0x63,0x8f,0xe6,0x6b,0xfc,0xe7, 0xff,0x14,0x64,0x08,0x6b,0xed,0x16,0xd8,0x00,0x65,0x27,0xed, 0x81,0x46,0x44,0xb6,0xdd,0xbb,0x85,0x72,0xe3,0x12,0xa8,0x7b, 0x8d,0xfb,0xe1,0x01,0x27,0x22,0x5e,0x15,0x40,0x6c,0xbe,0x9b, 0x51,0x52,0x89,0x88,0x5f,0x28,0x0e,0xa0,0x4e,0xb9,0x5f,0x28, 0xbe,0x79,0x9d,0x50,0xea,0xb4,0x26,0xb0,0x49,0xad,0xd3,0x02, 0x50,0xa6,0xd6,0x2d,0xf8,0xe5,0xf8,0x33,0x00,0x7c,0x6a,0x9d, 0x16,0x80,0x26,0xb5,0x4e,0x53,0x88,0x76,0x33,0xc9,0xe8,0x45, 0xa4,0xd2,0xe4,0x80,0x4b,0xb9,0xbf,0xd4,0xea,0x1e,0x42,0x78, 0x31,0xc6,0x34,0xc0,0x45,0xfc,0xbe,0xe3,0xcb,0xcd,0x2c,0x2f, 0x88,0x3a,0x5f,0xf6,0xd4,0xce,0xc5,0x31,0xfa,0xac,0x6e,0x38, 0xc1,0x64,0xaa,0x21,0x10,0x53,0xa3,0x50,0x72,0xb8,0x64,0x10, 0x87,0x48,0x38,0x95,0xd5,0x65,0x2e,0x21,0x9a,0xea,0x70,0x75, 0x2e,0x00,0xff,0x5e,0xe0,0x32,0x89,0xd0,0x64,0x00,0x53,0x99, 0x9d,0x67,0x0d,0x8f,0xa1,0x03,0x07,0xa5,0xb8,0x23,0xb1,0xaf, 0xbd,0x75,0x73,0xdd,0xdf,0xeb,0x1f,0x4d,0xc0,0x5a,0x7b,0x0b, 0x5c,0x47,0xf9,0x7c,0x8e,0xf6,0x7a,0x2f,0x22,0x6f,0xb9,0x49, 0xb8,0x8c,0xcd,0x6b,0x60,0x0d,0x9c,0x00,0xe7,0x80,0x01,0x56, 0xc6,0x98,0x36,0x84,0xf0,0x91,0x7b,0x0b,0xd6,0xc0,0xe9,0xc0, 0xd9,0xe5,0x48,0x3e,0x0b,0x80,0xd5,0xc0,0xd9,0xd5,0x48,0x5e, 0x1d,0x40,0x0b,0xbc,0x0f,0x9c,0xed,0x47,0xf2,0x59,0x00,0x0c, 0xbd,0xf3,0xe3,0x48,0x5e,0x97,0x84,0x21,0x84,0xd6,0x18,0xf3, 0xd5,0xe8,0x0c,0x78,0x02,0x1e,0x80,0xbb,0x63,0x6c,0xc1,0x27, 0xa8,0x1a,0x6f,0xa9,0xd1,0x8b,0x31,0xc1,0x00,0x00,0x00,0x00, 0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/sizes32.png000066400000000000000000000006241302634723100165740ustar00rootroot00000000000000‰PNG  IHDR szzôsRGB®ÎéNIDATXÃí–1NÄ0E_v öPq–ÊÍ&=— âî³®h†spŒuW*:¨8€ÆHQ”°‰/b¤4cæküçÿdkíØe'íFD¶Ý»…rã¨{ûá'"^@l¾›QR‰ˆ_( N¹_(¾yPê´&°I­ÓP¦Ö-øåø3|j€&µNSˆv3ÉèE¤Òä€K¹¿ÔêBx1Æ4ÀEü¾ãËÍ,/ˆ:_öÔÎÅ1ú¬n8Ádª!S£Pr¸d‡H8•Õe.!šêpu.ÿ^à2‰ÐdS™g ¡¥¸#±¯½usÝßëMÀZ{ \Gù|Žöz/"o¹I¸ŒÍk` œç€VƘ6„ð‘{ ÖÀéÀÙåH> €ÕÀÙÕH^@ ¼œíGòY ½óãH^—„!„ÖóÕè x€»clÁ'¨o©Ñ‹1ÁIEND®B`‚fityk-1.3.1/wxgui/img/stopmacro16.h000066400000000000000000000036671302634723100171250ustar00rootroot00000000000000static const unsigned char stopmacro16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd7, 0x08, 0x13, 0x00, 0x0a, 0x2a, 0x90, 0x67, 0x14, 0xdb, 0x00, 0x00, 0x00, 0xc9, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0xa5, 0x93, 0x31, 0x0e, 0xc2, 0x30, 0x0c, 0x45, 0x1f, 0x0e, 0xf6, 0xd0, 0x6e, 0xbd, 0x41, 0xc5, 0x21, 0x38, 0x06, 0x3b, 0x23, 0x9c, 0x83, 0xa3, 0xb0, 0xb2, 0xc3, 0x09, 0x3a, 0x72, 0x8c, 0x9e, 0x00, 0x55, 0x1d, 0xa2, 0x6e, 0x65, 0x69, 0x50, 0x28, 0x05, 0x52, 0xb0, 0x14, 0xc5, 0xb2, 0xfc, 0xbe, 0x6d, 0x25, 0x86, 0x3f, 0x6d, 0x31, 0xdc, 0x2b, 0x60, 0xfb, 0x03, 0x7f, 0x0a, 0xce, 0x01, 0x28, 0x66, 0xc2, 0x05, 0x70, 0x90, 0x28, 0x70, 0x03, 0xd6, 0x40, 0x9f, 0x70, 0x76, 0x43, 0x3e, 0x32, 0x52, 0xbd, 0xf6, 0x7d, 0xcf, 0xb7, 0x03, 0x1c, 0x03, 0xb0, 0x9c, 0xea, 0xad, 0xaa, 0x2a, 0x00, 0x54, 0x95, 0x3c, 0xcf, 0x51, 0x55, 0x54, 0x15, 0x33, 0xa3, 0x6d, 0xdb, 0xa7, 0x5c, 0x79, 0x37, 0x60, 0x80, 0x62, 0x58, 0x55, 0x71, 0xce, 0x7d, 0x17, 0x18, 0x43, 0xe1, 0x9e, 0x25, 0x60, 0x66, 0x64, 0x59, 0xf6, 0x04, 0x9b, 0x59, 0x9a, 0xc0, 0x54, 0xe5, 0xe0, 0x8b, 0x48, 0xfa, 0x08, 0x63, 0x78, 0xf6, 0x08, 0x71, 0x37, 0x71, 0x2c, 0xb6, 0x97, 0x67, 0xac, 0xeb, 0x1a, 0xef, 0x3d, 0x5d, 0xd7, 0xe1, 0x9c, 0xc3, 0x7b, 0x8f, 0x88, 0x3c, 0x2a, 0x37, 0x4d, 0xf3, 0x51, 0x60, 0x53, 0x96, 0xe5, 0x39, 0xe1, 0x1b, 0xef, 0xa7, 0x04, 0x0a, 0xe0, 0x12, 0x2d, 0x58, 0xca, 0x2e, 0xfc, 0xbf, 0x8d, 0x77, 0x6d, 0x63, 0x44, 0x3c, 0xcd, 0x85, 0xfe, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/stopmacro16.png000066400000000000000000000004741302634723100174530ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs  šœtIME× *gÛÉIDAT8Ë¥“1Â0 EöÐn½AÅ!8;#œƒ£°²Ã :rŒžU¢neiP(R°Ųü¾m%†?m1Ü+`û Î(fÂp(pÖ@ŸpvC>2R½ö}Ï·°œê­ª*T•<ÏQUT3£mÛ§\y7`€bXUqÎ}Cáž%`fdYö›YšÀTåà‹Húcxöq7q,¶—g¬ëï=]×áœÃ{ˆ<*7MóQ`S–å9áï§ à-XÊ.ü¿wmcD<Í…þ.IEND®B`‚fityk-1.3.1/wxgui/img/strip_bg.xpm000066400000000000000000000022751302634723100171270ustar00rootroot00000000000000/* XPM */ static const char * strip_bg_xpm[] = { "24 24 32 1", " c None", ". c #127704", "+ c #000000", "@ c #4E4E4E", "# c #CCCAC6", "$ c #E0DED9", "% c #D9D8D2", "& c #010A00", "* c #0B4C02", "= c #E4E2DD", "- c #D8D6D1", "; c #C3C2BC", "> c #D1940C", ", c #052501", "' c #031700", ") c #C7C4BB", "! c #9D9A94", "~ c #161616", "{ c #062801", "] c #0D0D0C", "^ c #CAC5BB", "/ c #D0CCC1", "( c #131311", "_ c #BFBBB1", ": c #C8C5B9", "< c #E5E3DD", "[ c #54514D", "} c #A09D94", "| c #C8C4B8", "1 c #D1CEC3", "2 c #7D7A72", "3 c #916708", " ", " ", " .. ", " .... ", " .... .. ", " .. .. ", " .. .. ", " .. .. .", " .. .. ..", " .. .. ...", " +++ .. .. ... ", " + +.. +++ ..... ", " + +..+@#$%++ ... ", " +++&*+=-;++ >> ", " ,')!++ ++++>>>> ", " ....~++>>>++ >>>>++", ".....{]^/++> >> ", ".*++++ (_:<++ ", ".+> + +[}|1++ ", ">+>>2+ +++ ", ">3+++ ", " >> ", " ", " "}; fityk-1.3.1/wxgui/img/sum.xpm000066400000000000000000000013651302634723100161210ustar00rootroot00000000000000/* XPM */ static const char * sum_xpm[] = { "24 24 2 1", " c None", ". c #000000", " ", " ", " ", " ", " .............. ", " .... .. ", " .... . ", " .... . ", " .... ", " .... ", " .... ", " .... ", " .... ", " .... ", " .... ", " .... ", " .... . ", " .... .. ", " .............. ", " ............... ", " ", " ", " ", " "}; fityk-1.3.1/wxgui/img/undo16.h000066400000000000000000000066201302634723100160530ustar00rootroot00000000000000static const unsigned char undo16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x87, 0x00, 0x00, 0x0b, 0x87, 0x01, 0x93, 0x40, 0x87, 0x53, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd6, 0x04, 0x05, 0x13, 0x15, 0x39, 0xbc, 0x3d, 0x70, 0x55, 0x00, 0x00, 0x01, 0xc0, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0xa5, 0x93, 0xcd, 0x4b, 0x54, 0x51, 0x18, 0xc6, 0x7f, 0xf7, 0xdc, 0x3b, 0xd1, 0x28, 0x44, 0x56, 0x82, 0xb4, 0x91, 0x90, 0x36, 0x06, 0xd2, 0x2a, 0x68, 0xd1, 0x1f, 0x90, 0xe1, 0x22, 0x5c, 0x28, 0x89, 0xdc, 0x81, 0x30, 0xc9, 0x1c, 0x62, 0x56, 0x2d, 0xa7, 0x21, 0x68, 0x7b, 0x89, 0x21, 0x70, 0x1c, 0xc2, 0x7b, 0xb5, 0x88, 0x36, 0x0a, 0x89, 0x2d, 0x22, 0x71, 0x21, 0x04, 0x2d, 0x8c, 0x08, 0x32, 0x46, 0x11, 0x9a, 0x10, 0x04, 0x9b, 0x28, 0xa6, 0xaf, 0x8b, 0x73, 0x3d, 0xaf, 0x8b, 0x69, 0xae, 0x33, 0xea, 0xc8, 0x44, 0xef, 0xee, 0x7c, 0x3c, 0xbf, 0xf7, 0x7d, 0x38, 0xcf, 0x81, 0x3a, 0xe5, 0x3a, 0x08, 0x0d, 0x94, 0xfa, 0x1f, 0xf1, 0x81, 0x00, 0xd7, 0x41, 0xec, 0x91, 0x37, 0x8d, 0xea, 0xb1, 0xf6, 0x89, 0x6f, 0xce, 0x03, 0xc1, 0xbe, 0x49, 0x56, 0x22, 0xea, 0xdc, 0xfd, 0x51, 0xbd, 0xcc, 0x61, 0x9e, 0xc5, 0x5f, 0x10, 0x29, 0xa6, 0x44, 0x7e, 0x3f, 0x13, 0x29, 0x7d, 0x10, 0xd9, 0x5a, 0x12, 0x29, 0x7d, 0x14, 0x29, 0x5c, 0x16, 0xd7, 0x41, 0x52, 0x69, 0x75, 0x6b, 0xaf, 0xce, 0xa8, 0xe9, 0xec, 0x3f, 0xaf, 0x32, 0xd7, 0x06, 0xe6, 0xe9, 0xf2, 0x34, 0x91, 0x0b, 0x10, 0x2c, 0xe3, 0x65, 0xfa, 0xc8, 0x5b, 0x6a, 0x34, 0x19, 0xd7, 0x0f, 0x2b, 0xd7, 0x4c, 0xd7, 0x41, 0xec, 0xa1, 0x2c, 0x6c, 0x2d, 0xd6, 0xa2, 0xe5, 0x27, 0xc8, 0x0f, 0x50, 0x27, 0x41, 0x17, 0xe0, 0x48, 0x17, 0xe7, 0x3b, 0x4b, 0x7c, 0x7a, 0xbb, 0xd4, 0xdd, 0xd9, 0xa3, 0x9e, 0x2e, 0xbe, 0x90, 0xaf, 0x00, 0x56, 0xde, 0x52, 0xc3, 0x5e, 0x76, 0x28, 0x63, 0x0f, 0xf6, 0xb0, 0x96, 0x9b, 0x3d, 0xd0, 0x5e, 0xc7, 0x99, 0x16, 0x68, 0x79, 0x0c, 0xd1, 0x6b, 0x04, 0x41, 0x96, 0x26, 0x53, 0x06, 0x80, 0x64, 0x68, 0x21, 0x95, 0x56, 0x37, 0xda, 0x03, 0x9d, 0xb1, 0x07, 0xaf, 0xb0, 0x96, 0x9b, 0xa3, 0xe3, 0xec, 0x25, 0x38, 0xda, 0xfb, 0xd7, 0xca, 0x09, 0x30, 0x9a, 0xd1, 0x28, 0x94, 0x79, 0x1c, 0xfc, 0x69, 0xbc, 0x89, 0x34, 0xb1, 0x44, 0x59, 0x6b, 0x54, 0xba, 0x54, 0x43, 0xd0, 0x45, 0xbc, 0x27, 0xbb, 0x96, 0xb4, 0x86, 0x7e, 0xfb, 0x11, 0xd1, 0xe8, 0x31, 0x50, 0x16, 0xde, 0xd8, 0xd5, 0x10, 0x10, 0xe6, 0x20, 0x19, 0xd7, 0xe3, 0x79, 0x4b, 0x0d, 0x7b, 0x53, 0x73, 0x60, 0x9e, 0x02, 0x20, 0x96, 0xc0, 0x88, 0x25, 0x30, 0x7e, 0x99, 0xbc, 0x7b, 0xfd, 0xea, 0x3a, 0xc8, 0x1f, 0x10, 0xbf, 0x7e, 0x90, 0x42, 0xc8, 0xe4, 0x4c, 0xcd, 0xa5, 0x4d, 0x53, 0xdd, 0x59, 0xdf, 0x00, 0x8c, 0x66, 0xd8, 0x5e, 0x3f, 0x3c, 0x89, 0x15, 0x48, 0xf5, 0xde, 0xbd, 0xb8, 0x7e, 0x59, 0x7e, 0x99, 0x22, 0x85, 0x2f, 0xdf, 0xea, 0x27, 0xb1, 0x1a, 0x02, 0x8c, 0x87, 0xeb, 0xb4, 0xea, 0x23, 0xd0, 0xb0, 0xfd, 0x99, 0xd5, 0xd5, 0xf7, 0xf8, 0x70, 0x97, 0x7f, 0x29, 0xd7, 0x41, 0xe4, 0x7b, 0x42, 0x64, 0xf3, 0xa2, 0xec, 0xfd, 0x68, 0x56, 0x23, 0x80, 0x0d, 0xd3, 0x78, 0xe0, 0x4d, 0x38, 0xb7, 0x01, 0x72, 0x11, 0xd5, 0x0a, 0x3a, 0x3c, 0xdb, 0x01, 0x39, 0x07, 0xc0, 0x21, 0x06, 0x3a, 0xdd, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/undo16.png000066400000000000000000000010631302634723100164040ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs ‡ ‡“@‡StIMEÖ9¼=pUÀIDAT8Ë¥“ÍKTQÆ÷Ü;Ñ(DV‚´‘6Ò*hÑá"\(‰Ü0ÉbV-§!h{‰!pÂ{µˆ6 ‰-"q!-Œ2Fš›(¦¯‹s=¯‹i®3êÈDïî|<¿÷}8Ï:å: ”úñ×Aì‘7ê±ö‰oÎÁ¾IV"êÜýQ½ÌažÅ_)¦D~?)}ÙZ)})\×ARiuk¯Î¨éì?¯2׿éò4‘ ,ãeúÈ[j4×+×L×Aì¡,l-Ö¢å'ÈP'AàHç;K|z»ÔÝÙ£ž.¾¯VÞRÃ^v(cö°–›=Ð^Ç™hy ÑkA–&S€dh!•V7Ú±¯°–›£ãì%8Úû×Ê 0šÑ(”yüi¼‰4±DYkTºTCÐE¼'»–´†~ûÑè1PÞØÕæ ×ãyK {Ss`ž –Àˆ%0~™¼{ýê:È¿~BÈäLÍ¥MSÝYߌfØ^?<‰HõÞ½¸~Y~™"…/ßê'±Œ‡ë´ê#аý™ÕÕ÷øp—)×Aä{Bdó¢ìýhV#€ ÓxàM8·rÕ :<Û9À!:Ý÷IEND®B`‚fityk-1.3.1/wxgui/img/undo_fit.xpm000066400000000000000000000056561302634723100171330ustar00rootroot00000000000000/* XPM */ static const char * undo_fit_xpm[] = { "24 24 105 2", " c None", ". c #000000", "+ c #CFCECA", "@ c #E1E1E0", "# c #97958F", "$ c #888680", "% c #8C8A83", "& c #7F7C74", "* c #EFE5BA", "= c #7B7973", "- c #66645E", "; c #3F3E3A", "> c #65635E", ", c #EFE7C1", "' c #EED680", ") c #DDDCDB", "! c #999891", "~ c #52514D", "{ c #161513", "] c #EFE4B6", "^ c #D5B75D", "/ c #B29544", "( c #797873", "_ c #82807A", ": c #D1B051", "< c #888681", "[ c #C0AF73", "} c #C0A048", "| c #986B07", "1 c #D1940C", "2 c #E0B74C", "3 c #D9C374", "4 c #8F6406", "5 c #D59D1C", "6 c #B1933F", "7 c #DFB74A", "8 c #CCB76D", "9 c #7C7B75", "0 c #494845", "a c #B8820A", "b c #D9A72E", "c c #504E48", "d c #42423F", "e c #484641", "f c #8E8C86", "g c #3A3937", "h c #23221F", "i c #2F2D2A", "j c #D7A62C", "k c #C7B26A", "l c #E2E2E1", "m c #B6B5AF", "n c #9F9D96", "o c #595854", "p c #1E1D1B", "q c #090807", "r c #151514", "s c #D4B150", "t c #A39256", "u c #242421", "v c #898883", "w c #33312D", "x c #141413", "y c #5A5958", "z c #E2CB79", "A c #898781", "B c #8E8C85", "C c #838078", "D c #B0AFA9", "E c #807D74", "F c #AAA9A4", "G c #DBDBD9", "H c #C9B46B", "I c #8D7E4A", "J c #67655F", "K c #403F3B", "L c #686661", "M c #7C7A72", "N c #D6D5D2", "O c #ABA9A3", "P c #75736A", "Q c #AE9C5C", "R c #96864F", "S c #3B3A36", "T c #9A9992", "U c #53524E", "V c #171614", "W c #767573", "X c #9B9993", "Y c #52504A", "Z c #44423D", "` c #4E4C46", " . c #3E3E39", ".. c #7A7974", "+. c #86847D", "@. c #9A9996", "#. c #B7B6B3", "$. c #7D7B75", "%. c #42413C", "&. c #8A8883", "*. c #6B6964", "=. c #78756C", "-. c #5F5D56", ";. c #54534D", ">. c #403F3A", " . . . . ", " . . . + . . . . . ", " . @ # $ % & . * . ", " . . = - ; > . , ' . . . . ", " . ) ! ~ { . ] ' ' ' ' ^ / . ", " . . ( _ . * ' ' ' ' ' ' ' : . ", " . < . [ ' ' ' ' ' ' ' ' ' } . ", " . . . . | 1 1 1 1 1 1 2 ' 3 . . ", " . . . 4 1 1 1 1 1 1 5 ' 6 . ", " . 4 1 . . . | 1 7 8 . ", " . . | . 9 0 . a b ' . ", " . . . 0 c d . 1 ' . ", " . . e f . g h i . j k . . ", " . . . . l m n o p q r . s t u . ", " . . . + . . . . . e n v w x y . z . . . ", " . @ # A B C . . D E F G . H I . . . ", " . . = J K L M . . . N O n P . Q R . S . ", " . ) T U V W X Y . . . o . Z ` . . .. . ", " . . ..+.@.#.$.. . . . . %.. . . . ", " . &.*.=.-.;.. . . . . ", " . . . >.. . . ", " . . . ", " ", " "}; fityk-1.3.1/wxgui/img/unused.xpm000066400000000000000000000006471302634723100166220ustar00rootroot00000000000000/* XPM */ static const char * unused_xpm[] = { "16 16 3 1", " c None", ". c #000000", "+ c #3E3E3E", ".+ .", " .+ .+", " .+ .+ ", " .+ .+ ", " .+ .+ ", " .+ .+ ", " .+ .+ ", " .++ ", " .++ ", " .+ .+ ", " .+ .+ ", " .+ .+ ", " .+ .+ ", " .+ .+ ", " .+ .+", ".+ ."}; fityk-1.3.1/wxgui/img/web16.h000066400000000000000000000103611302634723100156600ustar00rootroot00000000000000static const unsigned char web16_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d, 0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10, 0x08,0x06,0x00,0x00,0x00,0x1f,0xf3,0xff,0x61,0x00,0x00,0x00, 0x06,0x62,0x4b,0x47,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0xf9, 0x43,0xbb,0x7f,0x00,0x00,0x03,0x01,0x49,0x44,0x41,0x54,0x78, 0xda,0x5d,0x93,0x4b,0x6b,0x24,0x65,0x14,0x86,0x9f,0xea,0xaa, 0xbe,0x26,0xdd,0x1d,0xed,0x24,0x4e,0x12,0x6d,0x3a,0xb1,0xe3, 0x98,0x8c,0x71,0x5c,0x0d,0x0e,0x08,0x22,0x62,0x02,0x2a,0x88, 0x9b,0x01,0x19,0x77,0x6e,0x04,0x41,0x04,0x07,0xc6,0xad,0xb8, 0xd4,0x3f,0x20,0x5e,0xf0,0x07,0xc8,0x20,0xea,0x72,0x40,0x12, 0xd0,0x24,0x98,0xe0,0x8c,0x26,0x4c,0x4c,0x9c,0x5c,0xba,0x93, 0x49,0xc7,0xee,0x74,0x75,0xdd,0xbf,0xaa,0xfa,0xaa,0xca,0x85, 0x3d,0xd0,0x7a,0x56,0xe7,0xc0,0x79,0x5e,0xde,0xc5,0xfb,0x2a, 0xfc,0x6f,0x2a,0x93,0xb5,0xdc,0x85,0xa9,0x27,0x66,0x87,0x0a, 0xb9,0x6a,0xe0,0xda,0x9a,0xa2,0xa6,0x63,0x4b,0x84,0x76,0xef, 0xbc,0xb3,0xd1,0x69,0xee,0x39,0x40,0x3c,0xf8,0xaf,0x0d,0x1e, 0x63,0x33,0x0b,0xa3,0xf5,0xe9,0xea,0xa7,0xd5,0xa9,0xf1,0x57, 0x7c,0xc7,0x1e,0xb7,0x4c,0x25,0x25,0xfc,0x90,0x52,0xb1,0x18, 0x04,0x9e,0x7b,0xb7,0x34,0x31,0xfd,0x99,0x79,0x7a,0x70,0x0b, 0x48,0x1e,0x32,0xca,0xc3,0x65,0xe1,0xea,0x4b,0x8b,0xc5,0xac, 0xfa,0xf9,0xe5,0x67,0x2e,0xd5,0x16,0x5f,0x7f,0x83,0xf9,0x85, 0xcb,0xa8,0x9a,0x86,0x6e,0x79,0xc8,0x20,0x40,0x3f,0x6b,0xf2, 0xd1,0x87,0x1f,0xc4,0xcd,0x07,0xad,0x2f,0x5c,0x4f,0xdc,0xf4, 0x8d,0xb6,0x01,0xa0,0xf6,0xf9,0xf2,0xf4,0x74,0xed,0x87,0xc5, 0xa5,0xa5,0xda,0x3b,0xef,0xbe,0xa7,0x54,0x2e,0x4c,0xd2,0x13, 0x11,0x86,0xe3,0x13,0x27,0x11,0x95,0x62,0x9e,0x47,0x46,0xc7, 0x79,0x79,0xe9,0x35,0x65,0x67,0x77,0xaf,0x7e,0xb4,0xbb,0x95, 0x89,0x64,0xb8,0x0c,0x24,0x2a,0x90,0x9e,0xbb,0xf2,0xe2,0x27, 0x93,0x8f,0x8d,0xbd,0xfa,0xfe,0x8d,0x9b,0x8a,0x1d,0xc4,0xf4, 0x1c,0x41,0x94,0x4a,0x23,0x23,0x90,0x52,0x12,0x86,0x92,0x20, 0x94,0x64,0xb2,0x39,0x1e,0xaf,0xcf,0xe5,0xd6,0x56,0x7e,0x7a, 0xce,0xd4,0x3b,0xdf,0x03,0x1d,0x35,0x5f,0xaa,0x54,0x2f,0xce, 0x5d,0xfa,0xf8,0xda,0xf5,0xeb,0xa3,0x85,0x52,0x85,0xfb,0x2d, 0x03,0x89,0x4a,0x94,0x80,0x23,0x02,0xb2,0x9a,0x42,0x46,0x4d, 0xd1,0x3a,0x37,0x38,0xd7,0x0d,0x32,0xf9,0x02,0x42,0x26,0xda, 0xef,0x6b,0x2b,0x00,0xb7,0xb5,0x62,0xa9,0x34,0x6d,0x9b,0x7a, 0xb5,0xa1,0x27,0x9c,0x6c,0xfe,0x49,0xb1,0x5c,0x26,0x2b,0x42, 0x54,0x55,0x03,0x12,0x66,0x2e,0x4e,0x21,0x7c,0x9f,0xe1,0xe1, 0x02,0x96,0xe3,0x70,0x6e,0xd8,0xd4,0x9e,0x7e,0x56,0x05,0xe5, 0x05,0x48,0x86,0x34,0xcf,0x13,0x85,0xb3,0xd6,0xdf,0xe9,0xd2, 0x48,0x99,0x18,0xb0,0x5d,0x97,0xae,0xe9,0xa2,0x69,0x1a,0xf9, 0x6c,0x9a,0x40,0x46,0x38,0x7e,0x88,0xed,0x78,0x78,0x7e,0x88, 0x63,0xbb,0xdc,0xbd,0xd7,0x04,0x18,0x01,0xf2,0x5a,0xe0,0x8b, 0xa0,0x67,0x5a,0xd1,0xf2,0xfa,0x56,0xfa,0xcd,0xc5,0xe7,0x19, 0x29,0x17,0xb9,0x77,0xf0,0x80,0xfb,0xc7,0xad,0x7f,0x01,0xd3, 0x80,0x58,0x32,0x3f,0x5b,0x23,0xf0,0x25,0x3d,0xd3,0xe2,0xa8, 0x71,0x0c,0x24,0x31,0xa0,0x69,0xa1,0x70,0xda,0x99,0xa1,0xb2, 0x11,0xc9,0x20,0x27,0x65,0x84,0x94,0x21,0x4f,0x55,0xc7,0x89, 0x64,0xc8,0xc6,0xf6,0x3e,0x9b,0x5b,0x5d,0x6c,0xcb,0xa5,0x5e, 0x9d,0x20,0x88,0x62,0xf6,0x8f,0x4e,0x38,0x3b,0x69,0x46,0x40, 0x1b,0x90,0xa9,0x58,0x06,0x07,0xc2,0xea,0xfe,0xfc,0xc7,0xfa, 0x72,0xb4,0x7e,0x67,0x1b,0xdb,0xf5,0x11,0x41,0xc8,0xee,0xee, 0x3e,0x86,0xae,0x63,0x5b,0x16,0x86,0x69,0xd0,0xe9,0x19,0xf8, 0x52,0x72,0x78,0xd8,0x48,0xba,0x7b,0xab,0x3a,0xf0,0x0b,0x60, 0xa7,0x00,0x3b,0x74,0xcd,0x6f,0xda,0x3b,0x6b,0xc1,0xea,0xea, 0x26,0x71,0x02,0x9d,0xb6,0xce,0xce,0xde,0x3e,0x8e,0x6d,0x63, 0x5b,0x16,0xbe,0xe7,0xd2,0xd1,0x6d,0x74,0xc3,0x61,0x63,0xe5, 0x76,0x18,0xe8,0x27,0x1e,0x70,0x0b,0x10,0x6a,0x3f,0x96,0x8d, 0x28,0x70,0x2b,0xe6,0xd9,0x61,0x7d,0x62,0x76,0x3e,0xbd,0xbe, 0xb1,0xad,0x9e,0x9c,0xb6,0x91,0xbe,0x40,0xb8,0x0e,0xc2,0x15, 0x34,0x1a,0x87,0xf1,0xf2,0x8f,0xdf,0xfa,0xfa,0x5f,0x6b,0x1d, 0xe0,0x2b,0xe0,0x3b,0xc0,0x53,0x06,0x22,0x3d,0x01,0xdc,0xc8, 0x16,0x86,0xdf,0xce,0x8c,0x3e,0x99,0xe4,0xc7,0x66,0x1e,0xd5, 0x0a,0x25,0x2d,0x0e,0xfd,0x58,0x98,0x1d,0xdb,0x6a,0xfc,0xe6, 0x45,0xf6,0xb9,0x04,0xbe,0x06,0xbe,0x04,0x8e,0x81,0x58,0x19, 0xe8,0x92,0x02,0x14,0x80,0x2b,0xc0,0x5b,0xc0,0x55,0xa0,0xdc, 0x77,0x78,0x0a,0xdc,0xe9,0xdb,0xfe,0x15,0x30,0x81,0xe8,0x3f, 0x65,0x1a,0x10,0xc9,0x00,0x45,0xa0,0xd2,0x17,0x54,0x00,0x01, 0x74,0xfb,0xa0,0x37,0xd8,0xc6,0x7f,0x00,0xdf,0x9b,0x9d,0x76, 0x97,0x57,0x37,0x42,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44, 0xae,0x42,0x60,0x82, }; fityk-1.3.1/wxgui/img/web16.png000066400000000000000000000015141302634723100162150ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC»IDATxÚ]“Kk$e†Ÿêª¾&Ýí$Nm:±ã˜Œq\ "b*ˆ›wnAÆ­¸Ô? ^ðÈ êr@Ð$˜àŒ&LLœ\º“IÇîtuÝ¿ªúªÊ…=ÐzVçÀy^ÞÅû*üo*“µÜ…©'f‡ ¹jàÚš¢¦cK„vï¼³Ñiî9@<ø¯ c3 £õéê§Õ©ñW|Ç·L%%üR±ž{·41ý™yzp H2ÊÃeáêK‹Å¬úùåg.Õ_ƒù…˨š†nyÈ @?kòчÄÍ­/\OÜô¶ öùòôtí‡Å¥¥Ú;ï¾§T.LÒ†ã'•bžGFÇyyé5egw¯~´»•‰d¸ $*ž»òâ'“½úþ›ŠÄôA”J##R†’ ”d²9¯ÏåÖV~zÎÔ;ß5_ªT/Î]úøÚõ룅R…û-‰J”€#²šBFMÑ:78× 2ùB&Úïk+·µb©4m›zµ¡'œlþI±\&+BTUf.N!|Ÿáá–ãpnØÔž~VåH†4Ï…³ÖßéÒH™°]—®é¢iùlš@F8~ˆíxx~ˆc»Ü½×òZà‹ gZÑòúVúÍÅç)¹wð€ûÇ­Ó€X2?[#ð%=Óâ¨q $1 i¡pÚ™¡²É 'e„”!OUljdÈÆö>›[]lË¥^ ˆböN8;iF@©XÂêþüÇúr´~gÛõAÈîî>†®c[†iÐéøRrxØHº{«:ð `§;tÍoÚ;kÁêê&q¶ÎÎÞ>Žmc[¾çÒÑmtÃacåvè'p j?–(p+æÙa}bv>½¾±­žœ¶‘¾@¸Â4‡ñòßúú_kà+à;ÀS"=ÜȆßÎŒ>™äÇfÕ %-ýX˜ÛjüæEö¹¾¾ŽXè’€+À[ÀU Üwx ÜéÛþ0è?eÉE ÒTtû 7ØÆß›v—W7BIEND®B`‚fityk-1.3.1/wxgui/img/zoom-fit16.h000066400000000000000000000056561302634723100166620ustar00rootroot00000000000000static const unsigned char zoom_fit16_png[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, 0x61, 0x00, 0x00, 0x00, 0x06, 0x62, 0x4b, 0x47, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x43, 0xbb, 0x7f, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0b, 0x12, 0x00, 0x00, 0x0b, 0x12, 0x01, 0xd2, 0xdd, 0x7e, 0xfc, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5, 0x04, 0x09, 0x16, 0x1c, 0x39, 0xa7, 0x76, 0xc4, 0xe1, 0x00, 0x00, 0x01, 0x70, 0x49, 0x44, 0x41, 0x54, 0x38, 0xcb, 0x95, 0x92, 0xbd, 0x6e, 0xe2, 0x40, 0x14, 0x85, 0x3f, 0xbc, 0x79, 0x0f, 0x5b, 0x29, 0x78, 0x02, 0x2a, 0x9a, 0x74, 0x53, 0xed, 0x7b, 0xac, 0x1b, 0x24, 0x8a, 0x34, 0x14, 0x5b, 0x22, 0x9e, 0x03, 0xc9, 0x1d, 0x0d, 0x4f, 0x40, 0x47, 0xe5, 0x2e, 0x05, 0xed, 0x16, 0x60, 0x61, 0x59, 0x8b, 0x25, 0x87, 0x28, 0x3f, 0x63, 0x7b, 0xce, 0x16, 0xb1, 0x59, 0x48, 0x80, 0xdd, 0x1c, 0x69, 0x34, 0x9a, 0xd1, 0xcc, 0x37, 0xe7, 0x9e, 0xb9, 0x70, 0xaa, 0x7b, 0x20, 0x06, 0xde, 0x9a, 0x11, 0x37, 0x7b, 0xff, 0xd4, 0x2d, 0x10, 0x77, 0xbb, 0x5d, 0x2d, 0x97, 0x4b, 0xe5, 0x79, 0xae, 0xdd, 0x6e, 0xa7, 0xd9, 0x6c, 0x26, 0x63, 0x8c, 0x1a, 0xd0, 0xed, 0x35, 0x40, 0x3c, 0x99, 0x4c, 0x54, 0x14, 0x85, 0x9c, 0x73, 0x72, 0xce, 0xa9, 0xae, 0x6b, 0x55, 0x55, 0xa5, 0x2c, 0xcb, 0x34, 0x1c, 0x0e, 0x5b, 0xc8, 0x59, 0xdd, 0x1b, 0x63, 0x54, 0x14, 0x85, 0x00, 0x01, 0x6a, 0xd5, 0xae, 0xd3, 0x34, 0x6d, 0x9d, 0x9c, 0x2d, 0x27, 0x9e, 0xcf, 0xe7, 0x72, 0xce, 0x1d, 0x2e, 0x3b, 0xe7, 0x4e, 0x20, 0xd6, 0x5a, 0x45, 0x51, 0x74, 0xd1, 0xc5, 0x5b, 0x9e, 0xe7, 0x07, 0xdb, 0x6d, 0x09, 0xc7, 0x10, 0x6b, 0xad, 0x92, 0x24, 0x51, 0x13, 0xec, 0x89, 0x6e, 0x78, 0x7f, 0x16, 0x49, 0x78, 0x9e, 0xf7, 0x89, 0xfe, 0x6e, 0xe2, 0xef, 0xfc, 0x51, 0x1e, 0xf0, 0xb0, 0x58, 0x2c, 0x90, 0x44, 0xa7, 0xd3, 0xf9, 0x7c, 0xc0, 0xf3, 0x90, 0xc4, 0x6a, 0xb5, 0x02, 0x78, 0xb8, 0x18, 0x62, 0x96, 0x65, 0x87, 0xd0, 0x5a, 0xfb, 0xed, 0x7a, 0xbb, 0xdd, 0x5e, 0x0d, 0x11, 0x20, 0x1e, 0x8f, 0xc7, 0x4a, 0xd3, 0x54, 0xd6, 0x5a, 0x55, 0x55, 0xa5, 0xba, 0xae, 0x55, 0x96, 0xa5, 0xd6, 0xeb, 0xb5, 0x06, 0x83, 0x81, 0x80, 0x0a, 0xf8, 0x71, 0xb5, 0x91, 0x8c, 0x31, 0x8a, 0xa2, 0x48, 0x49, 0x92, 0x68, 0xb3, 0xd9, 0x68, 0x3a, 0x9d, 0xb6, 0x2f, 0xbf, 0x02, 0x8f, 0xc0, 0x1e, 0xf8, 0x05, 0x7c, 0xbf, 0xd8, 0x13, 0x67, 0x5a, 0xf9, 0x27, 0xe0, 0x07, 0x41, 0xb0, 0x0f, 0x82, 0xe0, 0x09, 0x78, 0x06, 0x0a, 0xa0, 0x7f, 0xf2, 0x13, 0x8d, 0xbe, 0x1d, 0x8d, 0xe3, 0x44, 0x7d, 0xe0, 0x77, 0x18, 0x86, 0x65, 0xaf, 0xd7, 0x7b, 0x69, 0xdc, 0x3c, 0x37, 0xfb, 0xff, 0x2d, 0x1f, 0xd8, 0x8f, 0x46, 0xa3, 0xba, 0xdf, 0xef, 0x57, 0x4d, 0x39, 0x4f, 0x5f, 0x05, 0xf8, 0xc0, 0x6b, 0x18, 0x86, 0xa5, 0xef, 0xfb, 0xe5, 0x57, 0x01, 0xc7, 0x90, 0x2d, 0x50, 0x03, 0x77, 0x7f, 0x00, 0xe1, 0xc1, 0x1b, 0x86, 0xaa, 0x55, 0x71, 0x63, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, }; fityk-1.3.1/wxgui/img/zoom-fit16.png000066400000000000000000000007431302634723100172070ustar00rootroot00000000000000‰PNG  IHDRóÿabKGDùC» pHYs  ÒÝ~ütIMEÕ 9§vÄápIDAT8Ë•’½nâ@…?¼y[)x*štSí{¬$Š4["žÉ O@Gå.í`aY‹%‡(?c{αYH€Ýi4šÑÌ7çž¹pª{ Þš7{ÿÔ-w»]-—Kåy®Ýn§Ùl&cŒÐí5@<™LT…œsrΩ®kUU¥,Ë4[ÈYÝcT…jÕ®Ó4mœ-'žÏçrÎ.;çN ÖZEQtÑÅ[žçÛm Çk­’$Qì‰nxIxž÷‰þnâïüQð°X,D§Óù|ÀóÄjµx¸b–e‡ÐZûíz»Ý^  ÇJÓTÖZUU¥º®U–¥Ö뵃€ øqµ‘Œ1Š¢HI’h³Ùh:¶/¿Àø|¿ØgZù'àA°‚à x  ò¾ãD}àw†e¯×{iÜ<7ûÿ-ØF£ºßïWM9O_øÀk†¥ïûåWÇ-PwáÁ†ªUqcIEND®B`‚fityk-1.3.1/wxgui/img/zoom_all.xpm000066400000000000000000000067361302634723100171400ustar00rootroot00000000000000/* XPM */ static const char * zoom_all_xpm[] = { "24 24 140 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #464646", "e c #4B4B4B", "f c #505050", "g c #525252", "h c #FBFBFB", "i c #FAFAFA", "j c #515151", "k c #4F4F4F", "l c #4A4A4A", "m c #C2C2C2", "n c #434343", "o c #0F0F0F", "p c #1F1F1F", "q c #B9B9B9", "r c #D6D6D6", "s c #535353", "t c #FDFDFD", "u c #FCFCFC", "v c #4D4D4D", "w c #E4E4E4", "x c #ABABAB", "y c #0E0E0E", "z c #1B1B1B", "A c #6D6D6D", "B c #E1E1E1", "C c #FEFEFE", "D c #F9F9F9", "E c #4E4E4E", "F c #E6E6E6", "G c #575757", "H c #090909", "I c #141414", "J c #A8A8A8", "K c #D8D8D8", "L c #EEEEEE", "M c #F8F8F8", "N c #DCDCDC", "O c #9B9B9B", "P c #060606", "Q c #111111", "R c #C5C5C5", "S c #DFDFDF", "T c #F5F5F5", "U c #F7F7F7", "V c #F2F2F2", "W c #EDEDED", "X c #BFBFBF", "Y c #C6C6C6", "Z c #E3E3E3", "` c #ECECEC", " . c #F4F4F4", ".. c #F0F0F0", "+. c #EAEAEA", "@. c #E0E0E0", "#. c #D7D7D7", "$. c #BABABA", "%. c #050505", "&. c #0B0B0B", "*. c #A5A5A5", "=. c #F6F6F6", "-. c #D1D1D1", ";. c #939393", ">. c #020202", ",. c #0A0A0A", "'. c #5F5F5F", "). c #D9D9D9", "!. c #E9E9E9", "~. c #484848", "{. c #D4D4D4", "]. c #000000", "^. c #494949", "/. c #474747", "(. c #454545", "_. c #CBCBCB", ":. c #3B3B3B", "<. c #DADADA", "[. c #444444", "}. c #414141", "|. c #BDBDBD", "1. c #C7C7C7", "2. c #CDCDCD", "3. c #C8C8C8", "4. c #B8B8B8", "5. c #030303", "6. c #313131", "7. c #999999", "8. c #BBBBBB", "9. c #B6B6B6", "0. c #909090", "a. c #2B2B2B", "b. c #010101", "c. c #7A7A7A", "d. c #9A9A9A", "e. c #777777", "f. c #3C3C3C", "g. c #686868", "h. c #797979", "i. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d e f g h i j f k l m n o ", " p q r : g g s t u g j k v w x y ", " z A 7 B f g t C C t u D f E F 1 G H ", " I J K L j g u C C t h M f E F N O P ", " Q R S 3 T M h t t u i U V W 6 1 X P ", " y Y Z ` V T M i i i U ...+.@.#.$.%. ", " &.*.B 2 E k .=.=.T 4 3 v e 1 -.;.>. ", " ,.'.).B e v L 3 3 L W !.e ~.{.~ : ]. ", " ,.= K ~.l e e F 2 l ^./.(._.* >. ", " P :.c (.(./.~.<.1 /.d [.}.|.$ ]. ", " %.j m 1._.c 2._._.3.m 4.(.]. ", " 5.6.7.8.|.8 8 8 9.0.a.].].]. ", " b.5.}.c.d.d.e.f.].]. ].].].]. ", " ].].].].].]. , , ].]. ", " ].g.. ].]. ", " ].h.i.].]. ", " ].g.p ]. ", " ].]. ", " "}; fityk-1.3.1/wxgui/img/zoom_left.xpm000066400000000000000000000066571302634723100173240ustar00rootroot00000000000000/* XPM */ static const char * zoom_left_xpm[] = { "24 24 137 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #D7D7D7", "e c #F5F5F5", "f c #FAFAFA", "g c #FBFBFB", "h c #F8F8F8", "i c #F0F0F0", "j c #E1E1E1", "k c #C2C2C2", "l c #434343", "m c #0F0F0F", "n c #1F1F1F", "o c #B9B9B9", "p c #D6D6D6", "q c #AEAEAE", "r c #828282", "s c #FDFDFD", "t c #FFFFFF", "u c #F2F2F2", "v c #ECECEC", "w c #E4E4E4", "x c #ABABAB", "y c #0E0E0E", "z c #1B1B1B", "A c #6D6D6D", "B c #818181", "C c #B1B1B1", "D c #FEFEFE", "E c #FCFCFC", "F c #F9F9F9", "G c #EEEEEE", "H c #E6E6E6", "I c #575757", "J c #090909", "K c #141414", "L c #A8A8A8", "M c #D8D8D8", "N c #B0B0B0", "O c #F4F4F4", "P c #DCDCDC", "Q c #9B9B9B", "R c #060606", "S c #111111", "T c #707070", "U c #4D4D4D", "V c #444444", "W c #454545", "X c #EDEDED", "Y c #BFBFBF", "Z c #EAEAEA", "` c #E0E0E0", " . c #BABABA", ".. c #050505", "+. c #0B0B0B", "@. c #A5A5A5", "#. c #7F7F7F", "$. c #F6F6F6", "%. c #D1D1D1", "&. c #939393", "*. c #020202", "=. c #0A0A0A", "-. c #5F5F5F", ";. c #D9D9D9", ">. c #7B7B7B", ",. c #E9E9E9", "'. c #D4D4D4", "). c #000000", "!. c #646464", "~. c #E3E3E3", "{. c #DFDFDF", "]. c #DADADA", "^. c #CBCBCB", "/. c #3B3B3B", "(. c #D5D5D5", "_. c #C8C8C8", ":. c #BDBDBD", "<. c #515151", "[. c #C7C7C7", "}. c #CDCDCD", "|. c #B8B8B8", "1. c #030303", "2. c #313131", "3. c #999999", "4. c #BBBBBB", "5. c #B6B6B6", "6. c #909090", "7. c #2B2B2B", "8. c #010101", "9. c #414141", "0. c #7A7A7A", "a. c #9A9A9A", "b. c #777777", "c. c #3C3C3C", "d. c #686868", "e. c #797979", "f. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d 6 e f g f h e i j k l m ", " n o p 2 q r s t t g h u v w x y ", " z A 7 j B l C D t t E F e G H 1 I J ", " K L M l l r N D t t g h O G H P Q R ", " S T U l l V V W W W V t t X 6 1 Y R ", " y T U l l l V V V V l t t Z ` d ... ", " +.@.j l l #.x $.t t 4 3 v w 1 %.&.*. ", " =.-.;.j >.l L 3 X X X ,.w 1 '.~ : ). ", " =.= M P * !.H X X ~.{.].'.^.* *. ", " R /.c 7 '.].1 ].1 M (.] _.:.$ ). ", " ..<.k [.^.c }.^.^._.k |.W ). ", " 1.2.3.4.:.8 8 8 5.6.7.).).). ", " 8.1.9.0.a.a.b.c.).). ).).).). ", " ).).).).).). , , ).). ", " ).d.. ).). ", " ).e.f.).). ", " ).d.n ). ", " ).). ", " "}; fityk-1.3.1/wxgui/img/zoom_mode.xpm000066400000000000000000000065171302634723100173110ustar00rootroot00000000000000/* XPM */ static const char * zoom_mode_xpm[] = { "24 24 131 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #000000", "} c #222222", "| c #757575", "1 c #D3D3D3", "2 c #DBDBDB", "3 c #E7E7E7", "4 c #EFEFEF", "5 c #F3F3F3", "6 c #F1F1F1", "7 c #E5E5E5", "8 c #D2D2D2", "9 c #BCBCBC", "0 c #5E5E5E", "a c #101010", "b c #212121", "c c #383838", "d c #CCCCCC", "e c #858585", "f c #979797", "g c #FAFAFA", "h c #9B9B9B", "i c #999999", "j c #F5F5F5", "k c #949494", "l c #E1E1E1", "m c #787878", "n c #434343", "o c #060606", "p c #1F1F1F", "q c #B9B9B9", "r c #D6D6D6", "s c #F9F9F9", "t c #FBFBFB", "u c #FDFDFD", "v c #FCFCFC", "w c #F8F8F8", "x c #F2F2F2", "y c #ECECEC", "z c #E4E4E4", "A c #ABABAB", "B c #0E0E0E", "C c #111111", "D c #6D6D6D", "E c #FEFEFE", "F c #EEEEEE", "G c #E6E6E6", "H c #575757", "I c #090909", "J c #141414", "K c #A8A8A8", "L c #D8D8D8", "M c #F6F6F6", "N c #F4F4F4", "O c #DCDCDC", "P c #C5C5C5", "Q c #DFDFDF", "R c #F7F7F7", "S c #EDEDED", "T c #BFBFBF", "U c #C6C6C6", "V c #E3E3E3", "W c #F0F0F0", "X c #EAEAEA", "Y c #E0E0E0", "Z c #D7D7D7", "` c #BABABA", " . c #050505", ".. c #A5A5A5", "+. c #D1D1D1", "@. c #939393", "#. c #020202", "$. c #0A0A0A", "%. c #5F5F5F", "&. c #D9D9D9", "*. c #EBEBEB", "=. c #E9E9E9", "-. c #D4D4D4", ";. c #030303", ">. c #E2E2E2", ",. c #DADADA", "'. c #CBCBCB", "). c #3B3B3B", "!. c #D5D5D5", "~. c #C8C8C8", "{. c #BDBDBD", "]. c #515151", "^. c #C2C2C2", "/. c #C7C7C7", "(. c #CDCDCD", "_. c #B8B8B8", ":. c #454545", "<. c #313131", "[. c #BBBBBB", "}. c #B6B6B6", "|. c #909090", "1. c #2B2B2B", "2. c #010101", "3. c #414141", "4. c #7A7A7A", "5. c #9A9A9A", "6. c #777777", "7. c #3C3C3C", "8. c #686868", "9. c #797979", "0. c #3A3A3A", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", "[ [ } | ~ 1 2 3 4 5 6 7 8 9 0 a [ [ ", "[ [ b c d e 7 f g h g i j k l m n o [ [ ", " p q r 3 s t u u v t w x y z A B ", " C D 8 l j g u E E u v s j F G 2 H I [ ", " J K L F M s v E E u t w N F G O h o ", " a P Q 4 j w t u u v g R x S 7 2 T o [ ", " B U V y x j w g g g R N W X Y Z ` . ", " I ..l 3 S 6 N M M j 5 4 y z 2 +.@.#.[ ", " $.%.&.l G *.F 4 4 F S =.z 2 -.~ : [ ", " ;.$.= L O >.7 G G 3 V Q ,.-.'.* #. [ ", " o ).d 8 -.,.2 ,.2 L !.] ~.{.$ [ ", " [ .].^./.'.d (.'.'.~.^._.:.[ [ ", " ;.<.i [.{.9 9 9 }.|.1.[ [ [ ", " [ 2.;.3.4.5.5.6.7.[ [ [ [ [ [ ", " [ [ [ [ [ [ , , [ [ ", " [ [ 8.[ [ [ ", " [ 9.0.[ [ ", "[ [ [ [ [ [ [ [ [ [ [ [ p [ ", "[ [ [ [ [ ", " ", " "}; fityk-1.3.1/wxgui/img/zoom_prev.xpm000066400000000000000000000070371302634723100173370ustar00rootroot00000000000000/* XPM */ static const char * zoom_prev_xpm[] = { "24 24 144 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #D7D7D7", "e c #F5F5F5", "f c #FAFAFA", "g c #FBFBFB", "h c #F8F8F8", "i c #F0F0F0", "j c #E1E1E1", "k c #C2C2C2", "l c #434343", "m c #0F0F0F", "n c #1F1F1F", "o c #B9B9B9", "p c #D6D6D6", "q c #F9F9F9", "r c #FDFDFD", "s c #FCFCFC", "t c #F2F2F2", "u c #ECECEC", "v c #E4E4E4", "w c #ABABAB", "x c #0E0E0E", "y c #1B1B1B", "z c #6D6D6D", "A c #F4F4F4", "B c #FEFEFE", "C c #EEEEEE", "D c #E6E6E6", "E c #575757", "F c #090909", "G c #141414", "H c #A8A8A8", "I c #D8D8D8", "J c #EDEDED", "K c #000000", "L c #DCDCDC", "M c #9B9B9B", "N c #060606", "O c #111111", "P c #C5C5C5", "Q c #DEDEDE", "R c #E8E8E8", "S c #D5D5D5", "T c #F7F7F7", "U c #BFBFBF", "V c #F7F3DF", "W c #DDDDDD", "X c #E9E9E9", "Y c #EAEAEA", "Z c #E0E0E0", "` c #BABABA", " . c #050505", ".. c #0A0A0A", "+. c #A0A0A0", "@. c #F9F6EA", "#. c #EED680", "$. c #515151", "%. c #979797", "&. c #E3E3E3", "*. c #D1D1D1", "=. c #939393", "-. c #020202", ";. c #F9F5E4", ">. c #F4E4AD", ",. c #F7EECC", "'. c #EFE4C2", "). c #948A6F", "!. c #CDCDCD", "~. c #D4D4D4", "{. c #F9F5E6", "]. c #F1DD97", "^. c #D1B051", "/. c #585858", "(. c #CBCBCB", "_. c #F2EFE4", ":. c #C0A048", "<. c #ADADAD", "[. c #C3A970", "}. c #D1940C", "|. c #E0B74C", "1. c #D9C374", "2. c #5A5A5A", "3. c #A3A3A3", "4. c #424242", "5. c #BCA36B", "6. c #D59D1C", "7. c #B1933F", "8. c #242424", "9. c #BEA56F", "0. c #986B07", "a. c #DFB74A", "b. c #CCB76D", "c. c #BC9F5F", "d. c #B8820A", "e. c #D9A72E", "f. c #686868", "g. c #D4B150", "h. c #A39256", "i. c #797979", "j. c #3A3A3A", "k. c #E2CB79", "l. c #C9B46B", "m. c #8D7E4A", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d 6 e f g f h e i j k l m ", " n o p 2 q f r r s g h t u v w x ", " y z 7 j A e e f B r s q e C D 1 E F ", " G H I J 3 K v 4 r r g h A C D L M N ", " O P Q R K K S u q g f T t J 6 1 U N ", " x P L K V K / W X 3 5 t i Y Z d ` . ", " ..+.K @.#.K K K $.%.W &.R v 1 *.=.-. ", " F % ;.#.#.>.,.'.).K 9 !.d I ~.~ : K ", " K {.].#.#.#.#.#.#.^.K /.( (.~ * -. ", "K _.].#.#.#.#.#.#.#.#.:.K <.o ` $ K ", " K [.}.}.}.}.}.}.|.#.1.K 2.3.4.K ", " K 5.}.}.}.}.}.}.6.#.7.K 8.K K K ", " K 9.}.K K K 0.}.a.b.K K K K K K ", " K c.K K K K d.e.#.K , , K K ", " K K K K }.#.K K f.. K K ", " K K g.h.K K i.j.K K ", " K k.K K f.n K ", " K l.m.K K K ", " K K ", " "}; fityk-1.3.1/wxgui/img/zoom_right.xpm000066400000000000000000000066401302634723100174770ustar00rootroot00000000000000/* XPM */ static const char * zoom_right_xpm[] = { "24 24 136 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #212121", "b c #5B5B5B", "c c #CCCCCC", "d c #D7D7D7", "e c #F5F5F5", "f c #FAFAFA", "g c #FBFBFB", "h c #F8F8F8", "i c #F0F0F0", "j c #E1E1E1", "k c #C2C2C2", "l c #434343", "m c #0F0F0F", "n c #1F1F1F", "o c #B9B9B9", "p c #D6D6D6", "q c #F9F9F9", "r c #FDFDFD", "s c #FFFFFF", "t c #828282", "u c #AEAEAE", "v c #ECECEC", "w c #E4E4E4", "x c #ABABAB", "y c #0E0E0E", "z c #1B1B1B", "A c #6D6D6D", "B c #FEFEFE", "C c #FCFCFC", "D c #B1B1B1", "E c #818181", "F c #E6E6E6", "G c #575757", "H c #090909", "I c #141414", "J c #A8A8A8", "K c #D8D8D8", "L c #EEEEEE", "M c #F6F6F6", "N c #B0B0B0", "O c #DCDCDC", "P c #9B9B9B", "Q c #060606", "R c #111111", "S c #C5C5C5", "T c #DFDFDF", "U c #444444", "V c #454545", "W c #4D4D4D", "X c #707070", "Y c #C6C6C6", "Z c #E3E3E3", "` c #F2F2F2", " . c #050505", ".. c #0B0B0B", "+. c #A5A5A5", "@. c #EDEDED", "#. c #F4F4F4", "$. c #7F7F7F", "%. c #D1D1D1", "&. c #939393", "*. c #020202", "=. c #0A0A0A", "-. c #5F5F5F", ";. c #D9D9D9", ">. c #EBEBEB", ",. c #7B7B7B", "'. c #D4D4D4", "). c #000000", "!. c #E2E2E2", "~. c #646464", "{. c #CBCBCB", "]. c #3B3B3B", "^. c #DADADA", "/. c #D5D5D5", "(. c #C8C8C8", "_. c #BDBDBD", ":. c #515151", "<. c #C7C7C7", "[. c #CDCDCD", "}. c #B8B8B8", "|. c #030303", "1. c #313131", "2. c #999999", "3. c #BBBBBB", "4. c #B6B6B6", "5. c #909090", "6. c #2B2B2B", "7. c #010101", "8. c #414141", "9. c #7A7A7A", "0. c #9A9A9A", "a. c #777777", "b. c #3C3C3C", "c. c #686868", "d. c #797979", "e. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", " a b c d 6 e f g f h e i j k l m ", " n o p 2 q g r s s g t u v w x y ", " z A 7 j e f r B s s C D l E F 1 G H ", " I J K L M q C B s s g N t l l O P Q ", " R S T 3 e s s U V V V U U l l W X Q ", " y Y Z v ` s s l U U U U l l l W X . ", " ..+.j 2 @.5 #.M s s 4 x $.l l %.&.*. ", " =.-.;.j F >.L 3 @.@.@.J l ,.'.~ : ). ", " =.= K O !.6 F @.@.Z ~.* '.{.* *. ", " Q ].c 7 '.^.1 ^.1 K /.] (._.$ ). ", " .:.k <.{.c [.{.{.(.k }.V ). ", " |.1.2.3._.8 8 8 4.5.6.).).). ", " 7.|.8.9.0.0.a.b.).). ).).).). ", " ).).).).).). , , ).). ", " ).c.. ).). ", " ).d.e.).). ", " ).c.n ). ", " ).). ", " "}; fityk-1.3.1/wxgui/img/zoom_up.xpm000066400000000000000000000064351302634723100170100ustar00rootroot00000000000000/* XPM */ static const char * zoom_up_xpm[] = { "24 24 128 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #4D4D4D", "4 c #F1F1F1", "5 c #E5E5E5", "6 c #D2D2D2", "7 c #BCBCBC", "8 c #5E5E5E", "9 c #101010", "0 c #212121", "a c #5B5B5B", "b c #CCCCCC", "c c #D7D7D7", "d c #F5F5F5", "e c #434343", "f c #F0F0F0", "g c #E1E1E1", "h c #C2C2C2", "i c #0F0F0F", "j c #1F1F1F", "k c #B9B9B9", "l c #D6D6D6", "m c #FCFCFC", "n c #7B7B7B", "o c #818181", "p c #F2F2F2", "q c #ECECEC", "r c #E4E4E4", "s c #ABABAB", "t c #0E0E0E", "u c #1B1B1B", "v c #6D6D6D", "w c #7F7F7F", "x c #444444", "y c #828282", "z c #AEAEAE", "A c #EEEEEE", "B c #E6E6E6", "C c #575757", "D c #090909", "E c #141414", "F c #A8A8A8", "G c #D8D8D8", "H c #F6F6F6", "I c #646464", "J c #B0B0B0", "K c #B1B1B1", "L c #DCDCDC", "M c #9B9B9B", "N c #060606", "O c #111111", "P c #C5C5C5", "Q c #DFDFDF", "R c #EFEFEF", "S c #454545", "T c #FFFFFF", "U c #EDEDED", "V c #BFBFBF", "W c #C6C6C6", "X c #E3E3E3", "Y c #EAEAEA", "Z c #E0E0E0", "` c #BABABA", " . c #050505", ".. c #0B0B0B", "+. c #A5A5A5", "@. c #D1D1D1", "#. c #939393", "$. c #020202", "%. c #0A0A0A", "&. c #5F5F5F", "*. c #D9D9D9", "=. c #E9E9E9", "-. c #D4D4D4", ";. c #000000", ">. c #DADADA", ",. c #CBCBCB", "'. c #3B3B3B", "). c #C8C8C8", "!. c #BDBDBD", "~. c #515151", "{. c #C7C7C7", "]. c #B8B8B8", "^. c #030303", "/. c #313131", "(. c #999999", "_. c #BBBBBB", ":. c #B6B6B6", "<. c #909090", "[. c #2B2B2B", "}. c #010101", "|. c #414141", "1. c #7A7A7A", "2. c #9A9A9A", "3. c #777777", "4. c #3C3C3C", "5. c #686868", "6. c #797979", "7. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 3 4 5 6 7 8 9 ", " 0 a b c 5 d e e e e d f g h e i ", " j k l 2 m n e e e e o p q r s t ", " u v 6 g d * e w e x y e z A B 1 C D ", " E F G A H I F s x x J K y A B L M N ", " O P Q R d m m H x S m T T U 5 1 V N ", " t W X q p m m H x S m T T Y Z c ` . ", " ..+.g 2 U H H H x S H R q r 1 @.#.$. ", " %.&.*.g B H H R e x U =.r 1 -.~ : ;. ", " %.= G L H H B e e X Q >.-.,.* $. ", " N '.b 6 -.e e e e e e ] ).!.$ ;. ", " .~.h {.e e e e e e h ].S ;. ", " ^./.(._.!.7 7 7 :.<.[.;.;.;. ", " }.^.|.1.2.2.3.4.;.;. ;.;.;.;. ", " ;.;.;.;.;.;. , , ;.;. ", " ;.5.. ;.;. ", " ;.6.7.;.;. ", " ;.5.j ;. ", " ;.;. ", " "}; fityk-1.3.1/wxgui/img/zoom_vert.xpm000066400000000000000000000067371302634723100173510ustar00rootroot00000000000000/* XPM */ static const char * zoom_vert_xpm[] = { "24 24 140 2", " c None", ". c #343434", "+ c #2D2D2D", "@ c #292929", "# c #262626", "$ c #2E2E2E", "% c #303030", "& c #737373", "* c #A1A1A1", "= c #B4B4B4", "- c #B2B2B2", "; c #9D9D9D", "> c #676767", ", c #202020", "' c #1C1C1C", ") c #272727", "! c #616161", "~ c #CACACA", "{ c #CFCFCF", "] c #D0D0D0", "^ c #CECECE", "/ c #C9C9C9", "( c #C1C1C1", "_ c #A7A7A7", ": c #4C4C4C", "< c #131313", "[ c #222222", "} c #757575", "| c #D3D3D3", "1 c #DBDBDB", "2 c #E7E7E7", "3 c #EFEFEF", "4 c #F3F3F3", "5 c #F1F1F1", "6 c #E5E5E5", "7 c #D2D2D2", "8 c #BCBCBC", "9 c #5E5E5E", "0 c #101010", "a c #4E4E4E", "b c #212121", "c c #5B5B5B", "d c #CCCCCC", "e c #464646", "f c #4B4B4B", "g c #505050", "h c #525252", "i c #FBFBFB", "j c #FAFAFA", "k c #515151", "l c #4F4F4F", "m c #4A4A4A", "n c #C2C2C2", "o c #434343", "p c #0F0F0F", "q c #1F1F1F", "r c #B9B9B9", "s c #D6D6D6", "t c #535353", "u c #FDFDFD", "v c #FCFCFC", "w c #4D4D4D", "x c #E4E4E4", "y c #ABABAB", "z c #0E0E0E", "A c #1B1B1B", "B c #6D6D6D", "C c #E1E1E1", "D c #F5F5F5", "E c #F8F8F8", "F c #FEFEFE", "G c #F9F9F9", "H c #F2F2F2", "I c #EDEDED", "J c #E6E6E6", "K c #575757", "L c #090909", "M c #141414", "N c #A8A8A8", "O c #D8D8D8", "P c #EEEEEE", "Q c #DCDCDC", "R c #9B9B9B", "S c #060606", "T c #111111", "U c #C5C5C5", "V c #DFDFDF", "W c #F7F7F7", "X c #BFBFBF", "Y c #C6C6C6", "Z c #E3E3E3", "` c #ECECEC", " . c #F4F4F4", ".. c #F0F0F0", "+. c #EAEAEA", "@. c #E0E0E0", "#. c #D7D7D7", "$. c #BABABA", "%. c #050505", "&. c #0B0B0B", "*. c #A5A5A5", "=. c #F6F6F6", "-. c #D1D1D1", ";. c #939393", ">. c #020202", ",. c #0A0A0A", "'. c #5F5F5F", "). c #D9D9D9", "!. c #E9E9E9", "~. c #D4D4D4", "{. c #000000", "]. c #484848", "^. c #494949", "/. c #474747", "(. c #454545", "_. c #CBCBCB", ":. c #3B3B3B", "<. c #DADADA", "[. c #444444", "}. c #414141", "|. c #BDBDBD", "1. c #C7C7C7", "2. c #CDCDCD", "3. c #C8C8C8", "4. c #B8B8B8", "5. c #030303", "6. c #313131", "7. c #999999", "8. c #BBBBBB", "9. c #B6B6B6", "0. c #909090", "a. c #2B2B2B", "b. c #010101", "c. c #7A7A7A", "d. c #9A9A9A", "e. c #777777", "f. c #3C3C3C", "g. c #686868", "h. c #797979", "i. c #3A3A3A", " ", " . + @ # # # ", " $ % & * = - ; > , ' ", " ) ! = ~ { ] ^ / ( _ : < ", " [ } ~ | 1 2 3 4 5 6 7 8 9 0 ", "a a b c d e f g h i j k g l m n o p k g l ", "a a q r s : h h t u v h k l w x y z h k l ", " A B 7 C D E u F F u v G H I J 1 K L ", " M N O P D E v F F u i E H I J Q R S ", " T U V 3 D E i u u v j W H I 6 1 X S ", " z Y Z ` H D E j j j W ...+.@.#.$.%. ", " &.*.C 2 . . .=.=.D 4 3 3 +.1 -.;.>. ", " ,.'.).C P P P 3 3 P I !.!.@.~.~ : {. ", "a a ,.= O ].m f f J 2 m ^./.(._.* >. a a ", "a a S :.d (.(./.].<.1 /.e [.}.|.$ {.a a a ", " %.k n 1._.d 2._._.3.n 4.(.{. ", " 5.6.7.8.|.8 8 8 9.0.a.{.{.{. ", " b.5.}.c.d.d.e.f.{.{. {.{.{.{. ", " {.{.{.{.{.{. , , {.{. ", " {.g.. {.{. ", " {.h.i.{.{. ", " {.g.q {. ", " {.{. ", " "}; fityk-1.3.1/wxgui/img/zshift.xpm000066400000000000000000000006471302634723100166260ustar00rootroot00000000000000/* XPM */ static const char * zshift_xpm[] = { "16 16 3 1", " c None", ". c #000000", "+ c #1065D9", " . . ", " . . ", " . . ", " . ", " . . ", " .+++++. ", " . . ", " . ", " . . ", " . . ", " . . ", " . ", "................", " . . ", " . . ", " . "}; fityk-1.3.1/wxgui/inputline.cpp000066400000000000000000000147571302634723100165370ustar00rootroot00000000000000// Purpose: input line with history (wxTextCtrl+wxSpinButton) // Copyright: (c) 2007 Marcin Wojdyr // Licence: wxWidgets licence, or (at your option) GPL ver. 2+ /// Input line with history (wxTextCtrl+wxSpinButton). /// Supported keybindings: /// up / Ctrl-p Move `back' through the history list, /// fetching the previous command. /// down / Ctrl-n Move `forward' through the history list, /// fetching the next command. /// page up Move to the first line in the history. /// page down Move to the end of the input history, /// i.e., the line currently being entered. /// Ctrl-a Move to the start of the line. /// Ctrl-e Move to the end of the line. /// Ctrl-k Cut the text from the current cursor position /// to the end of the line. /// Ctrl-u Cut backward from the cursor to the beginning /// of the current line. /// Ctrl-y Yank, the same as Ctrl-V /// This control was originally written for Fityk (http://fityk.sf.net) #include #include // fgets() #include "inputline.h" #include "cmn.h" InputLine::InputLine(wxWindow *parent, wxWindowID id, InputLineObserver* observer, wxString const& hist_file_) : wxPanel(parent, id), m_hpos(0), m_observer(observer), hist_file(hist_file_) { m_text = new wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS|wxTE_PROCESS_ENTER /*|wxTE_PROCESS_TAB*/); m_button = new wxSpinButton(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_VERTICAL|wxSP_ARROW_KEYS|wxNO_BORDER), m_button->SetRange(0, 0); m_button->SetValue(0); wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(m_text, 1, wxEXPAND); sizer->Add(m_button, 0, wxEXPAND); SetSizer(sizer); SetMinSize(wxSize(-1, m_text->GetBestSize().y)); #if !wxCHECK_VERSION(2, 9, 0) # define wxEVT_SPIN wxEVT_SCROLL_THUMBTRACK #endif m_button->Connect(wxEVT_SPIN, wxSpinEventHandler(InputLine::OnSpinButton), NULL, this); m_text->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(InputLine::OnKeyDownAtText), NULL, this); m_button->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(InputLine::OnKeyDownAtSpinButton), NULL, this); // read history if (!hist_file.IsEmpty()) { FFile f(hist_file, "r"); if (f.IsOpened()) { char line[512]; while (fgets(line, 512, f.fp())) { wxString s = wxString(line, wxConvUTF8).Trim(); if (!s.empty()) m_history.Add(s); } } } // add empty line that will be displayed initially m_history.Add(wxT("")); GoToHistoryEnd(); } InputLine::~InputLine() { // write history if (hist_file.IsEmpty()) return; FFile f(hist_file, "w"); if (!f.IsOpened()) return; for (size_t i = 0; i < m_history.GetCount(); ++i) f.Write(m_history[i] + "\n", wxConvUTF8); } wxSize InputLine::DoGetBestSize() const { return wxSize(wxPanel::DoGetBestSize().x, m_text->GetMinSize().y); } void InputLine::RedirectKeyPress(wxKeyEvent& event) { m_text->SetFocus(); m_text->SetInsertionPointEnd(); m_text->EmulateKeyPress(event); } void InputLine::HistoryMove(int n, bool relative) { int new_pos = relative ? m_hpos + n : n; if (!relative && n < 0) new_pos += m_history.GetCount(); if (new_pos == m_hpos || new_pos<0 || new_pos >= (int)m_history.GetCount()) return; // save line editing m_history[m_hpos] = m_text->GetValue(); m_hpos = new_pos; m_text->SetValue(m_history[new_pos]); m_button->SetValue(m_history.GetCount() - 1 - new_pos); m_text->SetFocus(); m_text->SetInsertionPointEnd(); } void InputLine::OnInputLine(const wxString& line) { m_history.Last() += line; if (line.EndsWith('\\')) { *(m_history.Last().end()-1) = ' '; return; } m_observer->ProcessInputLine(m_history.Last()); m_history.Add(""); GoToHistoryEnd(); m_text->SetFocus(); } void InputLine::GoToHistoryEnd() { const int hist_size = 1024; const int hist_chunk = 128; if (m_history.GetCount() > hist_size + hist_chunk) m_history.RemoveAt(0, m_history.GetCount() - hist_size); m_hpos = m_history.GetCount() - 1; m_button->SetRange(0, m_hpos); m_button->SetValue(0); } void InputLine::OnKeyDownAtText (wxKeyEvent& event) { if (event.ControlDown()) { switch (event.m_keyCode) { case 'A': m_text->SetInsertionPoint(0); return; case 'E': m_text->SetInsertionPointEnd(); return; case 'P': HistoryMove(-1, true); return; case 'N': HistoryMove(+1, true); return; case 'K': m_text->SetSelection(m_text->GetInsertionPoint(), m_text->GetLastPosition()); m_text->Cut(); return; case 'U': m_text->SetSelection(0, m_text->GetInsertionPoint()); m_text->Cut(); return; case 'Y': m_text->Paste(); return; } } switch (event.m_keyCode) { case WXK_RETURN: case WXK_NUMPAD_ENTER: { wxString s = m_text->GetValue().Trim(); if (!s.IsEmpty()) OnInputLine(s); m_text->Clear(); } break; // to process WXK_TAB, you need to uncomment wxTE_PROCESS_TAB //case WXK_TAB: // Navigate(); // break; case WXK_UP: case WXK_NUMPAD_UP: HistoryMove(-1, true); break; case WXK_DOWN: case WXK_NUMPAD_DOWN: HistoryMove(+1, true); break; case WXK_PAGEUP: case WXK_NUMPAD_PAGEUP: HistoryMove(0, false); break; case WXK_PAGEDOWN: case WXK_NUMPAD_PAGEDOWN: HistoryMove(-1, false); break; default: event.Skip(); } } void InputLine::OnKeyDownAtSpinButton(wxKeyEvent& event) { RedirectKeyPress(event); event.Skip(); } fityk-1.3.1/wxgui/inputline.h000066400000000000000000000027111302634723100161670ustar00rootroot00000000000000// Purpose: input line with history (wxTextCtrl+wxSpinButton) // Copyright: (c) 2007 Marcin Wojdyr // Licence: wxWidgets licence, or (at your option) GPL ver. 2+ #ifndef FITYK_WX_INPUTLINE_H_ #define FITYK_WX_INPUTLINE_H_ #include class InputLineObserver { public: virtual ~InputLineObserver() {} virtual void ProcessInputLine(const wxString& line) = 0; }; class InputLine : public wxPanel { public: /// receiver will be called when Enter is pressed InputLine(wxWindow *parent, wxWindowID winid, InputLineObserver* observer, wxString const& hist_file_); ~InputLine(); /// intended for use in EVT_KEY_DOWN handlers of other controls, /// to change focus and redirect keyboard input to text input void RedirectKeyPress(wxKeyEvent& event); void SetValue(const wxString& value) { m_text->SetValue(value); } protected: wxTextCtrl *m_text; wxSpinButton *m_button; wxArrayString m_history; int m_hpos; // current item in m_history InputLineObserver* m_observer; wxString const hist_file; void OnSpinButton(wxSpinEvent &event) { HistoryMove(m_history.GetCount() - 1 - event.GetPosition(), false); } void OnInputLine(const wxString& line); void HistoryMove(int n, bool relative); void GoToHistoryEnd(); void OnKeyDownAtText (wxKeyEvent& event); void OnKeyDownAtSpinButton (wxKeyEvent& event); wxSize DoGetBestSize() const; }; #endif // FITYK_WX_INPUTLINE_H_ fityk-1.3.1/wxgui/listptxt.cpp000066400000000000000000000162731302634723100164160ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// part of the sidebar (ListPlusText, which contains ListWithColors) #include #include #include "listptxt.h" #include "cmn.h" //SpinCtrl, ProportionalSplitter #include "sidebar.h" //SideBar::delete_selected_items() #include "frame.h" // frame->focus_input() and used in update_data_list() #include "mplot.h" // used in update_data_list() #include "fityk/common.h" // s2wx #include "fityk/logic.h" // used in update_data_list() #include "fityk/model.h" // used in update_data_list() #include "fityk/data.h" // used in update_data_list() using namespace std; enum { ID_DL_CMENU_SHOW_START = 27800 , ID_DL_CMENU_SHOW_END = ID_DL_CMENU_SHOW_START+20, ID_DL_CMENU_FITCOLS , ID_DL_SELECTALL , ID_DL_SWITCHINFO }; //=============================================================== // ListWithColors //=============================================================== BEGIN_EVENT_TABLE(ListWithColors, wxListView) EVT_LIST_COL_CLICK(-1, ListWithColors::OnColumnMenu) EVT_LIST_COL_RIGHT_CLICK(-1, ListWithColors::OnColumnMenu) EVT_RIGHT_DOWN (ListWithColors::OnRightDown) EVT_MENU_RANGE (ID_DL_CMENU_SHOW_START, ID_DL_CMENU_SHOW_END, ListWithColors::OnShowColumn) EVT_MENU (ID_DL_CMENU_FITCOLS, ListWithColors::OnFitColumnWidths) EVT_MENU (ID_DL_SELECTALL, ListWithColors::OnSelectAll) EVT_KEY_DOWN (ListWithColors::OnKeyDown) END_EVENT_TABLE() ListWithColors::ListWithColors(wxWindow *parent, wxWindowID id, vector > const& columns_) : wxListView(parent, id, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_HRULES|wxLC_VRULES), columns(columns_), sidebar(0) { for (size_t i = 0; i < columns.size(); ++i) if (columns[i].second != 0) InsertColumn(i, s2wx(columns[i].first), wxLIST_FORMAT_LEFT, columns[i].second); } void ListWithColors::populate(vector const& data, wxImageList* image_list, int active) { assert(data.size() % columns.size() == 0); if (!image_list && data == list_data) return; int length = data.size() / columns.size(); Freeze(); if (image_list) AssignImageList(image_list, wxIMAGE_LIST_SMALL); if (GetItemCount() != length) { DeleteAllItems(); for (int i = 0; i < length; ++i) InsertItem(i, wxT("")); } for (int i = 0; i < length; ++i) { int c = 0; for (size_t j = 0; j < columns.size(); ++j) { if (columns[j].second) { SetItem(i, c, s2wx(data[i*columns.size()+j]), c == 0 ? i : -1); ++c; } } //if (active != -2) // Select(i, i == active); } list_data = data; if (active >= 0 && active < length) Focus(active); Thaw(); } void ListWithColors::OnColumnMenu(wxListEvent&) { wxMenu popup_menu; for (size_t i = 0; i < columns.size(); ++i) { popup_menu.AppendCheckItem(ID_DL_CMENU_SHOW_START+i, s2wx(columns[i].first)); popup_menu.Check(ID_DL_CMENU_SHOW_START+i, columns[i].second); } popup_menu.AppendSeparator(); popup_menu.Append(ID_DL_CMENU_FITCOLS, wxT("Fit Columns")); PopupMenu (&popup_menu, 10, 3); } void ListWithColors::OnRightDown(wxMouseEvent &event) { wxMenu popup_menu; popup_menu.Append(ID_DL_SELECTALL, wxT("Select &All")); popup_menu.Append(ID_DL_SWITCHINFO, wxT("Show/Hide &Info")); PopupMenu (&popup_menu, event.GetX(), event.GetY()); } void ListWithColors::OnShowColumn(wxCommandEvent &event) { int n = event.GetId() - ID_DL_CMENU_SHOW_START; int col=0; for (int i = 0; i < n; ++i) if (columns[i].second) ++col; //TODO if col==0 take care about images bool show = event.IsChecked(); if (show) { InsertColumn(col, s2wx(columns[n].first)); for (int i = 0; i < GetItemCount(); ++i) SetItem(i, col, s2wx(list_data[i*columns.size()+n])); } else DeleteColumn(col); columns[n].second = show; Refresh(); } void ListWithColors::OnFitColumnWidths(wxCommandEvent&) { for (int i = 0; i < GetColumnCount(); ++i) SetColumnWidth(i, wxLIST_AUTOSIZE); } void ListWithColors::OnSelectAll(wxCommandEvent&) { for (int i = 0; i < GetItemCount(); ++i) Select(i, true); } void ListWithColors::OnKeyDown (wxKeyEvent& event) { switch (event.m_keyCode) { case WXK_DELETE: if (sidebar) sidebar->delete_selected_items(); break; default: frame->focus_input(event); } } //=============================================================== // ListPlusText //=============================================================== BEGIN_EVENT_TABLE(ListPlusText, ProportionalSplitter) EVT_MENU (ID_DL_SWITCHINFO, ListPlusText::OnSwitchInfo) END_EVENT_TABLE() ListPlusText::ListPlusText(wxWindow *parent, wxWindowID id, wxWindowID list_id, vector > const& columns_) : ProportionalSplitter(parent, id, 0.75) { list = new ListWithColors(this, list_id, columns_); inf = new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_RICH|wxTE_READONLY|wxTE_MULTILINE); } void ListPlusText::OnSwitchInfo(wxCommandEvent&) { if (IsSplit()) Unsplit(inf); else SplitHorizProp(list, inf); } //=============================================================== void DataListPlusText::update_data_list(bool nondata_changed) { if (!frame) return; MainPlot const* mplot = frame->get_main_plot(); wxColour const& bg_col = mplot->get_bg_color(); vector data_data; for (int i = 0; i < ftk->dk.count(); ++i) { const fityk::Data* data = ftk->dk.data(i); data_data.push_back(S(i)); data_data.push_back(S(data->model()->get_ff().names.size()) + "+" + S(data->model()->get_zz().names.size())); data_data.push_back(data->get_title()); data_data.push_back(data->get_filename()); } wxImageList* data_images = 0; if (nondata_changed || ftk->dk.count() > list->GetItemCount()) { data_images = new wxImageList(16, 16); for (int i = 0; i < ftk->dk.count(); ++i) data_images->Add(make_color_bitmap16(mplot->get_data_color(i), bg_col)); } int focused = list->GetFocusedItem(); if (focused < 0) focused = 0; else if (focused >= list->GetItemCount()) focused = list->GetItemCount() - 1; list->populate(data_data, data_images, focused); } vector DataListPlusText::get_selected_data() const { vector dd; for (int i=list->GetFirstSelected(); i != -1; i = list->GetNextSelected(i)) dd.push_back("@" + S(i)); //if (dd.empty()) { // int n = list->GetFocusedItem(); // dd.push_back("@" + S(n == -1 ? 0 : n)); //} return dd; } fityk-1.3.1/wxgui/listptxt.h000066400000000000000000000042521302634723100160550ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_LISTPTXT_H_ #define FITYK_WX_LISTPTXT_H_ #include #include #include #include #include #include "img/color.xpm" #include "cmn.h" //ProportionalSplitter class SideBar; class ListWithColors : public wxListView { public: ListWithColors(wxWindow *parent, wxWindowID id, std::vector > const& columns_); void populate(std::vector const& data, wxImageList* image_list = 0, int active = -2); void OnColumnMenu(wxListEvent &event); void OnRightDown(wxMouseEvent &event); void OnShowColumn(wxCommandEvent &event); void OnFitColumnWidths(wxCommandEvent &event); void OnSelectAll(wxCommandEvent &event); void OnKeyDown (wxKeyEvent& event); void set_side_bar(SideBar* sidebar_) { sidebar=sidebar_; } DECLARE_EVENT_TABLE() private: std::vector > columns; std::vector list_data; SideBar *sidebar; }; class ListPlusText : public ProportionalSplitter { public: ListWithColors *list; wxTextCtrl* inf; ListPlusText(wxWindow *parent, wxWindowID id, wxWindowID list_id, std::vector > const& columns_); void OnSwitchInfo(wxCommandEvent &event); void split(double prop) { SplitHorizProp(list, inf, prop); } DECLARE_EVENT_TABLE() }; class DataListPlusText : public ListPlusText { public: DataListPlusText(wxWindow *parent, wxWindowID id, wxWindowID list_id, std::vector > const& columns_) : ListPlusText(parent, id, list_id, columns_) {} void update_data_list(bool nondata_changed); std::vector get_selected_data() const; }; inline wxBitmap make_color_bitmap16(wxColour const& col, wxColour const& bg) { wxImage image(color_xpm); image.Replace(0, 0, 0, bg.Red(), bg.Green(), bg.Blue()); image.Replace(255, 255, 255, col.Red(), col.Green(), col.Blue()); return wxBitmap(image); } #endif fityk-1.3.1/wxgui/merge.cpp000066400000000000000000000074761302634723100156270ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr. // Licence: GNU General Public License ver. 2+ #include #include "merge.h" #include "cmn.h" #include "frame.h" #include "fityk/logic.h" #include "fityk/data.h" using namespace std; BEGIN_EVENT_TABLE (MergePointsDlg, wxDialog) EVT_CHECKBOX(-1, MergePointsDlg::OnCheckBox) END_EVENT_TABLE() MergePointsDlg::MergePointsDlg(wxWindow* parent, wxWindowID id) : wxDialog(parent, id, wxT("Merge data points"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); inf = new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_RICH|wxTE_READONLY|wxTE_MULTILINE|wxNO_BORDER); #ifdef __WXGTK__ wxColour bg_col = wxStaticText::GetClassDefaultAttributes().colBg; #else wxColour bg_col = GetBackgroundColour(); #endif inf->SetBackgroundColour(bg_col); inf->SetDefaultStyle(wxTextAttr(wxNullColour, bg_col)); update_info(); top_sizer->Add(inf, 1, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 10); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); dx_cb = new wxCheckBox(this, -1, wxT("merge points with |x1-x2|<")); dx_cb->SetValue(true); hsizer->Add(dx_cb, 0, wxALIGN_CENTER_VERTICAL); dx_val = new RealNumberCtrl(this, -1, ftk->get_settings()->epsilon); hsizer->Add(dx_val, 0); top_sizer->Add(hsizer, 0, wxALL, 5); y_rb = new wxRadioBox(this, -1, wxT("y = "), wxDefaultPosition, wxDefaultSize, ArrayString(wxT("sum"), wxT("avg")), 1, wxRA_SPECIFY_ROWS); top_sizer->Add(y_rb, 0, wxEXPAND|wxALL, 5); focused_data = frame->get_focused_data_index(); wxString fdstr = wxString::Format(wxT("dataset @%d"), focused_data); output_rb = new wxRadioBox(this, -1, wxT("output to ..."), wxDefaultPosition, wxDefaultSize, ArrayString(fdstr, wxT("new dataset")), 1, wxRA_SPECIFY_ROWS); top_sizer->Add(output_rb, 0, wxEXPAND|wxALL, 5); top_sizer->Add(CreateButtonSizer(wxOK|wxCANCEL), 0, wxALL|wxALIGN_CENTER, 5); SetSizerAndFit(top_sizer); } void MergePointsDlg::update_info() { vector dd = frame->get_selected_data_indices(); const fityk::Data* data = ftk->dk.data(dd[0]); double x_min = data->get_x_min(); double x_max = data->get_x_max(); int n = data->points().size(); wxString dstr = wxString::Format(wxT("@%d"), dd[0]); for (size_t i = 1; i < dd.size(); ++i) { data = ftk->dk.data(i); if (data->get_x_min() < x_min) x_min = data->get_x_min(); if (data->get_x_max() > x_max) x_max = data->get_x_max(); n += data->points().size(); dstr += wxString::Format(wxT(" @%d"), (int) i); } wxString s = wxString::Format(wxT("%i data points from: "), n) + dstr; s += wxString::Format(wxT("\nx in range (%g, %g)"), x_min, x_max); if (dd.size() != 1 && data->get_x_step() != 0.) s += wxString::Format(wxT("\nfixed step: %g"), data->get_x_step()); else s += wxString::Format(wxT("\naverage step: %g"), (x_max-x_min) / (n-1)); inf->SetValue(s); } string MergePointsDlg::get_command() { string s; if (dx_cb->GetValue()) { string eps = wx2s(dx_val->GetValue().Trim()); if (eps != eS(ftk->get_settings()->epsilon)) s += "with epsilon=" + eps + " "; } string dat = output_rb->GetSelection() == 0 ? S(focused_data) : S("+"); s += "@" + dat + " = "; if (dx_cb->GetValue()) s += y_rb->GetSelection() == 0 ? "sum_same_x" : "avg_same_x"; s += "(@" + join_vector(frame->get_selected_data_indices(), " and @") + ")"; return s; } fityk-1.3.1/wxgui/merge.h000066400000000000000000000011451302634723100152570ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_MERGE_H_ #define FITYK_WX_MERGE_H_ class RealNumberCtrl; class MergePointsDlg : public wxDialog { public: MergePointsDlg(wxWindow* parent, wxWindowID id=wxID_ANY); std::string get_command(); void update_info(); void OnCheckBox(wxCommandEvent&) { y_rb->Enable(dx_cb->GetValue()); } private: int focused_data; wxRadioBox *y_rb, *output_rb; wxCheckBox *dx_cb; RealNumberCtrl *dx_val; wxTextCtrl *inf; DECLARE_EVENT_TABLE() }; #endif fityk-1.3.1/wxgui/modelinfo.cpp000066400000000000000000000132151302634723100164700ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include //#include //#include #include #include "modelinfo.h" #include "frame.h" #include "fityk/logic.h" #include "fityk/model.h" #include "fityk/info.h" using namespace std; ModelInfoDlg::ModelInfoDlg(wxWindow* parent, wxWindowID id) : wxDialog(parent, id, wxString(wxT("Model as Formula or Script")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { } bool ModelInfoDlg::Initialize() { // +------------------------------------------------------+ // | _____ [] extra breaks num fmt: [6][g] | // | [o form] [ ] | // | [o gnup] [ mathematical formula (normal or gnuplot ] | // | [o scri] [ variant) or fityk script ] | // | ----- [ ] | // | [] simp [ ] | // | [ ] | // +------------------------------------------------------+ extra_space_cb = new wxCheckBox(this, -1, "extra breaks"); nf = new NumericFormatPanel(this); wxArrayString choices; choices.Add("formula"); choices.Add("formula (gnuplot)"); choices.Add("script (all models)"); rb = new wxRadioBox(this, -1, "content", wxDefaultPosition, wxDefaultSize, choices, 1, wxRA_SPECIFY_COLS); simplify_cb = new wxCheckBox(this, -1, "simplify"); main_tc = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH|wxTE_READONLY); wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *format_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *main_sizer = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *left_sizer = new wxBoxSizer(wxVERTICAL); format_sizer->Add(extra_space_cb, wxSizerFlags().Center().Border()); format_sizer->Add(nf, wxSizerFlags().Border()); left_sizer->Add(rb, wxSizerFlags().Expand().Border()); left_sizer->Add(simplify_cb, wxSizerFlags().Border()); main_sizer->Add(left_sizer, wxSizerFlags()); main_sizer->Add(main_tc, wxSizerFlags(1).Expand()); top_sizer->Add(format_sizer, wxSizerFlags().Right()); top_sizer->Add(main_sizer, wxSizerFlags(1).Expand()); wxBoxSizer *btn_sizer = new wxBoxSizer(wxHORIZONTAL); btn_sizer->Add(new wxButton(this, wxID_COPY), wxSizerFlags().Border()); btn_sizer->AddStretchSpacer(); btn_sizer->Add(new wxButton(this, wxID_SAVE), wxSizerFlags().Border()); btn_sizer->Add(new wxButton(this, wxID_CLOSE), wxSizerFlags().Right().Border()); top_sizer->Add(btn_sizer, wxSizerFlags().Expand()); SetSizerAndFit(top_sizer); SetSize(wxSize(640, 440)); SetEscapeId(wxID_CLOSE); try { update_text(); } catch (fityk::ExecuteError &e) { ftk->ui()->warn(string("Error: ") + e.what()); return false; } Connect(-1, wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(ModelInfoDlg::OnRadio)); Connect(-1, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(ModelInfoDlg::OnFormatChange)); Connect(-1, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(ModelInfoDlg::OnFormatChange)); Connect(wxID_COPY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ModelInfoDlg::OnCopy)); Connect(wxID_SAVE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ModelInfoDlg::OnSave)); return true; } void ModelInfoDlg::update_text() { string s; int sel = rb->GetSelection(); bool simplify = simplify_cb->GetValue(); bool extra_breaks = extra_space_cb->GetValue(); const char* fmt = nf->format().c_str(); vector datas = frame->get_selected_datas(); v_foreach (fityk::Data*, i, datas) { fityk::Model *model = (*i)->model(); if (sel == 0 || sel == 1) { // formula or gnuplot formula string formula = model->get_formula(simplify, fmt, extra_breaks); if (sel == 1) formula = fityk::gnuplotize_formula(formula); if (i != datas.begin()) s += "\n"; s += formula; } else { // if (sel == 2) // script models_as_script(ftk, s, false); // currently all models are exported at once break; } if (extra_breaks) s += "\n"; } main_tc->SetValue(s2wx(s)); } void ModelInfoDlg::OnRadio(wxCommandEvent& event) { simplify_cb->Enable(event.GetSelection() <= 1); update_text(); } void ModelInfoDlg::OnCopy(wxCommandEvent&) { wxString sel = main_tc->GetStringSelection(); if (sel.empty()) sel = main_tc->GetValue(); if (wxTheClipboard->Open()) { wxTheClipboard->SetData(new wxTextDataObject(sel)); wxTheClipboard->Close(); } } void ModelInfoDlg::OnSave(wxCommandEvent&) { EndModal(wxID_OK); } const string ModelInfoDlg::get_info_cmd() const { string ret; int sel = rb->GetSelection(); bool simplify = simplify_cb->GetValue(); if (nf->format() != ftk->get_settings()->numeric_format) ret = "with numeric_format='" + nf->format() + "' "; ret += "info "; if (sel == 0) ret += (simplify ? "simplified_formula" : "formula"); else if (sel == 1) ret += (simplify ? "simplified_gnuplot_formula" : "gnuplot_formula"); else // sel == 2 ret += "models"; return ret; } fityk-1.3.1/wxgui/modelinfo.h000066400000000000000000000014571302634723100161420ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_MODELINFO_H_ #define FITYK_WX_MODELINFO_H_ #include #include #include "fitinfo.h" // NumericFormatPanel /// Status bar configuration dialog class ModelInfoDlg: public wxDialog { public: ModelInfoDlg(wxWindow* parent, wxWindowID id); bool Initialize(); const std::string get_info_cmd() const; private: wxTextCtrl *main_tc; wxRadioBox *rb; wxCheckBox *simplify_cb, *extra_space_cb; NumericFormatPanel *nf; void update_text(); void OnRadio(wxCommandEvent&); void OnFormatChange(wxCommandEvent&) { update_text(); } void OnCopy(wxCommandEvent&); void OnSave(wxCommandEvent&); }; #endif // FITYK_WX_MODELINFO_H_ fityk-1.3.1/wxgui/mplot.cpp000066400000000000000000002025031302634723100156470ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include #include #include #include #include #include "mplot.h" #include "plotpane.h" #include "frame.h" #include "sidebar.h" #include "statbar.h" // HintReceiver #include "bgm.h" #include "gradient.h" #include "drag.h" #include "fityk/data.h" #include "fityk/logic.h" #include "fityk/model.h" #include "fityk/var.h" #include "fityk/func.h" #include "fityk/settings.h" #include "fityk/ast.h" #include "fityk/info.h" using namespace std; using fityk::is_zero; using fityk::Variable; using fityk::Function; using fityk::Tplate; using fityk::Model; enum { ID_plot_popup_za = 25001, ID_plot_popup_prefs , ID_peak_popup_info , ID_peak_popup_del , ID_peak_popup_guess , ID_peak_popup_edit , ID_peak_popup_share //+15 }; class MainPlotConfDlg: public wxDialog { public: MainPlotConfDlg(MainPlot* mp); private: MainPlot *mp_; wxCheckBox *model_cb_, *func_cb_, *labels_cb_, *vertical_labels_cb_, *desc_cb_; wxComboBox *label_combo_, *desc_combo_; wxColourPickerCtrl *bg_cp_, *inactive_cp_, *axis_cp_, *model_cp_, *func_cp_; wxSpinCtrl *data_colors_sc_, *model_width_sc_; MultiColorCombo *data_color_combo_; wxFontPickerCtrl *tics_fp_, *label_fp_; wxCheckBox *x_show_axis_cb_, *x_show_tics_cb_, *x_show_minor_tics_cb_, *x_show_grid_cb_, *x_reversed_cb_, *x_logarithm_cb_; wxCheckBox *y_show_axis_cb_, *y_show_tics_cb_, *y_show_minor_tics_cb_, *y_show_grid_cb_, *y_reversed_cb_, *y_logarithm_cb_; wxSpinCtrl *x_max_tics_sc_, *x_tic_size_sc_; wxSpinCtrl *y_max_tics_sc_, *y_tic_size_sc_; void OnModelCheckbox(wxCommandEvent& event) { mp_->model_visible_ = event.IsChecked(); mp_->refresh(); } void OnFuncCheckbox(wxCommandEvent& event) { mp_->peaks_visible_ = event.IsChecked(); mp_->refresh(); } void OnLabelsCheckbox(wxCommandEvent& event) { mp_->plabels_visible_ = event.IsChecked(); mp_->refresh(); } void OnDescCheckbox(wxCommandEvent& event) { mp_->desc_visible_ = event.IsChecked(); mp_->refresh(); } void OnModelWidthSpin(wxSpinEvent& event) { mp_->model_line_width_ = event.GetPosition(); mp_->refresh(); } void OnVerticalCheckbox(wxCommandEvent& event) { mp_->vertical_plabels_ = event.IsChecked(); if (mp_->plabels_visible_) mp_->refresh(); } void OnColor(wxColourPickerEvent& event); void OnDataColorsSpin(wxSpinEvent& event) { mp_->data_colors_.resize(event.GetPosition(), mp_->data_colors_[0]); data_color_combo_->Refresh(); frame->update_data_pane(); mp_->refresh(); } void OnDataColorSelection(wxCommandEvent&) { frame->update_data_pane(); mp_->refresh(); } void OnTicsFont(wxFontPickerEvent& event) { mp_->ticsFont = event.GetFont(); mp_->refresh(); } void OnLabelFont(wxFontPickerEvent& event) { mp_->plabelFont = event.GetFont(); mp_->refresh(); } void OnLabelTextChanged(wxCommandEvent&) { mp_->plabel_format_ = wx2s(label_combo_->GetValue()); if (mp_->plabels_visible_) mp_->refresh(); } void OnDescTextChanged(wxCommandEvent&) { mp_->desc_format_ = wx2s(desc_combo_->GetValue()); if (mp_->desc_visible_) mp_->refresh(); } void OnShowXAxis(wxCommandEvent& event) { mp_->x_axis_visible = event.IsChecked(); mp_->refresh(); } void OnShowYAxis(wxCommandEvent& event) { mp_->y_axis_visible = event.IsChecked(); mp_->refresh(); } void OnShowXTics(wxCommandEvent& event) { mp_->xtics_visible = event.IsChecked(); mp_->refresh(); } void OnShowYTics(wxCommandEvent& event) { mp_->ytics_visible = event.IsChecked(); mp_->refresh(); } void OnShowXMinorTics(wxCommandEvent& event) { mp_->xminor_tics_visible = event.IsChecked(); mp_->refresh(); } void OnShowYMinorTics(wxCommandEvent& event) { mp_->yminor_tics_visible = event.IsChecked(); mp_->refresh(); } void OnShowXGrid(wxCommandEvent& event) { mp_->x_grid = event.IsChecked(); mp_->refresh(); } void OnShowYGrid(wxCommandEvent& event) { mp_->y_grid = event.IsChecked(); mp_->refresh(); } void OnReversedX(wxCommandEvent& event) { mp_->xs.reversed = event.IsChecked(); frame->plot_pane()->refresh_plots(false, kAllPlots); } void OnReversedY(wxCommandEvent& event) { mp_->ys.reversed = event.IsChecked(); mp_->refresh(); } void OnLogX(wxCommandEvent& event) { mp_->xs.logarithm = event.IsChecked(); ftk->view.set_log_scale(mp_->xs.logarithm, mp_->ys.logarithm); frame->plot_pane()->refresh_plots(false, kAllPlots); } void OnLogY(wxCommandEvent& event) { mp_->ys.logarithm = event.IsChecked(); ftk->view.set_log_scale(mp_->xs.logarithm, mp_->ys.logarithm); mp_->refresh(); } void OnMaxXTicsSpin(wxSpinEvent& event) { mp_->x_max_tics = event.GetPosition(); mp_->refresh(); } void OnMaxYTicsSpin(wxSpinEvent& event) { mp_->y_max_tics = event.GetPosition(); mp_->refresh(); } void OnXTicSize(wxSpinEvent& event) { mp_->x_tic_size = event.GetPosition(); mp_->refresh(); } void OnYTicSize(wxSpinEvent& event) { mp_->y_tic_size = event.GetPosition(); mp_->refresh(); } }; // horizontal pixel range (from - to) is used for X values static void stroke_line(wxDC& dc, const vector& YY, int from=0, int to=-1) { if (to == -1) to = YY.size() - 1; wxGCDC* gdc = wxDynamicCast(&dc, wxGCDC); if (gdc) { wxGraphicsContext *gc = gdc->GetGraphicsContext(); wxGraphicsPath path = gc->CreatePath(); path.MoveToPoint(from, YY[from]); for (int i = from+1; i <= to; ++i) path.AddLineToPoint(i, YY[i]); gc->StrokePath(path); } else { int n = to - from + 1; wxPoint *points = new wxPoint[n]; for (int i = 0; i < n; ++i) { points[i].x = from + i; points[i].y = iround(YY[from + i]); } dc.DrawLines(n, points); delete [] points; } } static void stroke_line(wxDC& dc, const vector& XX, const vector& YY) { assert(XX.size() == YY.size()); int n = XX.size(); if (n == 0) return; wxGCDC* gdc = wxDynamicCast(&dc, wxGCDC); if (gdc) { wxGraphicsContext *gc = gdc->GetGraphicsContext(); wxGraphicsPath path = gc->CreatePath(); path.MoveToPoint(XX[0], YY[0]); for (int i = 1; i < n; ++i) path.AddLineToPoint(XX[i], YY[i]); gc->StrokePath(path); } else { wxPoint *points = new wxPoint[n]; for (int i = 0; i < n; ++i) { points[i].x = iround(XX[i]); points[i].y = iround(YY[i]); } dc.DrawLines(n, points); delete [] points; } } //=============================================================== // MainPlot (plot with data and fitted curves) //=============================================================== BEGIN_EVENT_TABLE(MainPlot, FPlot) EVT_PAINT ( MainPlot::OnPaint) EVT_MOTION ( MainPlot::OnMouseMove) EVT_LEAVE_WINDOW ( MainPlot::OnLeaveWindow) EVT_LEFT_DOWN ( MainPlot::OnButtonDown) EVT_RIGHT_DOWN ( MainPlot::OnButtonDown) EVT_MIDDLE_DOWN ( MainPlot::OnButtonDown) EVT_LEFT_DCLICK ( MainPlot::OnLeftDClick) EVT_LEFT_UP ( MainPlot::OnButtonUp) EVT_RIGHT_UP ( MainPlot::OnButtonUp) EVT_MIDDLE_UP ( MainPlot::OnButtonUp) EVT_MOUSE_AUX1_DOWN ( MainPlot::OnAuxDown) EVT_MOUSE_AUX2_DOWN ( MainPlot::OnAuxDown) EVT_MOUSEWHEEL ( MainPlot::OnMouseWheel) EVT_MENU (ID_plot_popup_za, MainPlot::OnZoomAll) EVT_MENU (ID_plot_popup_prefs, MainPlot::OnConfigure) EVT_MENU (ID_peak_popup_info, MainPlot::OnPeakInfo) EVT_MENU (ID_peak_popup_del, MainPlot::OnPeakDelete) EVT_MENU (ID_peak_popup_guess, MainPlot::OnPeakGuess) EVT_MENU (ID_peak_popup_edit, MainPlot::OnPeakEdit) EVT_MENU_RANGE (ID_peak_popup_share, ID_peak_popup_share+15, MainPlot::OnPeakShare) END_EVENT_TABLE() MainPlot::MainPlot (wxWindow *parent) : FPlot(parent), bgm_(new BgManager(xs)), dragged_func_(new DraggedFunc(ftk->mgr)), basic_mode_(mmd_zoom), mode_(mmd_zoom), crosshair_cursor_(false), pressed_mouse_button_(0), over_peak_(-1), hint_receiver_(NULL), auto_freeze_(false) { set_cursor(); SetMinSize(wxSize(200, 200)); } MainPlot::~MainPlot() { delete bgm_; delete dragged_func_; } void MainPlot::OnPaint(wxPaintEvent&) { update_buffer_and_blit(); } static double y_of_data_for_draw_data(vector::const_iterator i, const Model* /*model*/) { return i->y; } void MainPlot::draw_dataset(wxDC& dc, int n, bool set_pen) { bool shadowed; int offset; bool r = frame->get_sidebar()->howto_plot_dataset(n, shadowed, offset); if (!r) return; wxColour col = get_data_color(n); if (shadowed) { const wxColour& bg_col = get_bg_color(); col.Set((col.Red() + bg_col.Red())/2, (col.Green() + bg_col.Green())/2, (col.Blue() + bg_col.Blue())/2); } if (set_pen) draw_data(dc, y_of_data_for_draw_data, ftk->dk.data(n), 0, col, wxNullColour, offset); else draw_data(dc, y_of_data_for_draw_data, ftk->dk.data(n), 0, dc.GetPen().GetColour(), dc.GetPen().GetColour(), offset); } void MainPlot::draw(wxDC &dc, bool monochrome) { //printf("MainPlot::draw()\n"); int focused_data = frame->get_focused_data_index(); const Model* model = ftk->dk.get_model(focused_data); set_scale(get_pixel_width(dc), get_pixel_height(dc)); int Ymax = get_pixel_height(dc); prepare_peaktops(model, Ymax); if (monochrome) { dc.SetPen(*wxBLACK_PEN); dc.SetBrush(*wxBLACK_BRUSH); } if (desc_visible_) draw_desc(dc, focused_data, !monochrome); //draw datasets (selected and focused at the end) vector ord = frame->get_sidebar()->get_ordered_dataset_numbers(); v_foreach (int, i, ord) draw_dataset(dc, *i, !monochrome); if (xtics_visible) draw_xtics(dc, ftk->view, !monochrome); if (ytics_visible) draw_ytics(dc, ftk->view, !monochrome); if (peaks_visible_) draw_peaks(dc, model, !monochrome); //if (groups_visible_) // draw_groups(dc, model, !monochrome); if (model_visible_) draw_model(dc, model, !monochrome); if (x_axis_visible) draw_x_axis(dc, !monochrome); if (y_axis_visible) draw_y_axis(dc, !monochrome); if (visible_peaktops(mode_) && !monochrome) draw_peaktops(dc, model); if (mode_ == mmd_bg) { bgm_->update_focused_data(focused_data); draw_baseline(dc); } else { if (plabels_visible_) draw_plabels(dc, model, !monochrome); } } bool MainPlot::visible_peaktops(MouseModeEnum mode) { return (mode == mmd_zoom || mode == mmd_add || mode == mmd_peak || mode == mmd_activate); } void MainPlot::draw_x_axis (wxDC& dc, bool set_pen) { if (set_pen) dc.SetPen(wxPen(xAxisCol, pen_width)); int Y0 = ys.px(0.); dc.DrawLine (0, Y0, get_pixel_width(dc), Y0); } void MainPlot::draw_y_axis (wxDC& dc, bool set_pen) { if (set_pen) dc.SetPen(wxPen(xAxisCol, pen_width)); int X0 = xs.px(0.); dc.DrawLine (X0, 0, X0, get_pixel_height(dc)); } // one point for every pixel and extra points for function centers // The latter is to avoid plots like here: // https://groups.google.com/d/msg/fityk-users/9tHeKQ37rbg/4H6VUD9iTu8J static vector get_x_points_for_model_line(const Model *model, const Scale& xs, int width) { vector centers; v_foreach(int, k, model->get_ff().idx) { realt ctr; if (ftk->mgr.get_function(*k)->get_center(&ctr)) { realt X = xs.px_d(ctr); if (X > 0 && X < width-1) centers.push_back(ctr); } } sort(centers.begin(), centers.end()); vector xx(width + centers.size()); if (xs.scale >= 0) { reverse(centers.begin(), centers.end()); for (int i = 0, pos = 0; i < width; ++i) { realt x = xs.val(i); while (!centers.empty() && centers.back() < x) { xx[pos++] = centers.back(); centers.pop_back(); } xx[pos++] = x; } } else { for (int i = 0, pos = 0; i < width; ++i) { realt x = xs.val(i); while (!centers.empty() && centers.back() > x) { xx[pos++] = centers.back(); centers.pop_back(); } xx[pos++] = x; } } return xx; // counting on RVO } void MainPlot::draw_model(wxDC& dc, const Model* model, bool set_pen) { if (set_pen) dc.SetPen(wxPen(modelCol, model_line_width_ * pen_width)); int width = get_pixel_width(dc); vector xx = get_x_points_for_model_line(model, xs, width); vector yy(xx.size()); vector YY(xx.size()); model->compute_model(xx, yy); for (size_t i = 0; i != yy.size(); ++i) YY[i] = ys.px_d(yy[i]); vm_foreach(realt, x, xx) // in-place conversion to screen coords *x = xs.px_d(*x); stroke_line(dc, xx, YY); } //TODO draw groups //void MainPlot::draw_groups (wxDC& /*dc*/, const Model*, bool) //{ //} void MainPlot::draw_peaks(wxDC& dc, const Model* model, bool set_pen) { double level = 0; const vector& idx = model->get_ff().idx; int n = get_pixel_width(dc); vector xx(n), yy(n); vector YY(n); for (int i = 0; i < n; ++i) { xx[i] = xs.val(i); xx[i] += model->zero_shift(xx[i]); } for (int k = 0; k < (int) idx.size(); k++) { fill(yy.begin(), yy.end(), 0.); const Function* f = ftk->mgr.get_function(idx[k]); int from=0, to=n-1; realt left, right; if (f->get_nonzero_range(level, left, right)) { from = max(from, xs.px(left)); to = min(to, xs.px(right)); } if (set_pen) dc.SetPen(wxPen(peakCol[k % max_peak_cols], pen_width)); f->calculate_value(xx, yy); for (int i = from; i <= to; ++i) YY[i] = ys.px_d(yy[i]); stroke_line(dc, YY, from, to); } } void MainPlot::draw_peaktops (wxDC& dc, const Model* model) { dc.SetPen(wxPen(xAxisCol, pen_width)); dc.SetBrush (*wxTRANSPARENT_BRUSH); v_foreach (wxPoint, i, special_points) { dc.DrawRectangle (i->x - 1, i->y - 1, 3, 3); } draw_peaktop_selection(dc, model); } void MainPlot::draw_peaktop_selection (wxDC& dc, const Model* model) { // using the same pen int n = frame->get_sidebar()->get_active_function(); if (n == -1) return; const vector& idx = model->get_ff().idx; int t = index_of_element(idx, n); if (t != -1) dc.DrawCircle(special_points[t].x, special_points[t].y, 4); } void MainPlot::draw_plabels (wxDC& dc, const Model* model, bool set_pen) { prepare_peak_labels(model); //TODO re-prepare only when peaks where changed set_font(dc, plabelFont); vector previous; const vector& idx = model->get_ff().idx; for (int k = 0; k < (int) idx.size(); k++) { const wxPoint &peaktop = special_points[k]; if (set_pen) dc.SetTextForeground(peakCol[k % max_peak_cols]); wxString label = s2wx(plabels_[k]); wxCoord w, h; if (vertical_plabels_) { dc.GetMultiLineTextExtent(label, &h, &w); // w and h swapped h = 0; // Y correction is not needed } else dc.GetMultiLineTextExtent(label, &w, &h); int X = peaktop.x - w/2; int Y = peaktop.y - h - 2; wxRect rect(X, Y, w, h); // eliminate labels overlap // perhaps more sophisticated algorithm for automatic label placement // should be used const int mrg = 0; //margin around label, can be negative int counter = 0; // the number of different placements checked vector::const_iterator i = previous.begin(); while (i != previous.end() && counter < 10) { if (i->x > rect.GetRight()+mrg || rect.x > i->GetRight()+mrg || i->y > rect.GetBottom()+mrg || rect.y > i->GetBottom()+mrg) //there is no intersection ++i; else { // intersection -- try upper rectangle rect.SetY(i->y - h - 2); i = previous.begin(); //and check for intersections with all... ++counter; } } previous.push_back(rect); if (vertical_plabels_) dc.DrawRotatedText(label, rect.x, rect.y, 90); else dc.DrawLabel(label, rect, wxALIGN_CENTER|wxALIGN_BOTTOM); } } /* static bool operator< (const wxPoint& a, const wxPoint& b) { return a.x != b.x ? a.x < b.x : a.y < b.y; } */ void MainPlot::prepare_peaktops(const Model* model, int Ymax) { int Y0 = ys.px(0); const vector& idx = model->get_ff().idx; int n = idx.size(); special_points.resize(n); int no_ctr_idx = 0; for (int k = 0; k < n; k++) { const Function *f = ftk->mgr.get_function(idx[k]); double x; realt ctr; int X, Y; if (f->get_center(&ctr)) { X = xs.px(ctr - model->zero_shift(ctr)); // instead of these two lines we could simply do x=ctr, // but it would be slightly inaccurate x = xs.val(X); x += model->zero_shift(x); } else { X = no_ctr_idx * 10 + 5; ++no_ctr_idx; x = xs.val(X); x += model->zero_shift(x); } Y = ys.px(f->calculate_value(x)); if (Y < 0 || Y > Ymax) Y = Y0; special_points[k] = wxPoint(X, Y); } } void MainPlot::prepare_peak_labels(const Model* model) { const vector& idx = model->get_ff().idx; plabels_.resize(idx.size()); for (int k = 0; k < (int) idx.size(); k++) { const Function *f = ftk->mgr.get_function(idx[k]); string label = plabel_format_; string::size_type pos = 0; while ((pos = label.find("<", pos)) != string::npos) { string::size_type right = label.find(">", pos+1); if (right == string::npos) break; string tag(label, pos+1, right-pos-1); realt a; if (tag == "area") label.replace(pos, right-pos+1, f->get_area(&a) ? S(a) : " "); else if (tag == "height") label.replace(pos, right-pos+1, f->get_height(&a) ? S(a) : " "); else if (tag == "center") label.replace(pos, right-pos+1, f->get_center(&a) ? S(a) : " "); else if (tag == "fwhm") label.replace(pos, right-pos+1, f->get_fwhm(&a) ? S(a) : " "); else if (tag == "ib") label.replace(pos, right-pos+1, f->get_ibreadth(&a) ? S(a):" "); else if (tag == "name") label.replace(pos, right-pos+1, f->name); else if (tag == "br") label.replace(pos, right-pos+1, "\n"); else ++pos; } plabels_[k] = label; } } void MainPlot::draw_desc(wxDC& dc, int dataset, bool set_pen) { string result; try { parse_and_eval_info(ftk, desc_format_, dataset, result); } catch (const fityk::SyntaxError& /*e*/) { result = "syntax error!"; } catch (const fityk::ExecuteError& /*e*/) { result = "(---)"; } wxString label = s2wx(result); set_font(dc, plabelFont); if (set_pen) dc.SetTextForeground(xAxisCol); wxCoord w, h; dc.GetMultiLineTextExtent(label, &w, &h); wxSize size = dc.GetSize(); wxRect rect(size.x - w - 5, 5, w, h); dc.DrawLabel(label, rect, wxALIGN_RIGHT); } void MainPlot::draw_baseline(wxDC& dc, bool set_pen) { if (set_pen) dc.SetPen(wxPen(bg_pointsCol, pen_width)); dc.SetBrush (*wxTRANSPARENT_BRUSH); // bg line int width = get_pixel_width(dc); vector YY = bgm_->calculate_bgline(width, ys); stroke_line(dc, YY); // bg points (circles) v_foreach (fityk::PointQ, i, bgm_->get_bg()) { dc.DrawCircle(xs.px(i->x), ys.px(i->y), 3); dc.DrawCircle(xs.px(i->x), ys.px(i->y), 4); } } void MainPlot::read_settings(wxConfigBase *cf) { cf->SetPath(wxT("/MainPlot")); int data_colors_count = cf->Read(wxT("data_colors_count"), 16); if (data_colors_count < 2) data_colors_count = 2; else if (data_colors_count > kMaxDataColors) data_colors_count = kMaxDataColors; data_colors_.resize(data_colors_count); cf->SetPath(wxT("/MainPlot/Colors")); set_bg_color(cfg_read_color(cf, wxT("bg"), wxColour(48, 48, 48))); inactiveDataCol = cfg_read_color(cf, wxT("inactive_data"), wxColour(128, 128, 128)); modelCol = cfg_read_color(cf, wxT("model"), wxColour(255, 255, 0)); bg_pointsCol = cfg_read_color(cf, wxT("BgPoints"), wxColour(255, 0, 0)); cf->SetPath(wxT("data")); data_colors_[0] = cfg_read_color(cf, wxT("0"), wxColour(0, 255, 0)); for (int i = 1; i < (int) data_colors_.size(); i++) data_colors_[i] = cfg_read_color(cf, s2wx(S(i)), data_colors_[0]); cf->SetPath(wxT("../peak")); peakCol[0] = cfg_read_color(cf, wxT("0"), wxColour(255, 0, 0)); for (int i = 0; i < max_peak_cols; i++) peakCol[i] = cfg_read_color(cf, s2wx(S(i)), peakCol[0]); //for (int i = 0; i < max_group_cols; i++) // groupCol[i] = cfg_read_color(cf, wxString::Format(wxT("group/%i"), i), // wxColour(173, 216, 230)); cf->SetPath(wxT("/MainPlot/Visible")); peaks_visible_ = cfg_read_bool(cf, wxT("peaks"), true); plabels_visible_ = cfg_read_bool(cf, wxT("plabels"), false); desc_visible_ = cfg_read_bool(cf, wxT("desc"), false); //groups_visible_ = cfg_read_bool(cf, wxT("groups"), false); model_visible_ = cfg_read_bool(cf, wxT("model"), true); cf->SetPath(wxT("/MainPlot")); point_radius = cf->Read (wxT("point_radius"), 2); line_between_points = cfg_read_bool(cf,wxT("line_between_points"), false); draw_sigma = cfg_read_bool(cf,wxT("draw_sigma"), false); model_line_width_ = cf->Read(wxT("model_line_width"), 1); wxFont default_plabel_font(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); plabelFont = cfg_read_font(cf, wxT("plabelFont"), default_plabel_font); plabel_format_ = wx2s(cf->Read(wxT("plabel_format"), wxT(""))); desc_format_ = wx2s(cf->Read(wxT("desc_format"), wxT("filename"))); vertical_plabels_ = cfg_read_bool(cf, wxT("vertical_plabels"), false); x_max_tics = cf->Read(wxT("xMaxTics"), 7); y_max_tics = cf->Read(wxT("yMaxTics"), 7); x_tic_size = cf->Read(wxT("xTicSize"), 4); y_tic_size = cf->Read(wxT("yTicSize"), 4); xs.reversed = cfg_read_bool (cf, wxT("xReversed"), false); ys.reversed = cfg_read_bool (cf, wxT("yReversed"), false); xs.logarithm = cfg_read_bool (cf, wxT("xLogarithm"), false); ys.logarithm = cfg_read_bool (cf, wxT("yLogarithm"), false); ftk->view.set_log_scale(xs.logarithm, ys.logarithm); FPlot::read_settings(cf); refresh(); } void MainPlot::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("/MainPlot")); cf->Write (wxT("point_radius"), point_radius); cf->Write (wxT("line_between_points"), line_between_points); cf->Write (wxT("draw_sigma"), draw_sigma); cf->Write(wxT("model_line_width"), model_line_width_); cfg_write_font (cf, wxT("plabelFont"), plabelFont); cf->Write(wxT("plabel_format"), s2wx(plabel_format_)); cf->Write(wxT("desc_format"), s2wx(desc_format_)); cf->Write (wxT("vertical_plabels"), vertical_plabels_); cf->Write(wxT("xMaxTics"), x_max_tics); cf->Write(wxT("yMaxTics"), y_max_tics); cf->Write(wxT("xTicSize"), x_tic_size); cf->Write(wxT("yTicSize"), y_tic_size); cf->Write(wxT("xReversed"), xs.reversed); cf->Write(wxT("yReversed"), ys.reversed); cf->Write(wxT("xLogarithm"), xs.logarithm); cf->Write(wxT("yLogarithm"), ys.logarithm); cf->Write(wxT("data_colors_count"), (long) data_colors_.size()); cf->SetPath(wxT("/MainPlot/Colors")); cfg_write_color(cf, wxT("bg"), get_bg_color()); cfg_write_color (cf, wxT("inactive_data"), inactiveDataCol); cfg_write_color (cf, wxT("model"), modelCol); cfg_write_color (cf, wxT("BgPoints"), bg_pointsCol); cf->SetPath(wxT("data")); cfg_write_color(cf, wxT("0"), data_colors_[0]); for (size_t i = 1; i < data_colors_.size(); i++) if (data_colors_[i] != data_colors_[0]) cfg_write_color(cf, s2wx(S(i)), data_colors_[i]); cf->SetPath(wxT("../peak")); cfg_write_color(cf, wxT("0"), peakCol[0]); for (int i = 1; i < max_peak_cols; i++) if (peakCol[i] != peakCol[0]) cfg_write_color(cf, s2wx(S(i)), peakCol[i]); //cf->SetPath(wxT("../group")); //for (int i = 0; i < max_group_cols; i++) // cfg_write_color(cf, s2wx(S(i)), groupCol[i]); cf->SetPath(wxT("/MainPlot/Visible")); cf->Write (wxT("peaks"), peaks_visible_); cf->Write (wxT("plabels"), plabels_visible_); cf->Write (wxT("desc"), desc_visible_); //cf->Write (wxT("groups"), groups_visible_); cf->Write (wxT("model"), model_visible_); cf->SetPath(wxT("/MainPlot")); FPlot::save_settings(cf); } void MainPlot::OnLeaveWindow (wxMouseEvent&) { frame->clear_status_coords(); overlay.change_pos(-1, -1); frame->plot_pane()->draw_vertical_lines(-1, -1, this); } void MainPlot::show_popup_menu (wxMouseEvent &event) { wxMenu popup_menu; popup_menu.Append(ID_plot_popup_za, wxT("Zoom &All")); popup_menu.AppendSeparator(); popup_menu.Append(ID_plot_popup_prefs, wxT("Configure...")); PopupMenu(&popup_menu, event.GetX(), event.GetY()); } void MainPlot::show_peak_menu (wxMouseEvent &event) { if (over_peak_ == -1) return; wxMenu peak_menu; peak_menu.Append(ID_peak_popup_info, wxT("Show &Info")); peak_menu.Append(ID_peak_popup_del, wxT("&Delete")); peak_menu.Append(ID_peak_popup_guess, wxT("&Guess parameters")); peak_menu.Append(ID_peak_popup_edit, wxT("&Edit function")); realt dummy; const Function* p = ftk->mgr.get_function(over_peak_); peak_menu.Enable(ID_peak_popup_guess, p->get_center(&dummy)); int active = frame->get_sidebar()->get_active_function(); if (active >= 0 && active != over_peak_) { const Function* a = ftk->mgr.get_function(active); wxMenu *share_menu = new wxMenu; for (int i = 0; i != max(a->nv(), 16); ++i) { const string param = a->get_param(i); if (contains_element(p->tp()->fargs, param)) { share_menu->AppendCheckItem(ID_peak_popup_share+i, "&" + s2wx(param)); if (a->var_name(param) == p->var_name(param)) share_menu->Check(ID_peak_popup_share+i, true); } } peak_menu.Append(-1, "&Share with %" + s2wx(a->name), share_menu); } PopupMenu (&peak_menu, event.GetX(), event.GetY()); } void MainPlot::PeakInfo() { if (over_peak_ >= 0) exec("info prop %" + ftk->mgr.get_function(over_peak_)->name); } void MainPlot::OnPeakDelete(wxCommandEvent&) { if (over_peak_ >= 0) exec("delete %" + ftk->mgr.get_function(over_peak_)->name); } void MainPlot::OnPeakGuess(wxCommandEvent&) { if (over_peak_ < 0) return; const Function* p = ftk->mgr.get_function(over_peak_); realt ctr; if (p->get_center(&ctr)) { double plusmin = 0; realt fwhm, ib; if (p->get_fwhm(&fwhm)) plusmin = fabs(fwhm); if (p->get_ibreadth(&ib) && fabs(ib) > plusmin) plusmin = fabs(ib); plusmin = max(plusmin, 1.); exec(frame->get_datasets() + "guess %" + p->name + " = " + frame->get_guess_string(p->tp()->name) + " [" + eS(ctr-plusmin) + ":" + eS(ctr+plusmin) + "]"); } } void MainPlot::OnPeakEdit(wxCommandEvent&) { if (over_peak_ < 0) return; const Function* p = ftk->mgr.get_function(over_peak_); string t = p->get_current_assignment(ftk->mgr.variables(), ftk->mgr.parameters()); frame->edit_in_input(t); } void MainPlot::OnPeakShare(wxCommandEvent& event) { int active = frame->get_sidebar()->get_active_function(); if (over_peak_ < 0 || active < 0) return; const Function* a = ftk->mgr.get_function(active); const Function* p = ftk->mgr.get_function(over_peak_); string param = a->get_param(event.GetId() - ID_peak_popup_share); string lhs = "%" + p->name + "." + param; if (event.IsChecked()) exec(lhs + " = %" + a->name + "." + param); else exec(lhs + " = ~{" + lhs + "}"); } // mouse usage // // Simple Rules: // 1. When one button is down, pressing other button cancels action // 2. Releasing / keeping down / pressing Ctrl/Alt keys, when you keep // mouse button down makes no difference. // 3. Ctrl and Alt buttons are equivalent. // ---------------------------------- // Usage: // Left/Right Button (no Ctrl) -- mode dependent // Ctrl + Left/Right Button -- the same as Left/Right in normal mode // Middle Button -- rectangle zoom // Shift sometimes makes a difference void MainPlot::switch_to_mode(MouseModeEnum m) { if (pressed_mouse_button_) { if (dragged_func_->has_changed()) frame->get_sidebar()->update_param_panel(); // reverts the values dragged_func_->stop(); downX = downY = INT_MIN; pressed_mouse_button_ = 0; frame->set_status_text(""); } MouseModeEnum old = mode_; if (old == m) return; if (m != mmd_peak) basic_mode_ = m; mode_ = m; update_mouse_hints(); set_cursor(); overlay.switch_mode(mode_ == mmd_activate ? Overlay::kVLine : get_normal_ovmode()); if (old == mmd_bg) bgm_->define_bg_func(); if (old == mmd_bg || mode_ == mmd_bg || visible_peaktops(old) != visible_peaktops(mode_)) refresh(); else overlay.draw_overlay(); } void MainPlot::set_data_color(int n, const wxColour& col) { if (n >= kMaxDataColors) return; if (n >= (int) data_colors_.size()) data_colors_.resize(n+1, data_colors_[0]); data_colors_[n] = col; } // update mouse hint on status bar void MainPlot::update_mouse_hints() { if (!hint_receiver_) return; const char *left=""; const char *right=""; const char *mode_name=""; const char *shift_left = ""; const char *shift_right = ""; if (pressed_mouse_button_) { if (pressed_mouse_button_ != 1) left = "cancel"; if (pressed_mouse_button_ != 3) right = "cancel"; } else { //button not pressed switch (mode_) { case mmd_peak: left = "move peak"; right = "peak menu"; break; case mmd_zoom: left = "zoom"; right = "menu"; shift_left = "vertical zoom"; shift_right = "horizontal zoom"; mode_name = "normal"; break; case mmd_bg: left = "add point"; right = "del point"; mode_name = "baseline"; break; case mmd_add: left = "manual add"; right = "add in range"; mode_name = "add-peak"; break; case mmd_activate: left = "activate"; right = "disactivate"; mode_name = "data range"; shift_left = "activate rectangle"; shift_right = "disactivate rectangle"; break; case mmd_readonly: assert(0); } } hint_receiver_->set_hints(left, right, mode_name, shift_left, shift_right); } void MainPlot::set_cursor() { SetCursor(mode_ == mmd_peak ? wxCURSOR_CROSS : wxCURSOR_ARROW); } void MainPlot::OnMouseMove(wxMouseEvent &event) { //display coords in status bar int X = event.GetX(); int Y = event.GetY(); frame->set_status_coords(xs.valr(X), ys.valr(Y), pte_main); if (pressed_mouse_button_ == 0) { // no button pressed if (visible_peaktops(mode_)) look_for_peaktop(event); if (mode_ == mmd_activate) { if (event.AltDown() || event.CmdDown()) { if (overlay.mode() == Overlay::kVLine) { overlay.switch_mode(get_normal_ovmode()); overlay.draw_overlay(); } } else overlay.switch_mode(Overlay::kVLine); } } else if (pressed_mouse_button_ == 1 && mouse_op_ == kDragPeak && over_peak_ >= 0) { dragged_func_->move(event.ShiftDown(), X, Y, xs.valr(X), ys.valr(Y)); frame->set_status_text(dragged_func_->status()); draw_overlay_func(ftk->mgr.get_function(over_peak_), frame->get_sidebar()->parpan_values()); } overlay.change_pos(X, Y); if (overlay.mode() == Overlay::kVLine || overlay.mode() == Overlay::kCrossHair) frame->plot_pane()->draw_vertical_lines(X, -1, this); else if (overlay.mode() == Overlay::kVRange) frame->plot_pane()->draw_vertical_lines(X, downX, this); } // peak description shown on the status bar static string get_peak_description(int n) { if (n < 0) return ""; const Function* f = ftk->mgr.get_function(n); string s = "%" + f->name + " " + f->tp()->name + " "; for (int i = 0; i < f->nv(); ++i) s += " " + f->get_param(i) + "=" + S(f->av()[i]); return s; } void MainPlot::look_for_peaktop(wxMouseEvent& event) { int focused_data = frame->get_sidebar()->get_focused_data(); const Model* model = ftk->dk.get_model(focused_data); const vector& idx = model->get_ff().idx; if (special_points.size() != idx.size()) refresh(); int n = get_special_point_at_pointer(event); int nearest = n == -1 ? -1 : idx[n]; if (over_peak_ != nearest) { // change cursor, statusbar text and draw limits over_peak_ = nearest; frame->set_status_text(get_peak_description(nearest)); switch_to_mode(nearest == -1 ? basic_mode_ : mmd_peak); } } void MainPlot::cancel_mouse_press() { if (pressed_mouse_button_) { overlay.switch_mode(get_normal_ovmode()); if (dragged_func_->has_changed()) frame->get_sidebar()->update_param_panel(); // reverts the values dragged_func_->stop(); if (GetCapture() == this) ReleaseMouse(); connect_esc_to_cancel(false); downX = downY = INT_MIN; pressed_mouse_button_ = 0; frame->set_status_text(""); update_mouse_hints(); set_cursor(); } } MouseOperation MainPlot::what_mouse_operation(const wxMouseEvent& event) { bool ctrl = (event.AltDown() || event.CmdDown()); bool shift = event.ShiftDown(); int button = event.GetButton(); if (button == 2 || // middle button always zooms (button == 1 && (ctrl || (mode_ == mmd_zoom && !shift)))) return kRectangularZoom; else if (button == 3 && (ctrl || (mode_ == mmd_zoom && !shift))) return kShowPlotMenu; else if (button == 1 && mode_ == mmd_zoom && shift) return kVerticalZoom; else if (button == 3 && mode_ == mmd_zoom && shift) return kHorizontalZoom; else if (button == 1 && mode_ == mmd_peak) return kDragPeak; else if (button == 3 && mode_ == mmd_peak) return kShowPeakMenu; else if (button == 1 && mode_ == mmd_bg) return kAddBgPoint; else if (button == 3 && mode_ == mmd_bg) return kDeleteBgPoint; else if (button == 1 && mode_ == mmd_add) return kAddPeakTriangle; else if (button == 3 && mode_ == mmd_add) return kAddPeakInRange; else if (button == 1 && mode_ == mmd_activate) return shift ? kActivateRect : kActivateSpan; else if (button == 3 && mode_ == mmd_activate) return shift ? kDisactivateRect : kDisactivateSpan; else return kNoMouseOp; } void MainPlot::OnButtonDown (wxMouseEvent &event) { if (pressed_mouse_button_) { // if one button is already down, pressing other button cancels action cancel_mouse_press(); overlay.change_pos(event.GetX(), event.GetY()); overlay.draw_overlay(); frame->plot_pane()->draw_vertical_lines(-1, -1, this); return; } pressed_mouse_button_ = event.GetButton(); downX = event.GetX(); downY = event.GetY(); double x = xs.valr(event.GetX()); double y = ys.valr(event.GetY()); mouse_op_ = what_mouse_operation(event); if (mouse_op_ == kRectangularZoom) { SetCursor(wxCURSOR_MAGNIFIER); CaptureMouse(); connect_esc_to_cancel(true); overlay.start_mode(Overlay::kRect, downX, downY); frame->set_status_text("Select second corner to zoom..."); } else if (mouse_op_ == kShowPlotMenu) { show_popup_menu(event); pressed_mouse_button_ = 0; } else if (mouse_op_ == kShowPeakMenu) { show_peak_menu(event); pressed_mouse_button_ = 0; } else if (mouse_op_ == kVerticalZoom) { SetCursor(wxCURSOR_SIZENS); CaptureMouse(); connect_esc_to_cancel(true); overlay.start_mode(Overlay::kHRange, downX, downY); frame->set_status_text("Select vertical span..."); } else if (mouse_op_ == kHorizontalZoom) { SetCursor(wxCURSOR_SIZEWE); CaptureMouse(); connect_esc_to_cancel(true); overlay.start_mode(Overlay::kVRange, downX, downY); frame->set_status_text("Select horizontal span..."); } else if (mouse_op_ == kDragPeak) { frame->get_sidebar()->activate_function(over_peak_); SetCursor(wxCURSOR_SIZENWSE); connect_esc_to_cancel(true); const Function* p = ftk->mgr.get_function(over_peak_); dragged_func_->start(p, downX, downY, x, y, frame->get_sidebar()->dragged_func_callback()); overlay.start_mode(Overlay::kFunction, downX, downY); draw_overlay_limits(p); frame->set_status_text("Moving %" + p->name + "..."); } else if (mouse_op_ == kAddBgPoint) { bgm_->add_background_point(x, y); refresh(); } else if (mouse_op_ == kDeleteBgPoint) { bgm_->rm_background_point(x); refresh(); } else if (mouse_op_ == kAddPeakTriangle) { const Tplate* tp = ftk->get_tpm()->get_tp(frame->get_peak_type()); if (tp == NULL) return; if (tp->traits & Tplate::kPeak) { func_draft_kind_ = Tplate::kPeak; overlay.start_mode(Overlay::kPeakDraft, downX, ys.px(0)); } else if (tp->traits & Tplate::kSigmoid) { func_draft_kind_ = Tplate::kSigmoid; overlay.start_mode(Overlay::kSigmoidDraft, downX, downY); } else { func_draft_kind_ = Tplate::kLinear; overlay.start_mode(Overlay::kLinearDraft, downX, downY); } SetCursor(wxCURSOR_SIZING); connect_esc_to_cancel(true); frame->set_status_text("Add function from wireframe..."); // see also: add_peak_from_draft() } else if (mouse_op_ == kAddPeakInRange) { SetCursor(wxCURSOR_SIZEWE); connect_esc_to_cancel(true); overlay.start_mode(Overlay::kVRange, downX, downY); frame->set_status_text("Select range to add a peak in it..."); } else if (mouse_op_ == kActivateSpan || mouse_op_ == kDisactivateSpan || mouse_op_ == kActivateRect || mouse_op_ == kDisactivateRect) { string act_str; if (mouse_op_ == kActivateSpan || mouse_op_ == kActivateRect) { if (!can_activate()) { pressed_mouse_button_ = 0; wxMessageBox( wxT("You pressed the left mouse button in data-range mode,") wxT("\nbut all data points are already active.") wxT("\n\nThe left button activates,") wxT("\nand the right disactivates points."), wxT("How to use mouse..."), wxOK|wxICON_INFORMATION); return; } act_str = "activate"; } else act_str = "disactivate"; string status_beginning; CaptureMouse(); connect_esc_to_cancel(true); if (mouse_op_ == kActivateRect || mouse_op_ == kDisactivateRect) { SetCursor(wxCURSOR_SIZENWSE); overlay.start_mode(Overlay::kRect, downX, downY); status_beginning = "Select data in rectangle to "; } else { SetCursor(wxCURSOR_SIZEWE); overlay.start_mode(Overlay::kVRange, downX, downY); status_beginning = "Select data range to "; } frame->set_status_text(status_beginning + act_str + "..."); } update_mouse_hints(); } void MainPlot::OnAuxDown(wxMouseEvent &event) { cancel_action(); int step = (event.GetEventType() == wxEVT_AUX1_DOWN ? -1 : +1); frame->zoom_hist().move(step); } void MainPlot::OnMouseWheel(wxMouseEvent &event) { cancel_action(); // wheel rotation is typically +/-120 double scale = -0.0025 * event.GetWheelRotation(); int X = event.GetX(); int Y = event.GetY(); int W = GetClientSize().GetWidth(); int H = GetClientSize().GetHeight(); double x0 = xs.valr(iround(-scale * X)); double x1 = xs.valr(iround(W + scale * (W - X))); if (x1 < x0) swap(x0, x1); double y0 = ys.valr(iround(-scale * Y)); double y1 = ys.valr(iround(H + scale * (H - Y))); if (y1 < y0) swap(y0, y1); frame->change_zoom(RealRange(x0, x1), RealRange(y0, y1)); } bool MainPlot::can_activate() { vector sel = frame->get_sidebar()->get_selected_data_indices(); v_foreach (int, i, sel) { const fityk::Data* data = ftk->dk.data(*i); // if data->is_empty() we allow to try disactivate data to let user // experiment with mouse right after launching the program if (data->is_empty() || data->get_n() != (int) data->points().size()) return true; } return false; } static void freeze_functions_in_range(double x1, double x2, bool freeze) { string cmd; v_foreach (Function*, i, ftk->mgr.functions()) { realt ctr; if (!(*i)->get_center(&ctr)) continue; if (!(x1 < ctr && ctr < x2)) continue; for (int j = 0; j != (*i)->used_vars().get_count(); ++j) { const Variable* var = ftk->mgr.get_variable((*i)->used_vars().get_idx(j)); if (freeze && var->is_simple()) { cmd += "$" + var->name + "=" + eS(var->value()) + "; "; } else if (!freeze && var->is_constant()) { cmd += "$" + var->name + "=~" + eS(var->value()) + "; "; } } } if (!cmd.empty()) exec(cmd); } void MainPlot::OnButtonUp (wxMouseEvent &event) { int button = event.GetButton(); if (button != pressed_mouse_button_) { pressed_mouse_button_ = 0; return; } overlay.switch_mode(get_normal_ovmode()); if (GetCapture() == this) ReleaseMouse(); connect_esc_to_cancel(false); pressed_mouse_button_ = 0; update_mouse_hints(); set_cursor(); // some actions are cancelled when Down and Up events are in the same place if (abs(event.GetX() - downX) + abs(event.GetY() - downY) < 5 && (mouse_op_ == kRectangularZoom || mouse_op_ == kVerticalZoom || mouse_op_ == kHorizontalZoom || mouse_op_ == kActivateSpan || mouse_op_ == kDisactivateSpan || mouse_op_ == kActivateRect || mouse_op_ == kDisactivateRect || mouse_op_ == kAddPeakTriangle || mouse_op_ == kAddPeakInRange)) { frame->set_status_text(""); overlay.draw_overlay(); return; } // zoom if (mouse_op_ == kRectangularZoom) { double x1 = xs.valr(downX); double x2 = xs.valr(event.GetX()); double y1 = ys.valr(downY); double y2 = ys.valr(event.GetY()); frame->change_zoom(RealRange(min(x1,x2), max(x1,x2)), RealRange(min(y1,y2), max(y1,y2))); } else if (mouse_op_ == kVerticalZoom) { double y1 = ys.valr(downY); double y2 = ys.valr(event.GetY()); frame->change_zoom(ftk->view.hor, RealRange(min(y1,y2), max(y1,y2))); } else if (mouse_op_ == kHorizontalZoom) { double x1 = xs.valr(downX); double x2 = xs.valr(event.GetX()); frame->change_zoom(RealRange(min(x1,x2), max(x1,x2)), ftk->view.ver); } // drag peak else if (mouse_op_ == kDragPeak) { string cmd = dragged_func_->get_cmd(); dragged_func_->stop(); if (!cmd.empty()) exec(cmd); else { overlay.draw_overlay(); frame->set_status_text(""); } } // activate or disactivate data else if (mouse_op_ == kActivateSpan || mouse_op_ == kDisactivateSpan || mouse_op_ == kActivateRect || mouse_op_ == kDisactivateRect) { bool rect = (mouse_op_ == kActivateRect || mouse_op_ == kDisactivateRect); bool activate = (mouse_op_== kActivateSpan || mouse_op_ == kActivateRect); string c = (activate ? "A = a or" : "A = a and not"); double x1 = xs.valr(downX); double x2 = xs.valr(event.GetX()); if (x1 > x2) swap(x1, x2); string cond = eS(x1) + " < x and x < " + eS(x2); if (rect) { double y1 = ys.valr(downY); double y2 = ys.valr(event.GetY()); cond += " and " + eS(min(y1,y2)) + " < y and y < " + eS(max(y1,y2)); } exec(frame->get_datasets() + c + " (" + cond + ")"); if (auto_freeze_ && !rect) freeze_functions_in_range(x1, x2, !activate); } // add peak (left button) else if (mouse_op_ == kAddPeakTriangle) { add_peak_from_draft(event.GetX(), event.GetY()); } // add peak (in range) else if (mouse_op_ == kAddPeakInRange) { double x1 = xs.valr(downX); double x2 = xs.valr(event.GetX()); exec(frame->get_datasets() + "guess " + frame->get_guess_string(frame->get_peak_type()) + " [" + eS(min(x1,x2)) + " : " + eS(max(x1,x2)) + "]"); } else { ;// nothing - action done in OnButtonDown() } } void MainPlot::add_peak_from_draft(int X, int Y) { string args; double x1 = xs.valr(downX); double y1 = ys.valr(downY); double x2 = xs.valr(X); double y2 = ys.valr(Y); if (func_draft_kind_ == Tplate::kLinear) { if (downX == X) return; double m = (y2 - y1) / (x2 - x1); args = "slope=~" + eS(m) + ", intercept=~" + eS(y1-m*x1) + ", avgy=~" + eS((y1+y2)/2); } else if (func_draft_kind_ == Tplate::kPeak) { double height = y2; double center = x1; double hwhm = fabs(center - x2); double area = 2 * height * hwhm; args = "height=~" + eS(height) + ", center=~" + eS(center) + ", area=~" + eS(area); if (ftk->mgr.find_variable_nr("_hwhm") == -1) args += ", hwhm=~" + eS(hwhm); } else if (func_draft_kind_ == Tplate::kSigmoid) { double lower = y1 - fabs(y2-y1); double upper = y1 + fabs(y2-y1); double xmid = x1; // this corresponds to the drawing in Overlay::draw_overlay() double wsig = (y2 > y1 ? 1 : -1) * 0.5 * fabs(x2-x1); args = "lower=~" + eS(lower) + ", upper=~" + eS(upper) + ", xmid=~" + eS(xmid) + ", wsig=~" + eS(wsig); } string tail = "F += " + frame->get_guess_string(frame->get_peak_type()); if (*(tail.end() - 1) == ')') { tail.resize(tail.size() - 1); tail += ", " + args + ")"; } else tail += "(" + args + ")"; string cmd; if (ftk->dk.count() == 1) cmd = tail; else { vector sel = frame->get_sidebar()->get_selected_data_indices(); cmd = "@" + join_vector(sel, "." + tail + "; @") + "." + tail; } exec(cmd); } static void calculate_values(const vector& xx, vector& yy, const Tplate::Ptr& tp, const vector& p_values) { int len = p_values.size(); vector varnames(len); for (int i = 0; i != len; ++i) varnames[i] = "v" + S(i); boost::scoped_ptr f( (*tp->create)(ftk->get_settings(), "tmp", tp, varnames)); f->init(); // create variables with the same values as p_values vector variables(len); const vector dummy_vars; for (int i = 0; i != len; ++i) { fityk::OpTree* tree = new fityk::OpTree(p_values[i]); variables[i] = new Variable("v" + S(i), vector(), vector1(tree)); variables[i]->set_var_idx(dummy_vars); variables[i]->recalculate(dummy_vars, vector()); } f->update_var_indices(variables); f->do_precomputations(variables); f->calculate_value(xx, yy); purge_all_elements(variables); } void MainPlot::draw_overlay_func(const Function* f, const vector& p_values) { int n = GetClientSize().GetWidth(); if (n <= 0) return; vector xx(n), yy(n, 0); for (int i = 0; i < n; ++i) xx[i] = xs.val(i); calculate_values(xx, yy, f->tp(), p_values); wxPoint *points = new wxPoint[n]; for (int i = 0; i < n; ++i) { points[i].x = i; points[i].y = ys.px(yy[i]); } overlay.draw_lines(n, points); delete [] points; } void MainPlot::draw_overlay_limits(const Function* f) { double cutoff = ftk->get_settings()->function_cutoff; if (cutoff == 0) return; realt x1, x2; bool r = f->get_nonzero_range(cutoff, x1, x2); if (r) { int xleft = xs.px(x1); int xright = xs.px(x2); wxPoint lim[4] = { wxPoint(xleft, 0), wxPoint(xleft, ys.px(cutoff)), wxPoint(xright, ys.px(cutoff)), wxPoint(xright, 0) }; overlay.draw_lines(4, lim); } } void MainPlot::OnConfigure(wxCommandEvent&) { MainPlotConfDlg dialog(this); dialog.ShowModal(); } void MainPlot::OnZoomAll(wxCommandEvent&) { frame->GViewAll(); } //=============================================================== MainPlotConfDlg::MainPlotConfDlg(MainPlot* mp) : wxDialog(NULL, -1, wxString(wxT("Configure Main Plot")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE), mp_(mp) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *hor_sizer = new wxBoxSizer(wxHORIZONTAL); wxFlexGridSizer *gsizer = new wxFlexGridSizer(2, 5, 5); wxSizerFlags cl = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL), cr = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT); gsizer->Add(new wxStaticText(this, -1, wxT("background")), cr); bg_cp_ = new wxColourPickerCtrl(this, -1, mp_->get_bg_color()); gsizer->Add(bg_cp_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("colors for datasets")), cr); wxBoxSizer *data_col_sizer = new wxBoxSizer(wxHORIZONTAL); data_colors_sc_ = new SpinCtrl(this, -1, mp_->data_colors_.size(), 2, MainPlot::kMaxDataColors, /*width=*/60); data_col_sizer->Add(data_colors_sc_, cl); data_color_combo_ = new MultiColorCombo(this, &mp_->get_bg_color(), mp_->data_colors_); data_color_combo_->SetSelection(0); data_col_sizer->Add(data_color_combo_, cl); gsizer->Add(data_col_sizer, cr); gsizer->Add(new wxStaticText(this, -1, wxT("inactive data")), cr); inactive_cp_ = new wxColourPickerCtrl(this, -1, mp_->inactiveDataCol); gsizer->Add(inactive_cp_, cl); model_cb_ = new wxCheckBox(this, -1, wxT("model (sum)")); model_cb_->SetValue(mp_->model_visible_); gsizer->Add(model_cb_, cr); wxBoxSizer *model_sizer = new wxBoxSizer(wxHORIZONTAL); model_cp_ = new wxColourPickerCtrl(this, -1, mp_->modelCol); model_sizer->Add(model_cp_, cl.Border(wxRIGHT)); model_sizer->Add(new wxStaticText(this, -1, wxT("width:")), cl); model_width_sc_ = new SpinCtrl(this, -1, mp_->model_line_width_, 1, 5); model_sizer->Add(model_width_sc_, cl); gsizer->Add(model_sizer, cl); func_cb_ = new wxCheckBox(this, -1, wxT("functions")); func_cb_->SetValue(mp_->peaks_visible_); gsizer->Add(func_cb_, cr); func_cp_ = new wxColourPickerCtrl(this, -1, mp_->peakCol[0]); gsizer->Add(func_cp_, cl); labels_cb_ = new wxCheckBox(this, -1, wxT("function labels")); labels_cb_->SetValue(mp_->plabels_visible_); gsizer->Add(labels_cb_, cr); label_fp_ = new wxFontPickerCtrl(this, -1, mp_->plabelFont); gsizer->Add(label_fp_, cl); gsizer->Add(new wxStaticText(this, -1, wxEmptyString), cr); vertical_labels_cb_ = new wxCheckBox(this, -1, wxT("vertical")); vertical_labels_cb_->SetValue(mp_->vertical_plabels_); gsizer->Add(vertical_labels_cb_, cl); gsizer->Add(new wxStaticText(this, -1, wxEmptyString), cr); wxArrayString label_choices; label_choices.Add(wxT("")); label_choices.Add(wxT("")); label_choices.Add(wxT("
")); label_choices.Add(wxT("")); label_choices.Add(wxT("")); label_choices.Add(wxT("")); label_choices.Add(wxT(" ")); label_choices.Add(wxT("
")); label_combo_ = new wxComboBox(this, -1, s2wx(mp_->plabel_format_), wxDefaultPosition, wxDefaultSize, label_choices); label_combo_->SetToolTip(wxT("Labels can show the following properties:\n") wxT(" area\n") wxT(" height\n") wxT("
center\n") wxT(" peak FWHM\n") wxT(" integral breadth (area/FWHM)\n") wxT(" function's name\n") wxT("
line break\n")); gsizer->Add(label_combo_, cl); desc_cb_ = new wxCheckBox(this, -1, wxT("plot description")); desc_cb_->SetValue(mp_->desc_visible_); gsizer->Add(desc_cb_, cr); wxArrayString desc_choices; desc_choices.Add("title"); desc_choices.Add("filename"); desc_choices.Add("fit"); desc_choices.Add("filename,fit"); desc_combo_ = new wxComboBox(this, -1, s2wx(mp_->desc_format_), wxDefaultPosition, wxDefaultSize, desc_choices); desc_combo_->SetToolTip("Description (in the right top corner)\n" "is an output of the info command.\n" "You can give any info arguments here."); gsizer->Add(desc_combo_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("axis & tics color")), cr); axis_cp_ = new wxColourPickerCtrl(this, -1, mp_->xAxisCol); gsizer->Add(axis_cp_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("tic label font")), cr); tics_fp_ = new wxFontPickerCtrl(this, -1, mp_->ticsFont); gsizer->Add(tics_fp_, cl); hor_sizer->Add(gsizer, wxSizerFlags().Border()); wxStaticBoxSizer *xsizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("X axis")); x_show_axis_cb_ = new wxCheckBox(this, -1, wxT("show axis")); x_show_axis_cb_->SetValue(mp_->x_axis_visible); xsizer->Add(x_show_axis_cb_, 0, wxALL, 5); x_show_tics_cb_ = new wxCheckBox(this, -1, wxT("show tics")); x_show_tics_cb_->SetValue(mp_->xtics_visible); xsizer->Add(x_show_tics_cb_, 0, wxALL, 5); wxBoxSizer* xsizer_t = new wxBoxSizer(wxVERTICAL); x_show_minor_tics_cb_ = new wxCheckBox(this, -1, wxT("show minor tics")); x_show_minor_tics_cb_->SetValue(mp_->xminor_tics_visible); xsizer_t->Add(x_show_minor_tics_cb_, 0, wxALL, 5); x_show_grid_cb_ = new wxCheckBox(this, -1, wxT("show grid")); x_show_grid_cb_->SetValue(mp_->x_grid); xsizer_t->Add(x_show_grid_cb_, 0, wxALL, 5); wxBoxSizer *xmt_sizer = new wxBoxSizer(wxHORIZONTAL); xmt_sizer->Add(new wxStaticText(this, -1, wxT("max. number of tics")), 0, wxALL|wxALIGN_CENTRE_VERTICAL, 5); x_max_tics_sc_ = new wxSpinCtrl(this, -1, wxT("7"), wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, 30, 7); x_max_tics_sc_->SetValue(mp_->x_max_tics); xmt_sizer->Add(x_max_tics_sc_, 0, wxALL, 5); xsizer_t->Add(xmt_sizer); wxBoxSizer *xts_sizer = new wxBoxSizer(wxHORIZONTAL); xts_sizer->Add(new wxStaticText(this, -1, wxT("length of tics")), 0, wxALL|wxALIGN_CENTRE_VERTICAL, 5); x_tic_size_sc_ = new wxSpinCtrl(this, -1, wxT("4"), wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, -10, 20, 4); x_tic_size_sc_->SetValue(mp_->x_tic_size); xts_sizer->Add(x_tic_size_sc_, 0, wxALL, 5); xsizer_t->Add(xts_sizer); xsizer->Add(xsizer_t, 0, wxLEFT, 15); x_reversed_cb_ = new wxCheckBox(this, -1, wxT("reversed axis")); x_reversed_cb_->SetValue(mp_->xs.reversed); xsizer->Add(x_reversed_cb_, 0, wxALL, 5); x_logarithm_cb_ = new wxCheckBox(this, -1, wxT("logarithmic scale")); x_logarithm_cb_->SetValue(mp_->xs.logarithm); xsizer->Add(x_logarithm_cb_, 0, wxALL, 5); hor_sizer->Add(xsizer, 0, wxALL, 5); wxStaticBoxSizer *ysizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Y axis")); y_show_axis_cb_ = new wxCheckBox(this, -1, wxT("show axis")); y_show_axis_cb_->SetValue(mp_->y_axis_visible); ysizer->Add(y_show_axis_cb_, 0, wxALL, 5); y_show_tics_cb_ = new wxCheckBox(this, -1, wxT("show tics")); y_show_tics_cb_->SetValue(mp_->ytics_visible); ysizer->Add(y_show_tics_cb_, 0, wxALL, 5); wxBoxSizer* ysizer_t = new wxBoxSizer(wxVERTICAL); y_show_minor_tics_cb_ = new wxCheckBox(this, -1, wxT("show minor tics")); y_show_minor_tics_cb_->SetValue(mp_->yminor_tics_visible); ysizer_t->Add(y_show_minor_tics_cb_, 0, wxALL, 5); y_show_grid_cb_ = new wxCheckBox(this, -1, wxT("show grid")); y_show_grid_cb_->SetValue(mp_->y_grid); ysizer_t->Add(y_show_grid_cb_, 0, wxALL, 5); wxBoxSizer *ymt_sizer = new wxBoxSizer(wxHORIZONTAL); ymt_sizer->Add(new wxStaticText(this, -1, wxT("max. number of tics")), 0, wxALL|wxALIGN_CENTRE_VERTICAL, 5); y_max_tics_sc_ = new wxSpinCtrl(this, -1, wxT("7"), wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, 30, 7); y_max_tics_sc_->SetValue(mp_->y_max_tics); ymt_sizer->Add(y_max_tics_sc_, 0, wxALL, 5); ysizer_t->Add(ymt_sizer); wxBoxSizer *yts_sizer = new wxBoxSizer(wxHORIZONTAL); yts_sizer->Add(new wxStaticText(this, -1, wxT("length of tics")), 0, wxALL|wxALIGN_CENTRE_VERTICAL, 5); y_tic_size_sc_ = new wxSpinCtrl(this, -1, wxT("4"), wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, 20, 4); y_tic_size_sc_->SetValue(mp_->y_tic_size); yts_sizer->Add(y_tic_size_sc_, 0, wxALL, 5); ysizer_t->Add(yts_sizer); ysizer->Add(ysizer_t, 0, wxLEFT, 15); y_reversed_cb_ = new wxCheckBox(this, -1, wxT("reversed axis")); y_reversed_cb_->SetValue(mp_->ys.reversed); ysizer->Add(y_reversed_cb_, 0, wxALL, 5); y_logarithm_cb_ = new wxCheckBox(this, -1, wxT("logarithmic scale")); y_logarithm_cb_->SetValue(mp_->ys.logarithm); ysizer->Add(y_logarithm_cb_, 0, wxALL, 5); hor_sizer->Add(ysizer, 0, wxALL, 5); top_sizer->Add(hor_sizer, 0); top_sizer->Add(persistance_note(this), wxSizerFlags().Center().Border()); top_sizer->Add(new wxButton(this, wxID_CLOSE), wxSizerFlags().Right().Border()); SetSizerAndFit(top_sizer); SetEscapeId(wxID_CLOSE); Connect(model_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnModelCheckbox)); Connect(model_width_sc_->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(MainPlotConfDlg::OnModelWidthSpin)); Connect(func_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnFuncCheckbox)); Connect(labels_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnLabelsCheckbox)); Connect(desc_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnDescCheckbox)); Connect(vertical_labels_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnVerticalCheckbox)); Connect(-1, wxEVT_COMMAND_COLOURPICKER_CHANGED, wxColourPickerEventHandler(MainPlotConfDlg::OnColor)); Connect(tics_fp_->GetId(), wxEVT_COMMAND_FONTPICKER_CHANGED, wxFontPickerEventHandler(MainPlotConfDlg::OnTicsFont)); Connect(label_fp_->GetId(), wxEVT_COMMAND_FONTPICKER_CHANGED, wxFontPickerEventHandler(MainPlotConfDlg::OnLabelFont)); Connect(label_combo_->GetId(), wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(MainPlotConfDlg::OnLabelTextChanged)); Connect(label_combo_->GetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(MainPlotConfDlg::OnLabelTextChanged)); Connect(desc_combo_->GetId(), wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(MainPlotConfDlg::OnDescTextChanged)); Connect(desc_combo_->GetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(MainPlotConfDlg::OnDescTextChanged)); Connect(data_colors_sc_->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(MainPlotConfDlg::OnDataColorsSpin)); Connect(data_color_combo_->GetId(), wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(MainPlotConfDlg::OnDataColorSelection)); Connect(x_show_axis_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowXAxis)); Connect(y_show_axis_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowYAxis)); Connect(x_show_tics_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowXTics)); Connect(y_show_tics_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowYTics)); Connect(x_show_minor_tics_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowXMinorTics)); Connect(y_show_minor_tics_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowYMinorTics)); Connect(x_show_grid_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowXGrid)); Connect(y_show_grid_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnShowYGrid)); Connect(x_reversed_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnReversedX)); Connect(y_reversed_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnReversedY)); Connect(x_logarithm_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnLogX)); Connect(y_logarithm_cb_->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(MainPlotConfDlg::OnLogY)); Connect(x_max_tics_sc_->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(MainPlotConfDlg::OnMaxXTicsSpin)); Connect(y_max_tics_sc_->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(MainPlotConfDlg::OnMaxYTicsSpin)); Connect(x_tic_size_sc_->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(MainPlotConfDlg::OnXTicSize)); Connect(y_tic_size_sc_->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(MainPlotConfDlg::OnYTicSize)); } void MainPlotConfDlg::OnColor(wxColourPickerEvent& event) { int id = event.GetId(); if (id == bg_cp_->GetId()) { mp_->set_bg_color(event.GetColour()); frame->update_data_pane(); data_color_combo_->Refresh(); } else if (id == inactive_cp_->GetId()) mp_->inactiveDataCol = event.GetColour(); else if (id == axis_cp_->GetId()) mp_->xAxisCol = event.GetColour(); else if (id == model_cp_->GetId()) mp_->modelCol = event.GetColour(); else if (id == func_cp_->GetId()) { for (int i = 0; i < MainPlot::max_peak_cols; ++i) mp_->peakCol[i] = event.GetColour(); } mp_->refresh(); } fityk-1.3.1/wxgui/mplot.h000066400000000000000000000137611302634723100153220ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_MPLOT_H_ #define FITYK_WX_MPLOT_H_ #include "plot.h" #include "fityk/tplate.h" // Tplate::Kind /// it cares about visualization of spline / polyline background /// which can be set by selecting points on Plot namespace fityk { class Function; } class HintReceiver; class BgManager; class DraggedFunc; // operation started by pressing mouse button enum MouseOperation { // press-move-release operation kRectangularZoom, kVerticalZoom, kHorizontalZoom, kActivateSpan, kDisactivateSpan, kActivateRect, kDisactivateRect, kAddPeakInRange, kAddPeakTriangle, kDragPeak, // one-click operation kShowPlotMenu, kShowPeakMenu, kAddBgPoint, kDeleteBgPoint, // nothing kNoMouseOp }; /// main plot, single in application, displays data, fitted peaks etc. class MainPlot : public FPlot { friend class MainPlotConfDlg; public: static const int kMaxDataColors = 256; MainPlot(wxWindow *parent); ~MainPlot(); void OnPaint(wxPaintEvent &event); virtual void draw(wxDC &dc, bool monochrome=false); void OnLeaveWindow (wxMouseEvent& event); void OnMouseMove(wxMouseEvent &event); void OnButtonDown (wxMouseEvent &event); void OnLeftDClick (wxMouseEvent&) { PeakInfo(); } void OnButtonUp (wxMouseEvent &event); void OnAuxDown(wxMouseEvent &event); void OnMouseWheel(wxMouseEvent &event); void OnConfigure(wxCommandEvent&); void OnZoomAll(wxCommandEvent& event); void PeakInfo(); void OnPeakInfo(wxCommandEvent&) { PeakInfo(); } void OnPeakDelete(wxCommandEvent& event); void OnPeakGuess(wxCommandEvent &event); void OnPeakEdit(wxCommandEvent &event); void OnPeakShare(wxCommandEvent &event); // function called when Esc is pressed virtual void cancel_action() { cancel_mouse_press(); overlay.draw_overlay(); } void cancel_mouse_press(); void save_settings(wxConfigBase *cf) const; void read_settings(wxConfigBase *cf); void update_mouse_hints(); void set_cursor(); void switch_to_mode(MouseModeEnum m); void set_mode(MouseModeEnum m) { mode_ = m; } MouseModeEnum get_mouse_mode() const { return mode_; } const wxColour& get_data_color(int n) const { return data_colors_[n < (int) data_colors_.size() ? n : 0]; } const wxColour& get_func_color(int n) const { return peakCol[n % max_peak_cols]; } void set_data_color(int n, const wxColour& col); void set_data_point_size(int /*n*/, int r) { point_radius = r; } void set_data_with_line(int /*n*/, bool b) { line_between_points = b; } void set_data_with_sigma(int /*n*/, bool b) { draw_sigma = b; } int get_data_point_size(int /*n*/) const { return point_radius; } bool get_data_with_line(int /*n*/) const { return line_between_points; } void set_func_color(int n, const wxColour& col) { peakCol[n % max_peak_cols] = col; } bool get_x_reversed() const { return x_reversed_; } void show_popup_menu(wxMouseEvent &event); void set_hint_receiver(HintReceiver *hr) { hint_receiver_ = hr; update_mouse_hints(); } void set_auto_freeze(bool value) { auto_freeze_ = value; } BgManager* bgm() { return bgm_; } void draw_overlay_func(const fityk::Function* f, const std::vector& p_values); void draw_overlay_limits(const fityk::Function* f); bool crosshair_cursor() const { return crosshair_cursor_; } void set_crosshair_cursor(bool c) { crosshair_cursor_ = c; overlay.switch_mode(get_normal_ovmode()); } Overlay::Mode get_normal_ovmode() const { return crosshair_cursor_ ? Overlay::kCrossHair : Overlay::kNone; } private: BgManager* bgm_; DraggedFunc *dragged_func_; // for mouse-driven function dragging MouseModeEnum basic_mode_, mode_; ///actual mode -- either basic_mode_ or mmd_peak // plot properties stored in config //static const int max_group_cols = 8; static const int max_peak_cols = 32; bool peaks_visible_, /*groups_visible_,*/ model_visible_, plabels_visible_, desc_visible_, x_reversed_; wxFont plabelFont; std::string plabel_format_, desc_format_; bool vertical_plabels_; wxColour modelCol, bg_pointsCol; int model_line_width_; //wxColour groupCol[max_group_cols]; wxColour peakCol[max_peak_cols]; std::vector data_colors_; bool crosshair_cursor_; std::vector plabels_; // peak labels int pressed_mouse_button_; MouseOperation mouse_op_; int over_peak_; /// the cursor is over peaktop of this peak fityk::Tplate::Kind func_draft_kind_; // for function adding (drawing draft) HintReceiver *hint_receiver_; // used to set mouse hints, probably statusbar bool auto_freeze_; void draw_x_axis (wxDC& dc, bool set_pen=true); void draw_y_axis (wxDC& dc, bool set_pen=true); void draw_baseline(wxDC& dc, bool set_pen=true); void draw_model (wxDC& dc, const fityk::Model* model, bool set_pen=true); //void draw_groups (wxDC& dc, const fityk::Model* model, bool set_pen=true); void draw_peaks (wxDC& dc, const fityk::Model* model, bool set_pen=true); void draw_peaktops (wxDC& dc, const fityk::Model* model); void draw_peaktop_selection(wxDC& dc, const fityk::Model* model); void draw_desc(wxDC& dc, int dataset, bool set_pen=true); void draw_plabels (wxDC& dc, const fityk::Model* model, bool set_pen=true); void draw_dataset(wxDC& dc, int n, bool set_pen=true); void prepare_peaktops(const fityk::Model* model, int Ymax); void prepare_peak_labels(const fityk::Model* model); void look_for_peaktop (wxMouseEvent& event); void show_peak_menu (wxMouseEvent &event); static bool visible_peaktops(MouseModeEnum mode); void add_peak_from_draft(int X, int Y); bool can_activate(); MouseOperation what_mouse_operation(const wxMouseEvent& event); DECLARE_EVENT_TABLE() }; #endif fityk-1.3.1/wxgui/parpan.cpp000066400000000000000000000320431302634723100157750ustar00rootroot00000000000000// Purpose: ParameterPanel and LockableRealCtrl (both for input of real numbers) // Copyright 2007-2010 Marcin Wojdyr // Licence: wxWidgets licence #include #include "parpan.h" #include "cmn.h" //KFTextCtrl #include "img/lock.xpm" #include "img/lock_open.xpm" #include "img/goto.xpm" using namespace std; static wxString double2wxstr(double v) { return wxString::Format(wxT("%.7g"), v); } //=============================================================== // ValueChangingWidget //=============================================================== /// small widget used to change value of associated wxTextCtrl with real number class ValueChangingWidget : public wxSlider { public: ValueChangingWidget(wxWindow* parent, wxWindowID id, ValueChangingWidgetObserver* observer); private: ValueChangingWidgetObserver *observer_; wxTimer timer_; void OnTimer(wxTimerEvent &event); void OnThumbTrack(wxScrollEvent&); }; ValueChangingWidget::ValueChangingWidget(wxWindow* parent, wxWindowID id, ValueChangingWidgetObserver* observer) : wxSlider(parent, id, 0, -100, 100, wxDefaultPosition, wxSize(60, -1)), observer_(observer), timer_(this, -1) { Connect(wxEVT_TIMER, wxTimerEventHandler(ValueChangingWidget::OnTimer)); Connect(wxEVT_SCROLL_THUMBTRACK, wxScrollEventHandler(ValueChangingWidget::OnThumbTrack)); } void ValueChangingWidget::OnTimer(wxTimerEvent&) { wxMouseState state = wxGetMouseState(); int slider_pos = GetValue(); #if wxCHECK_VERSION(2, 9, 1) if (state.LeftIsDown()) #else if (state.LeftDown()) #endif observer_->change_value(this, slider_pos*0.001); #if wxCHECK_VERSION(2, 9, 1) else if (state.MiddleIsDown()) #else else if (state.MiddleDown()) #endif observer_->change_value(this, slider_pos*0.0001); #if wxCHECK_VERSION(2, 9, 1) else if (state.RightIsDown()) #else else if (state.RightDown()) #endif observer_->change_value(this, slider_pos*0.00001); else { timer_.Stop(); SetValue(0); // move the slider to the central position observer_->finalize_changes(); } } void ValueChangingWidget::OnThumbTrack(wxScrollEvent&) { if (!timer_.IsRunning()) timer_.Start(100); } class LockButton : public wxBitmapButton { public: static void initialize_bitmaps(); LockButton(wxWindow* parent, bool connect_default_handler) : wxBitmapButton(parent, -1, bitmaps[0], wxDefaultPosition, wxDefaultSize, wxNO_BORDER), state_(0) { assert(bitmaps[0].IsOk()); if (connect_default_handler) Connect(GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(LockButton::OnClick)); } void set_state(int state) { assert(state >= 0 && state < 3); state_ = state; SetBitmapLabel(bitmaps[state]); } int state() const { return state_; } private: static wxBitmap bitmaps[3]; int state_; void OnClick(wxCommandEvent&) { set_state(state_ == 0 ? 1 : 0); } }; wxBitmap LockButton::bitmaps[3]; void LockButton::initialize_bitmaps() { if (bitmaps[0].IsOk()) return; #ifdef __WXMAC__ // wxOSX supports border-less image buttons only when using bitmap of // one of the standard sizes (128x128, 48x48, 24x24 or 16x16). // Let's resize the bitmaps from 12x14 to 16x16. #define RESIZE_BMP(xpm) \ wxImage(xpm).Size(wxSize(16, 16), wxPoint(2, 1)) #else #define RESIZE_BMP(xpm) xpm #endif bitmaps[0] = wxBitmap(RESIZE_BMP(lock_xpm)); bitmaps[1] = wxBitmap(RESIZE_BMP(lock_open_xpm)); bitmaps[2] = wxBitmap(RESIZE_BMP(goto_xpm)); } LockableRealCtrl::LockableRealCtrl(wxWindow* parent, bool percent) : wxPanel(parent, -1) { if (percent) text = new KFTextCtrl(this, -1, wxT(""), 50, wxTE_RIGHT); else text = new KFTextCtrl(this, -1, wxT("")); LockButton::initialize_bitmaps(); lock = new LockButton(this, true); wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); sizer->Add(text, wxSizerFlags().Center()); if (percent) sizer->Add(new wxStaticText(this, -1, wxT("%")), wxSizerFlags().Center()); sizer->Add(lock, wxSizerFlags().Center()); SetSizerAndFit(sizer); } double LockableRealCtrl::get_value() const { double d; bool ok = text->GetValue().ToDouble(&d); return ok ? d : 0.; } void LockableRealCtrl::set_value(double value) { if (value != get_value()) text->ChangeValue(wxString::Format(wxT("%g"), value)); } bool LockableRealCtrl::is_locked() const { return lock->state() == 0; } void LockableRealCtrl::set_lock(bool locked) { lock->set_state(locked ? 0 : 1); } bool LockableRealCtrl::is_nonzero() const { double d; bool ok = text->GetValue().ToDouble(&d); if (!ok) return false; return d != 0. || !is_locked(); } ParameterPanel::ParameterPanel(wxWindow* parent, wxWindowID id, ParameterPanelObserver *observer) : wxPanel(parent, id), observer_(observer), active_item_(-1), key_sink_(NULL) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); title_st_ = new wxStaticText(this, -1, wxEmptyString); top_sizer->Add(title_st_, wxSizerFlags().Center()); grid_sizer_ = new wxFlexGridSizer(3, 0, 0); grid_sizer_->AddGrowableCol(1); grid_sizer_->AddGrowableCol(2); top_sizer->Add(grid_sizer_, wxSizerFlags(1).Expand()); //SetSizerAndFit(top_sizer); SetSizer(top_sizer); SetAutoLayout(true); } wxString ParameterPanel::get_label2(int n) const { return rows_[n].text->GetToolTip()->GetTip(); } void ParameterPanel::change_value(ValueChangingWidget *w, double factor) { int n = 0; for ( ; n != get_count(); ++n) if (rows_[n].arm == w) break; assert(n != get_count()); double term = fabs(values_[n]) * factor; if (term == 0) return; if (active_item_ != n) { active_item_ = n; old_value_ = values_[n]; } values_[n] += term; rows_[n].text->SetValue(double2wxstr(values_[n])); observer_->on_parameter_changing(values_); } void ParameterPanel::finalize_changes() { if (active_item_ == -1) return; assert(active_item_ < get_count()); observer_->on_parameter_changed(active_item_); active_item_ = -1; } void ParameterPanel::change_parameter_value(int idx, double value) { if (idx < get_count()) set_value(idx, value); } double ParameterPanel::get_value(int n) const { //double d; //bool ok = rows_[n].text->GetValue().ToDouble(&d); //return ok ? d : 0.; return values_[n]; } void ParameterPanel::set_value(int n, double value) { values_[n] = value; rows_[n].text->ChangeValue(double2wxstr(value)); } void ParameterPanel::set_normal_parameter(int n, const wxString& label, double value, bool locked, const wxString& label2) { change_mode(n, true); set_value(n, value); rows_[n].label->SetLabel(label); rows_[n].text->SetToolTip(label2); rows_[n].lock->set_state(locked ? 0 : 1); rows_[n].text->SetEditable(!locked); rows_[n].arm->Enable(!locked); } void ParameterPanel::set_disabled_parameter(int n, const wxString& label, double value, const wxString& label2) { change_mode(n, false); set_value(n, value); rows_[n].label->SetLabel(label); rows_[n].text->SetToolTip(label2); rows_[n].lock->set_state(2); rows_[n].label2->SetLabel(label2); } void ParameterPanel::change_mode(int n, bool normal) { assert (n <= get_count()); if (n == get_count()) append_row(); ParameterRowData& row = rows_[n]; if (row.text->IsEnabled() == normal) return; row.text->Enable(normal); row.arm->Show(normal); row.label2->Show(!normal); } void ParameterPanel::append_row() { #if 1 // Deleting/destroying controls causes strange problems in wx2.9. // To avoid it, we hide controls rather than delete it. if (rows_.size() > values_.size()) { ParameterRowData& row = rows_[values_.size()]; row.label->Show(true); row.text->Show(true); row.lock->Show(true); row.arm->Show(true); values_.push_back(0.); return; } #endif ParameterRowData data; data.label = new wxStaticText(this, -1, wxEmptyString); // KFTextCtrl is a wxTextCtrl which sends wxEVT_COMMAND_TEXT_ENTER // when un-focused. #ifdef __WXMSW__ int text_width = 60; #else int text_width = 80; #endif data.text = new KFTextCtrl(this, -1, wxEmptyString, text_width); data.rsizer = new wxBoxSizer(wxHORIZONTAL); LockButton::initialize_bitmaps(); data.lock = new LockButton(this, false); data.arm = new ValueChangingWidget(this, -1, this); data.label2 = new wxStaticText(this, -1, wxEmptyString); data.rsizer->Add(data.lock, wxSizerFlags().Center().Left()); data.rsizer->Add(data.label2, wxSizerFlags().Center().Left()); data.rsizer->Add(data.arm, wxSizerFlags(1).Center()); grid_sizer_->Add(data.label, wxSizerFlags().Center() #ifdef __WXMSW__ .Border(wxLEFT, 2) #endif ); grid_sizer_->Add(data.text, wxSizerFlags().Expand().Center() .Border(wxLEFT|wxTOP|wxBOTTOM, 2)); grid_sizer_->Add(data.rsizer, wxSizerFlags().Expand().Center()); data.label2->Show(false); data.text->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(ParameterPanel::OnTextEnter), NULL, this); data.text->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(ParameterPanel::OnMouseWheel), NULL, this); data.arm->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(ParameterPanel::OnMouseWheel), NULL, this); data.lock->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(ParameterPanel::OnLockButton), NULL, this); rows_.push_back(data); values_.push_back(0.); if (key_sink_ != NULL) { data.lock->Connect(wxEVT_KEY_DOWN, key_sink_method_, NULL, key_sink_); data.arm->Connect(wxEVT_KEY_DOWN, key_sink_method_, NULL, key_sink_); } } void ParameterPanel::set_key_sink(wxEvtHandler* sink, wxObjectEventFunction method) { key_sink_ = sink; key_sink_method_ = method; } void ParameterPanel::delete_row_range(int begin, int end) { // Deleting/destroying controls causes strange problems in wx2.9. // To avoid it, we hide controls rather than delete it. #if 0 for (int i = 3*end - 1; i >= 3*begin; --i) grid_sizer_->Detach(i); for (int i = begin; i < end; ++i) { ParameterRowData& row = rows_[i]; row.label->Destroy(); row.text->Destroy(); row.lock->Destroy(); row.arm->Destroy(); row.label2->Destroy(); } rows_.erase(rows_.begin() + begin, rows_.begin() + end); #else for (int i = begin; i < end; ++i) { ParameterRowData& row = rows_[i]; row.label->Show(false); row.text->Show(false); row.lock->Show(false); row.arm->Show(false); row.label2->Show(false); } #ifdef __WXMAC__ Refresh(); #endif #endif values_.erase(values_.begin() + begin, values_.begin() + end); } int ParameterPanel::find_in_rows(wxObject* w) { for (int n = 0; n != get_count(); ++n) if (w == rows_[n].text || w == rows_[n].lock || w == rows_[n].arm) return n; assert(0); return 0; } void ParameterPanel::OnLockButton(wxCommandEvent& event) { int n = find_in_rows(event.GetEventObject()); int old_state = rows_[n].lock->state(); if (old_state != 2) { rows_[n].lock->set_state(old_state == 0 ? 1 : 0); bool locked = (old_state != 0); rows_[n].text->SetEditable(!locked); rows_[n].arm->Enable(!locked); } observer_->on_parameter_lock_clicked(n, old_state); } void ParameterPanel::OnTextEnter(wxCommandEvent &event) { int n = find_in_rows(event.GetEventObject()); wxTextCtrl *tc = rows_[n].text; if (tc->GetValue() == double2wxstr(values_[n])) return; double t; bool ok = tc->GetValue().ToDouble(&t); if (ok) { values_[n] = t; observer_->on_parameter_changed(n); } else tc->ChangeValue(double2wxstr(values_[n])); } void ParameterPanel::OnMouseWheel(wxMouseEvent &event) { double change = 1e-5 * event.GetWheelRotation(); if (event.ShiftDown()) change *= 10; if (event.CmdDown()) change *= 100; if (event.AltDown()) change /= 20; int n = find_in_rows(event.GetEventObject()); double new_value = values_[n] + fabs(values_[n]) * change; set_value(n, new_value); observer_->on_parameter_changed(n); } const char **get_lock_xpm() { return lock_xpm; } const char **get_lock_open_xpm() { return lock_open_xpm; } fityk-1.3.1/wxgui/parpan.h000066400000000000000000000101361302634723100154410ustar00rootroot00000000000000// Purpose: ParameterPanel and LockableRealCtrl (both for input of real numbers) // Copyright 2007-2010 Marcin Wojdyr // Licence: wxWidgets licence #ifndef FITYK_WX_PARPAN_H_ #define FITYK_WX_PARPAN_H_ #include #include #include "fityk/fityk.h" // realt #include "drag.h" // DraggedFuncObserver class SideBar; class ValueChangingWidget; class ValueChangingWidgetObserver { public: virtual ~ValueChangingWidgetObserver() {} virtual void change_value(ValueChangingWidget *w, double factor) = 0; virtual void finalize_changes() = 0; }; class LockButton; // LockableRealCtrl - input widget (text + lock-button) for real values // that can be marked as locked (constant). class LockableRealCtrl : public wxPanel { public: LockableRealCtrl(wxWindow* parent, bool percent=false); bool is_locked() const; void set_lock(bool locked); bool is_null() const { return text->IsEmpty(); } bool is_nonzero() const; // non-zero value or not locked double get_value() const; wxString get_string() const { return text->GetValue(); } void set_string(wxString const& s) { text->ChangeValue(s); } void set_value(double value); void Clear() { text->ChangeValue(wxT("")); } wxTextCtrl* get_text_ctrl() const { return text; } private: wxTextCtrl *text; LockButton *lock; }; class ParameterPanelObserver { public: virtual ~ParameterPanelObserver() {} virtual void on_parameter_changing(const std::vector& values) = 0; virtual void on_parameter_changed(int n) = 0; virtual void on_parameter_lock_clicked(int n, int state) = 0; }; struct ParameterRowData { wxTextCtrl *text; wxBoxSizer *rsizer; LockButton* lock; ValueChangingWidget *arm; wxStaticText *label, *label2; }; /// A list of input widgets, each row contains label, text, lock-button and /// slider. In alternative "disabled" mode a row contains label, disabled text /// and a second label in place of the lock-button and slider. /// The text control is meant for input of real number, /// the lock button is for marking the number as constant (locked), /// the slider is (ab)used as a handle for changing smoothly the number. /// There is a title (a text label) at the top. class ParameterPanel : public wxPanel, public ValueChangingWidgetObserver, public DraggedFuncObserver { public: ParameterPanel(wxWindow* parent, wxWindowID id, ParameterPanelObserver *observer); void set_normal_parameter(int n, const wxString& label, double value, bool locked, const wxString& label2); void set_disabled_parameter(int n, const wxString& label, double value, const wxString& label2); void delete_row_range(int begin, int end); wxString get_label2(int n) const; double get_value(int n) const; void set_value(int n, double value); int get_count() const { return values_.size(); } const std::vector& values() const { return values_; } wxString get_title() const { return title_st_->GetLabel(); } void set_title(const wxString& title) { title_st_->SetLabel(title); } void set_key_sink(wxEvtHandler* sink, wxObjectEventFunction method); // implementation of ValueChangingWidgetObserver virtual void change_value(ValueChangingWidget *w, double factor); virtual void finalize_changes(); // implementation of DraggedFuncObserver virtual void change_parameter_value(int idx, double value); private: ParameterPanelObserver* observer_; std::vector rows_; std::vector values_; wxStaticText* title_st_; wxFlexGridSizer *grid_sizer_; int active_item_; double old_value_; wxEvtHandler* key_sink_; wxObjectEventFunction key_sink_method_; void change_mode(int n, bool normal); void append_row(); int find_in_rows(wxObject* w); void OnLockButton(wxCommandEvent& event); void OnTextEnter(wxCommandEvent &event); void OnMouseWheel(wxMouseEvent &event); }; // access to xpm bitmaps const char **get_lock_xpm(); const char **get_lock_open_xpm(); #endif fityk-1.3.1/wxgui/plot.cpp000066400000000000000000000452601302634723100154770ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// FPlot, the base class for MainPlot and AuxPlot #include #include #include #include "plot.h" #include "cmn.h" #include "frame.h" //ftk #include "fityk/data.h" #include "fityk/logic.h" using namespace std; using fityk::Rect; using fityk::Model; void Scale::set(double m, double M, int pixels) { double h = 0; if (logarithm) { M = log(max(M, fityk::epsilon)); m = log(max(m, fityk::epsilon)); } h = M - m; origin = reversed ? M : m; if (h == 0) h = 0.1; scale = pixels / (reversed ? -h : h); // small (subpixel) shift that aligns axis with pixel grid if (!logarithm) origin = round(origin * scale) / scale; } double Scale::valr(int px) const { if (logarithm) { double val = exp(px / scale + origin); double delta = fabs(val - exp((px-1) / scale + origin)); double t = pow(10, floor(log10(delta))); return floor(val / t + 0.5) * t; } else { double val = px / scale + origin; double delta = fabs(0.5 / scale); double t = pow(10, floor(log10(delta))); return floor(val / t + 0.5) * t; } } void Overlay::bg_color_updated(const wxColor& bg) { if (0.299*bg.Red() + 0.587*bg.Green() + 0.114*bg.Blue() < 128) color_.Set(192, 192, 192); else color_.Set(64, 64, 64); } void Overlay::draw_overlay() { if (mode_ == kFunction) // function is drawn by calling draw_lines() return; if (!panel_->get_bitmap().IsOk()) return; wxClientDC dc(panel_) ; panel_->blit(dc); dc.SetPen(wxPen(color_, 1, wxPENSTYLE_SHORT_DASH)); dc.SetBrush(*wxTRANSPARENT_BRUSH); switch (mode_) { case kRect: if (x1_ != x2_ || y1_ != y2_) { int width = abs(x1_ - x2_); int height = abs(y1_ - y2_); dc.DrawRectangle(min(x1_, x2_), min(y1_, y2_), width, height); } break; case kLinearDraft: { int width = dc.GetSize().GetWidth(); int height = dc.GetSize().GetHeight(); int dy = y2_ - y1_; int dx = x2_ - x1_; if (abs(dy) < abs(dx)) { double m = (double) dy / dx; dc.DrawLine(0, y1_ - m * x1_, width, y1_ + m * (width - x1_)); } else { double im = (double) dx / dy; dc.DrawLine(x1_ - y1_ * im, 0, x1_ + (height - y1_) * im, height); } break; } case kPeakDraft: { int ctr = x1_; int hwhm = abs(x1_ - x2_); int ymid = (y2_ + y1_) / 2; dc.DrawLine(ctr, y1_, ctr, y2_); // vertical line dc.DrawLine(ctr - hwhm, ymid, ctr + hwhm, ymid); // horizontal dc.DrawLine(ctr, y2_, ctr - 2 * hwhm, y1_); // left slope dc.DrawLine(ctr, y2_, ctr + 2 * hwhm, y1_); // right slope break; } case kSigmoidDraft: { int dy = y2_ - y1_; int dx = abs(x2_ - x1_); int dc_width = dc.GetSize().GetWidth(); dc.DrawLine(0, y1_ - dy, x1_ - dx, y1_ - dy); dc.DrawLine(x1_ - dx, y1_ - dy, x1_ + dx, y1_ + dy); dc.DrawLine(x1_ + dx, y1_ + dy, dc_width, y1_ + dy); break; } case kCrossHair: dc.CrossHair(x2_, y2_); break; case kVLine: dc.DrawLine(x2_, 0, x2_, dc.GetSize().GetHeight()); break; case kHLine: dc.DrawLine(0, y2_, dc.GetSize().GetWidth(), y2_); break; case kVRange: dc.DrawLine(x1_, 0, x1_, dc.GetSize().GetHeight()); dc.DrawLine(x2_, 0, x2_, dc.GetSize().GetHeight()); break; case kHRange: dc.DrawLine(0, y1_, dc.GetSize().GetWidth(), y1_); dc.DrawLine(0, y2_, dc.GetSize().GetWidth(), y2_); break; case kFunction: assert(0); break; case kNone: break; } } void Overlay::draw_lines(int n, wxPoint points[]) { if (!panel_->get_bitmap().IsOk()) return; wxClientDC dc(panel_) ; panel_->blit(dc); if (n <= 0) return; dc.SetPen(wxPen(color_, 1, wxPENSTYLE_SHORT_DASH)); dc.DrawLines(n, points); } //=============================================================== // FPlot (plot with data and fitted curves) //=============================================================== FPlot::FPlot(wxWindow *parent) : BufferedPanel(parent), overlay(this), pen_width(1), draw_sigma(false), downX(INT_MIN), downY(INT_MIN), esc_source_(NULL) { } FPlot::~FPlot() { } void FPlot::set_font(wxDC &dc, wxFont const& font) { if (pen_width > 1) { wxFont f = font; f.SetPointSize(f.GetPointSize() * pen_width); dc.SetFont(f); } else dc.SetFont(font); } static void draw_line_with_style(wxDC& dc, wxPenStyle style, wxCoord X1, wxCoord Y1, wxCoord X2, wxCoord Y2) { wxPen pen = dc.GetPen(); wxPenStyle old_style = pen.GetStyle(); pen.SetStyle(style); dc.SetPen(pen); dc.DrawLine (X1, Y1, X2, Y2); pen.SetStyle(old_style); dc.SetPen(pen); } void FPlot::draw_vertical_lines_on_overlay(int X1, int X2) { wxPoint pp[4] = { wxPoint(X1, 0), wxPoint(X1, GetClientSize().GetHeight() + 1), wxPoint(X2, GetClientSize().GetHeight() + 1), wxPoint(X2, 0) }; if (X1 < 0) overlay.draw_lines(0, pp); else if (X2 < 0) overlay.draw_lines(2, pp); else overlay.draw_lines(4, pp); } void FPlot::set_bg_color(wxColour const& c) { BufferedPanel::set_bg_color(c); overlay.bg_color_updated(c); } /// draw x axis tics void FPlot::draw_xtics (wxDC& dc, Rect const &v, bool set_pen) { if (set_pen) { dc.SetPen(wxPen(xAxisCol, pen_width)); dc.SetTextForeground(xAxisCol); } set_font(dc, ticsFont); // get tics text height wxCoord h; dc.GetTextExtent(wxT("1234567890"), 0, &h); vector minors; vector x_tics = scale_tics_step(v.left(), v.right(), x_max_tics, minors, xs.logarithm); //if x axis is visible tics are drawed at the axis, //otherwise tics are drawed at the bottom edge of the plot const int pixel_height = get_pixel_height(dc); int Y = pixel_height - h; if (x_axis_visible && !ys.logarithm && ys.px(0) >= 0 && ys.px(0) < Y) Y = ys.px(0); for (vector::const_iterator i = x_tics.begin(); i != x_tics.end(); ++i) { int X = xs.px(*i); dc.DrawLine (X, Y, X, Y - x_tic_size); wxString label = format_label(*i, v.right() - v.left()); wxCoord w; dc.GetTextExtent (label, &w, 0); dc.DrawText (label, X - w/2, Y + 1); if (x_grid) { wxPen pen = dc.GetPen(); pen.SetStyle(wxPENSTYLE_DOT); wxDCPenChanger pen_changer(dc, pen); dc.DrawLine(X, 0, X, Y); dc.DrawLine(X, Y+1+h, X, pixel_height); /* draw_line_with_style(dc, wxPENSTYLE_DOT, X, 0, X, Y); draw_line_with_style(dc, wxPENSTYLE_DOT, X, Y+1+h, X, pixel_height); */ } } //draw minor tics if (xminor_tics_visible) for (vector::const_iterator i = minors.begin(); i != minors.end(); ++i) { int X = xs.px(*i); dc.DrawLine (X, Y, X, Y - x_tic_size); } } /// draw y axis tics void FPlot::draw_ytics (wxDC& dc, Rect const &v, bool set_pen) { if (set_pen) { dc.SetPen(wxPen(xAxisCol, pen_width)); dc.SetTextForeground(xAxisCol); } set_font(dc, ticsFont); const int pixel_width = get_pixel_width(dc); //if y axis is visible, tics are drawed at the axis, //otherwise tics are drawed at the left hand edge of the plot int X = 0; if (y_axis_visible && xs.px(0) > 0 && xs.px(0) < pixel_width - 10) X = xs.px(0); vector minors; vector y_tics = scale_tics_step(v.bottom(), v.top(), y_max_tics, minors, ys.logarithm); for (vector::const_iterator i = y_tics.begin(); i != y_tics.end(); ++i) { int Y = ys.px(*i); dc.DrawLine (X, Y, X + y_tic_size, Y); wxString label = format_label(*i, v.top() - v.bottom()); if (x_axis_visible && label == wxT("0")) continue; wxCoord w, h; dc.GetTextExtent (label, &w, &h); dc.DrawText (label, X + y_tic_size + 1, Y - h/2); if (y_grid) { draw_line_with_style(dc, wxPENSTYLE_DOT, 0,Y, X,Y); draw_line_with_style(dc, wxPENSTYLE_DOT, X+y_tic_size+1+w+1, Y, pixel_width, Y); } } //draw minor tics if (yminor_tics_visible) for (vector::const_iterator i = minors.begin(); i != minors.end(); ++i) { int Y = ys.px(*i); dc.DrawLine (X, Y, X + y_tic_size, Y); } } double FPlot::get_max_abs_y (double (*compute_y)(vector::const_iterator, Model const*), vector::const_iterator first, vector::const_iterator last, Model const* model) { double max_abs_y = 0; for (vector::const_iterator i = first; i < last; ++i) { if (i->is_active) { double y = fabs(((*compute_y)(i, model))); if (y > max_abs_y) max_abs_y = y; } } return max_abs_y; } static void stroke_lines(wxDC& dc, wxGraphicsContext *gc, int n, wxPoint2DDouble *pp) { if (n < 2) return; if (gc) { gc->StrokeLines(n, pp); } else { wxPoint *points = new wxPoint[n]; for (int i = 0; i < n; ++i) { points[i].x = iround(pp[i].m_x); points[i].y = iround(pp[i].m_y); } dc.DrawLines(n, points); delete [] points; } } void FPlot::draw_data_by_activity(wxDC& dc, wxPoint2DDouble *pp, const vector& aa, bool state) { int len = aa.size(); int count_state = count(aa.begin(), aa.end(), state); if (count_state == 0) return; wxGCDC* gdc = wxDynamicCast(&dc, wxGCDC); wxGraphicsContext *gc = gdc ? gdc->GetGraphicsContext() : NULL; if (line_between_points) { int start = (aa[0] == state ? 0 : -1); for (int i = 1; i != len; ++i) { if (aa[i] == state && start == -1) start = i; else if (aa[i] != state && start != -1) { wxPoint2DDouble start_bak = pp[start]; wxPoint2DDouble i_bak = pp[i]; if (start > 0) { // draw half of the line between points start-1 and start --start; start_bak = pp[start]; pp[start] = (pp[start] + pp[start+1]) / 2; } // draw half of the line between points i-1 and i pp[i] = (pp[i-1] + pp[i]) / 2; stroke_lines(dc, gc, i - start + 1, pp + start); pp[i] = i_bak; pp[start] = start_bak; start = -1; } } if (start != -1) { wxPoint2DDouble start_bak = pp[start]; if (start > 0) { // draw half of the line between points start-1 and start --start; start_bak = pp[start]; pp[start] = (pp[start] + pp[start+1]) / 2; } stroke_lines(dc, gc, len - start, pp + start); pp[start] = start_bak; } } if (point_radius > 1) { int r = (point_radius - 1) * pen_width; if (gc) { for (int i = 0; i != len; ++i) if (aa[i] == state) gc->DrawEllipse(pp[i].m_x - r/2., pp[i].m_y - r/2., r, r); } else for (int i = 0; i != len; ++i) if (aa[i] == state) dc.DrawEllipse(pp[i].m_x - r/2, pp[i].m_y - r/2, r, r); } else if (!line_between_points) { // if we are here, point_radius == 1 if (gc) { wxGraphicsPath path = gc->CreatePath(); for (int i = 0; i != len; ++i) if (aa[i] == state) { double rx = iround(pp[i].m_x); double ry = iround(pp[i].m_y); path.MoveToPoint(rx, ry - 0.1); path.AddLineToPoint(rx, ry + 0.1); } gc->SetAntialiasMode(wxANTIALIAS_NONE); gc->StrokePath(path); gc->SetAntialiasMode(wxANTIALIAS_DEFAULT); } else for (int i = 0; i != len; ++i) if (aa[i] == state) dc.DrawPoint(iround(pp[i].m_x), iround(pp[i].m_y)); } } void FPlot::draw_data (wxDC& dc, double (*compute_y)(vector::const_iterator, Model const*), fityk::Data const* data, Model const* model, wxColour const& color, wxColour const& inactive_color, int Y_offset, bool cumulative) { if (data->is_empty()) return; vector::const_iterator first = data->get_point_at(ftk->view.left()), last = data->get_point_at(ftk->view.right()); if (first > data->points().begin()) --first; if (last < data->points().end()) ++last; // prepare coordinates int len = last - first; if (len <= 0) return; wxPoint2DDouble *pp = new wxPoint2DDouble[len]; vector aa(len); vector yy(len); Y_offset *= (get_pixel_height(dc) / 100); for (int i = 0; i != len; ++i) { const Point& p = *(first + i); pp[i].m_x = xs.px_d(p.x); yy[i] = (*compute_y)((first+i), model); if (cumulative && i > 0) yy[i] += yy[i-1]; pp[i].m_y = ys.px_d(yy[i]) - Y_offset; aa[i] = p.is_active; } // draw inactive wxColour icol = inactive_color.Ok() ? inactive_color : inactiveDataCol; dc.SetPen(wxPen(icol, pen_width)); dc.SetBrush(wxBrush(icol, wxBRUSHSTYLE_SOLID)); draw_data_by_activity(dc, pp, aa, false); if (draw_sigma) for (int i = 0; i != len; ++i) if (!aa[i]) { double sigma = (first + i)->sigma; dc.DrawLine(iround(pp[i].m_x), ys.px(yy[i] - sigma) - Y_offset, iround(pp[i].m_x), ys.px(yy[i] + sigma) - Y_offset); } // draw active wxColour acol = color.Ok() ? color : activeDataCol; dc.SetPen(wxPen(acol, pen_width)); dc.SetBrush(wxBrush(acol, wxBRUSHSTYLE_SOLID)); draw_data_by_activity(dc, pp, aa, true); if (draw_sigma) for (int i = 0; i != len; ++i) if (aa[i]) { double sigma = (first + i)->sigma; dc.DrawLine(iround(pp[i].m_x), ys.px(yy[i] - sigma) - Y_offset, iround(pp[i].m_x), ys.px(yy[i] + sigma) - Y_offset); } delete [] pp; } void FPlot::set_scale(int pixel_width, int pixel_height) { Rect const &v = ftk->view; if (pixel_width > 0) xs.set(v.left(), v.right(), pixel_width); if (pixel_height > 0) ys.set(v.top(), v.bottom(), pixel_height); } int FPlot::get_special_point_at_pointer(wxMouseEvent& event) { // searching the closest peak-top and distance from it, d = dx + dy < 10 int nearest = -1; int min_dist = 10; for (vector::const_iterator i = special_points.begin(); i != special_points.end(); ++i) { int d = abs(event.GetX() - i->x) + abs(event.GetY() - i->y); if (d < min_dist) { min_dist = d; nearest = i - special_points.begin(); } } return nearest; } void FPlot::read_settings(wxConfigBase *cf) { cf->SetPath(wxT("Visible")); x_axis_visible = cfg_read_bool (cf, wxT("xAxis"), true); y_axis_visible = cfg_read_bool (cf, wxT("yAxis"), false); xtics_visible = cfg_read_bool (cf, wxT("xtics"), true); ytics_visible = cfg_read_bool (cf, wxT("ytics"), true); xminor_tics_visible = cfg_read_bool (cf, wxT("xMinorTics"), true); yminor_tics_visible = cfg_read_bool (cf, wxT("yMinorTics"), false); x_grid = cfg_read_bool (cf, wxT("xgrid"), false); y_grid = cfg_read_bool (cf, wxT("ygrid"), false); cf->SetPath(wxT("../Colors")); xAxisCol = cfg_read_color(cf, wxT("xAxis"), wxColour(wxT("WHITE"))); cf->SetPath(wxT("..")); ticsFont = cfg_read_font(cf, wxT("ticsFont"), wxFont( #ifdef __WXMAC__ 10, #else 8, #endif wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); } void FPlot::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("Visible")); cf->Write (wxT("xAxis"), x_axis_visible); cf->Write (wxT("yAxis"), y_axis_visible); cf->Write (wxT("xtics"), xtics_visible); cf->Write (wxT("ytics"), ytics_visible); cf->Write (wxT("xMinorTics"), xminor_tics_visible); cf->Write (wxT("yMinorTics"), yminor_tics_visible); cf->Write (wxT("xgrid"), x_grid); cf->Write (wxT("ygrid"), y_grid); cf->SetPath(wxT("../Colors")); cfg_write_color (cf, wxT("xAxis"), xAxisCol); cf->SetPath(wxT("..")); cfg_write_font (cf, wxT("ticsFont"), ticsFont); } void FPlot::OnKeyDown(wxKeyEvent& event) { if (event.GetKeyCode() == WXK_ESCAPE) cancel_action(); else event.Skip(); } void FPlot::connect_esc_to_cancel(bool connect) { if (esc_source_ != NULL) { esc_source_->Disconnect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(FPlot::OnKeyDown), 0, this); esc_source_ = NULL; } if (connect) { wxWindow *fw = wxWindow::FindFocus(); if (fw == NULL || fw == this) return; esc_source_ = fw; fw->Connect(wxID_ANY, wxEVT_KEY_DOWN, wxKeyEventHandler(FPlot::OnKeyDown), 0, this); } } fityk-1.3.1/wxgui/plot.h000066400000000000000000000143221302634723100151370ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_PLOT_H_ #define FITYK_WX_PLOT_H_ #include #include #include #include "fityk/fityk.h" // Point #include "fityk/common.h" // iround() #include "uplot.h" // BufferedPanel #include "cmn.h" // compatibility with wx2.8 (defined wxPenStyle, etc.) // convention: lowercase coordinates of point are real values, // and uppercase ones are coordinates of point on screen (integers). // INT_MIN, given as coordinate, is invalid value, means "cancel drawing" namespace fityk { class Model; class Data; struct Rect; } using fityk::Point; class wxPoint2DDouble; inline int get_pixel_width(wxDC const& dc) { int w; dc.GetClippingBox(NULL, NULL, &w, NULL); //if (w != 0) printf("Clipping On (width)\n"); return w != 0 ? w : dc.GetSize().GetWidth(); } inline int get_pixel_height(wxDC const& dc) { int h; dc.GetClippingBox(NULL, NULL, NULL, &h); //if (h != 0) printf("Clipping On (height)\n"); return h != 0 ? h : dc.GetSize().GetHeight(); } /// convertion between pixels and logical values class Scale { public: double scale, origin; bool logarithm, reversed; Scale() : scale(1.), origin(0.), logarithm(false), reversed(false) {} /// value -> pixel int px(double val) const { return iround(px_d(val)); } inline double px_d(double val) const; /// pixel -> value inline double val(int px) const; // Returns the same value as val(), but rounded in a smart way, // so when the number is formatted with "%.12g", it is not too long. double valr(int px) const; // set scale using minimum and maximum logical values and width/height // of the screen in pixels. // In case of y scale, where pixel=0 is at the top, m and M are switched void set(double m, double M, int pixels); private: static int inf_px(double t) { return t > 0 ? SHRT_MAX : SHRT_MIN; } }; double Scale::px_d(double val) const { if (logarithm) { if (val <= 0) return inf_px(-scale); val = log(val); } double t = (val - origin) * scale; return fabs(t) < SHRT_MAX ? t : (double) inf_px(t); } double Scale::val(int px) const { double a = px / scale + origin; return logarithm ? exp(a) : a; } class Overlay { public: enum Mode { kNone, kRect, kLinearDraft, kPeakDraft, kSigmoidDraft, kFunction, kCrossHair, kVLine, kHLine, kVRange, kHRange }; Overlay(BufferedPanel *panel) : panel_(panel), mode_(kNone), color_(192,192,192) {} void start_mode(Mode m, int x1, int y1) { mode_=m; x1_=x2_=x1; y1_=y2_=y1; } void switch_mode(Mode m) { mode_=m; } void change_pos(int x2,int y2) { x2_=x2; y2_=y2; if (mode_!=kNone) draw_overlay(); } void draw_overlay(); void draw_lines(int n, wxPoint points[]); Mode mode() const { return mode_; } void bg_color_updated(const wxColour& bg); private: BufferedPanel *panel_; Mode mode_; wxColour color_; int x1_, x2_, y1_, y2_; }; /// This class has no instances, MainPlot and AuxPlot are derived from it /// It knows how to draw on wxDC. Note that wxDC:SetClippingRegion() should be /// used together with wxDC::SetDeviceOrigin(). Clipping box is used only in /// get_pixel_width() and get_pixel_height() functions. /// When plotting a curve, values in each x from 0 to get_pixel_width() is /// calculated. class FPlot : public BufferedPanel { public: FPlot(wxWindow *parent); virtual ~FPlot(); void set_font(wxDC &dc, wxFont const& font); void set_scale(int pixel_width, int pixel_height); int get_special_point_at_pointer(wxMouseEvent& event); Scale const& get_x_scale() const { return xs; } Scale const& get_y_scale() const { return ys; } virtual void save_settings(wxConfigBase *cf) const; virtual void read_settings(wxConfigBase *cf); void set_magnification(int m) { pen_width = m > 0 ? m : 1; } void draw_vertical_lines_on_overlay(int X1, int X2); virtual void set_bg_color(wxColour const& c); protected: Scale xs, ys; Overlay overlay; // properties stored in config int pen_width; wxColour activeDataCol, inactiveDataCol, xAxisCol; wxFont ticsFont; int point_radius; bool line_between_points; bool draw_sigma; bool x_axis_visible, y_axis_visible, xtics_visible, ytics_visible, xminor_tics_visible, yminor_tics_visible; bool x_grid, y_grid; int x_max_tics, y_max_tics, x_tic_size, y_tic_size; int downX, downY; std::vector special_points; //used to mark positions of peak tops wxWindow *esc_source_; // temporary source of OnKeyDown() events void draw_xtics (wxDC& dc, fityk::Rect const& v, bool set_pen=true); void draw_ytics (wxDC& dc, fityk::Rect const &v, bool set_pen=true); double get_max_abs_y(double (*compute_y)(std::vector::const_iterator, fityk::Model const*), std::vector::const_iterator first, std::vector::const_iterator last, fityk::Model const* model); void draw_data (wxDC& dc, double (*compute_y)(std::vector::const_iterator, fityk::Model const*), fityk::Data const* data, fityk::Model const* model, wxColour const& color = wxNullColour, wxColour const& inactive_color = wxNullColour, int Y_offset = 0, bool cumulative=false); // if connect is true: connect, otherwise disconnect; // connect to the currently focused window and handle wxEVT_KEY_DOWN // event: if Esc is pressed call cancel_action(). void connect_esc_to_cancel(bool connect); virtual void cancel_action() {} // handler used by connect_esc_to_cancel() void OnKeyDown(wxKeyEvent& event); private: void draw_data_by_activity(wxDC& dc, wxPoint2DDouble *pp, const std::vector& aa, bool state); }; #endif fityk-1.3.1/wxgui/plotpane.cpp000066400000000000000000000122231302634723100163340ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include "plotpane.h" #include "plot.h" #include "mplot.h" #include "aplot.h" #include "frame.h" // exec() using namespace std; void ZoomHistory::push(const string& s) { if (pos_ + 1 < items_.size()) items_.erase(items_.begin() + pos_ + 1, items_.end()); items_.push_back(s); ++pos_; if (pos_ > 50) { items_.erase(items_.begin(), items_.begin() + 10); pos_ -= 10; } } void ZoomHistory::set_pos(size_t p) { size_t old_pos = pos_; pos_ = std::min(p, items_.size() - 1); if (pos_ != old_pos) exec("plot " + items_[pos_]); } PlotPane::PlotPane(wxWindow *parent, wxWindowID id) : ProportionalSplitter(parent, id) { plot_ = new MainPlot(this); aux_split_ = new ProportionalSplitter(this, -1, 0.5); SplitHorizProp(plot_, aux_split_); aux_plot_[0] = new AuxPlot(aux_split_, plot_, wxT("0")); aux_plot_[1] = new AuxPlot(aux_split_, plot_, wxT("1")); aux_plot_[1]->Show(false); aux_split_->Initialize(aux_plot_[0]); } void PlotPane::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("/PlotPane")); cf->Write(wxT("PlotPaneProportion"), GetProportion()); cf->Write(wxT("AuxPlotsProportion"), aux_split_->GetProportion()); cf->Write(wxT("ShowAuxPane0"), aux_visible(0)); cf->Write(wxT("ShowAuxPane1"), aux_visible(1)); plot_->save_settings(cf); for (int i = 0; i < 2; ++i) aux_plot_[i]->save_settings(cf); } void PlotPane::read_settings(wxConfigBase *cf) { cf->SetPath(wxT("/PlotPane")); SetProportion(cfg_read_double(cf, wxT("PlotPaneProportion"), 0.80)); aux_split_->SetProportion( cfg_read_double(cf, wxT("AuxPlotsProportion"), 0.5)); show_aux(0, cfg_read_bool(cf, wxT("ShowAuxPane0"), true)); show_aux(1, cfg_read_bool(cf, wxT("ShowAuxPane1"), false)); plot_->read_settings(cf); for (int i = 0; i < 2; ++i) aux_plot_[i]->read_settings(cf); } void PlotPane::refresh_plots(bool now, WhichPlot which_plot) { if (now) plot_->redraw_now(); else plot_->refresh(); if (which_plot == kAllPlots) { for (int i = 0; i < 2; ++i) if (aux_visible(i)) { if (now) aux_plot_[i]->redraw_now(); else aux_plot_[i]->refresh(); } } } bool PlotPane::aux_visible(int n) const { return IsSplit() && (aux_split_->GetWindow1() == aux_plot_[n] || aux_split_->GetWindow2() == aux_plot_[n]); } void PlotPane::show_aux(int n, bool show) { if (aux_visible(n) == show) return; if (show) { if (!IsSplit()) { //both where invisible SplitHorizProp(plot_, aux_split_); aux_split_->Show(true); assert(!aux_split_->IsSplit()); if (aux_split_->GetWindow1() == aux_plot_[n]) ; else { aux_split_->SplitHorizProp(aux_plot_[0], aux_plot_[1]); aux_plot_[n]->Show(true); aux_split_->Unsplit(aux_plot_[n==0 ? 1 : 0]); } } else {//one was invisible aux_split_->SplitHorizProp(aux_plot_[0], aux_plot_[1]); aux_plot_[n]->Show(true); } } else { //hide if (aux_split_->IsSplit()) //both where visible aux_split_->Unsplit(aux_plot_[n]); else // only one was visible Unsplit(); //hide whole aux_split_ } } void PlotPane::draw_vertical_lines(int X1, int X2, FPlot* skip) { if (plot_ != skip) plot_->draw_vertical_lines_on_overlay(X1, X2); for (int i = 0; i < 2; ++i) if (aux_visible(i) && aux_plot_[i] != skip) aux_plot_[i]->draw_vertical_lines_on_overlay(X1, X2); } wxBitmap PlotPane::prepare_bitmap_for_export(int W, int H, bool include_aux) { // bitmap depth is given explicitely - which is also a workaround for // http://trac.wxwidgets.org/ticket/13328 const int depth = 32; int th = H; int ah[2] = { 0, 0 }; if (include_aux) { int my = get_plot()->get_bitmap().GetSize().y; for (int i = 0; i != 2; ++i) if (aux_visible(i)) { int ay = get_aux_plot(i)->GetClientSize().y; ah[i] = iround(ay * H / my); th += 5 + ah[i]; } } wxBitmap bmp(W, th, depth); wxMemoryDC memory_dc(bmp); MainPlot *plot = get_plot(); MouseModeEnum old_mode = plot->get_mouse_mode(); // We change the mode to avoid drawing peaktops. // In the case of mmd_bg peaktops are not drawn anyway, // and changing the mode would prevent drawing the baseline. if (plot->get_mouse_mode() != mmd_bg) plot->set_mode(mmd_readonly); memory_dc.DrawBitmap(plot->draw_on_bitmap(W, H, depth), 0, 0); plot->set_mode(old_mode); int y = H + 5; for (int i = 0; i != 2; ++i) if (include_aux && aux_visible(i)) { AuxPlot *aplot = get_aux_plot(i); memory_dc.DrawBitmap(aplot->draw_on_bitmap(W, ah[i], depth), 0, y); y += ah[i] + 5; } return bmp; } fityk-1.3.1/wxgui/plotpane.h000066400000000000000000000031011302634723100157740ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_PLOTPANE_H_ #define FITYK_WX_PLOTPANE_H_ #include "cmn.h" //for MouseModeEnum, ProportionalSplitter class MainPlot; class AuxPlot; class FPlot; class ZoomHistory { public: ZoomHistory(const std::string& s) : items_(1, s), pos_(0) {} void push(const std::string& s); void move(int n) { set_pos(n >= -(int)pos_ ? pos_ + n : 0); } void set_pos(size_t p); size_t pos() const { return pos_; } const std::vector& items() const { return items_; } private: std::vector items_; size_t pos_; }; /// A pane containing main and auxiliary plots and a proxy for some /// of the methods of plots. class PlotPane : public ProportionalSplitter { friend class FPrintout; public: PlotPane(wxWindow *parent, wxWindowID id=-1); void save_settings(wxConfigBase *cf) const; void read_settings(wxConfigBase *cf); void refresh_plots(bool now, WhichPlot which_plot); const MainPlot* get_plot() const { return plot_; } MainPlot* get_plot() { return plot_; } AuxPlot* get_aux_plot(int n) const { assert(n>=0 && n<2); return aux_plot_[n]; } void show_aux(int n, bool show); bool aux_visible(int n) const; void draw_vertical_lines(int X1, int X2, FPlot* skip); wxBitmap prepare_bitmap_for_export(int W, int H, bool include_aux); private: MainPlot *plot_; ProportionalSplitter *aux_split_; AuxPlot *aux_plot_[2]; }; #endif // FITYK_WX_PLOTPANE_H_ fityk-1.3.1/wxgui/powdifpat.cpp000066400000000000000000002261301302634723100165130ustar00rootroot00000000000000// Author: Marcin Wojdyr // Licence: GNU General Public License ver. 2+ //TODO: // // deconvolution of instrumental profile // buffer the plot with data // import .cif files #include #include #include #include #include #include #include #include #include #include #include #include #include "fityk/common.h" #include "fityk/func.h" #include "powdifpat.h" #include "sgchooser.h" #include "atomtables.h" #include "cmn.h" #include "uplot.h" // BufferedPanel, scale_tics_step() #include "parpan.h" // LockableRealCtrl #include "ceria.h" #if !STANDALONE_POWDIFPAT #include "frame.h" #include "fityk/logic.h" #include "fityk/data.h" #endif // icons and images #include "img/correction.h" #include "img/info32.h" #include "img/peak32.h" #include "img/radiation32.h" #include "img/rubik32.h" #include "img/run32.h" #include "img/sizes32.h" using namespace std; class PlotWithLines : public PlotWithTics { public: PlotWithLines(wxWindow* parent, PhasePanel *phase_panel, PowderBook *powder_book); virtual void draw(wxDC &dc, bool); private: void draw_active_data(wxDC& dc); PhasePanel *phase_panel_; PowderBook *powder_book_; DISALLOW_COPY_AND_ASSIGN(PlotWithLines); }; class PhasePanel : public wxPanel { friend class PowderBook; public: PhasePanel(wxNotebook *parent, PowderBook *powder_book_); void OnSpaceGroupButton(wxCommandEvent& event); void OnClearButton(wxCommandEvent& event); void OnAddToQLButton(wxCommandEvent& event); void OnNameChanged(wxCommandEvent& event); void OnSpaceGroupChanged(wxCommandEvent&); void OnSpaceGroupChanging(wxCommandEvent&) { powder_book->deselect_phase_quick_list(); } void OnParameterChanging(wxCommandEvent&); void OnParameterChanged(wxCommandEvent&); void OnLineToggled(wxCommandEvent& event); void OnLineSelected(wxCommandEvent& event); void OnAtomsFocus(wxFocusEvent&); void OnAtomsUnfocus(wxFocusEvent&); void OnAtomsChanged(wxCommandEvent& event); void set_phase(string const& name, CelFile const& cel); const Crystal& get_crystal() const { return cr_; } Crystal& get_crystal() { return cr_; } bool editing_atoms() const { return editing_atoms_; } int get_selected_hkl() const { return hkl_list->GetSelection(); } private: static const wxString default_atom_string; PowderBook *powder_book; wxTextCtrl *name_tc, *sg_tc; LockableRealCtrl *par_a, *par_b, *par_c, *par_alpha, *par_beta, *par_gamma; wxButton *save_btn; wxCheckListBox *hkl_list; wxTextCtrl *atoms_tc, *info_tc; wxStaticText *sg_nr_st; bool atoms_show_help_; bool editing_atoms_; PlotWithLines *sample_plot_; // line number with the first syntax error atoms_tc; -1 if correct int line_with_error_; Crystal cr_; void enable_parameter_fields(); void update_disabled_parameters(); void update_miller_indices(bool sg_changed); void set_ortho_angles(); void update_space_group_ui(); DISALLOW_COPY_AND_ASSIGN(PhasePanel); }; namespace { LockableRealCtrl *addMaybeRealCtrl(wxWindow *parent, wxString const& label, wxSizer *sizer, wxSizerFlags const& flags, bool locked=true) { wxStaticText *st = new wxStaticText(parent, -1, label); LockableRealCtrl *ctrl = new LockableRealCtrl(parent); ctrl->set_lock(locked); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->Add(st, 0, wxALIGN_CENTER_VERTICAL); hsizer->Add(ctrl, 0); sizer->Add(hsizer, flags); return ctrl; } } // anonymous namespace #ifndef wxTBK_BUTTONBAR // for wx < 2.9 #define wxTBK_BUTTONBAR wxBK_BUTTONBAR #endif vector PowderBook::phase_desc; int PowderBook::xaxis_sel = 0; PowderBook::PowderBook(wxWindow* parent, wxWindowID id) : wxToolbook(parent, id, wxDefaultPosition, wxDefaultSize, #ifdef __WXOSX_CARBON__ wxTBK_BUTTONBAR #else wxBK_LEFT #endif ), x_min(10), x_max(150), y_max(1000), data(NULL) { #if !STANDALONE_POWDIFPAT int data_nr = frame->get_focused_data_index(); if (data_nr >= 0) { data = ftk->dk.data(data_nr); x_min = data->get_x_min(); x_max = data->get_x_max(); y_max = 0; v_foreach(fityk::Point, p, data->points()) if (p->is_active && p->y > y_max) y_max = p->y; } #endif initialize_quick_phase_list(); wxImageList *image_list = new wxImageList(32, 32); image_list->Add(GET_BMP(info32)); image_list->Add(GET_BMP(radiation32)); image_list->Add(GET_BMP(rubik32)); image_list->Add(GET_BMP(peak32)); image_list->Add(GET_BMP(run32)); image_list->Add(GET_BMP(sizes32)); AssignImageList(image_list); AddPage(PrepareIntroPanel(), wxT("intro"), false, 0); AddPage(PrepareInstrumentPanel(), wxT("instrument"), false, 1); AddPage(PrepareSamplePanel(), wxT("sample"), false, 2); AddPage(PreparePeakPanel(), wxT("peak"), false, 3); AddPage(PrepareActionPanel(), wxT("action"), false, 4); AddPage(PrepareSizeStrainPanel(), wxT("size-strain"), false, 5); #if !STANDALONE_POWDIFPAT fill_forms(); #endif wxColour c = GetToolBar()->GetBackgroundColour(); GetToolBar()->SetBackgroundColour(wxColour(max(0, c.Red() - 50), max(0, c.Green() - 50), c.Blue(), c.Alpha())); Connect(GetId(), wxEVT_COMMAND_TOOLBOOK_PAGE_CHANGED, (wxObjectEventFunction) &PowderBook::OnPageChanged); } static wxString get_cel_files_dir() { wxString fityk_dir = wxStandardPaths::Get().GetUserDataDir(); #if STANDALONE_POWDIFPAT fityk_dir.Replace(wxT("powdifpat"), wxT("fityk")); #endif wxString cel_dir = fityk_dir + wxFILE_SEP_PATH + wxT("cel_files") + wxFILE_SEP_PATH; return cel_dir; } void PowderBook::initialize_quick_phase_list() { wxString cel_dir = get_cel_files_dir(); if (!wxDirExists(cel_dir)) { wxMkdir(cel_dir); write_default_cel_files((const char*) cel_dir.mb_str()); } wxDir dir(cel_dir); wxString filename; bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES); while (cont) { FILE *f = wxFopen(cel_dir + filename, wxT("r")); if (f) { CelFile cel = read_cel_file(f); fclose(f); if (cel.sgs != NULL) { wxString name = wxFileName(filename).GetName(); quick_phase_list[wx2s(name)] = cel; } } cont = dir.GetNext(&filename); } } wxPanel* PowderBook::PrepareIntroPanel() { static const char* intro_str = #if STANDALONE_POWDIFPAT "This simple program can generate diffraction pattern using information\n" "about symmetry group, unit cell and radiation wavelength.\n" "At this moment the program is experimental and the old PowderCell\n" "is definitely more reliable.\n" "This is a stand-alone version of a dialog in fityk program.\n"; #else "Before you start:\n" " - load a powder diffraction pattern,\n" " - if you want to analyze only a part of the pattern, deactivate the rest" "\n" " - either remove the background manually\n" " or add a polynomial (or other function) to model it.\n" "\n" "This tool constructs a model for powder diffraction data. " "The model has constrained positions of peaks " "and unconstrained intensities. " "Fitting the model to the data optimizes all parameters at the same time. " "This type of refinement is known as the Pawley method.\n" "\n" "Space group data have been generated using the CCTBX library.\n" "\n" "The size-strain analysis is not implemented yet.\n"; #endif wxPanel *panel = new wxPanel(this); wxSizer *intro_sizer = new wxBoxSizer(wxVERTICAL); wxTextCtrl *intro_tc = new wxTextCtrl(panel, -1, pchar2wx(intro_str), wxDefaultPosition, wxDefaultSize, wxTE_READONLY|wxTE_MULTILINE |wxNO_BORDER); intro_tc->SetBackgroundColour(GetBackgroundColour()); intro_sizer->Add(intro_tc, wxSizerFlags(1).Expand().Border(wxALL, 20)); #if STANDALONE_POWDIFPAT wxStaticText *file_picker_desc = new wxStaticText(panel, -1, wxT("You can use a data file as a background image")); intro_sizer->Add(file_picker_desc, wxSizerFlags().Expand().Border()); file_picker = new wxFilePickerCtrl(panel, -1); intro_sizer->Add(file_picker, wxSizerFlags().Expand().Border()); wxBoxSizer *range_sizer = new wxBoxSizer(wxHORIZONTAL); range_sizer->Add(new wxStaticText(panel, -1, wxT("Generate pattern from")), wxSizerFlags().Center().Border()); range_from = new RealNumberCtrl(panel, -1, wxT("20")); range_sizer->Add(range_from, wxSizerFlags().Center().Border()); range_sizer->Add(new wxStaticText(panel, -1, wxT("to")), wxSizerFlags().Center().Border()); range_to = new RealNumberCtrl(panel, -1, wxT("150")); range_sizer->Add(range_to, wxSizerFlags().Center().Border()); intro_sizer->Add(range_sizer); Connect(file_picker->GetId(), wxEVT_COMMAND_FILEPICKER_CHANGED, (wxObjectEventFunction) &PowderBook::OnFilePicked); #endif wxStaticBoxSizer *legend_box = new wxStaticBoxSizer(wxHORIZONTAL, panel, wxT("Legend")); wxFlexGridSizer *legend = new wxFlexGridSizer(2, 5, 5); legend->Add(new wxStaticBitmap(panel, -1, wxBitmap(get_lock_xpm())), wxSizerFlags().Center().Right()); legend->Add(new wxStaticText(panel, -1, wxT("parameter is known")), wxSizerFlags().Center().Left()); legend->Add(new wxStaticBitmap(panel, -1, wxBitmap(get_lock_open_xpm())), wxSizerFlags().Center().Right()); legend->Add(new wxStaticText(panel, -1, wxT("parameter should be optimized")), wxSizerFlags().Center().Left()); legend_box->Add(legend, wxSizerFlags(1).Expand().Border()); intro_sizer->Add(legend_box); intro_sizer->AddSpacer(20); panel->SetSizerAndFit(intro_sizer); return panel; } wxPanel* PowderBook::PrepareInstrumentPanel() { wxPanel *panel = new wxPanel(this); wxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); radiation_rb = new wxRadioBox(panel, -1, wxT("radiation"), wxDefaultPosition, wxDefaultSize, ArrayString(wxT("x-ray"), wxT("neutron")), 1, wxRA_SPECIFY_ROWS); radiation_rb->SetToolTip(wxT("used only to set initial intensities")); hsizer->AddSpacer(50); hsizer->Add(radiation_rb, wxSizerFlags().Border()); hsizer->AddStretchSpacer(); wxArrayString xaxis_choices; xaxis_choices.Add(wxT("2\u03B8")); //\u03B8 = theta xaxis_choices.Add(wxT("Q")); xaxis_choices.Add(wxT("d")); xaxis_rb = new wxRadioBox(panel, -1, wxT("x axis"), wxDefaultPosition, wxDefaultSize, xaxis_choices, 3); // \u03C0 = pi, \u03BB = lambda wxString desc = wxT("Q = 4 \u03C0 sin(\u03B8) / \u03BB\n") wxT("d = \u03BB / (2 sin \u03B8)"); xaxis_rb->SetToolTip(desc); xaxis_rb->SetSelection(xaxis_sel); hsizer->Add(xaxis_rb, wxSizerFlags().Border()); hsizer->AddSpacer(50); sizer->Add(hsizer, wxSizerFlags().Expand()); // wavelength panel wave_panel = new wxPanel(panel, -1); wxSizer *wave_sizer = new wxStaticBoxSizer(wxHORIZONTAL, wave_panel, wxT("wavelengths")); anode_lb = new wxListBox(wave_panel, -1); for (Anode const* i = anodes; i->name; ++i) { anode_lb->Append(pchar2wx(i->name)); anode_lb->Append(pchar2wx(i->name) + wxT(" A1")); anode_lb->Append(pchar2wx(i->name) + wxT(" A12")); } #ifdef __WXMAC__ anode_lb->EnsureVisible(0); #endif wave_sizer->Add(anode_lb, wxSizerFlags(1).Border().Expand()); wxSizer *lambda_sizer = new wxFlexGridSizer(2, 5, 5); lambda_sizer->Add(new wxStaticText(wave_panel, -1, wxT("wavelength")), wxSizerFlags().Center()); lambda_sizer->Add(new wxStaticText(wave_panel, -1, wxT("intensity")), wxSizerFlags().Center()); for (int i = 0; i < max_wavelengths; ++i) { LockableRealCtrl *lambda = new LockableRealCtrl(wave_panel); lambda_sizer->Add(lambda); lambda_ctrl.push_back(lambda); LockableRealCtrl *intens = new LockableRealCtrl(wave_panel, true); lambda_sizer->Add(intens); intensity_ctrl.push_back(intens); if (i == 0) { intens->set_value(100); intens->Enable(false); //intens->SetEditable(false); } } lambda_sizer->AddSpacer(20); lambda_sizer->AddSpacer(1); wave_sizer->Add(lambda_sizer, wxSizerFlags(1).Border()); wave_panel->SetSizerAndFit(wave_sizer); if (xaxis_sel != 0) wave_panel->Enable(false); sizer->Add(wave_panel, wxSizerFlags().Expand()); // x corrections wxSizer *corr_sizer = new wxStaticBoxSizer(wxVERTICAL, panel, wxT("corrections (use with care)")); corr_sizer->Add(new wxGenericStaticBitmap(panel, -1, GET_BMP(correction)), wxSizerFlags().Border()); wxSizer *g_sizer = new wxGridSizer(2, 5, 5); for (int i = 1; i <= 6; ++i) { wxSizer *px_sizer = new wxBoxSizer(wxHORIZONTAL); wxString label = wxString::Format(wxT("p%d = "), i); px_sizer->Add(new wxStaticText(panel, -1, label), wxSizerFlags().Center()); LockableRealCtrl *cor = new LockableRealCtrl(panel); px_sizer->Add(cor); g_sizer->Add(px_sizer, wxSizerFlags()); corr_ctrl.push_back(cor); } corr_sizer->Add(g_sizer, wxSizerFlags().Expand().Border()); sizer->Add(corr_sizer, wxSizerFlags().Expand()); panel->SetSizerAndFit(sizer); for (size_t i = 0; i < lambda_ctrl.size(); ++i) lambda_ctrl[i]->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(PowderBook::OnLambdaChange), NULL, this); for (size_t i = 1; i < intensity_ctrl.size(); ++i) intensity_ctrl[i]->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(PowderBook::OnLambdaChange), NULL, this); Connect(anode_lb->GetId(), wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(PowderBook::OnAnodeSelected)); Connect(xaxis_rb->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(PowderBook::OnXAxisSelected)); return panel; } PlotWithLines::PlotWithLines(wxWindow* parent, PhasePanel* phase_panel, PowderBook* powder_book) : PlotWithTics(parent), phase_panel_(phase_panel), powder_book_(powder_book) { set_bg_color(wxColour(64, 64, 64)); } static double get_max_intensity(const vector& bp) { double max_intensity = 0.; v_foreach (PlanesWithSameD, i, bp) if (i->intensity > max_intensity) max_intensity = i->intensity; return max_intensity; } void PlotWithLines::draw(wxDC &dc, bool) { draw_tics(dc, powder_book_->x_min, powder_book_->x_max, 0, powder_book_->y_max); // draw data dc.SetPen(*wxGREEN_PEN); draw_active_data(dc); //TODO buffer the plot with tics and data // draw lines int Y0 = dc.GetSize().GetHeight(); int Yx = getY(0); // Y of x axis wxPen peak_pen(*wxRED, 1, wxPENSTYLE_DOT); //wxYELLOW_PEN and wxYELLOW were added in 2.9 wxPen sel_peak_pen(wxColour(255, 255, 0)); wxPen mark_pen = *wxRED_PEN; dc.SetPen(peak_pen); const vector& bp = phase_panel_->get_crystal().bp; int selected = phase_panel_->get_selected_hkl(); double max_intensity = get_max_intensity(bp);; double h_mult = 0; if (max_intensity > 0) h_mult = powder_book_->y_max / max_intensity; v_foreach (PlanesWithSameD, i, bp) { if (!i->enabled) continue; bool is_selected = (i - bp.begin() == selected); dc.SetPen(is_selected ? sel_peak_pen : mark_pen); double x = powder_book_->d2x(i->d); int X = getX(x); // draw short line at the bottom to mark position of the peak dc.DrawLine(X, Y0, X, (Yx+Y0)/2); if (i->intensity && !phase_panel_->editing_atoms()) { int Y1 = getY(h_mult * i->intensity); dc.SetPen(is_selected ? sel_peak_pen : peak_pen); // draw line that has height proportional to peak intensity dc.DrawLine(X, Yx, X, Y1); } } } void PlotWithLines::draw_active_data(wxDC& dc) { #if STANDALONE_POWDIFPAT if (!powder_book_->data) return; xylib::Block const *block = powder_book_->data->get_block(0); xylib::Column const& xcol = block->get_column(1); xylib::Column const& ycol = block->get_column(2); int n = block->get_point_count(); //for (int i = 0; i != n; ++i) // draw_point(dc, xcol.get_value(i), ycol.get_value(i)); wxPoint *points = new wxPoint[n]; for (int i = 0; i != n; ++i) { points[i].x = getX(xcol.get_value(i)); points[i].y = getY(ycol.get_value(i)); } #else // STANDALONE_POWDIFPAT if (!powder_book_->data) return; int n = powder_book_->data->get_n(); if (n == 0) return; wxPoint *points = new wxPoint[n]; for (int i = 0; i != n; ++i) { points[i].x = getX(powder_book_->data->get_x(i)); points[i].y = getY(powder_book_->data->get_y(i)); } #endif // STANDALONE_POWDIFPAT dc.DrawLines(n, points); delete [] points; } const wxString PhasePanel::default_atom_string = wxT("Optional: atom positions, e.g.\n") wxT("Si 0 0 0\n") wxT("C 0.25 0.25 0.25"); PhasePanel::PhasePanel(wxNotebook *parent, PowderBook *powder_book_) : wxPanel(parent), powder_book(powder_book_), line_with_error_(-1) { wxSizer *vsizer = new wxBoxSizer(wxVERTICAL); wxSizer *h0sizer = new wxBoxSizer(wxHORIZONTAL); h0sizer->Add(new wxStaticText(this, -1, wxT("Name:")), wxSizerFlags().Center().Border()); name_tc = new KFTextCtrl(this, -1, wxEmptyString, 150); h0sizer->Add(name_tc, wxSizerFlags().Center().Border()); wxBoxSizer *h2sizer = new wxBoxSizer(wxHORIZONTAL); save_btn = new wxButton(this, wxID_SAVE); h2sizer->Add(save_btn, wxSizerFlags().Border()); h2sizer->AddStretchSpacer(); wxButton *s_clear_btn = new wxButton(this, wxID_CLEAR); h2sizer->Add(s_clear_btn, wxSizerFlags().Border()); h0sizer->Add(h2sizer, wxSizerFlags().Expand()); vsizer->Add(h0sizer, wxSizerFlags().Expand()); wxSizer *h1sizer = new wxBoxSizer(wxHORIZONTAL); h1sizer->Add(new wxStaticText(this, -1, wxT("Space group:")), wxSizerFlags().Center().Border()); sg_tc = new KFTextCtrl(this, -1, wxT("P 1"), 120); h1sizer->Add(sg_tc, wxSizerFlags().Center()); wxButton *sg_btn = new wxButton(this, -1, wxT("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); h1sizer->Add(sg_btn, wxSizerFlags().Center().Border()); sg_nr_st = new wxStaticText(this, -1, wxEmptyString); h1sizer->Add(sg_nr_st, wxSizerFlags().Center().Border()); vsizer->Add(h1sizer, wxSizerFlags().Expand()); wxSizer *stp_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, wxT("lattice parameters")); wxSizer *par_sizer = new wxGridSizer(3, 2, 2); wxSizerFlags flags = wxSizerFlags().Right(); par_a = addMaybeRealCtrl(this, wxT("a ="), par_sizer, flags); par_b = addMaybeRealCtrl(this, wxT("b ="), par_sizer, flags); par_c = addMaybeRealCtrl(this, wxT("c ="), par_sizer, flags); // greek letters: alpha \u03B1, beta \u03B2, gamma \u03B3 par_alpha = addMaybeRealCtrl(this, wxT("\u03B1 ="), par_sizer, flags); par_beta = addMaybeRealCtrl(this, wxT("\u03B2 ="), par_sizer, flags); par_gamma = addMaybeRealCtrl(this, wxT("\u03B3 ="), par_sizer, flags); stp_sizer->Add(par_sizer, wxSizerFlags(1).Expand()); vsizer->Add(stp_sizer, wxSizerFlags().Border().Expand()); ProportionalSplitter *vsplit = new ProportionalSplitter(this, -1, 0.75); ProportionalSplitter *hkl_split = new ProportionalSplitter(vsplit,-1, 0.4); hkl_list = new wxCheckListBox(hkl_split, -1); sample_plot_ = new PlotWithLines(hkl_split, this, powder_book); ProportionalSplitter *atom_split = new ProportionalSplitter(vsplit,-1, 0.6); atoms_tc = new wxTextCtrl(atom_split, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RICH|wxTE_MULTILINE); atoms_tc->ChangeValue(default_atom_string); atoms_show_help_ = true; atoms_tc->SetSelection(-1, -1); info_tc = new wxTextCtrl(atom_split, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RICH|wxTE_READONLY|wxTE_MULTILINE); info_tc->SetBackgroundColour(powder_book->GetBackgroundColour()); vsplit->SplitHorizProp(hkl_split, atom_split); hkl_split->SplitVertProp(hkl_list, sample_plot_); atom_split->SplitVertProp(atoms_tc, info_tc); vsizer->Add(vsplit, wxSizerFlags(1).Expand().Border()); SetSizerAndFit(vsizer); Connect(sg_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &PhasePanel::OnSpaceGroupButton); Connect(save_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &PhasePanel::OnAddToQLButton); Connect(s_clear_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &PhasePanel::OnClearButton); Connect(name_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED, (wxObjectEventFunction) &PhasePanel::OnNameChanged); Connect(sg_tc->GetId(), wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &PhasePanel::OnSpaceGroupChanged); Connect(sg_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED, (wxObjectEventFunction) &PhasePanel::OnSpaceGroupChanging); const LockableRealCtrl* param_controls[] = { par_a, par_b, par_c, par_alpha, par_beta, par_gamma }; for (int i = 0; i != sizeof(param_controls) / sizeof(par_a); ++i) { wxWindowID id = param_controls[i]->get_text_ctrl()->GetId(); Connect(id, wxEVT_COMMAND_TEXT_UPDATED, (wxObjectEventFunction) &PhasePanel::OnParameterChanging); Connect(id, wxEVT_COMMAND_TEXT_ENTER, (wxObjectEventFunction) &PhasePanel::OnParameterChanged); } Connect(hkl_list->GetId(), wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, (wxObjectEventFunction) &PhasePanel::OnLineToggled); Connect(hkl_list->GetId(), wxEVT_COMMAND_LISTBOX_SELECTED, (wxObjectEventFunction) &PhasePanel::OnLineSelected); atoms_tc->Connect(wxEVT_SET_FOCUS, (wxObjectEventFunction) &PhasePanel::OnAtomsFocus, NULL, this); atoms_tc->Connect(wxEVT_KILL_FOCUS, (wxObjectEventFunction) &PhasePanel::OnAtomsUnfocus, NULL, this); atoms_tc->Connect(wxEVT_COMMAND_TEXT_UPDATED, (wxObjectEventFunction) &PhasePanel::OnAtomsChanged, NULL, this); } void PhasePanel::OnSpaceGroupButton(wxCommandEvent& event) { SpaceGroupChooser dlg(this, sg_tc->GetValue()); if (dlg.ShowModal() == wxID_OK) sg_tc->SetValue(dlg.get_value()); OnSpaceGroupChanged(event); } void PhasePanel::OnAddToQLButton(wxCommandEvent&) { wxString name = name_tc->GetValue(); if (name.find(wxT("|")) != string::npos) { wxMessageBox(wxT("The pipe character '|' is not allowed in name."), wxT("Error"), wxOK|wxICON_ERROR); return; } wxListBox *saved_phase_lb = powder_book->get_saved_phase_lb(); if (saved_phase_lb->FindString(name) != wxNOT_FOUND) { int answer = wxMessageBox(wxT("Name `") + name + wxT("' already exists.\nOverwrite?"), wxT("Overwrite?"), wxYES_NO|wxICON_QUESTION); if (answer != wxYES) return; } else saved_phase_lb->Append(name); CelFile cel; cel.sgs = cr_.sgs; cel.a = par_a->get_value(); cel.b = par_b->get_value(); cel.c = par_c->get_value(); cel.alpha = par_alpha->get_value(); cel.beta = par_beta->get_value(); cel.gamma = par_gamma->get_value(); v_foreach (Atom, i, cr_.atoms) { t_pse const* pse = find_in_pse(i->symbol); assert (pse != NULL); AtomInCell aic; aic.Z = pse->Z; aic.x = i->pos[0].x; aic.y = i->pos[0].y; aic.z = i->pos[0].z; cel.atoms.push_back(aic); } saved_phase_lb->SetStringSelection(name); powder_book->quick_phase_list[wx2s(name)] = cel; FILE *f = wxFopen(get_cel_files_dir() + name + wxT(".cel"), wxT("w")); if (f) { write_cel_file(cel, f); fclose(f); } } void PhasePanel::OnClearButton(wxCommandEvent& event) { name_tc->Clear(); sg_tc->Clear(); par_a->Clear(); par_b->Clear(); par_c->Clear(); par_alpha->Clear(); par_beta->Clear(); par_gamma->Clear(); OnSpaceGroupChanged(event); powder_book->update_phase_labels(this); } void PhasePanel::OnNameChanged(wxCommandEvent&) { powder_book->deselect_phase_quick_list(); powder_book->update_phase_labels(this); } void PhasePanel::OnSpaceGroupChanged(wxCommandEvent&) { string text = wx2s(sg_tc->GetValue()); const SpaceGroupSetting *sgs = parse_any_sg_symbol(text.c_str()); cr_.set_space_group(sgs); update_space_group_ui(); update_miller_indices(true); powder_book->deselect_phase_quick_list(); sample_plot_->refresh(); } void PhasePanel::update_space_group_ui() { if (cr_.sgs == NULL) { sg_tc->Clear(); hkl_list->Clear(); sg_nr_st->SetLabel(wxEmptyString); return; } sg_tc->ChangeValue(s2wx(fullHM(cr_.sgs))); const char* system = get_crystal_system_name(cr_.xs()); sg_nr_st->SetLabel(wxString::Format(wxT("%d, %s, order %d"), cr_.sgs->sgnumber, pchar2wx(system).c_str(), get_sg_order(cr_.sg_ops))); enable_parameter_fields(); update_disabled_parameters(); } void PhasePanel::enable_parameter_fields() { switch (cr_.xs()) { case TriclinicSystem: par_b->Enable(true); par_c->Enable(true); par_alpha->Enable(true); par_beta->Enable(true); par_gamma->Enable(true); break; case MonoclinicSystem: par_b->Enable(true); par_c->Enable(true); par_beta->Enable(true); par_alpha->Enable(false); par_alpha->set_value(90.); par_gamma->Enable(false); par_gamma->set_value(90.); break; case OrthorhombicSystem: par_b->Enable(true); par_c->Enable(true); set_ortho_angles(); break; case TetragonalSystem: par_b->Enable(false); par_c->Enable(true); set_ortho_angles(); break; /* Crystals in the trigonal crystal system are either in the rhombohedral lattice system or in the hexagonal lattice system. Those in the rhombohedral space groups are described either using the hexagonal basis or the rhombohedral basis. The latter is not supported yet. case RhombohedralSystem: par_b->Enable(false); par_c->Enable(false); par_alpha->Enable(true); par_beta->Enable(false); par_gamma->Enable(false); break; */ case TrigonalSystem: case HexagonalSystem: par_b->Enable(false); par_c->Enable(true); par_alpha->set_value(90); par_beta->set_value(90); par_gamma->set_value(120); break; case CubicSystem: par_b->Enable(false); par_c->Enable(false); set_ortho_angles(); break; case UndefinedSystem: break; } } void PhasePanel::set_ortho_angles() { par_alpha->Enable(false); par_alpha->set_value(90.); par_beta->Enable(false); par_beta->set_value(90.); par_gamma->Enable(false); par_gamma->set_value(90.); } void PhasePanel::OnParameterChanging(wxCommandEvent&) { update_disabled_parameters(); powder_book->deselect_phase_quick_list(); } void PhasePanel::OnParameterChanged(wxCommandEvent&) { update_miller_indices(false); sample_plot_->refresh(); } void PhasePanel::OnLineToggled(wxCommandEvent& event) { int n = event.GetSelection(); PlanesWithSameD& bp = cr_.bp[n]; // event.IsChecked() is not set (wxGTK 2.9) bp.enabled = hkl_list->IsChecked(n); sample_plot_->refresh(); } static wxString make_info_string_for_line(const PlanesWithSameD& bp, PowderBook *powder_book) { wxString info = wxT("line "); wxString mult_str = wxT("multiplicity: "); wxString sfac_str = wxT("|F(hkl)|: "); v_foreach (Plane, i, bp.planes) { if (i != bp.planes.begin()) { info += wxT(", "); mult_str += wxT(", "); sfac_str += wxT(", "); } info += wxString::Format(wxT("(%d,%d,%d)"), i->h, i->k, i->l); mult_str += wxString::Format(wxT("%d"), i->multiplicity); sfac_str += wxString::Format(wxT("%g"), sqrt(i->F2)); } info += wxString::Format(wxT("\nd=%g\n"), bp.d); info += mult_str + wxT("\n") + sfac_str; info += wxString::Format(wxT("\nLorentz-polarization: %g"), bp.lpf); info += wxString::Format(wxT("\ntotal intensity: %g"), bp.intensity); for (int i = 0; ; ++i) { double lambda = powder_book->get_lambda(i); if (lambda == 0.) break; wxString format = (i == 0 ? wxT("\n2\u03B8: %g") : wxT(", %g")); info += wxString::Format(format, lambda); } return info; } static wxString make_info_string_for_atoms(const vector& atoms, int error_line) { wxString info = wxT("In unit cell:"); v_foreach (Atom, i, atoms) { info += wxString::Format(wxT(" %d %s "), (int) i->pos.size(), pchar2wx(i->symbol).c_str()); } if (error_line != -1) info += wxString::Format(wxT("\nError in line %d."), error_line); return info; } void PhasePanel::OnLineSelected(wxCommandEvent& event) { if (event.IsSelection()) { int n = event.GetSelection(); PlanesWithSameD const& bp = cr_.bp[n]; info_tc->ChangeValue(make_info_string_for_line(bp, powder_book)); } sample_plot_->refresh(); } void PhasePanel::OnAtomsFocus(wxFocusEvent&) { if (atoms_show_help_) { atoms_tc->Clear(); atoms_show_help_ = false; } wxString info = make_info_string_for_atoms(cr_.atoms, line_with_error_); info_tc->ChangeValue(info); editing_atoms_ = true; sample_plot_->refresh(); } void PhasePanel::OnAtomsUnfocus(wxFocusEvent&) { double lambda = powder_book->get_lambda(0); cr_.update_intensities(powder_book->get_radiation_type(), lambda); int n = hkl_list->GetSelection(); if (n >= 0) { PlanesWithSameD const& bp = cr_.bp[n]; info_tc->SetValue(make_info_string_for_line(bp, powder_book)); } editing_atoms_ = false; sample_plot_->refresh(); } void PhasePanel::OnAtomsChanged(wxCommandEvent&) { string atoms_str = wx2s(atoms_tc->GetValue()); if (atoms_str.size() < 3) { info_tc->Clear(); return; } line_with_error_ = parse_atoms(atoms_str.c_str(), cr_); powder_book->deselect_phase_quick_list(); wxString info = make_info_string_for_atoms(cr_.atoms, line_with_error_); info_tc->SetValue(info); } void PhasePanel::update_disabled_parameters() { if (!par_b->IsEnabled()) par_b->set_string(par_a->get_string()); if (!par_c->IsEnabled()) par_c->set_string(par_a->get_string()); /* if (cr_.xs() == RhombohedralSystem) { par_beta->set_string(par_alpha->get_string()); par_gamma->set_string(par_alpha->get_string()); } */ } void PhasePanel::update_miller_indices(bool sg_changed) { double a = par_a->get_value(); double b = par_b->get_value(); double c = par_c->get_value(); double alpha = par_alpha->get_value() * M_PI / 180.; double beta = par_beta->get_value() * M_PI / 180.; double gamma = par_gamma->get_value() * M_PI / 180.; double lambda = powder_book->get_lambda(0); double min_d = powder_book->get_min_d(); RadiationType radiation = powder_book->get_radiation_type(); if (a <= 0 || b <= 0 || c <= 0 || alpha <= 0 || beta <= 0 || gamma <= 0 || min_d <= 0) { hkl_list->Clear(); return; } if (sg_changed || cr_.uc == NULL || cr_.uc->a != a || cr_.uc->b != b || cr_.uc->c != c || cr_.uc->alpha != alpha || cr_.uc->beta != beta || cr_.uc->gamma != gamma || cr_.old_min_d != min_d) { cr_.set_unit_cell(new UnitCell(a, b, c, alpha, beta, gamma)); cr_.generate_reflections(min_d); hkl_list->Clear(); vm_foreach (PlanesWithSameD, i, cr_.bp) { i->enabled = powder_book->is_d_active(i->d); char ac = (i->planes.size() == 1 ? ' ' : '*'); Miller const& m = i->planes[0]; hkl_list->Append(wxString::Format(wxT("(%d,%d,%d)%c d=%g"), m.h, m.k, m.l, ac, i->d)); hkl_list->Check(hkl_list->GetCount() - 1, i->enabled); } #ifdef __WXMAC__ hkl_list->EnsureVisible(0); #endif } cr_.update_intensities(radiation, lambda); } void PhasePanel::set_phase(string const& name, CelFile const& cel) { name_tc->ChangeValue(s2wx(name)); powder_book->update_phase_labels(this); cr_.set_space_group(cel.sgs); par_a->set_string(wxString::Format(wxT("%g"), (cel.a))); par_b->set_string(wxString::Format(wxT("%g"), (cel.b))); par_c->set_string(wxString::Format(wxT("%g"), (cel.c))); par_alpha->set_string(wxString::Format(wxT("%g"), (cel.alpha))); par_beta->set_string(wxString::Format(wxT("%g"), (cel.beta))); par_gamma->set_string(wxString::Format(wxT("%g"), (cel.gamma))); wxString atoms_str; v_foreach (AtomInCell, i, cel.atoms) { t_pse const* pse = find_Z_in_pse(i->Z); if (pse == NULL) continue; atoms_str += wxString::Format(wxT("%s %g %g %g\n"), pchar2wx(pse->symbol).c_str(), i->x, i->y, i->z); } atoms_tc->ChangeValue(atoms_str); update_space_group_ui(); cr_.atoms.clear(); line_with_error_ = parse_atoms((const char*) atoms_str.mb_str(), cr_); wxString info = make_info_string_for_atoms(cr_.atoms, line_with_error_); info_tc->SetValue(info); atoms_show_help_ = false; update_miller_indices(true); } wxPanel* PowderBook::PrepareSamplePanel() { wxPanel *panel = new wxPanel(this); wxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); wxSizer *left_sizer = new wxStaticBoxSizer(wxVERTICAL, panel, wxT("saved structures")); saved_phase_lb = new wxListBox(panel, -1, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE|wxLB_SORT); for (map::const_iterator i = quick_phase_list.begin(); i != quick_phase_list.end(); ++i) saved_phase_lb->Append(s2wx(i->first)); #ifdef __WXMAC__ saved_phase_lb->EnsureVisible(0); #endif left_sizer->Add(saved_phase_lb, wxSizerFlags(1).Border().Expand()); wxButton *s_remove_btn = new wxButton(panel, wxID_REMOVE); left_sizer->Add(s_remove_btn, wxSizerFlags().Center().Border(wxLEFT|wxRIGHT)); wxButton *s_import_btn = new wxButton(panel, wxID_OPEN, wxT("Import")); left_sizer->Add(s_import_btn, wxSizerFlags().Center().Border()); sizer->Add(left_sizer, wxSizerFlags().Expand()); sample_nb = new wxNotebook(panel, -1, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM); PhasePanel *page = new PhasePanel(sample_nb, this); sample_nb->AddPage(page, wxT("+")); sizer->Add(sample_nb, wxSizerFlags(1).Expand()); panel->SetSizerAndFit(sizer); Connect(saved_phase_lb->GetId(), wxEVT_COMMAND_LISTBOX_SELECTED, wxCommandEventHandler(PowderBook::OnQuickPhaseSelected)); Connect(s_remove_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PowderBook::OnQuickListRemove)); Connect(s_import_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PowderBook::OnQuickListImport)); return panel; } wxPanel* PowderBook::PreparePeakPanel() { wxPanel *panel = new wxPanel(this); wxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxArrayString peak_choices; peak_choices.Add(wxT("Gaussian")); peak_choices.Add(wxT("Lorentzian")); peak_choices.Add(wxT("Pearson VII")); peak_choices.Add(wxT("Pseudo-Voigt")); peak_choices.Add(wxT("Voigt")); peak_rb = new wxRadioBox(panel, -1, wxT("peak function"), wxDefaultPosition, wxDefaultSize, peak_choices, 5); peak_rb->SetSelection(3 /*Pseudo-Voigt*/); sizer->Add(peak_rb, wxSizerFlags().Expand().Border()); split_cb = new wxCheckBox(panel, -1, wxT("split (different widths and shapes for both sides)")); sizer->Add(split_cb, wxSizerFlags().Border()); wxArrayString center_choices; center_choices.Add(wxT("independent for each peak")); center_choices.Add(wxT("constrained by wavelength and lattice parameters")); center_rb = new wxRadioBox(panel, -1, wxT("peak position"), wxDefaultPosition, wxDefaultSize, center_choices, 1); center_rb->SetSelection(1); center_rb->Enable(0, false); sizer->Add(center_rb, wxSizerFlags().Expand().Border()); wxArrayString peak_widths; peak_widths.Add(wxT("independent for each hkl")); peak_widths.Add(wxT("H\u00B2=U tan\u00B2\u03B8 + V tan\u03B8 + W + ") wxT("Z/cos\u00B2\u03B8")); width_rb = new wxRadioBox(panel, -1, wxT("peak width"), wxDefaultPosition, wxDefaultSize, peak_widths, 1); sizer->Add(width_rb, wxSizerFlags().Expand().Border()); wxArrayString peak_shapes; peak_shapes.Add(wxT("independent for each hkl (initial value: A)")); peak_shapes.Add(wxT("A + B (2\u03B8) + C (2\u03B8)\u00B2")); peak_shapes.Add(wxT("A + B / (2\u03B8) + C / (2\u03B8)\u00B2")); shape_rb = new wxRadioBox(panel, -1, wxT("peak shape"), wxDefaultPosition, wxDefaultSize, peak_shapes, 1); sizer->Add(shape_rb, wxSizerFlags().Expand().Border()); wxSizer *stp_sizer = new wxStaticBoxSizer(wxHORIZONTAL, panel, wxT("initial parameters")); wxSizer *par_sizer = new wxGridSizer(4, 10, 5); wxSizerFlags flags = wxSizerFlags().Right(); par_u = addMaybeRealCtrl(panel, wxT("U ="), par_sizer, flags, false); par_v = addMaybeRealCtrl(panel, wxT("V ="), par_sizer, flags, false); par_w = addMaybeRealCtrl(panel, wxT("W ="), par_sizer, flags, false); par_w->set_value(0.1); par_z = addMaybeRealCtrl(panel, wxT("Z ="), par_sizer, flags, false); par_a = addMaybeRealCtrl(panel, wxT("A ="), par_sizer, flags, false); par_a->set_value(0.8); // valid value for both Voigt and Pearson7 par_b = addMaybeRealCtrl(panel, wxT("B ="), par_sizer, flags, false); par_c = addMaybeRealCtrl(panel, wxT("C ="), par_sizer, flags, false); stp_sizer->Add(par_sizer, wxSizerFlags(1).Expand()); sizer->Add(stp_sizer, wxSizerFlags().Border().Expand()); update_peak_parameters(); panel->SetSizerAndFit(sizer); Connect(peak_rb->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(PowderBook::OnPeakRadio)); Connect(split_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(PowderBook::OnPeakSplit)); Connect(width_rb->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(PowderBook::OnWidthRadio)); Connect(shape_rb->GetId(), wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(PowderBook::OnShapeRadio)); return panel; } wxString PowderBook::get_peak_name() const { wxString s; switch (peak_rb->GetSelection()) { case 0: s = wxT("Gaussian"); break; case 1: s = wxT("Lorentzian"); break; case 2: s = wxT("Pearson7"); break; case 3: s = wxT("PseudoVoigt"); break; case 4: s = wxT("Voigt"); break; } return split_cb->GetValue() ? wxT("Split") + s : s; } void PowderBook::set_peak_name(const string& name) { string basename; if (startswith(name, "Split")) { split_cb->SetValue(true); basename = name.substr(5); } else basename = name; int sel = 0; if (basename == "Gaussian") sel = 0; else if (basename == "Lorentzian") sel = 1; else if (basename == "Pearson7") sel = 2; else if (basename == "PseudoVoigt") sel = 3; else if (basename == "Voigt") sel = 4; peak_rb->SetSelection(sel); } #if !STANDALONE_POWDIFPAT static bool has_old_variables() { v_foreach (fityk::Variable*, i, ftk->mgr.variables()) if (startswith((*i)->name, "pd")) return true; return false; } #endif wxPanel* PowderBook::PrepareActionPanel() { wxPanel *panel = new wxPanel(this); #if !STANDALONE_POWDIFPAT wxSizer *sizer = new wxBoxSizer(wxVERTICAL); sizer->Add(new wxStaticText(panel, -1, wxT("Script that prepares model:")), wxSizerFlags().Border()); action_txt = new wxTextCtrl(panel, -1, wxEmptyString, wxDefaultPosition, wxSize(-1, 200), wxTE_RICH|wxTE_READONLY|wxTE_MULTILINE); sizer->Add(action_txt, wxSizerFlags(1).Expand().Border(wxLEFT|wxRIGHT)); // apparently Mac/Carbon does not like multi-line static texts wxStaticText *text = new wxStaticText(panel, -1, wxT("Press OK to execute the script above and close this window.") #ifndef __WXOSX_CARBON__ wxT("\nIf the initial model is good, fit it to the data.") wxT("\nOtherwise, reopen this window and correct the model.") #endif ); wxFont font = text->GetFont(); font.SetPointSize(font.GetPointSize() - 1); text->SetFont(font); sizer->Add(text, wxSizerFlags().Border()); wxBoxSizer *btn_sizer = new wxBoxSizer(wxHORIZONTAL); wxButton *del_btn = new wxButton(panel, -1, wxT("Delete old model")); del_btn->Enable(has_old_variables()); del_btn->SetToolTip(wxT("delete %pd*, $pd*")); btn_sizer->Add(del_btn, wxSizerFlags().Border()); btn_sizer->AddStretchSpacer(); wxButton *cancel_btn = new wxButton(panel, wxID_CANCEL); btn_sizer->Add(cancel_btn, wxSizerFlags().Border()); wxButton *ok_btn = new wxButton(panel, wxID_OK); btn_sizer->Add(ok_btn, wxSizerFlags().Border()); sizer->Add(btn_sizer, wxSizerFlags().Expand()); panel->SetSizerAndFit(sizer); Connect(del_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PowderBook::OnDelButton)); Connect(ok_btn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(PowderBook::OnOk)); #endif //!STANDALONE_POWDIFPAT return panel; } static wxString get_var(LockableRealCtrl *ctrl, double mult = 1.) { return wxString::Format(ctrl->is_locked() ? wxT("%.9g") : wxT("~%.9g"), ctrl->get_value() * mult); } static wxString hkl2wxstr(const Miller& hkl) { wxString s; bool separate = !(hkl.h > -10 && hkl.h < 10 && hkl.k > -10 && hkl.k < 10 && hkl.l > -10 && hkl.l < 10); if (hkl.h < 0) s += wxT("m"); s += s2wx(S(abs(hkl.h))); if (separate) s += wxT("_"); if (hkl.k < 0) s += wxT("m"); s += s2wx(S(abs(hkl.k))); if (separate) s += wxT("_"); if (hkl.l < 0) s += wxT("m"); s += s2wx(S(abs(hkl.l))); return s; } #if !STANDALONE_POWDIFPAT // All variable and function names have "pd" prefix. // Each name is composed from a few parts. // One example: "$pd1b_c201": // "pd" - prefix // "1" - first phase (usually there is only one phase) // "b" - first wavelength // "_" - separator // "c" - center // "201" - hkl=(201) // The variable $pd1a_c201 contains the center (position) of the (201) // reflection of the first phase, in the radiation of the first wavelenth. wxString PowderBook::prepare_commands() { wxString s; if (has_old_variables()) s = wxT("delete %pd*, $pd* # delete old model\n"); wxString ds_pref; if (ftk->dk.count() > 1) { int data_nr = frame->get_focused_data_index(); ds_pref.Printf(wxT("@%d."), data_nr); } int xaxis_val = xaxis_rb->GetSelection(); //wavelength char lambda_symbol = 'a'; if (xaxis_val == 0) { for (size_t i = 0; i != lambda_ctrl.size(); ++i) { if (!lambda_ctrl[i]->is_nonzero() || !intensity_ctrl[i]->is_nonzero()) continue; s += wxString::Format(wxT("$pd_lambda_%c = %s\n"), lambda_symbol, get_var(lambda_ctrl[i]).c_str()); if (i != 0) { s += wxString::Format(wxT("$pd_intens_%c = %s\n"), lambda_symbol, get_var(intensity_ctrl[i], 0.01).c_str()); } ++lambda_symbol; } } else ++lambda_symbol; // corrections if (ftk->get_tpm()->get_tp("PdXcorr") != NULL) s += wxT("undefine PdXcorr\n"); wxString xc_args, xc_vargs, xc_def; wxString xc_formulas[] = { wxT("p1/tan(x*pi/180)"), wxT("p2/sin(x*pi/180)"), wxT("p3/tan(x/2*pi/180)"), wxT("p4*sin(x*pi/180)"), wxT("p5*cos(x/2*pi/180)"), wxT("p6") }; for (int i = 0; i != (int) corr_ctrl.size(); ++i) { if (corr_ctrl[i]->is_nonzero()) { if (!xc_args.empty()) { xc_args += wxT(", "); xc_vargs += wxT(", "); xc_def += wxT(" + "); } xc_args += wxString::Format(wxT("p%d"), i+1); xc_vargs += wxString::Format(wxT("$pd_p%d"), i+1); xc_def += xc_formulas[i]; s += wxString::Format(wxT("$pd_p%d = %s\n"), i+1, get_var(corr_ctrl[i]).c_str()); } } if (!xc_args.empty()) { if (xc_args == wxT("p6")) { // special case, we don't need "define" s += wxT("%pd_xcorr = Constant($pd_p6)\n"); } else { s += wxT("define PdXcorr(") + xc_args + wxT(") = ") + xc_def + wxT("\n"); s += wxT("%pd_xcorr = PdXcorr(") + xc_vargs + wxT(")\n"); } s += ds_pref + wxT("Z = %pd_xcorr\n"); } bool has_u = par_u->is_nonzero(); bool has_v = par_v->is_nonzero(); bool has_w = par_w->is_nonzero(); bool has_z = par_z->is_nonzero(); double u_val = par_u->get_value(); double v_val = par_v->get_value(); double w_val = par_w->get_value(); double z_val = par_z->get_value(); s += wxT("\n"); int width_sel = width_rb->GetSelection(); if (width_sel == 1 /*H2=Utan2T...*/) { if (has_u) s += wxT("$pd_u = ") + get_var(par_u) + wxT("\n"); if (has_v) s += wxT("$pd_v = ") + get_var(par_v) + wxT("\n"); if (has_w) s += wxT("$pd_w = ") + get_var(par_w) + wxT("\n"); if (has_z) s += wxT("$pd_z = ") + get_var(par_z) + wxT("\n"); } bool has_a = par_a->IsEnabled() && par_a->is_nonzero(); bool has_b = par_b->IsEnabled() && par_b->is_nonzero(); bool has_c = par_c->IsEnabled() && par_c->is_nonzero(); double a_val = par_a->get_value(); if (has_a) s += wxT("$pd_a = ") + get_var(par_a) + wxT("\n"); if (has_b) s += wxT("$pd_b = ") + get_var(par_b) + wxT("\n"); if (has_c) s += wxT("$pd_c = ") + get_var(par_c) + wxT("\n"); for (int i = 0; i < (int) sample_nb->GetPageCount() - 1; ++i) { const PhasePanel* p = get_phase_panel(i); const Crystal& cr = p->get_crystal(); double max_intensity = get_max_intensity(cr.bp); double h_mult = y_max / (max_intensity > 0 ? max_intensity : 2); s += wxT("\n# ") + p->name_tc->GetValue() + wxT("\n"); wxString pre = wxString::Format(wxT("$pd%d_"), i); s += pre + wxT("a = ") + get_var(p->par_a) + wxT("\n"); if (p->par_b->IsEnabled()) s += pre + wxT("b = ") + get_var(p->par_b) + wxT("\n"); if (p->par_c->IsEnabled()) s += pre + wxT("c = ") + get_var(p->par_c) + wxT("\n"); double d2r = M_PI/180.; if (p->par_alpha->IsEnabled()) s += pre + wxT("alpha = ") + get_var(p->par_alpha, d2r) + wxT("\n"); if (p->par_beta->IsEnabled()) s += pre + wxT("beta = ") + get_var(p->par_beta, d2r) + wxT("\n"); if (p->par_gamma->IsEnabled()) s += pre + wxT("gamma = ") + get_var(p->par_gamma, d2r) + wxT("\n"); if (cr.xs() == TriclinicSystem) { wxString v_str = wxT(":a*:b*:c *") wxT(" sqrt(1 - cos(:alpha)^2 - cos(:beta)^2 - cos(:gamma)^2") wxT(" + 2*cos(:alpha)*cos(:beta)*cos(:gamma))\n"); v_str.Replace(wxT(":"), pre); s += pre + wxT("volume = ") + v_str; } bool has_shape = peak_rb->GetSelection() >= 2; int shape_sel = shape_rb->GetSelection(); v_foreach (PlanesWithSameD, j, cr.bp) { if (!j->enabled) continue; const Miller& hkl = j->planes[0]; wxString hkl_str = hkl2wxstr(hkl); wxString hvar = pre + wxT("h") + hkl_str; double h = h_mult * max(j->intensity, 1.); double lambda1 = get_lambda(0); double ctr = 180 / M_PI * 2 * asin(lambda1 / (2 * j->d)); s += wxT("\n") + hvar + wxString::Format(wxT(" = ~%.5g\n"), h); // we need to pre-define $pdXa_cHKL if wvar or svar depend on it wxString cvar_a = wxString::Format(wxT("$pd%da_c%s"), i, hkl_str.c_str()); wxString theta_rad = cvar_a + wxT("*pi/360"); if (width_sel == 1 || (has_shape && shape_sel >= 1)) { s += cvar_a + wxT(" = 0 # will be changed\n"); } wxString wvar = pre + wxT("w") + hkl_str; if (width_sel == 0 /*independent*/) { double t = tan(ctr/2); double c = cos(ctr/2); double hwhm = sqrt(u_val*t*t + v_val*t + w_val + z_val/(c*c))/2; s += wvar + wxString::Format(wxT(" = ~%.5g\n"), hwhm); } else if (width_sel == 1 /*H2=Utan2T...*/) { s += wvar + wxT(" = sqrt("); if (has_u) s += wxT("$pd_u*tan(") + theta_rad + wxT(")^2"); if (has_v) { if (has_u) s += wxT(" + "); s += wxT("$pd_v*tan(") + theta_rad + wxT(")"); } if (has_w) { if (has_u || has_v) s += wxT(" + "); s += wxT("$pd_w"); } if (has_z) { if (has_u || has_v || has_w) s += wxT(" + "); s += wxT("$pd_z/cos(") + theta_rad + wxT(")^2"); } s += wxT(")\n"); } wxString svar = pre + wxT("s") + hkl_str; if (shape_sel == 0 /*independent*/) { s += svar + wxString::Format(wxT(" = ~%.5g\n"), a_val); } else if (shape_sel == 1 || shape_sel == 2) { s += svar + wxT(" = "); if (has_a) s += wxT("$pd_a"); if (has_b) { if (has_a) s += wxT(" + "); s += (shape_sel == 1 ? wxT("$pd_b*") : wxT("$pd_b/")) + cvar_a; } if (has_c) { if (has_a || has_b) s += wxT(" + "); s += (shape_sel == 1 ? wxT("$pd_c*") : wxT("$pd_c/(")) + cvar_a + wxT("*") + cvar_a + (shape_sel == 1 ? wxT("") : wxT(")")); } s += wxT("\n"); } for (char wave = 'a'; wave != lambda_symbol; ++wave) { wxString cvar = wxString::Format(wxT("$pd%d%c_c%s"), i, wave, hkl_str.c_str()); wxString rd_str; // d^-1 switch (cr.xs()) { case CubicSystem: // use only a rd_str.Printf(wxT("sqrt(%d)/:a"), hkl.h*hkl.h + hkl.k*hkl.k + hkl.l*hkl.l); break; case TetragonalSystem: // use a and c rd_str.Printf(wxT("sqrt(%d/:a^2 + %d/:c^2)"), hkl.h*hkl.h + hkl.k*hkl.k, hkl.l*hkl.l); break; //TODO rhombohedral basis are not supported case TrigonalSystem: case HexagonalSystem: rd_str.Printf(wxT("sqrt(%g/:a^2 + %d/:c^2)"), 4./3.*(hkl.h*hkl.h + hkl.h*hkl.k + hkl.k*hkl.k), hkl.l*hkl.l); break; case OrthorhombicSystem: // use a, b, c rd_str.Printf( wxT("sqrt(%d/:a^2 + %d/:b^2 + %d/:c^2)"), hkl.h*hkl.h, hkl.k*hkl.k, hkl.l*hkl.l); break; case MonoclinicSystem: rd_str.Printf( wxT("(1/sin(:beta) * ") wxT("sqrt(%d/:a^2 + %d*sin(:beta)^2/:b^2 + %d/:c^2 ") wxT("- %d*cos(:beta)/(:a*:c)))"), hkl.h*hkl.h, hkl.k*hkl.k, hkl.l*hkl.l, 2*hkl.h*hkl.l); break; case TriclinicSystem: rd_str.Printf( wxT("(sqrt(") wxT(" (%d*:b*:c*sin(:alpha))^2 + ") wxT(" (%d*:a*:c*sin(:beta))^2 + ") wxT(" (%d*:a*:b*sin(:gamma))^2 + ") wxT("%d*:a*:b*:c^2*(cos(:alpha)*cos(:beta) - cos(:gamma)) + ") wxT("%d*:a^2*:b*:c*(cos(:beta)*cos(:gamma) - cos(:alpha)) + ") wxT("%d*:a*:b^2*:c*(cos(:alpha)*cos(:gamma) - cos(:beta)) ") wxT(") / :volume)"), hkl.h, hkl.k, hkl.l, 2*hkl.h*hkl.k, 2*hkl.k*hkl.l, 2*hkl.h*hkl.l); break; case UndefinedSystem: rd_str = wxT(" # undefined system # "); break; } rd_str.Replace(wxT(":"), wxString::Format(wxT("$pd%d_"), i)); s += cvar; if (xaxis_val == 0) // 2T s += wxString::Format( wxT(" = 360/pi * asin($pd_lambda_%c/2 * %s)\n"), wave, rd_str.c_str()); else if (xaxis_val == 1) // Q s += wxString::Format(wxT(" = 2*pi*%s\n"), rd_str.c_str()); else if (xaxis_val == 2) { // d if (cr.xs() == CubicSystem) // we can simplify this one s += wxString::Format(wxT(" = $pd%d_a/sqrt(%d)\n"), i, hkl.h*hkl.h + hkl.k*hkl.k + hkl.l*hkl.l); else s += wxString::Format(wxT(" = 1/%s\n"), rd_str.c_str()); } wxString fname = wxString::Format(wxT("%%pd%d%c_%s"), i, wave, hkl_str.c_str()); s += fname + wxT(" = ") + get_peak_name(); // all functions have height and center wxString height = hvar; if (wave != 'a') height += wxString::Format(wxT("*$pd_intens_%c"), wave); s += wxString::Format(wxT("(%s, %s, "), height.c_str(), cvar.c_str()); if (split_cb->GetValue()) { // split function s += wvar + wxT(", ") + wvar; if (has_shape) s += wxT(", ") + svar + wxT(", ") + svar; } else { // normal (not split) function s += wvar; if (has_shape) s += wxT(", ") + svar; } s += wxT(")\n"); s += ds_pref + wxT("F += ") + fname + wxT("\n"); } } } return s; } static void var2lockctrl(const string& varname, LockableRealCtrl* ctrl, double mult=1.) { int k = ftk->mgr.find_variable_nr(varname); if (k == -1) return; const fityk::Variable* v = ftk->mgr.get_variable(k); ctrl->set_value(v->value() * mult); ctrl->set_lock(v->is_constant()); } // this function does the opposite to prepare_commands(): // fills the form using assigned previously $pd* and %pd functions void PowderBook::fill_forms() { // instrument page for (size_t i = 0; i != lambda_ctrl.size(); ++i) { char wave = 'a' + i; var2lockctrl("pd_lambda_" + S(wave), lambda_ctrl[i]); var2lockctrl("pd_intens_" + S(wave), intensity_ctrl[i], 100); } // corrections for (size_t i = 0; i != corr_ctrl.size(); ++i) { var2lockctrl("pd_" + S(i+1), corr_ctrl[i]); } int first_func = -1; // sample page for (size_t i = 0; ; ++i) { string pre = "pd" + S(i) + "_"; int k = ftk->mgr.find_variable_nr(pre + "a"); if (k == -1) break; assert(i == sample_nb->GetPageCount() - 1); PhasePanel* p = get_phase_panel(i); var2lockctrl(pre+"a", p->par_a); var2lockctrl(pre+"b", p->par_b); var2lockctrl(pre+"c", p->par_c); var2lockctrl(pre+"alpha", p->par_alpha); var2lockctrl(pre+"beta", p->par_beta); var2lockctrl(pre+"gamma", p->par_gamma); if (i < phase_desc.size()) { p->name_tc->ChangeValue(phase_desc[i].name); update_phase_labels(p, i); p->sg_tc->ChangeValue(phase_desc[i].sg); wxCommandEvent dummy; p->OnSpaceGroupChanged(dummy); p->atoms_tc->SetValue(phase_desc[i].atoms); } Crystal& cr = p->get_crystal(); assert(cr.bp.size() == p->hkl_list->GetCount()); int n = 0; vm_foreach (PlanesWithSameD, j, cr.bp) { wxString fname = wxString::Format(wxT("pd%da_"), (int) i) + hkl2wxstr(j->planes[0]); int nr = ftk->mgr.find_function_nr(wx2s(fname)); j->enabled = (nr != -1); p->hkl_list->Check(n, j->enabled); ++n; if (j->enabled && first_func == -1) first_func = nr; } } // peak page if (first_func != -1) { const fityk::Function *f = ftk->mgr.get_function(first_func); set_peak_name(f->tp()->name); int w = index_of_element(f->tp()->fargs, "hwhm"); if (w == -1) w = index_of_element(f->tp()->fargs, "hwhm1"); if (w != -1) { int idx = f->used_vars().get_idx(w); const fityk::Variable* hwhm = ftk->mgr.get_variable(idx); if (!hwhm->is_simple() || hwhm->name == "pd_w") width_rb->SetSelection(1); } int sh = index_of_element(f->tp()->fargs, "shape"); if (sh == -1) sh = index_of_element(f->tp()->fargs, "shape1"); if (sh != -1) { int idx = f->used_vars().get_idx(sh); const fityk::Variable* shape = ftk->mgr.get_variable(idx); if (!shape->is_simple() || shape->name == "pd_a") { string formula = shape->get_formula(ftk->mgr.parameters()); bool has_div = contains_element(formula, '/'); shape_rb->SetSelection(has_div ? 2 : 1); } } } var2lockctrl("pd_u", par_u); var2lockctrl("pd_v", par_v); var2lockctrl("pd_w", par_w); var2lockctrl("pd_z", par_z); var2lockctrl("pd_a", par_a); var2lockctrl("pd_b", par_b); var2lockctrl("pd_c", par_c); } #endif //!STANDALONE_POWDIFPAT wxPanel* PowderBook::PrepareSizeStrainPanel() { wxPanel *panel = new wxPanel(this); wxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxTextCtrl *txt = new wxTextCtrl(panel, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_RICH|wxTE_READONLY|wxTE_MULTILINE); txt->SetBackgroundColour(GetBackgroundColour()); txt->ChangeValue(wxT("It should be easy to put here simple size-strain analysis, like Williamson-Hall. But first we'd like to handle somehow instrumental broadening.")); sizer->Add(txt, wxSizerFlags(1).Expand().Border()); panel->SetSizerAndFit(sizer); return panel; } #if STANDALONE_POWDIFPAT void PowderBook::OnFilePicked(wxFileDirPickerEvent& event) { set_file(event.GetPath()); } void PowderBook::set_file(wxString const& path) { try { delete data; data = xylib::load_file(wx2s(path)); xylib::Block const *block = data->get_block(0); xylib::Column const& xcol = block->get_column(1); xylib::Column const& ycol = block->get_column(2); x_min = xcol.get_min(); x_max = xcol.get_max(block->get_point_count()); y_max = ycol.get_max(block->get_point_count()); range_from->set(x_min); range_to->set(x_max); for (size_t i = 0; i < sample_nb->GetPageCount(); ++i) get_phase_panel(i)->sample_plot_->refresh(); } catch (runtime_error const& e) { data = NULL; wxMessageBox(wxT("Can not load file:\n") + s2wx(e.what()), wxT("Error"), wxICON_ERROR); } } #endif void PowderBook::OnXAxisSelected(wxCommandEvent&) { bool use_wavelength = (xaxis_rb->GetSelection() == 0); wave_panel->Enable(use_wavelength); } void PowderBook::OnAnodeSelected(wxCommandEvent& event) { int n = event.GetSelection(); if (n < 0) return; // clear controls for (size_t i = 0; i < lambda_ctrl.size(); ++i) lambda_ctrl[i]->Clear(); for (size_t i = 1; i < intensity_ctrl.size(); ++i) intensity_ctrl[i]->Clear(); // set new value wxString s = anode_lb->GetString(n); for (Anode const* i = anodes; i->name; ++i) { if (s.StartsWith(pchar2wx(i->name))) { double a1 = 0, a2 = 0; if (s.EndsWith(wxT("A12"))) { a1 = i->alpha1; a2 = i->alpha2; } else if (s.EndsWith(wxT("A1"))) { a1 = i->alpha1; } else a1 = (2 * i->alpha1 + i->alpha2) / 3.; lambda_ctrl[0]->set_value(a1); if (a2 != 0) { lambda_ctrl[1]->set_value(a2); intensity_ctrl[1]->set_value(50); } } } } void PowderBook::OnQuickPhaseSelected(wxCommandEvent& event) { int n = event.GetSelection(); if (n < 0) return; string name = wx2s(saved_phase_lb->GetString(n)); CelFile const& cel = quick_phase_list[name]; PhasePanel *panel = get_current_phase_panel(); assert(panel->GetParent() == sample_nb); panel->set_phase(name, cel); panel->save_btn->Enable(false); panel->sample_plot_->refresh(); } void PowderBook::OnQuickListRemove(wxCommandEvent&) { int n = saved_phase_lb->GetSelection(); if (n < 0) return; string name = wx2s(saved_phase_lb->GetString(n)); assert(saved_phase_lb->GetCount() == quick_phase_list.size()); saved_phase_lb->SetSelection(wxNOT_FOUND); saved_phase_lb->Delete(n); quick_phase_list.erase(name); } void PowderBook::OnQuickListImport(wxCommandEvent&) { wxFileDialog dlg (this, wxT("Import CIF or CEL files"), wxT(""), wxT(""), wxT("all supported files|*.cif;*.CIF;*.cel;*.CEL|") wxT("CIF files (*.cif)|*.cif;*.CIF|") wxT("PowderCell files (*.cel)|*.cel;*.CEL"), wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST); if (dlg.ShowModal() != wxID_OK) return; wxArrayString paths; dlg.GetPaths(paths); for (size_t i = 0; i != paths.GetCount(); ++i) { wxFileName fn(paths[i]); wxString name = fn.GetName(); wxString ext = fn.GetExt(); if (saved_phase_lb->FindString(name) != wxNOT_FOUND) { int answer = wxMessageBox(wxT("Name `") + name + wxT("' already exists.\nOverwrite?"), wxT("Overwrite?"), wxYES_NO|wxICON_QUESTION); if (answer != wxYES) continue;; } if (ext == wxT("cif") || ext == wxT("CIF")) { wxMessageBox(wxT("Support for CIF files is not ready yet."), wxT("Sorry."), wxOK|wxICON_ERROR); continue; } else { FILE *f = wxFopen(paths[i], wxT("r")); if (f) { CelFile cel = read_cel_file(f); fclose(f); if (cel.sgs != NULL) quick_phase_list[wx2s(name)] = cel; } } saved_phase_lb->Append(name); } } void PowderBook::OnLambdaChange(wxCommandEvent&) { anode_lb->SetSelection(wxNOT_FOUND); } void PowderBook::OnPageChanged(wxBookCtrlEvent& event) { if (event.GetSelection() == 2) { // sample for (size_t i = 0; i != sample_nb->GetPageCount(); ++i) { PhasePanel* p = get_phase_panel(i); p->update_miller_indices(false); p->sample_plot_->refresh(); } } else if (event.GetSelection() == 4) { // action #if !STANDALONE_POWDIFPAT action_txt->SetValue(prepare_commands()); #endif } } PhasePanel *PowderBook::get_phase_panel(int n) { return static_cast(sample_nb->GetPage(n)); } PhasePanel *PowderBook::get_current_phase_panel() { return static_cast(sample_nb->GetCurrentPage()); } void PowderBook::deselect_phase_quick_list() { saved_phase_lb->SetSelection(wxNOT_FOUND); PhasePanel *panel = get_current_phase_panel(); bool valid = !panel->name_tc->GetValue().empty(); panel->save_btn->Enable(valid); } RadiationType PowderBook::get_radiation_type() const { if (radiation_rb->GetSelection() == 0) return kXRay; else return kNeutron; } double PowderBook::get_lambda(int n) const { if (n < 0 || n >= (int) lambda_ctrl.size()) return 0; if (xaxis_rb->GetSelection() != 0) return 0.; return lambda_ctrl[n]->get_value(); } double PowderBook::d2x(double d) const { int xaxis_val = xaxis_rb->GetSelection(); if (xaxis_val == 0) { // 2T double lambda0 = lambda_ctrl[0]->get_value(); return 180 / M_PI * 2 * asin(lambda0 / (2 * d)); } else if (xaxis_val == 1) // Q return 2 * M_PI / d; else if (xaxis_val == 2) // d return d; return 0.; } bool PowderBook::is_d_active(double d) const { #if !STANDALONE_POWDIFPAT double x = d2x(d); vector::const_iterator point = data->get_point_at(x); return point != data->points().end() && point->is_active; #else return true; #endif } double PowderBook::get_min_d() const { int xaxis_val = xaxis_rb->GetSelection(); if (xaxis_val == 0) // 2T return get_lambda(0) / (2 * sin(x_max * M_PI / 180 / 2.)); else if (xaxis_val == 1) // Q return 2 * M_PI / x_max; else if (xaxis_val == 2) // d return x_min; return 0; } void PowderBook::OnPeakRadio(wxCommandEvent& event) { // enable/disable peak and shape radiobuttons int sel = event.GetSelection(); bool has_shape = (sel > 1); // not Gaussian/Lorentzian shape_rb->Enable(has_shape); update_peak_parameters(); } void PowderBook::OnPeakSplit(wxCommandEvent& event) { // Split-* functions don't have width/shape set as f(2T) now. // This could be implemented (two sets of parameters - for left and right). bool is_split = event.IsChecked(); if (is_split && width_rb->GetSelection() == 1 /*f(2T)*/) width_rb->SetSelection(0); width_rb->Enable(1, !is_split); if (shape_rb->IsEnabled()) { if (is_split && shape_rb->GetSelection() >= 1 /*f(2T)*/) shape_rb->SetSelection(0); shape_rb->Enable(1, !is_split); shape_rb->Enable(2, !is_split); } } void PowderBook::OnWidthRadio(wxCommandEvent&) { update_peak_parameters(); } void PowderBook::OnShapeRadio(wxCommandEvent&) { update_peak_parameters(); } void PowderBook::update_peak_parameters() { bool has_shape = shape_rb->IsEnabled(); par_a->Enable(has_shape); par_b->Enable(has_shape); par_c->Enable(has_shape); } // update wxNoteBook page labels: set the current page name to be the same // as the name in wxTextCtrl, make sure there is always one empty page. void PowderBook::update_phase_labels(PhasePanel* p, int active) { wxString name = p->name_tc->GetValue(); bool valid = !name.empty(); int last = sample_nb->GetPageCount() - 1; if (active == -1) active = sample_nb->GetSelection(); wxString empty_label = wxT("+"); bool last_empty = (sample_nb->GetPageText(last) == empty_label); sample_nb->SetPageText(active, valid ? name : empty_label); if (valid) { bool has_empty = false; for (size_t i = 0; i < sample_nb->GetPageCount(); ++i) if (sample_nb->GetPageText(last) == empty_label) { has_empty = true; break; } if (!has_empty) { PhasePanel *page = new PhasePanel(sample_nb, this); sample_nb->AddPage(page, wxT("+")); } } else if (active != last && last_empty) { sample_nb->DeletePage(last); } } #if !STANDALONE_POWDIFPAT void PowderBook::OnDelButton(wxCommandEvent&) { exec("delete %pd*, $pd*"); } void PowderBook::OnOk(wxCommandEvent&) { wxString script = action_txt->GetValue(); ftk->ui()->exec_string_as_script(script.mb_str()); save_phase_desc(); wxDialog* dialog = static_cast(GetParent()); dialog->EndModal(wxID_OK); // unlike exec(), exec_string_as_script() does not call after_cmd_updates() frame->after_cmd_updates(); } #endif void PowderBook::save_phase_desc() { xaxis_sel = xaxis_rb->GetSelection(); int n = (int) sample_nb->GetPageCount() - 1; phase_desc.resize(n); for (int i = 0; i < n; ++i) { const PhasePanel* p = get_phase_panel(i); phase_desc[i].name = p->name_tc->GetValue(); phase_desc[i].sg = p->sg_tc->GetValue(); phase_desc[i].atoms = p->atoms_tc->GetValue(); } } #if STANDALONE_POWDIFPAT #include #include "img/powdifpat16.xpm" #include "img/powdifpat48.xpm" class App : public wxApp { public: wxString version; bool OnInit(); void OnAbout(wxCommandEvent&); void OnClose(wxCommandEvent&) { GetTopWindow()->Close(); } }; IMPLEMENT_APP(App) static const wxCmdLineEntryDesc cmdLineDesc[] = { #if wxCHECK_VERSION(2, 9, 0) { wxCMD_LINE_SWITCH, "V", "version", "output version information and exit", wxCMD_LINE_VAL_NONE, 0 }, { wxCMD_LINE_PARAM, 0, 0, "data file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, #else { wxCMD_LINE_SWITCH, wxT("V"), wxT("version"), wxT("output version information and exit"), wxCMD_LINE_VAL_NONE, 0 }, { wxCMD_LINE_PARAM, 0, 0, wxT("data file"), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, #endif { wxCMD_LINE_NONE, 0, 0, 0, wxCMD_LINE_VAL_NONE, 0 } }; bool App::OnInit() { version = wxT("0.1.0"); // write numbers in C locale setlocale(LC_NUMERIC, "C"); SetAppName(wxT("powdifpat")); // parse command line parameters wxCmdLineParser cmdLineParser(cmdLineDesc, argc, argv); if (cmdLineParser.Parse(false) != 0) { cmdLineParser.Usage(); return false; } if (cmdLineParser.Found(wxT("V"))) { wxMessageOutput::Get()->Printf(wxT("powdifpat ") + version + wxT("\n")); return false; } wxImage::AddHandler(new wxPNGHandler); wxFrame *frame = new wxFrame(NULL, wxID_ANY, GetAppName()); #ifdef __WXMSW__ frame->SetIcon(wxIcon(wxT("powdifpat"))); // load from a resource #else wxIconBundle ib; ib.AddIcon(wxIcon(powdifpat48_xpm)); ib.AddIcon(wxIcon(powdifpat16_xpm)); frame->SetIcons(ib); #endif wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); PowderBook *pb = new PowderBook(frame, wxID_ANY); sizer->Add(pb, wxSizerFlags(1).Expand()); wxBoxSizer *btn_sizer = new wxBoxSizer(wxHORIZONTAL); wxButton *about = new wxButton(frame, wxID_ABOUT); wxButton *close = new wxButton(frame, wxID_CLOSE); btn_sizer->Add(about, wxSizerFlags().Border()); btn_sizer->AddStretchSpacer(); btn_sizer->Add(close, wxSizerFlags().Border()); sizer->Add(btn_sizer, wxSizerFlags().Expand().Border()); frame->SetSizerAndFit(sizer); // wxMSW bug workaround frame->SetBackgroundColour(pb->GetBackgroundColour()); if (cmdLineParser.GetParamCount() == 1) { wxString path = cmdLineParser.GetParam(0); pb->set_file(path); pb->file_picker->SetPath(path); } frame->Show(); Connect(about->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(App::OnAbout)); Connect(close->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(App::OnClose)); return true; } void App::OnAbout(wxCommandEvent&) { wxAboutDialogInfo adi; adi.SetVersion(version); wxString desc = wxT("Powder diffraction pattern generator.\n"); adi.SetDescription(desc); adi.SetWebSite(wxT("http://www.unipress.waw.pl/fityk/powdifpat/")); adi.SetCopyright(wxT("(C) 2008 - 2011 Marcin Wojdyr ")); wxAboutBox(adi); } #else PowderDiffractionDlg::PowderDiffractionDlg(wxWindow* parent, wxWindowID id) : wxDialog(parent, id, wxT("powder diffraction analysis"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); PowderBook *pb = new PowderBook(this, wxID_ANY); sizer->Add(pb, wxSizerFlags(1).Expand()); SetSizerAndFit(sizer); if (GetClientSize().GetHeight() < 440) #ifdef __WXMAC__ SetClientSize(-1, 520); #else SetClientSize(-1, 440); #endif } #endif fityk-1.3.1/wxgui/powdifpat.h000066400000000000000000000071711302634723100161620ustar00rootroot00000000000000// Author: Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// A tool for creating models for powder diffraction patterns (Pawley method) #ifndef FITYK_WX_POWDIFPAT_H_ #define FITYK_WX_POWDIFPAT_H_ #include #include #include #include #include "ceria.h" #ifndef STANDALONE_POWDIFPAT #define STANDALONE_POWDIFPAT 0 // disable warnings (-Wundef) #endif #if STANDALONE_POWDIFPAT # include # include #else namespace fityk { class Data; } #endif class LockableRealCtrl; class PhasePanel; class RealNumberCtrl; class PowderBook : public wxToolbook { friend class PlotWithLines; #if STANDALONE_POWDIFPAT friend class App; #endif public: static const int max_wavelengths = 5; std::map quick_phase_list; PowderBook(wxWindow* parent, wxWindowID id); PhasePanel *get_phase_panel(int n); PhasePanel *get_current_phase_panel(); void deselect_phase_quick_list(); RadiationType get_radiation_type() const; double get_lambda(int n) const; double get_min_d() const; double d2x(double d) const; bool is_d_active(double d) const; wxListBox *get_saved_phase_lb() { return saved_phase_lb; } void update_phase_labels(PhasePanel* p, int active=-1); double get_x_min() const { return x_min; } double get_x_max() const { return x_max; } #if STANDALONE_POWDIFPAT void OnFilePicked(wxFileDirPickerEvent& event); void set_file(wxString const& path); #endif private: // used to store extra phase data (i.e. data not stored in variables) struct PhasePanelExtraData { wxString name; wxString sg; wxString atoms; }; static int xaxis_sel; static std::vector phase_desc; wxPanel *wave_panel; wxListBox *anode_lb, *saved_phase_lb; std::vector lambda_ctrl, intensity_ctrl, corr_ctrl; wxNotebook *sample_nb; double x_min, x_max, y_max; #if STANDALONE_POWDIFPAT wxFilePickerCtrl *file_picker; RealNumberCtrl *range_from, *range_to; const xylib::DataSet* data; #else const fityk::Data* data; #endif wxRadioBox *radiation_rb, *xaxis_rb; wxRadioBox *peak_rb, *center_rb, *width_rb, *shape_rb; wxCheckBox *split_cb; wxTextCtrl *peak_txt; LockableRealCtrl *par_u, *par_v, *par_w, *par_z, *par_a, *par_b, *par_c; wxTextCtrl *action_txt; wxPanel* PrepareIntroPanel(); wxPanel* PrepareInstrumentPanel(); wxPanel* PrepareSamplePanel(); wxPanel* PreparePeakPanel(); wxPanel* PrepareActionPanel(); wxPanel* PrepareSizeStrainPanel(); void initialize_quick_phase_list(); void update_peak_parameters(); wxString prepare_commands(); void fill_forms(); wxString get_peak_name() const; void set_peak_name(const std::string& name); void save_phase_desc(); void OnXAxisSelected(wxCommandEvent& event); void OnAnodeSelected(wxCommandEvent& event); void OnQuickPhaseSelected(wxCommandEvent& event); void OnQuickListRemove(wxCommandEvent&); void OnQuickListImport(wxCommandEvent&); void OnLambdaChange(wxCommandEvent& event); void OnPageChanged(wxBookCtrlEvent& event); void OnPeakRadio(wxCommandEvent& event); void OnPeakSplit(wxCommandEvent& event); void OnWidthRadio(wxCommandEvent& event); void OnShapeRadio(wxCommandEvent& event); void OnDelButton(wxCommandEvent&); void OnOk(wxCommandEvent&); }; #if !STANDALONE_POWDIFPAT class PowderDiffractionDlg : public wxDialog { public: PowderDiffractionDlg(wxWindow* parent, wxWindowID id); }; #endif // STANDALONE_POWDIFPAT #endif // FITYK_WX_POWDIFPAT_H_ fityk-1.3.1/wxgui/powdifpat.rc000066400000000000000000000003021302634723100163240ustar00rootroot00000000000000// This file is used only on MS Windows platform. // It can be compiled by windres // wxWidgets resource definitions #include "wx/msw/wx.rc" // program icon powdifpat ICON "img/powdifpat.ico" fityk-1.3.1/wxgui/print.cpp000066400000000000000000000237511302634723100156560ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// printing #include #include #include #include "print.h" #include "cmn.h" #include "plotpane.h" #include "plot.h" #include "mplot.h" #include "aplot.h" using namespace std; //====================================================================== // PageSetupDialog //====================================================================== BEGIN_EVENT_TABLE(PageSetupDialog, wxDialog) EVT_BUTTON(wxID_PRINT, PageSetupDialog::OnApply) EVT_BUTTON(wxID_APPLY, PageSetupDialog::OnApply) END_EVENT_TABLE() PageSetupDialog::PageSetupDialog(wxWindow *parent, PrintManager *print_mgr) : wxDialog(parent, -1, wxT("Page Setup"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), pm(print_mgr) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); // orientation wxString orient_choices[] = { wxT("Portrait"), wxT("Landscape") }; orientation_rb = new wxRadioBox(this, -1, wxT("Orientation"), wxDefaultPosition, wxDefaultSize, 2, orient_choices, 2, wxRA_SPECIFY_COLS); top_sizer->Add(orientation_rb, 0, wxALL|wxEXPAND, 5); wxStaticBoxSizer *hsizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Margins (mm)")); wxBoxSizer *m1sizer = new wxBoxSizer(wxHORIZONTAL); m1sizer->Add(new wxStaticText(this, -1, "Top"), 0, wxALIGN_CENTER_VERTICAL); top_margin_sc = new SpinCtrl(this, -1, 0, -100, 500); m1sizer->Add(top_margin_sc, 0, wxALL, 5); hsizer->Add(m1sizer, 0, wxALIGN_CENTER|wxRIGHT, 15); wxBoxSizer *m2sizer = new wxBoxSizer(wxHORIZONTAL); m2sizer->Add(new wxStaticText(this, -1, "Left"), 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5); left_margin_sc = new SpinCtrl(this, -1, 0, -100, 500); m2sizer->Add(left_margin_sc, 0, wxLEFT, 5); m2sizer->AddStretchSpacer(); m2sizer->Add(new wxStaticText(this, -1, "Right"), 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT); right_margin_sc = new SpinCtrl(this, -1, 0, -100, 500); m2sizer->Add(right_margin_sc, 0, wxLEFT|wxRIGHT|wxALIGN_RIGHT, 5); hsizer->Add(m2sizer, 0, wxEXPAND); wxBoxSizer *m3sizer = new wxBoxSizer(wxHORIZONTAL); m3sizer->Add(new wxStaticText(this, -1, "Bottom"), 0, wxALIGN_CENTER_VERTICAL); bottom_margin_sc = new SpinCtrl(this, -1, 0, -100, 500); m3sizer->Add(bottom_margin_sc, 0, wxALL, 5); hsizer->Add(m3sizer, 0, wxALIGN_CENTER|wxRIGHT, 30); top_sizer->Add(hsizer, 0, wxALL|wxEXPAND, 5); wxString color_choices[] = { wxT("black lines on white background"), wxT("colors from plots on white background") }; colors_rb = new wxRadioBox(this, -1, wxT("Colors"), wxDefaultPosition, wxDefaultSize, 2, color_choices, 1, wxRA_SPECIFY_COLS); top_sizer->Add(colors_rb, 0, wxALL|wxEXPAND, 5); wxStaticBoxSizer *boxsizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Optional elements")); for (int i = 0; i < 2; ++i) { plot_aux_cb[i] = new wxCheckBox(this, -1, wxString::Format(wxT("auxiliary plot %i"), i)); boxsizer->Add(plot_aux_cb[i], 0, wxLEFT|wxTOP, 5); } plot_borders_cb = new wxCheckBox(this, -1, wxT("line between plots")); boxsizer->Add(plot_borders_cb, 0, wxALL, 5); top_sizer->Add(boxsizer, 0, wxALL|wxEXPAND, 5); top_sizer->Add (new wxStaticLine(this, -1), 0, wxEXPAND|wxLEFT|wxRIGHT, 5); wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL); wxButton *print_btn = new wxButton(this, wxID_PRINT); print_btn->SetToolTip("Apply & Print"); button_sizer->Add(print_btn, 0, wxALL, 5); button_sizer->AddStretchSpacer(); wxButton *apply_btn = new wxButton(this, wxID_APPLY); apply_btn->SetToolTip("Apply & Close"); button_sizer->Add(apply_btn, 0, wxALL, 5); button_sizer->Add(new wxButton(this, wxID_CANCEL), 0, wxTOP|wxRIGHT, 5); top_sizer->Add(button_sizer, 0, wxALL|wxEXPAND, 5); SetSizerAndFit(top_sizer); bool landscape = pm->print_data.GetOrientation() == wxLANDSCAPE; orientation_rb->SetSelection(landscape ? 1 : 0); colors_rb->SetSelection(pm->colors ? 1 : 0); for (int i = 0; i < 2; ++i) { if (pm->plot_pane->aux_visible(i)) { plot_aux_cb[i]->SetValue(pm->plot_aux[i]); } else { plot_aux_cb[i]->SetValue(false); plot_aux_cb[i]->Enable(false); } } plot_borders_cb->SetValue(pm->plot_borders); left_margin_sc->SetValue(pm->margin_left); right_margin_sc->SetValue(pm->margin_right); top_margin_sc->SetValue(pm->margin_top); bottom_margin_sc->SetValue(pm->margin_bottom); } void PageSetupDialog::OnApply(wxCommandEvent& event) { bool landscape = (orientation_rb->GetSelection() == 1); pm->print_data.SetOrientation(landscape ? wxLANDSCAPE : wxPORTRAIT); pm->colors = colors_rb->GetSelection() == 1; for (int i = 0; i < 2; ++i) pm->plot_aux[i] = plot_aux_cb[i]->GetValue(); pm->plot_borders = plot_borders_cb->GetValue(); pm->margin_left = left_margin_sc->GetValue(); pm->margin_right = right_margin_sc->GetValue(); pm->margin_top = top_margin_sc->GetValue(); pm->margin_bottom = bottom_margin_sc->GetValue(); EndModal(event.GetId()); } //=============================================================== // Printing utilities //=============================================================== bool FPrintout::OnPrintPage(int page) { if (page != 1) return false; wxDC *dc = GetDC(); if (!dc) return false; // respect margins wxCoord wmm, hmm; GetPageSizeMM(&wmm, &hmm); wxCoord wp, hp; GetPageSizePixels(&wp, &hp); float mmToDeviceX = float(wp) / wmm; float mmToDeviceY = float(hp) / hmm; dc->SetDeviceOrigin(pm_->margin_left * mmToDeviceX, pm_->margin_top * mmToDeviceY); dc->SetUserScale(float(wmm - pm_->margin_left - pm_->margin_right) / wmm, float(hmm - pm_->margin_top - pm_->margin_bottom) / hmm); const int space = 10; // vertical space between plots (in screen units) // `pp' is a list of plots that are to be printed. // PlotPane::get_visible_plots() can't be used, because aux plots can be // disabled in print setup. vector pp; pp.push_back(pm_->plot_pane->get_plot()); for (int i = 0; i < 2; ++i) if (pm_->plot_pane->aux_visible(i) && pm_->plot_aux[i]) pp.push_back(pm_->plot_pane->get_aux_plot(i)); // width is the same for all plots int W = pm_->plot_pane->GetClientSize().GetWidth(); // height is a sum of all heights + (N-1)*space int H = (pp.size() - 1) * space; for (vector::const_iterator i = pp.begin(); i != pp.end(); ++i) H += (*i)->GetClientSize().GetHeight(); int w, h; // size in DC units dc->GetSize(&w, &h); double y_scale = (float) h / H; // drawing plots, every at different posY for (vector::const_iterator i = pp.begin(); i != pp.end(); ++i) { if (pm_->plot_borders && i != pp.begin()) { int Y = iround(-0.5 * space * y_scale); dc->SetPen(*wxLIGHT_GREY_PEN); dc->DrawLine(0, Y, w, Y); } int plot_height = iround((*i)->GetClientSize().GetHeight() * y_scale); dc->SetClippingRegion(0, 0, w, plot_height); //dc->SetBrush(*wxGREEN_BRUSH); // for debugging //dc->DrawEllipse(0, 0, w, plot_height); // for debugging (*i)->set_magnification(w / W + 1); // +1 for no special reason (*i)->draw(*dc, !pm_->colors); // <- 99% of plotting is done here (*i)->set_magnification(1); dc->DestroyClippingRegion(); OffsetLogicalOrigin(0, plot_height + space * y_scale); } return true; } //=============================================================== PrintManager::PrintManager(PlotPane* pane) : plot_pane(pane) { read_settings(wxConfig::Get()); } PrintManager::~PrintManager() { save_settings(wxConfig::Get()); } void PrintManager::save_settings(wxConfigBase *cf) const { cf->Write(wxT("/print/colors"), colors); cf->Write(wxT("/print/plotBorders"), plot_borders); for (int i = 0; i < 2; ++i) cf->Write(wxString::Format(wxT("/print/plotAux%i"), i), plot_aux[i]); bool landscape = print_data.GetOrientation() == wxLANDSCAPE; cf->Write(wxT("/print/landscape"), landscape); } void PrintManager::read_settings(wxConfigBase *cf) { colors = cfg_read_bool(cf, wxT("/print/colors"), false); plot_borders = cfg_read_bool(cf, wxT("/print/plotBorders"), true); for (int i = 0; i < 2; ++i) plot_aux[i] = cfg_read_bool(cf, wxString::Format(wxT("/print/plotAux%i"), i), true); #if defined(__WXGTK__) && !wxCHECK_VERSION(2, 9, 5) // gtk-printing landscape mode has been fixed in r72646 bool landscape = false; #else bool landscape = cfg_read_bool(cf, wxT("/print/landscape"), true); #endif print_data.SetOrientation(landscape ? wxLANDSCAPE : wxPORTRAIT); margin_left = margin_right = margin_top = margin_bottom = 20; } void PrintManager::print() { wxPrintDialogData print_dialog_data(print_data); print_dialog_data.SetFromPage(1); print_dialog_data.SetToPage(1); print_dialog_data.EnablePageNumbers(false); print_dialog_data.EnableSelection(false); wxPrinter printer (&print_dialog_data); FPrintout printout(this); bool r = printer.Print(plot_pane, &printout, true); if (r) { print_data = printer.GetPrintDialogData().GetPrintData(); } else if (wxPrinter::GetLastError() == wxPRINTER_ERROR) wxMessageBox("Printer Error.", "Printing", wxICON_ERROR|wxCANCEL); } fityk-1.3.1/wxgui/print.h000066400000000000000000000027531302634723100153220ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_PRINT_H_ #define FITYK_WX_PRINT_H_ #include #include class PlotPane; class SpinCtrl; // it can be confusing how the code is split into classes here, // but let's leave it as it is class PrintManager { public: bool colors; bool plot_aux[2], plot_borders; int margin_left, margin_right, margin_top, margin_bottom; PlotPane* plot_pane; wxPrintData print_data; PrintManager(PlotPane* pane); ~PrintManager(); void print(); void save_settings(wxConfigBase *cf) const; void read_settings(wxConfigBase *cf); }; class PageSetupDialog: public wxDialog { public: PageSetupDialog(wxWindow *parent, PrintManager *print_mgr); void OnApply(wxCommandEvent& event); private: PrintManager *pm; wxRadioBox *orientation_rb, *colors_rb; wxCheckBox *plot_aux_cb[2], *plot_borders_cb; SpinCtrl *left_margin_sc, *right_margin_sc, *top_margin_sc, *bottom_margin_sc; DECLARE_EVENT_TABLE() }; class FPrintout: public wxPrintout { public: FPrintout(PrintManager const* pm) : wxPrintout("fityk"), pm_(pm) {} bool HasPage(int page) { return (page == 1); } bool OnPrintPage(int page); void GetPageInfo(int *minPage,int *maxPage,int *selPageFrom,int *selPageTo) { *minPage = *maxPage = *selPageFrom = *selPageTo = 1; } private: PrintManager const* pm_; }; #endif fityk-1.3.1/wxgui/recent.cpp000066400000000000000000000063031302634723100157740ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2014 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include "recent.h" using std::list; using std::string; static const int MAX_NUMBER_OF_ITEMS = 15; static const char* MAGIC_SEP = " "; void RecentFiles::load_from_config(wxConfigBase *c) { items_.clear(); if (menu_ != NULL) delete menu_; menu_ = new wxMenu; if (c && c->HasGroup(config_group_)) { // gaps shouldn't happend in the config file, but just in case... int counter = 0; for (int i = 0; i < MAX_NUMBER_OF_ITEMS; i++) { wxString key = wxString::Format("%s/%i", config_group_, i); if (c->HasEntry(key)) { wxString value = c->Read(key, wxT("")); if (value.empty()) // it should not normally happen continue; int id = first_item_id_ + counter; ++counter; wxString opt; string::size_type sep = value.find(MAGIC_SEP); if (sep != string::npos) { opt = value.substr(sep+3); value.resize(sep); } wxFileName fn(value); Item item = { id, fn, opt }; items_.push_back(item); wxString hint = fn.GetFullPath(); if (!opt.empty()) hint += " " + opt; menu_->Append(id, fn.GetFullName(), hint); } } } } void RecentFiles::save_to_config(wxConfigBase *c) { if (!c) return; if (c->HasGroup(config_group_)) c->DeleteGroup(config_group_); int counter = 0; for (list::const_iterator i = items_.begin(); i != items_.end(); ++i){ wxString key = wxString::Format("%s/%i", config_group_, counter); counter++; wxString value = i->fn.GetFullPath(); if (!i->options.empty()) value += MAGIC_SEP + i->options; c->Write(key, value); } } void RecentFiles::add(const wxString& path, const wxString& options) { assert(menu_ != NULL); const wxFileName fn = wxFileName(path); // avoid duplicates for (list::iterator it = items_.begin(); it != items_.end(); ++it) { if (it->fn == fn && it->options == options) { pull(it->id); return; } } int id; if (items_.size() < (size_t) MAX_NUMBER_OF_ITEMS) { id = first_item_id_ + items_.size(); } else { id = items_.back().id; items_.pop_back(); menu_->Destroy(id); } Item item = { id, fn, options }; items_.push_front(item); wxString hint = fn.GetFullPath(); if (!options.empty()) hint += " " + options; menu_->Prepend(id, fn.GetFullName(), hint); } const RecentFiles::Item& RecentFiles::pull(int id) { for (list::iterator it = items_.begin(); it != items_.end(); ++it) { if (it->id == id) { if (it != items_.begin()) { items_.push_front(*it); // it does not invalidate iterator items_.erase(it); menu_->Prepend(menu_->Remove(id)); } break; } } return items_.front(); } fityk-1.3.1/wxgui/recent.h000066400000000000000000000017371302634723100154470ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2014 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Recent Files - for use in menu #ifndef FITYK_WX_RECENT_H_ #define FITYK_WX_RECENT_H_ #include #include #include #include class RecentFiles { public: struct Item { int id; wxFileName fn; wxString options; }; RecentFiles(int first_item_id, const wxString& config_group) : first_item_id_(first_item_id), config_group_(config_group), menu_(NULL) {} void load_from_config(wxConfigBase *c); void save_to_config(wxConfigBase *c); wxMenu* menu() { return menu_; } void add(const wxString& path, const wxString& options); // moves the item to the top and returns file path const Item& pull(int id); private: const int first_item_id_; const wxString config_group_; std::list items_; wxMenu *menu_; }; #endif // FITYK_WX_RECENT_H_ fityk-1.3.1/wxgui/sample_inputline.cpp000066400000000000000000000020711302634723100200620ustar00rootroot00000000000000// InputLine sample, by Marcin Wojdyr, public domain #include #include "inputline.h" class Frame : public wxFrame, public InputLineObserver { public: Frame(); // implementation of InputLineObserver virtual void ProcessInputLine(const wxString& s) { m_output->AppendText(s + wxT("\n")); } private: InputLine* m_input; wxTextCtrl* m_output; }; class App : public wxApp { public: bool OnInit() { wxApp::OnInit(); Frame *frame = new Frame; frame->Show(true); return true; } }; IMPLEMENT_APP(App) Frame::Frame() : wxFrame(0, wxID_ANY, wxT("InputLine sample")) { wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); m_input = new InputLine(this, wxID_ANY, this, wxEmptyString); m_output = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY); sizer->Add(m_input, 0, wxEXPAND); sizer->Add(m_output, 1, wxEXPAND); SetSizerAndFit(sizer); m_input->SetFocus(); } fityk-1.3.1/wxgui/setdlg.cpp000066400000000000000000000351721302634723100160040ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Settings Dialog (SettingsDlg) #include #include #include #include #include #include "setdlg.h" #include "fityk/settings.h" #include "fityk/logic.h" // settings_mgr() #include "frame.h" //ftk using namespace std; namespace { RealNumberCtrl *addRealNumberCtrl(wxWindow *parent, const wxString& label, double value, wxSizer *sizer, int indentation=0, bool percent=false) { wxStaticText *st = new wxStaticText(parent, -1, label); RealNumberCtrl *ctrl = new RealNumberCtrl(parent, -1, value); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); if (indentation) hsizer->AddSpacer(indentation); hsizer->Add(st, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); hsizer->Add(ctrl, 0, wxALL, 5); if (percent) hsizer->Add(new wxStaticText(parent, -1, wxT("%")), 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5); sizer->Add(hsizer, 0, wxEXPAND); return ctrl; } wxTextCtrl *addTextCtrl(wxWindow *parent, const wxString& label, const string& value, wxSizer *sizer) { wxStaticText *st = new wxStaticText(parent, -1, label); wxTextCtrl *ctrl = new wxTextCtrl(parent, -1, s2wx(value)); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->Add(st, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); hsizer->Add(ctrl, 0, wxALL, 5); sizer->Add(hsizer, 0, wxEXPAND); return ctrl; } wxDirPickerCtrl *addDirPicker(wxWindow *parent, const wxString& label, const string& path, wxSizer *sizer) { wxStaticText *st = new wxStaticText(parent, -1, label); wxDirPickerCtrl *ctrl = new wxDirPickerCtrl(parent, -1, s2wx(path)); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->Add(st, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); hsizer->Add(ctrl, 0, wxALL, 5); sizer->Add(hsizer, 0, wxEXPAND); return ctrl; } wxCheckBox *addCheckbox(wxWindow *parent, const wxString& label, bool value, wxSizer *sizer, int indentation=0) { wxCheckBox *ctrl = new wxCheckBox(parent, -1, label); ctrl->SetValue(value); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); if (indentation) hsizer->AddSpacer(indentation); hsizer->Add(ctrl); sizer->Add(hsizer, 0, wxEXPAND|wxALL, 5); return ctrl; } wxChoice *addEnumSetting(wxWindow *parent, const wxString& label, const string& option, wxSizer* sizer, int indentation=0) { wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); if (indentation) hsizer->AddSpacer(indentation); wxStaticText *st = new wxStaticText(parent, -1, label); hsizer->Add(st, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); wxArrayString array; const char** values = fityk::SettingsMgr::get_allowed_values(option); while (*values != NULL) { array.Add(pchar2wx(*values)); ++values; } wxChoice *ctrl = new wxChoice(parent, -1, wxDefaultPosition, wxDefaultSize, array); ctrl->SetStringSelection(s2wx(ftk->settings_mgr()->get_as_string(option))); hsizer->Add(ctrl, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); sizer->Add(hsizer, 0, wxEXPAND); return ctrl; } SpinCtrl* addSpinCtrl(wxWindow *parent, const wxString& label, int value, int min_v, int max_v, wxSizer *sizer, int indentation=0) { wxStaticText *st = new wxStaticText(parent, -1, label); SpinCtrl *spin = new SpinCtrl(parent, -1, value, min_v, max_v, 70); wxBoxSizer *box = new wxBoxSizer(wxHORIZONTAL); if (indentation) box->AddSpacer(indentation); box->Add(st, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); box->Add(spin, 0, wxTOP|wxBOTTOM, 5); sizer->Add(box, 0, wxEXPAND); return spin; } wxStaticText* new_bold_text(wxWindow *parent, const wxString& label) { wxStaticText *fcterm = new wxStaticText(parent, -1, label); wxFont bold_font = fcterm->GetFont(); bold_font.SetWeight(wxFONTWEIGHT_BOLD); fcterm->SetFont(bold_font); return fcterm; } } //anonymous namespace SettingsDlg::SettingsDlg(wxWindow* parent) : wxDialog(parent, -1, wxT("Engine Settings"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { const fityk::Settings* settings = ftk->get_settings(); wxNotebook *nb = new wxNotebook(this, -1); wxPanel *page_general = new wxPanel(nb, -1); nb->AddPage(page_general, wxT("general")); wxPanel *page_peakfind = new wxPanel(nb, -1); nb->AddPage(page_peakfind, wxT("peak-finding")); wxNotebook *page_fitting = new wxNotebook(nb, -1); nb->AddPage(page_fitting, wxT("fitting")); // page general wxBoxSizer *sizer_general = new wxBoxSizer(wxVERTICAL); sigma_ch = addEnumSetting(page_general, wxT("default std. dev. of data y:"), "default_sigma", sizer_general); cut_func = addRealNumberCtrl(page_general, wxT("f(x) is negligible if |f(x)|<"), settings->function_cutoff, sizer_general); verbosity_sp = addSpinCtrl(page_general, wxT("verbosity level (in output pane)"), settings->verbosity, -1, 2, sizer_general); sigma_ch = addEnumSetting(page_general, wxT("default std. dev. of data y:"), "default_sigma", sizer_general); onerror_ch = addEnumSetting(page_general, "action on error", "on_error", sizer_general); seed_sp = addSpinCtrl(page_general, wxT("pseudo-random generator seed (0 = time-based)"), settings->pseudo_random_seed, 0, 999999, sizer_general); eps_rc = addRealNumberCtrl(page_general, wxT("epsilon for floating-point comparison"), settings->epsilon, sizer_general); format_tc = addTextCtrl(page_general, wxT("numeric format used by info/print"), settings->numeric_format, sizer_general); cwd_dp = addDirPicker(page_general, "working directory", settings->cwd, sizer_general); page_general->SetSizerAndFit(sizer_general); // page peak-finding wxBoxSizer *sizer_pf = new wxBoxSizer(wxVERTICAL); height_correction = addRealNumberCtrl(page_peakfind, wxT("factor used to correct detected peak height"), settings->height_correction, sizer_pf); width_correction = addRealNumberCtrl(page_peakfind, wxT("factor used to correct detected peak width"), settings->width_correction, sizer_pf); page_peakfind->SetSizerAndFit(sizer_pf); // page fitting wxPanel *page_fit_common = new wxPanel(page_fitting, -1); page_fitting->AddPage(page_fit_common, wxT("common")); wxPanel *page_fit_LM = new wxPanel(page_fitting, -1); page_fitting->AddPage(page_fit_LM, wxT("Lev-Mar")); wxPanel *page_fit_NM = new wxPanel(page_fitting, -1); page_fitting->AddPage(page_fit_NM, wxT("Nelder-Mead")); wxPanel *page_fit_GA = new wxPanel(page_fitting, -1); page_fitting->AddPage(page_fit_GA, wxT("GA")); // sub-page common wxBoxSizer *sizer_fcmn = new wxBoxSizer(wxVERTICAL); domain_p = addRealNumberCtrl(page_fit_common, wxT("default domain of variable is +/-"), settings->domain_percent, sizer_fcmn, 0, /*percent=*/true); fit_replot_cb = addCheckbox(page_fit_common, wxT("refresh plot after each iteration"), settings->fit_replot, sizer_fcmn); delay_sp = addSpinCtrl(page_fit_common, wxT("time (in sec.) between stats/plot updates"), settings->refresh_period, -1, 9999, sizer_fcmn); //wxStaticBoxSizer *sizer_fcstop = new wxStaticBoxSizer(wxHORIZONTAL, // page_fit_common, wxT("termination criteria")); sizer_fcmn->AddSpacer(10); sizer_fcmn->Add(new_bold_text(page_fit_common, wxT("termination criteria")), wxSizerFlags().Border()); mwssre_sp = addSpinCtrl(page_fit_common, wxT("max. WSSR evaluations"), settings->max_wssr_evaluations, 0, 999999, sizer_fcmn, 10); fit_max_time = addRealNumberCtrl(page_fit_common, wxT("max. fitting time"), settings->max_fitting_time, sizer_fcmn, 10); //sizer_fcmn->Add(sizer_fcstop, 0, wxEXPAND|wxALL, 5); page_fit_common->SetSizerAndFit(sizer_fcmn); // sub-page Lev-Mar wxBoxSizer *sizer_flm = new wxBoxSizer(wxVERTICAL); sizer_flm->Add(new_bold_text(page_fit_LM, wxT("lambda parameter")), wxSizerFlags().Border()); lm_lambda_ini = addRealNumberCtrl(page_fit_LM, wxT("initial value"), settings->lm_lambda_start, sizer_flm, 10); lm_lambda_up = addRealNumberCtrl(page_fit_LM, wxT("increasing factor"), settings->lm_lambda_up_factor, sizer_flm, 10); lm_lambda_down = addRealNumberCtrl(page_fit_LM, wxT("decreasing factor"), settings->lm_lambda_down_factor, sizer_flm, 10); sizer_flm->AddSpacer(10); sizer_flm->Add(new_bold_text(page_fit_LM, wxT("termination criteria")), wxSizerFlags().Border()); lm_stop = addRealNumberCtrl(page_fit_LM, wxT("WSSR relative change <"), settings->lm_stop_rel_change, sizer_flm, 10); lm_max_lambda = addRealNumberCtrl(page_fit_LM, wxT("max. value of lambda"), settings->lm_max_lambda, sizer_flm, 10); page_fit_LM->SetSizerAndFit(sizer_flm); // sub-page N-M wxBoxSizer *sizer_fnm = new wxBoxSizer(wxVERTICAL); sizer_fnm->Add(new_bold_text(page_fit_NM, wxT("simplex initialization")), wxSizerFlags().Border()); nm_move_all = addCheckbox(page_fit_NM, wxT("randomize all vertices (otherwise one is left)"), settings->nm_move_all, sizer_fnm, 10); nm_distrib = addEnumSetting(page_fit_NM, wxT("distribution type"), "nm_distribution", sizer_fnm, 10); nm_move_factor = addRealNumberCtrl(page_fit_NM, wxT("factor by which domain is expanded"), settings->nm_move_factor, sizer_fnm, 10); sizer_fnm->AddSpacer(10); sizer_fnm->Add(new_bold_text(page_fit_NM, wxT("termination criteria")), wxSizerFlags().Border()); nm_convergence = addRealNumberCtrl(page_fit_NM, wxT("relative difference between vertices"), settings->nm_convergence, sizer_fnm, 10); page_fit_NM->SetSizerAndFit(sizer_fnm); // TODO: sub-page GA //finish layout wxBoxSizer *top_sizer = new wxBoxSizer (wxVERTICAL); top_sizer->Add(nb, 1, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 10); #ifdef __WXMAC__ nb->SetMinSize(wxSize(-1, 300)); #endif wxStaticText *note = new SmallStaticText(this, wxT("These settings can be saved in the init script") wxT(" (Session \u2023 Edit Init File).") wxT("\nThe interface can be configured in GUI \u2023 Configure.")); top_sizer->Add(note, 0, wxALL|wxALIGN_CENTER, 10); top_sizer->Add (CreateButtonSizer (wxOK|wxCANCEL), 0, wxALL|wxALIGN_CENTER, 5); SetSizerAndFit(top_sizer); Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SettingsDlg::OnOK)); } static string add(const char* name, const string& new_value) { string old_value = ftk->settings_mgr()->get_as_string(name); if (old_value == new_value) return ""; return S(name) + " = " + new_value + ", "; } void SettingsDlg::exec_set_command() { string assign = "set "; assign += add("default_sigma", wx2s(sigma_ch->GetStringSelection())); assign += add("function_cutoff", wx2s(cut_func->GetValue())); assign += add("verbosity", S(verbosity_sp->GetValue())); assign += add("on_error", wx2s(onerror_ch->GetStringSelection())); assign += add("pseudo_random_seed", S(seed_sp->GetValue())); assign += add("epsilon", wx2s(eps_rc->GetValue())); assign += add("numeric_format", "'" + wx2s(format_tc->GetValue()) + "'"); assign += add("cwd", "'" + wx2s(cwd_dp->GetPath()) + "'"); assign += add("height_correction", wx2s(height_correction->GetValue())); assign += add("width_correction", wx2s(width_correction->GetValue())); assign += add("max_wssr_evaluations", S(mwssre_sp->GetValue())); assign += add("max_fitting_time", wx2s(fit_max_time->GetValue())); assign += add("domain_percent", wx2s(domain_p->GetValue())); assign += add("fit_replot", fit_replot_cb->GetValue() ? "1" : "0"); assign += add("refresh_period", S(delay_sp->GetValue())); assign += add("lm_lambda_start", wx2s(lm_lambda_ini->GetValue())); assign += add("lm_lambda_up_factor", wx2s(lm_lambda_up->GetValue())); assign += add("lm_lambda_down_factor", wx2s(lm_lambda_down->GetValue())); assign += add("lm_stop_rel_change", wx2s(lm_stop->GetValue())); assign += add("lm_max_lambda", wx2s(lm_max_lambda->GetValue())); assign += add("nm_move_all", nm_move_all->GetValue() ? "1" : "0"); assign += add("nm_distribution", wx2s(nm_distrib->GetStringSelection())); assign += add("nm_move_factor", wx2s(nm_move_factor->GetValue())); assign += add("nm_convergence", wx2s(nm_convergence->GetValue())); if (assign.size() == 4) // no options return; assign.resize(assign.size() - 2); exec(assign); } void SettingsDlg::OnOK(wxCommandEvent&) { exec_set_command(); EndModal(wxID_OK); } /* We used to have Directories tab in the Settings dialog, but probably the settings there were rarely useful and confusing, so it was removed. The settings are still read from .fityk/wxoption, and can be changed by editing the config file. The keys are: /loadDataDir - default directory for load-data dialogs /execScriptDir - default directory for execute-script dialogs /exportDir - default directory for export dialogs */ fityk-1.3.1/wxgui/setdlg.h000066400000000000000000000017071302634723100154460ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_SETDLG_H_ #define FITYK_WX_SETDLG_H_ #include #include #include #include "cmn.h" //s2wx, RealNumberCtrl class wxDirPickerCtrl; class SettingsDlg : public wxDialog { public: SettingsDlg(wxWindow* parent); void OnOK(wxCommandEvent& event); private: wxChoice *sigma_ch, *nm_distrib, *onerror_ch; wxSpinCtrl *delay_sp, *seed_sp, *mwssre_sp, *verbosity_sp; RealNumberCtrl *cut_func, *eps_rc, *height_correction, *width_correction, *domain_p, *fit_max_time, *lm_lambda_ini, *lm_lambda_up, *lm_lambda_down, *lm_stop, *lm_max_lambda, *nm_convergence, *nm_move_factor; wxCheckBox *nm_move_all, *fit_replot_cb; wxTextCtrl *format_tc; wxDirPickerCtrl *cwd_dp; void exec_set_command(); }; #endif fityk-1.3.1/wxgui/sgchooser.cpp000066400000000000000000000117731302634723100165170ustar00rootroot00000000000000// Author: Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include "sgchooser.h" #include #include #include "ceria.h" #include "cmn.h" using namespace std; SpaceGroupChooser::SpaceGroupChooser(wxWindow* parent, const wxString& initial_value) : wxDialog(parent, -1, wxT("Choose space group"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { wxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxSizer *ssizer = new wxBoxSizer(wxHORIZONTAL); ssizer->Add(new wxStaticText(this, -1, wxT("system:")), wxSizerFlags().Border().Center()); wxArrayString s_choices; s_choices.Add(wxT("All lattice systems")); for (int i = 2; i < 9; ++i) s_choices.Add(pchar2wx(CrystalSystemNames[i])); system_c = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, s_choices); system_c->SetSelection(0); ssizer->Add(system_c, wxSizerFlags(1).Border()); sizer->Add(ssizer, wxSizerFlags().Expand()); wxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); hsizer->Add(new wxStaticText(this, -1, wxT("centering:")), wxSizerFlags().Border().Center()); wxString letters = wxT("PABCIRF"); for (size_t i = 0; i < sizeof(centering_cb)/sizeof(centering_cb[0]); ++i) { centering_cb[i] = new wxCheckBox(this, -1, letters[i]); centering_cb[i]->SetValue(true); hsizer->Add(centering_cb[i], wxSizerFlags().Border()); } sizer->Add(hsizer); list = new wxListView(this, -1, wxDefaultPosition, wxSize(300, 500), wxLC_REPORT|wxLC_HRULES|wxLC_VRULES); list->InsertColumn(0, wxT("No")); list->InsertColumn(1, wxT("H-M symbol")); list->InsertColumn(2, wxT("Sch\u00F6nflies symbol")); list->InsertColumn(3, wxT("Hall symbol")); regenerate_list(initial_value); // set widths of columns int col_widths[4]; int total_width = 0; for (int i = 0; i < 4; i++) { list->SetColumnWidth(i, wxLIST_AUTOSIZE); col_widths[i] = list->GetColumnWidth(i); total_width += col_widths[i]; } // leave margin of 50 px for scrollbar int empty_width = GetClientSize().GetWidth() - total_width - 50; if (empty_width > 0) for (int i = 0; i < 4; i++) list->SetColumnWidth(i, col_widths[i] + empty_width / 4); sizer->Add(list, wxSizerFlags(1).Expand().Border()); sizer->Add(CreateButtonSizer(wxOK|wxCANCEL), wxSizerFlags().Expand()); SetSizerAndFit(sizer); for (size_t i = 0; i < sizeof(centering_cb)/sizeof(centering_cb[0]); ++i) Connect(centering_cb[i]->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, (wxObjectEventFunction) &SpaceGroupChooser::OnCheckBox); Connect(system_c->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, (wxObjectEventFunction) &SpaceGroupChooser::OnSystemChoice); //Connect(list->GetId(), wxEVT_COMMAND_LIST_ITEM_FOCUSED, // (wxObjectEventFunction) &SpaceGroupChooser::OnListItemFocused); Connect(list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, (wxObjectEventFunction) &SpaceGroupChooser::OnListItemActivated); } void SpaceGroupChooser::OnListItemActivated(wxCommandEvent&) { EndModal(wxID_OK); } void SpaceGroupChooser::regenerate_list(const wxString& sel_value) { list->DeleteAllItems(); int syst = system_c->GetSelection(); int sel_idx = -1; for (const SpaceGroupSetting* i = space_group_settings; i->sgnumber; ++i) { if (syst != 0 && get_crystal_system(i->sgnumber) != syst+1) continue; switch (i->HM[0]) { case 'P': if (!centering_cb[0]->IsChecked()) continue; break; case 'A': if (!centering_cb[1]->IsChecked()) continue; break; case 'B': if (!centering_cb[2]->IsChecked()) continue; break; case 'C': if (!centering_cb[3]->IsChecked()) continue; break; case 'I': if (!centering_cb[4]->IsChecked()) continue; break; case 'R': if (!centering_cb[5]->IsChecked()) continue; break; case 'F': if (!centering_cb[6]->IsChecked()) continue; break; default: assert(0); } int n = list->GetItemCount(); list->InsertItem(n, wxString::Format(wxT("%d"), i->sgnumber)); wxString hm = s2wx(fullHM(i)); list->SetItem(n, 1, hm); wxString schoen(SchoenfliesSymbolsAsUTF8[i->sgnumber-1], wxConvUTF8); list->SetItem(n, 2, schoen); list->SetItem(n, 3, pchar2wx(i->Hall)); if (hm == sel_value) sel_idx = n; } if (sel_idx != -1) { list->Select(sel_idx, true); list->EnsureVisible(sel_idx); } } wxString SpaceGroupChooser::get_value() const { int n = list->GetFirstSelected(); if (n < 0) return wxEmptyString; wxListItem info; info.SetId(n); info.SetColumn(1); info.SetMask(wxLIST_MASK_TEXT); list->GetItem(info); return info.GetText(); } fityk-1.3.1/wxgui/sgchooser.h000066400000000000000000000016231302634723100161550ustar00rootroot00000000000000// Author: Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// A dialog for choosing space group settings #ifndef FITYK_WX_SGCHOOSER_H_ #define FITYK_WX_SGCHOOSER_H_ #include class wxChoice; class wxListView; class wxCheckBox; class SpaceGroupChooser : public wxDialog { public: SpaceGroupChooser(wxWindow* parent, const wxString& initial_value); wxString get_value() const; private: wxChoice *system_c; wxListView *list; wxCheckBox *centering_cb[7]; void OnCheckBox(wxCommandEvent&) { regenerate_list(get_value()); } void OnSystemChoice(wxCommandEvent&) { regenerate_list(get_value()); } void OnListItemActivated(wxCommandEvent&); void regenerate_list(const wxString& sel_value); // disallow copy and assign SpaceGroupChooser(const SpaceGroupChooser&); void operator=(const SpaceGroupChooser&); }; #endif //FITYK_WX_SGCHOOSER_H_ fityk-1.3.1/wxgui/sgtables.c000066400000000000000000001665431302634723100157750ustar00rootroot00000000000000/* sgtables.c * Author: Marcin Wojdyr (only the code, not data) * Licence: GNU General Public License ver. 2+ */ #include "sgtables.h" #include #include const ThirdOfSeitzMx seitz_mx_codes[] = { /* generated by cctbx and listed below sm_dict.py */ /* 0 */ { "x" , 1, 0, 0, 0 }, /* 1 */ { "y" , 0, 1, 0, 0 }, /* 2 */ { "z" , 0, 0, 1, 0 }, /* 3 */ { "-x" , -1, 0, 0, 0 }, /* 4 */ { "-y" , 0,-1, 0, 0 }, /* 5 */ { "-z" , 0, 0,-1, 0 }, /* 6 */ { "x-y" , 1,-1, 0, 0 }, /* 7 */ { "-x+y" , -1, 1, 0, 0 }, /* 8 */ { "x+1/2" , 1, 0, 0, 6 }, /* 9 */ { "x+1/4" , 1, 0, 0, 3 }, /* : */ { "x+3/4" , 1, 0, 0, 9 }, /* ; */ { "y+1/2" , 0, 1, 0, 6 }, /* < */ { "y+1/4" , 0, 1, 0, 3 }, /* = */ { "y+3/4" , 0, 1, 0, 9 }, /* > */ { "z+1/2" , 0, 0, 1, 6 }, /* ? */ { "z+1/3" , 0, 0, 1, 4 }, /* @ */ { "z+1/4" , 0, 0, 1, 3 }, /* A */ { "z+1/6" , 0, 0, 1, 2 }, /* B */ { "z+2/3" , 0, 0, 1, 8 }, /* C */ { "z+3/4" , 0, 0, 1, 9 }, /* D */ { "z+5/6" , 0, 0, 1, 10 }, /* E */ { "-x+1/2" , -1, 0, 0, 6 }, /* F */ { "-x+1/4" , -1, 0, 0, 3 }, /* G */ { "-x+3/4" , -1, 0, 0, 9 }, /* H */ { "-y+1/2" , 0,-1, 0, 6 }, /* I */ { "-y+1/4" , 0,-1, 0, 3 }, /* J */ { "-y+3/4" , 0,-1, 0, 9 }, /* K */ { "-z+1/2" , 0, 0,-1, 6 }, /* L */ { "-z+1/3" , 0, 0,-1, 4 }, /* M */ { "-z+1/4" , 0, 0,-1, 3 }, /* N */ { "-z+1/6" , 0, 0,-1, 2 }, /* O */ { "-z+2/3" , 0, 0,-1, 8 }, /* P */ { "-z+3/4" , 0, 0,-1, 9 }, /* Q */ { "-z+5/6" , 0, 0,-1, 10 }, }; const SpaceGroupSetting space_group_settings[] = { /* generated by cctbx and listed below list_sg.py */ { 1, 0, "", "P 1", " P 1" , "" }, { 2, 0, "", "P -1", "-P 1" , "" }, { 3, 0, "b", "P 1 2 1", " P 2y" , "315" }, { 3, 0, "c", "P 1 1 2", " P 2" , "342" }, { 3, 0, "a", "P 2 1 1", " P 2x" , "045" }, { 4, 0, "b", "P 1 21 1", " P 2yb" , "3;5" }, { 4, 0, "c", "P 1 1 21", " P 2c" , "34>" }, { 4, 0, "a", "P 21 1 1", " P 2xa" , "845" }, { 5, 0, "b1", "C 1 2 1", " C 2y" , "315" }, { 5, 0, "b2", "A 1 2 1", " A 2y" , "315" }, { 5, 0, "b3", "I 1 2 1", " I 2y" , "315" }, { 5, 0, "c1", "A 1 1 2", " A 2" , "342" }, { 5, 0, "c2", "B 1 1 2", " B 2" , "342" }, { 5, 0, "c3", "I 1 1 2", " I 2" , "342" }, { 5, 0, "a1", "B 2 1 1", " B 2x" , "045" }, { 5, 0, "a2", "C 2 1 1", " C 2x" , "045" }, { 5, 0, "a3", "I 2 1 1", " I 2x" , "045" }, { 6, 0, "b", "P 1 m 1", " P -2y" , "042" }, { 6, 0, "c", "P 1 1 m", " P -2" , "015" }, { 6, 0, "a", "P m 1 1", " P -2x" , "312" }, { 7, 0, "b1", "P 1 c 1", " P -2yc" , "04>" }, { 7, 0, "b2", "P 1 n 1", " P -2yac" , "84>" }, { 7, 0, "b3", "P 1 a 1", " P -2ya" , "842" }, { 7, 0, "c1", "P 1 1 a", " P -2a" , "815" }, { 7, 0, "c2", "P 1 1 n", " P -2ab" , "8;5" }, { 7, 0, "c3", "P 1 1 b", " P -2b" , "0;5" }, { 7, 0, "a1", "P b 1 1", " P -2xb" , "3;2" }, { 7, 0, "a2", "P n 1 1", " P -2xbc" , "3;>" }, { 7, 0, "a3", "P c 1 1", " P -2xc" , "31>" }, { 8, 0, "b1", "C 1 m 1", " C -2y" , "042" }, { 8, 0, "b2", "A 1 m 1", " A -2y" , "042" }, { 8, 0, "b3", "I 1 m 1", " I -2y" , "042" }, { 8, 0, "c1", "A 1 1 m", " A -2" , "015" }, { 8, 0, "c2", "B 1 1 m", " B -2" , "015" }, { 8, 0, "c3", "I 1 1 m", " I -2" , "015" }, { 8, 0, "a1", "B m 1 1", " B -2x" , "312" }, { 8, 0, "a2", "C m 1 1", " C -2x" , "312" }, { 8, 0, "a3", "I m 1 1", " I -2x" , "312" }, { 9, 0, "b1", "C 1 c 1", " C -2yc" , "04>" }, { 9, 0, "b2", "A 1 n 1", " A -2yab" , "8H2" }, { 9, 0, "b3", "I 1 a 1", " I -2ya" , "842" }, { 9, 0, "-b1", "A 1 a 1", " A -2ya" , "842" }, { 9, 0, "-b2", "C 1 n 1", " C -2yac" , "84>" }, { 9, 0, "-b3", "I 1 c 1", " I -2yc" , "04>" }, { 9, 0, "c1", "A 1 1 a", " A -2a" , "815" }, { 9, 0, "c2", "B 1 1 n", " B -2ab" , "8;5" }, { 9, 0, "c3", "I 1 1 b", " I -2b" , "0;5" }, { 9, 0, "-c1", "B 1 1 b", " B -2b" , "0;5" }, { 9, 0, "-c2", "A 1 1 n", " A -2ab" , "8;5" }, { 9, 0, "-c3", "I 1 1 a", " I -2a" , "815" }, { 9, 0, "a1", "B b 1 1", " B -2xb" , "3;2" }, { 9, 0, "a2", "C n 1 1", " C -2xac" , "E1>" }, { 9, 0, "a3", "I c 1 1", " I -2xc" , "31>" }, { 9, 0, "-a1", "C c 1 1", " C -2xc" , "31>" }, { 9, 0, "-a2", "B n 1 1", " B -2xab" , "E;2" }, { 9, 0, "-a3", "I b 1 1", " I -2xb" , "3;2" }, { 10, 0, "b", "P 1 2/m 1", "-P 2y" , "315" }, { 10, 0, "c", "P 1 1 2/m", "-P 2" , "342" }, { 10, 0, "a", "P 2/m 1 1", "-P 2x" , "045" }, { 11, 0, "b", "P 1 21/m 1", "-P 2yb" , "3;5" }, { 11, 0, "c", "P 1 1 21/m", "-P 2c" , "34>" }, { 11, 0, "a", "P 21/m 1 1", "-P 2xa" , "845" }, { 12, 0, "b1", "C 1 2/m 1", "-C 2y" , "315" }, { 12, 0, "b2", "A 1 2/m 1", "-A 2y" , "315" }, { 12, 0, "b3", "I 1 2/m 1", "-I 2y" , "315" }, { 12, 0, "c1", "A 1 1 2/m", "-A 2" , "342" }, { 12, 0, "c2", "B 1 1 2/m", "-B 2" , "342" }, { 12, 0, "c3", "I 1 1 2/m", "-I 2" , "342" }, { 12, 0, "a1", "B 2/m 1 1", "-B 2x" , "045" }, { 12, 0, "a2", "C 2/m 1 1", "-C 2x" , "045" }, { 12, 0, "a3", "I 2/m 1 1", "-I 2x" , "045" }, { 13, 0, "b1", "P 1 2/c 1", "-P 2yc" , "31K" }, { 13, 0, "b2", "P 1 2/n 1", "-P 2yac" , "E1K" }, { 13, 0, "b3", "P 1 2/a 1", "-P 2ya" , "E15" }, { 13, 0, "c1", "P 1 1 2/a", "-P 2a" , "E42" }, { 13, 0, "c2", "P 1 1 2/n", "-P 2ab" , "EH2" }, { 13, 0, "c3", "P 1 1 2/b", "-P 2b" , "3H2" }, { 13, 0, "a1", "P 2/b 1 1", "-P 2xb" , "0H5" }, { 13, 0, "a2", "P 2/n 1 1", "-P 2xbc" , "0HK" }, { 13, 0, "a3", "P 2/c 1 1", "-P 2xc" , "04K" }, { 14, 0, "b1", "P 1 21/c 1", "-P 2ybc" , "3;K" }, { 14, 0, "b2", "P 1 21/n 1", "-P 2yn" , "E;K" }, { 14, 0, "b3", "P 1 21/a 1", "-P 2yab" , "E;5" }, { 14, 0, "c1", "P 1 1 21/a", "-P 2ac" , "E4>" }, { 14, 0, "c2", "P 1 1 21/n", "-P 2n" , "EH>" }, { 14, 0, "c3", "P 1 1 21/b", "-P 2bc" , "3H>" }, { 14, 0, "a1", "P 21/b 1 1", "-P 2xab" , "8H5" }, { 14, 0, "a2", "P 21/n 1 1", "-P 2xn" , "8HK" }, { 14, 0, "a3", "P 21/c 1 1", "-P 2xac" , "84K" }, { 15, 0, "b1", "C 1 2/c 1", "-C 2yc" , "31K" }, { 15, 0, "b2", "A 1 2/n 1", "-A 2yab" , "E;5" }, { 15, 0, "b3", "I 1 2/a 1", "-I 2ya" , "E15" }, { 15, 0, "-b1", "A 1 2/a 1", "-A 2ya" , "E15" }, { 15, 0, "-b2", "C 1 2/n 1", "-C 2yac" , "E1K" }, { 15, 0, "-b3", "I 1 2/c 1", "-I 2yc" , "31K" }, { 15, 0, "c1", "A 1 1 2/a", "-A 2a" , "E42" }, { 15, 0, "c2", "B 1 1 2/n", "-B 2ab" , "EH2" }, { 15, 0, "c3", "I 1 1 2/b", "-I 2b" , "3H2" }, { 15, 0, "-c1", "B 1 1 2/b", "-B 2b" , "3H2" }, { 15, 0, "-c2", "A 1 1 2/n", "-A 2ab" , "EH2" }, { 15, 0, "-c3", "I 1 1 2/a", "-I 2a" , "E42" }, { 15, 0, "a1", "B 2/b 1 1", "-B 2xb" , "0H5" }, { 15, 0, "a2", "C 2/n 1 1", "-C 2xac" , "84K" }, { 15, 0, "a3", "I 2/c 1 1", "-I 2xc" , "04K" }, { 15, 0, "-a1", "C 2/c 1 1", "-C 2xc" , "04K" }, { 15, 0, "-a2", "B 2/n 1 1", "-B 2xab" , "8H5" }, { 15, 0, "-a3", "I 2/b 1 1", "-I 2xb" , "0H5" }, { 16, 0, "", "P 2 2 2", " P 2 2" , "342""045""315" }, { 17, 0, "", "P 2 2 21", " P 2c 2" , "34>""045""31K" }, { 17, 0, "cab", "P 21 2 2", " P 2a 2a" , "E42""845""315" }, { 17, 0, "bca", "P 2 21 2", " P 2 2b" , "342""0H5""3;5" }, { 18, 0, "", "P 21 21 2", " P 2 2ab" , "342""8H5""E;5" }, { 18, 0, "cab", "P 2 21 21", " P 2bc 2" , "3H>""045""3;K" }, { 18, 0, "bca", "P 21 2 21", " P 2ac 2ac" , "E4>""84K""315" }, { 19, 0, "", "P 21 21 21", " P 2ac 2ab" , "E4>""8H5""3;K" }, { 20, 0, "", "C 2 2 21", " C 2c 2" , "34>""045""31K" }, { 20, 0, "cab", "A 21 2 2", " A 2a 2a" , "E42""845""315" }, { 20, 0, "bca", "B 2 21 2", " B 2 2b" , "342""0H5""3;5" }, { 21, 0, "", "C 2 2 2", " C 2 2" , "342""045""315" }, { 21, 0, "cab", "A 2 2 2", " A 2 2" , "342""045""315" }, { 21, 0, "bca", "B 2 2 2", " B 2 2" , "342""045""315" }, { 22, 0, "", "F 2 2 2", " F 2 2" , "342""045""315" }, { 23, 0, "", "I 2 2 2", " I 2 2" , "342""045""315" }, { 24, 0, "", "I 21 21 21", " I 2b 2c" , "3H2""04K""3;K" }, { 25, 0, "", "P m m 2", " P 2 -2" , "342""312""042" }, { 25, 0, "cab", "P 2 m m", " P -2 2" , "015""045""042" }, { 25, 0, "bca", "P m 2 m", " P -2 -2" , "015""312""315" }, { 26, 0, "", "P m c 21", " P 2c -2" , "34>""312""04>" }, { 26, 0, "ba-c", "P c m 21", " P 2c -2c" , "34>""31>""042" }, { 26, 0, "cab", "P 21 m a", " P -2a 2a" , "815""845""042" }, { 26, 0, "-cba", "P 21 a m", " P -2 2a" , "015""845""842" }, { 26, 0, "bca", "P b 21 m", " P -2 -2b" , "015""3;2""3;5" }, { 26, 0, "a-cb", "P m 21 b", " P -2b -2" , "0;5""312""3;5" }, { 27, 0, "", "P c c 2", " P 2 -2c" , "342""31>""04>" }, { 27, 0, "cab", "P 2 a a", " P -2a 2" , "815""045""842" }, { 27, 0, "bca", "P b 2 b", " P -2b -2b" , "0;5""3;2""315" }, { 28, 0, "", "P m a 2", " P 2 -2a" , "342""E12""842" }, { 28, 0, "ba-c", "P b m 2", " P 2 -2b" , "342""3;2""0H2" }, { 28, 0, "cab", "P 2 m b", " P -2b 2" , "0;5""045""0H2" }, { 28, 0, "-cba", "P 2 c m", " P -2c 2" , "01K""045""04>" }, { 28, 0, "bca", "P c 2 m", " P -2c -2c" , "01K""31>""315" }, { 28, 0, "a-cb", "P m 2 a", " P -2a -2a" , "815""E12""315" }, { 29, 0, "", "P c a 21", " P 2c -2ac" , "34>""E1>""842" }, { 29, 0, "ba-c", "P b c 21", " P 2c -2b" , "34>""3;2""0H>" }, { 29, 0, "cab", "P 21 a b", " P -2b 2a" , "0;5""845""8H2" }, { 29, 0, "-cba", "P 21 c a", " P -2ac 2a" , "81K""845""04>" }, { 29, 0, "bca", "P c 21 b", " P -2bc -2c" , "0;K""31>""3;5" }, { 29, 0, "a-cb", "P b 21 a", " P -2a -2ab" , "815""E;2""3;5" }, { 30, 0, "", "P n c 2", " P 2 -2bc" , "342""3;>""0H>" }, { 30, 0, "ba-c", "P c n 2", " P 2 -2ac" , "342""E1>""84>" }, { 30, 0, "cab", "P 2 n a", " P -2ac 2" , "81K""045""84>" }, { 30, 0, "-cba", "P 2 a n", " P -2ab 2" , "8;5""045""8H2" }, { 30, 0, "bca", "P b 2 n", " P -2ab -2ab" , "8;5""E;2""315" }, { 30, 0, "a-cb", "P n 2 b", " P -2bc -2bc" , "0;K""3;>""315" }, { 31, 0, "", "P m n 21", " P 2ac -2" , "E4>""312""84>" }, { 31, 0, "ba-c", "P n m 21", " P 2bc -2bc" , "3H>""3;>""042" }, { 31, 0, "cab", "P 21 m n", " P -2ab 2ab" , "8;5""8H5""042" }, { 31, 0, "-cba", "P 21 n m", " P -2 2ac" , "015""84K""84>" }, { 31, 0, "bca", "P n 21 m", " P -2 -2bc" , "015""3;>""3;K" }, { 31, 0, "a-cb", "P m 21 n", " P -2ab -2" , "8;5""312""E;5" }, { 32, 0, "", "P b a 2", " P 2 -2ab" , "342""E;2""8H2" }, { 32, 0, "cab", "P 2 c b", " P -2bc 2" , "0;K""045""0H>" }, { 32, 0, "bca", "P c 2 a", " P -2ac -2ac" , "81K""E1>""315" }, { 33, 0, "", "P n a 21", " P 2c -2n" , "34>""E;>""8H2" }, { 33, 0, "ba-c", "P b n 21", " P 2c -2ab" , "34>""E;2""8H>" }, { 33, 0, "cab", "P 21 n b", " P -2bc 2a" , "0;K""845""8H>" }, { 33, 0, "-cba", "P 21 c n", " P -2n 2a" , "8;K""845""0H>" }, { 33, 0, "bca", "P c 21 n", " P -2n -2ac" , "8;K""E1>""3;5" }, { 33, 0, "a-cb", "P n 21 a", " P -2ac -2n" , "81K""E;>""3;5" }, { 34, 0, "", "P n n 2", " P 2 -2n" , "342""E;>""8H>" }, { 34, 0, "cab", "P 2 n n", " P -2n 2" , "8;K""045""8H>" }, { 34, 0, "bca", "P n 2 n", " P -2n -2n" , "8;K""E;>""315" }, { 35, 0, "", "C m m 2", " C 2 -2" , "342""312""042" }, { 35, 0, "cab", "A 2 m m", " A -2 2" , "015""045""042" }, { 35, 0, "bca", "B m 2 m", " B -2 -2" , "015""312""315" }, { 36, 0, "", "C m c 21", " C 2c -2" , "34>""312""04>" }, { 36, 0, "ba-c", "C c m 21", " C 2c -2c" , "34>""31>""042" }, { 36, 0, "cab", "A 21 m a", " A -2a 2a" , "815""845""042" }, { 36, 0, "-cba", "A 21 a m", " A -2 2a" , "015""845""842" }, { 36, 0, "bca", "B b 21 m", " B -2 -2b" , "015""3;2""3;5" }, { 36, 0, "a-cb", "B m 21 b", " B -2b -2" , "0;5""312""3;5" }, { 37, 0, "", "C c c 2", " C 2 -2c" , "342""31>""04>" }, { 37, 0, "cab", "A 2 a a", " A -2a 2" , "815""045""842" }, { 37, 0, "bca", "B b 2 b", " B -2b -2b" , "0;5""3;2""315" }, { 38, 0, "", "A m m 2", " A 2 -2" , "342""312""042" }, { 38, 0, "ba-c", "B m m 2", " B 2 -2" , "342""312""042" }, { 38, 0, "cab", "B 2 m m", " B -2 2" , "015""045""042" }, { 38, 0, "-cba", "C 2 m m", " C -2 2" , "015""045""042" }, { 38, 0, "bca", "C m 2 m", " C -2 -2" , "015""312""315" }, { 38, 0, "a-cb", "A m 2 m", " A -2 -2" , "015""312""315" }, { 39, 0, "", "A b m 2", " A 2 -2b" , "342""3;2""0H2" }, { 39, 0, "ba-c", "B m a 2", " B 2 -2a" , "342""E12""842" }, { 39, 0, "cab", "B 2 c m", " B -2a 2" , "815""045""842" }, { 39, 0, "-cba", "C 2 m b", " C -2a 2" , "815""045""842" }, { 39, 0, "bca", "C m 2 a", " C -2a -2a" , "815""E12""315" }, { 39, 0, "a-cb", "A c 2 m", " A -2b -2b" , "0;5""3;2""315" }, { 40, 0, "", "A m a 2", " A 2 -2a" , "342""E12""842" }, { 40, 0, "ba-c", "B b m 2", " B 2 -2b" , "342""3;2""0H2" }, { 40, 0, "cab", "B 2 m b", " B -2b 2" , "0;5""045""0H2" }, { 40, 0, "-cba", "C 2 c m", " C -2c 2" , "01K""045""04>" }, { 40, 0, "bca", "C c 2 m", " C -2c -2c" , "01K""31>""315" }, { 40, 0, "a-cb", "A m 2 a", " A -2a -2a" , "815""E12""315" }, { 41, 0, "", "A b a 2", " A 2 -2ab" , "342""E;2""8H2" }, { 41, 0, "ba-c", "B b a 2", " B 2 -2ab" , "342""E;2""8H2" }, { 41, 0, "cab", "B 2 c b", " B -2ab 2" , "8;5""045""8H2" }, { 41, 0, "-cba", "C 2 c b", " C -2ac 2" , "81K""045""84>" }, { 41, 0, "bca", "C c 2 a", " C -2ac -2ac" , "81K""E1>""315" }, { 41, 0, "a-cb", "A c 2 a", " A -2ab -2ab" , "8;5""E;2""315" }, { 42, 0, "", "F m m 2", " F 2 -2" , "342""312""042" }, { 42, 0, "cab", "F 2 m m", " F -2 2" , "015""045""042" }, { 42, 0, "bca", "F m 2 m", " F -2 -2" , "015""312""315" }, { 43, 0, "", "F d d 2", " F 2 -2d" , "342""F<@"":J@" }, { 43, 0, "cab", "F 2 d d", " F -2d 2" , "9""04>" }, { 45, 0, "cab", "I 2 c b", " I -2a 2" , "815""045""842" }, { 45, 0, "bca", "I c 2 a", " I -2b -2b" , "0;5""3;2""315" }, { 46, 0, "", "I m a 2", " I 2 -2a" , "342""E12""842" }, { 46, 0, "ba-c", "I b m 2", " I 2 -2b" , "342""3;2""0H2" }, { 46, 0, "cab", "I 2 m b", " I -2b 2" , "0;5""045""0H2" }, { 46, 0, "-cba", "I 2 c m", " I -2c 2" , "01K""045""04>" }, { 46, 0, "bca", "I c 2 m", " I -2c -2c" , "01K""31>""315" }, { 46, 0, "a-cb", "I m 2 a", " I -2a -2a" , "815""E12""315" }, { 47, 0, "", "P m m m", "-P 2 2" , "342""045""315" }, { 48, '1', "", "P n n n", " P 2 2 -1n" , "342""045""315" }, { 48, '2', "", "P n n n", "-P 2ab 2bc" , "EH2""0HK""E1K" }, { 49, 0, "", "P c c m", "-P 2 2c" , "342""04K""31K" }, { 49, 0, "cab", "P m a a", "-P 2a 2" , "E42""045""E15" }, { 49, 0, "bca", "P b m b", "-P 2b 2b" , "3H2""0H5""315" }, { 50, '1', "", "P b a n", " P 2 2 -1ab" , "342""045""315" }, { 50, '2', "", "P b a n", "-P 2ab 2b" , "EH2""0H5""E15" }, { 50, '1', "cab", "P n c b", " P 2 2 -1bc" , "342""045""315" }, { 50, '2', "cab", "P n c b", "-P 2b 2bc" , "3H2""0HK""31K" }, { 50, '1', "bca", "P c n a", " P 2 2 -1ac" , "342""045""315" }, { 50, '2', "bca", "P c n a", "-P 2a 2c" , "E42""04K""E1K" }, { 51, 0, "", "P m m a", "-P 2a 2a" , "E42""845""315" }, { 51, 0, "ba-c", "P m m b", "-P 2b 2" , "3H2""045""3;5" }, { 51, 0, "cab", "P b m m", "-P 2 2b" , "342""0H5""3;5" }, { 51, 0, "-cba", "P c m m", "-P 2c 2c" , "34>""04K""315" }, { 51, 0, "bca", "P m c m", "-P 2c 2" , "34>""045""31K" }, { 51, 0, "a-cb", "P m a m", "-P 2 2a" , "342""845""E15" }, { 52, 0, "", "P n n a", "-P 2a 2bc" , "E42""0HK""E;K" }, { 52, 0, "ba-c", "P n n b", "-P 2b 2n" , "3H2""8HK""E1K" }, { 52, 0, "cab", "P b n n", "-P 2n 2b" , "EH>""0H5""E1K" }, { 52, 0, "-cba", "P c n n", "-P 2ab 2c" , "EH2""04K""E;K" }, { 52, 0, "bca", "P n c n", "-P 2ab 2n" , "EH2""8HK""31K" }, { 52, 0, "a-cb", "P n a n", "-P 2n 2bc" , "EH>""0HK""E15" }, { 53, 0, "", "P m n a", "-P 2ac 2" , "E4>""045""E1K" }, { 53, 0, "ba-c", "P n m b", "-P 2bc 2bc" , "3H>""0HK""315" }, { 53, 0, "cab", "P b m n", "-P 2ab 2ab" , "EH2""8H5""315" }, { 53, 0, "-cba", "P c n m", "-P 2 2ac" , "342""84K""E1K" }, { 53, 0, "bca", "P n c m", "-P 2 2bc" , "342""0HK""3;K" }, { 53, 0, "a-cb", "P m a n", "-P 2ab 2" , "EH2""045""E;5" }, { 54, 0, "", "P c c a", "-P 2a 2ac" , "E42""84K""31K" }, { 54, 0, "ba-c", "P c c b", "-P 2b 2c" , "3H2""04K""3;K" }, { 54, 0, "cab", "P b a a", "-P 2a 2b" , "E42""0H5""E;5" }, { 54, 0, "-cba", "P c a a", "-P 2ac 2c" , "E4>""04K""E15" }, { 54, 0, "bca", "P b c b", "-P 2bc 2b" , "3H>""0H5""31K" }, { 54, 0, "a-cb", "P b a b", "-P 2b 2ab" , "3H2""8H5""E15" }, { 55, 0, "", "P b a m", "-P 2 2ab" , "342""8H5""E;5" }, { 55, 0, "cab", "P m c b", "-P 2bc 2" , "3H>""045""3;K" }, { 55, 0, "bca", "P c m a", "-P 2ac 2ac" , "E4>""84K""315" }, { 56, 0, "", "P c c n", "-P 2ab 2ac" , "EH2""84K""3;K" }, { 56, 0, "cab", "P n a a", "-P 2ac 2bc" , "E4>""0HK""E;5" }, { 56, 0, "bca", "P b n b", "-P 2bc 2ab" , "3H>""8H5""E1K" }, { 57, 0, "", "P b c m", "-P 2c 2b" , "34>""0H5""3;K" }, { 57, 0, "ba-c", "P c a m", "-P 2c 2ac" , "34>""84K""E15" }, { 57, 0, "cab", "P m c a", "-P 2ac 2a" , "E4>""845""31K" }, { 57, 0, "-cba", "P m a b", "-P 2b 2a" , "3H2""845""E;5" }, { 57, 0, "bca", "P b m a", "-P 2a 2ab" , "E42""8H5""3;5" }, { 57, 0, "a-cb", "P c m b", "-P 2bc 2c" , "3H>""04K""3;5" }, { 58, 0, "", "P n n m", "-P 2 2n" , "342""8HK""E;K" }, { 58, 0, "cab", "P m n n", "-P 2n 2" , "EH>""045""E;K" }, { 58, 0, "bca", "P n m n", "-P 2n 2n" , "EH>""8HK""315" }, { 59, '1', "", "P m m n", " P 2 2ab -1ab" , "342""8H5""E;5" }, { 59, '2', "", "P m m n", "-P 2ab 2a" , "EH2""845""3;5" }, { 59, '1', "cab", "P n m m", " P 2bc 2 -1bc" , "3H>""045""3;K" }, { 59, '2', "cab", "P n m m", "-P 2c 2bc" , "34>""0HK""3;5" }, { 59, '1', "bca", "P m n m", " P 2ac 2ac -1ac", "E4>""84K""315" }, { 59, '2', "bca", "P m n m", "-P 2c 2a" , "34>""845""E1K" }, { 60, 0, "", "P b c n", "-P 2n 2ab" , "EH>""8H5""31K" }, { 60, 0, "ba-c", "P c a n", "-P 2n 2c" , "EH>""04K""E;5" }, { 60, 0, "cab", "P n c a", "-P 2a 2n" , "E42""8HK""3;K" }, { 60, 0, "-cba", "P n a b", "-P 2bc 2n" , "3H>""8HK""E15" }, { 60, 0, "bca", "P b n a", "-P 2ac 2b" , "E4>""0H5""E;K" }, { 60, 0, "a-cb", "P c n b", "-P 2b 2ac" , "3H2""84K""E;K" }, { 61, 0, "", "P b c a", "-P 2ac 2ab" , "E4>""8H5""3;K" }, { 61, 0, "ba-c", "P c a b", "-P 2bc 2ac" , "3H>""84K""E;5" }, { 62, 0, "", "P n m a", "-P 2ac 2n" , "E4>""8HK""3;5" }, { 62, 0, "ba-c", "P m n b", "-P 2bc 2a" , "3H>""845""E;K" }, { 62, 0, "cab", "P b n m", "-P 2c 2ab" , "34>""8H5""E;K" }, { 62, 0, "-cba", "P c m n", "-P 2n 2ac" , "EH>""84K""3;5" }, { 62, 0, "bca", "P m c n", "-P 2n 2a" , "EH>""845""3;K" }, { 62, 0, "a-cb", "P n a m", "-P 2c 2n" , "34>""8HK""E;5" }, { 63, 0, "", "C m c m", "-C 2c 2" , "34>""045""31K" }, { 63, 0, "ba-c", "C c m m", "-C 2c 2c" , "34>""04K""315" }, { 63, 0, "cab", "A m m a", "-A 2a 2a" , "E42""845""315" }, { 63, 0, "-cba", "A m a m", "-A 2 2a" , "342""845""E15" }, { 63, 0, "bca", "B b m m", "-B 2 2b" , "342""0H5""3;5" }, { 63, 0, "a-cb", "B m m b", "-B 2b 2" , "3H2""045""3;5" }, { 64, 0, "", "C m c a", "-C 2ac 2" , "E4>""045""E1K" }, { 64, 0, "ba-c", "C c m b", "-C 2ac 2ac" , "E4>""84K""315" }, { 64, 0, "cab", "A b m a", "-A 2ab 2ab" , "EH2""8H5""315" }, { 64, 0, "-cba", "A c a m", "-A 2 2ab" , "342""8H5""E;5" }, { 64, 0, "bca", "B b c m", "-B 2 2ab" , "342""8H5""E;5" }, { 64, 0, "a-cb", "B m a b", "-B 2ab 2" , "EH2""045""E;5" }, { 65, 0, "", "C m m m", "-C 2 2" , "342""045""315" }, { 65, 0, "cab", "A m m m", "-A 2 2" , "342""045""315" }, { 65, 0, "bca", "B m m m", "-B 2 2" , "342""045""315" }, { 66, 0, "", "C c c m", "-C 2 2c" , "342""04K""31K" }, { 66, 0, "cab", "A m a a", "-A 2a 2" , "E42""045""E15" }, { 66, 0, "bca", "B b m b", "-B 2b 2b" , "3H2""0H5""315" }, { 67, 0, "", "C m m a", "-C 2a 2" , "E42""045""E15" }, { 67, 0, "ba-c", "C m m b", "-C 2a 2a" , "E42""845""315" }, { 67, 0, "cab", "A b m m", "-A 2b 2b" , "3H2""0H5""315" }, { 67, 0, "-cba", "A c m m", "-A 2 2b" , "342""0H5""3;5" }, { 67, 0, "bca", "B m c m", "-B 2 2a" , "342""845""E15" }, { 67, 0, "a-cb", "B m a m", "-B 2a 2" , "E42""045""E15" }, { 68, '1', "", "C c c a", " C 2 2 -1ac" , "342""045""315" }, { 68, '2', "", "C c c a", "-C 2a 2ac" , "E42""84K""31K" }, { 68, '1', "ba-c", "C c c b", " C 2 2 -1ac" , "342""045""315" }, { 68, '2', "ba-c", "C c c b", "-C 2a 2c" , "E42""04K""E1K" }, { 68, '1', "cab", "A b a a", " A 2 2 -1ab" , "342""045""315" }, { 68, '2', "cab", "A b a a", "-A 2a 2b" , "E42""0H5""E;5" }, { 68, '1', "-cba", "A c a a", " A 2 2 -1ab" , "342""045""315" }, { 68, '2', "-cba", "A c a a", "-A 2ab 2b" , "EH2""0H5""E15" }, { 68, '1', "bca", "B b c b", " B 2 2 -1ab" , "342""045""315" }, { 68, '2', "bca", "B b c b", "-B 2ab 2b" , "EH2""0H5""E15" }, { 68, '1', "a-cb", "B b a b", " B 2 2 -1ab" , "342""045""315" }, { 68, '2', "a-cb", "B b a b", "-B 2b 2ab" , "3H2""8H5""E15" }, { 69, 0, "", "F m m m", "-F 2 2" , "342""045""315" }, { 70, '1', "", "F d d d", " F 2 2 -1d" , "342""045""315" }, { 70, '2', "", "F d d d", "-F 2uv 2vw" , "FI2""0IM""F1M" }, { 71, 0, "", "I m m m", "-I 2 2" , "342""045""315" }, { 72, 0, "", "I b a m", "-I 2 2c" , "342""04K""31K" }, { 72, 0, "cab", "I m c b", "-I 2a 2" , "E42""045""E15" }, { 72, 0, "bca", "I c m a", "-I 2b 2b" , "3H2""0H5""315" }, { 73, 0, "", "I b c a", "-I 2b 2c" , "3H2""04K""3;K" }, { 73, 0, "ba-c", "I c a b", "-I 2a 2b" , "E42""0H5""E;5" }, { 74, 0, "", "I m m a", "-I 2b 2" , "3H2""045""3;5" }, { 74, 0, "ba-c", "I m m b", "-I 2a 2a" , "E42""845""315" }, { 74, 0, "cab", "I b m m", "-I 2c 2c" , "34>""04K""315" }, { 74, 0, "-cba", "I c m m", "-I 2 2b" , "342""0H5""3;5" }, { 74, 0, "bca", "I m c m", "-I 2 2a" , "342""845""E15" }, { 74, 0, "a-cb", "I m a m", "-I 2c 2" , "34>""045""31K" }, { 75, 0, "", "P 4", " P 4" , "402""342""132" }, { 76, 0, "", "P 41", " P 4w" , "40@""34>""13C" }, { 77, 0, "", "P 42", " P 4c" , "40>""342""13>" }, { 78, 0, "", "P 43", " P 4cw" , "40C""34>""13@" }, { 79, 0, "", "I 4", " I 4" , "402""342""132" }, { 80, 0, "", "I 41", " I 4bw" , "48@""EH>"";3C" }, { 81, 0, "", "P -4", " P -4" , "135""342""405" }, { 82, 0, "", "I -4", " I -4" , "135""342""405" }, { 83, 0, "", "P 4/m", "-P 4" , "402""342""132" }, { 84, 0, "", "P 42/m", "-P 4c" , "40>""342""13>" }, { 85, '1', "", "P 4/n", " P 4ab -1ab" , "H82""342"";E2" }, { 85, '2', "", "P 4/n", "-P 4a" , "H02""EH2""1E2" }, { 86, '1', "", "P 42/n", " P 4n -1n" , "H8>""342"";E>" }, { 86, '2', "", "P 42/n", "-P 4bc" , "48>""EH2"";3>" }, { 87, 0, "", "I 4/m", "-I 4" , "402""342""132" }, { 88, '1', "", "I 41/a", " I 4bw -1bw" , "48@""EH>"";3C" }, { 88, '2', "", "I 41/a", "-I 4ad" , "J9@""E4>""=GC" }, { 89, 0, "", "P 4 2 2", " P 4 2" , "402""342""132""045""105""315""435" }, { 90, 0, "", "P 4 21 2", " P 4ab 2ab" , "H82""342"";E2""8H5""105""E;5""435" }, { 91, 0, "", "P 41 2 2", " P 4w 2c" , "40@""34>""13C""04K""10P""315""43M" }, { 92, 0, "", "P 41 21 2", " P 4abw 2nw" , "H8@""34>"";EC""8HP""105""E;M""43K" }, { 93, 0, "", "P 42 2 2", " P 4c 2" , "40>""342""13>""045""10K""315""43K" }, { 94, 0, "", "P 42 21 2", " P 4n 2n" , "H8>""342"";E>""8HK""105""E;K""435" }, { 95, 0, "", "P 43 2 2", " P 4cw 2c" , "40C""34>""13@""04K""10M""315""43P" }, { 96, 0, "", "P 43 21 2", " P 4nw 2abw" , "H8C""34>"";E@""8HM""105""E;P""43K" }, { 97, 0, "", "I 4 2 2", " I 4 2" , "402""342""132""045""105""315""435" }, { 98, 0, "", "I 41 2 2", " I 4bw 2bw" , "48@""EH>"";3C""0HM"";8K""E1P""435" }, { 99, 0, "", "P 4 m m", " P 4 -2" , "402""342""132""312""432""042""102" }, { 100, 0, "", "P 4 b m", " P 4 -2ab" , "402""342""132""E;2""HE2""8H2"";82" }, { 101, 0, "", "P 42 c m", " P 4c -2c" , "40>""342""13>""31>""432""04>""102" }, { 102, 0, "", "P 42 n m", " P 4n -2n" , "H8>""342"";E>""E;>""432""8H>""102" }, { 103, 0, "", "P 4 c c", " P 4 -2c" , "402""342""132""31>""43>""04>""10>" }, { 104, 0, "", "P 4 n c", " P 4 -2n" , "402""342""132""E;>""HE>""8H>"";8>" }, { 105, 0, "", "P 42 m c", " P 4c -2" , "40>""342""13>""312""43>""042""10>" }, { 106, 0, "", "P 42 b c", " P 4c -2ab" , "40>""342""13>""E;2""HE>""8H2"";8>" }, { 107, 0, "", "I 4 m m", " I 4 -2" , "402""342""132""312""432""042""102" }, { 108, 0, "", "I 4 c m", " I 4 -2c" , "402""342""132""31>""43>""04>""10>" }, { 109, 0, "", "I 41 m d", " I 4bw -2" , "48@""EH>"";3C""312""4E@""8H>"";0C" }, { 110, 0, "", "I 41 c d", " I 4bw -2c" , "48@""EH>"";3C""31>""4EC""8H2"";0@" }, { 111, 0, "", "P -4 2 m", " P -4 2" , "135""342""405""045""432""315""102" }, { 112, 0, "", "P -4 2 c", " P -4 2c" , "135""342""405""04K""43>""31K""10>" }, { 113, 0, "", "P -4 21 m", " P -4 2ab" , "135""342""405""8H5""HE2""E;5"";82" }, { 114, 0, "", "P -4 21 c", " P -4 2n" , "135""342""405""8HK""HE>""E;K"";8>" }, { 115, 0, "", "P -4 m 2", " P -4 -2" , "135""342""405""312""105""042""435" }, { 116, 0, "", "P -4 c 2", " P -4 -2c" , "135""342""405""31>""10K""04>""43K" }, { 117, 0, "", "P -4 b 2", " P -4 -2ab" , "135""342""405""E;2"";85""8H2""HE5" }, { 118, 0, "", "P -4 n 2", " P -4 -2n" , "135""342""405""E;>"";8K""8H>""HEK" }, { 119, 0, "", "I -4 m 2", " I -4 -2" , "135""342""405""312""105""042""435" }, { 120, 0, "", "I -4 c 2", " I -4 -2c" , "135""342""405""31>""10K""04>""43K" }, { 121, 0, "", "I -4 2 m", " I -4 2" , "135""342""405""045""432""315""102" }, { 122, 0, "", "I -4 2 d", " I -4 2bw" , "135""342""405""0HM""H3C""3;M"";0C" }, { 123, 0, "", "P 4/m m m", "-P 4 2" , "402""342""132""045""105""315""435" }, { 124, 0, "", "P 4/m c c", "-P 4 2c" , "402""342""132""04K""10K""31K""43K" }, { 125, '1', "", "P 4/n b m", " P 4 2 -1ab" , "402""342""132""045""105""315""435" }, { 125, '2', "", "P 4/n b m", "-P 4a 2b" , "H02""EH2""1E2""0H5""105""E15""HE5" }, { 126, '1', "", "P 4/n n c", " P 4 2 -1n" , "402""342""132""045""105""315""435" }, { 126, '2', "", "P 4/n n c", "-P 4a 2bc" , "H02""EH2""1E2""0HK""10K""E1K""HEK" }, { 127, 0, "", "P 4/m b m", "-P 4 2ab" , "402""342""132""8H5"";85""E;5""HE5" }, { 128, 0, "", "P 4/m n c", "-P 4 2n" , "402""342""132""8HK"";8K""E;K""HEK" }, { 129, '1', "", "P 4/n m m", " P 4ab 2ab -1ab", "H82""342"";E2""8H5""105""E;5""435" }, { 129, '2', "", "P 4/n m m", "-P 4a 2a" , "H02""EH2""1E2""845"";85""3;5""435" }, { 130, '1', "", "P 4/n c c", " P 4ab 2n -1ab" , "H82""342"";E2""8HK""10K""E;K""43K" }, { 130, '2', "", "P 4/n c c", "-P 4a 2ac" , "H02""EH2""1E2""84K"";8K""3;K""43K" }, { 131, 0, "", "P 42/m m c", "-P 4c 2" , "40>""342""13>""045""10K""315""43K" }, { 132, 0, "", "P 42/m c m", "-P 4c 2c" , "40>""342""13>""04K""105""31K""435" }, { 133, '1', "", "P 42/n b c", " P 4n 2c -1n" , "H8>""342"";E>""04K"";85""31K""HE5" }, { 133, '2', "", "P 42/n b c", "-P 4ac 2b" , "H0>""EH2""1E>""0H5""10K""E15""HEK" }, { 134, '1', "", "P 42/n n m", " P 4n 2 -1n" , "H8>""342"";E>""045"";8K""315""HEK" }, { 134, '2', "", "P 42/n n m", "-P 4ac 2bc" , "H0>""EH2""1E>""0HK""105""E1K""HE5" }, { 135, 0, "", "P 42/m b c", "-P 4c 2ab" , "40>""342""13>""8H5"";8K""E;5""HEK" }, { 136, 0, "", "P 42/m n m", "-P 4n 2n" , "H8>""342"";E>""8HK""105""E;K""435" }, { 137, '1', "", "P 42/n m c", " P 4n 2n -1n" , "H8>""342"";E>""8HK""105""E;K""435" }, { 137, '2', "", "P 42/n m c", "-P 4ac 2a" , "H0>""EH2""1E>""845"";8K""3;5""43K" }, { 138, '1', "", "P 42/n c m", " P 4n 2ab -1n" , "H8>""342"";E>""8H5""10K""E;5""43K" }, { 138, '2', "", "P 42/n c m", "-P 4ac 2ac" , "H0>""EH2""1E>""84K"";85""3;K""435" }, { 139, 0, "", "I 4/m m m", "-I 4 2" , "402""342""132""045""105""315""435" }, { 140, 0, "", "I 4/m c m", "-I 4 2c" , "402""342""132""04K""10K""31K""43K" }, { 141, '1', "", "I 41/a m d", " I 4bw 2bw -1bw", "48@""EH>"";3C""0HM"";8K""E1P""435" }, { 141, '2', "", "I 41/a m d", "-I 4bd 2" , "I:@""E4>"""";3C""84M""10K""3;P""HE5" }, { 142, '2', "", "I 41/a c d", "-I 4bd 2c" , "I:@""E4>""""06>""71>" }, { 159, 0, "", "P 3 1 c", " P 3 -2c" , "462""732""10>""37>""64>" }, { 160, 'H', "", "R 3 m", " R 3 -2\"" , "462""732""432""062""712" }, { 160, 'R', "", "R 3 m", " P 3* -2" , "201""120""102""210""021" }, { 161, 'H', "", "R 3 c", " R 3 -2\"c" , "462""732""43>""06>""71>" }, { 161, 'R', "", "R 3 c", " P 3* -2n" , "201""120"";8>"">;8""8>;" }, { 162, 0, "", "P -3 1 m", "-P 3 2" , "462""732""435""065""715" }, { 163, 0, "", "P -3 1 c", "-P 3 2c" , "462""732""43K""06K""71K" }, { 164, 0, "", "P -3 m 1", "-P 3 2\"" , "462""732""105""375""645" }, { 165, 0, "", "P -3 c 1", "-P 3 2\"c" , "462""732""10K""37K""64K" }, { 166, 'H', "", "R -3 m", "-R 3 2\"" , "462""732""105""375""645" }, { 166, 'R', "", "R -3 m", "-P 3* 2" , "201""120""435""543""354" }, { 167, 'H', "", "R -3 c", "-R 3 2\"c" , "462""732""10K""37K""64K" }, { 167, 'R', "", "R -3 c", "-P 3* 2n" , "201""120""HEK""KHE""EKH" }, { 168, 0, "", "P 6", " P 6" , "602""462""342""732""172" }, { 169, 0, "", "P 61", " P 61" , "60A""46?""34>""73B""17D" }, { 170, 0, "", "P 65", " P 65" , "60D""46B""34>""73?""17A" }, { 171, 0, "", "P 62", " P 62" , "60?""46B""342""73?""17B" }, { 172, 0, "", "P 64", " P 64" , "60B""46?""342""73B""17?" }, { 173, 0, "", "P 63", " P 6c" , "60>""462""34>""732""17>" }, { 174, 0, "", "P -6", " P -6" , "735""462""015""732""465" }, { 175, 0, "", "P 6/m", "-P 6" , "602""462""342""732""172" }, { 176, 0, "", "P 63/m", "-P 6c" , "60>""462""34>""732""17>" }, { 177, 0, "", "P 6 2 2", " P 6 2" , "602""462""342""732""172""435""645""065""105""715""375" }, { 178, 0, "", "P 61 2 2", " P 61 2 (0 0 5)", "60A""46?""34>""73B""17D""43Q""645""06N""10L""71K""37O" }, { 179, 0, "", "P 65 2 2", " P 65 2 (0 0 1)", "60D""46B""34>""73?""17A""43N""645""06Q""10O""71K""37L" }, { 180, 0, "", "P 62 2 2", " P 62 2 (0 0 4)", "60?""46B""342""73?""17B""43O""645""06L""10O""715""37L" }, { 181, 0, "", "P 64 2 2", " P 64 2 (0 0 2)", "60B""46?""342""73B""17?""43L""645""06O""10L""715""37O" }, { 182, 0, "", "P 63 2 2", " P 6c 2c" , "60>""462""34>""732""17>""43K""645""06K""105""71K""375" }, { 183, 0, "", "P 6 m m", " P 6 -2" , "602""462""342""732""172""102""712""372""432""642""062" }, { 184, 0, "", "P 6 c c", " P 6 -2c" , "602""462""342""732""172""10>""71>""37>""43>""64>""06>" }, { 185, 0, "", "P 63 c m", " P 6c -2" , "60>""462""34>""732""17>""102""71>""372""43>""642""06>" }, { 186, 0, "", "P 63 m c", " P 6c -2c" , "60>""462""34>""732""17>""10>""712""37>""432""64>""062" }, { 187, 0, "", "P -6 m 2", " P -6 2" , "735""462""015""732""465""435""712""065""432""715""062" }, { 188, 0, "", "P -6 c 2", " P -6c 2" , "73K""462""01K""732""46K""435""71>""065""43>""715""06>" }, { 189, 0, "", "P -6 2 m", " P -6 -2" , "735""462""015""732""465""102""645""372""105""642""375" }, { 190, 0, "", "P -6 2 c", " P -6c -2c" , "73K""462""01K""732""46K""10>""645""37>""105""64>""375" }, { 191, 0, "", "P 6/m m m", "-P 6 2" , "602""462""342""732""172""435""645""065""105""715""375" }, { 192, 0, "", "P 6/m c c", "-P 6 2c" , "602""462""342""732""172""43K""64K""06K""10K""71K""37K" }, { 193, 0, "", "P 63/m c m", "-P 6c 2" , "60>""462""34>""732""17>""435""64K""065""10K""715""37K" }, { 194, 0, "", "P 63/m m c", "-P 6c 2c" , "60>""462""34>""732""17>""43K""645""06K""105""71K""375" }, { 195, 0, "", "P 2 3", " P 2 2 3" , "342""045""315""201""531""234""504""120""153""423""450" }, { 196, 0, "", "F 2 3", " F 2 2 3" , "342""045""315""201""531""234""504""120""153""423""450" }, { 197, 0, "", "I 2 3", " I 2 2 3" , "342""045""315""201""531""234""504""120""153""423""450" }, { 198, 0, "", "P 21 3", " P 2ac 2ab 3" , "E4>""8H5""3;K""201""K3;"">E4""58H""120"";K3""4>E""H58" }, { 199, 0, "", "I 21 3", " I 2b 2c 3" , "3H2""04K""3;K""201""5E1""23H""58H""120""15E""4>E""H58" }, { 200, 0, "", "P m -3", "-P 2 2 3" , "342""045""315""201""531""234""504""120""153""423""450" }, { 201, '1', "", "P n -3", " P 2 2 3 -1n" , "342""045""315""201""531""234""504""120""153""423""450" }, { 201, '2', "", "P n -3", "-P 2ab 2bc 3" , "EH2""0HK""E1K""201""KE1""2EH""K0H""120""1KE""H2E""HK0" }, { 202, 0, "", "F m -3", "-F 2 2 3" , "342""045""315""201""531""234""504""120""153""423""450" }, { 203, '1', "", "F d -3", " F 2 2 3 -1d" , "342""045""315""201""531""234""504""120""153""423""450" }, { 203, '2', "", "F d -3", "-F 2uv 2vw 3" , "FI2""0IM""F1M""201""MF1""2FI""M0I""120""1MF""I2F""IM0" }, { 204, 0, "", "I m -3", "-I 2 2 3" , "342""045""315""201""531""234""504""120""153""423""450" }, { 205, 0, "", "P a -3", "-P 2ac 2ab 3" , "E4>""8H5""3;K""201""K3;"">E4""58H""120"";K3""4>E""H58" }, { 206, 0, "", "I a -3", "-I 2b 2c 3" , "3H2""04K""3;K""201""5E1""23H""58H""120""15E""4>E""H58" }, { 207, 0, "", "P 4 3 2", " P 4 2 3" , "402""342""132""045""105""315""435""201""321""531""051""234""024""504""354""120""153""213""423""543""450""240""510" }, { 208, 0, "", "P 42 3 2", " P 4n 2 3" , "H8>""342"";E>""045"";8K""315""HEK""201""E>;""531""8K;""234""8>H""504""EKH""120""153"">;E""423""KHE""450"">H8""K;8" }, { 209, 0, "", "F 4 3 2", " F 4 2 3" , "402""342""132""045""105""315""435""201""321""531""051""234""024""504""354""120""153""213""423""543""450""240""510" }, { 210, 0, "", "F 41 3 2", " F 4d 2 3" , "I9@""3H>""=FC""045""<9M""3;K""JFP""201""F@<""5E;"":M=""234""9@I""58H""GMJ""120"";5E""@=G""H>3""MIF""450""@J:""P=9" }, { 211, 0, "", "I 4 3 2", " I 4 2 3" , "402""342""132""045""105""315""435""201""321""531""051""234""024""504""354""120""153""213""423""543""450""240""510" }, { 212, 0, "", "P 43 3 2", " P 4acd 2ab 3" , "J9C""E4>""=G@""8H5""<:P""3;K""IFM""201""G@=""K3;"":P<"">E4""9CJ""58H""FMI""120"";K3""@=G""4>E""MIF""H58""CJ9""P<:" }, { 213, 0, "", "P 41 3 2", " P 4bd 2ab 3" , "I:@""E4>""E4"":@I""58H""GPJ""120"";K3""CE""PJG""H58""@I:""M=9" }, { 214, 0, "", "I 41 3 2", " I 4bd 2c 3" , "I:@""E4>""E""MIF""H58""CJ9""P<:" }, { 215, 0, "", "P -4 3 m", " P -4 2 3" , "135""342""405""045""432""315""102""201""054""531""324""234""351""504""021""120""153""540""423""210""450""513""243" }, { 216, 0, "", "F -4 3 m", " F -4 2 3" , "135""342""405""045""432""315""102""201""054""531""324""234""351""504""021""120""153""540""423""210""450""513""243" }, { 217, 0, "", "I -4 3 m", " I -4 2 3" , "135""342""405""045""432""315""102""201""054""531""324""234""351""504""021""120""153""540""423""210""450""513""243" }, { 218, 0, "", "P -4 3 n", " P -4n 2 3" , ";EK""342""H8K""045""HE>""315"";8>""201""8KH""531""E>H""234""EK;""504""8>;""120""153""KH8""423"">;8""450""K;E"">HE" }, { 219, 0, "", "F -4 3 c", " F -4a 2 3" , ";35""EH2""485""045""H32""E;5""182""201""854""KE1""3>4""234""E51""K84""0>1""120""1KE""548""H2E"">10""450""51E"">HE" }, { 220, 0, "", "I -4 3 d", " I -4bd 2c 3" , "E""@<9""H58""M""342"";E>""045"";8K""315""HEK""201""E>;""531""8K;""234""8>H""504""EKH""120""153"">;E""423""KHE""450"">H8""K;8" }, { 224, '1', "", "P n -3 m", " P 4n 2 3 -1n" , "H8>""342"";E>""045"";8K""315""HEK""201""E>;""531""8K;""234""8>H""504""EKH""120""153"">;E""423""KHE""450"">H8""K;8" }, { 224, '2', "", "P n -3 m", "-P 4bc 2bc 3" , "48>""EH2"";3>""0HK"";85""E1K""435""201""3>;""KE1""85;""2EH""8>4""K0H""354""120""1KE"">;3""H2E""543""HK0"">48""5;8" }, { 225, 0, "", "F m -3 m", "-F 4 2 3" , "402""342""132""045""105""315""435""201""321""531""051""234""024""504""354""120""153""213""423""543""450""240""510" }, { 226, 0, "", "F m -3 c", "-F 4a 2 3" , "H02""EH2""1E2""045"";05""E;5""4E5""201""E21""KE1""0K1""234""824""K84""3K4""120""1KE""21E""H2E""K43""450""248""K;8" }, { 227, '1', "", "F d -3 m", " F 4d 2 3 -1d" , "I9@""3H>""=FC""045""<9M""3;K""JFP""201""F@<""5E;"":M=""234""9@I""58H""GMJ""120"";5E""@=G""H>3""MIF""450""@J:""P=9" }, { 227, '2', "", "F d -3 m", "-F 4vw 2vw 3" , "49@""GI>""=3C""0IM""=9K""G1P""435""201""3@<""PF;"":5=""2FI"":@H""P0J""354""120"";PF""@=E""I>G""5HE""IM0""@49""K<:" }, { 228, '1', "", "F d -3 c", " F 4d 2 3 -1ad" , "I9@""3H>""=FC""045""<9M""3;K""JFP""201""F@<""5E;"":M=""234""9@I""58H""GMJ""120"";5E""@=G""H>3""MIF""450""@J:""P=9" }, { 228, '2', "", "F d -3 c", "-F 4ud 2vw 3" , "H9@""FJ>""=EC""0IM""<9K""F;P""4E5""201""E@<""MG;"":K=""2FI""9@H""M8J""3K4""120"";MG""@=3""J>F""KHE""IM0""@4:""5=9" }, { 229, 0, "", "I m -3 m", "-I 4 2 3" , "402""342""132""045""105""315""435""201""321""531""051""234""024""504""354""120""153""213""423""543""450""240""510" }, { 230, 0, "", "I a -3 d", "-I 4bd 2c 3" , "I:@""E4>""E""MIF""H58""CJ9""P<:" }, /* end of the generated code */ { 0, 0, "", "", "", "" } }; int get_seitz_mx_count(const SpaceGroupSetting *sgs) { assert(strlen(sgs->encoded_seitz) % 3 == 0); return strlen(sgs->encoded_seitz) / 3; } void decode_seitz_mx(char x, char y, char z, SeitzMatrix *sm) { int i; char a[] = { x, y, z }; for (i = 0; i != 3; ++i) { const ThirdOfSeitzMx *c = &seitz_mx_codes[a[i] - '0']; sm->R[3*i + 0] = c->r1; sm->R[3*i + 1] = c->r2; sm->R[3*i + 2] = c->r3; sm->T[i] = c->t; } } void get_seitz_mx(const SpaceGroupSetting *sgs, int n, SeitzMatrix *sm) { assert(n < (int) strlen(sgs->encoded_seitz) / 3); decode_seitz_mx(sgs->encoded_seitz[3*n], sgs->encoded_seitz[3*n+1], sgs->encoded_seitz[3*n+2], sm); } const SpaceGroupSetting* find_first_sg_with_number(int sgn) { const SpaceGroupSetting *p; for (p = space_group_settings; p->sgnumber != 0; ++p) if (p->sgnumber == sgn) return p; return NULL; } const char* SchoenfliesSymbols[] = { "C1^1", "Ci^1", "C2^1", "C2^2", "C2^3", "Cs^1", "Cs^2", "Cs^3", "Cs^4", "C2h^1", "C2h^2", "C2h^3", "C2h^4", "C2h^5", "C2h^6", "D2^1", "D2^2", "D2^3", "D2^4", "D2^5", "D2^6", "D2^7", "D2^8", "D2^9", "C2v^1", "C2v^2", "C2v^3", "C2v^4", "C2v^5", "C2v^6", "C2v^7", "C2v^8", "C2v^9", "C2v^10", "C2v^11", "C2v^12", "C2v^13", "C2v^14", "C2v^15", "C2v^16", "C2v^17", "C2v^18", "C2v^19", "C2v^20", "C2v^21", "C2v^22", "D2h^1", "D2h^2", "D2h^3", "D2h^4", "D2h^5", "D2h^6", "D2h^7", "D2h^8", "D2h^9", "D2h^10", "D2h^11", "D2h^12", "D2h^13", "D2h^14", "D2h^15", "D2h^16", "D2h^17", "D2h^18", "D2h^19", "D2h^20", "D2h^21", "D2h^22", "D2h^23", "D2h^24", "D2h^25", "D2h^26", "D2h^27", "D2h^28", "C4^1", "C4^2", "C4^3", "C4^4", "C4^5", "C4^6", "S4^1", "S4^2", "C4h^1", "C4h^2", "C4h^3", "C4h^4", "C4h^5", "C4h^6", "D4^1", "D4^2", "D4^3", "D4^4", "D4^5", "D4^6", "D4^7", "D4^8", "D4^9", "D4^10", "C4v^1", "C4v^2", "C4v^3", "C4v^4", "C4v^5", "C4v^6", "C4v^7", "C4v^8", "C4v^9", "C4v^10", "C4v^11", "C4v^12", "D2d^1", "D2d^2", "D2d^3", "D2d^4", "D2d^5", "D2d^6", "D2d^7", "D2d^8", "D2d^9", "D2d^10", "D2d^11", "D2d^12", "D4h^1", "D4h^2", "D4h^3", "D4h^4", "D4h^5", "D4h^6", "D4h^7", "D4h^8", "D4h^9", "D4h^10", "D4h^11", "D4h^12", "D4h^13", "D4h^14", "D4h^15", "D4h^16", "D4h^17", "D4h^18", "D4h^19", "D4h^20", "C3^1", "C3^2", "C3^3", "C3^4", "C3i^1", "C3i^2", "D3^1", "D3^2", "D3^3", "D3^4", "D3^5", "D3^6", "D3^7", "C3v^1", "C3v^2", "C3v^3", "C3v^4", "C3v^5", "C3v^6", "D3d^1", "D3d^2", "D3d^3", "D3d^4", "D3d^5", "D3d^6", "C6^1", "C6^2", "C6^3", "C6^4", "C6^5", "C6^6", "C3h^1", "C6h^1", "C6h^2", "D6^1", "D6^2", "D6^3", "D6^4", "D6^5", "D6^6", "C6v^1", "C6v^2", "C6v^3", "C6v^4", "D3h^1", "D3h^2", "D3h^3", "D3h^4", "D6h^1", "D6h^2", "D6h^3", "D6h^4", "T^1", "T^2", "T^3", "T^4", "T^5", "Th^1", "Th^2", "Th^3", "Th^4", "Th^5", "Th^6", "Th^7", "O^1", "O^2", "O^3", "O^4", "O^5", "O^6", "O^7", "O^8", "Td^1", "Td^2", "Td^3", "Td^4", "Td^5", "Td^6", "Oh^1", "Oh^2", "Oh^3", "Oh^4", "Oh^5", "Oh^6", "Oh^7", "Oh^8", "Oh^9", "Oh^10" }; /* The table below was produced from the table above by this Python script: def u_superscript(d): if d == '1': n = 0xB9 elif d == '2': n = 0xB2 elif d == '3': n = 0xB3 else: n = 0x2070 + int(d) return unichr(n).encode('utf8').encode('string-escape') for s in table_above: base, idx = s.split('^') print ('"' + base + "".join(u_superscript(c) for c in idx) + '",'), */ const char* SchoenfliesSymbolsAsUTF8[] = { "C1\xc2\xb9", "Ci\xc2\xb9", "C2\xc2\xb9", "C2\xc2\xb2", "C2\xc2\xb3", "Cs\xc2\xb9", "Cs\xc2\xb2", "Cs\xc2\xb3", "Cs\xe2\x81\xb4", "C2h\xc2\xb9", "C2h\xc2\xb2", "C2h\xc2\xb3", "C2h\xe2\x81\xb4", "C2h\xe2\x81\xb5", "C2h\xe2\x81\xb6", "D2\xc2\xb9", "D2\xc2\xb2", "D2\xc2\xb3", "D2\xe2\x81\xb4", "D2\xe2\x81\xb5", "D2\xe2\x81\xb6", "D2\xe2\x81\xb7", "D2\xe2\x81\xb8", "D2\xe2\x81\xb9", "C2v\xc2\xb9", "C2v\xc2\xb2", "C2v\xc2\xb3", "C2v\xe2\x81\xb4", "C2v\xe2\x81\xb5", "C2v\xe2\x81\xb6", "C2v\xe2\x81\xb7", "C2v\xe2\x81\xb8", "C2v\xe2\x81\xb9", "C2v\xc2\xb9\xe2\x81\xb0", "C2v\xc2\xb9\xc2\xb9", "C2v\xc2\xb9\xc2\xb2", "C2v\xc2\xb9\xc2\xb3", "C2v\xc2\xb9\xe2\x81\xb4", "C2v\xc2\xb9\xe2\x81\xb5", "C2v\xc2\xb9\xe2\x81\xb6", "C2v\xc2\xb9\xe2\x81\xb7", "C2v\xc2\xb9\xe2\x81\xb8", "C2v\xc2\xb9\xe2\x81\xb9", "C2v\xc2\xb2\xe2\x81\xb0", "C2v\xc2\xb2\xc2\xb9", "C2v\xc2\xb2\xc2\xb2", "D2h\xc2\xb9", "D2h\xc2\xb2", "D2h\xc2\xb3", "D2h\xe2\x81\xb4", "D2h\xe2\x81\xb5", "D2h\xe2\x81\xb6", "D2h\xe2\x81\xb7", "D2h\xe2\x81\xb8", "D2h\xe2\x81\xb9", "D2h\xc2\xb9\xe2\x81\xb0", "D2h\xc2\xb9\xc2\xb9", "D2h\xc2\xb9\xc2\xb2", "D2h\xc2\xb9\xc2\xb3", "D2h\xc2\xb9\xe2\x81\xb4", "D2h\xc2\xb9\xe2\x81\xb5", "D2h\xc2\xb9\xe2\x81\xb6", "D2h\xc2\xb9\xe2\x81\xb7", "D2h\xc2\xb9\xe2\x81\xb8", "D2h\xc2\xb9\xe2\x81\xb9", "D2h\xc2\xb2\xe2\x81\xb0", "D2h\xc2\xb2\xc2\xb9", "D2h\xc2\xb2\xc2\xb2", "D2h\xc2\xb2\xc2\xb3", "D2h\xc2\xb2\xe2\x81\xb4", "D2h\xc2\xb2\xe2\x81\xb5", "D2h\xc2\xb2\xe2\x81\xb6", "D2h\xc2\xb2\xe2\x81\xb7", "D2h\xc2\xb2\xe2\x81\xb8", "C4\xc2\xb9", "C4\xc2\xb2", "C4\xc2\xb3", "C4\xe2\x81\xb4", "C4\xe2\x81\xb5", "C4\xe2\x81\xb6", "S4\xc2\xb9", "S4\xc2\xb2", "C4h\xc2\xb9", "C4h\xc2\xb2", "C4h\xc2\xb3", "C4h\xe2\x81\xb4", "C4h\xe2\x81\xb5", "C4h\xe2\x81\xb6", "D4\xc2\xb9", "D4\xc2\xb2", "D4\xc2\xb3", "D4\xe2\x81\xb4", "D4\xe2\x81\xb5", "D4\xe2\x81\xb6", "D4\xe2\x81\xb7", "D4\xe2\x81\xb8", "D4\xe2\x81\xb9", "D4\xc2\xb9\xe2\x81\xb0", "C4v\xc2\xb9", "C4v\xc2\xb2", "C4v\xc2\xb3", "C4v\xe2\x81\xb4", "C4v\xe2\x81\xb5", "C4v\xe2\x81\xb6", "C4v\xe2\x81\xb7", "C4v\xe2\x81\xb8", "C4v\xe2\x81\xb9", "C4v\xc2\xb9\xe2\x81\xb0", "C4v\xc2\xb9\xc2\xb9", "C4v\xc2\xb9\xc2\xb2", "D2d\xc2\xb9", "D2d\xc2\xb2", "D2d\xc2\xb3", "D2d\xe2\x81\xb4", "D2d\xe2\x81\xb5", "D2d\xe2\x81\xb6", "D2d\xe2\x81\xb7", "D2d\xe2\x81\xb8", "D2d\xe2\x81\xb9", "D2d\xc2\xb9\xe2\x81\xb0", "D2d\xc2\xb9\xc2\xb9", "D2d\xc2\xb9\xc2\xb2", "D4h\xc2\xb9", "D4h\xc2\xb2", "D4h\xc2\xb3", "D4h\xe2\x81\xb4", "D4h\xe2\x81\xb5", "D4h\xe2\x81\xb6", "D4h\xe2\x81\xb7", "D4h\xe2\x81\xb8", "D4h\xe2\x81\xb9", "D4h\xc2\xb9\xe2\x81\xb0", "D4h\xc2\xb9\xc2\xb9", "D4h\xc2\xb9\xc2\xb2", "D4h\xc2\xb9\xc2\xb3", "D4h\xc2\xb9\xe2\x81\xb4", "D4h\xc2\xb9\xe2\x81\xb5", "D4h\xc2\xb9\xe2\x81\xb6", "D4h\xc2\xb9\xe2\x81\xb7", "D4h\xc2\xb9\xe2\x81\xb8", "D4h\xc2\xb9\xe2\x81\xb9", "D4h\xc2\xb2\xe2\x81\xb0", "C3\xc2\xb9", "C3\xc2\xb2", "C3\xc2\xb3", "C3\xe2\x81\xb4", "C3i\xc2\xb9", "C3i\xc2\xb2", "D3\xc2\xb9", "D3\xc2\xb2", "D3\xc2\xb3", "D3\xe2\x81\xb4", "D3\xe2\x81\xb5", "D3\xe2\x81\xb6", "D3\xe2\x81\xb7", "C3v\xc2\xb9", "C3v\xc2\xb2", "C3v\xc2\xb3", "C3v\xe2\x81\xb4", "C3v\xe2\x81\xb5", "C3v\xe2\x81\xb6", "D3d\xc2\xb9", "D3d\xc2\xb2", "D3d\xc2\xb3", "D3d\xe2\x81\xb4", "D3d\xe2\x81\xb5", "D3d\xe2\x81\xb6", "C6\xc2\xb9", "C6\xc2\xb2", "C6\xc2\xb3", "C6\xe2\x81\xb4", "C6\xe2\x81\xb5", "C6\xe2\x81\xb6", "C3h\xc2\xb9", "C6h\xc2\xb9", "C6h\xc2\xb2", "D6\xc2\xb9", "D6\xc2\xb2", "D6\xc2\xb3", "D6\xe2\x81\xb4", "D6\xe2\x81\xb5", "D6\xe2\x81\xb6", "C6v\xc2\xb9", "C6v\xc2\xb2", "C6v\xc2\xb3", "C6v\xe2\x81\xb4", "D3h\xc2\xb9", "D3h\xc2\xb2", "D3h\xc2\xb3", "D3h\xe2\x81\xb4", "D6h\xc2\xb9", "D6h\xc2\xb2", "D6h\xc2\xb3", "D6h\xe2\x81\xb4", "T\xc2\xb9", "T\xc2\xb2", "T\xc2\xb3", "T\xe2\x81\xb4", "T\xe2\x81\xb5", "Th\xc2\xb9", "Th\xc2\xb2", "Th\xc2\xb3", "Th\xe2\x81\xb4", "Th\xe2\x81\xb5", "Th\xe2\x81\xb6", "Th\xe2\x81\xb7", "O\xc2\xb9", "O\xc2\xb2", "O\xc2\xb3", "O\xe2\x81\xb4", "O\xe2\x81\xb5", "O\xe2\x81\xb6", "O\xe2\x81\xb7", "O\xe2\x81\xb8", "Td\xc2\xb9", "Td\xc2\xb2", "Td\xc2\xb3", "Td\xe2\x81\xb4", "Td\xe2\x81\xb5", "Td\xe2\x81\xb6", "Oh\xc2\xb9", "Oh\xc2\xb2", "Oh\xc2\xb3", "Oh\xe2\x81\xb4", "Oh\xe2\x81\xb5", "Oh\xe2\x81\xb6", "Oh\xe2\x81\xb7", "Oh\xe2\x81\xb8", "Oh\xe2\x81\xb9", "Oh\xc2\xb9\xe2\x81\xb0", }; /* * PowderCell uses settings (the second number after RGNR) that are listed at: * http://www.ccp14.ac.uk/ccp/web-mirrors/powdcell/a_v/v_1/powder/details/setting.htm * The following table was generated from PCWSPGR.DAT file. In this file * lines starting with "spgr" contain description of settings. * Examples: * * spgr 3 1 3 0 2 4 1 P 1 2 1 * spgr 48 1 5 0 8 12 3 P n n n * spgr 48 2 5 1 4 12 2 P n n n * spgr 155 1 11 0 6 5 2 R 3 2 * spgr 155 2 10 0 6 5 2 R 3 2 * * We used the following records from these lines: * - the number of space-group type used in IT generally (2nd record) * - the corresponding Laue group (actually the code explained below, 4th) * - the existence of a inversion centre in origin (0...no, 1...yes) (5th) * - the full Hermann-Mauguin symbol (the last one), * * The code of Laue group is useful to distinguish :R and :H settings: * 8 trigonal, rhombohedral coordinate system (-3) * 9 trigonal, hexagonal coordinate system (-3) * 10 trigonal, rhombohedral coordinate system (-3m) * 11 trigonal, hexagonal coordinate system (-3m) * Here we have a dictionary to match them with the settings in the table above. * E.g. sg=15, pc_setting==9, std_setting==3 means that * "RGNR 15 9" <-> 4th setting for SG 15 in space_group_settings[] * If there is only one position in space_group_settings[] for given SG number, * of pc_setting=n corresponds to n-th position in space_group_settings[], * the item is omitted. */ typedef struct { unsigned char sg; /* space group number */ /* number that goes after SG number in PowderCell .cel file (1-18 or 0) */ unsigned char pc_setting; /* 0 - 1st setting for this SG in the table above, 1 - 2nd, ... */ unsigned char std_setting; } PowderCellSgSetting; const PowderCellSgSetting powdercell_settings[] = { {3,2,0}, {3,3,1}, {3,4,1}, {3,5,2}, {3,6,2}, {4,2,0}, {4,3,1}, {4,4,1}, {4,5,2}, {4,6,2}, {5,3,3}, {5,4,4}, {5,5,6}, {5,6,7}, {5,7,1}, {5,8,0}, {5,9,4}, {5,10,3}, {5,11,7}, {5,12,6}, {5,13,2}, {5,14,2}, {5,15,5}, {5,16,5}, {5,17,8}, {5,18,8}, {6,2,0}, {6,3,1}, {6,4,1}, {6,5,2}, {6,6,2}, {7,2,2}, {7,3,3}, {7,4,5}, {7,5,6}, {7,6,8}, {7,7,1}, {7,8,1}, {7,9,4}, {7,10,4}, {7,11,7}, {7,12,7}, {7,13,2}, {7,14,0}, {7,15,5}, {7,16,3}, {7,17,8}, {7,18,6}, {8,3,3}, {8,4,4}, {8,5,6}, {8,6,7}, {8,7,1}, {8,8,0}, {8,9,4}, {8,10,3}, {8,11,7}, {8,12,6}, {8,13,2}, {8,14,2}, {8,15,5}, {8,16,5}, {8,17,8}, {8,18,8}, {9,2,3}, {9,3,6}, {9,4,9}, {9,5,12}, {9,6,15}, {9,7,1}, {9,8,4}, {9,9,7}, {9,10,10}, {9,11,13}, {9,12,16}, {9,13,2}, {9,14,5}, {9,15,8}, {9,16,11}, {9,17,14}, {10,2,0}, {10,3,1}, {10,4,1}, {10,5,2}, {10,6,2}, {11,2,0}, {11,3,1}, {11,4,1}, {11,5,2}, {11,6,2}, {12,3,3}, {12,4,4}, {12,5,6}, {12,6,7}, {12,7,1}, {12,8,0}, {12,9,4}, {12,10,3}, {12,11,7}, {12,12,6}, {12,13,2}, {12,14,2}, {12,15,5}, {12,16,5}, {12,17,8}, {12,18,8}, {13,2,2}, {13,3,3}, {13,4,5}, {13,5,6}, {13,6,8}, {13,7,1}, {13,8,1}, {13,9,4}, {13,10,4}, {13,11,7}, {13,12,7}, {13,13,2}, {13,14,0}, {13,15,5}, {13,16,3}, {13,17,8}, {13,18,6}, {14,2,2}, {14,3,3}, {14,4,5}, {14,5,6}, {14,6,8}, {14,7,1}, {14,8,1}, {14,9,4}, {14,10,4}, {14,11,7}, {14,12,7}, {14,13,2}, {14,14,0}, {14,15,5}, {14,16,3}, {14,17,8}, {14,18,6}, {15,2,3}, {15,3,6}, {15,4,9}, {15,5,12}, {15,6,15}, {15,7,1}, {15,8,4}, {15,9,7}, {15,10,10}, {15,11,13}, {15,12,16}, {15,13,2}, {15,14,5}, {15,15,8}, {15,16,11}, {15,17,14}, {17,2,0}, {17,3,1}, {17,4,1}, {17,5,2}, {17,6,2}, {18,2,0}, {18,3,1}, {18,4,1}, {18,5,2}, {18,6,2}, {20,2,0}, {20,3,1}, {20,4,1}, {20,5,2}, {20,6,2}, {21,2,0}, {21,3,1}, {21,4,1}, {21,5,2}, {21,6,2}, {25,2,0}, {25,3,1}, {25,4,1}, {25,5,2}, {25,6,2}, {27,2,0}, {27,3,1}, {27,4,1}, {27,5,2}, {27,6,2}, {32,2,0}, {32,3,1}, {32,4,1}, {32,5,2}, {32,6,2}, {34,2,0}, {34,3,1}, {34,4,1}, {34,5,2}, {34,6,2}, {35,2,0}, {35,3,1}, {35,4,1}, {35,5,2}, {35,6,2}, {37,2,0}, {37,3,1}, {37,4,1}, {37,5,2}, {37,6,2}, {42,2,0}, {42,3,1}, {42,4,1}, {42,5,2}, {42,6,2}, {43,2,0}, {43,3,1}, {43,4,1}, {43,5,2}, {43,6,2}, {44,2,0}, {44,3,1}, {44,4,1}, {44,5,2}, {44,6,2}, {45,2,0}, {45,3,1}, {45,4,1}, {45,5,2}, {45,6,2}, {48,3,0}, {48,4,1}, {48,5,0}, {48,6,1}, {48,7,0}, {48,8,1}, {48,9,0}, {48,10,1}, {48,11,0}, {48,12,1}, {49,2,0}, {49,3,1}, {49,4,1}, {49,5,2}, {49,6,2}, {50,3,0}, {50,4,1}, {50,5,2}, {50,6,3}, {50,7,2}, {50,8,3}, {50,9,4}, {50,10,5}, {50,11,4}, {50,12,5}, {55,2,0}, {55,3,1}, {55,4,1}, {55,5,2}, {55,6,2}, {56,2,0}, {56,3,1}, {56,4,1}, {56,5,2}, {56,6,2}, {58,2,0}, {58,3,1}, {58,4,1}, {58,5,2}, {58,6,2}, {59,3,0}, {59,4,1}, {59,5,2}, {59,6,3}, {59,7,2}, {59,8,3}, {59,9,4}, {59,10,5}, {59,11,4}, {59,12,5}, {61,3,0}, {61,4,1}, {61,5,0}, {61,6,1}, {65,2,0}, {65,3,1}, {65,4,1}, {65,5,2}, {65,6,2}, {66,2,0}, {66,3,1}, {66,4,1}, {66,5,2}, {66,6,2}, {70,3,0}, {70,4,1}, {70,5,0}, {70,6,1}, {70,7,0}, {70,8,1}, {70,9,0}, {70,10,1}, {70,11,0}, {70,12,1}, {72,2,0}, {72,3,1}, {72,4,1}, {72,5,2}, {72,6,2}, {73,3,0}, {73,4,1}, {73,5,0}, {73,6,1}, {0,0,0} }; const SpaceGroupSetting* get_sg_from_powdercell_rgnr(int sgn, int setting) { const PowderCellSgSetting *i; const SpaceGroupSetting *sgs0 = find_first_sg_with_number(sgn); if (setting == 0 || sgs0 == NULL || (sgs0+1)->sgnumber != sgn) return sgs0; for (i = powdercell_settings; i->sg != 0; ++i) if (i->sg == sgn && i->pc_setting) return sgs0 + i->std_setting; /* if we are here, the setting is not in PowderCell table, * i.e. std_setting == pc_setting - 1 */ return sgs0 + setting - 1; } #if 0 ----------------------------- sm_dict.py ------------------------------- from cctbx import sgtbx smrows = {} for s in sgtbx.space_group_symbol_iterator(): #print s.number(), s.universal_hermann_mauguin().replace(" ","_") sg = sgtbx.space_group(s.hall()) for i in sg.smx(): sm = i.as_int_array() for n, s in enumerate(i.as_xyz().split(",")): if s not in smrows: smrows[s] = sm[3*n:3*n+3] + (sm[9+n],) else: assert smrows[s] == sm[3*n:3*n+3] + (sm[9+n],) keys = sorted(smrows.keys(), cmp=lambda x, y: cmp(len(x), len(y)) or cmp(x,y)) if __name__ == '__main__': for n, k in enumerate(keys): print '/* %s */ { "%-8s, %2d,%2d,%2d,%3d },' % ( (chr(n+ord('0')),k+'"') + smrows[k]) ----------------------------- list_sg.py ------------------------------- from cctbx import sgtbx import sm_dict def encode_xyz(xyz): return "".join(chr(sm_dict.keys.index(t)+ord('0')) for t in xyz.split(",")) for s in sgtbx.space_group_symbol_iterator(): ext_ = s.extension() ext = ("'%s'" % ext_ if (ext_ and ext_ != '\0') else "0") qualif = '"%s"' % s.qualifier() hm = '"%s",' % s.hermann_mauguin() hall = '"%s"' % s.hall().replace('"', r'\"') sm = '""'.join(encode_xyz(m.as_xyz()) for m in sgtbx.space_group(s.hall()).smx() if not m.is_unit_mx()) print '{ %3d, %3s, %6s, %-13s %-17s,\n "%s" },' % ( s.number(), ext, qualif, hm, hall, sm) #endif fityk-1.3.1/wxgui/sgtables.h000066400000000000000000000033121302634723100157620ustar00rootroot00000000000000/* sgtables.h * Author: Marcin Wojdyr (only the code, not data) * Licence: GNU General Public License ver. 2+ * * Data generated by cctbx (http://cctbx.sourceforge.net): * - tables that contain symbols of 230 crystallographic space groups * and symbols of 530 space group settings, all generated by cctbx. * - seitz matrices for each of 530 settings, * - translation of setting numbers used in PowderCell's .cel files * to more popular setting symbols */ #ifndef FITYK_SGTABLES_H_ #define FITYK_SGTABLES_H_ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ typedef struct { int R[9]; int T[3]; /* divide by 12. before use */ } SeitzMatrix; typedef struct { char txt[8]; char r1, r2, r3, t; } ThirdOfSeitzMx; typedef struct { int sgnumber; /* space group number (1-230) */ char ext; /* '1', '2', 'H', 'R' or '\0' */ char qualif[5]; /* e.g. "-cba" or "b1" */ char HM[11]; /* H-M symbol; nul-terminated string */ char Hall[16]; /* Hall symbol; nul-terminated string */ /* encoded seitz matrices, without the unit matrix */ const char* encoded_seitz; } SpaceGroupSetting; extern const ThirdOfSeitzMx seitz_mx_codes[]; extern const SpaceGroupSetting space_group_settings[]; extern const char* SchoenfliesSymbols[]; extern const char* SchoenfliesSymbolsAsUTF8[]; int get_seitz_mx_count(const SpaceGroupSetting *sgs); void decode_seitz_mx(char x, char y, char z, SeitzMatrix *sm); void get_seitz_mx(const SpaceGroupSetting *sgs, int n, SeitzMatrix *sm); const SpaceGroupSetting* find_first_sg_with_number(int sgn); const SpaceGroupSetting* get_sg_from_powdercell_rgnr(int sgn, int setting); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* FITYK_SGTABLES_H_ */ fityk-1.3.1/wxgui/sidebar.cpp000066400000000000000000001106421302634723100161270ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// class SideBar #include #include #include #include #include "sidebar.h" #include "parpan.h" #include "listptxt.h" #include "gradient.h" #include "cmn.h" //SpinCtrl, ProportionalSplitter, change_color_dlg, ... #include "frame.h" //frame #include "plotpane.h" #include "mplot.h" #include "fityk/common.h" //vector4, join_vector, S(), ... #include "fityk/logic.h" #include "fityk/data.h" #include "fityk/model.h" #include "fityk/func.h" #include "img/add.xpm" #include "img/sum.xpm" #include "img/rename.xpm" #include "img/close.xpm" #include "img/colorsel.xpm" #include "img/editf.xpm" #include "img/shiftup.xpm" #include "img/dpsize.xpm" //#include "img/convert.xpm" #include "img/copyfunc.xpm" #include "img/unused.xpm" #include "img/zshift.xpm" #include "img/eq_fwhm.h" #include "img/eq_shape.h" using namespace std; using fityk::Tplate; using fityk::Variable; using fityk::Function; using fityk::Model; enum { ID_DP_LIST = 27500 , ID_DP_LOOK , ID_DP_PSIZE , ID_DP_PLINE , ID_DP_PS , ID_DP_SHIFTUP , ID_DP_NEW , ID_DP_DUP , ID_DP_REN , ID_DP_DEL , ID_DP_CPF , ID_DP_COL , ID_FP_FILTER , ID_FP_LIST , ID_FP_NEW , ID_FP_DEL , ID_FP_EDIT , ID_FP_CHTYPE , ID_FP_COL , ID_FP_HWHM , ID_FP_SHAPE , ID_VP_LIST , ID_VP_NEW , ID_VP_DEL , ID_VP_EDIT }; //=============================================================== // SideBar //=============================================================== static void add_bitmap_button(wxWindow* parent, wxWindowID id, const char** xpm, wxString const& tip, wxSizer* sizer) { wxBitmapButton *btn = new wxBitmapButton(parent, id, wxBitmap(xpm)); btn->SetToolTip(tip); sizer->Add(btn); } // wxToggleBitmapButton was added in 2.9. We use wxToggleButton instead static void add_toggle_bitmap_button(wxWindow* parent, wxWindowID id, wxString const& /*label*/, const wxBitmap& bmp, wxString const& tip, wxSizer* sizer) { /* wxToggleButton *btn = new wxToggleButton(parent, id, label, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); */ wxBitmapToggleButton *btn = new wxBitmapToggleButton(parent, id, bmp); btn->SetToolTip(tip); sizer->Add(btn, wxSizerFlags().Expand()); } BEGIN_EVENT_TABLE(SideBar, ProportionalSplitter) EVT_BUTTON (ID_DP_NEW, SideBar::OnDataButtonNew) EVT_BUTTON (ID_DP_DUP, SideBar::OnDataButtonDup) EVT_BUTTON (ID_DP_REN, SideBar::OnDataButtonRen) EVT_BUTTON (ID_DP_DEL, SideBar::OnDataButtonDel) EVT_BUTTON (ID_DP_CPF, SideBar::OnDataButtonCopyF) EVT_BUTTON (ID_DP_COL, SideBar::OnDataButtonCol) EVT_CHOICE (ID_DP_LOOK, SideBar::OnDataLookChanged) EVT_SPINCTRL (ID_DP_PSIZE, SideBar::OnDataPSizeChanged) EVT_CHECKBOX (ID_DP_PLINE, SideBar::OnDataPLineChanged) EVT_CHECKBOX (ID_DP_PS, SideBar::OnDataPSChanged) EVT_SPINCTRL (ID_DP_SHIFTUP, SideBar::OnDataShiftUpChanged) EVT_LIST_ITEM_SELECTED(ID_DP_LIST, SideBar::OnDataSelectionChanged) EVT_LIST_ITEM_DESELECTED(ID_DP_LIST, SideBar::OnDataSelectionChanged) EVT_LIST_ITEM_FOCUSED(ID_DP_LIST, SideBar::OnDataFocusChanged) EVT_CHOICE (ID_FP_FILTER, SideBar::OnFuncFilterChanged) EVT_BUTTON (ID_FP_NEW, SideBar::OnFuncButtonNew) EVT_BUTTON (ID_FP_DEL, SideBar::OnFuncButtonDel) EVT_BUTTON (ID_FP_EDIT, SideBar::OnFuncButtonEdit) EVT_BUTTON (ID_FP_CHTYPE, SideBar::OnFuncButtonChType) EVT_BUTTON (ID_FP_COL, SideBar::OnFuncButtonCol) EVT_TOGGLEBUTTON (ID_FP_HWHM, SideBar::OnFuncButtonHwhm) EVT_TOGGLEBUTTON (ID_FP_SHAPE, SideBar::OnFuncButtonShape) EVT_LIST_ITEM_FOCUSED(ID_FP_LIST, SideBar::OnFuncFocusChanged) EVT_LIST_ITEM_SELECTED(ID_FP_LIST, SideBar::OnFuncSelectionChanged) EVT_LIST_ITEM_DESELECTED(ID_FP_LIST, SideBar::OnFuncSelectionChanged) EVT_BUTTON (ID_VP_NEW, SideBar::OnVarButtonNew) EVT_BUTTON (ID_VP_DEL, SideBar::OnVarButtonDel) EVT_BUTTON (ID_VP_EDIT, SideBar::OnVarButtonEdit) EVT_LIST_ITEM_FOCUSED(ID_VP_LIST, SideBar::OnVarFocusChanged) EVT_LIST_ITEM_SELECTED(ID_VP_LIST, SideBar::OnVarSelectionChanged) EVT_LIST_ITEM_DESELECTED(ID_VP_LIST, SideBar::OnVarSelectionChanged) END_EVENT_TABLE() SideBar::SideBar(wxWindow *parent, wxWindowID id) : ProportionalSplitter(parent, id, 0.75), pp_func_(NULL), active_function_(-1), skipOnFuncFocusChanged_(false) { //wxPanel *upper = new wxPanel(this, -1); //wxBoxSizer *upper_sizer = new wxBoxSizer(wxVERTICAL); nb = new wxNotebook(this, -1); //upper_sizer->Add(nb, 1, wxEXPAND); //upper->SetSizerAndFit(upper_sizer); param_panel_ = new ParameterPanel(this, -1, this); param_panel_->set_key_sink(frame, wxKeyEventHandler(FFrame::focus_input)); SplitHorizProp(nb, param_panel_); //----- data page ----- data_page = new wxPanel(nb, -1); wxBoxSizer *data_sizer = new wxBoxSizer(wxVERTICAL); d = new DataListPlusText(data_page, -1, ID_DP_LIST, vector4(pair("No", 43), pair("#F+#Z", 43), pair("Name", 108), pair("File", 0))); d->list->set_side_bar(this); data_sizer->Add(d, 1, wxEXPAND|wxALL, 1); wxBoxSizer *data_look_sizer = new wxBoxSizer(wxHORIZONTAL); wxArrayString choices; choices.Add(wxT("show all datasets")); choices.Add(wxT("show only selected")); choices.Add(wxT("shadow unselected")); choices.Add(wxT("hide all")); data_look = new wxChoice(data_page, ID_DP_LOOK, wxDefaultPosition, wxDefaultSize, choices); data_look_sizer->Add(data_look, 1, wxEXPAND); data_sizer->Add(data_look_sizer, 0, wxEXPAND); wxBoxSizer *data_spin_sizer = new wxBoxSizer(wxHORIZONTAL); // point-size spin button data_spin_sizer->Add(new wxStaticBitmap(data_page, -1, wxBitmap(dpsize_xpm)), 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5); dpsize_sc = new SpinCtrl(data_page, ID_DP_PSIZE, 1, 1, 9, 40); dpsize_sc->SetToolTip(wxT("data point size")); data_spin_sizer->Add(dpsize_sc, 0); // line between points dpline_cb = new wxCheckBox(data_page, ID_DP_PLINE, wxT("line")); dpline_cb->SetToolTip(wxT("line between data points")); data_spin_sizer->Add(dpline_cb, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5); // line between points dpsigma_cb = new wxCheckBox(data_page, ID_DP_PS, wxT("\u03C3")); // sigma dpsigma_cb->SetToolTip(wxT("show std. dev. of y")); data_spin_sizer->Add(dpsigma_cb, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5); // shift-up spin button data_spin_sizer->AddStretchSpacer(); data_spin_sizer->Add(new wxStaticBitmap(data_page, -1, wxBitmap(shiftup_xpm)), 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5); shiftup_sc = new SpinCtrl(data_page, ID_DP_SHIFTUP, 0, 0, 80, 50); shiftup_sc->SetToolTip(wxT("shift up (in % of plot height)")); data_spin_sizer->Add(shiftup_sc, 0); data_sizer->Add(data_spin_sizer, 0, wxEXPAND); wxBoxSizer *data_buttons_sizer = new wxBoxSizer(wxHORIZONTAL); add_bitmap_button(data_page, ID_DP_COL, colorsel_xpm, wxT("change color"), data_buttons_sizer); //add_bitmap_button(data_page, ID_DP_NEW, add_xpm, // wxT("new data"), data_buttons_sizer); add_bitmap_button(data_page, ID_DP_DUP, sum_xpm, wxT("duplicate/sum"), data_buttons_sizer); add_bitmap_button(data_page, ID_DP_CPF, copyfunc_xpm, wxT("copy F to next dataset"), data_buttons_sizer); add_bitmap_button(data_page, ID_DP_REN, rename_xpm, wxT("rename"), data_buttons_sizer); add_bitmap_button(data_page, ID_DP_DEL, close_xpm, wxT("delete"), data_buttons_sizer); data_sizer->Add(data_buttons_sizer, 0, wxEXPAND); data_page->SetSizerAndFit(data_sizer); nb->AddPage(data_page, wxT("data")); //----- functions page ----- func_page = new wxPanel(nb, -1); wxBoxSizer *func_sizer = new wxBoxSizer(wxVERTICAL); vector > fdata; fdata.push_back( pair("Name", 54) ); fdata.push_back( pair("Type", 80) ); fdata.push_back( pair("Center", 60) ); fdata.push_back( pair("Area", 0) ); fdata.push_back( pair("Height", 0) ); fdata.push_back( pair("FWHM", 0) ); f = new ListPlusText(func_page, -1, ID_FP_LIST, fdata); f->list->set_side_bar(this); func_sizer->Add(f, 1, wxEXPAND|wxALL, 1); wxBoxSizer *func_buttons_sizer = new wxBoxSizer(wxHORIZONTAL); add_toggle_bitmap_button(func_page, ID_FP_HWHM, wxT("=W"), GET_BMP(eq_fwhm), wxT("same HWHM for all functions"), func_buttons_sizer); add_toggle_bitmap_button(func_page, ID_FP_SHAPE, wxT("=S"), GET_BMP(eq_shape), wxT("same shape for all functions"), func_buttons_sizer); add_bitmap_button(func_page, ID_FP_NEW, add_xpm, wxT("new function"), func_buttons_sizer); add_bitmap_button(func_page, ID_FP_EDIT, editf_xpm, wxT("edit function"), func_buttons_sizer); //add_bitmap_button(func_page, ID_FP_CHTYPE, convert_xpm, // wxT("change type of function"), func_buttons_sizer); add_bitmap_button(func_page, ID_FP_COL, colorsel_xpm, wxT("change color"), func_buttons_sizer); add_bitmap_button(func_page, ID_FP_DEL, close_xpm, wxT("delete"), func_buttons_sizer); func_sizer->Add(func_buttons_sizer, 0, wxEXPAND); func_page->SetSizerAndFit(func_sizer); nb->AddPage(func_page, wxT("functions")); //----- variables page ----- var_page = new wxPanel(nb, -1); wxBoxSizer *var_sizer = new wxBoxSizer(wxVERTICAL); vector > vdata = vector4( pair("Name", 52), pair("#/#", 72), pair("value", 70), pair("formula", 0) ); v = new ListPlusText(var_page, -1, ID_VP_LIST, vdata); v->list->set_side_bar(this); var_sizer->Add(v, 1, wxEXPAND|wxALL, 1); wxBoxSizer *var_buttons_sizer = new wxBoxSizer(wxHORIZONTAL); add_bitmap_button(var_page, ID_VP_NEW, add_xpm, wxT("new variable"), var_buttons_sizer); add_bitmap_button(var_page, ID_VP_DEL, close_xpm, wxT("delete"), var_buttons_sizer); add_bitmap_button(var_page, ID_VP_EDIT, editf_xpm, wxT("edit variable"), var_buttons_sizer); var_sizer->Add(var_buttons_sizer, 0, wxEXPAND); var_page->SetSizerAndFit(var_sizer); nb->AddPage(var_page, wxT("variables")); } void SideBar::OnDataButtonNew (wxCommandEvent&) { exec("@+ = 0"); } void SideBar::OnDataButtonDup (wxCommandEvent&) { exec("@+ = " + join_vector(d->get_selected_data(), " + ")); } void SideBar::OnDataButtonRen (wxCommandEvent&) { int n = get_focused_data(); fityk::Data *data = ftk->dk.data(n); wxString old_title = s2wx(data->get_title()); wxString s = wxGetTextFromUser( wxString::Format(wxT("New name for dataset @%i"), n), wxT("Rename dataset"), old_title); if (!s.IsEmpty() && s != old_title) exec("@" + S(n) + ": title = '" + wx2s(s) + "'"); } void SideBar::delete_selected_items() { int n = nb->GetSelection(); if (n < 0) return; string txt = wx2s(nb->GetPageText(n)); vector elems; if (txt == "data") { elems = d->get_selected_data(); } else if (txt == "functions") { elems = get_selected_func(); vm_foreach (string, i, elems) *i = "%" + *i; } else if (txt == "variables") { elems = get_selected_vars(); vm_foreach (string, i, elems) *i = "$" + *i; } else assert(0); exec("delete " + join_vector(elems, ", ")); } void SideBar::OnDataButtonCopyF (wxCommandEvent&) { int n = get_focused_data(); if (n+1 >= ftk->dk.count()) return; d->list->Select(n, false); d->list->Select(n+1, true); d->list->Focus(n+1); string cmd = "@" + S(n+1) + ".F=copy(@" + S(n) + ".F)"; if (!ftk->dk.get_model(n)->get_zz().names.empty() || !ftk->dk.get_model(n+1)->get_zz().names.empty()) cmd += "; @" + S(n+1) + ".Z=copy(@" + S(n) + ".Z)"; if (ftk->mgr.find_function_nr("bg" + S(n)) != -1) cmd += "; %bg" + S(n+1) + "=copy(%bg" + S(n) + ")"; update_data_buttons(); exec(cmd); } void SideBar::OnDataButtonCol (wxCommandEvent&) { int sel_size = d->list->GetSelectedItemCount(); if (sel_size == 0) return; else if (sel_size == 1) { int n = d->list->GetFirstSelected(); wxColour col = frame->get_main_plot()->get_data_color(n); if (change_color_dlg(col)) { frame->get_main_plot()->set_data_color(n, col); update_lists(); frame->plot_pane()->refresh_plots(false, kMainPlot); } } else {//sel_size > 1 int first_sel = d->list->GetFirstSelected(); int last_sel = 0; for (int i = first_sel; i != -1; i = d->list->GetNextSelected(i)) last_sel = i; wxColour first_col = frame->get_main_plot()->get_data_color(first_sel); wxColour last_col = frame->get_main_plot()->get_data_color(last_sel); GradientDlg gd(this, -1, first_col, last_col); gd.FindWindow(wxID_APPLY)->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(SideBar::OnDataColorsChanged), NULL, this); gd.ShowModal(); } } void SideBar::OnDataColorsChanged(wxCommandEvent& event) { wxWindow* object = wxDynamicCast(event.GetEventObject(), wxWindow); if (object == NULL || object->GetId() != wxID_APPLY) return; GradientDlg *gd = static_cast(object->GetParent()); vector selected; for (int i = d->list->GetFirstSelected(), c = 0; i != -1; i = d->list->GetNextSelected(i), ++c) { selected.push_back(i); wxColour col = gd->get_value(c / (d->list->GetSelectedItemCount()-1.)); frame->get_main_plot()->set_data_color(i, col); } update_lists(); frame->plot_pane()->refresh_plots(false, kMainPlot); for (int i = 0; i != d->list->GetItemCount(); ++i) d->list->Select(i, contains_element(selected, i)); } void SideBar::OnDataLookChanged (wxCommandEvent&) { frame->plot_pane()->refresh_plots(false, kMainPlot); } void SideBar::OnDataShiftUpChanged (wxSpinEvent&) { frame->plot_pane()->refresh_plots(false, kMainPlot); } void SideBar::OnDataPSizeChanged (wxSpinEvent& event) { //for (int i = d->list->GetFirstSelected(); i != -1; // i = d->list->GetNextSelected(i)) // frame->get_main_plot()->set_data_point_size(i, event.GetPosition()); // now it is set globally frame->get_main_plot()->set_data_point_size(0, event.GetPosition()); frame->plot_pane()->refresh_plots(false, kMainPlot); } void SideBar::OnDataPLineChanged (wxCommandEvent& event) { frame->get_main_plot()->set_data_with_line(0, event.IsChecked()); frame->plot_pane()->refresh_plots(false, kMainPlot); } void SideBar::OnDataPSChanged (wxCommandEvent& event) { frame->get_main_plot()->set_data_with_sigma(0, event.IsChecked()); frame->plot_pane()->refresh_plots(false, kMainPlot); } void SideBar::OnFuncFilterChanged (wxCommandEvent&) { update_lists(false); } void SideBar::OnFuncButtonNew (wxCommandEvent&) { string peak_type = frame->get_peak_type(); const Tplate *tp = ftk->get_tpm()->get_tp(peak_type); string t = "%put_name_here = " + peak_type + "(" + join_vector(tp->fargs, "= , ") + "= )"; frame->edit_in_input(t); } void SideBar::OnFuncButtonEdit (wxCommandEvent&) { if (!pp_func_) return; string t = pp_func_->get_current_assignment(ftk->mgr.variables(), ftk->mgr.parameters()); frame->edit_in_input(t); } void SideBar::OnFuncButtonChType (wxCommandEvent&) { ftk->ui()->warn("Sorry. Changing type of function is not implemented yet."); } void SideBar::OnFuncButtonCol (wxCommandEvent&) { vector const& ffi = ftk->dk.get_model(frame->get_focused_data_index())->get_ff().idx; vector::const_iterator in_ff = find(ffi.begin(), ffi.end(), active_function_); if (in_ff == ffi.end()) return; int color_id = in_ff - ffi.begin(); wxColour col = frame->get_main_plot()->get_func_color(color_id); if (change_color_dlg(col)) { frame->get_main_plot()->set_func_color(color_id, col); update_lists(); frame->plot_pane()->refresh_plots(false, kMainPlot); } } void SideBar::OnVarButtonNew (wxCommandEvent&) { frame->edit_in_input("$put_name_here = "); } void SideBar::OnVarButtonEdit (wxCommandEvent&) { int n = get_focused_var(); if (n < 0 || n >= (int) ftk->mgr.variables().size()) return; const Variable* var = ftk->mgr.get_variable(n); string t = "$" + var->name + " = "+ var->get_formula(ftk->mgr.parameters()); frame->edit_in_input(t); } void SideBar::read_settings(wxConfigBase *cf) { cf->SetPath(wxT("/SideBar")); d->split(cfg_read_double(cf, wxT("dataProportion"), 0.75)); f->split(cfg_read_double(cf, wxT("funcProportion"), 0.75)); v->split(cfg_read_double(cf, wxT("varProportion"), 0.75)); data_look->Select(cf->Read(wxT("dataLook"), 1L)); } void SideBar::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("/SideBar")); cf->Write(wxT("dataProportion"), d->GetProportion()); cf->Write(wxT("funcProportion"), f->GetProportion()); cf->Write(wxT("varProportion"), v->GetProportion()); cf->Write(wxT("dataLook"), data_look->GetSelection()); } void SideBar::update_lists(bool nondata_changed) { Freeze(); d->update_data_list(nondata_changed); update_func_list(nondata_changed); update_var_list(); //-- enable/disable buttons update_data_buttons(); update_func_buttons(); update_var_buttons(); int n = get_focused_data(); dpline_cb->SetValue(frame->get_main_plot()->get_data_with_line(n)); dpsize_sc->SetValue(frame->get_main_plot()->get_data_point_size(n)); update_data_inf(); update_func_inf(); update_var_inf(); update_param_panel(); Thaw(); } void SideBar::update_func_list(bool nondata_changed) { MainPlot const* mplot = frame->get_main_plot(); wxColour const& bg_col = mplot->get_bg_color(); //functions static vector func_col_id; static int old_func_size; vector func_data; vector new_func_col_id; Model const* model = ftk->dk.get_model(frame->get_focused_data_index()); int func_size = ftk->mgr.functions().size(); if (active_function_ == -1) active_function_ = func_size - 1; else { if (active_function_ >= func_size || ftk->mgr.get_function(active_function_) != pp_func_) active_function_ = ftk->mgr.find_function_nr(active_function_name_); if (active_function_ == -1 || func_size == old_func_size+1) active_function_ = func_size - 1; } if (active_function_ != -1) active_function_name_ = ftk->mgr.get_function(active_function_)->name; else active_function_name_ = ""; int pos = -1; for (int i = 0; i < func_size; ++i) { if (i == active_function_) pos = new_func_col_id.size(); Function const* fun = ftk->mgr.get_function(i); func_data.push_back(fun->name); func_data.push_back(fun->tp()->name); realt a; func_data.push_back(fun->get_center(&a) ? S(a) : S("-")); func_data.push_back(fun->get_area(&a) ? S(a) : S("-")); func_data.push_back(fun->get_height(&a) ? S(a) : S("-")); func_data.push_back(fun->get_fwhm(&a) ? S(a) : S("-")); vector const& ffi = model->get_ff().idx; vector const& zzi = model->get_zz().idx; vector::const_iterator in_ff = find(ffi.begin(), ffi.end(), i); int color_id = -2; if (in_ff != ffi.end()) color_id = in_ff - ffi.begin(); else if (find(zzi.begin(), zzi.end(), i) != zzi.end()) color_id = -1; new_func_col_id.push_back(color_id); } wxImageList* func_images = 0; if (nondata_changed || func_col_id != new_func_col_id) { func_col_id = new_func_col_id; func_images = new wxImageList(16, 16); v_foreach (int, i, func_col_id) { if (*i == -2) func_images->Add(wxBitmap(unused_xpm)); else if (*i == -1) func_images->Add(wxBitmap(zshift_xpm)); else func_images->Add(make_color_bitmap16(mplot->get_func_color(*i), bg_col)); } } old_func_size = func_size; skipOnFuncFocusChanged_ = true; f->list->populate(func_data, func_images, pos); skipOnFuncFocusChanged_ = false; } void SideBar::update_var_list() { vector var_data; // count references first vector const& variables = ftk->mgr.variables(); vector var_vrefs(variables.size(), 0), var_frefs(variables.size(), 0); v_foreach (Variable*, i, variables) { for (int j = 0; j != (*i)->used_vars().get_count(); ++j) var_vrefs[(*i)->used_vars().get_idx(j)]++; } v_foreach (Function*, i, ftk->mgr.functions()) { for (int j = 0; j != (*i)->used_vars().get_count(); ++j) var_frefs[(*i)->used_vars().get_idx(j)]++; } for (int i = 0; i < size(variables); ++i) { const Variable* var = variables[i]; var_data.push_back(var->name); //name string refs = S(var_frefs[i]) + "+" + S(var_vrefs[i]) + " / " + S(var->used_vars().get_count()); var_data.push_back(refs); //refs var_data.push_back(S(var->value())); //value var_data.push_back(var->get_formula(ftk->mgr.parameters())); //formula } v->list->populate(var_data); } int SideBar::get_focused_data() const { wxListView *lv = d->list; int focused = lv->GetFocusedItem(); if (focused >= ftk->dk.count()) { d->update_data_list(false); focused = ftk->dk.count() - 1; lv->Focus(focused); } else if (focused < 0) { focused = 0; if (lv->GetItemCount() != 0) lv->Focus(focused); } return focused; } int SideBar::get_focused_var() const { if (ftk->mgr.variables().empty()) return -1; else { int n = v->list->GetFocusedItem(); return n > 0 ? n : 0; } } vector SideBar::get_selected_data_indices() { vector sel; if (!frame) // app not fully initialized yet return sel; wxListView *lv = d->list; if (ftk->dk.count() != lv->GetItemCount()) d->update_data_list(false); for (int i = lv->GetFirstSelected(); i != -1; i = lv->GetNextSelected(i)) sel.push_back(i); if (sel.empty()) { int n = get_focused_data(); if (lv->GetItemCount() > n) lv->Select(n, true); sel.push_back(n); } return sel; } // in plotting order vector SideBar::get_ordered_dataset_numbers() { wxListView *lv = d->list; if (ftk->dk.count() != lv->GetItemCount()) d->update_data_list(false); vector ordered; int count = lv->GetItemCount(); if (count == 0) return ordered; vector selected; int focused = lv->GetFocusedItem(); // focused but not selected is not important if (focused >= 0 && !lv->IsSelected(focused)) focused = -1; for (int i = 0; i < count; ++i) { if (lv->IsSelected(i)) { if (i != focused) selected.push_back(i); } else ordered.push_back(i); } ordered.insert(ordered.end(), selected.begin(), selected.end()); if (focused >= 0) ordered.push_back(focused); assert ((int) ordered.size() == count); return ordered; } string SideBar::get_sel_datasets_as_string() { if (ftk->dk.count() == 1) return ""; if (data_look->GetSelection() == 0) // all datasets return " @*"; string s; for (int i = d->list->GetFirstSelected(); i != -1; i = d->list->GetNextSelected(i)) s += " @" + S(i); if (s.empty()) s = " @" + S(get_focused_data()); return s; } //bool SideBar::is_func_selected(int n) const //{ // return f->list->IsSelected(n) || f->list->GetFocusedItem() == n; //} // void SideBar::activate_function(int n) { if (active_function_ == n) return; active_function_ = n; do_activate_function(); if (n < f->list->GetItemCount()) { skipOnFuncFocusChanged_ = true; f->list->Focus(n); skipOnFuncFocusChanged_ = false; for (int i = 0; i != f->list->GetItemCount(); ++i) f->list->Select(i, i == n); } } void SideBar::do_activate_function() { if (active_function_ != -1) active_function_name_ = ftk->mgr.get_function(active_function_)->name; else active_function_name_ = ""; frame->plot_pane()->refresh_plots(false, kMainPlot); update_func_inf(); update_param_panel(); } //void SideBar::select_datasets(const vector& datasets) //{ // if (datasets.empty()) // return; // wxListView *lv = d->list; // int n = lv->GetItemCount(); // for (int i = 0; i != n; ++i) // lv->Select(i, contains_element(datasets, i)); // if (datasets[0] < n) // lv->Focus(datasets[0]); //} // Focus is _not_ used for data-related operations, only for function-related // ones. Sum and functions are shown only for focused dataset. void SideBar::OnDataFocusChanged(wxListEvent &) { int n = d->list->GetFocusedItem(); //ftk->msg("[F] id:" + S(event.GetIndex()) + " focused:" // + S(d->list->GetFocusedItem())); if (n < 0) return; int length = ftk->dk.count(); if (length > 1) frame->plot_pane()->refresh_plots(false, kAllPlots); update_data_inf(); } void SideBar::OnDataSelectionChanged(wxListEvent &/*event*/) { if (data_look->GetSelection() != 0) // ! all datasets frame->plot_pane()->refresh_plots(false, kAllPlots); //bool selected= (event.GetEventType() == wxEVT_COMMAND_LIST_ITEM_SELECTED); //assert (selected // || event.GetEventType() == wxEVT_COMMAND_LIST_ITEM_DESELECTED); //long index = event.GetIndex(); //ftk->msg("id:" + S(index) + " e.sel:" + S(selected) // + " issel:" + S(d->list->IsSelected(index)) // + " foc:" + S(d->list->GetFocusedItem())); update_data_buttons(); } void SideBar::update_data_buttons() { bool not_the_last = get_focused_data()+1 < ftk->dk.count(); int sel_d = d->list->GetSelectedItemCount(); data_page->FindWindow(ID_DP_REN)->Enable(sel_d == 1); //data_page->FindWindow(ID_DP_DEL)->Enable(sel_d > 0); //data_page->FindWindow(ID_DP_COL)->Enable(sel_d > 0); data_page->FindWindow(ID_DP_CPF)->Enable(sel_d == 1 && not_the_last); } void SideBar::update_func_buttons() { int sel_f = f->list->GetSelectedItemCount(); func_page->FindWindow(ID_FP_DEL)->Enable(sel_f > 0); func_page->FindWindow(ID_FP_EDIT)->Enable(sel_f == 1); //func_page->FindWindow(ID_FP_CHTYPE)->Enable(sel_f > 0); func_page->FindWindow(ID_FP_COL)->Enable(sel_f > 0); bool has_hwhm = false, has_shape = false; v_foreach (Function*, i, ftk->mgr.functions()) { if (contains_element((*i)->tp()->fargs, "hwhm")) has_hwhm = true; if (contains_element((*i)->tp()->fargs, "shape")) has_shape = true; } func_page->FindWindow(ID_FP_HWHM)->Enable(has_hwhm); func_page->FindWindow(ID_FP_SHAPE)->Enable(has_shape); } void SideBar::update_var_buttons() { int sel_v = v->list->GetSelectedItemCount(); var_page->FindWindow(ID_VP_DEL)->Enable(sel_v > 0); var_page->FindWindow(ID_VP_EDIT)->Enable(sel_v == 1); } string SideBar::get_datasets_for_plot() { int first = frame->get_focused_data_index(); string s = "@" + S(first); if (data_look->GetSelection() == 0) // all datasets return s + ", @*"; else { // only selected datasets for (int i = d->list->GetFirstSelected(); i != -1; i = d->list->GetNextSelected(i)) if (i != first) s += ", @" + S(i); return s; } } void SideBar::update_data_inf() { int n = get_focused_data(); if (n < 0) return; wxTextCtrl* inf = d->inf; inf->Clear(); inf->AppendText(wxString::Format(wxT("@%d: "), n)); inf->AppendText(s2wx(ftk->dk.data(n)->get_info())); wxFileName fn(s2wx(ftk->dk.data(n)->get_filename())); if (fn.IsOk() && !fn.IsAbsolute()) { fn.MakeAbsolute(); inf->AppendText(wxT("\nPath: ") + fn.GetFullPath()); } inf->ShowPosition(0); // update also data filename in app window title frame->update_app_title(); } void SideBar::update_func_inf() { wxTextCtrl* inf = f->inf; inf->Clear(); if (active_function_ < 0) return; Function const* func = ftk->mgr.get_function(active_function_); realt a; if (func->get_center(&a)) inf->AppendText(wxT("Center: ") + s2wx(format1("%.10" REALT_LENGTH_MOD "g", a))); if (func->get_area(&a)) inf->AppendText(wxT("\nArea: ") + s2wx(S(a))); if (func->get_height(&a)) inf->AppendText(wxT("\nHeight: ") + s2wx(S(a))); if (func->get_fwhm(&a)) inf->AppendText(wxT("\nFWHM: ") + s2wx(S(a))); if (func->get_ibreadth(&a)) inf->AppendText(wxT("\nI.Breadth: ") + s2wx(S(a))); v_foreach (string, i, func->get_other_prop_names()) { func->get_other_prop(*i, &a); inf->AppendText(s2wx("\n" + *i + ": " + S(a))); } vector in; for (int i = 0; i < ftk->dk.count(); ++i) { const Model *model = ftk->dk.get_model(i); if (contains_element(model->get_ff().idx, active_function_)) in.push_back("@" + S(i) + ".F"); if (contains_element(model->get_zz().idx, active_function_)) in.push_back("@" + S(i) + ".Z"); } if (!in.empty()) inf->AppendText(s2wx("\nIn: " + join_vector(in, ", "))); inf->ShowPosition(0); } void SideBar::update_var_inf() { wxTextCtrl* inf = v->inf; inf->Clear(); int n = get_focused_var(); if (n < 0) return; const Variable* var = ftk->mgr.get_variable(n); string t = "$"+var->name + " = " + var->get_formula(ftk->mgr.parameters()); t += "\n" + var->domain.str(); inf->AppendText(s2wx(t)); vector in = ftk->mgr.get_variable_references(var->name); if (!in.empty()) inf->AppendText(s2wx("\nIn: " + join_vector(in, ", "))); inf->ShowPosition(0); } bool SideBar::howto_plot_dataset(int n, bool& shadowed, int& offset) const { // choice_idx: 0: "show all datasets" // 1: "show only selected" // 2: "shadow unselected" // 3: "hide all" int choice_idx = data_look->GetSelection(); bool sel = d->list->IsSelected(n) || d->list->GetFocusedItem() == n; if ((choice_idx == 1 && !sel) || choice_idx == 3) return false; shadowed = (choice_idx == 2 && !sel); offset = n * shiftup_sc->GetValue(); return true; } vector SideBar::get_selected_func() const { vector dd; for (int i = f->list->GetFirstSelected(); i != -1; i = f->list->GetNextSelected(i)) dd.push_back(wx2s(f->list->GetItemText(i))); //if (dd.empty() && f->list->GetItemCount() > 0) { // int n = f->list->GetFocusedItem(); // dd.push_back(ftk->mgr.get_function(n == -1 ? 0 : n)->xname); //} return dd; } vector SideBar::get_selected_vars() const { vector dd; for (int i = v->list->GetFirstSelected(); i != -1; i = v->list->GetNextSelected(i)) dd.push_back(ftk->mgr.get_variable(i)->name); return dd; } void SideBar::OnFuncFocusChanged(wxListEvent&) { if (skipOnFuncFocusChanged_) return; int n = f->list->GetFocusedItem(); if (n == -1) active_function_ = -1; else { string name = wx2s(f->list->GetItemText(n)); active_function_ = ftk->mgr.find_function_nr(name); } do_activate_function(); } void SideBar::OnVarFocusChanged(wxListEvent&) { update_var_inf(); } void SideBar::make_same_func_par(string const& p, bool checked) { vector cmds = ftk->mgr.share_par_cmd(p, checked); v_foreach(string, cmd, cmds) exec(*cmd); } void SideBar::on_parameter_changing(const std::vector& values) { frame->get_main_plot()->draw_overlay_func(pp_func_, values); } void SideBar::on_parameter_changed(int n) { string vname = wx2s(param_panel_->get_label2(n)); exec(vname + " = ~" + eS(param_panel_->get_value(n))); } void SideBar::on_parameter_lock_clicked(int n, int state) { string vname = wx2s(param_panel_->get_label2(n)); if (state == 0) exec(vname + " = ~{" + vname + "}"); else if (state == 1) exec(vname + " = {" + vname + "}"); else { // state == 2 nb->SetSelection(2); // "variables" page wxString vname_no_prefix = s2wx(vname.substr(1)); for (int i = 0; i != v->list->GetItemCount(); ++i) { if (v->list->GetItemText(i) == vname_no_prefix) { v->list->Select(i, true); v->list->EnsureVisible(i); v->list->Focus(i); } else v->list->Select(i, false); } } } void SideBar::update_param_panel() { int old_count = param_panel_->get_count(); if (active_function_ < 0) { param_panel_->delete_row_range(0, old_count); pp_func_ = NULL; return; } pp_func_ = ftk->mgr.get_function(active_function_); wxString new_label = s2wx("%" + pp_func_->name + " : " + pp_func_->tp()->name); if (param_panel_->get_title() != new_label) param_panel_->set_title(new_label); int new_count = pp_func_->nv(); // don't show too many parameters of vararg functions // (but if user defined function with large number of arguments // let him see all parameters) if (new_count > 8 && pp_func_->tp()->fargs.empty()) new_count = 8; if (new_count < old_count) param_panel_->delete_row_range(new_count, old_count); for (int i = 0; i < new_count; ++i) { const Variable* var = ftk->mgr.get_variable(pp_func_->used_vars().get_idx(i)); wxString label = s2wx(pp_func_->get_param(i)); if (var->is_simple() || var->is_constant()) { bool locked = var->is_constant(); param_panel_->set_normal_parameter(i, label, var->value(), locked, s2wx("$"+var->name)); } else param_panel_->set_disabled_parameter(i, label, var->value(), s2wx("$"+var->name)); } // Layout() is needed only when the layout has changed (e.g. when label2 // is shown for the first time). We call it always, just in case. param_panel_->Layout(); if (new_count != old_count) { int sash_pos = GetClientSize().GetHeight() - 3 - param_panel_->GetSizer()->GetMinSize().GetHeight(); if (sash_pos < GetSashPosition()) SetSashPosition(max(50, sash_pos)); } } fityk-1.3.1/wxgui/sidebar.h000066400000000000000000000110421302634723100155660ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_SIDEBAR_H_ #define FITYK_WX_SIDEBAR_H_ #include #include #include #include #include #include #include "cmn.h" // ProportionalSplitter #include "parpan.h" // ParameterPanelObserver class GradientDlg; class FancyRealCtrl; class ListPlusText; class DataListPlusText; namespace fityk { class Function; } class SideBar : public ProportionalSplitter, public ParameterPanelObserver { public: SideBar(wxWindow *parent, wxWindowID id=-1); void OnDataButtonNew (wxCommandEvent& event); void OnDataButtonDup (wxCommandEvent& event); void OnDataButtonRen (wxCommandEvent& event); void OnDataButtonDel (wxCommandEvent&) { delete_selected_items(); } void OnDataButtonCopyF (wxCommandEvent& event); void OnDataButtonCol (wxCommandEvent& event); void OnDataColorsChanged(wxCommandEvent& event); void OnDataLookChanged (wxCommandEvent& event); void OnDataPSizeChanged (wxSpinEvent& event); void OnDataPLineChanged (wxCommandEvent& event); void OnDataPSChanged (wxCommandEvent& event); void OnDataShiftUpChanged (wxSpinEvent& event); void OnFuncButtonNew (wxCommandEvent& event); void OnFuncButtonDel (wxCommandEvent&) { delete_selected_items(); } void OnFuncButtonEdit (wxCommandEvent& event); void OnFuncButtonChType (wxCommandEvent& event); void OnFuncButtonCol (wxCommandEvent& event); void OnFuncButtonHwhm (wxCommandEvent& event) { make_same_func_par("hwhm", event.IsChecked()); } void OnFuncButtonShape (wxCommandEvent& event) { make_same_func_par("shape", event.IsChecked()); } void OnVarButtonNew (wxCommandEvent& event); void OnVarButtonDel (wxCommandEvent&) { delete_selected_items(); } void OnVarButtonEdit (wxCommandEvent& event); void OnFuncFilterChanged (wxCommandEvent& event); void OnDataFocusChanged(wxListEvent &); void OnDataSelectionChanged(wxListEvent &); void update_data_buttons(); void update_func_buttons(); void update_var_buttons(); void OnFuncFocusChanged(wxListEvent &event); void OnFuncSelectionChanged(wxListEvent&) { update_func_buttons(); } void OnVarFocusChanged(wxListEvent &event); void OnVarSelectionChanged(wxListEvent&) { update_var_buttons(); } void read_settings(wxConfigBase *cf); void save_settings(wxConfigBase *cf) const; void update_lists(bool nondata_changed=true); /// get active dataset number -- if none is focused, return first one (0) int get_focused_data() const; int get_active_function() const { return active_function_; } int get_focused_var() const; std::vector get_ordered_dataset_numbers(); std::string get_sel_datasets_as_string(); std::vector get_selected_data_indices(); //bool is_func_selected(int n) const; //int set_selection(int page) { return nb->SetSelection(page); } void activate_function(int n); //void select_datasets(const std::vector& datasets); std::vector get_selected_data() const; bool howto_plot_dataset(int n, bool& shadowed, int& offset) const; std::vector get_selected_func() const; std::vector get_selected_vars() const; void update_data_inf(); void update_func_inf(); void update_var_inf(); void update_param_panel(); void delete_selected_items(); std::string get_datasets_for_plot(); DraggedFuncObserver* dragged_func_callback() { return param_panel_; } const std::vector& parpan_values() { return param_panel_->values(); } // implementation of ParameterPanelObserver virtual void on_parameter_changing(const std::vector& values); virtual void on_parameter_changed(int n); virtual void on_parameter_lock_clicked(int n, int state); private: wxNotebook *nb; wxPanel *data_page, *func_page, *var_page; fityk::Function const* pp_func_; ///parameter panel function ParameterPanel *param_panel_; DataListPlusText *d; ListPlusText *f, *v; wxChoice *data_look; wxSpinCtrl *shiftup_sc, *dpsize_sc; wxCheckBox *dpline_cb, *dpsigma_cb; int active_function_; std::string active_function_name_; bool skipOnFuncFocusChanged_; void update_func_list(bool nondata_changed); void update_var_list(); void do_activate_function(); void make_same_func_par(std::string const& p, bool checked); DECLARE_EVENT_TABLE() }; #endif fityk-1.3.1/wxgui/statbar.cpp000066400000000000000000000260411302634723100161550ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ /// Status Bar (FStatusBar) and dialog for its configuration (ConfStatBarDlg) #include #include #include #include #include "statbar.h" #include "cmn.h" //wx2s, s2wx, GET_BMP #include "fityk/common.h" //vector2 #include "fityk/lexer.h" //Lexer // icons #include "img/mouse16.h" #include "img/sbprefs.h" #include "img/ok24.h" using namespace std; //=============================================================== // FStatusBar //=============================================================== FStatusBar::FStatusBar(wxWindow *parent) : wxPanel(parent, -1), extra_parser(NULL), last_x(0), last_y(0) { wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL); split = new wxSplitterWindow(this, -1, wxDefaultPosition, wxDefaultSize, 0); wxPanel *panel_text = new wxPanel(split, -1); wxPanel *panel_coords = new wxPanel(split, -1); text = new wxStaticText(panel_text, -1, wxT("")); coords = new wxStaticText(panel_coords, -1, wxT(""), wxDefaultPosition, wxSize(200, -1)); wxFont font = coords->GetFont(); font.SetFamily(wxFONTFAMILY_TELETYPE); coords->SetFont(font); // using sizer here should not be necessary, but on wxGTK 2.8 `coords' // sometimes disappears, and these 3 lines are a workaround wxBoxSizer *coords_sizer = new wxBoxSizer(wxHORIZONTAL); coords_sizer->Add(coords, 1); panel_coords->SetSizerAndFit(coords_sizer); split->SplitVertically(panel_text, panel_coords); split->SetSashGravity(1.0); split->SetMinimumPaneSize(150); sizer->Add(split, wxSizerFlags(1).Centre().Border(wxLEFT)); prefbtn = new wxBitmapButton #ifdef __WXMSW__ // on wxMSW the default width is too small (this, -1, GET_BMP(sbprefs), wxDefaultPosition, wxSize(22, 16)); #else (this, -1, GET_BMP(sbprefs)); #endif prefbtn->SetToolTip(wxT("configure status bar")); sizer->Add(prefbtn, wxSizerFlags().Expand().Centre()); // wxALIGN_RIGHT flag for wxStaticText doesn't work on wxGTK 2.9 // (wx bug #10716), so we must align the text in a different way wxString long_hint = wxT("add-in-range"); lmouse_hint = new wxStaticText(this, -1, long_hint); rmouse_hint = new wxStaticText(this, -1, long_hint, wxDefaultPosition, wxDefaultSize, #ifdef __WXMAC__ // wxST_NO_AUTORESIZE breaks the layout // on wxCarbon 2.9.2 (I haven't investigate // it further) 0 #else wxST_NO_AUTORESIZE #endif ); mousebmp = new wxStaticBitmap(this, -1, GET_BMP(mouse16)); wxBoxSizer *lmouse_sizer = new wxBoxSizer(wxHORIZONTAL); lmouse_sizer->AddStretchSpacer(); lmouse_sizer->Add(lmouse_hint, wxSizerFlags().Right()); lmouse_sizer->SetMinSize(rmouse_hint->GetClientSize()); wxBoxSizer *hint_sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *vhint_sizer = new wxBoxSizer(wxHORIZONTAL); vhint_sizer->Add(lmouse_sizer, wxSizerFlags(1).Expand().FixedMinSize()); vhint_sizer->Add(mousebmp, wxSizerFlags().Centre().Border(wxRIGHT, 3)); vhint_sizer->Add(rmouse_hint, wxSizerFlags().Centre().FixedMinSize()); hint_sizer->Add(new wxStaticLine(this), wxSizerFlags().Expand()); hint_sizer->Add(vhint_sizer, wxSizerFlags(1).Expand().FixedMinSize()); sizer->Add(hint_sizer, wxSizerFlags().Expand()); sizer->AddSpacer(16); SetSizer(sizer); Connect(prefbtn->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction) &FStatusBar::OnPrefButton); mousebmp->Connect(wxEVT_LEFT_DOWN, (wxObjectEventFunction) &FStatusBar::OnMouseBmpClicked, NULL, this); mousebmp->Connect(wxEVT_RIGHT_DOWN, (wxObjectEventFunction) &FStatusBar::OnMouseBmpClicked, NULL, this); } void FStatusBar::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("/StatusBar")); int coord_width = split->GetClientSize().x - split->GetSashPosition(); cf->Write(wxT("coord_width"), coord_width); cf->Write(wxT("show_btn"), show_btn); cf->Write(wxT("show_hints"), show_hints); cf->Write(wxT("e_prec"), e_prec); cf->Write(wxT("extraValue"), extra_value); } void FStatusBar::read_settings(wxConfigBase *cf) { cf->SetPath(wxT("/StatusBar")); int coord_width = cf->Read(wxT("coord_width"), 200); show_btn = cfg_read_bool(cf, wxT("show_btn"), true); show_hints = cfg_read_bool(cf, wxT("show_hints"), true); e_prec = cf->Read(wxT("e_prec"), 3); wxString ev = cf->Read(wxT("extraValue"), wxT("")); set_extra_value(ev); update_extra_fmt(); split->SetSashPosition(split->GetClientSize().x - coord_width); show_or_hide(); } void FStatusBar::set_hints(string const& left, string const& right, string const& mode_name, string const& shift_left, string const& shift_right) { lmouse_hint->SetLabel(s2wx(left)); rmouse_hint->SetLabel(s2wx(right)); string tip = "In this mode (" + mode_name + "), on main plot:" "\n left mouse button: " + left + "\n right mouse button: " + right + "\n Shift + left button: " + shift_left + "\n Shift + right button: " + shift_right + "\nIn all modes, on main plot:" "\n middle mouse button: zoom" "\n Ctrl + left button: zoom" "\n Ctrl + right button: menu" ; mousebmp->SetToolTip(s2wx(tip)); Layout(); } void FStatusBar::update_extra_fmt() { extra_fmt = wxString::Format(wxT(" : %% -.%df"), e_prec); } void FStatusBar::set_coords(double x, double y, PlotTypeEnum pte) { wxString fmt = (pte == pte_main ? wxT("% -8.12g % -7.12g") : wxT("% -8.12g [% -7.12g]")); wxString label = wxString::Format(fmt, x, y); if (!extra_value.IsEmpty()) { double val = extra_parser.calculate_custom(vector2(x, y)); label += wxString::Format(extra_fmt, val); } coords->SetLabel(label); last_x = x; last_y = y; last_pte = pte; } bool FStatusBar::set_extra_value(wxString const& s) { static const vector names = vector2(string("x"), string("y")); if (!s.empty()) { string as = wx2s(s); fityk::Lexer lex(as.c_str()); extra_parser.clear_vm(); bool r = extra_parser.parse_full(lex, 0, &names); if (!r) { extra_value.clear(); return false; } } extra_value = s; return true; } void FStatusBar::show_or_hide() { wxSizer *sizer = GetSizer(); sizer->Show(1, show_btn); sizer->Show(2, show_hints); sizer->Layout(); } void FStatusBar::OnPrefButton(wxCommandEvent&) { show_last_coordinates(); ConfStatBarDlg dlg(NULL, -1, this); dlg.ShowModal(); } void FStatusBar::OnMouseBmpClicked(wxMouseEvent&) { wxToolTip *tip = mousebmp->GetToolTip(); if (tip == NULL) return; wxMessageBox(tip->GetTip(), wxT("Mouse usage")); } //=============================================================== // ConfStatBarDlg //=============================================================== ConfStatBarDlg::ConfStatBarDlg(wxWindow* parent, wxWindowID id, FStatusBar* sb_) //explicit conversion of title to wxString() is neccessary : wxDialog(parent, id, wxString(wxT("Configure Status Bar")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), sb(sb_) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); show_btn_cb = new wxCheckBox(this, -1, wxT("show settings button")); show_btn_cb->SetValue(sb->show_btn); top_sizer->Add(show_btn_cb, wxSizerFlags().Border()); show_hints_cb = new wxCheckBox(this, -1, wxT("show mouse hints")); show_hints_cb->SetValue(sb->show_hints); top_sizer->Add(show_hints_cb, wxSizerFlags().Border()); wxStaticBoxSizer *f_sizer = new wxStaticBoxSizer(wxVERTICAL, this, wxT("extra value")); wxStaticText *evcomment = new wxStaticText(this, -1, wxT("In addition to the x and y, extra numeric value (a function") wxT("\nof x and/or y) can be shown on the status bar, e.g.:") wxT("\n4*pi*sin(x/2*pi/180)/1.5405")); evcomment->SetFont(*wxITALIC_FONT); f_sizer->Add(evcomment, wxSizerFlags().Border()); wxFlexGridSizer *gsizer = new wxFlexGridSizer(3, 5, 5); gsizer->AddGrowableCol(1); gsizer->Add(new wxStaticText(this, -1, wxT("formula")), wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT)); extra_tc = new wxTextCtrl(this, -1, sb->extra_value); gsizer->Add(extra_tc, wxSizerFlags().Expand().Center()); okbmp = new wxStaticBitmap(this, -1, GET_BMP(ok24)); gsizer->Add(okbmp, wxSizerFlags().Center() #if wxCHECK_VERSION(2, 8, 8) .ReserveSpaceEvenIfHidden() #endif ); gsizer->Add(new wxStaticText(this, -1,wxT("precision")), wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT)); e_prec_sc = new SpinCtrl(this, -1, sb->e_prec, 0, 9, 40); gsizer->Add(e_prec_sc, wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL)); f_sizer->Add(gsizer, wxSizerFlags(1).Expand().Border()); top_sizer->Add(f_sizer, wxSizerFlags(1).Expand().Border()); top_sizer->Add(persistance_note(this), wxSizerFlags().Border()); top_sizer->Add(new wxButton(this, wxID_CLOSE), wxSizerFlags().Right().Border()); SetSizerAndFit(top_sizer); SetEscapeId(wxID_CLOSE); //okbmp->Show(!sb->extra_value.empty()); Connect(show_btn_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, (wxObjectEventFunction) &ConfStatBarDlg::OnShowBtnCheckbox); Connect(show_hints_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, (wxObjectEventFunction) &ConfStatBarDlg::OnShowHintsCheckbox); Connect(extra_tc->GetId(), wxEVT_COMMAND_TEXT_UPDATED, (wxObjectEventFunction) &ConfStatBarDlg::OnExtraValueChange); Connect(e_prec_sc->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, (wxObjectEventFunction) &ConfStatBarDlg::OnPrecisionSpin); } void ConfStatBarDlg::OnShowBtnCheckbox(wxCommandEvent& event) { sb->show_btn = event.IsChecked(); sb->show_or_hide(); } void ConfStatBarDlg::OnShowHintsCheckbox(wxCommandEvent& event) { sb->show_hints = event.IsChecked(); sb->show_or_hide(); } void ConfStatBarDlg::OnPrecisionSpin(wxCommandEvent&) { //if (event.GetId() == e_prec_sc->GetId()) sb->e_prec = e_prec_sc->GetValue(); sb->update_extra_fmt(); sb->show_last_coordinates(); } void ConfStatBarDlg::OnExtraValueChange(wxCommandEvent&) { bool ok = sb->set_extra_value(extra_tc->GetValue()); okbmp->Show(ok); #if !wxCHECK_VERSION(2, 8, 8) GetSizer()->Layout(); #endif sb->show_last_coordinates(); } fityk-1.3.1/wxgui/statbar.h000066400000000000000000000055471302634723100156320ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_STATBAR_H_ #define FITYK_WX_STATBAR_H_ #include #include #include #include "cmn.h" //SpinCtrl #include "fityk/eparser.h" // ExpressionParser // used by MainPlot to set hints on FStatusBar class HintReceiver { public: virtual ~HintReceiver() {} virtual void set_hints(std::string const& left, std::string const& right, std::string const& mode_name, std::string const& shift_left, std::string const& shift_right)=0; }; /// Status bar in Fityk class FStatusBar: public wxPanel, public HintReceiver { friend class ConfStatBarDlg; public: FStatusBar(wxWindow *parent); void set_text(wxString const& text_) { text->SetLabel(text_); } wxString get_text() const { return text->GetLabel(); } void set_hints(std::string const& left, std::string const& right, std::string const& mode_name, std::string const& shift_left, std::string const& shift_right); void set_coords(double x, double y, PlotTypeEnum pte); void clear_coords() { coords->SetLabel(wxEmptyString); } bool set_extra_value(wxString const& s); void update_extra_fmt(); wxString const& get_extra_value() const { return extra_value; } void save_settings(wxConfigBase *cf) const; void read_settings(wxConfigBase *cf); void OnPrefButton(wxCommandEvent&); void OnMouseBmpClicked(wxMouseEvent&); // show last coordinates (as example) in the current format void show_last_coordinates() { set_coords(last_x, last_y, last_pte); } private: // a number calculated as a function of cursor coordinates x and y and // shown at the status bar (as a 3rd number, after x and y) wxString extra_value; fityk::ExpressionParser extra_parser; // parser/vm for extra value int e_prec; // precision of extra value shown at status bar bool show_btn; bool show_hints; double last_x, last_y; PlotTypeEnum last_pte; wxString extra_fmt; wxStaticText *text; wxStaticText *coords; wxStaticText *lmouse_hint, *rmouse_hint; wxBitmapButton *prefbtn; wxStaticBitmap *mousebmp; wxSplitterWindow *split; void show_or_hide(); }; /// Status bar configuration dialog class ConfStatBarDlg: public wxDialog { public: ConfStatBarDlg(wxWindow* parent, wxWindowID id, FStatusBar* sb_); void OnShowBtnCheckbox(wxCommandEvent& event); void OnShowHintsCheckbox(wxCommandEvent& event); void OnExtraValueChange(wxCommandEvent&); void OnPrecisionSpin(wxCommandEvent& event); private: FStatusBar *sb; wxTextCtrl *extra_tc; wxCheckBox *show_btn_cb, *show_hints_cb; wxSpinCtrl *e_prec_sc; wxStaticBitmap *okbmp; }; #endif // FITYK_WX_STATBAR_H_ fityk-1.3.1/wxgui/textpane.cpp000066400000000000000000000321151302634723100163440ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #include #include #include #include #include #include #include #include "textpane.h" #include "frame.h" #include "inputline.h" using namespace std; enum { ID_OUTPUT_CLEAR = 27001, ID_OUTPUT_CONFIGURE, ID_OUTPUT_EDITLINE }; class OutputWinConfDlg : public wxDialog { public: OutputWinConfDlg(wxWindow* parent, wxWindowID id, OutputWin* ow); private: OutputWin *ow_; wxStaticText *font_label_; wxColourPickerCtrl *cp_bg_, *cp_input_, *cp_output_, *cp_quote_, *cp_warning_; wxFontPickerCtrl *font_picker_; wxTextCtrl *preview_; void show_preview(); void OnSystemFontCheckbox(wxCommandEvent& event); void OnFontChange(wxFontPickerEvent& event); void OnColor(wxColourPickerEvent& event); }; //=============================================================== // TextPane //=============================================================== TextPane::TextPane(wxWindow *parent) : wxPanel(parent, -1) { wxBoxSizer *io_sizer = new wxBoxSizer(wxVERTICAL); // on Linux platform GUI and CLI history is stored in the same file wxString hist_file = get_conf_file("history"); // readline and editline (libedit) use different history format, // we like to use the same file file format as CLI, but it's not easy // with libedit. If it's libedit history we use a different file. FILE *f = wxFopen(hist_file, "r"); if (f) { char buf[10]; char* ret = fgets(buf, 10, f); fclose(f); if (ret && strncmp(buf, "_HiStOrY_", 9) == 0) // libedit weirdness hist_file += "_gui"; } input_field = new InputLine(this, -1, this, hist_file); output_win = new OutputWin (this, -1); io_sizer->Add(output_win, 1, wxEXPAND); io_sizer->Add(input_field, 0, wxEXPAND); SetSizer(io_sizer); io_sizer->SetSizeHints(this); } void TextPane::edit_in_input(string const& s) { input_field->SetValue(s2wx(s)); input_field->SetFocus(); } void TextPane::ProcessInputLine(wxString const& s) { frame->set_status_text(wx2s(s)); exec(wx2s(s)); //displaying and executing command } //=============================================================== // OutputWin //=============================================================== BEGIN_EVENT_TABLE(OutputWin, wxTextCtrl) EVT_RIGHT_DOWN ( OutputWin::OnRightDown) EVT_MENU (ID_OUTPUT_CLEAR, OutputWin::OnClear) EVT_MENU (ID_OUTPUT_CONFIGURE, OutputWin::OnConfigure) EVT_MENU (ID_OUTPUT_EDITLINE, OutputWin::OnEditLine) EVT_KEY_DOWN ( OutputWin::OnKeyDown) END_EVENT_TABLE() OutputWin::OutputWin (wxWindow *parent, wxWindowID id) : wxTextCtrl(parent, id, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH|wxNO_BORDER|wxTE_READONLY) {} void OutputWin::add_initial_text() { SetDefaultStyle(wxTextAttr(text_color_[UserInterface::kNormal])); AppendText("This window shows your "); SetDefaultStyle(wxTextAttr(text_color_[UserInterface::kInput])); AppendText("commands"); SetDefaultStyle(wxTextAttr(text_color_[UserInterface::kNormal])); AppendText(".\n"); } void OutputWin::read_settings(wxConfigBase *cf) { cf->SetPath(wxT("/OutputWin/Colors")); bg_color_ = cfg_read_color(cf, wxT("bg"), wxColour(0, 43, 54)); text_color_[UserInterface::kNormal] = cfg_read_color(cf, wxT("normal"), wxColour(131, 148, 150)); text_color_[UserInterface::kInput] = cfg_read_color(cf, wxT("input"), wxColour(133, 153, 0)); text_color_[UserInterface::kQuoted] = cfg_read_color(cf, wxT("quot"), wxColour(38, 139, 210)); text_color_[UserInterface::kWarning] = cfg_read_color(cf, wxT("warn"), wxColour(220, 50, 47)); cf->SetPath(wxT("/OutputWin")); wxFont font = cfg_read_font(cf, wxT("font"), wxNullFont); SetDefaultStyle(wxTextAttr(bg_color_, bg_color_, font)); SetBackgroundColour(bg_color_); if (IsEmpty()) add_initial_text(); Refresh(); } void OutputWin::save_settings(wxConfigBase *cf) const { cf->SetPath(wxT("/OutputWin/Colors")); cfg_write_color (cf, wxT("normal"), text_color_[UserInterface::kNormal]); cfg_write_color (cf, wxT("warn"), text_color_[UserInterface::kWarning]); cfg_write_color (cf, wxT("quot"), text_color_[UserInterface::kQuoted]); cfg_write_color (cf, wxT("input"), text_color_[UserInterface::kInput]); cfg_write_color (cf, wxT("bg"), bg_color_); cf->SetPath(wxT("/OutputWin")); cfg_write_font (cf, wxT("font"), GetDefaultStyle().GetFont()); } void OutputWin::append_text (UserInterface::Style style, const wxString& str) { const int max_len = 1048576; const int delta = 262144; if (GetLastPosition() > max_len) Remove(0, delta); SetDefaultStyle (wxTextAttr (text_color_[style])); AppendText (str); // in wxMSW 2.9.1(trunk) there is a scrolling-related bug: // when the control is auto-scrolled after appending text, // the page gets blank. Clicking on scrollbar shows the text again. // Below is a workaround. #ifdef __WXMSW__ ScrollLines(-1); ScrollLines(1); #endif } void OutputWin::show_preferences_dialog() { OutputWinConfDlg dlg(NULL, -1, this); dlg.ShowModal(); } void OutputWin::OnClear (wxCommandEvent&) { Clear(); add_initial_text(); } void OutputWin::OnEditLine (wxCommandEvent&) { InputLine *input_field = static_cast(GetParent())->input_field; input_field->SetValue(selection_); input_field->SetFocus(); } void OutputWin::OnRightDown (wxMouseEvent& event) { wxMenu popup_menu; popup_menu.Append (ID_OUTPUT_EDITLINE, wxT("&Edit Line/Selection")); selection_ = GetStringSelection(); if (selection_.empty()) { wxTextCoord col, row; if (HitTest(event.GetPosition(), &col, &row) != wxTE_HT_UNKNOWN) { wxString line = GetLineText(row); if (line.StartsWith(wxT("=-> "))) selection_ = line.substr(4); } } else if (selection_.StartsWith(wxT("=-> "))) selection_ = selection_.substr(4); if (selection_.empty()) popup_menu.Enable(ID_OUTPUT_EDITLINE, false); popup_menu.Append (ID_OUTPUT_CLEAR, wxT("Clea&r")); popup_menu.Append (ID_OUTPUT_CONFIGURE, wxT("&Configure...")); PopupMenu (&popup_menu, event.GetX(), event.GetY()); } void OutputWin::OnKeyDown (wxKeyEvent& event) { frame->focus_input(event); } void OutputWin::set_bg_color(wxColour const &color) { bg_color_ = color; SetBackgroundColour (color); SetDefaultStyle (wxTextAttr(wxNullColour, color)); } OutputWinConfDlg::OutputWinConfDlg(wxWindow* parent, wxWindowID id, OutputWin* ow) : wxDialog(parent, id, wxString(wxT("Configure Output Window")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER), ow_(ow) { wxBoxSizer *top_sizer = new wxBoxSizer(wxVERTICAL); wxCheckBox *system_font_cb = new wxCheckBox(this, -1, wxT("use the regular system font")); top_sizer->Add(system_font_cb, wxSizerFlags().Border()); wxBoxSizer *fsizer = new wxBoxSizer(wxHORIZONTAL); fsizer->AddSpacer(16); font_label_ = new wxStaticText(this, -1, wxT("font:")); fsizer->Add(font_label_, wxSizerFlags().Center().Border()); font_picker_ = new wxFontPickerCtrl(this, -1, ow_->GetDefaultStyle().GetFont()); fsizer->Add(font_picker_, wxSizerFlags(1).Center().Border()); top_sizer->Add(fsizer, wxSizerFlags().Expand()); wxBoxSizer *hsizer = new wxBoxSizer(wxHORIZONTAL); wxGridSizer *gsizer = new wxGridSizer(2, 5, 5); wxSizerFlags cl = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL), cr = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL|wxALIGN_RIGHT); gsizer->Add(new wxStaticText(this, -1, wxT("background color")), cr); cp_bg_ = new wxColourPickerCtrl(this, -1, ow_->bg_color_); gsizer->Add(cp_bg_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("input color")), cr); cp_input_ = new wxColourPickerCtrl(this, -1, ow_->text_color_[UserInterface::kInput]); gsizer->Add(cp_input_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("output color")), cr); cp_output_ = new wxColourPickerCtrl(this, -1, ow_->text_color_[UserInterface::kNormal]); gsizer->Add(cp_output_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("quotation color")), cr); cp_quote_ = new wxColourPickerCtrl(this, -1, ow_->text_color_[UserInterface::kQuoted]); gsizer->Add(cp_quote_, cl); gsizer->Add(new wxStaticText(this, -1, wxT("warning color")), cr); cp_warning_ = new wxColourPickerCtrl(this, -1, ow_->text_color_[UserInterface::kWarning]); gsizer->Add(cp_warning_, cl); hsizer->Add(gsizer, wxSizerFlags()); preview_ = new wxTextCtrl(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_RICH|wxTE_READONLY); preview_->SetMinSize(wxSize(140, -1)); hsizer->Add(preview_, wxSizerFlags(1).Expand()); top_sizer->Add(hsizer, wxSizerFlags(1).Expand().Border()); top_sizer->Add(persistance_note(this), wxSizerFlags().Border()); top_sizer->Add(new wxButton(this, wxID_CLOSE), wxSizerFlags().Right().Border()); SetSizerAndFit(top_sizer); if (ow_->GetDefaultStyle().GetFont() == *wxNORMAL_FONT) { system_font_cb->SetValue(true); font_label_->Enable(false); font_picker_->Enable(false); } show_preview(); SetEscapeId(wxID_CLOSE); Connect(system_font_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, (wxObjectEventFunction) &OutputWinConfDlg::OnSystemFontCheckbox); Connect(font_picker_->GetId(), wxEVT_COMMAND_FONTPICKER_CHANGED, (wxObjectEventFunction) &OutputWinConfDlg::OnFontChange); Connect(cp_bg_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, (wxObjectEventFunction) &OutputWinConfDlg::OnColor); Connect(cp_input_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, (wxObjectEventFunction) &OutputWinConfDlg::OnColor); Connect(cp_output_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, (wxObjectEventFunction) &OutputWinConfDlg::OnColor); Connect(cp_quote_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, (wxObjectEventFunction) &OutputWinConfDlg::OnColor); Connect(cp_warning_->GetId(), wxEVT_COMMAND_COLOURPICKER_CHANGED, (wxObjectEventFunction) &OutputWinConfDlg::OnColor); } void OutputWinConfDlg::OnSystemFontCheckbox(wxCommandEvent& event) { bool checked = event.IsChecked(); font_label_->Enable(!checked); font_picker_->Enable(!checked); wxFont const& font = checked ? *wxNORMAL_FONT : font_picker_->GetSelectedFont(); ow_->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, font)); show_preview(); } void OutputWinConfDlg::OnFontChange(wxFontPickerEvent& event) { ow_->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, event.GetFont())); show_preview(); } void OutputWinConfDlg::OnColor(wxColourPickerEvent& event) { int id = event.GetId(); if (id == cp_bg_->GetId()) ow_->set_bg_color(event.GetColour()); else if (id == cp_input_->GetId()) ow_->text_color_[UserInterface::kInput] = event.GetColour(); else if (id == cp_output_->GetId()) ow_->text_color_[UserInterface::kNormal] = event.GetColour(); else if (id == cp_quote_->GetId()) ow_->text_color_[UserInterface::kQuoted] = event.GetColour(); else if (id == cp_warning_->GetId()) ow_->text_color_[UserInterface::kWarning] = event.GetColour(); show_preview(); } void OutputWinConfDlg::show_preview() { const wxColour& output = ow_->text_color_[UserInterface::kNormal]; const wxColour& input = ow_->text_color_[UserInterface::kInput]; const wxColour& quote = ow_->text_color_[UserInterface::kQuoted]; const wxColour& warning = ow_->text_color_[UserInterface::kWarning]; preview_->Clear(); preview_->SetBackgroundColour(ow_->bg_color_); preview_->SetDefaultStyle(ow_->GetDefaultStyle()); preview_->SetDefaultStyle(wxTextAttr(output)); preview_->AppendText(wxT("\nsettings preview\n\n")); preview_->SetDefaultStyle(wxTextAttr(input)); preview_->AppendText(wxT("=-> i pi\n")); preview_->SetDefaultStyle(wxTextAttr(output)); preview_->AppendText(wxT("3.14159\n")); preview_->SetDefaultStyle(wxTextAttr(input)); preview_->AppendText(wxT("=-> c < file.fit\n")); preview_->SetDefaultStyle(wxTextAttr(quote)); preview_->AppendText(wxT("1> bleh in file\n")); preview_->SetDefaultStyle(wxTextAttr(warning)); preview_->AppendText(wxT("Syntax error.\n")); } fityk-1.3.1/wxgui/textpane.h000066400000000000000000000027071302634723100160150ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ #ifndef FITYK_WX_TEXTPANE_H_ #define FITYK_WX_TEXTPANE_H_ #include "fityk/ui.h" // UserInterface::Style #include "inputline.h" // InputLine, InputLineObserver class wxConfigBase; class OutputWin : public wxTextCtrl { friend class OutputWinConfDlg; public: OutputWin(wxWindow *parent, wxWindowID id); void append_text(fityk::UserInterface::Style style, const wxString& str); void save_settings(wxConfigBase *cf) const; void read_settings(wxConfigBase *cf); void show_preferences_dialog(); private: wxColour text_color_[4]; wxColour bg_color_; wxString selection_; // string passed to OnEditLine() void add_initial_text(); void set_bg_color(wxColour const &color); void OnRightDown (wxMouseEvent& event); void OnEditLine(wxCommandEvent&); void OnClear(wxCommandEvent&); void OnKeyDown (wxKeyEvent& event); void OnConfigure(wxCommandEvent&) { show_preferences_dialog(); } DECLARE_EVENT_TABLE() }; /// A pane containing input line and output window. class TextPane : public wxPanel, public InputLineObserver { public: TextPane(wxWindow *parent); void edit_in_input(std::string const& s); // implementation of InputLineObserver virtual void ProcessInputLine(wxString const& s); OutputWin *output_win; InputLine *input_field; }; #endif // FITYK_WX_TEXTPANE_H_ fityk-1.3.1/wxgui/uplot.cpp000066400000000000000000000172461302634723100156670ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // (It is also part of xyconvert and can be distributed under LGPL2.1) /// utilities for making plot (BufferedPanel, scale_tics_step()) #include #include #include "uplot.h" //#include "cmn.h" #if !defined(XYCONVERT) && !defined(STANDALONE_POWDIFPAT) #include "frame.h" // frame->antialias() inline bool antialias() { return frame->antialias(); } #else inline bool antialias() { return false; } #endif using namespace std; BufferedPanel::BufferedPanel(wxWindow *parent) : wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxFULL_REPAINT_ON_RESIZE), support_antialiasing_(true), dirty_(true) { SetBackgroundStyle(wxBG_STYLE_CUSTOM); Connect(wxEVT_IDLE, wxIdleEventHandler(BufferedPanel::OnIdle)); } void BufferedPanel::redraw_now() { dirty_ = true; Refresh(false); Update(); } void BufferedPanel::gc_draw(wxMemoryDC& dc) { if (antialias() && support_antialiasing_) { wxGCDC gdc(dc); #ifdef __WXMSW__ // this is necessary only for PNG output on Windows, // together with explicit 32-bit bitmap depth in // PlotPane::prepare_bitmap_for_export() gdc.SetBackground(wxBrush(bg_color_)); gdc.Clear(); #endif draw(gdc); } else draw(dc); } wxBitmap BufferedPanel::draw_on_bitmap(int w, int h, int depth) { wxBitmap bmp = wxBitmap(w, h, depth); memory_dc_.SelectObject(bmp); memory_dc_.SetBackground(wxBrush(bg_color_)); memory_dc_.Clear(); gc_draw(memory_dc_); if (buffer_.Ok()) { memory_dc_.SelectObject(buffer_); memory_dc_.SetBackground(wxBrush(bg_color_)); } return bmp; } void BufferedPanel::update_buffer_and_blit() { //cout << "BufferedPanel::update_buffer_and_blit()" << endl; wxPaintDC pdc(this); // check size wxCoord w, h; pdc.GetSize(&w, &h); if (w == 0 || h == 0) return; if (!buffer_.Ok() || w != buffer_.GetWidth() || h != buffer_.GetHeight()) { memory_dc_.SelectObject(wxNullBitmap); buffer_ = wxBitmap(w, h); memory_dc_.SelectObject(buffer_); memory_dc_.SetBackground(wxBrush(bg_color_)); dirty_ = true; } // update the buffer if necessary if (dirty_) { memory_dc_.SetLogicalFunction(wxCOPY); memory_dc_.Clear(); gc_draw(memory_dc_); // This condition is almost always true. It was added because on // wxGTK 2.8 with some window managers, after loading a data file // the next paint event had the update region set to the area // of the file dialog, and the rest of the plot remained not updated. if (GetUpdateRegion().GetBox().GetSize() == pdc.GetSize()) dirty_ = false; } blit(pdc); } void BufferedPanel::blit(wxDC& dc) { dc.Blit(0, 0, buffer_.GetWidth(), buffer_.GetHeight(), &memory_dc_, 0, 0); } void BufferedPanel::OnIdle(wxIdleEvent&) { if (dirty_) Refresh(false); } void BufferedPanel::set_bg_color(wxColour const& c) { bg_color_ = c; if (memory_dc_.IsOk()) memory_dc_.SetBackground(wxBrush(c)); } PlotWithTics::PlotWithTics(wxWindow* parent) : BufferedPanel(parent) { Connect(GetId(), wxEVT_PAINT, (wxObjectEventFunction) &PlotWithTics::OnPaint); } void PlotWithTics::draw_tics(wxDC &dc, double x_min, double x_max, double y_min, double y_max) { // prepare scaling double const margin = 0.1; double dx = x_max - x_min; double dy = y_max - y_min; int W = dc.GetSize().GetWidth(); int H = dc.GetSize().GetHeight(); xScale = (1 - 1.2 * margin) * W / dx; yScale = - (1 - 1.2 * margin) * H / dy; xOffset = - x_min * xScale + margin * W; yOffset = H - y_min * yScale - margin * H; // draw scale dc.SetPen(*wxWHITE_PEN); dc.SetTextForeground(*wxWHITE); dc.SetFont(*wxSMALL_FONT); // ... horizontal vector minors; vector tics = scale_tics_step(x_min, x_max, 4, minors); for (vector::const_iterator i = tics.begin(); i != tics.end(); ++i){ int X = getX(*i); wxString label = format_label(*i, x_max - x_min); wxCoord tw, th; dc.GetTextExtent (label, &tw, &th); int Y = dc.DeviceToLogicalY(H - th - 2); dc.DrawText (label, X - tw/2, Y + 1); dc.DrawLine (X, Y, X, Y - 4); } // ... vertical tics = scale_tics_step(y_min, y_max, 4, minors); for (vector::const_iterator i = tics.begin(); i != tics.end(); ++i){ int Y = getY(*i); wxString label = format_label(*i, y_max - y_min); wxCoord tw, th; dc.GetTextExtent (label, &tw, &th); dc.DrawText (label, dc.DeviceToLogicalX(5), Y - th/2); dc.DrawLine (dc.DeviceToLogicalX(0), Y, dc.DeviceToLogicalX(4), Y); } } void PlotWithTics::draw_axis_labels(wxDC& dc, string const& x_name, string const& y_name) { int W = dc.GetSize().GetWidth(); int H = dc.GetSize().GetHeight(); if (!x_name.empty()) { wxCoord tw, th; dc.GetTextExtent(x_name, &tw, &th); dc.DrawText(x_name, (W - tw)/2, 2); } if (!y_name.empty()) { wxCoord tw, th; dc.GetTextExtent(y_name, &tw, &th); dc.DrawRotatedText(y_name, W - 2, (H - tw)/2, 270); } } vector scale_tics_step (double beg, double end, int max_tics, vector &minors, bool logarithm) { vector result; minors.clear(); if (beg >= end || max_tics <= 0) return result; if (logarithm) { if (beg <= 0) beg = 1e-1; if (end <= beg) end = 2*beg; double min_logstep = (log10(end/beg)) / max_tics; bool with_2_5 = (min_logstep < log10(2.)); double logstep = ceil(min_logstep); double step0 = pow(10, logstep * ceil(log10(beg) / logstep)); for (int i = 2; i <= 9; ++i) { double v = step0/10. * i; if (v > beg && v < end) { if (with_2_5 && (i == 2 || i == 5)) result.push_back(v); else minors.push_back(v); } } for (double t = step0; t < end; t *= pow(10,logstep)) { result.push_back(t); for (int i = 2; i <= 9; ++i) { double v = t * i; if (v > beg && v < end) { if (with_2_5 && (i == 2 || i == 5)) result.push_back(v); else minors.push_back(v); } } } } else { // !logarithm double min_step = (end - beg) / max_tics; double s = pow(10, floor (log10 (min_step))); int minor_div = 5; //ratio of major-step to minor-step // now s <= min_step if (s >= min_step) ; else if (s * 2 >= min_step) { s *= 2; minor_div = 2; } else if (s * 2.5 >= min_step) s *= 2.5; else if (s * 5 >= min_step) s *= 5; else s *= 10; for (double t = s * floor(beg / s); t < end; t += s) { if (t > beg) { // make sure that 0 is not displayed as e.g. -2.7893e-17 if (fabs(t) < 1e-6 * fabs(min_step)) t = 0.; result.push_back(t); } for (int i = 1; i < minor_div; ++i) { double v = t + s * i / minor_div; if (v > beg && v < end) minors.push_back(v); } } } return result; } fityk-1.3.1/wxgui/uplot.h000066400000000000000000000061041302634723100153230ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // (It is also part of xyconvert and can be distributed under LGPL2.1) #ifndef FITYK_WX_UPLOT_H_ #define FITYK_WX_UPLOT_H_ #include // floor #include /// wxPanel with associated bitmap buffer, used for drawing plots /// refresh() must be called when data is changed /// BufferedPanel checks if size of the plot was changed and refreshes /// plot automatically. class BufferedPanel : public wxPanel { public: static wxString format_label(double x, double range) { return wxString::Format(range < 1e6 ? wxT("%.12g") : wxT("%g"), x); } BufferedPanel(wxWindow *parent); virtual ~BufferedPanel() {} /// mark panel as dirty and needing replotting, /// to be called when the content of panel is changed void refresh() { dirty_ = true; } // force redrawing panel now void redraw_now(); /// called from wxPaint event handler /// updates buffer only if the window size is changed or if dirty_ void update_buffer_and_blit(); /// copy bitmap to window void blit(wxDC& dc); /// wraps dc in wxGCDC (if needed) and calls draw() void gc_draw(wxMemoryDC &dc); /// create bitmap w x h with given depth (-1 = screen) and draw plot on it wxBitmap draw_on_bitmap(int w, int h, int depth=-1); /// plotting function called to refresh buffer virtual void draw(wxDC &dc, bool monochrome=false) = 0; /// get bitmap buffer wxBitmap const& get_bitmap() const { return buffer_; } /// set background color virtual void set_bg_color(wxColour const& c); /// get background color wxColour const& get_bg_color() const { return bg_color_; } protected: bool support_antialiasing_; private: bool dirty_; wxMemoryDC memory_dc_; wxBitmap buffer_; wxColour bg_color_; bool resize_buffer(wxDC &dc); void OnIdle(wxIdleEvent&); }; class PlotWithTics : public BufferedPanel { public: PlotWithTics(wxWindow* parent); void OnPaint(wxPaintEvent &) { update_buffer_and_blit(); } void draw_tics(wxDC &dc, double x_min, double x_max, double y_min, double y_max); void draw_axis_labels(wxDC& dc, std::string const& x_name, std::string const& y_name); void draw_point(wxDC& dc, double x, double y) { dc.DrawPoint(getX(x), getY(y)); } protected: double xScale, yScale; double xOffset, yOffset; int getX(double x) { return iround(x * xScale + xOffset); } int getY(double y) { return iround(y * yScale + yOffset); } // Round real to integer. Defined here to avoid dependency on ../common.h. static int iround(double d) { return static_cast(floor(d+0.5)); } }; /// returns positions of major and minor tics, for normal or logarithmic scale std::vector scale_tics_step(double beg, double end, int max_tics, std::vector &minors, bool logarithm=false); #endif //FITYK_WX_UPLOT_H_ fityk-1.3.1/wxgui/winres.rc000066400000000000000000000002731302634723100156450ustar00rootroot00000000000000// This file is used only on MS Windows platform. // It can be compiled by windres // wxWidgets resource definitions #include // program icon fityk ICON "img/fityk.ico" fityk-1.3.1/wxgui/xybrowser.cpp000066400000000000000000000352541302634723100165670ustar00rootroot00000000000000// Author: Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // (It is also part of xyconvert and can be distributed under LGPL2.1) #include #include #include "xylib/xylib.h" #include "xylib/cache.h" #include "xybrowser.h" using namespace std; #ifndef XYCONVERT #include "cmn.h" #include "fityk/data.h" using fityk::get_file_basename; #else // copied from common.h #ifdef _MSC_VER #define snprintf sprintf_s #endif template std::string format1(const char* fmt, T t) { char buffer[N]; snprintf(buffer, N, fmt, t); buffer[N-1] = '\0'; return std::string(buffer); } inline std::string S(int n) { return format1("%d", n); } inline std::string S(double d) { return format1("%g", d); } // copied from cmn.h class SpinCtrl: public wxSpinCtrl { public: SpinCtrl(wxWindow* parent, wxWindowID id, int val, int min, int max, int width=50) : wxSpinCtrl (parent, id, wxString::Format(wxT("%i"), val), wxDefaultPosition, wxSize(width, -1), wxSP_ARROW_KEYS, min, max, val) {} }; #endif // XYCONVERT PreviewPlot::PreviewPlot(wxWindow* parent) : PlotWithTics(parent), block_nr(0), idx_x(1), idx_y(2), data_updated_(false) { set_bg_color(wxColour(64, 64, 64)); support_antialiasing_ = false; } void PreviewPlot::draw(wxDC &dc, bool) { if (data_.get() == NULL || !data_updated_ || block_nr < 0 || block_nr >= data_->get_block_count()) return; xylib::Block const *block = data_->get_block(block_nr); if (idx_x < 0 || idx_x > block->get_column_count() || idx_y < 0 || idx_y > block->get_column_count()) return; xylib::Column const& xcol = block->get_column(idx_x); xylib::Column const& ycol = block->get_column(idx_y); const int np = block->get_point_count(); draw_tics(dc, xcol.get_min(), xcol.get_max(np), ycol.get_min(), ycol.get_max(np)); draw_axis_labels(dc, xcol.get_name(), ycol.get_name()); // draw data dc.SetPen(*wxGREEN_PEN); for (int i = 0; i < np; ++i) draw_point(dc, xcol.get_value(i), ycol.get_value(i)); } void PreviewPlot::load_dataset(string const& filename, string const& filetype, string const& options) { try { data_ = xylib::cached_load_file(filename, filetype, options); data_updated_ = true; } catch (runtime_error const& /*e*/) { data_updated_ = false; } } XyFileBrowser::XyFileBrowser(wxWindow* parent) : wxSplitterWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER), auto_plot_cb(NULL) { // +----------------------------+ // | | rupper_panel | // | left_panel +---------------+ // | | rbottom_panel | // +----------------------------+ SetSashGravity(0.5); SetMinimumPaneSize(20); wxPanel *left_panel = new wxPanel(this, -1); wxBoxSizer *left_sizer = new wxBoxSizer(wxVERTICAL); wxSplitterWindow *right_splitter = new wxSplitterWindow(this, -1, wxDefaultPosition, wxDefaultSize, wxSP_NOBORDER); right_splitter->SetSashGravity(0.5); right_splitter->SetMinimumPaneSize(20); wxPanel *rupper_panel = new wxPanel(right_splitter, -1); wxBoxSizer *rupper_sizer = new wxBoxSizer(wxVERTICAL); wxPanel *rbottom_panel = new wxPanel(right_splitter, -1); wxBoxSizer *rbottom_sizer = new wxBoxSizer(wxVERTICAL); // ----- left panel ----- wxString all(wxFileSelectorDefaultWildcardStr); wxString wild = "All Files (" + all + ")|" + all + "|" + wxString(xylib::get_wildcards_string()); filectrl = new wxFileCtrl(left_panel, -1, wxEmptyString, wxEmptyString, wild, wxFC_OPEN|wxFC_MULTIPLE|wxFC_NOSHOWHIDDEN); left_sizer->Add(filectrl, 1, wxALL|wxEXPAND, 5); // selecting block wxBoxSizer *block_sizer = new wxBoxSizer(wxHORIZONTAL); block_sizer->Add(new wxStaticText(left_panel, -1, "file format:"), wxSizerFlags().Border(wxLEFT|wxRIGHT).Center()); format_ch = new wxChoice(left_panel, -1, wxDefaultPosition, wxSize(140,-1)); format_ch->Append(wxString("")); const xylibFormat *format; for (int i = 0; (format = xylib_get_format(i)) != NULL; ++i) format_ch->Append(format->desc); format_ch->SetSelection(0); block_sizer->Add(format_ch, wxSizerFlags(0).Border(wxRIGHT)); block_sizer->Add(new wxStaticText(left_panel, -1, "block:"), wxSizerFlags().Border(wxLEFT|wxRIGHT).Center()); block_ch = new wxChoice(left_panel, -1); block_sizer->Add(block_ch, wxSizerFlags(1)); left_sizer->Add(block_sizer, wxSizerFlags().Border().Expand()); comma_cb = new wxCheckBox(left_panel, wxID_ANY, "decimal comma"); comma_cb->SetValue(false); left_sizer->Add(comma_cb, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5); // selecting columns wxPanel *columns_panel = new wxPanel (left_panel, -1); wxStaticBoxSizer *h2a_sizer = new wxStaticBoxSizer(wxHORIZONTAL, columns_panel, wxT("Select columns (0 for point index):")); h2a_sizer->Add (new wxStaticText (columns_panel, -1, wxT("x")), 0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); x_column = new SpinCtrl(columns_panel, wxID_ANY, 1, 0, 999, 50); h2a_sizer->Add (x_column, 0, wxALL|wxALIGN_LEFT, 5); h2a_sizer->Add (new wxStaticText (columns_panel, -1, wxT("y")), 0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 5); y_column = new SpinCtrl(columns_panel, wxID_ANY, 2, 0, 999, 50); h2a_sizer->Add (y_column, 0, wxALL|wxALIGN_LEFT, 5); #ifdef XYCONVERT std_dev_b = new wxCheckBox(columns_panel, -1, wxT("\u03C3")); #else std_dev_b = new wxRadioButton(columns_panel, -1, wxT("\u03C3")); #endif std_dev_b->SetValue(false); h2a_sizer->Add(std_dev_b, 0, wxALL|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL,5); s_column = new SpinCtrl(columns_panel, wxID_ANY, 3, 1, 999, 50); h2a_sizer->Add(s_column, 0, wxALL|wxALIGN_LEFT, 5); #ifndef XYCONVERT h2a_sizer->Add(new wxStaticText(columns_panel, wxID_ANY, "or"), 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); sd_sqrt_rb = new wxRadioButton(columns_panel, wxID_ANY, wxT("\u03C3=max{\u221Ay, 1} or")); h2a_sizer->Add(sd_sqrt_rb, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); sd_1_rb = new wxRadioButton(columns_panel, wxID_ANY, wxT("\u03C3=1")); h2a_sizer->Add(sd_1_rb, 0, wxALL|wxEXPAND, 5); #endif columns_panel->SetSizer(h2a_sizer); left_sizer->Add (columns_panel, 0, wxALL|wxEXPAND, 5); #ifndef XYCONVERT wxBoxSizer *dt_sizer = new wxBoxSizer(wxHORIZONTAL); dt_sizer->Add(new wxStaticText(left_panel, wxID_ANY, "data title:"), 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); title_tc = new wxTextCtrl(left_panel, -1, ""); dt_sizer->Add(title_tc, 1, wxALL|wxALIGN_CENTER_VERTICAL, 5); left_sizer->Add (dt_sizer, 0, wxEXPAND); #endif update_s_column(); // ----- right upper panel ----- text_preview = new wxTextCtrl(rupper_panel, -1, wxT(""), wxDefaultPosition, wxSize(300, -1), wxTE_RICH|wxTE_READONLY|wxTE_MULTILINE); rupper_sizer->Add(text_preview, 1, wxEXPAND|wxALL, 5); auto_text_cb = new wxCheckBox(rupper_panel, -1, wxT("file preview (64kB)")); auto_text_cb->SetValue(false); rupper_sizer->Add(auto_text_cb, 0, wxALL, 5); // ----- right bottom panel ----- plot_preview = new PreviewPlot(rbottom_panel); rbottom_sizer->Add(plot_preview, 1, wxEXPAND|wxALL, 5); auto_plot_cb = new wxCheckBox(rbottom_panel, -1, wxT("plot")); auto_plot_cb->SetValue(true); rbottom_sizer->Add(auto_plot_cb, 0, wxALL, 5); // ------ finishing layout ----------- left_panel->SetSizerAndFit(left_sizer); rupper_panel->SetSizerAndFit(rupper_sizer); rbottom_panel->SetSizerAndFit(rbottom_sizer); SplitVertically(left_panel, right_splitter); right_splitter->SplitHorizontally(rupper_panel, rbottom_panel); update_block_list(); #ifdef XYCONVERT Connect(std_dev_b->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(XyFileBrowser::OnStdDevSwitched)); #else Connect(std_dev_b->GetId(), wxEVT_RADIOBUTTON, wxCommandEventHandler(XyFileBrowser::OnStdDevSwitched)); Connect(sd_sqrt_rb->GetId(), wxEVT_RADIOBUTTON, wxCommandEventHandler(XyFileBrowser::OnStdDevSwitched)); Connect(sd_1_rb->GetId(), wxEVT_RADIOBUTTON, wxCommandEventHandler(XyFileBrowser::OnStdDevSwitched)); #endif Connect(comma_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(XyFileBrowser::OnCommaCheckBox)); Connect(auto_text_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(XyFileBrowser::OnAutoTextCheckBox)); Connect(auto_plot_cb->GetId(), wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(XyFileBrowser::OnAutoPlotCheckBox)); Connect(x_column->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(XyFileBrowser::OnColumnChanged)); Connect(y_column->GetId(), wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler(XyFileBrowser::OnColumnChanged)); Connect(format_ch->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(XyFileBrowser::OnFormatChanged)); Connect(block_ch->GetId(), wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(XyFileBrowser::OnBlockChanged)); Connect(filectrl->GetId(), wxEVT_FILECTRL_SELECTIONCHANGED, wxFileCtrlEventHandler(XyFileBrowser::OnPathChanged)); } void XyFileBrowser::update_s_column() { s_column->Enable(std_dev_b->GetValue()); } void XyFileBrowser::update_block_list() { vector bb; if (plot_preview && plot_preview->get_data().get() != NULL) for (int i = 0; i < plot_preview->get_data()->get_block_count(); ++i) { const string& name = plot_preview->get_data()->get_block(i)->get_name(); bb.push_back(name.empty() ? "Block #" + S(i+1) : name); } else { bb.push_back(""); } if (bb.size() != (size_t) block_ch->GetCount()) { block_ch->Clear(); for (size_t i = 0; i < bb.size(); ++i) block_ch->Append(wxString(bb[i])); } else { for (size_t i = 0; i < bb.size(); ++i) if (block_ch->GetString(i) != wxString(bb[i])) block_ch->SetString(i, wxString(bb[i])); } block_ch->SetSelection(0); block_ch->Enable(block_ch->GetCount() > 1); } void XyFileBrowser::update_title_from_file() { #ifndef XYCONVERT wxString current_title = title_tc->GetValue().Trim(); if (!current_title.empty() && current_title != auto_title_) return; wxArrayString paths; filectrl->GetPaths(paths); string title; if (paths.GetCount() >= 1) { title = get_file_basename(paths[0].ToStdString()); int x_idx = x_column->GetValue(); int y_idx = y_column->GetValue(); if (x_idx != 1 || y_idx != 2 || std_dev_b->GetValue()) title += ":" + S(x_idx) + ":" + S(y_idx); } auto_title_ = wxString(title); title_tc->ChangeValue(auto_title_); #endif } void XyFileBrowser::OnCommaCheckBox(wxCommandEvent&) { update_plot_preview(); } void XyFileBrowser::OnAutoTextCheckBox (wxCommandEvent& event) { if (event.IsChecked()) update_text_preview(); else text_preview->Clear(); } void XyFileBrowser::OnAutoPlotCheckBox(wxCommandEvent&) { update_plot_preview(); } void XyFileBrowser::OnFormatChanged(wxCommandEvent&) { update_plot_preview(); int format_idx = format_ch->GetSelection(); if (format_idx == 0) { comma_cb->Enable(true); } else { const char* name = xylib_get_format(format_idx - 1)->name; comma_cb->Enable(strcmp(name, "text") == 0 || strcmp(name, "csv") == 0); } } void XyFileBrowser::OnBlockChanged(wxCommandEvent&) { update_plot_preview(); } void XyFileBrowser::OnColumnChanged(wxSpinEvent&) { if (auto_plot_cb->GetValue()) update_plot_preview(); update_title_from_file(); } wxString XyFileBrowser::get_one_path() { wxArrayString a; filectrl->GetPaths(a); if (a.GetCount() == 1) return a[0]; else return wxEmptyString; } void XyFileBrowser::update_text_preview() { static char buffer[65536]; const int buf_size = 65536; fill(buffer, buffer+buf_size, 0); text_preview->Clear(); wxString path = get_one_path(); if (!path.empty() && wxFileExists(path)) { int bytes_read = wxFile(path).Read(buffer, buf_size-1); wxString str(buffer); // implicit conversion using current locale if (str.empty()) str = wxString::From8BitData(buffer, bytes_read); // remove nulls to display binary files (it looks better than randomly // truncated binary file) for (wxString::iterator i = str.begin(); i != str.end(); ++i) if (*i == '\0') *i = '\1'; text_preview->SetValue(str); if (!str.empty() && bytes_read == buf_size-1) { text_preview->SetDefaultStyle(wxTextAttr(*wxBLACK, *wxYELLOW)); text_preview->AppendText( "\nThis preview shows only the first 64kb of file.\n"); text_preview->SetDefaultStyle(wxTextAttr()); text_preview->ShowPosition(0); } } } void XyFileBrowser::update_plot_preview() { if (auto_plot_cb->GetValue()) { wxString path = get_one_path(); if (!path.IsEmpty()) { plot_preview->idx_x = x_column->GetValue(); plot_preview->idx_y = y_column->GetValue(); plot_preview->block_nr = block_ch->GetSelection(); string options; if (comma_cb->IsEnabled() && comma_cb->GetValue()) options = "decimal-comma"; plot_preview->load_dataset((const char*) path.ToUTF8(), get_filetype(), options); } } else plot_preview->make_outdated(); plot_preview->refresh(); } string XyFileBrowser::get_filetype() const { int idx = format_ch->GetSelection(); if (idx > 0) return xylib_get_format(idx - 1)->name; else return ""; } void XyFileBrowser::update_file_options() { if (auto_text_cb->GetValue()) update_text_preview(); block_ch->SetSelection(0); if (auto_plot_cb->GetValue()) update_plot_preview(); update_block_list(); update_title_from_file(); } fityk-1.3.1/wxgui/xybrowser.h000066400000000000000000000043311302634723100162240ustar00rootroot00000000000000// This file is part of fityk program. Copyright 2001-2013 Marcin Wojdyr // Licence: GNU General Public License ver. 2+ // (It is also part of xyconvert and can be distributed under LGPL2.1) #ifndef FITYK_WX_XYBROWSER_H_ #define FITYK_WX_XYBROWSER_H_ #include #include #include #include "xylib/xylib.h" #include "xylib/cache.h" // dataset_shared_ptr #include "uplot.h" #if XYLIB_VERSION < 10500 typedef shared_ptr dataset_shared_ptr; #endif class PreviewPlot : public PlotWithTics { public: int block_nr, idx_x, idx_y; PreviewPlot(wxWindow* parent); virtual void draw(wxDC &dc, bool); void load_dataset(const std::string& filename, const std::string& filetype, const std::string& options); dataset_shared_ptr get_data() const { return data_; } void make_outdated() { data_updated_ = false; } private: dataset_shared_ptr data_; bool data_updated_; // if false, draw() doesn't do anything (plot is clear) }; class XyFileBrowser : public wxSplitterWindow { public: wxFileCtrl *filectrl; wxSpinCtrl *x_column, *y_column, *s_column; wxCheckBox *comma_cb; wxChoice *format_ch, *block_ch; #ifdef XYCONVERT wxCheckBox *std_dev_b; #else wxRadioButton *std_dev_b, *sd_sqrt_rb, *sd_1_rb; wxTextCtrl *title_tc; wxString auto_title_; #endif XyFileBrowser(wxWindow* parent); std::string get_filetype() const; void update_file_options(); void update_s_column(); private: wxTextCtrl *text_preview; PreviewPlot *plot_preview; wxCheckBox *auto_text_cb, *auto_plot_cb; void OnCommaCheckBox(wxCommandEvent&); void OnStdDevSwitched(wxCommandEvent&) { update_s_column(); } void OnAutoTextCheckBox(wxCommandEvent& event); void OnAutoPlotCheckBox(wxCommandEvent& event); void OnColumnChanged(wxSpinEvent& event); void OnFormatChanged(wxCommandEvent& event); void OnBlockChanged(wxCommandEvent& event); void OnPathChanged(wxFileCtrlEvent&) { update_file_options(); } void update_text_preview(); void update_plot_preview(); void update_block_list(); wxString get_one_path(); void update_title_from_file(); }; #endif // FITYK_WX_XYBROWSER_H_